I'm developing an application using asp.net core and Serilog for logging.
I have the following code:
Log.Information("Application Starting.");
Log.Information("Message: fetching all Requests");
My Serilog config file look like this:
{
"Serilog": {
"Using": [ "Serilog.Settings.Configuration" ],
"MinimumLevel": {
"Default": "Information",
"Override": {
"System": "Warning",
"Microsoft": "Warning"
}
},
{
"Name": "Logger",
"Args": {
"configureLogger": {
"Filter": [
{
"Name": "ByIncludingOnly",
"Args": {
}
}
],
"WriteTo": [
{
"Name": "File",
"Args": {
"path": "..\\Logs\structuredLog.json",
"formatter": "Serilog.Formatting.Json.JsonFormatter, Serilog",
"fileSizeLimitBytes": 20485760
}
}
],
"Enrich": [
"FromLogContext",
"WithMachineName",
"WithProcessId",
"WithThreadId"
],
"Properties": {
"ApplicationName": "Serilog.WebApplication"
}
}
}
}
]
}
The Problem:
As an output i get an invalid JSON file:
{"Timestamp":"2021-07-27T10:09:41.9531148+02:00","Level":"Information","MessageTemplate":"Application Starting."}
{"Timestamp":"2021-07-27T10:09:46.7538684+02:00","Level":"Information","MessageTemplate":"Message: fetching all Requests"}
I expect to get something like this:
[
{
"Timestamp":"2021-07-27T10:09:41.9531148+02:00",
"Level":"Information",
"MessageTemplate":"Application Starting."
},
{
"Timestamp":"2021-07-27T10:09:46.7538684+02:00",
"Level":"Information",
"MessageTemplate":"Message: fetching all Requests"
}
]
Can someone please help me to solve this problem!
You are correct with the statement that the JSON file is not a valid JSON object. In the context of a logging library the output should not be seen as a file but a stream of data. So each log entry is one item in a possibly never ending flow.
This is also why it makes no sense to add an opening array indicator and adding comma after each line.
After I generate the json log, I can adjust the format by using the format that comes with vs.
Format shortcut: Ctrl+K or Ctrl+D.
If it doesn't work, do it like this:
Result:
Related
Am new to serilog but I cannot see how to set the name of the log being generated by Serilog.
I am using the ASP.net core and have registered serilog and using the appsettings.json to log into my file which works as expected.
However the name of the file isn't adhering to the WriteTo configuration as defined:
"Serilog": {
"Using": [
"Serilog.Sinks.Console"
],
"MinimumLevel": {
"Default": "Debug",
"Override": {
"Microsoft": "Debug",
"System": "Debug"
}
},
"Enrich": [
"FromLogContext",
"WithExceptionDetails",
"WithEnvironmentUserName",
"WithMachineName",
"WithProcessId",
"WithProcessName",
"WithThreadId"
],
"WriteTo": [
{
"Name": "Console",
"Args": {
"path": "Logs/logFile_.log"
},
"Theme": "Code"
},
{
"Name": "File",
"Args": {
"path": "Logs/logFile_.log",
"fileSizeLimitBytes": "1000",
"retainedFileCountLimit": 5,
"rollingInterval": "Day"
// , "shared" : "true"
},
"outputTemplate": "===> {Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] {Message}{NewLine}{Exception}"
}
]
}
The filename looks like:
ProjectName.Api20220309_01.log
Rather than expected:
logfile_20220309_01.log
Is this something out of the box? Or is there something I should look for?
Just for background I have several projects in the one solution where serilog is running.
Can anyone tell me how to get the value from an appsettings.json file in my program.cs file in a Blazor (core 5) App.
Basically just need to write the "var seqUrl =" correctly. I think.
Please and thank you.
In my Main method of Program.cs I have
IConfiguration configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", false, true)
.AddJsonFile("appsettings.Development.json", true, true)
.Build();
var levelSwitch = new LoggingLevelSwitch();
var seqUrl = configuration.GetSection("SeriLog").GetSection("WriteTo").GetSection("Name:Seq").GetSection("Args").GetSection("serverUrl").Value;
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.MinimumLevel.ControlledBy(levelSwitch)
.WriteTo.Seq(seqUrl,
apiKey: "xxxxxxxxxxxx",
controlLevelSwitch: levelSwitch)
.CreateLogger();
My appsettings.json looks like this.
"SeriLog": {
"Using": [
"Serilog.Sinks.File",
"Serilog.Sinks.Seq",
"Serilog.Sinks.Console"
],
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"system": "Warning"
}
},
"Enrich": [ "WithMachineName", "WithEnvironmentUserName", "WithClientIp", "WithClientAgent", "WithEnvironmentName", "WithProcessId", "WithProcessName", "WithThreadId" ],
"WriteTo": [
{
"Name": "File",
"Args": {
"path": "C:\\Temp\\Logs\\JsonLog.json",
"formatter": "Serilog.Formatting.Json.JsonFormatter, Serilog",
"rollingInterval": "Day"
}
},
{
"Name": "Seq",
"Args": {
"serverUrl": "http://xxxxxxxxxxx"
}
}
]
I think you should consider restructuring the JSON in your appsettings file. The value for "WriteTo" is an array, but I would make it just an object rather than an array, then each element should be a child object. Use the "Name" variable to name them. Like this:
"WriteTo": {
"File": {
"Args": {
"path": "C:\\Temp\\Logs\\JsonLog.json",
"formatter": "Serilog.Formatting.Json.JsonFormatter, Serilog",
"rollingInterval": "Day"
}
},
"Seq": {
"Args": {
"serverUrl": "http://xxxxxxxxxxx"
}
}
}
Then you should be able to retrieve the values using the same style that you are, just with the complete path to the variable you need. For example:
var seqUrl = configuration.GetSection("SeriLog:WriteTo:Seq:serverUrl").Value;
I don't remember if this syntax is 100% correct or not (the path might not be colon separated, I'm not completely sure) but this concept should work. You just weren't entering the correct names into the .GetSection() method in your code, and I think it gets kind of tricky when you are trying to retrieve an array element like this, hence my suggestion to convert from array to a simple object.
I'm trying to use Serilog in a dotnet webapi app. I need logging to go to both the Console and a Rolling log file.
Everything is coming out to the Console but nothing is appearing in the rolling log file and I'm not getting any errors anywhere.
I have setup serilog in my code like so:
// in program.cs Main
var configuration = new ConfigurationBuilder()
.SetBasePath(BASEDIR)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.Build();
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.Enrich.FromLogContext()
.Enrich.With(new ThreadIdEnricher())
.CreateLogger();
// startup.cs Configure
app.UseSerilogRequestLogging();
And in appsetting.json I have
{
"Serilog": {
"Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ],
"Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ],
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft.AspNetCore.Mvc.Internal": "Warning",
"Microsoft.AspNetCore.Authentication": "Warning",
"Microsoft.AspNetCore": "Warning",
"Microsoft": "Warning",
"System": "Warning"
}
},
"WriteTo": [
{
"Name": "Async",
"Args": {
"configure": [
{
"Name": "Console",
"Args": {
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} {Level:u1} TID:{ThreadId} {Message:lj}{NewLine}{Exception}",
"theme": "Serilog.Sinks.SystemConsole.Themes.SystemConsoleTheme::Literate, Serilog.Sinks.Console"
}
}
]
}
},
{
"Name": "Async",
"Args": {
"configure": [
{
"Name": "RollingFile",
"Args": {
"pathFormat": "c:\\logs\\{Date}.log",
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} {Level:u1} TID:{ThreadId} {Message:lj}{NewLine}{Exception}",
"buffered": false,
"rollingInterval": "Serilog.RollingInterval.Day, Serilog.Sinks.File",
"retainedFileCountLimit": 7
}
}
]
}
}
]
}
}
have you tried to change to static file name? does the path exists? it seems that the configuration on the readme from their github page is a bit differnt from yours: https://github.com/serilog/serilog-sinks-file#user-content-json-appsettingsjson-configuration:~:text=node%2C%20%3A-,%7B,%7D,-See%20the%20XML
also maybe try to work your way back from setting it up in code then move back to config file?
From studying Serilog.Sinks.AzureTableStorage I have the following
In Main
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.Build();
var logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration) // the error happens here
.CreateLogger();
logger.Information("Hello, world!");
In appsetttings.json ( with different connection string)
"Serilog": {
"Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.AzureTableStorage" ],
"MinimumLevel": "Debug",
"WriteTo": [
{ "Name": "Console" },
{
"Name": "File",
"Args": { "path": "%TEMP%\\Logs\\serilog-configuration-sample.txt" }
},
{
"Name": "AzureTableStorage",
"Args": {
"storageTableName": "mystoragetable",
"connectionString": "myconnectionstring"
}
}
],
"Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ],
"Destructure": [
{
"Name": "With",
"Args": { "policy": "Sample.CustomPolicy, Sample" }
},
{
"Name": "ToMaximumDepth",
"Args": { "maximumDestructuringDepth": 4 }
},
{
"Name": "ToMaximumStringLength",
"Args": { "maximumStringLength": 100 }
},
{
"Name": "ToMaximumCollectionCount",
"Args": { "maximumCollectionCount": 10 }
}
],
"Properties": {
"Application": "Sample"
}
}
I see in the debug output yet no data gets logged to the storage table.
Exception thrown: 'System.InvalidCastException' in System.Private.CoreLib.dll
An unhandled exception of type 'System.InvalidCastException' occurred in System.Private.CoreLib.dll
Invalid cast from 'System.String' to 'Serilog.Core.IDestructuringPolicy'.
[Update]
If I use a very simple config as per the ReadMe.Md in GitHub, I get the same error.
[Update]
I copied in the code from Kennyzx link. The error has changed to
System.InvalidCastException
HResult=0x80004002
Message=Invalid cast from 'System.String' to 'Serilog.Core.ILogEventFilter'.
Source=System.Private.CoreLib
I decided to try upgrading the serilog-settings-configuration sample project to .netcore2.1 and thus asked this question
After a few hours I came to the conclusion that serilog-settings-configuration s is not compatible with dotnetcore 2.1
I try to set up a new .NET Core 2.1 Console project called UseSerilog and I can reproduce the issue.
After I remove the Destructure and Filter sections from the configuration then the app begins to work.
Then I check the source code of the Serilog.Settings.Configuration package, I find this commit, and I come to conclusion that you need to write some code in order to make it work like this way.
For the below configuration, you are expected to write a CustomPolicy class in the "Sample" namespace that implements IDestructuringPolicy.
{
"Name": "With",
"Args": { "policy": "Sample.CustomPolicy, Sample" }
}
If you remove this, and leave Destructure as below, it is working.
"Destructure": [
{
"Name": "ToMaximumDepth",
"Args": { "maximumDestructuringDepth": 3 }
},
{
"Name": "ToMaximumStringLength",
"Args": { "maximumStringLength": 10 }
},
{
"Name": "ToMaximumCollectionCount",
"Args": { "maximumCollectionCount": 5 }
}
]
Hope this finding helps you.
I would like to use NJsonSchema to generate C# classes. The problem is that for nested arrays, the type ends up looking like this:
System.Collections.ObjectModel.ObservableCollection<System.Tuple<System.Linq.Enumerable+WhereSelectEnumerableIterator2[NJsonSchema.JsonSchema4,System.String]>>
My test code for generating the classes looks like this:
var schemaAsync = NJsonSchema.JsonSchema4.FromFileAsync(
#"<myPath>/MyFile.json");
var schema = schemaAsync.Result;
var generator = new NJsonSchema.CodeGeneration.CSharp.CSharpGenerator(schema);
var file = generator.GenerateFile();
System.IO.File.WriteAllText(
#"<myPath>/SomeClass.cs",
file);
I have two JSON schema files, there's the definition file (Def1.json):
{
"$schema": "http://json-schema.org/draft-04/schema#",
"definitions": {
"InnerList": {
"description": "Only ever has 2 items",
"type": "array",
"items": [
{
"type": "integer",
"minimum": 0,
"maximum": 100,
"default": 0
},
{
"type": "integer",
"minimum": 0,
"maximum": 100,
"default": 0
}
],
"additionalItems": false
},
"OuterList": {
"type": "array",
"items": {
"$ref": "#/definitions/InnerList"
}
},
}
}
And a separate schema that makes use of the definition file:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "MySchema",
"type": "object",
"required": [ "OuterList" ],
"properties": {
"OuterList": { "$ref": "Def1.json#/definitions/OuterList" }
},
"additionalProperties": false
}
Am I using the library incorrectly?
This problem has been fixed in the latest version.