Enriches Serilog events with information from HttpContext.Current
To use the enricher first install the NuGet package
Install-Package Serilog.Enrichers.HttpContextData
Then, apply the enricher to you LoggerConfiguration
:
Log.Logger = new LoggerConfiguration()
.Enrich.WithHttpContextData()
// ...other configuration...
.CreateLogger();
You will have enriched log events that look like the screenshot below (Serilog log event sinked to Seq)
You can configure the HttpContextDataEnricher to enable filtering of captured log data by HttpContextData instance
// Create a settings instance
HttpContextDataLogFilterSettings settings = new HttpContextDataLogFilterSettings();
// Append full stack trace if enriched log event has an Exception object
settings.AppendFullStackTrace = true;
//Form submitted values to replace on save - this prevents logging passwords, etc
settings.FormFilters = new List<HttpContextDataLogFilter>
{
new HttpContextDataLogFilter { Name= "Password", ReplaceWith="" } // Do not capture form field named Password. See "Filter Name and ReplaceWith conventions"
, new HttpContextDataLogFilter { Name = "Pwd", ReplaceWith = "*** WE DO NOT RECORDS PASSWORDS *** " } // Capture field named Pwd and replace the value
};
//Cookie values to replace on save - this prevents logging auth tokens, etc.
settings.CookieFilters = new List<HttpContextDataLogFilter>
{
new HttpContextDataLogFilter { Name= "AUTH", ReplaceWith="" } // Do not capture cookie named AUTH. See "Filter Name and ReplaceWith conventions"
, new HttpContextDataLogFilter { Name = "SESS_ID", ReplaceWith = "*** WE DO NOT RECORDS COOKIES *** " } // Capture cookie named SESS_ID and replace the value
};
//Request header values to replace on save - this prevents logging sensitive request headers.
settings.HeaderFilters = new List<HttpContextDataLogFilter>
{
new HttpContextDataLogFilter { Name= "", ReplaceWith="" } // This is a special case. See "Filter Name and ReplaceWith conventions"
, new HttpContextDataLogFilter { Name = "Accept", ReplaceWith = "***" } // Capture Accept header value and replace
, new HttpContextDataLogFilter { Name = "Content-Type", ReplaceWith = "" } // Do not capture Content-Type header value. See "Filter Name and ReplaceWith conventions"
};
//Server variable values to replace on save - this prevents logging sensitive request headers.
settings.ServerVarFilters = new List<HttpContextDataLogFilter>
{
new HttpContextDataLogFilter { Name = "ALL_HTTP", ReplaceWith = "***" } // Capture ALL_HTTP server variable and replace
, new HttpContextDataLogFilter { Name = "ALL_RAW", ReplaceWith = "" } // Do not capture ALL_RAW server variable. See "Filter Name and ReplaceWith conventions"
};
//The Regex pattern of data keys to include. For example, "Redis.*" would include all keys that start with Redis
//This is applied only if enriched log event has an Exception object. Matched data values from exceptions Data array are captured in CustomData property of the HttpContextData instance
settings.DataIncludePattern = @"\b([0-9]{1,3}\.){3}[0-9]{1,3}$"
While capturing context data two conventions are followed to discard a single value with a specified name or set of values.
If you have a HttpContextDataLogFilter instance with empty string (be warned not null) Name inside a HttpContextDataLogFilterSettings filter all items will be discarded and not captured.
HttpContextDataLogFilterSettings settings = new HttpContextDataLogFilterSettings();
// The second HttpContextDataLogFilter instance has an empty string name which will cause all header items to be discarded
settings.HeaderFilters = new List<HttpContextDataLogFilter>
{
new HttpContextDataLogFilter { Name = "Accept", ReplaceWith = "***" } // Capture Accept header value and replace
, new HttpContextDataLogFilter { Name= "", ReplaceWith="" } // This is a special case. See "Filter Name and ReplaceWith conventions"
, new HttpContextDataLogFilter { Name = "Content-Type", ReplaceWith = "" } // Do not capture Content-Type header value. See "Filter Name and ReplaceWith conventions"
};
If you have a HttpContextDataLogFilter instance with empty string (be warned not null) Value inside a HttpContextDataLogFilterSettings filter that specific item matching the Name value will be discarded
HttpContextDataLogFilterSettings settings = new HttpContextDataLogFilterSettings();
// The second HttpContextDataLogFilter instance has an empty string value for "Content-Type" which will cause Content-Type header value to be discarded
settings.HeaderFilters = new List<HttpContextDataLogFilter>
{
new HttpContextDataLogFilter { Name = "Accept", ReplaceWith = "***" } // Capture Accept header value and replace
, new HttpContextDataLogFilter { Name = "Content-Type", ReplaceWith = "" } // Do not capture Content-Type header value. See "Filter Name and ReplaceWith conventions"
};
NEW With version 0.1.1 You can also specify a regular expression in the Name
property of an HttpContextDataLogFilter
instance, in this case you will need to set the NameIsRegex
property to true.
Please note regex filters also follow the the empty string convention described above.
var logFilterSettings = new HttpContextDataLogFilterSettings
{
ServerVarFilters = new List<HttpContextDataLogFilter>
{
new HttpContextDataLogFilter {Name = "AUTH_U.*", ReplaceWith = "", NameIsRegex = true }, // will remove all server variables matched by the regex specified in the Name property.
new HttpContextDataLogFilter {Name = "AUTH_PASSWORD", ReplaceWith = "***"},
}
};
// Prepare the log filter settings instance
HttpContextDataLogFilterSettings settings = new HttpContextDataLogFilterSettings();
// The second HttpContextDataLogFilter instance has an empty string value for "Content-Type" which will cause Content-Type header value to be discarded
settings.HeaderFilters = new List<HttpContextDataLogFilter>
{
new HttpContextDataLogFilter { Name = "Accept", ReplaceWith = "***" } // Capture Accept header value and replace
, new HttpContextDataLogFilter { Name = "Content-Type", ReplaceWith = "" } // Do not capture Content-Type header value. See "Filter Name and ReplaceWith conventions"
};
//...
// Maybe, some more settings....
//...
//Create the enricher
var contextEnricher = new HttpContextDataEnricher(LogEventLevel.Error, settings);
Log.Logger = new LoggerConfiguration()
.Enrich.With(contextEnricher) // <<--- This is how we configure our enricher
// ...other configuration...
.CreateLogger();
HttpContextDataEnricher uses LogEventLevel.Error as the minimum log level which means only log events with log level of Error and above will be enriched. But, you can customize MinimumLogLevel as demonstrated in "Initializing the Enricher with settings" section
Serilog supports deserializing log event property as structured objects through destructuring operator. You can create an HttpContextData instance and log context data without using the enricher. Here is an example
var text = $"Destructured info log message on {DateTime.Now}";
var ctxData = new HttpContextData(this.HttpContext);
var dto = ctxData.ToDto(); // <--- ToDto() extension method creates a serialazable anonymous copy of HttpContextData instance
// Log destructured httpcontext data
Log.Logger.Information("Here is the current context data {@dto}", dto);
HttpContextData and HttpContextDataLogFilter classes include code inspired by Nick Craver's work on StackExchange.Exceptional