首页 > 解决方案 > 通过 Fluentd 将日志消息写入 Grafana Loki

问题描述

我们有使用 Serilog 记录应用程序跟踪消息的 .NET WebAPI 服务 (C#)。我们仅使用一个 Serilog 接收器 TCPSink 将消息发送到 Fluentd sidecar 容器,因此我们可以轻松更改日志记录目标,而无需更改 WebAPI 应用程序代码。这对于 Elasticsearch 和 Humio 等目标非常有效。我们现在想用一个新的 Fluentd sidecar 容器来支持 Grafana Loki。

使用默认格式(JsonFormatter)的 TCPSink,我们可以轻松支持 Elasticsearch/Humio 的格式(logstash?)。但是 Loki 的格式却大不相同。有没有办法按照 Grafana Loki 的要求将 Fluentd 中的消息从本质上的原始 JSON 格式化为流格式?还是我们应该编写一个“LokiFormatter”并将其与 TCPSink 一起使用,类似于 GrafanaLoki 接收器?

这是 C# 中的一些测试代码。我们希望使用 TCPSink 接收器。请注意,注释掉的“GrafanaLoki”接收器确实有效。

 private static void Main()
        {
            var configuration = new ConfigurationBuilder()
                .SetBasePath(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location))
                .AddYamlFile(CONFIGURATION_FILE_NAME, optional: false)
                .Build();            
           
            try
            {
                loggingLevel.MinimumLevel = LogEventLevel.Information;

                var lc = new LoggerConfiguration();

                lc.MinimumLevel.ControlledBy(loggingLevel);
                lc.MinimumLevel.Override("Microsoft", LogEventLevel.Warning);
                lc.MinimumLevel.Override("System", LogEventLevel.Error);

                Serilog.Debugging.SelfLog.Enable(msg => System.Console.WriteLine(msg));

                lc.WriteTo.Console();
                lc.WriteTo.TCPSink("tcp://localhost:9880");

                //var credentials = new LokiCredentials() { Login = "**username**", Password = "**password** };
                //lc.WriteTo.GrafanaLoki("https://logs-prod-us-central1.grafana.net", credentials: credentials);

                lc.Enrich.FromLogContext();
                lc.Enrich.WithProperty("applicationName", APPLICATION_NAME);
                lc.Enrich.WithProperty("environment", "dev");

                Log.Logger = lc.CreateLogger();

                int bob = 111;
                Log.Information("This is a test {bob}", bob);

                var msg = "Danger! Danger! Will Robinson!";
                Log.Warning("This is a warning : {msg}", msg);
            }
            catch (Exception ex)
            {
                Log.Error(ex, $"Error in {APPLICATION_NAME}");
            }
            finally
            {
                while (true)
                {
                    Thread.Sleep(1000);
                }
            }
        }

这是提议的 Loki sidecar 容器的 Dockerfile。

FROM fluent/fluentd:v1.14.0-1.0
# FROM __DockerBaseImage__
USER root
RUN fluent-gem install fluent-plugin-grafana-loki
COPY fluentd.conf /fluentd/etc/fluent.conf
USER fluent

带配置

<source>
  @type tcp
  <parse>
    @type json
  </parse>
  port 9880
  bind 0.0.0.0
  tag xxxx
</source>
<match xxxx>
  @type loki
  url                 https://logs-prod-us-central1.grafana.net
  username            **username**
  password            **password**
  extra_labels        {"env":"dev","farm":"a"} 
  flush_interval      5s
  flush_at_shutdown   true
  buffer_chunk_limit  1m
</match>

有没有办法在 Fluentd 中添加解析器/过滤器来格式化 Loki 的传入 TCP JSON?还是一个正确的 fluentd 插件而不是“fluent-plugin-grafana-loki”?

标签: c#grafanaserilogfluentdloki

解决方案


推荐阅读