如何使用SLF4J和Log4j2

时间:2015-05-06 20:02:40

标签: java slf4j log4j2

我有那些具体的要求

  • 需要能够登录 致命 级别
  • 需要使用 SLF4J
  • 需要使用 Log4j2

目前,我的实施

final Logger logger = LoggerFactory.getLogger(HelloWorld.class);
final Marker marker = MarkerFactory.getMarker("FATAL");
logger.error(marker, "!!! Fatal World !!!");

这是我的 PatternLayout (在yaml中)

PatternLayout:
  Pattern: "%d{ISO8601_BASIC} %-5level %marker [%t] %logger{3.} - %msg%n"

这是日志输出

20150506T155705,158 ERROR FATAL [main] - !!! Fatal World !!!

您是否知道如何有效地删除" ERROR"从日志输出?

非常感谢

6 个答案:

答案 0 :(得分:7)

Marker并不是你想要的。 Marker用于“丰富”日志消息,使其更易于搜索。您正在尝试更改日志级别/优先级,这有点不同。

您正在使用logger.error(),该邮件会将邮件记录为ERROR级别。

如果没有预先定义FATAL级别(通常有logger.fatal()),那么请使用允许您指定日志级别的通用logger.log()。 p>

logger.fatal(yourMessage);

OR

logger.log(priorityLevel, yourMessage);

更新

来自SLF4J网站:

  

标记接口是org.slf4j包的一部分,它使FATAL级别在很大程度上是多余的。如果给定的错误需要注意超出为普通错误分配的错误,只需使用特殊指定的标记标记日志记录语句,该标记可以命名为“致命”或任何其他您喜欢的名称。

http://www.slf4j.org/faq.html#fatal

因此,使用SLF4J,不可能具有FATAL日志级别。我强烈反对这一决定背后的理由,但事实就是如此。

答案 1 :(得分:5)

这是我与一些同事一起提出的最接近的解决方案:

  1. 使用 SLF4J 标记创建致命标记类。
  2. 使用RoutingAppender,使用标记作为路由模式:" $$ {marker:}"
  3. 配置一个特定于致命的 appender,它有自己的PatternLayout,它不包含LogLevel但是包含硬编码的FATAL级别。
  4. 这是 Java 示例:

    Marker fatal = MarkerFactory.getMarker("FATAL");
    // Usage example
    final Logger logger = LoggerFactory.getLogger(FatalLogger.class);
    logger.log(fatal, "this is a fatal message");
    
    // Log sample : 
    20150514T115144,279  FATAL [main] FatalLogger - this is a fatal message
    

    这里是 YAML 示例:

    Configuration:
      status: debug
    
      Appenders:
        RandomAccessFile:
          - name: APPLICATION_APPENDER
            fileName: logs/application.log
            PatternLayout:
              Pattern: "%d{ISO8601_BASIC} %-5level %msg%n"
          - name: FATAL_APPENDER
            fileName: logs/application.log
            PatternLayout:
              Pattern: "%d{ISO8601_BASIC} FATAL %msg%n"
    
        Routing:
          name: ROUTING_APPENDER
          Routes:
            pattern: "$${marker:}"
            Route:
            - key: FATAL
              ref: FATAL_APPENDER
            - ref: APPLICATION_APPENDER #DefaultRoute
    
      Loggers:
        Root:
          level: trace
          AppenderRef:
            - ref: ROUTING_APPENDER
    

答案 2 :(得分:2)

我知道问题是针对log4j的。在查看与logback相关时,我找到了这个页面。这是sl4j建议的内容:https://www.slf4j.org/faq.html#fatal

答案 3 :(得分:1)

以下是我为 log4j 所做的事情,我也推荐 log4j2 ....

编写您自己的自定义slf4j静态绑定程序又称桥。这需要一些工作,但由于各种复杂的原因 1 ,我将在博客上写一篇文章非常值得一天。

这是你做的。

  1. 您可以在此处复制此代码:https://github.com/apache/logging-log4j2/tree/master/log4j-slf4j-impl
  2. 然后,您想要编辑Log4jLogger类并更改标记方法(跟踪,错误,警告,信息等)以适当地分派。即if (marker.contains("FATAL")) fatal(....);
  3. 从项目中排除原始log4j-slf4j-impl并使用新代码。
  4. <强>&LT;皂箱咆哮&GT;

    老实说,我认为slf4j存在严重缺陷,因为

    • 它使得很难/不可能覆盖硬核静态初始化以及不提供logger.fatal(...)
    • 不需要标记,并且本质上很复杂:
      • 很少有项目使用标记。我实际上看起来/ grepped开源项目和标记使用率接近于零。
      • 使用标记的是因为缺少fatal。它不是80/20。标记为1%,fatal为99%。
      • 许多开发人员认为以某种方式使用“致命”标记会将其映射为致命的。
      • Few know what a detached marker is including myself
      • 与MDC上下文提供的内容重叠。给定面向事件维度的数据库(elasticsearch,druid等),MDC上下文优越(名称/值对)。

    <强>&LT; / SOAP-盒咆哮&GT;

    1 其中一个实际上可以成为日志框架启动过程的一部分,而不是很难确定几乎任意的静态初始化

答案 4 :(得分:0)

我到目前为止找到的唯一解决方案是使用5个标记:

final Marker traceMarker = MarkerFactory.getMarker("TRACE");
final Marker debugMarker = MarkerFactory.getMarker("DEBUG");
final Marker infoMarker = MarkerFactory.getMarker("INFO");
final Marker warnMarker = MarkerFactory.getMarker("WARN");
final Marker errorMarker = MarkerFactory.getMarker("ERROR");
final Marker fatalMarker = MarkerFactory.getMarker("FATAL");

每次记录传递标记:

logger.info(infoMarker, "!!! INFO World !!!");
logger.error(errorMarker, "!!! ERROR World !!!");
logger.error(fatalMarker, "!!! FATAL World !!!");

修改 PatternLayout 以完全删除 LogLevel 并始终记录标记,例如:

PatternLayout:
  Pattern: "%d{ISO8601_BASIC} %marker [%t] %logger{3.} - %msg%n"

我认为这个解决方案是一个黑客......它还会以正确的方式使用LogLevel删除任何外部库的日志级别。

摘要:此解决方案不是一个好的解决方案。

更新:我尝试了另一种解决方案,写了一个RewritePolicy:

public class FatalRewritePolicy implements RewritePolicy {

    public static final String FATAL = "FATAL";

    @Override
    public LogEvent rewrite(final LogEvent logEvent) {

        final Marker marker = logEvent.getMarker();
        if (marker == null)
            return logEvent;

        // Log Level is final in the LogEvent, there's no way we can modify it.
        Level level = logEvent.getLevel();

        return null;
    }
}

似乎没有办法在 Log4j2 有意义)中更改LogEvent的LogLevel。

摘要:仍然没有解决方案。

答案 5 :(得分:0)

你可以添加&#34;致命&#34;在你的消息的开头。例如:

LOGGER.error("FATAL: database connection lost.");

你确实失去了一些东西,比如基于级别的过滤,但这对许多人来说可能没问题,特别是因为你不太可能过滤掉FATAL语句(调试和跟踪,当然)。