如何将字符串附加到所有日志消息

时间:2016-01-24 07:21:29

标签: java log4j

我想使用log4j将一个字符串(用户名和线程号)附加到我的java应用程序中的每条日志消息中。有什么简单干净的方法吗?要覆盖的任何一种方法吗?

2 个答案:

答案 0 :(得分:1)

您还可以查看log4j的嵌套诊断上下文功能。

答案 1 :(得分:1)

如果您准备使用某些框架作为AspectJ,那么它非常简单。在这里,我将举一个使用Maven的例子。

首先是pom:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>dummy-log</groupId>
    <artifactId>dummy-log</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <description>
    How to append a string to all log messages
    http://stackoverflow.com/questions/34973214/how-to-append-a-string-to-all-log-messages
    </description>

    <properties>
        <main.class>dummy.log.MainApp</main.class>

        <jdk.version>1.7</jdk.version>
        <project.encoding>UTF-8</project.encoding>

        <project.build.sourceEncoding>${project.encoding}</project.build.sourceEncoding>
        <project.reporting.outputEncoding>${project.encoding}</project.reporting.outputEncoding>

        <maven.compiler.source>${jdk.version}</maven.compiler.source>
        <maven.compiler.target>${jdk.version}</maven.compiler.target>
        <maven.compiler.compilerVersion>${jdk.version}</maven.compiler.compilerVersion>
        <maven.compiler.fork>true</maven.compiler.fork>
        <maven.compiler.verbose>true</maven.compiler.verbose>
        <maven.compiler.optimize>true</maven.compiler.optimize>
        <maven.compiler.debug>true</maven.compiler.debug>

        <maven.jar.plugin.version>2.6</maven.jar.plugin.version>
        <maven.antrun.plugin.version>1.8</maven.antrun.plugin.version>
        <aspectj.maven.plugin.version>1.8</aspectj.maven.plugin.version>

        <aspectj.version>1.8.7</aspectj.version>
        <log4j.version>1.2.17</log4j.version>
    </properties>

    <dependencies>
        <!-- compile time weaving -->

        <!-- required to avoid warning from aspectj-maven-plugin, even if aspectjweaver 
            is also a dependency -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>${aspectj.version}</version>
        </dependency>

        <!-- aspectjrt is only a subset of aspectjweaver -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>${aspectj.version}</version>
        </dependency>

        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>${log4j.version}</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>aspectj-maven-plugin</artifactId>
            </plugin>
        </plugins>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.codehaus.mojo</groupId>
                    <artifactId>aspectj-maven-plugin</artifactId>
                    <version>${aspectj.maven.plugin.version}</version>
                    <configuration>
                        <complianceLevel>${jdk.version}</complianceLevel>
                        <showWeaveInfo>true</showWeaveInfo>
                    </configuration>
                    <executions>
                        <execution>
                            <goals>
                                <goal>compile</goal>
                                <goal>test-compile</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>

    <profiles>
        <profile>
            <id>class-antrun</id>
            <build>
                <plugins>
                    <plugin>
                        <artifactId>maven-antrun-plugin</artifactId>
                        <version>${maven.antrun.plugin.version}</version>
                        <configuration>
                            <target>
                                <java fork="true" classname="${main.class}">
                                    <classpath refid="maven.compile.classpath" />
                                </java>
                            </target>
                        </configuration>
                    </plugin>
                </plugins>
            </build>
        </profile>
        <profile>
            <id>only-under-eclipse</id>
            <activation>
                <property>
                    <name>m2e.version</name>
                </property>
            </activation>
            <build>
                <pluginManagement>
                    <plugins>
                        <plugin>
                            <groupId>org.eclipse.m2e</groupId>
                            <artifactId>lifecycle-mapping</artifactId>
                            <version>1.0.0</version>
                            <configuration>
                                <lifecycleMappingMetadata>
                                    <pluginExecutions>
                                        <pluginExecution>
                                            <pluginExecutionFilter>
                                                <groupId>org.codehaus.mojo</groupId>
                                                <artifactId>aspectj-maven-plugin</artifactId>
                                                <versionRange>[${aspectj.maven.plugin.version},)</versionRange>
                                                <goals>
                                                    <goal>compile</goal>
                                                    <goal>test-compile</goal>
                                                </goals>
                                            </pluginExecutionFilter>
                                            <action>
                                                <ignore />
                                            </action>
                                        </pluginExecution>
                                    </pluginExecutions>
                                </lifecycleMappingMetadata>
                            </configuration>
                        </plugin>
                    </plugins>
                </pluginManagement>
            </build>
        </profile>
    </profiles>

</project>

然后在消息中包含线程名称的log4j配置文件:

log4j.rootLogger=ERROR,stdout

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%p\t%d{ISO8601}\t%r\t%c\t[%t]\t%m%n

现在是一个主要的课程:

package dummy.log;

import org.apache.log4j.Logger;

public final class MainApp {

    private static final Logger LOG = Logger.getLogger(MainApp.class);

    public static void main(final String[] args) {

        LOG.info("Hello!");
        LOG.debug("Hello!");
        LOG.error("Hello!");
        LOG.fatal("Hello!");
        LOG.trace("Hello!");
        LOG.warn("Hello!");

    }

}

用于获取用户名的编织作业由以下内容完成:

package dummy.log;

import static java.lang.String.format;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class AspectjDemo {

    @Around("call(public void org.apache.log4j.Logger.*(Object)) && args(msg) && !within(AspectjDemo)")
    public Object formatMessageLog(final Object msg, 
            final ProceedingJoinPoint invocation,
            final JoinPoint.EnclosingStaticPart callerContext) throws Throwable {
        return formatLogAndProceed(msg, null, invocation, callerContext);
    }

    @Around("call(public void org.apache.log4j.Logger.*(Object, Throwable)) && args(msg, exception) && !within(AspectjDemo)")
    public Object formatMessageLog(final Object msg, 
            final Throwable exception, 
            final ProceedingJoinPoint invocation,
            final JoinPoint.EnclosingStaticPart callerContext) throws Throwable {
        return formatLogAndProceed(msg, exception, invocation, callerContext);
    }

    private Object formatLogAndProceed(final Object msg, final Throwable exception,
            final ProceedingJoinPoint invocation, final JoinPoint.EnclosingStaticPart callerContext) throws Throwable {

        final Object[] arguments = invocation.getArgs();
        final String user = System.getProperty("user.name");
        arguments[0] = formatMessage(user, msg);

        return invocation.proceed(arguments);
    }

    private String formatMessage(final String user, final Object originalMessage) {
        return format("Log (user is \'%s\'): %s", user, originalMessage);
    }
}

试一试:

mvn clean compile antrun:run -Pclass-antrun

你会得到类似的东西:

[INFO] --- aspectj-maven-plugin:1.8:compile (default) @ dummy-log ---
[INFO] Showing AJC message detail for messages of types: [error, warning, fail]
[INFO] Join point 'method-call(void org.apache.log4j.Logger.info(java.lang.Object))' in Type 'dummy.log.MainApp' (MainApp.java:11) advised by around advice from 'dummy.log.AspectjDemo' (AspectjDemo.java:14)
[INFO] Join point 'method-call(void org.apache.log4j.Logger.debug(java.lang.Object))' in Type 'dummy.log.MainApp' (MainApp.java:12) advised by around advice from 'dummy.log.AspectjDemo' (AspectjDemo.java:14)
[INFO] Join point 'method-call(void org.apache.log4j.Logger.error(java.lang.Object))' in Type 'dummy.log.MainApp' (MainApp.java:13) advised by around advice from 'dummy.log.AspectjDemo' (AspectjDemo.java:14)
[INFO] Join point 'method-call(void org.apache.log4j.Logger.fatal(java.lang.Object))' in Type 'dummy.log.MainApp' (MainApp.java:14) advised by around advice from 'dummy.log.AspectjDemo' (AspectjDemo.java:14)
[INFO] Join point 'method-call(void org.apache.log4j.Logger.trace(java.lang.Object))' in Type 'dummy.log.MainApp' (MainApp.java:15) advised by around advice from 'dummy.log.AspectjDemo' (AspectjDemo.java:14)
[INFO] Join point 'method-call(void org.apache.log4j.Logger.warn(java.lang.Object))' in Type 'dummy.log.MainApp' (MainApp.java:16) advised by around advice from 'dummy.log.AspectjDemo' (AspectjDemo.java:14)
[WARNING] advice defined in dummy.log.AspectjDemo has not been applied [Xlint:adviceDidNotMatch]
    /home/pierre/workspace-js/dummy-log/src/main/java/dummy/log/AspectjDemo.java:21

[INFO] 
[INFO] --- maven-antrun-plugin:1.8:run (default-cli) @ dummy-log ---
[INFO] Executing tasks

main:
     [java] ERROR   2016-01-24 10:57:37,379 1   dummy.log.MainApp   [main]  Log (user is 'pierre'): Hello!
     [java] FATAL   2016-01-24 10:57:37,380 2   dummy.log.MainApp   [main]  Log (user is 'pierre'): Hello!
[INFO] Executed tasks

这里的用户名是操作系统名称。您可以根据需要更换它,例如使用servlet过滤器检索的用户名。

就是这样。希望它会有所帮助。