static SerilogLoggerProvider CreateProvider( string serverUrl, string apiKey, LogLevel minimumLevel, IDictionary <string, LogLevel> levelOverrides) { var levelSwitch = new LoggingLevelSwitch(minimumLevel); var sink = new SeqSink( serverUrl, apiKey, 1000, TimeSpan.FromSeconds(2), 256 * 1024, levelSwitch, null); LevelOverrideMap overrideMap = null; if (levelOverrides != null && levelOverrides.Count != 0) { var overrides = new Dictionary <string, LoggingLevelSwitch>(); foreach (var levelOverride in levelOverrides) { overrides.Add(levelOverride.Key, new LoggingLevelSwitch(levelOverride.Value)); } overrideMap = new LevelOverrideMap(overrides, levelSwitch); } var logger = new Logger(levelSwitch, sink, sink.Dispose, overrideMap); var provider = new SerilogLoggerProvider(logger); return(provider); }
/// <summary> /// Adds a sink that writes log events to a http://getseq.net Seq event server. /// </summary> /// <param name="loggerSinkConfiguration">The logger configuration.</param> /// <param name="serverUrl">The base URL of the Seq server that log events will be written to.</param> /// <param name="restrictedToMinimumLevel">The minimum log event level required /// in order to write an event to the sink.</param> /// <param name="batchPostingLimit">The maximum number of events to post in a single batch.</param> /// <param name="period">The time to wait between checking for event batches.</param> /// <param name="bufferBaseFilename">Path for a set of files that will be used to buffer events until they /// can be successfully transmitted across the network. Individual files will be created using the /// pattern <paramref name="bufferBaseFilename"/>-{Date}.json.</param> /// <param name="apiKey">A Seq <i>API key</i> that authenticates the client to the Seq server.</param> /// <returns>Logger configuration, allowing configuration to continue.</returns> /// <exception cref="ArgumentNullException">A required parameter is null.</exception> public static LoggerConfiguration Seq( this LoggerSinkConfiguration loggerSinkConfiguration, string serverUrl, LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum, int batchPostingLimit = SeqSink.DefaultBatchPostingLimit, TimeSpan?period = null, string apiKey = null, string bufferBaseFilename = null) { if (loggerSinkConfiguration == null) { throw new ArgumentNullException("loggerSinkConfiguration"); } if (serverUrl == null) { throw new ArgumentNullException("serverUrl"); } var defaultedPeriod = period ?? SeqSink.DefaultPeriod; ILogEventSink sink; if (bufferBaseFilename == null) { sink = new SeqSink(serverUrl, apiKey, batchPostingLimit, defaultedPeriod); } else { sink = new DurableSeqSink(serverUrl, bufferBaseFilename, apiKey, batchPostingLimit, defaultedPeriod); } return(loggerSinkConfiguration.Sink(sink, restrictedToMinimumLevel)); }
public void EventsAreFormattedIntoJsonPayloads() { var evt = Some.LogEvent("Hello, {Name}!", "Alice"); var json = SeqSink.FormatRawPayload(new[] { evt }, null); Assert.Contains("Name\":\"Alice", json); }
public void EventsAreDroppedWhenCompactJsonRenderingFails() { var evt = Some.LogEvent(new NastyException(), "Hello, {Name}!", "Alice"); var json = SeqSink.FormatCompactPayload(new[] { evt }, null); Assert.Empty(json); }
public void EventsAreDroppedWhenJsonRenderingFails() { var evt = Some.LogEvent(new NastyException(), "Hello, {Name}!", "Alice"); var json = SeqSink.FormatRawPayload(new[] { evt }, null); Assert.Contains("[]", json); }
/// <summary> /// Subscribes to an <see cref="IObservable{EventEntry}" /> using a <see cref="SeqSink" />. /// </summary> /// <param name="eventStream">The event stream. Typically this is an instance of <see cref="ObservableEventListener" />.</param> /// <param name="serverUrl">The base URL of the Seq server that log events will be written to.</param> /// <param name="apiKey">A Seq <i>API key</i> that authenticates the client to the Seq server.</param> /// <param name="bufferingInterval">The buffering interval between each batch publishing. Default value is <see cref="Buffering.DefaultBufferingInterval" />.</param> /// <param name="onCompletedTimeout">Time limit for flushing the entries after an <see cref="SeqSink.OnCompleted" /> call is received.</param> /// <param name="bufferingCount">Number of entries that will trigger batch publishing. Default is <see cref="Buffering.DefaultBufferingCount" /></param> /// <param name="maxBufferSize">The maximum number of entries that can be buffered before the sink starts dropping entries. /// This means that if the timeout period elapses, some event entries will be dropped and not sent to the store. Normally, calling <see cref="IDisposable.Dispose" /> on /// the <see cref="System.Diagnostics.Tracing.EventListener" /> will block until all the entries are flushed or the interval elapses. /// If <see langword="null" /> is specified, then the call will block indefinitely until the flush operation finishes.</param> /// <returns> /// A subscription to the sink that can be disposed to unsubscribe the sink and dispose it, or to get access to the sink instance. /// </returns> public static SinkSubscription<SeqSink> LogToSeq( this IObservable<EventEntry> eventStream, string serverUrl, string apiKey = null, TimeSpan? bufferingInterval = null, TimeSpan? onCompletedTimeout = null, int bufferingCount = Buffering.DefaultBufferingCount, int maxBufferSize = Buffering.DefaultMaxBufferSize) { var sink = new SeqSink( serverUrl, apiKey, bufferingInterval ?? Buffering.DefaultBufferingInterval, bufferingCount, maxBufferSize, onCompletedTimeout ?? Timeout.InfiniteTimeSpan); var subscription = eventStream.Subscribe(sink); return new SinkSubscription<SeqSink>(subscription, sink); }
/// <summary> /// Subscribes to an <see cref="IObservable{EventEntry}" /> using a <see cref="SeqSink" />. /// </summary> /// <param name="eventStream">The event stream. Typically this is an instance of <see cref="ObservableEventListener" />.</param> /// <param name="serverUrl">The base URL of the Seq server that log events will be written to.</param> /// <param name="apiKey">A Seq <i>API key</i> that authenticates the client to the Seq server.</param> /// <param name="bufferingInterval">The buffering interval between each batch publishing. Default value is <see cref="Buffering.DefaultBufferingInterval" />.</param> /// <param name="onCompletedTimeout">Time limit for flushing the entries after an <see cref="SeqSink.OnCompleted" /> call is received.</param> /// <param name="bufferingCount">Number of entries that will trigger batch publishing. Default is <see cref="Buffering.DefaultBufferingCount" /></param> /// <param name="maxBufferSize">The maximum number of entries that can be buffered before the sink starts dropping entries. /// This means that if the timeout period elapses, some event entries will be dropped and not sent to the store. Normally, calling <see cref="IDisposable.Dispose" /> on /// the <see cref="System.Diagnostics.Tracing.EventListener" /> will block until all the entries are flushed or the interval elapses. /// If <see langword="null" /> is specified, then the call will block indefinitely until the flush operation finishes.</param> /// <returns> /// A subscription to the sink that can be disposed to unsubscribe the sink and dispose it, or to get access to the sink instance. /// </returns> public static SinkSubscription <SeqSink> LogToSeq( this IObservable <EventEntry> eventStream, string serverUrl, string apiKey = null, TimeSpan?bufferingInterval = null, TimeSpan?onCompletedTimeout = null, int bufferingCount = Buffering.DefaultBufferingCount, int maxBufferSize = Buffering.DefaultMaxBufferSize) { var sink = new SeqSink( serverUrl, apiKey, bufferingInterval ?? Buffering.DefaultBufferingInterval, bufferingCount, maxBufferSize, onCompletedTimeout ?? Timeout.InfiniteTimeSpan); var subscription = eventStream.Subscribe(sink); return(new SinkSubscription <SeqSink>(subscription, sink)); }
/// <summary> /// Adds a sink that writes log events to a http://getseq.net Seq event server. /// </summary> /// <param name="loggerSinkConfiguration">The logger configuration.</param> /// <param name="serverUrl">The base URL of the Seq server that log events will be written to.</param> /// <param name="restrictedToMinimumLevel">The minimum log event level required /// in order to write an event to the sink.</param> /// <param name="batchPostingLimit">The maximum number of events to post in a single batch.</param> /// <param name="period">The time to wait between checking for event batches.</param> /// <param name="bufferBaseFilename">Path for a set of files that will be used to buffer events until they /// can be successfully transmitted across the network. Individual files will be created using the /// pattern <paramref name="bufferBaseFilename"/>-{Date}.json.</param> /// <param name="apiKey">A Seq <i>API key</i> that authenticates the client to the Seq server.</param> /// <param name="bufferFileSizeLimitBytes">The maximum size, in bytes, to which the buffer /// log file for a specific date will be allowed to grow. By default no limit will be applied.</param> /// <returns>Logger configuration, allowing configuration to continue.</returns> /// <exception cref="ArgumentNullException">A required parameter is null.</exception> public static LoggerConfiguration Seq( this LoggerSinkConfiguration loggerSinkConfiguration, string serverUrl, LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum, int batchPostingLimit = SeqSink.DefaultBatchPostingLimit, TimeSpan?period = null, string apiKey = null, string bufferBaseFilename = null, long?bufferFileSizeLimitBytes = null) { if (loggerSinkConfiguration == null) { throw new ArgumentNullException("loggerSinkConfiguration"); } if (serverUrl == null) { throw new ArgumentNullException("serverUrl"); } if (bufferFileSizeLimitBytes.HasValue && bufferFileSizeLimitBytes < 0) { throw new ArgumentException("Negative value provided; file size limit must be non-negative"); } var defaultedPeriod = period ?? SeqSink.DefaultPeriod; ILogEventSink sink; if (bufferBaseFilename == null) { sink = new SeqSink(serverUrl, apiKey, batchPostingLimit, defaultedPeriod); } else { sink = new DurableSeqSink(serverUrl, bufferBaseFilename, apiKey, batchPostingLimit, defaultedPeriod, bufferFileSizeLimitBytes); } return(loggerSinkConfiguration.Sink(sink, restrictedToMinimumLevel)); }
/// <summary> /// Adds a Seq logger configured from the supplied configuration section. /// </summary> /// <param name="loggerFactory">The logger factory.</param> /// <param name="serverUrl"></param> /// <param name="apiKey">A Seq API key to authenticate or tag messages from the logger.</param> /// <param name="minimumLevel">The level below which events will be suppressed (the default is <see cref="LogLevel.Information"/>).</param> /// <param name="levelOverrides">A dictionary mapping logger name prefixes to minimum logging levels.</param> /// <returns>A logger factory to allow further configuration.</returns> public static ILoggerFactory AddSeq( this ILoggerFactory loggerFactory, string serverUrl, string apiKey = null, LogLevel minimumLevel = LogLevel.Information, IDictionary <string, LogLevel> levelOverrides = null) { var levelSwitch = new LoggingLevelSwitch(minimumLevel); var sink = new SeqSink( serverUrl, apiKey, 1000, TimeSpan.FromSeconds(2), 256 * 1024, levelSwitch, null); LevelOverrideMap overrideMap = null; if (levelOverrides != null && levelOverrides.Count != 0) { var overrides = new Dictionary <string, LoggingLevelSwitch>(); foreach (var levelOverride in levelOverrides) { overrides.Add(levelOverride.Key, new LoggingLevelSwitch(levelOverride.Value)); } overrideMap = new LevelOverrideMap(overrides, levelSwitch); } var logger = new Logger(levelSwitch, sink, new LogContextEnricher(), sink.Dispose, overrideMap); loggerFactory.AddProvider(new SerilogLoggerProvider(logger)); return(loggerFactory); }
/// <summary> /// Adds a sink that writes log events to a <a href="https://getseq.net">Seq</a> server. /// </summary> /// <param name="loggerSinkConfiguration">The logger configuration.</param> /// <param name="serverUrl">The base URL of the Seq server that log events will be written to.</param> /// <param name="restrictedToMinimumLevel">The minimum log event level required /// in order to write an event to the sink.</param> /// <param name="batchPostingLimit">The maximum number of events to post in a single batch.</param> /// <param name="period">The time to wait between checking for event batches.</param> /// <param name="bufferBaseFilename">Path for a set of files that will be used to buffer events until they /// can be successfully transmitted across the network. Individual files will be created using the /// pattern <paramref name="bufferBaseFilename"/>-{Date}.json.</param> /// <param name="apiKey">A Seq <i>API key</i> that authenticates the client to the Seq server.</param> /// <param name="bufferFileSizeLimitBytes">The maximum size, in bytes, to which the buffer /// log file for a specific date will be allowed to grow. By default no limit will be applied.</param> /// <param name="eventBodyLimitBytes">The maximum size, in bytes, that the JSON representation of /// an event may take before it is dropped rather than being sent to the Seq server. Specify null for no limit. /// The default is 265 KB.</param> /// <param name="controlLevelSwitch">If provided, the switch will be updated based on the Seq server's level setting /// for the corresponding API key. Passing the same key to MinimumLevel.ControlledBy() will make the whole pipeline /// dynamically controlled. Do not specify <paramref name="restrictedToMinimumLevel"/> with this setting.</param> /// <param name="messageHandler">Used to construct the HttpClient that will send the log messages to Seq.</param> /// <param name="retainedInvalidPayloadsLimitBytes">A soft limit for the number of bytes to use for storing failed requests. /// The limit is soft in that it can be exceeded by any single error payload, but in that case only that single error /// payload will be retained.</param> /// <param name="compact">Use the compact log event format defined by /// <a href="https://github.com/serilog/serilog-formatting-compact">Serilog.Formatting.Compact</a>. Has no effect on /// durable log shipping. Requires Seq 3.3+.</param> /// <param name="queueSizeLimit">The maximum number of events that will be held in-memory while waiting to ship them to /// Seq. Beyond this limit, events will be dropped. The default is 100,000. Has no effect on /// durable log shipping.</param> /// <returns>Logger configuration, allowing configuration to continue.</returns> /// <exception cref="ArgumentNullException">A required parameter is null.</exception> public static LoggerConfiguration Seq( this LoggerSinkConfiguration loggerSinkConfiguration, string serverUrl, LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum, int batchPostingLimit = SeqSink.DefaultBatchPostingLimit, TimeSpan?period = null, string apiKey = null, string bufferBaseFilename = null, long?bufferFileSizeLimitBytes = null, long?eventBodyLimitBytes = 256 *1024, LoggingLevelSwitch controlLevelSwitch = null, HttpMessageHandler messageHandler = null, long?retainedInvalidPayloadsLimitBytes = null, bool compact = false, int queueSizeLimit = SeqSink.DefaultQueueSizeLimit) { if (loggerSinkConfiguration == null) { throw new ArgumentNullException(nameof(loggerSinkConfiguration)); } if (serverUrl == null) { throw new ArgumentNullException(nameof(serverUrl)); } if (bufferFileSizeLimitBytes.HasValue && bufferFileSizeLimitBytes < 0) { throw new ArgumentOutOfRangeException(nameof(bufferFileSizeLimitBytes), "Negative value provided; file size limit must be non-negative."); } if (queueSizeLimit < 0) { throw new ArgumentOutOfRangeException(nameof(queueSizeLimit), "Queue size limit must be non-zero."); } var defaultedPeriod = period ?? SeqSink.DefaultPeriod; ILogEventSink sink; if (bufferBaseFilename == null) { sink = new SeqSink( serverUrl, apiKey, batchPostingLimit, defaultedPeriod, eventBodyLimitBytes, controlLevelSwitch, messageHandler, compact, queueSizeLimit); } else { #if DURABLE sink = new DurableSeqSink( serverUrl, bufferBaseFilename, apiKey, batchPostingLimit, defaultedPeriod, bufferFileSizeLimitBytes, eventBodyLimitBytes, controlLevelSwitch, messageHandler, retainedInvalidPayloadsLimitBytes); #else // We keep the API consistent for easier packaging and to support bait-and-switch. throw new NotSupportedException("Durable log shipping is not supported on this platform."); #endif } return(loggerSinkConfiguration.Sink(sink, restrictedToMinimumLevel)); }