用于详细(和多行)日志的Java日志API

用于详细(和多行)日志的Java日志API,java,logging,slf4j,log4j2,jboss-logging,Java,Logging,Slf4j,Log4j2,Jboss Logging,我想找到一个API,它允许我在应用程序的所有关键日志点中提供一组特定的规范信息。更具体地说,它将是一条多行消息,包含以下信息(除基本信息外): 日志类别 简短描述标题 描述 我的应用程序将采取的响应操作(损坏控制) 详细信息(例外信息等) 例如,对于单个多行日志,如下所示: 2017-11-10 14:26:59,156 [main] WARN o.s.t.c.s.ExampleClass: Caption: Unconformable data Description: The

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

  • 日志类别
  • 简短描述标题
  • 描述
  • 我的应用程序将采取的响应操作(损坏控制)
  • 详细信息(例外信息等)
  • 例如,对于单个多行日志,如下所示:

    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>....
    
    一个人会在他们的代码中写下:

    ActiveMQUtilLogger.LOGGER.failedToParseAddressList(e, addressList);
    
    这是我能找到的最接近我所寻找的东西。很酷。但是,我没有使用JBoss(也不想锁定到那个API中)

    我可以使用LOG4J,它有一个可以在布局中使用的参数,默认情况下我会使用它;我的代码可以委托给某个
    structuredatamessage
    工厂来解决这个问题。然而,它比使用像JBossAPI这样的东西要大一点


    有人对这个问题有什么建议吗?不管是另一个API、一个代码模式还是一个漂亮的技巧?

    您没有说明不使用log4j2的具体原因,所以我建议您这样做。正如您所指出的,它提供了
    structuredatamessage
    ,您可以使用它来满足您的需要。虽然在本例中,我建议使用
    MapMessage
    ,因为您的示例没有包含
    id
    type
    之类内置在
    structuredataMessage
    类中的内容

    下面是一些快速示例代码:

    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>
    
    最后的一些想法:

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

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

    然而,它比使用像JBossAPI这样的东西要大一点

    我真的不知道它有多笨重。如果您发现在大多数情况下,
    MapMessage
    中只有一个或两个项目在更改,那么您可以轻松编写与您提到的API类似的非常具体的方法。要添加到上述示例中,请执行以下操作:

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

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

    您没有说明不使用log4j2的任何具体原因,因此我建议您采用这种方法。正如您所指出的,它提供了
    structuredatamessage
    ,您可以使用它来满足您的需要。虽然在本例中,我建议使用
    MapMessage
    ,因为您的示例没有包含
    id
    type
    之类内置在
    structuredataMessage
    类中的内容

    下面是一些快速示例代码:

    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>
    
    最后的一些想法:

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

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

    然而,它比使用像JBossAPI这样的东西要大一点

    我真的不知道它有多笨重。如果您发现在大多数情况下,
    MapMessage
    中只有一个或两个项目在更改,那么您可以轻松编写与您提到的API类似的非常具体的方法。要添加到上述示例中,请执行以下操作:

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

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

    您是否在某种容器中运行?您可能会使用一种模式来完成,但这可能取决于您正在使用的日志管理器。您是否在某种容器中运行?你可以使用一个模式,但这可能取决于你正在使用的日志管理器。是的,我想我会像这样使用它,但想看看是否还有其他想法。谢谢,我想我会像这样使用它,但我想看看是否还有其他想法。谢谢