简体   繁体   中英

How to Change log4j Configuration When Packaging

I have a fairly simple Java application that is being distributed out to users as an executable JAR file. In order to track usage and assist in diagnostics, I want to add logging capability to the application but, from one execution to the next, I can never be sure where the users are going to be running this application.

In order to make this work, I have configured my application to use a log4j socket appender - no matter where the user is running this application, messages are sent to the socket and properly logged, which is perfect.

What I'm running into now, though, it that I would prefer to use different log4j configurations when I am running locally vs. when I deploy this application into production. When running locally (from my IDE, IntelliJ), I would prefer to use a console appender for a couple reasons:

  1. It's trivial to see what is happening.
  2. Should I be developing without an Internet connection, I don't want to hang up on not being able to connect.
  3. I don't want to clutter the production logs with what I am doing during development.

When I package the application and distribute it, however, I would like it to use the socket appender, rather than the console appender.

Is there any easy way to accomplish what I want? I am using Maven to build my application, but I am not horribly skilled with it.

This turned out to be simpler than I originally expected - and Vikdor's comment led me to the right answer. I had started digging into having multiple profiles (one for dev and one for prod) but later realized I didn't really need to have two. When working locally, I wasn't really going through the Maven build process - I was just executing the Java classes. The only time I went through the Maven build process was when I wanted to package my application for deployment. As such, I simply added a section to my POM file that uses the maven-antrun-plugin. My final code ended up looking like this:

File: log4j.properties:

# Set root logger level to DEBUG and its only appender to A1.
log4j.rootLogger=DEBUG, A1

# A1 is set to be a ConsoleAppender.
log4j.appender.A1=org.apache.log4j.ConsoleAppender

# A1 uses PatternLayout.
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n

File: log4j_production.properties

# Set root logger level to DEBUG and its only appender to A1.
log4j.rootLogger=DEBUG, A2

log4j.appender.A2=org.apache.log4j.net.SocketAppender
log4j.appender.A2.remoteHost=my.server.com
log4j.appender.A2.port=6000
log4j.appender.A2.layout=org.apache.log4j.PatternLayout
log4j.appender.A2.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n

File: POM.xml

...
<build>
    <finalName>${project.artifactId}</finalName>
    <plugins>
        <plugin>
            <artifactId>maven-antrun-plugin</artifactId>
            <executions>
                <execution>
                    <phase>prepare-package</phase>
                    <goals>
                        <goal>run</goal>
                    </goals>
                    <configuration>
                        <tasks>
                            <delete file="${project.build.outputDirectory}/log4j.properties"/>
                            <copy file="src/main/resources/log4j_production.properties"
                                  toFile="${project.build.outputDirectory}/log4j.properties"/>
                        </tasks>
                    </configuration>
                </execution>
            </executions>
        </plugin>
...

That seemed to do the trick. When I run locally, I load log4j.properties, which gives me a console appender. When I package for a production distribution, Maven will replace the default log4j.properties file with the alternate one, which uses a socket appender.

Thanks!

Here's a simpler approach to your problem...

Put two log4j.properties files under src/main/resources directory, like this:-

src/main/resources
|- log4j.properties 
|- log4j_dev.properties 

log4j.properties contains the production configuration, and by default, Log4J will automatically pick this file up because you are using the standard file name.

log4j_dev.properties contains the development configuration. To ensure IntelliJ picks this up during development, you will overwrite the log configuration using -Dlog4j.configuration=<configuration-file> VM option. I attached a screenshot on how you might configure this using IntelliJ:-

在此处输入图片说明

I will strongly recommend making it determined in run-time instead of build-time.

For example, when you are running your app, have config/ directory put in beginning of classpath, and put your log4j.xml there. Of course, you may still keep a default log4.xml in your application JAR, so that if you don't provide it in deployment, your app can still run.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM