Java 记录 API 详细(和多行)日志
Java Logging API for Detailed (and multiline) Logs
我想找到一个 API,它可以让我在我的应用程序的所有关键日志点中提供特定的 规范集 信息。更具体地说,它将是一条 multi-line 消息,其中包含以下信息(除了基础信息):
- 日志类别
- 简短描述标题
- 描述
- 我的应用程序将采取的响应行动(损害控制)
- 详情(异常信息等)
单个 multi-line 日志查找,例如,像这样:
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、代码模式还是一个漂亮的技巧?
您没有说明不使用 log4j2 的任何具体原因,因此我建议您采用该方法。正如您所指出的,它提供了 StructuredDataMessage
,您可以使用它来满足您的需求。尽管在这种情况下我建议使用 MapMessage
,因为您的示例不包含 id
和 type
之类的东西,它们内置于 StructuredDataMessage
class.
这是一些快速示例代码:
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
一些最后的想法:
my code could delegate to some StructuredDataMessage factory to solve this
我同意,工厂模式在这里是个不错的选择。正如我在示例代码中评论的那样,您可以将 buildMsg
方法移动到工厂 class。
However, it's a little bit bulkier than using something like this JBoss API.
我真的不明白它有什么笨重的地方。如果您发现大多数时候 MapMessage
中只有一两个项目发生变化,您可以轻松编写非常具体的方法,类似于您提到的 API。添加到上面的示例:
public static MapMessage reallySpecificLogMessage(String details){
return buildMsg("My specific message title", "My specific description",
"My specific response action", details);
}
您可能希望将常量分配给此方法中使用的字符串,但正如我所说,这只是一个简单示例。
我想找到一个 API,它可以让我在我的应用程序的所有关键日志点中提供特定的 规范集 信息。更具体地说,它将是一条 multi-line 消息,其中包含以下信息(除了基础信息):
- 日志类别
- 简短描述标题
- 描述
- 我的应用程序将采取的响应行动(损害控制)
- 详情(异常信息等)
单个 multi-line 日志查找,例如,像这样:
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、代码模式还是一个漂亮的技巧?
您没有说明不使用 log4j2 的任何具体原因,因此我建议您采用该方法。正如您所指出的,它提供了 StructuredDataMessage
,您可以使用它来满足您的需求。尽管在这种情况下我建议使用 MapMessage
,因为您的示例不包含 id
和 type
之类的东西,它们内置于 StructuredDataMessage
class.
这是一些快速示例代码:
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
一些最后的想法:
my code could delegate to some StructuredDataMessage factory to solve this
我同意,工厂模式在这里是个不错的选择。正如我在示例代码中评论的那样,您可以将 buildMsg
方法移动到工厂 class。
However, it's a little bit bulkier than using something like this JBoss API.
我真的不明白它有什么笨重的地方。如果您发现大多数时候 MapMessage
中只有一两个项目发生变化,您可以轻松编写非常具体的方法,类似于您提到的 API。添加到上面的示例:
public static MapMessage reallySpecificLogMessage(String details){
return buildMsg("My specific message title", "My specific description",
"My specific response action", details);
}
您可能希望将常量分配给此方法中使用的字符串,但正如我所说,这只是一个简单示例。