I'm using the SQL Server Serilog sink and using different appsettings.<EVN>.json configuration files (one for the default which is appsettings.json and one for the specific environment I am running in which is currently appsettings.test.json). appsettings.json specifies a SQL Server localhost in the connection string and the appsettings.test.json file specifies a different SQL server for the connection string. When running under any environment other than DEVELOPMENT, Serilog will create a LOG table in both the localdb and whatever environment I am testing (TEST_MSSQL in this case). My assumption is that there would only be one log configured and that the server setting in the appsettings.test.json (External SQL Server) would override the value in the default appsettings.json (Local SQL Server), but it appears to be creating configuring in both the localhost and test SQL Servers.
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.UseSerilog((context, config) => config.ReadFrom.Configuration(Configuration))
.Build()
.Run();
Settings in default appsettings.json
"Serilog": {
"Using": [ "Serilog.Sinks.MSSqlServer" ],
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"System": "Error"
}
},
"WriteTo": [
{
"Name": "Console"
},
{
"Name": "MSSqlServer",
"Args": {
"connectionString": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=MyDB;Integrated Security=True;Connect Timeout=30;",
"schemaName": "dbo",
"tableName": "Log",
"autoCreateSqlTable": true,
"restrictedToMinimumLevel": "Warning",
"batchPostingLimit": 1000,
"period": "0.00:00:30",
"columnOptionsSection": {
"addStandardColumns": [ "LogEvent" ],
"removeStandardColumns": [ "MessageTemplate", "Properties" ],
"logEvent": {
"excludeAdditionalProperties": true,
"excludeStandardColumns": true
}
}
}
}
]
}
Settings in appsettings.test.json
"Serilog": {
"WriteTo": [
{
"Args": {
"connectionString": "Data Source=TEST_MSSQL;Initial Catalog=MyDB;Integrated Security=True;Connect Timeout=30;"
}
}
]
}
When running under any environment other than DEVELOPMENT, Serilog will create a LOG table in both the localdb and whatever environment I am testing (TEST_MSSQL in this case).
I can reproduce same issue based on the configuration data you provided.
To override default connectionString for Serilog you specified in appsettings.json file and fix above issue, you can update your appsettings.test.json file like below.
{
"Serilog": {
"WriteTo": [
{
"Name": "Console"
},
{
"Name": "MSSqlServer",
"Args": {
"connectionString": "Data Source=TEST_MSSQL;Initial Catalog=MyDB;Integrated Security=True;Connect Timeout=30;",
}
}
]
}
}
Related
I have an Asp.net core web api using .net core 6.
I use Serilog to store the app log in a text file.
sometimes I get this error:
Caught exception while emitting to sink Serilog.Sinks.SystemConsole.ConsoleSink: System.IO.IOException: The handle is invalid.
at System.ConsolePal.WindowsConsoleStream.Write(ReadOnlySpan`1 buffer)
at System.IO.StreamWriter.Flush(Boolean flushStream, Boolean flushEncoder)
at System.IO.StreamWriter.Write(String value)
at System.IO.TextWriter.SyncTextWriter.Write(String value)
at Serilog.Sinks.SystemConsole.ConsoleSink.Emit(LogEvent logEvent)
at Serilog.Core.Sinks.SafeAggregateSink.Emit(LogEvent logEvent)
could you please help me how can I solve this issue?
this is my appsetting:
"Serilog": {
"Using": [
"Serilog.Sinks.Console",
"Serilog.Sinks.File"
],
"MinimumLevel": "Information",
"WriteTo": [
{
"Name": "File",
"Args": {
"path": "AppLogs/bckLog-.log",
"rollingInterval": "Day",
"restrictedToMinimumLevel": "Warning"
}
},
{
"Name": "Console"
}
],
"Enrich": [
"FromLogContext"
]
}
and this is my program.cs
Serilog.Debugging.SelfLog.Enable(message => { Log.Logger?.Error(message); Console.WriteLine(message); });
Log.Logger = new LoggerConfiguration().ReadFrom.Configuration(builder.Configuration).CreateLogger();
builder.Host.UseSerilog();
I'm trying to configure Serilog for my ASP.NET app using appsettings.json and am following the instructions from the GitHub Serilog.Settings.Configuration project readme. I cannot get the Console output format expression working from appsettings.json when I also set a theme. When both are configured directly in code it works just fine.
This is the Serilog section of appsettings.json. Note the full template is more complex, it uses Substring(SourceContext, LastIndexOf(SourceContext, '.') + 1) amonst others, but this is how I am testing for now:
{
"Serilog": {
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft.AspNetCore": "Warning",
"Microsoft.EntityFrameworkCore.Database.Command": "Warning"
}
},
"WriteTo": [
{
"Name": "Console",
"Args": {
"formatter": {
"type": "Serilog.Templates.ExpressionTemplate, Serilog.Expressions",
"template": "[{#t:HH:mm:ss:fff} {#l:u3}] {SourceContext,48} : {#m}\n{#x}"
},
"theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console"
}
}
],
"Enrich": [ "FromLogContext" ]
}
}
And this is the resulting output (with theme colors):
[17:13:38 INF] Configure
[17:13:38 INF] Now listening on: https://localhost:5001
[17:13:38 INF] Now listening on: http://localhost:5000
[17:13:38 INF] Application started. Press Ctrl+C to shut down.
Which appears to be the default format (note the msec field in the timestamp and the Source Context field are missing).
When I omit the theme setting from the json, the output looks like this, i.e. with the correct expression template applied (e.g. source context) but without any color:
[17:13:37:498 INF] App.Web.Server.Program : Server started
[17:13:37:797 INF] App.Web.Server.Startup : ConfigureServices
This is the same format I get when I configure the logger in code, but then I get the theme color too!
I also tried to use this format from the project's samples:
"WriteTo": [
{
"Name": "Console",
"Args": {
"outputTemplate": "[{Timestamp:HH:mm:ss} {SourceContext} [{Level}] {Message}{NewLine}{Exception}",
"theme": "Serilog.Sinks.SystemConsole.Themes.SystemConsoleTheme::Grayscale, Serilog.Sinks.Console"
}
}
]
This is without the format expression, just the format (and a slight variation on the format itself) and, as expected, results in:
[14:35:11 Microsoft.Hosting.Lifetime [Information] Now listening on: "https://localhost:5001"
[14:35:11 Microsoft.Hosting.Lifetime [Information] Now listening on: "http://localhost:5000"
I tried umpteen variations and combinations without any success. So it seems that using appsettings.json I can either get the expression template working, or the theme working, but not both at the same time.
Again: when configured directly in code it "just works" ...
Suggestion are welcome.
I tried as below:
Packages:
in appsettings.json:
"Serilog": {
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft.AspNetCore": "Warning",
"Microsoft.EntityFrameworkCore.Database.Command": "Warning"
}
},
"WriteTo": [
{
"Name": "Console",
"Args": {
"theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console",
"outputTemplate": "Time:{Timestamp: HH:mm:ss.fff} Level:{Level} DetailedInfo:{Message}{NewLine}{Exception}"
}
}
],
"Enrich": ["FromLogContext"]
}
In program.cs:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.UseSerilog((context, logger) =>
{
logger.ReadFrom.Configuration(context.Configuration);
});
Result:
and with
"theme": "Serilog.Sinks.SystemConsole.Themes.SystemConsoleTheme::Grayscale, Serilog.Sinks.Console"
I want to change/override the filename declared appsettings.json with whatever I provide when I setup the logger while keeping all the other settings as is.
I have serilog settings declared in the appsettings.json
"Serilog": {
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Information",
"System": "Information"
}
},
"WriteTo": [
{ "Name": "Console" },
{
"Name": "File",
"Args": {
"path":"MyAppName_.log"
"rollOnFileSizeLimit": "true",
"fileSizeLimitBytes": 1000000,
"rollingInterval": "Day",
"flushToDiskInterval": 1,
"outputTemplate": "{Timestamp:o} [{Level:u3}] ({Application}/{MachineName}/{ThreadId}) {Message:lj}{NewLine}{Exception}"
}
}
],
"Enrich": [ "FromLogContext", "%COMPUTERNAME%", "WithThreadId", "USERNAME","USERDOMAIN" ],
"Properties": { "Application": "MyAppName" }
}
The below code is in ConfigureServices method in Startup.cs
var appName = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;
var fileName = #$"C://Logs/{MyAppName}\{MyAppName}-{DateTime.Today.ToString("MM-dd-yyyy")}.log";
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(Configuration)
.WriteTo.File(fileName)
.CreateLogger();
Is it possible?
I am using ASP.NET Core 3.1 and Serilog.AspNetCore 3.2.0
I've a healthcheck endpoint in my .NetCore(2.2) WebAPI project for which I don't want to generate and write any logs. I'm writing the logs to WindowsEventLog. For that, I'm using a separate config file just for the logging purpose which I'm loading in my startup.
This is the endpoint that I've in the controller for healthcheck:
[Route("healthcheck")]
[AllowAnonymous]
public IActionResult Get()
{
return Ok("");
}
This is how I'm loading the config file (SeriLogSettings.json) that I created for holding my Serilog configuration:
public Startup(IConfiguration configuration, IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddJsonFile("SeriLogSettings.json", optional: false)
.AddEnvironmentVariables();
Configuration = builder.Build();
}
And this is how my SerilogSettings.json looks like:
{
"Serilog": {
"Using": [ "Serilog.Settings.Configuration", "Serilog.Sinks.EventLog" ],
"Filter": [
{
"Name": "ByExcluding",
"Args": {
"expression": "EndsWith(RequestPath, '%/healthcheck')"
}
}
],
"MinimumLevel": {
"Default": "Debug",
"Override": {
"Microsoft": "Warning",
"System": "Warning"
}
},
"Enrich": [ "FromLogContext" ],
"WriteTo": [
{
"Name": "EventLog",
"Args": {
"source": "WebAPI",
"logName": "Application",
"managedEventSource": true
}
}
],
"Properties": {
"Application": "ApplicationAPI"
}
}
}
Despite using the ByExcluding expression to exclude the logs for /healthcheck endpoint, I'm getting the logs in the WindowsEventLog.
I'm not able to fix why this is happening and not sure what am I doing wrong?
The problem is the % character in the path you're checking, it should just be /healthcheck.
"expression": "EndsWith(RequestPath, '/healthcheck')"
If you take a look at the documentation on the GitHub page, you'll see they also just mention /SomeEndpoint when testing the request path.
may be simple -
"EndsWith(RequestPath, '/healthcheck')" should become
"StartsWith(RequestPath, '/healthcheck')"
Because your requst may by
/healthcheck/live, /healthcheck/ready
Or more puzzle situation
You did not show packages for your project.
Maybe you are using package Serilog.Expressions instead of package Serilog.Filters.Expressions(deprecated)
Those packages use different formats for string 'expression'
Old
"expression": "EndsWith(RequestPath, '/healthcheck')"
New
"expression": "RequestPath like '/healthcheck%')"
The documentation
This is very similar to this question except its about appending arrays between two different JSON files.
I have an ASP.NET Core application
I have the following in appsettings.Development.Json
"Serilog": {
"WriteTo": [
{
"Name": "ApplicationInsightsTraces",
"Args": { "instrumentationKey": "XXXXXXXX" }
}
]
}
And in appsettings.json:
"Serilog": {
// . . . Rest of Serilog configs
"WriteTo": [
{
"Name": "Console",
"Args": {
"theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console",
"outputTemplate": "[{Timestamp:HH:mm:ss} {Level:u3}] {RequestId}-{SourceContext} {$Scope:lj}: {Message:lj}{NewLine}{Exception}"
},
"restrictedToMinimumLevel": "Information"
},
}
Because Keys overwrite other keys in Appsettings.json I end up with the Console sink being overridden. Is there a syntax to allow it to be appended?
The answer is to use WriteTo:1 and make it an object not an array in appsettings.Development.json like so:
"Serilog": {
"WriteTo:1":
{
"Name": "ApplicationInsightsTraces",
"Args": { "instrumentationKey": "d95066c9-0b17-4e0a-84d4-bb2a4f111016" }
}
}