当前位置: 首页 > 知识库问答 >
问题:

在运行时添加Sentry Log4j2 appender

孟英锐
2023-03-14

我已经浏览了之前关于在运行时添加Log4j2附加器的线程,但没有一个真正适合我的场景。

我们将一个长时间运行的Flink作业打包到一个胖jar中,我们基本上将其提交给一个运行的Flink集群。我们想把错误日志转发给哨兵。很方便,Sentry提供了一个我希望能够使用的Log4j2 appender,但所有让Log4j2工作的尝试都失败了——对此有点疯狂(花了几天时间)。

因为Flink(也使用log4j2)提供了一组默认的日志配置,优先于我们在jar中捆绑的任何配置文件;我基本上只剩下在运行时配置appender,看看这是否会使它注册appender并将日志事件转发给它。

附带说明:我试图覆盖Flink提供的配置文件(本质上是将appender直接添加到Log4j2.properties文件中),但Flink由于缺少依赖项io.sentry而无法加载插件。IHub-这没有意义,因为所有示例/sentry文档都没有提及除类路径中已经存在的log4j相关依赖项之外的任何其他依赖项。

我遵循了log4j文档中的示例:初始化后以编程方式修改当前配置,但日志无法传递给Sentry。

Sentylog4J.scala

package com.REDACTED.thoros.config

import io.sentry.log4j2.SentryAppender
import org.apache.logging.log4j.Level
import org.apache.logging.log4j.LogManager
import org.apache.logging.log4j.core.LoggerContext
import org.apache.logging.log4j.core.config.AppenderRef
import org.apache.logging.log4j.core.config.Configuration
import org.apache.logging.log4j.core.config.LoggerConfig

object SentryLog4j2 {
 val SENTRY_LOGGER_NAME = "Sentry"
 val SENTRY_BREADCRUMBS_LEVEL: Level = Level.ALL
 val SENTRY_MINIMUM_EVENT_LEVEL: Level = Level.ERROR
 val SENTRY_DSN =
   "REDACTED"

 def init(): Unit = {
   // scalafix:off
   val loggerContext: LoggerContext =
     LogManager.getContext(false).asInstanceOf[LoggerContext]
   val configuration: Configuration = loggerContext.getConfiguration

   val sentryAppender: SentryAppender = SentryAppender.createAppender(
     SENTRY_LOGGER_NAME,
     SENTRY_BREADCRUMBS_LEVEL,
     SENTRY_MINIMUM_EVENT_LEVEL,
     SENTRY_DSN,
     false,
     null
   )
   sentryAppender.start()
   configuration.addAppender(sentryAppender)
   // Creating a new dedicated logger for Sentry
   val ref: AppenderRef =
     AppenderRef.createAppenderRef("Sentry", null, null)
   val refs: Array[AppenderRef] = Array(ref)
   val loggerConfig: LoggerConfig = LoggerConfig.createLogger(
     false,
     Level.ERROR,
     "org.apache.logging.log4j",
     "true",
     refs,
     null,
     configuration,
     null
   )
   loggerConfig.addAppender(sentryAppender, null, null)
   configuration.addLogger("org.apache.logging.log4j", loggerConfig)
   println(configuration.getAppenders)
   loggerContext.updateLoggers()
   // scalafix:on
 }
}

然后调用Sentylog4J。init(),位于主模块中。

import org.apache.logging.log4j.LogManager
import org.apache.logging.log4j.Logger
import org.apache.logging.log4j.core.LoggerContext
import org.apache.logging.log4j.core.config.Configuration

object Main {
  val logger: Logger = LogManager.getLogger()
  sys.env.get("ENVIRONMENT") match {
    case Some("dev") | Some("staging") | Some("production") =>
      SentryLog4j2.init()
    case _ => SentryLog4j2.init() // <-- this was only added during debugging
  }

    def main(args: Array[String]): Unit = {
       logger.error("test") // this does not forward the logevent to the appender
    }
}

我想我需要以某种方式将appender注册到rootLogger使用的loggerConfig,以便所有的记录器都可以使用。错误语句是否传播到配置的Sentry appender?

非常感谢您的指导!

共有1个答案

水瀚漠
2023-03-14

虽然这不是如何让log4j2和SentryAppender工作的答案。对于其他在这个问题上遇到障碍的人,我只简单地解释一下我做了些什么来让哨兵集成工作。我最终决定不再使用SentryAppender,而是使用原始的sentry客户端。添加一个包装类,公开典型的调试方法、信息方法、警告方法和错误方法。然后对于warn方法,我还将logevent发送给Sentry。

这基本上是我让它在Flink集群中工作的唯一方法。

见下例:

sealed trait LoggerLike {
  type LoggerFn = (String, Option[Object]) => Unit
  val debug: LoggerFn
  val info: LoggerFn
  val warn: LoggerFn
  val error: LoggerFn
}


trait LazyLogging {
  @transient
  protected lazy val logger: CustomLogger =
    CustomLogger.getLogger(getClass.getName, enableSentry = true)
}


final class CustomLogger(slf4JLogger: Logger) extends LoggerLike {...your implementation...}

然后对于每个类/对象(至少是scala语言),您只需扩展LazyLogging特征即可获得记录器实例。

 类似资料:
  • 我知道ApplicationContext扩展点,如ApplicationContext事件和BeanFactoryPostProcessor。 我手头的问题是,在创建了一些bean之后,我需要添加bean,我想这会丢弃BeanFactoryPostProcessor选项,因为在应用程序上下文开始注册bean之前会发生这种情况。 我尝试在上下文刷新后添加一个singletonBean:

  • 在运行时添加到当单击时。 我使用以下代码: 但是在中没有显示任何。

  • 问题内容: 我的应用程序有一个模块,允许用户在运行时在jLayeredpane上添加jButton。我想向此动态添加的内容添加动作侦听器,而且我还必须提供在运行时删除动态添加的按钮的访问权限。有什么办法吗? 问题答案: 原始答案 总体上不错,但是在这种情况下做的却不同 为了跟踪添加的任意数量,您需要将它们保留在列表中。 因此,在创建新按钮之后,将侦听器添加到该按钮,然后将其添加到窗格中,然后需要将

  • 问题内容: 如何在Java运行时添加camel路线?我找到了Grails示例,但是已经用Java实现了。 我的applicationContext.xml已经有一些预定义的静态路由,我想在运行时为其添加一些动态路由。可能吗?因为包括动态路由的唯一方法是编写route.xml,然后将路由定义加载到上下文。它如何在现有静态路由上工作? 问题答案: 你可以在CamelContext上简单地调用一些不同的

  • 问题内容: 我有一个和上。 在运行时添加到单击时。 我使用以下代码: 但没有显示任何在。 问题答案: 我看到您创建了一个名为: 但您永远不会将其添加到面板中。相反,您将没有文本的新内容添加到面板中: 当然,这将构造一个不可见的空标签。 添加类似后,还尝试在您的实例上调用和,如下所示: 这样,您可能还需要调用您的框架实例,以便调整大小以适合新组件。 另外,请不要使用/ 布局,这是非常糟糕的做法(除非

  • 如何在Java的运行时添加骆驼路线?我找到了一个Grails示例,但我已经在Java实现了它。 我的应用程序上下文。xml已经有一些预定义的静态路由,我想在运行时向它添加一些动态路由。可能吗?因为包含动态路由的唯一方法是编写路由。然后将路由定义加载到上下文。它将如何在现有的静态路由上工作?运行时路由