Skip to content

Instantly share code, notes, and snippets.

@chrisfcarroll
Last active September 21, 2017 20:58
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chrisfcarroll/7c44af5929507643b84c410a639e62d2 to your computer and use it in GitHub Desktop.
Save chrisfcarroll/7c44af5929507643b84c410a639e62d2 to your computer and use it in GitHub Desktop.
A StringList Sink for Serilog. Typical usage:
using System;
using System.Collections.Generic;
using System.IO;
using Serilog;
using Serilog.Configuration;
using Serilog.Core;
using Serilog.Events;
using Serilog.Formatting;
using Serilog.Formatting.Display;
namespace TestBase.Extra
{
/// <summary>
/// An <see cref="ILogEventSink"/> sink for Serilog which logs to a given <see cref="IList{T}"/> of string.
/// Each emitted <see cref="LogEvent"/> will be <see cref="ICollection{T}.Add"/>ed to the IList after being formatted
/// by the given <see cref="ITextFormatter"/>
/// </summary>
/// <remarks>
/// You may wish to be careful to only use this for short-lived loggers if you use a <see cref="List{T}"/>
/// or other in-memory structure as your <see cref="IList{T}"/>.
/// </remarks>
class StringListSink : ILogEventSink
{
readonly IList<string> stringList;
readonly ITextFormatter _textFormatter;
readonly object _syncRoot = new object();
/// <summary>
/// An <see cref="ILogEventSink"/> sink for Serilog which logs to a given <see cref="IList{T}"/> of string.
/// </summary>
/// <param name="stringList">You may wish to be careful to only use this for short-lived loggers, if you
/// use a <see cref="List{T}"/> or other in-memory structure as your <see cref="IList{T}"/>.</param>
public StringListSink(IList<string> stringList, ITextFormatter textFormatter)
{
if (textFormatter == null) throw new ArgumentNullException("textFormatter");
this.stringList = stringList;
_textFormatter = textFormatter;
}
public void Emit(LogEvent logEvent)
{
if (logEvent == null) throw new ArgumentNullException("logEvent");
lock (_syncRoot)
{
using (var payload = new StringWriter())
{
_textFormatter.Format(logEvent, payload);
stringList.Add(payload.ToString());
}
}
}
public static ILogEventSink For(IList<string> stringList)
{
var formatter = new MessageTemplateTextFormatter(DefaultOutputTemplate,null);
return new StringListSink(stringList, formatter);
}
internal const string DefaultOutputTemplate = "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] {Message}{NewLine}{Exception}";
}
public static class StringListLoggerConfigurationExtensions
{
/// <summary>
/// Write log events to the provided <see cref="StringListSink"/>.
/// </summary>
/// <param name="sinkConfiguration">Logger sink configuration.</param>
/// <param name="stringList">The string list to write log events to.</param>
/// <param name="outputTemplate">Message template describing the output format.</param>
/// <param name="restrictedToMinimumLevel">The minimum level for
/// events passed through the sink.
/// <returns>Configuration object allowing method chaining.</returns>
/// <param name="formatProvider">Supplies culture-specific formatting information, or null.</param>
/// <exception cref="ArgumentNullException"></exception>
public static LoggerConfiguration StringList(
this LoggerSinkConfiguration sinkConfiguration,
IList<string> stringList,
LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum,
string outputTemplate = StringListSink.DefaultOutputTemplate,
IFormatProvider formatProvider = null)
{
if (stringList == null) throw new ArgumentNullException("stringList");
if (outputTemplate == null) throw new ArgumentNullException("outputTemplate");
var formatter = new MessageTemplateTextFormatter(outputTemplate, formatProvider);
var sink = new StringListSink(stringList, formatter);
return sinkConfiguration.Sink(sink, restrictedToMinimumLevel);
}
/// <summary>
/// Write log events to the provided <see cref="System.IO.TextWriter"/>.
/// </summary>
/// <param name="sinkConfiguration">Logger sink configuration.</param>
/// <param name="stringList">The string list to write log events to.</param>
/// <param name="formatter">Text formatter used by sink.</param>
/// /// <param name="restrictedToMinimumLevel">The minimum level for
/// events passed through the sink.
/// <exception cref="ArgumentNullException"></exception>
public static LoggerConfiguration StringList(
this LoggerSinkConfiguration sinkConfiguration,
ITextFormatter formatter,
IList<string> stringList,
LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum)
{
if (stringList == null) throw new ArgumentNullException("stringList");
if (formatter == null) throw new ArgumentNullException("formatter");
var sink = new StringListSink(stringList, formatter);
return sinkConfiguration.Sink(sink, restrictedToMinimumLevel);
}
}
}
@chrisfcarroll
Copy link
Author

chrisfcarroll commented Jun 12, 2017

Typical usage

// Given field loglines= new List<string>();
logger = new LoggerConfiguration().WriteTo.StringList(loglines).MinimumLevel.Debug().CreateLogger();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment