/// <summary> /// Adds a non-durable sink that will send log events to Grafana Loki. /// A non-durable sink will lose data after a system or process restart. /// </summary> /// <param name="sinkConfiguration"> /// The logger configuration. /// </param> /// <param name="uri"> /// The root URI of Loki. /// </param> /// <param name="labels"> /// The globals log event labels, which will be user for enriching all requests. /// </param> /// <param name="filtrationMode"> /// The mode for labels filtration /// </param> /// <param name="filtrationLabels"> /// The list of label keys used for filtration /// </param> /// <param name="credentials"> /// Auth <see cref="LokiCredentials"/>. /// </param> /// <param name="outputTemplate"> /// A message template describing the format used to write to the sink. /// Default value is <code>"[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}"</code>. /// </param> /// <param name="restrictedToMinimumLevel"> /// The minimum level for events passed through the sink. /// Default value is <see cref="LevelAlias.Minimum"/>. /// </param> /// <param name="batchPostingLimit"> /// The maximum number of events to post in a single batch. Default value is 1000. /// </param> /// <param name="queueLimit"> /// The maximum number of events stored in the queue in memory, waiting to be posted over /// the network. Default value is infinitely. /// </param> /// <param name="period"> /// The time to wait between checking for event batches. Default value is 2 seconds. /// </param> /// <param name="textFormatter"> /// The formatter rendering individual log events into text, for example JSON. Default /// value is <see cref="MessageTemplateTextFormatter"/>. /// </param> /// <param name="httpClient"> /// A custom <see cref="IHttpClient"/> implementation. Default value is /// <see cref="DefaultLokiHttpClient"/>. /// </param> /// <returns>Logger configuration, allowing configuration to continue.</returns> public static LoggerConfiguration GrafanaLoki( this LoggerSinkConfiguration sinkConfiguration, string uri, IEnumerable <LokiLabel> labels = null, LokiLabelFiltrationMode?filtrationMode = null, IEnumerable <string> filtrationLabels = null, LokiCredentials credentials = null, string outputTemplate = DefaultOutputTemplate, LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum, int batchPostingLimit = 1000, int?queueLimit = null, TimeSpan?period = null, ITextFormatter textFormatter = null, IHttpClient httpClient = null) { if (sinkConfiguration == null) { throw new ArgumentNullException(nameof(sinkConfiguration)); } var(batchFormatter, formatter, client) = SetupClientAndFormatters(labels, filtrationMode, filtrationLabels, textFormatter, outputTemplate, httpClient, credentials); return(sinkConfiguration.Http( LokiRoutesBuilder.BuildLogsEntriesRoute(uri), batchPostingLimit, queueLimit, period, formatter, batchFormatter, restrictedToMinimumLevel, client)); }
public void RequestUriShouldBeCorrect(string uri) { var logger = new LoggerConfiguration() .WriteTo.GrafanaLoki("http://loki:3100", httpClient: _client) .CreateLogger(); logger.Error("An error occured"); logger.Dispose(); _client.RequestUri.ShouldBe(LokiRoutesBuilder.BuildLogsEntriesRoute(uri)); }
/// <summary> /// Adds a non-durable sink that will send log events to Grafana Loki. /// A non-durable sink will lose data after a system or process restart. /// </summary> /// <param name="sinkConfiguration"> /// The logger configuration. /// </param> /// <param name="uri"> /// The root URI of Loki. /// </param> /// <param name="labels"> /// The global log event labels, which will be user for enriching all requests. /// </param> /// <param name="propertiesAsLabels"> /// The list of properties, which would be mapped to the labels. /// </param> /// <param name="credentials"> /// Auth <see cref="LokiCredentials"/>. /// </param> /// <param name="restrictedToMinimumLevel"> /// The minimum level for events passed through the sink. /// Default value is <see cref="LevelAlias.Minimum"/>. /// </param> /// <param name="batchPostingLimit"> /// The maximum number of events to post in a single batch. Default value is 1000. /// </param> /// <param name="queueLimit"> /// The maximum number of events stored in the queue in memory, waiting to be posted over /// the network. Default value is infinitely. /// </param> /// <param name="period"> /// The time to wait between checking for event batches. Default value is 2 seconds. /// </param> /// <param name="textFormatter"> /// The formatter rendering individual log events into text, for example JSON. Default /// value is <see cref="MessageTemplateTextFormatter"/>. /// </param> /// <param name="httpClient"> /// A custom <see cref="ILokiHttpClient"/> implementation. Default value is /// <see cref="LokiHttpClient"/>. /// </param> /// <param name="reservedPropertyRenamingStrategy"> /// Renaming strategy for properties' names equal to reserved keywords. /// </param> /// <param name="useInternalTimestamp"> /// Should use internal sink timestamp instead of application one to use as log timestamp. /// </param> /// <returns>Logger configuration, allowing configuration to continue.</returns> public static LoggerConfiguration GrafanaLoki( this LoggerSinkConfiguration sinkConfiguration, string uri, IEnumerable <LokiLabel>?labels = null, IEnumerable <string>?propertiesAsLabels = null, LokiCredentials?credentials = null, LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum, int batchPostingLimit = 1000, int?queueLimit = null, TimeSpan?period = null, ITextFormatter?textFormatter = null, ILokiHttpClient?httpClient = null, IReservedPropertyRenamingStrategy?reservedPropertyRenamingStrategy = null, bool useInternalTimestamp = false) { if (sinkConfiguration == null) { throw new ArgumentNullException(nameof(sinkConfiguration)); } reservedPropertyRenamingStrategy ??= new DefaultReservedPropertyRenamingStrategy(); period ??= TimeSpan.FromSeconds(1); textFormatter ??= new LokiJsonTextFormatter(reservedPropertyRenamingStrategy); httpClient ??= new LokiHttpClient(); httpClient.SetCredentials(credentials); var batchFormatter = new LokiBatchFormatter( reservedPropertyRenamingStrategy, labels, propertiesAsLabels, useInternalTimestamp); var sink = new LokiSink( LokiRoutesBuilder.BuildLogsEntriesRoute(uri), batchPostingLimit, queueLimit, period.Value, textFormatter, batchFormatter, httpClient); return(sinkConfiguration.Sink(sink, restrictedToMinimumLevel)); }
/// <summary> /// Adds a durable sink that will send log events to Grafana Loki. A durable sink /// will persist log events on disk in buffer files before sending them over the /// network, thus protecting against data loss after a system or process restart. The /// buffer files will use a rolling behavior defined by the file size specified in /// <paramref name="bufferFileSizeLimitBytes"/>, i.e. a new buffer file is created when /// current has passed its limit. The maximum number of retained files is defined by /// <paramref name="retainedBufferFileCountLimit"/>, and when that limit is reached the /// oldest file is dropped to make room for a new. /// </summary> /// <param name="sinkConfiguration"> /// The logger configuration. /// </param> /// <param name="uri"> /// The root URI of Loki. /// </param> /// <param name="bufferBaseFileName"> /// The relative or absolute 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"/>*.json", which should /// not clash with any other file names in the same directory. Default value is "Buffer". /// </param> /// <param name="bufferFileSizeLimitBytes"> /// The approximate maximum size, in bytes, to which a buffer file for a specific time interval will be /// allowed to grow. By default no limit will be applied. /// </param> /// <param name="bufferFileShared"> /// Allow the buffer file to be shared by multiple processes. Default value is false. /// </param> /// <param name="retainedBufferFileCountLimit"> /// The maximum number of buffer files that will be retained, including the current buffer /// file. Under normal operation only 2 files will be kept, however if the log server is /// unreachable, the number of files specified by <paramref name="retainedBufferFileCountLimit"/> /// will be kept on the file system. For unlimited retention, pass null. Default value is 31. /// </param> /// <param name="labels"> /// The globals log event labels, which will be user for enriching all requests. /// </param> /// <param name="excludedLabels"> /// Keys, which would be excluded from a the label list in a payload. /// </param> /// <param name="credentials"> /// Auth <see cref="LokiCredentials"/>. /// </param> /// <param name="outputTemplate"> /// A message template describing the format used to write to the sink. /// Default value is <code>"[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}"</code>. /// </param> /// <param name="restrictedToMinimumLevel"> /// The minimum level for events passed through the sink. /// Default value is <see cref="LevelAlias.Minimum"/>. /// </param> /// <param name="batchPostingLimit"> /// The maximum number of events to post in a single batch. Default value is 1000. /// </param> /// <param name="queueLimit"> /// The maximum number of events stored in the queue in memory, waiting to be posted over /// the network. Default value is infinitely. /// </param> /// <param name="period"> /// The time to wait between checking for event batches. Default value is 2 seconds. /// </param> /// <param name="textFormatter"> /// The formatter rendering individual log events into text, for example JSON. Default /// value is <see cref="MessageTemplateTextFormatter"/>. /// </param> /// <param name="httpClient"> /// A custom <see cref="IHttpClient"/> implementation. Default value is /// <see cref="DefaultLokiHttpClient"/>. /// </param> /// <returns>Logger configuration, allowing configuration to continue.</returns> public static LoggerConfiguration DurableGrafanaLokiUsingFileSizeRolledBuffers( this LoggerSinkConfiguration sinkConfiguration, string uri, string bufferBaseFileName = "Buffer", long?bufferFileSizeLimitBytes = 1024 * 1024 * 1024, bool bufferFileShared = false, int?retainedBufferFileCountLimit = 31, IEnumerable <LokiLabel> labels = null, IEnumerable <string> excludedLabels = null, LokiCredentials credentials = null, string outputTemplate = DefaultOutputTemplate, LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum, int batchPostingLimit = 1000, int?queueLimit = null, TimeSpan?period = null, ITextFormatter textFormatter = null, IHttpClient httpClient = null) { if (sinkConfiguration == null) { throw new ArgumentNullException(nameof(sinkConfiguration)); } var(batchFormatter, formatter, client) = SetupClientAndFormatters(labels, excludedLabels, textFormatter, outputTemplate, httpClient, credentials); return(sinkConfiguration.DurableHttpUsingFileSizeRolledBuffers( LokiRoutesBuilder.BuildLogsEntriesRoute(uri), bufferBaseFileName, bufferFileSizeLimitBytes, bufferFileShared, retainedBufferFileCountLimit, batchPostingLimit, period, formatter, batchFormatter, restrictedToMinimumLevel, client)); }
public void CorrectRoutesShouldBeBuilt(string host, string expected) { var route = LokiRoutesBuilder.BuildLogsEntriesRoute(host); route.ShouldBe(expected); }