在运行时添加Sentry Log4j2附加器 [英] Add Sentry Log4j2 appender at runtime
问题描述
我一直在浏览以前关于在运行时添加Log4j2附加器的帖子,但似乎没有一个真正符合我的方案。
我们将一个长时间运行的Flink作业打包到一个FAT JAR中,我们实质上将其提交给正在运行的Flink集群。我们希望将错误日志转发到哨兵。Sentry提供了我希望能够使用的Log4j2 appender,但所有让Log4j2工作的尝试都失败了--对此有点疯狂(花了几天时间)。
由于Flink(也使用log4j2)提供了一组默认日志记录配置,该配置优先于我们在JAR中捆绑的任何配置文件;因此,我基本上只能尝试在运行时配置附加器,以查看这是否会使它注册附加器并将LogEvent转发给它。
作为附注:我试图重写Flink提供的配置文件(实质上是将附加器直接添加到Log4j2.properties
文件中),但Flink无法加载插件,因为缺少依赖项-io.sentry.IHub
-这没有意义,因为所有示例/哨兵文档都没有提到类路径中已存在的log4j相关依赖项之外的任何其他依赖项。
我遵循了log4j文档中的示例:Programmatically Modifying the Current Configuration after Initialization但日志无法传递给哨兵。
SentryLog4j.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
}
}
然后调用Main
模块中的SentryLog4j.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
}
}
我想我需要以某种方式将附加器注册到rootLogger使用的loggerConfiger,以便所有logger.error
语句都被传播到配置的Sentry附加器?
非常感谢各位对此的指导!
log4j2
,但不是如何让推荐答案和Sentry Appender工作的答案。对于在这个问题上遇到困难的其他人,我将简要解释我是如何使哨兵集成工作起来的。
我最终决定放弃使用SentryAppender,转而使用原始的哨兵客户端。添加一个包装类,公开典型的debug
、info
、warn
和error
方法。然后,对于warn
+方法,我还会将日志事件发送给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特征以获得一个记录器实例。
这篇关于在运行时添加Sentry Log4j2附加器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!