I have a .NET 3.1 app.
While I'm fine with it logging information to console in general, there is one part (API client) where it generates tons of logs and it is too much for console. How to make it so that for a particular class logs go not to console but to a file?
Create 2 loggers?
Log.Logger = new LoggerConfiguration()
.WriteTo.File(#"MyFile.txt")
.WriteTo.Logger(lc => lc
.Filter.ByExcluding(Matching.FromSource<ApiClient>())
.WriteTo.Console())
.CreateLogger();
Now everything will get written to MyFile.txt but any logs from inside ApiClient won't get output to console
Another option, in case Filter gets a little complicated, is WriteTo.Conditional, which has extra support in Serilog.Expressions:
dotnet add package serilog.expressions
Then:
Log.Logger = new LoggerConfiguration()
.WriteTo.File("MyFile.txt")
.WriteTo.Conditional(
"SourceContext <> 'MyNamespace.ApiClient'",
wt => wt.Console())
.CreateLogger();
Related
I'm trying to configure Serilog for a Web API project in .NET 6.
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(builder.Configuration)
.Enrich.FromLogContext()
.WriteTo.Console()
.CreateLogger();
builder.Logging.ClearProviders();
builder.Logging.AddSerilog(Log.Logger);
//builder.Host.UseSerilog(Log.Logger);
What behavior difference is there between adding Serilog to the logging pipeline and setting Serilog as the logging provider? Should I call both methods?
There is a huge difference. 🙂
The .AddSerilog() provider adds a Serilog provider as one of potentially many providers. With the following configuration, the Microsoft logger will first log to the Console provider, then to the Serilog provider:
.ConfigureLogging(logging => logging.AddConsole().AddSerilog())
The .UseSerilog() configures Serilog as the only provider. The following will send all logs to Serilog regardless of whether you've configured the logging pipeline:
.UseSerilog();
The difference really boils down to using Micosoft's pluggable model or using Serilog's pluggable model.
Typically you wouldn't use .AddSerilog() as the Serilog library is really intended to be used as the sole provider with one or more "sinks", but there may be cases where you need to log to a particular destination for which there exists a Micosoft ILogger and ILoggerProvider, but for which no Serilog sink exists (and you don't want to have to write it yourself). In such cases, you might choose to add Serilog as an additional provider.
There is no difference, only syntax varies. However you need to ensure that if you read from configuration then there is no need to mention enrichers or files in the declaration, else you might end up creating two log file output:
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(builder.Configuration)
.Enrich.FromLogContext() // No need
.WriteTo.Console() // No need
.WriteTo.File("Logs/Log.txt") // No Need
.CreateLogger();
With intellisense it is easier to define the configuration in code rather than in appsetting.json. As opposed to configuration you can detect error in this method quite easily. Hence better use :
Log.Logger = new LoggerConfiguration()
.Enrich.FromLogContext()
.WriteTo.Console()
.WriteTo.File("Logs/Log.txt")
.CreateLogger();
I am using Serilog in both a class library and a .NET console application (C#). The logger is currently configured in the console application:
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Verbose()
.WriteTo.File(
"verboseLog.txt",
restrictedToMinimumLevel: Serilog.Events.LogEventLevel.Verbose,
outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}"
)
.CreateLogger();
I would like to conditionally configure it in the library if the caller has not configured it yet. (This library may be used with other applications in the future by other programmers.) Serilog's wiki on Github doesn't mention any default value for Log.Logger, and I haven't found an answer anywhere else. Is there a way to detect if the static Log.Logger has already been configured in Serilog?
Configuring the logging system in a library is not a good idea. Logging configuration is something you want to do at the application level. I'd wager that there's a good reason you can't know if the logger is configured or not: because you don't need to know! 😉
With that said, here's a (dirty) solution to figure out if the logger is configured or not:
bool isLoggerConfigured = Log.Logger.GetType().Name != "SilentLogger";
Note that this solution relies on an implementation detail (the name of the silent logger internal class) that might change in the future.
I wanted my application to have capability of logging to a file, so I started to look for something more than default .NET Core 2.2 logging framework. I see that Serilog might do the job. However, I cannot find any document on how to setup Serilog in .NET Core Console application with Dependency Injection. All I see is ASP.NET materials, which is probably not what I need.
I started doing it myself. I installed (Nuget):
Serilog
Serilog.Extensions.Logging
Serilog.Sinks.File
Serilog.Sinks.Console (to use Serilog for all my logging)
I created an extension forServiceCollection
public static void AddLogging(this IServiceCollection services, Microsoft.Extensions.Logging.LogLevel logLevel)
{
var serilogLogger = new LoggerConfiguration()
.WriteTo.Console()
.WriteTo.File("log.txt")
.CreateLogger();
services.AddLogging(builder =>
{
builder.SetMinimumLevel(logLevel);
builder.AddSerilog(logger: serilogLogger, dispose: true);
});
}
Logging works, however:
log level is not what I set it to. It seems that serilog is using INFO level, although I wanted to have DEBUG. Why isn't my setting respected? After all, I'm still using NET Core's logging framework, so I'm using it to setup the log level
am I actually doing this setup correctly? I am not really sure if dispose should be true. Generally, I want NET Core's Dependency Injection framework to take care of disposal of services.
I'm not sure about builder.SetMinimumLevel (it doesn't use the Serilog enum).
We set the logger level when creating the LoggerConfiguration object.
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.Console(restrictedToMinimumLevel: LogEventLevel.Debug) // restricted... is Optional
(...)
.CreateLogger();
BTW. It's worth pointing out the following section from Configuration Basics
Logger vs. sink minimums - it is important to realize that the logging level can only be raised for sinks, not lowered. So, if the logger's MinimumLevel is set to Information then a sink with Debug as its specified level will still only see Information level events. This is because the logger-level configuration controls which logging statements will result in the creation of events, while the sink-level configuration only filters these. To create a single logger with a more verbose level, use a separate LoggerConfiguration.
I'm not sure about builder.AddSerilog.
Here's what works for me.
using Serilog;
(...)
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
(...)
.CreateLogger();
(...)
return new HostBuilder()
.ConfigureHostConfiguration(...)
.ConfigureServices(...)
.UseSerilog();
I'd like to use Serilog for my project, but I can't quite get it to work properly.
Right now, this is what I've got, just for verifying and testing purposes:
public MainLogger([NotNull] ILogPathProvider logPathProvider)
{
m_logger = Log.Logger = new LoggerConfiguration()
.WriteTo.Console()
.CreateLogger();
m_logger.Warning("blabla");
}
As you can see, there is not a lot going on besides just opening a log and trying to write a warning.
However, this warning does not appear.
Is there anything I forgot to configure / call?
Assuming you installed the correct NuGet Packages (Serilog and Serilog.Sinks.Console), then your code sample should print a Warning message in the console without requiring any changes.
You can confirm this by creating a simple Console application, installing the packages above, and running the same code.
The problem is elsewhere in your application and/or environment... It has nothing to do with Serilog.
Most likely, your method MainLogger is not being called at all, or perhaps your Console output is being redirected to somewhere else.
I am looking at serilog and running a few tests. So far it is working fine writing to the console or file. However I am not having any luck getting it to work with the RavenDb sink. I am trying to get this working in an asp.net 5 app.
I have reviewed the following articles:
http://nblumhardt.com/2015/05/diagnostic-logging-in-dnx-asp-net-5/
http://nblumhardt.com/2013/06/serilog-and-ravendb/
I started with an empty app, and added the following dependencies in project.json.
"Serilog.Framework.Logging": "1.0.0-rc1-final-10071",
"Serilog.Sinks.RavenDB": "1.5.4",
"RavenDB.Client": "3.0.30000"
I also removed dnxcore.
Then I added the following code in startup.cs:
public Startup()
{
var documentStore = new DocumentStore()
{
Url = "http://localhost:8080",
DefaultDatabase = "Logs"
}.Initialize();
Log.Logger = new LoggerConfiguration()
.WriteTo.File(#"c:\temp\log.txt")
.WriteTo.Console()
.WriteTo.RavenDB(documentStore)
.CreateLogger();
}
public void ConfigureServices(IServiceCollection services)
{
}
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
loggerFactory.AddSerilog();
app.UseIISPlatformHandler();
app.Run(async (context) =>
{
Log.Information("Hello World");
await context.Response.WriteAsync("Hello World!");
});
}
Everything gets logged to the file and console just fine, and the Logs database gets created, but no log entries are stored in RavenDb.
I have tried various log levels. I tried reducing the batch size. I suspected this had something to do with the lifecycle of the document store, so I added the following in the ConfigureServices method.
services.AddSingleton(x =>
{
return new DocumentStore()
{
Url = "http://localhost:8080/",
DefaultDatabase = "Test",
}.Initialize();
}
Then I moved the logger configuration code into the Configure method and used DI instance, but that doesn't work either. I can store other objects in RavenDb using the same DocumentStore just fine.
Have I missed a configuration setting or something?
I was able to get this working with the latest RavenDb client. I created a new (package) style library, added Serilog nuget package v2.0.0-beta-403, added the RavenDB.Client v3 nuget package, and dropped in the .cs files from the existing Serilog.Sinks.RavenDb library. It compiled and worked, I didn't have to change any code.
I haven't had a chance to test it much yet, but it seem to be working fine. Of course I don't know how stable Serilog v2 beta is, or how long until it is released. The nice thing is that serilog v2 supports .netcore. Unfortunately the RavenDb client doesn't, at least not yet.