我目前正在开发大型(功能明智的)休息网络服务,我想捕获日志真的很好,所以我可以很好地了解发生了什么。现在我使用log4j进行日志记录,使用以下附加设置:
<!-- Appenders -->
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-5p: %c - %m%n" />
</layout>
</appender>
生成这些日志:
10:44:55,893 INFO [STDOUT] INFO : my.package.MyClass - I'm class message
如何使此消息看起来像是
10:44:55,893 INFO : my.package.MyClass - I'm class message
我可以制作一个特殊的appender或者它是什么,并且在一些不是所有的类中使用它,即我想在我的几个日志中使用它:
Payload: some request parameters
Response: some response that my service returns
extra data : some extra data
没有这些INFO [STDOUT] INFO my.package.MyClass in front of it
更新
我忘记在问题中提到我正在使用Jboss 5.我认为jboss可能会将10:44:55,893 INFO [STDOUT]
添加到我放在log4j配置中的任何格式。
BOUNTY UPDATE
我改变了这个:
<!-- ============================== -->
<!-- Append messages to the console -->
<!-- ============================== -->
<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
<errorHandler class="org.jboss.logging.util.OnlyOnceErrorHandler"/>
<param name="Target" value="System.out"/>
<param name="Threshold" value="INFO"/>
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Message\n -->
<param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c{1}] %m%n"/>
</layout>
</appender>
到此:
<!-- ============================== -->
<!-- Append messages to the console -->
<!-- ============================== -->
<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
<errorHandler class="org.jboss.logging.util.OnlyOnceErrorHandler"/>
<param name="Target" value="System.out"/>
<param name="Threshold" value="INFO"/>
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Message\n -->
<param name="ConversionPattern" value="%m%n"/>
</layout>
</appender>
它有效,但像这样做似乎有点难看。还有其他方法吗?我正在使用spring MVC / JBoss组合。
我现在收到了很好的干净信息:
10:44:55,893 INFO : my.package.MyClass - I'm class message
没有恼人的
10:44:55,893 INFO [STDOUT]
前缀
答案 0 :(得分:7)
问题1:
为appender使用以下模式布局:
<param name="ConversionPattern" value="%d{ABSOLUTE} %-5p: %c - %m%n" />
您声明的配置文件中的转换模式不会导致您声明的日志类型。例如,日期/时间不包含在转换模式中。
问题2:
您可以使用一个特殊的记录器,它使用另一个只记录纯消息的appender。
您的配置将如下所示:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="consoleAppender" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%m%n" />
</layout>
</appender>
<appender name="consoleAppender2" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{ABSOLUTE} %-5p: %c - %m%n" />
</layout>
</appender>
<logger name="specialLogger" additivity="false">
<level value="INFO" />
<appender-ref ref="consoleAppender" />
</logger>
<root>
<priority value="INFO" />
<appender-ref ref="consoleAppender2" />
</root>
</log4j:configuration>
您可以将specialLogger用于纯消息,而无需其他信息。它可以用于多个类。
在specialLogger的配置中,需要additivity = "false"
,否则根记录器的appender consoleAppender2
也会记录相同的消息。 (在这种情况下,该消息将被记录两次。)
您的代码可能如下所示:
public class TestClassA
{
private static Logger specialLogger = Logger.getLogger("specialLogger");
private static Logger logger = Logger.getLogger(TestClassA.class);
public TestClassA() {
}
public void doSomething() {
logger.info("Some message from TestClassA");
specialLogger.info("Some message via the specialLogger from TestClassA");
}
}
调用doSomething导致:
17:17:18,125 INFO : com.foo.TestClassA - Some message from TestClassA
Some message via the specialLogger from TestClassA
在主类的某个地方,您需要照常配置log4j,例如:
DOMConfigurator.configureAndWatch("log4j.xml", 60 * 1000);
答案 1 :(得分:4)
INFO [STDOUT]
通常来自log4j,也可以监听System.out。我们有一个类似的情况,应用程序本身有自己的log4j配置,因此有自己的根appender。这将记录到JBoss log4j监听的控制台。这反过来又会增加INFO [STDOUT]
,就像您在写System.out
时直接写ERROR [STDERR]
(或System.err
)一样。
我们的解决方案是删除特定于应用程序的log4j配置,并使用JBoss写入的配置。
另一种方法可能是直接写入特定于应用程序的日志文件而不是写入控制台。在服务器环境中,您最有可能引用日志文件。
至于第二部分,即自动扩展带有响应,请求等数据的日志:
在一个案例中,我们为无状态会话bean提供了一个超类,它提供了日志记录功能并且每个实例都有一个(可覆盖的)记录器。然后像info
这样的基本方法会调用记录器并自动添加所需的数据。
第二种方法可能是MCD
,即您将一些数据(如请求)放入线程本地MDC(基本上是一个映射),然后在模式定义中访问它们。
例如,我们有几个类似的应用程序,每个应用程序都有一些其他类别的类。因此,我们需要消息源自哪个应用程序,从而将应用程序名称添加到MDC:
代码中:
MDC.put("app.name", "myapplication");
在log4j模式中配置:
<param name="ConversionPattern" value="%d %-5p [%c (%X{app.name})] %m%n"/>
(请注意%X {app.name} )
我没有测试你是否可以做一些事情,比如将请求放入MDC,然后使用:%X{request.getAttribute('xyz')}
但是如果它只是在MDC中获取值并在其上调用toString()
,那么你可能会创建一个这样的请求包装器:
class RequestLogWrapper {
private HttpServletRequest request; //initialize through constructor etc.
public String toString() {
return request.getAttribute("xyz") + ";" + request.getAttribute("abc") + ... //handle null etc. as well
}
}
然后拨打MDC.put("request", new RequestLogWrapper(request));
,在配置中使用%X{request}
。
答案 2 :(得分:1)
尝试使用此模式,因为它会为您提供干净的信息:
<param name="ConversionPattern" value="%d{HH:mm:ss.SSS} %-5p %c %X %m/>
最好在请求进入时向MDC添加一些唯一值,然后将%X {uniqueValueKey}添加到您的模式中。它将允许您跟踪此唯一请求的日志。
答案 3 :(得分:1)
如果您不喜欢log4j xml配置文件,则可以切换到属性文件。您无法使用简单属性文件配置过滤器,但由于您似乎不需要它们,因此这不应该是一个问题。
鉴于你是
...目前正在开发大型(功能明智的)休息网络服务,我希望捕获日志真的很好,所以我可以很好地了解发生了什么。
然后我担心你想要的输出根本不会给你很多见解,它不会很好地扩展,并且一旦应用程序按预期变大,它会让你失去理智......
请参阅Log4j Best Practices以获取日志设计的良好参考。请查看所有其段落,包括最后的装饰考虑因素。希望这会有所帮助。
答案 4 :(得分:0)
仅打印消息,以下转换模式将执行。
<param name="ConversionPattern" value="%m%n"/>
根据您的要求,您可以将转换模式设置为您想要的
您是否只将所有相关信息放入邮件中?我不确定,但这不是一个好主意。