Is there an option in Serilog to change log file parameters in runtime, the same way LogLevel can be changed? - asp.net-core

With Serilog in asp.net core you can change the log level in runtine by using
MinimumLevel.ControlledBy(SeriLogLevelSwitch).
Is there a similar way to do this with LoggerConfiguration().WriteTo.File(...)
For instance i need to change the configuration for log fileSizeLimitBytes, or rollingInterval withour restaring the service. Can this be achieved with Serilog?

By pulling in the latest Serilog.AspNetCore you'll find a class called ReloadableLogger, constructed through the CreateBootstrapLogger() extension method:
// using Serilog;
var logger = new LoggerConfiguration()
.WriteTo.File(...)
.CreateBootstrapLogger();
// Optional but suggested:
Log.Logger = logger;
// Use the logger...
// Change parameters later on:
logger.Reload(lc => lc
.WriteTo.File(...));
You might find that some interactions between CreateBootstrapLogger() and UseSerilog(callback) in ASP.NET Core trip things up a bit; if you use this technique, try the parameterless version of UseSerilog().
ReloadableLogger has only just appeared and is focusing on a slightly different scenario, so you may still need to work through some awkwardness setting this up - YMMV.

Related

Can I determine `IsDevelopment` from `IWebJobsBuilder`

Very much an XY problem, but I'm interested in the underlying answer too.
See bottom for XY context.
I'm in a .NET Core 3 AzureFunctions (v3) App project.
This code makes my question fairly clear, I think:
namespace MyProj.Functions
{
internal class CustomStartup : IWebJobsStartup
{
public void Configure(IWebJobsBuilder builder)
{
var isDevelopment = true; //Can I correctly populate this, such that it's true only for local Dev?
if(isDevelopment)
{
// Do stuff I wouldn't want to do in Prod, or on CI...
}
}
}
}
XY Context:
I have set up Swagger/Swashbuckle for my Function, and ideally I want it to auto-open the swagger page when I start the Function, locally.
On an API project this is trivial to do in Project Properties, but a Functions csproj doesn't have the option to start a web page "onDebug"; that whole page of project Properties is greyed out.
The above is the context in which I'm calling builder.AddSwashBuckle(Assembly.GetExecutingAssembly()); and I've added a call to Diagnostics.Process to start a webpage during Startup. This works just fine for me.
I've currently got that behind a [Conditional("DEBUG")] flag, but I'd like it to be more constrained if possible. Definitely open to other solutions, but I haven't been able to find any so ...
While I am not completely sure that it is possible in azure functions I think that setting the ASPNETCORE_ENVIRONMENT application setting as described in https://learn.microsoft.com/en-us/azure/azure-functions/functions-how-to-use-azure-function-app-settings should allow you to get whether the environment is set as production or development by injecting a IHostEnvironment dependency and checking
.IsDevelopment()
on the injected dependency.

EF Core Migration error: "Unable to create an object of type 'ApplicationContext'"

I'm trying to do the migration with EF Core but I get an error - how can I fix this error?
PM> add-migration ini
Unable to create an object of type 'ApplicationContext'. Add an
implementation of 'IDesignTimeDbContextFactory' to
the project, or see https://go.microsoft.com/fwlink/?linkid=851728 for
additional patterns supported at design time.
This will also happen if you have multiple start-up projects - when migrating, just select one (in VS right click Solution and Set StartUp Projects...)
I had the same issue with asp.net core 3.1.
For me, it was pretty straight forward, adding an implementation of IDesignTimeDbContextFactory to the main web project fixed the issue.
A basic implementation looks something like this:
public class DesignTimeDbContextFactory : IDesignTimeDbContextFactory<YourDbContext>
{
public YourDbContext CreateDbContext(string[] args)
{
IConfigurationRoot configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.Build();
var builder = new DbContextOptionsBuilder<YourDbContext >();
var connectionString = configuration.GetConnectionString("DefaultConnection");
builder.UseSqlServer(connectionString);
return new YourDbContext(builder.Options);
}
}
Please refer to this blog post on the subject.
It is highly probably because of your default startup project:
Open Package manager console and write this command:
PM> Add-Migration -StartupProject[YourProjectPath(just press a tab all the.csproj paths will come up, and then choose your DataBaseLayer project to execute a migration for)] migrationName
In this way you don't need to again go to solution and set startup
project with your webProject whenever you finished adding a new migration.
1.Modify your code in ConfigureService with :
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"),
x => x.MigrationsAssembly("WebApplication")));
In command line which includes WebApplication.csproj:
dotnet ef migrations add Init
I got this error when creating a migration. In my code in the ApplicationContext constructor, I used the Database.EnsureCreated() method. Typically this method is used for small applications where you need to check for the existence of a database and create it once. When creating an application with a database that will change with new versions and using migrations, you should not use this method.
In my case, this error existed because I was applying migrations at runtime. After removing Database.Migrate(); in my code, I was able to add the new migration without errors.
By the way, I used EF Core .NET command-line interface (CLI) tools, not the Package Manager Console (I run into problems I couldn't solve when I was using the Package Manager Console, so I went for the CLI alternative, and it was worth the change).
Also, make sure you use the appropriate options to select your startup project and your target project.
I got this error when the Primary Key for the table was not set manually (with attributes or with FluentAPI) and was not determined automatically (not "Id" kayword and not "TableName" + "Id")
Stack: ASP.NET Core EF + Postgres (Npgsql)

How to remove properties from log entries in ASP.Net Core

I'm using Serilog with ASP.Net Core 2.0, writing to RollingFile using JsonFormatter. Followed the instructions here to configure: https://github.com/serilog/serilog-aspnetcore. Everything works great, but in every log entry I get the following properties that I did not log:
SourceContext
RequestId
RequestPath
I presume they are being added by the ASP.Net Core logging framework. How can I get rid of them?
This can be achieved by plugging an enricher into the logging pipeline:
.Enrich.With(new RemovePropertiesEnricher())
Where:
class RemovePropertiesEnricher : ILogEventEnricher
{
public void Enrich(LogEvent le, ILogEventPropertyFactory lepf)
{
le.RemovePropertyIfPresent("SourceContext");
le.RemovePropertyIfPresent("RequestId");
le.RemovePropertyIfPresent("RequestPath");
}
}
Yes, you can get rid of them. Try to use log template:
_loggerConfiguration.WriteTo.Console(LogLevel.Debug, "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level}] {Message}{NewLine}{Exception}");
In this scenario, you won't see mentioned properties in your output.
When you are logging an object, Serilog has the concept of destructuring.
And if you want to remove(ignore) some properties in those objects for logging, there are two options.
You can use attributes. Take a look at this post.
Then there is by-ignoring. You need this Destructurama.ByIgnoring nuget.
Note you should not use both. Using both did not work for me.

Serilog configuration and Application Insight .net core

Im trying to filter my input to application insight by configuration. Im sending data from SeriLog with the ApplicationInsightsTraces-sink as can be seen below in my configuration:
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(Configuration)
.WriteTo
.ApplicationInsightsTraces(Configuration.GetSection("ApplicationInsights")
.GetSection("InstrumentationKey").Value)
.CreateLogger();
This code sends the correct data to the "Trace" in Application Insights but AI gets the traces from somewhere else also. I guess the framework in some way? I would like to turn off the standard logging of traces from the framework so that I can use only one filter for what to log (loglevel and specific overrides for example "Microsoft.AspNetCore": "Warning". I would prefer to not filter in a processor for each Trace. Any ideas?
It seems to be working the way I want it to when I reset the options object by row provided below. Im not exactly sure which property in ApplicationInsightsServiceOptions that did the change.
services.Configure<ApplicationInsightsServiceOptions>(
options => Configuration.GetSection("applicationInsights").Bind(options));

NServiceBus Generic Host and Common.Logging

Folks,
I got NServiceBus logging working correctly following the directions found here:
http://docs.particular.net/nservicebus/logging/
However, I am using Common.Logging. If I use the LogManager for Common.Logging, it doesn't log.
If I use the LogManager for log4net, everything works just fine.
Anyone have any insight here?
I figured this out. I needed to programatically set up Common.Logging instead of declaratively (in the config file).
Basically, I added this line before I did my fluent bus configuration:
LogManager.Adapter = new Log4NetLoggerFactoryAdapter(new NameValueCollection { { "configType", "INLINE" } });
SetLoggingLibrary.Log4Net(log4net.Config.XmlConfigurator.Configure);
And my bus logging section looks like this:
.Log4Net<ColoredConsoleAppender>(cca =>
{
cca.Layout = patternLayout;
})
.Log4Net<RollingFileAppender>(fa =>
{
fa.File = "log/handler.log";
fa.AppendToFile = true;
fa.RollingStyle = RollingFileAppender.RollingMode.Size;
fa.MaxSizeRollBackups = 5;
fa.MaximumFileSize = "1000KB";
fa.StaticLogFileName = true;
fa.Layout = patternLayout;
})
This allows me to load the logging levels in the config file, but leave the appender configuration in code as suggested by Udi (and I think it's a great idea)
I know I could of used the built in logging level of nServiceBus, but I couldn't figure out how to get fine grained control of that so that I could ignore nHibernate logging, but get all of the nServiceBus logging.
If anyone needs more guidance as to what I did, just comment here, or if you know how to get fine grained control using the nServiceBus logging level, let me know that too.
Common.Logging serves as an abstraction from log4net for the internal purposes of NServiceBus.
As of NServiceBus 5 CommonLogging is supported OOTB http://docs.particular.net/nservicebus/logging/common-logging