【问题标题】:How to output GCP structured logs in scala?如何在scala中输出GCP结构化日志?
【发布时间】:2020-08-19 09:59:55
【问题描述】:

我有一个在 GKE 中运行的容器,它托管一个 scala 应用程序。在我们的堆栈中,我们正在尝试改进调试,并且我正在尝试让我们的部署输出结构化日志。我已经为我们堆栈的 python 部分实现了这一点,但是我在使用 scala 时遇到了问题。

在 scala 中,我们目前使用 slf4j 和 logback 来记录消息。我已经完成了一些配置工作,让 logback 将输出格式化为单行 json,但现在我正在努力让它真正用于自定义字段。

在 python 中我可以这样做:

custom_fields = { "userID": "andy" }
logger.info("User logged in", custom_fields)

我找到了一些如何在 scala 中执行此操作的示例,但我认为它们不适合:

这是一个使用 MDC 的示例,我担心的是我认为这不是线程安全的吗?我有多个异步运行的线程一次处理多个用户。我可以将所有日志调用包装在互斥锁中,并在互斥锁中添加/记录/删除字段,但这感觉非常繁重,并且可能会破坏系统的性能:https://gquintana.github.io/2017/12/01/Structured-logging-with-SL-FJ-and-Logback.html

我还看到了将 StructuredArgument 传递给日志调用的示例:https://github.com/logstash/logstash-logback-encoder#event-specific-custom-fields

但正如我之前的问题中所详述的那样:How to import StructuredArgument for structured logging in scala using slf4j and logback

我似乎无法在 Scala 中使用它。

实现这一点的最佳方法是什么?

【问题讨论】:

  • 如果您正在寻找读取 Stackdriver 日志 (GCP) 的方法,您可以使用客户端 libraries 调用 logging API 或 Logging REST API 端点。

标签: scala logging logback slf4j google-cloud-logging


【解决方案1】:

是的,slf4j、logback 和其他经典 JVM 日志系统中的 MDC 和 NDC 使用 threadlocals,因此它们只能在单个线程中使用而无需费力。它只是不是为异步日志设计的。

但它并没有你想的那么重,因为 logback-slf4j MDC 使用了LogbackMDCAdapter,它是线程安全的,但适用于线程本地语义。

这意味着您可以传递一个包含所需日志记录上下文的自定义案例类,然后在每个日志上,将其添加到 MDC,记录初始消息,然后清除 MDC。

这个的辅助函数是这样的:

def asyncLog(msg: String, context: CustomLoggingContext){ 
  MDC.put(context)
  logger.log(msg)
  MDC.clear()
}

其他选项是:

  • 仍然使用 slf4j 并将上下文信息作为普通消息的一部分写入,然后在其他地方解析它(例如在 logstash 中)。
  • 使用其他具有此类功能的日志框架/系统
  • 自己写

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-06
    • 1970-01-01
    • 2020-11-10
    • 1970-01-01
    相关资源
    最近更新 更多