【问题标题】:Java Logging API for Detailed (and multiline) Logs用于详细(和多行)日志的 Java Logging API
【发布时间】:2017-11-10 20:02:55
【问题描述】:

我想找到一个 API,它允许我在我的应用程序的所有关键日志点中提供特定的规范集信息。更具体地说,它将是一条多行消息,其中包含以下信息(除了基本信息):

  1. 日志分类
  2. 简短说明标题
  3. 说明
  4. 我的应用程序将采取的响应操作(损害控制)
  5. 详细信息(异常信息等)

使用单个多行日志查看,例如,如下所示:

2017-11-10 14:26:59,156 [main] WARN o.s.t.c.s.ExampleClass:
    Caption: Unconformable data
    Description: The data provided from the X datasource in order to perform Y operation could not be translated
    Response Action: Application will discard unusable data into this component's DLQ
    Details: The data string "x" was not of expected Integer type
        <Some stacktrace>....

这是一个冗长的语句,它将非常详细地说明发生了什么、发生在哪里以及应用程序为响应异常事件正在做什么。

我能找到的最接近的是 JBoss 日志记录 API 和我在 ActiveMQ Artemis source 中找到的一些代码示例。 消息格式声明可以像这样在单个文件中定义:

   @LogMessage(level = Logger.Level.WARN)
   @Message(id = 202008, value = "Failed to check Address list {0}.",
      format = Message.Format.MESSAGE_FORMAT)
   void failedToParseAddressList(@Cause Exception e, String addressList);

人们会在他们的代码中记录line with this message

ActiveMQUtilLogger.LOGGER.failedToParseAddressList(e, addressList);

这是我能找到的最接近我正在寻找的东西。很酷。但是,我没有使用 JBoss(也不想锁定该 API)。

我可以使用 LOG4J,它有一个StructuredDataMessage and Structured Data Lookup,可以在布局中使用,默认情况下我会使用它;我的代码可以委托给一些StructuredDataMessage 工厂来解决这个问题。但是,它比使用 JBoss API 之类的东西要笨重一些。

是否有人对这个问题有任何建议——无论是另一个 API、代码模式还是一个漂亮的技巧?

【问题讨论】:

  • 您是否在某种容器中运行?您可能会使用模式来执行此操作,但这可能取决于您使用的日志管理器。

标签: java logging slf4j log4j2 jboss-logging


【解决方案1】:

你没有说明你不使用 log4j2 的任何具体原因,所以我建议你走这条路。正如您所指出的,它提供了StructuredDataMessage,您可以使用它来满足您的需求。尽管在这种情况下,我建议使用 MapMessage,因为您的示例不包括 idtype 之类的东西,它们内置在 StructuredDataMessage 类中。

这里有一些快速示例代码:

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.message.MapMessage;

public class MapMessageExample {

    private static final Logger log = LogManager.getLogger();   

    public static void main(String[] args){
        log.info(buildMsg("My title", "This is the description", 
                "No response needed", "Some details here"));        
    }

    // This could be moved into a factory class
    public static MapMessage buildMsg(String title, String description, 
            String responseAction, String details)
    {
        MapMessage mapMsg = new MapMessage();
        mapMsg.put("title", title);
        mapMsg.put("desc", description);
        mapMsg.put("response", responseAction);
        mapMsg.put("details", details);
        return mapMsg;
    }
}

还有一个与之配套的 log4j2.xml 配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%M] %-5level %logger{36}%n\tCaption: ${map:title}%n\tDescription: ${map:desc}%n\tResponse Action: ${map:response}%n\tDetails: ${map:details}%n" />
        </Console>
    </Appenders>

    <Loggers>
        <Root level="debug">
            <AppenderRef ref="Console" />
        </Root>
    </Loggers>
</Configuration>

这是一些示例输出:

00:40:45.810 [main] INFO  example.MapMessageExample
    Caption: My title
    Description: This is the description
    Response Action: No response needed
    Details: Some details here

一些最后的想法:

我的代码可以委托给一些 StructuredDataMessage 工厂来解决这个问题

我同意,工厂模式在这里是一个不错的选择。正如我在示例代码中评论的那样,您可以将 buildMsg 方法移动到工厂类。

但是,它比使用 JBoss API 之类的东西要笨重一些。

我真的不明白它有多笨重。如果您发现大部分时间只有MapMessage 中的一两个项目发生变化,您可以轻松编写类似于您提到的 API 的非常具体的方法。添加到上面的例子:

public static MapMessage reallySpecificLogMessage(String details){
    return buildMsg("My specific message title", "My specific description",
            "My specific response action", details);
}

您可能希望将常量分配给此方法中使用的字符串,但正如我所说,这只是一个简单的示例。

【讨论】:

  • 是的,我想我会像这样使用它,但想看看是否还有其他/其他想法。谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多