Install the Serilog.Enrichers.GlobalLogContext package from NuGet:
Install-Package Serilog.Enrichers.GlobalLogContext
Add the Serilog namespaces to your C# file:
using Serilog;
using Serilog.Context;
Include the global log context enricher in your logger configuration:
Log.Logger = new LoggerConfiguration()
.Enrich.FromGlobalLogContext()
// ... other configuration ...
.CreateLogger();
The FromGlobalLogContext() enricher dynamically adds properties present in the Serilog.Context.GlobalLogContext, to all produced events in your application.
Then, properties can be added and removed from the global log context using GlobalLogContext.PushProperty():
GlobalLogContext.PushProperty("AppVersion", GetThisAppVersion());
GlobalLogContext.PushProperty("OperatingSystem", GetCurrentOS());
After the code above is executed, any log event written to any Serilog sink will carry the properties AppVersion and OperatingSystem automatically.
Source: https://github.com/augustoproiete/serilog-enrichers-globallogcontext
Original answer
One way to achieve that, would be to create a custom Serilog Enricher that you hook up to the Serilog logging pipeline at the start, that you can also access throughout your application (ideally via dependency injection).
This enricher would provide you with a way to add new properties, and it would be responsible in making sure that the properties are applied to all log events.
The example below is a simplified version of this idea (definitely not recommended for production use as-is, but rather as pseudo-code to show the basics of how the main pieces fit together):
// WARNING: This is *NOT* Production code :)
public sealed class GlobalPropertyEnricher : ILogEventEnricher
{
// TODO: Make it thread-safe
private static readonly Dictionary<string, object> _properties =
new Dictionary<string, object>();
private static readonly Lazy<GlobalPropertyEnricher> _instance =
new Lazy<GlobalPropertyEnricher>(() => new GlobalPropertyEnricher());
public static GlobalPropertyEnricher Instance => _instance.Value;
private GlobalPropertyEnricher()
{
}
public static void SetProperty(string propertyName, object value)
{
// TODO: Make it thread-safe
_properties[propertyName] = value;
}
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
{
// TODO: Make it thread-safe
// TODO: Properties should be cached (instead of CreateProperty) every time
foreach (var p in _properties)
{
var property = propertyFactory.CreateProperty(p.Key, p.Value);
logEvent.AddPropertyIfAbsent(property);
}
}
}
NB: For the purposes of this example, I have a static class accessible globally through your app, but you prob. would have that registered as a singleton instance in your DI container.
With the enricher example above, you can add/replace properties from anywhere via GlobalPropertyEnricher.SetProperty. e.g.
GlobalPropertyEnricher.SetProperty("Name", "Augusto");
GlobalPropertyEnricher.SetProperty("Year", DateTime.UtcNow.Year);
Finally, when you include the enricher in the Serilog pipeline, all the properties you set will be added to every event log message you write anywhere in the app:
Log.Logger = new LoggerConfiguration()
.Enrich.With(GlobalPropertyEnricher.Instance)
.WriteTo.(...)
.CreateLogger();