通过 Logback 记录到 App Engine request_log

Posted

技术标签:

【中文标题】通过 Logback 记录到 App Engine request_log【英文标题】:Logging to App Engine request_log through Logback 【发布时间】:2020-03-07 20:47:28 【问题描述】:

我有一个使用 App Engine 标准环境 - Java 11 在 Ninja Framework 上构建的应用,使用 Ninja 附带的注入 Logger,即 Apache Logback .通常,这会记录到实例的stdout,因此我的所有消息都以每条目一行的格式出现,并且在stdout 日志通道上,这在尝试跟踪生产中的错误时不太方便.

有一个关于使用 Logback [1] 登录到 Stackdriver 的 Google 文档指南,我已经尝试过,但没有效果:日志现在以 application.log 结尾,即仍然是一个单独的频道,request_log 频道是空的。 我尝试通过将projects/dive-site-overwatch/logs/appengine.googleapis.com%2Frequest_log 作为<log> 元素放在logback.xml 中来更改推荐的配置,这导致所有请求都失败,因为URL 编码的solidus 上的“无效格式”。相反,按原样添加solidus 会导致异常,因为它是非法字符。

我当前部署的 Logback 配置如下(你可以看出我的想法已经用完了......):

<configuration>
    <statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />

    <appender name = "STDOUT" class = "ch.qos.logback.core.ConsoleAppender">
        <!-- encoders are assigned the type
             ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
        <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
            <layout class="tech.provingground.dive_overwatch.etc.logging.layouts.StackdriverLayout">
                <pattern>%-4relative [%thread] %-5level %logger35 - %msg</pattern>
            </layout>
        </encoder>
    </appender>

    <appender name = "CLOUD" class = "com.google.cloud.logging.logback.LoggingAppender">
        <log>application.log</log> <!-- Optional : default java.log -->
        <flushLevel>WARN</flushLevel> <!-- Optional : default ERROR -->
        <enhancer>tech.provingground.dive_overwatch.etc.logging.enhancers.TestEnhancer</enhancer>
        <encoder>
            <layout class="tech.provingground.dive_overwatch.etc.logging.layouts.StackdriverLayout">
                <pattern>%-4relative [%thread] %-5level %logger35 - %msg</pattern>
            </layout>
        </encoder>
    </appender>

    <root level = "info">
        <appender-ref ref = "CLOUD" />
<!--        <appender-ref ref = "STDOUT" />-->
    </root>
</configuration>

查看应用程序的标准,我可以看到许多指向 Stackdriver 拒绝请求的日志:

java.lang.RuntimeException: java.util.concurrent.TimeoutException: Waited 6 seconds for com.google.common.util.concurrent.CollectionFuture$ListFuture@77fbc3ba[status=PENDING, info=[futures=[[com.google.api.core.ApiFutureToListenableFuture@772ddfb8, com.google.api.core.ApiFutureToListenableFuture@7d905614, com.google.api.core.ApiFutureToListenableFuture@7396512d, com.google.api.core.ApiFutureToListenableFuture@5ad9baf6]]]]
    at com.google.cloud.logging.LoggingImpl.flush(LoggingImpl.java:581)
    at com.google.cloud.logging.LoggingImpl.write(LoggingImpl.java:562)
    at com.google.cloud.logging.logback.LoggingAppender.append(LoggingAppender.java:215)
    at com.google.cloud.logging.logback.LoggingAppender.append(LoggingAppender.java:70)
    at ch.qos.logback.core.UnsynchronizedAppenderBase.doAppend(UnsynchronizedAppenderBase.java:84)
[...]

如果是身份验证错误,我可以理解 403 或类似状态代码,但标准环境应该提供服务帐户,并自动授予 Logs Writer 角色。 p>

我有点难过。有没有办法让我的应用程序日志与我的其他请求日志在同一个位置,在常规的request_log 中?


[1]https://cloud.google.com/logging/docs/setup/java#logback_appender_for

【问题讨论】:

【参考方案1】:

您应该查看这个example,它使用 logback 进行 JSON 日志记录!关键元素是它包含跟踪 ID,以便消息与请求日志相关。

来自样本:

// Build structured log messages as an object.
Object globalLogFields = null;
// Add log correlation to nest all log messages beneath request log in Log Viewer.
String traceHeader = req.headers("x-cloud-trace-context");
if (traceHeader != null && project != null) 
  String trace = traceHeader.split("/")[0];
  globalLogFields =
      kv(
          "logging.googleapis.com/trace",
          String.format("projects/%s/traces/%s", project, trace));

// Create a structured log entry using key value pairs.
logger.error(
    "This is the default display field.",
    kv("component", "arbitrary-property"),
    kv("severity", "NOTICE"),
    globalLogFields);

【讨论】:

一步​​更接近我想要实现的目标,但它仍然没有将日志行与请求放在同一个条目中。即使我添加了StructuredArgument logNameField = kv("logging.googleapis.com/logName", String.format("projects/%s/logs/%s", project, "appengine.googleapis.com%2Frequest_log")); 之类的字段,它们仍然被放置在标准输出中。

以上是关于通过 Logback 记录到 App Engine request_log的主要内容,如果未能解决你的问题,请参考以下文章

Logback 将不同的消息记录到两个文件中

logback模板

Java Syslog 仅使用 logback 记录到本地机器

如何将数据从 Android 移动设备发送到 Google App Engine 数据存储区?

SkyWalking结合Logback获取全局唯一标识 trace-id 记录到日志中

NodeJS 中的 Google App Engine 日志记录