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();
Related
I have setup Serilog with .net 6 asp.net core project but the IP Address is not showing up in the logs using the json formatter.
var logger = new LoggerConfiguration()
.Enrich.WithClientIp()
.Enrich.WithClientAgent()
.Enrich.FromLogContext()
.ReadFrom.Configuration(builder.Configuration)
.CreateLogger();
builder.Logging.ClearProviders();
builder.Logging.AddSerilog(logger);
And I have setup my appsettings like this. But I'm not sure why the IP Address is not showing up in the logs for any request (get, put, etc.)
"Serilog": {
"Using": [ "Serilog.Sinks.File, Serilog.Enrichers.ClientInfo" ],
"MinimumLevel": {
"Default": "Information"
},
"Enrich": [ "FromLogContext", "WithMachineName", "WithProcessId", "WithThreadId", "WithClientIP", "WithClientAgent" ],
"WriteTo": [
{
"Name": "Console",
"Args": {
"outputTemplate": "===> {Timestamp:HH:mm:ss} [{Level}] {Message}{NewLine}{Exception}"
}
},
{
"Name": "File",
"Args": {
"path": "C://Temp//appLog_.json",
"formatter": "Serilog.Formatting.Json.JsonFormatter, Serilog",
"rollOnFileSizeLimit": true,
"fileSizeLimitBytes": 4194304,
"retainedFileCountLimit": 10,
"rollingInterval": "Day"
}
}
]
},
In Program.cs, I change the code into below code:
builder.Host.UseSerilog((ctx, lc) => lc
.WriteTo.Console()
.ReadFrom.Configuration(ctx.Configuration));
...
app.UseSerilogRequestLogging(options =>
{
// Customize the message template
options.MessageTemplate = "{RemoteIpAddress} {RequestScheme} {RequestHost} {RequestMethod} {RequestPath} responded {StatusCode} in {Elapsed:0.0000} ms";
// Emit debug-level events instead of the defaults
options.GetLevel = (httpContext, elapsed, ex) => LogEventLevel.Debug;
// Attach additional properties to the request completion event
options.EnrichDiagnosticContext = (diagnosticContext, httpContext) =>
{
diagnosticContext.Set("RequestHost", httpContext.Request.Host.Value);
diagnosticContext.Set("RequestScheme", httpContext.Request.Scheme);
diagnosticContext.Set("RemoteIpAddress", httpContext.Connection.RemoteIpAddress);
};
});
Read net6.0 Serilog example and Adding IP logging to know more.
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'm attempting to try Serilog out in an asp.net core web api (3.1) but seem to be having trouble with the following:
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.log.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables()
.Build();
//Configure logger
var loggerConfiguration = new LoggerConfiguration().ReadFrom.Configuration(configuration);
Log.Logger = loggerConfiguration.CreateLogger();
It is throwing the exception:
Exception has occurred: CLR/System.InvalidOperationException
An unhandled exception of type 'System.InvalidOperationException' occurred in Microsoft.Extensions.Configuration.Binder.dll: 'Cannot create instance of type 'System.String' because it is missing a public parameterless constructor.'
at Microsoft.Extensions.Configuration.ConfigurationBinder.CreateInstance(Type type)
at Microsoft.Extensions.Configuration.ConfigurationBinder.BindInstance(Type type, Object instance, IConfiguration config, BinderOptions options)
at Microsoft.Extensions.Configuration.ConfigurationBinder.Get(IConfiguration configuration, Type type, Action`1 configureOptions)
at Microsoft.Extensions.Configuration.ConfigurationBinder.Get(IConfiguration configuration, Type type)
at Serilog.Settings.Configuration.ObjectArgumentValue.ConvertTo(Type toType, ResolutionContext resolutionContext)
at Serilog.Settings.Configuration.ConfigurationReader.<>c__DisplayClass18_2.<CallConfigurationMethods>b__3(<>f__AnonymousType9`2 <>h__TransparentIdentifier0)
at System.Linq.Utilities.<>c__DisplayClass2_0`3.<CombineSelectors>b__0(TSource x)
at System.Linq.Enumerable.SelectListPartitionIterator`2.ToList()
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at Serilog.Settings.Configuration.ConfigurationReader.CallConfigurationMethods(ILookup`2 methods, IList`1 configurationMethods, Object receiver)
at Serilog.Settings.Configuration.ConfigurationReader.ApplySinks(LoggerConfiguration loggerConfiguration)
at Serilog.Settings.Configuration.ConfigurationReader.Configure(LoggerConfiguration loggerConfiguration)
at Serilog.Configuration.LoggerSettingsConfiguration.Settings(ILoggerSettings settings)
at Serilog.ConfigurationLoggerConfigurationExtensions.Configuration(LoggerSettingsConfiguration settingConfiguration, IConfiguration configuration, String sectionName, DependencyContext dependencyContext)
at Serilog.ConfigurationLoggerConfigurationExtensions.Configuration(LoggerSettingsConfiguration settingConfiguration, IConfiguration configuration, DependencyContext dependencyContext)
My appsettings.log.json looks like this:
{
"Serilog": {
"Using": [ "Serilog.Sinks.Console" ],
"MinimumLevel": "Debug",
"WriteTo": [
{ "Name": "Console" },
{
"Name": "File",
"Args": {
"path": "%ProgramData%\\Logs\\BoxIt\\BoxIt-{Date}.txt",
"rollOnFileSizeLimit": "true",
"rollingInterval": "Day",
"fileSizeLimitBytes": 10000000,
"outputTemplate:": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}"
}
}
],
"Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ],
"Destructure": [
{
"Name": "ToMaximumDepth",
"Args": { "maximumDestructuringDepth": 4 }
},
{
"Name": "ToMaximumStringLength",
"Args": { "maximumStringLength": 100 }
},
{
"Name": "ToMaximumCollectionCount",
"Args": { "maximumCollectionCount": 10 }
}
],
"Properties": {
"Application": "Box-It"
}
}
}
Most of the articles I've read initialize this in a very similar fashion so I'm not quite sure if there is something wrong with the config file or how I'm reading the configuration.
"outputTemplate:": was the issue here. The colon inside the double quotes was a mistake and was leading to the error above.
Logging to AzureTableStorage is causing an overhead that blocks next calls, compared to when logging into a file, is there a way to make this process faster (batch or async option)?
My code in appsetttings.josn:
"Serilog": {
"MinimumLevel": "Information",
"WriteTo": [
{
"Name": "AzureTableStorage",
"Args": {
"storageTableName": "tbl",
"connectionString": "DefaultEndpointsProtocol=http;AccountName=xxx;AccountKey=/xxxxxxxx"
}
}
]
}
I ended up using https://github.com/serilog/serilog-sinks-async and the batch option in AzureTableStorage, similar to:
"WriteTo": [
{
"Name": "Async",
"Args": {
"configure": [
{
"Name": "AzureTableStorage",
"Args": {
"storageTableName": "tbl",
"connectionString": "DefaultEndpointsProtocol=http;AccountName=xxx;AccountKey=xxx"
}
}
]
}
}
]
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" }
}
}