I want to use UTC DateTime in Serilog filename. I am using the below configuration for serilog in my appseting.json file.
"Serilog": {
"Using": [],
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"System": "Warning"
}
},
"Enrich": [
"FromLogContext",
"WithMachineName",
"WithProcessId",
"WithThreadId"
],
"WriteTo": [
{
"Name": "Console"
},
{
"Name": "File",
"Args": {
"path": "Logs\\log-.json",
"formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact",
"rollingInterval": "Hour",
"shared": true
}
}
]
}
and below is the program.cs file code which I use for serilog.
public static void Main(string[] args)
{
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json").Build();
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.CreateLogger();
try
{
CreateHostBuilder(args).Build().Run();
}
catch (Exception e)
{
Log.Fatal(e, "The Application failed to start correctly");
}
finally
{
Log.CloseAndFlush();
}
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args).UseSerilog()
.ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); });
Currently, serilog producing the log file name as log-2020091323.json which is not UTC DateTime.
I'm using asp.net core 3.1.
You can use Install-Package Serilog.Sinks.Map nuget package and configet it in Serilog setup to archive this as in below code example
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Information()
// Ex: UtcDateTime value '202009201010'
.WriteTo.Map("UtcDateTime", DateTime.UtcNow.ToString("yyyyMMddHHmm")
, (UtcDateTime, wt) => wt.File($"logs/log-{UtcDateTime}.txt"))
.CreateLogger();
Log.Information("Hello, Serilog!");
Log.CloseAndFlush(); // Ex: log file name 'log-202009201010.txt'
This code save logs to new file each minute if you need to configure it for each hour use DateTime.UtcNow.ToString("yyyyMMddHH"), or DateTime.UtcNow.ToString("yyyyMMdd") for each day.
Related
I am unable to get Serilog selflog working in my .NET Core 6.0 C# Windows Service. This is how the Main looks like :
public static void Main(string[] args)
{
Serilog.Debugging.SelfLog.Enable(msg => System.Diagnostics.Debug.WriteLine($"Seri-serlflog : {msg}"));
Log.Logger = new LoggerConfiguration().DefaultLoggerSetup<Program>();
var serviceName = "MyService";
var configurationBuilder = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build();
var appSettings = configurationBuilder.Get<AppSettings>();
try
{
Log.Information("{#serviceName} microservice starting up.", serviceName);
var built = Host.CreateDefaultBuilder(args)
.UseSerilog((hostingContext, loggerConfiguration) => loggerConfiguration.ReadFrom.Configuration(hostingContext.Configuration))
.ConfigureServices((hostContext, services) =>
{
services
.AddHostedService<MyApp.Cloud.MyService.BusinessLogicLayer.MyService>()
.Configure<MySettings>(configurationBuilder.GetSection("MQSettings"))
.AddAutoMapper(typeof(ConnectorToCloudTreatment))
.AddTransi...
}).Build();
Log.Information("{#serviceName} all built.", serviceName);
built.Run();
Log.Information("{#serviceName} microservice closing down.", serviceName);
}
catch (Exception ex)
{
Log.Fatal(ex, "Unhanled exception in {#serviceName}.", serviceName);
}
finally
{
Log.Information("{#serviceName} Cleaning up.", serviceName);
Log.CloseAndFlush();
Log.Information("{#serviceName} Application Exit.", serviceName);
}
}
}
The serilog part of application.json looks like this :
"serilog": {
"Using": [ "Serilog.Sinks.MSSqlServer", "Serilog.Sinks.Email" ],
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"System": "Warning"
}
},
"Enrich": [ "FromLogContext", "WithMachineName", "WithProcessId" ],
"WriteTo": [
{
"Name": "Console",
"Args": {
"outputTemplate": "[{Timestamp:HH:mm:ss.fff} [{Level}] {SourceContext} {Message}{NewLine}{Exception}",
"theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console"
}
},
{
"Name": "File",
"Args": {
"path": "/Logs/logs.txt",
"outputTemplate": "{Timestamp:G} {SourceContext} [{Level}] {Message}{NewLine:1}{Exception:1}",
"formatter": "Serilog.Formatting.Json.JsonFormatter, Serilog",
"fileSizeLimitBytes": 1000000,
"rollOnFileSizeLimit": "true",
"shared": "true",
"flushToDiskInterval": 3
}
}
]
}
I do a lot of logging in this application and it works fine but there is a couple of problems and to find why I need to use the selflog but I do not get any information at all to the output > debug?
Edit : Seems like this may have something to do with the injection. In program.cs I use the static Log but in all other classes I use injected typed loggers. But regardless I should get a couple of $"Seri-serlflog : {msg}" rows in the output?
If you're trying to get debug level logging, you'll have to loosen your log level:
"MinimumLevel": {
"Default": "Debug",
"Override": {
"Microsoft": "Debug",
"System": "Debug"
}
Currently all the tasks records create in a one log file. I want to create separate log file for each tasks rather than one log file. (Currently log file contains batch jobs)
{
"Serilog": {
"Using": [ "Serilog.Sinks.RollingFile.Extension" ],
"MinimumLevel": {
"Default": "Warning",
"Override": {
"Microsoft": "Warning",
"System": "Warning"
}
},
"Enrich": [ "FromLogContext", "WithMachineName", "WithProcessId", "WithThreadId" ],
"WriteTo": [
{
"Name": "File",
"Args": {
"rollingInterval": "Day",
"fileSizeLimitBytes": 10485760,
"pathFormat": "RDJOBS_{Date}_{Level}.json",
"path": "c://logs",
"formatter": "Serilog.Formatting.Json.JsonFormatter, Serilog"
}
},
{
"Name": "Seq",
"Args": {
"serverUrl": "http://localhost:5421"
}
}
]
}
}
You can use the Filter.ByExcluding() and Filter.ByIncludingOnly() to add filter expression to filter events passing through the Serilog pipeline, for each task or class, when you use them, you can set a property for them, then use the filter expression to filter the log and write to a different log file.
For demo purposes, we can set a property to the LogEvents in this method execution path.
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
_logger.LogInformation("Worker is called");
using (LogContext.PushProperty("foobar", 1))
{
Foo();
await Task.CompletedTask;
}
}
The following code snippet shows a filtering example.
const string logTemplate = #"{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u4}] [{SourceContext:l}] {Message:lj}{NewLine}{Exception}";
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.Enrich.FromLogContext()
.WriteTo.Logger(l =>
{
l.WriteTo.File("log.txt", LogEventLevel.Information, logTemplate,
rollingInterval: RollingInterval.Day
);
l.Filter.ByExcluding(e => e.Properties.ContainsKey("foobar"));
})
.WriteTo.Logger(l =>
{
l.WriteTo.File("foobar.txt", LogEventLevel.Information, logTemplate,
rollingInterval: RollingInterval.Day
);
l.Filter.ByIncludingOnly(e => e.Properties.ContainsKey("foobar"));
})
.CreateLogger()
With the configuration above, normal logs (without the property foobar in log events) will be saved to the log.txt file, while logs with the property foobar will be saved to the foobar.txt file.
After running the application, the result as below:
More detail information, check this sample.
I have a small console app. I have enabled Debug and Console logging. However, they do not seem to be honouring my config for log level. Here is my setup:
Add Config file and create logger
// global to Program
private static ILogger<Program> _logger;
private const string _configFile = "appsettings.json";
//inside Main
_config = new ConfigurationBuilder()
.AddJsonFile(_configFile, optional: false, reloadOnChange: true)
//.AddEnvironmentVariables()
.AddCommandLine(args)
.Build();
using var loggerFactory = LoggerFactory.Create(builder =>
{
builder.AddDebug();
builder.AddSimpleConsole();
});
_logger = loggerFactory.CreateLogger<Program>();
appconfig.json
"Logging": {
"IncludeScopes": true,
"LogLevel": {
"Default": "Debug",
"Microsoft": "Warning"
},
"Debug": {
"LogLevel": {
"Default": "Trace",
"Microsoft": "Warning",
"FleetLogix.TcaProcessor": "Trace"
}
},
"SimpleConsole": {
"IncludeScopes": "false",
"SingleLine": "false",
"TimestampFormat": "yyyy-MM-dd HH:mm:ss ",
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"FleetLogix.TcaProcessor": "Information"
}
}
},
Its currently set to log to two providers, Debug (visual studio run pane) and Console. This is working. Debug is meant to log at Trace, but is only logging at Info. Console is logging at Info, but is not prefixing the timestamp onto the messages.
Is my config setup correctly? (correct property names, correct depth, etc)
What should I change it to?
Console also has the awful line break that reading tells me you need to fork Microsoft.Extensions.Logging.Console to fix, so another day. :/
I know you've moved on to Serilog, but the answer here is that you're not connecting the config up to the LoggerFactory. You need to identify the config object and also which section to load logging settings from, using the .AddConfiguration extension method from Microsoft.Extensions.Configuration:
using Microsoft.Extensions.Configuration;
var loggerFactory = LoggerFactory.Create(builder =>
{
builder.AddConfiguration(_config.GetSection("Logging"));
builder.AddDebug();
builder.AddSimpleConsole();
});
This question is similar:
.NET Non-host LoggerFactory configuration
I ended up switching to Serilog as I needed a file writer anyway. The only hard part was working out the differences between the older and current version, where rollingfile sink has now been integrated into file sink
Program.cs
#region Initialise Logger
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(_config)
.CreateLogger();
Log.Information("Logger started");
#endregion
appsettings.json
"Serilog": {
"Using": [
"Serilog.Sinks.Console",
"Serilog.Sinks.File"
],
"MinimumLevel": "Debug",
"WriteTo": [
{
"Name": "Console"
},
{
"Name": "File",
"Args": {
"path": "c:\\scripts\\log\\myprogram.log",
"rollingInterval": "Day",
"retainedFileCountLimit": 7
}
}
],
"Properties": {
"Application": "MyProgram"
}
},
I'm using serilog through Microsoft.Extensions.Logging.ILogger.
This is my configuration in Program.cs:
public class Program
{
public static void Main(string[] args)
{
IConfigurationRoot configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.Build();
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.CreateLogger();
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSerilog()
.ConfigureLogging((context, logging) =>
{
logging.ClearProviders();
logging.AddSerilog();
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
I use the ILogger through DI. Everything works fine. Now I want to log some specific log to some file and some specific log to database. For example I want to log info about something to somewhere and info about something else to somewhere else.
For example: I have a game. I want to log names of connected players and their actions to some file and events in the game and errors to a database.
I know how to log into a db and file, but I dont know how can i separate the logs. How can I do it?
This is the config file (right now just for the file sink).
{
"Serilog": {
"Using": [],
"MinimumLevel": {
"Default": "Debug",
"Override": {
"Microsoft": "Error",
"System": "Error"
}
},
"Enrich": [ "SomeName" ],
"WriteTo": [
{ "Name": "Console" },
{
"Name": "File",
"Args": {
"path": "log.log",
"rollingInterval": "Day",
"outputTemplate": "SomeFormat"
}
}
],
"Application": "SomeName"
},
You can store in different sinks by settings filtering exceptions
You could filter in many different ways. The one that worked for me was to filter by namespace like:
var isController = Matching.FromSource("MyApp.Controllers");
var isService = Matching.FromSource("MyApp.Services");
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Verbose()
.WriteTo.RollingFile("d:/logs/recon-api-all-{Date}.log")
.WriteTo.Logger(l => l
.Filter.ByIncludingOnly(isController)
.WriteTo.RollingFile("d:/logs/recon-api-controller-{Date}.log"))
.WriteTo.Logger(l => l
.Filter.ByIncludingOnly(isService)
.WriteTo.MSSqlServer(connectionString: ""))
.WriteTo.Logger(l => l
.Filter.ByExcluding(e => isController(e) || iService(e))
.WriteTo.RollingFile("d:/logs/recon-api-other-{Date}.log"))
.CreateLogger();
You can find a similar post here
You could try to write your own sinks.
The LogEvent class offered by Serilog has a custom
readonly Dictionary<string, LogEventPropertyValue> _properties
which you could use to pass some flags. Based on the flags, your sinks can decide if they act or not upon your message.
But this is all at Serilog lvl. The integration with ILogger might take more thought.
I am trying to set up Serilog as my logger in a multi project solution using Asp.Net Core 2.0.1, EF 2.0.1 and MVC 6.
I have set up Serilog, mostly following the guidelines from this blog post
Set up Serilog post
There is a problem with the json in that post, which I've corrected and is shown here
appsettings.json file
{
"ApplicationConfiguration": {
"ConnectionStrings": {
"DevelopmentConnection": "Server=(localdb)\\mssqllocaldb;Database=TestingConfigurationNetCoreTwo_Development;Trusted_Connection=True;MultipleActiveResultSets=true"
},
"ApplicationInfo": {
"VersionNumber": "1.0.0",
"Author": "Jimbo",
"ApplicationName": "CustomTemplate",
"CreatedOn": "November 20, 2017"
},
"Serilog": {
"Using": [
"Serilog.Sinks.RollingFile",
"Serilog.Sinks.Async",
"Serilog.Sinks.ApplicationInsights",
"Serilog.Sinks.Console",
"Serilog.Sinks.Seq"
],
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning"
}
},
"WriteTo": [
{
"Name": "Async",
"Args": {
"configure": [
{
"Name": "RollingFile",
"Args": { "pathFormat": "Logs/log-{Date}.log" }
}
]
}
}
],
"Enrich": ["FromLogContext", "WithMachineName", "WithThreadId"],
"Properties": {
"Application": "CustomTemplate"
}
}
}
}
I have the logger configuration work in the Main method of Program.cs
public static int Main(string[] args)
{
var currentEnv = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.AddJsonFile($"appsettings.{currentEnv}.json", optional: true)
.AddEnvironmentVariables()
.Build();
//Configure logger
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
//do this for now
//TODO:figure out how to add to Serilog config in appsettings.json
.WriteTo.Seq("http://localhost:5341")
.CreateLogger();
Log.Information("Logger created");
try
{
Log.Information("Starting web host");
BuildWebHost(args).Run();
return 0;
}
catch (Exception ex)
{
Log.Fatal(ex, "Web Host terminated unexpectedly");
return 1;
}
finally
{
Log.CloseAndFlush();
}
//BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
And in my Startup method
services.AddLogging(loggingBuilder =>
loggingBuilder.AddSerilog(dispose: true));
I was assuming Serilog would create the Logs folder once I ran the application, but no Log folder or logs. I added a Logs folder to both the root of the solution, and the web app project and ran it again. No logs. The blog post author suggested looking in the machines root folder. I looked both in C and OneDrive main folders (Solution Files stored on OneDrive) but there were no logs there either.
I then noticed a stack trace warning
System.IO.FileNotFoundException occurred
HResult=0x80070002
Message=The configuration file 'appsettings.json' was not found and is not optional. The physical path is 'C:\Users\OneDrive\TestingConfigurationAspNetCore2\TestMvcApp\bin\Debug\netcoreapp2.0\appsettings.json'.
Source=
StackTrace:
at Microsoft.Extensions.Configuration.FileConfigurationProvider.Load(Boolean reload)
at Microsoft.Extensions.Configuration.FileConfigurationProvider.Load()
at Microsoft.Extensions.Configuration.ConfigurationRoot..ctor(IList`1 providers)
at Microsoft.Extensions.Configuration.ConfigurationBuilder.Build()
I was getting this warning before, which is why I added the set bath path method in the configuration set up, because the application was failing at the code line
.AddJsonFile("appsettings.json")
which was fairly obvious because in the bin folder the file isn't called appsettings.json, its called TestMvcApp.runtimeconfig.json.
Once I added .SetBasePath, the code ran through so I put a breakpoint after the configuration setup. The configuration object contains all the settings from my appsettings.json file, so why I am getting that stack trace error? I don't know but I'll bet a dollar it is why there are no logs (no log messages appear in the console either)
Any help on why the stack trace error or why there are no log messages being written to the log file or displayed on the console would be most appreciated.
which was fairly obvious because in the bin folder the file isn't
called appsettings.json, its called TestMvcApp.runtimeconfig.json.
TestMvcApp.runtimeconfig.json is not your appsettings.json, it's a runtime configuration file as it's clear from the file name.
I bet that your appsettings.json is just not copied to the output directory during the build. To fix that select appsettings.json in Visual Studio Solution explorer, in context menu select properties and set 'Copy to Output Directory' to 'Copy always' or 'Copy if newer':
Also your json configuration has several issues:
Serilog section should not be inside ApplicationConfiguration section. It should be on the same level, i.e top-level section.
You also has suspicious WriteTo section with one sink (RollingFile) inside another (Async). Check here sample json configuration for Serilog.
In order to use all those sinks (Serilog.Sinks.RollingFile, Serilog.Sinks.Console) you should install corresponding sink NuGets: Serilog.Sinks.RollingFile, Serilog.Sinks.Console, etc.
Here is configuration file (with RollingFile sink only) that works fine for me:
{
"ApplicationConfiguration": {
"ConnectionStrings": {
"DevelopmentConnection": "Server=(localdb)\\mssqllocaldb;Database=TestingConfigurationNetCoreTwo_Development;Trusted_Connection=True;MultipleActiveResultSets=true"
},
"ApplicationInfo": {
"VersionNumber": "1.0.0",
"Author": "Jimbo",
"ApplicationName": "CustomTemplate",
"CreatedOn": "November 20, 2017"
}
},
"Serilog": {
"Using": [
"Serilog.Sinks.RollingFile"
],
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning"
}
},
"WriteTo": [
{
"Name": "RollingFile",
"Args": { "pathFormat": "c:\\log-{Date}.log" }
}
],
"Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ],
"Properties": {
"Application": "CustomTemplate"
}
}
}
The accepted answer only logged some messages for my project. I'm not sure why. Ondrej Balas's approach worked better for me.
Install these Nuget packages:
Serilog
Serilog.AspNetCore
Serilog.Settings.Configuration
Serilog.Sinks.Console
Serilog.Sinks.RollingFile
Program.cs needs .UseSerilog() added:
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.ConfigureLogging((hostingContext, logging) =>
{
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
})
.UseStartup<Startup>()
.UseSerilog()
.Build();
Startup.cs needs a couple of changes
one in the constructor:
public Startup(IConfiguration configuration)
{
Log.Logger = new LoggerConfiguration().ReadFrom.Configuration(configuration).CreateLogger();
Configuration = configuration;
}
another in Configure():
loggerFactory.AddSerilog();
if (env.IsDevelopment())
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
}
appsettings.json needs a Serilog config entry in root:
"Serilog": {
"Using": [ "Serilog.Sinks.Console" ],
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"System": "Warning"
}
},
"WriteTo": [
{ "Name": "Console" },
{
"Name": "RollingFile",
"Args": {
"pathFormat": "logs\\log-{Date}.log",
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] [{SourceContext}] {Message}{NewLine}{Exception}"
}
}
],
"Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ],
"Properties": {
"Application": "My Application"
}
}