Provides Serilog appender for Sitecore.
Note. This repository is unofficial private project and is not supported by Sitecore.
- Serilog integration in Sitecore
- Use any Sink from Serilog with Sitecore
- Custom enricher for Sitecore context (like database, context item, page item, rendering, datasource, etc) in log event (with option to extend it)
- Custom HTTP context enricher (currently HTTP method and URL are logged)
- Add your custom enrichers
You can see how your log event with exception details could look like (in SEQ):
See examples project for more details.
Create a custom appender:
namespace SitecoreSerilog.Example
{
public class BaseSeqSitecoreAppender : BaseSitecoreSerilogAppender
{
public string ApiKey { get; set; }
public string SeqHost { get; set; }
// configure Enrichers here (use listed below or define your own enrichers):
protected override LoggerConfiguration Enrich(LoggerConfiguration configuration)
{
return configuration
// application name enricher (so you know, which site is used)
.Enrich.WithApplicationName(() => Sitecore.Context.Site?.Name ?? "FallbackValue")
// spoke name enricher (so you know, which environment is used)
.Enrich.WithSpokeName(Settings.GetSetting("SpokeName"))
.Enrich.FromLogContext()
.Enrich.WithUtcTimestamp()
.Enrich.WithMachineName()
.Enrich.WithEnvironmentUserName()
.Enrich.WithProcessId()
.Enrich.WithProcessName()
.Enrich.WithThreadId()
.Enrich.WithMemoryUsage()
// custom SitecoreContextEnricher - so you can see the Sitecore Context Details in log event
.Enrich.WithSitecoreContext((options) => { options.MinLevel = LogEventLevel.Error; })
// custom HttpContextEnricher - so you can see HttpContext details in log event
.Enrich.WithHttpContext(LogEventLevel.Error)
;
}
// configure where Serilog should write
protected override LoggerConfiguration WriteTo(LoggerConfiguration configuration)
{
return configuration
// in this example I write to SEQ, but you can use any Sink you need
.WriteTo.Seq(SeqHost, apiKey: ApiKey);
}
// validate your configuration (if returned false - Serilog won't write anything)
protected override bool ValidateConfiguration()
{
return !string.IsNullOrEmpty(SeqHost);
}
}
}
Use your appender:
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/"
xmlns:set="http://www.sitecore.net/xmlconfig/set/">
<sitecore>
<log4net>
<!-- use custom appender class here: -->
<appender name="SerilogAppender"
type="SitecoreSerilog.Example.BaseSeqSitecoreAppender, SitecoreSerilog.Example"
patch:after="appender[@name='LogFileAppender']">
<minimumlevel value="INFO" />
<apikey value="$(env:SEQ_API_KEY)" />
<seqhost value="$(env:SEQ_URL)" />
<layout type="log4net.Layout.PatternLayout" />
<encoding value="utf-8" />
</appender>
<!-- add it to root logger -->
<root>
<appender-ref ref="SerilogAppender" patch:after="*[@ref='LogFileAppender']" />
</root>
<!-- or add it to any other logger, e.g. Crawling: -->
<logger name="Sitecore.Diagnostics.Crawling">
<appender-ref ref="SerilogAppender" patch:after="*[@ref='CrawlingLogFileAppender']" />
</logger>
</log4net>
</sitecore>
</configuration>
.Enrich.WithSitecoreContext(LogEventLevel.Error)
E.g. add additional items to Logger:
.Enrich.WithSitecoreContext(options =>
{
// configure min log level:
options.MinLevel = LogEventLevel.Error;
// extend default enrich object:
options
// add current Sitecore MVC page context
.WithItem("PageItem", () => PageContext.CurrentOrNull?.Item)
// add current rendering datasource
.WithItem("Datasource", () => RenderingContext.CurrentOrNull?.Rendering?.Item)
.WithContextOption(Constants.OptionNames.Context,
context =>
{
// add current RenderingId
context.WithProperty("RenderingId",
() => RenderingContext.CurrentOrNull?.Rendering?.Id.ToString());
})
;
})
.Enrich.WithHttpContext(LogEventLevel.Error)
Use SelfLog
from Serilog to troubleshoot issues.
Can be configured in the following way:
using Serilog.Core;
using Serilog.Debugging;
using SitecoreSerilog.Appenders;
namespace SitecoreSerilog.Example
{
public class TroubleshootingAppender : BaseSitecoreSerilogAppender
{
// all the required methods
// called after Serilog logger configured
protected override void AfterActivateOptions(Logger logger)
{
base.AfterActivateOptions(logger);
// configure Serilog internal output into default Sitecore output (need to be configured once)
SelfLog.Enable(ErrorHandler.Error);
}
}
}
Then in the default Sitecore log.txt
file you can see if any issue occured. E.g.:
2660 12:17:03 INFO Trace: log4net:ERROR [SerilogAppender] 2024-06-11T10:17:03.2636440Z Exception while emitting periodic batch from Serilog.Sinks.Seq.SeqSink: System.AggregateException: One or more errors occurred. ---> System.Net.Http.HttpRequestException: An error occurred while sending the request. ---> System.Net.WebException: The remote name could not be resolved: '***********************'
at System.Net.HttpWebRequest.EndGetRequestStream(IAsyncResult asyncResult, TransportContext& context)
at System.Net.Http.HttpClientHandler.GetRequestStreamCallback(IAsyncResult ar)
--- End of inner exception stack trace ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Serilog.Sinks.Seq.SeqSink.<EmitBatchAsync>d__13.MoveNext()
--- End of inner exception stack trace ---
at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
at Serilog.Sinks.PeriodicBatching.PeriodicBatchingSink.EmitBatch(IEnumerable`1 events)
at Serilog.Sinks.PeriodicBatching.PeriodicBatchingSink.OnTick()
---> (Inner Exception #0) System.Net.Http.HttpRequestException: An error occurred while sending the request. ---> System.Net.WebException: The remote name could not be resolved: 'logging-seq.dev.apebs.de'
at System.Net.HttpWebRequest.EndGetRequestStream(IAsyncResult asyncResult, TransportContext& context)
at System.Net.Http.HttpClientHandler.GetRequestStreamCallback(IAsyncResult ar)
--- End of inner exception stack trace ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Serilog.Sinks.Seq.SeqSink.<EmitBatchAsync>d__13.MoveNext()<---
You can contact me via email or in Sitecore Slack: [email protected]
. Or please open an issue.