82 lines
4.2 KiB
C#
82 lines
4.2 KiB
C#
using Serilog;
|
||
using Serilog.Events;
|
||
using Serilog.Filters;
|
||
using Serilog.Sinks.Grafana.Loki;
|
||
using System.Collections.Immutable;
|
||
using System.Text.RegularExpressions;
|
||
|
||
namespace KLHZ.Trader.Service.Infrastructure
|
||
{
|
||
internal static class IHostBuilderExtensions
|
||
{
|
||
private readonly static Regex urlCheckRegex = new("^http://|https://.+");
|
||
private readonly static ImmutableArray<string> DefaultLabels = new List<string>()
|
||
{
|
||
"action",
|
||
}.ToImmutableArray();
|
||
|
||
/// <summary>
|
||
/// Добавить логирование в Loki
|
||
/// </summary>
|
||
/// <param name="hostBuilder"></param>
|
||
/// <param name="lokiUrl">url loki, куда писать логи.</param>
|
||
/// <param name="serviceName">Название сервиса, от имени которого пишутся логи. Если передан null - берется название домена. </param>
|
||
/// <param name="writeToConsole">Флаг, включающий дублирование логов в консоль.</param>
|
||
/// <param name="minLevel">Минимальный уровень логирования приложения.</param>
|
||
/// <param name="EFMinLogLevel">Минимальный уровень логирования для EF.</param>
|
||
/// <param name="excludeEFLogs">Удалять из логов записи, сгенерированные EF.</param>
|
||
/// <param name="excludeMetricsScrapingLogs">Удалять из логов записи, возникшие в результате скреппинга метрик прометеусом..</param>
|
||
/// <param name="additionalFiltratonLabels">Набор тегов, который будет извлекаться при отправке в Loki
|
||
/// и помечаться как Label для ускорения поиска по логам.</param>
|
||
/// <returns></returns>
|
||
/// <exception cref="ArgumentException"></exception>
|
||
public static IHostBuilder ConfigureSerilog(this IHostBuilder hostBuilder, string? lokiUrl,
|
||
string? serviceName = null,
|
||
bool writeToConsole = false,
|
||
List<string>? additionalFiltratonLabels = null,
|
||
LogEventLevel minLevel = LogEventLevel.Information,
|
||
LogEventLevel EFMinLogLevel = LogEventLevel.Information,
|
||
bool excludeEFLogs = true,
|
||
bool excludeMetricsScrapingLogs = true
|
||
)
|
||
{
|
||
if (string.IsNullOrEmpty(lokiUrl) || !urlCheckRegex.IsMatch(lokiUrl)) throw new ArgumentException("Bad lokiUrl!");
|
||
var labels = new List<string>();
|
||
|
||
if (additionalFiltratonLabels != null && additionalFiltratonLabels.Count > 0)
|
||
{
|
||
labels.AddRange(additionalFiltratonLabels);
|
||
}
|
||
labels.AddRange(DefaultLabels);
|
||
hostBuilder.UseSerilog((ctx, lc) =>
|
||
{
|
||
if (excludeEFLogs)
|
||
lc.Filter.ByExcluding(Matching.WithProperty("SourceContext", "Microsoft.EntityFrameworkCore.Database.Command"));
|
||
if (excludeMetricsScrapingLogs)
|
||
lc.Filter.ByExcluding(Matching.WithProperty("RequestPath", "/metrics"));
|
||
lc.MinimumLevel.Is(minLevel);
|
||
lc.MinimumLevel.Override("Microsoft.EntityFrameworkCore.Database.Command", EFMinLogLevel);
|
||
lc.WriteTo.GrafanaLoki(lokiUrl,
|
||
queueLimit: 1000000,
|
||
labels: new List<LokiLabel>
|
||
{
|
||
new ()
|
||
{
|
||
Key = "service",
|
||
Value = serviceName ?? AppDomain.CurrentDomain.FriendlyName
|
||
}
|
||
},
|
||
restrictedToMinimumLevel: minLevel,
|
||
propertiesAsLabels: labels,
|
||
textFormatter: new LokiJsonTextFormatter()
|
||
|
||
);
|
||
|
||
if (writeToConsole)
|
||
lc.WriteTo.Console();
|
||
});
|
||
|
||
return hostBuilder;
|
||
}
|
||
}
|
||
} |