Log4j, Log4j 2 - Yash-777/Java_Mail GitHub Wiki

Logging API stackpost - The Java Logging API facilitates software servicing and maintenance at customer sites by producing log reports suitable for analysis by end-users, system administrators, field service engineers, and software development teams. The Logging APIs capture information such as security failures, configuration errors, performance bottlenecks, and/or bugs in the application or platform. The core package includes support for delivering plain text or XML formatted log records to memory, output streams, consoles, files, and sockets. In addition, the logging APIs are capable of interacting with logging services that already exist on the host operating system.

Maven POX.XML

<profiles>
    <profile>
      <id>dev</id>
      <activation> <activeByDefault>true</activeByDefault> </activation>
      <properties>
        <war.classifier>dev</war.classifier>
        <conf.directory>conf/dev</conf.directory>
        <environment>DEV</environment>

        <mailerror.host></mailerror.host>
        <mailerror.port></mailerror.port>
        <mailerror.from></mailerror.from>
        <mailerror.to></mailerror.to>
        <env.mail.subject></env.mail.subject>
      </properties>
    </profile>
</profiles> 

log4j.properties

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

# File based log output
log4j.appender.RFile.File=${catalina.home}/logs/MyAppNameSpecificLog.log
log4j.appender.RFile=org.apache.log4j.RollingFileAppender
log4j.appender.RFile.MaxFileSize=10000KB
# Keep 80 backup files
log4j.appender.RFile.MaxBackupIndex=80
log4j.appender.RFile.layout=org.apache.log4j.PatternLayout
log4j.appender.RFile.layout.ConversionPattern=   %5p\t[%d] [%t] (%F:%L) %c \n     \t%m%n\n

#Email Delivery failure
log4j.appender.email=org.apache.log4j.net.SMTPAppender
log4j.appender.email.SMTPHost=${mailerror.host}
log4j.appender.email.SMTPPort=${mailerror.port}
log4j.appender.email.SMTPUsername[email protected]
log4j.appender.email.SMTPPassword=mypw
log4j.appender.email.From=${mailerror.from}
log4j.appender.email.To=${mailerror.to}
log4j.appender.email.Subject=${env.mail.subject}

log4j.appender.email.layout=org.apache.log4j.PatternLayout
log4j.appender.email.layout.ConversionPattern=%d %-5p (%F:%L) - %m%n
log4j.appender.email.filter.LevelRFilter=org.apache.log4j.varia.LevelRangeFilter
log4j.appender.email.filter.LevelRFilter.LevelMin=fatal
log4j.appender.email.filter.LevelRFilter.LevelMax=fatal

Third-party Log level changing

#####Configuration related to Apache Axis STARTs###########
#https://wiki.apache.org/ws/FrontPage/Axis/DealingWithCommonExceptions
log4j.logger.org.apache.axis.ConfigurationException = INFO
#####Configuration related to Apache Axis ENDs###########

# To handle different jar files log level
log4j.logger.de.eonis=INFO

# This sets all FOP logging to INFO. The only output from the renderers is logged on the DEBUG level.
log4j.logger.org.apache.fop = INFO
log4j.logger.org.apache.fop.render = DEBUG

log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="trace" name="MyAppName" packages="">
  <Appenders>
    <RollingRandomAccessFile  name="RollFile" fileName="${sys:catalina.home}/logs/MyAppNameSpecificLog.log"
                 filePattern="${sys:catalina.home}/logs/archive/$${date:yyyy-MM}/MyAppNameSpecificLog-${environment}-%d{MM-dd-yyyy}-%i.log.gz">
      <PatternLayout>
        <Pattern>%d %-5p (%F:%L) - %m%n</Pattern>
      </PatternLayout>
      <Policies>
        <TimeBasedTriggeringPolicy />
        <SizeBasedTriggeringPolicy size="10 MB"/>
      </Policies>
      <DefaultRolloverStrategy max="20"/>
    </RollingRandomAccessFile>

    <SMTP name="MailError" subject="${env.mail.subject}" to="${mailerror.to}" from="${mailerror.from}"
          smtpHost="${mailerror.host}" smtpPort="${mailerror.port}" bufferSize="50" >
      <ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
      <PatternLayout>
        <pattern>%d %-5p (%F:%L) - %m%n</pattern>
      </PatternLayout>
    </SMTP>
  </Appenders>

  <Loggers>
    <Root level="trace">
      <AppenderRef ref="RollFile"/>
      <AppenderRef ref="MailError" level="ERROR"/>
    </Root>
  </Loggers>
</Configuration>


πŸ“˜ Log4j 2 Logging Implementation

πŸ” What is Log4j 2?

Log4j 2 is a powerful and flexible logging framework for Java applications. It supports asynchronous logging, fine-grained configuration, multiple output targets (file, console, etc.), and log rotation.

βœ… Why Use Log4j 2?

  • Performance: Async loggers improve throughput.
  • Separation: Different log files for different concerns (e.g., request_response, commissionrun).
  • Maintainability: Easy to manage log level and format per component.
  • Log Rotation: Automatic size-based and date-based log rolling.
  • Integration: Works with SLF4J (LoggerFactory.getLogger()).

Code Usage (Mapped to Log Files)

Appender Name Log Path Logger Name Code Usage
COMMISSION_RUN_APPENDER /apps/logs/myapp/commissionrun.log commissionRun LoggerFactory.getLogger("commissionRun")
REQUEST_RESPONSE_APPENDER /apps/logs/myapp/request_response.log request_response LoggerFactory.getLogger("request_response")
INT_APPENDER /apps/logs/myapp/integration.log integration LoggerFactory.getLogger("integration")
FILEAPPENDER (Root) /apps/logs/myapp/application.log Root logger Used when logger name is not explicitly configured in XML

πŸ“¦ Maven Setup πŸ› οΈ Implementation Steps

πŸ”Ή Step 1: Add Dependencies: Add the following to your pom.xml:

<properties>
    <apache.log4j.version>2.24.2</apache.log4j.version>
</properties>

<dependencies>
<!-- Log4j 2 API -->
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-api</artifactId>
        <version>${apache.log4j.version}</version>
    </dependency>
<!-- Core Log4j 2 functionality -->
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>${apache.log4j.version}</version>
    </dependency>
<!-- πŸ§ͺ Optional: SLF4J Bridge (If you're using SLF4J) If you're using SLF4J as an abstraction -->
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-slf4j-impl</artifactId>
        <version>${apache.log4j.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-jul</artifactId>
        <version>${apache.log4j.version}</version>
    </dependency>
</dependencies>

🎯 These dependencies support native Log4j 2 logging, SLF4J bridge compatibility, and Java Util Logging (JUL) redirection.

πŸ—‚οΈ Step 2: Create log4j2.xml

πŸ“ Location: src/main/resources/log4j2.xml

πŸ”§ Configuration Highlights:

  • Multiple RollingFile appenders for different log categories
  • Log rotation policies (100MB max size, 100 backups)
  • Separate loggers for:
    • request_response β†’ request_response.log
    • commissionRun β†’ commissionrun.log
    • integration β†’ integration.log
  • Root logger for generic logging

βœ… log4j2.xml Configuration File (with comments)

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN" shutdownHook="disable" monitorInterval="60">
    
    <!-- ========== Appenders ========== -->
    <Appenders>

        <!-- Console appender for debugging during development -->
        <Console name="Console" target="SYSTEM_OUT" ignoreExceptions="false">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" charset="UTF-8" />
        </Console>

        <!-- General application log appender -->
        <RollingFile name="FILEAPPENDER"
                     fileName="/apps/logs/myapp/application.log"
                     filePattern="/apps/logs/myapp/application-%d{MM-dd-yyyy}-%i.log.gz"
                     ignoreExceptions="false">
            <PatternLayout charset="UTF-8">
                <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
            </PatternLayout>
            <Policies>
                <!-- Rotate log when it exceeds 100 MB -->
                <SizeBasedTriggeringPolicy size="100 MB" />
            </Policies>
            <!-- Keep up to 100 old log files -->
            <DefaultRolloverStrategy max="100"/>
        </RollingFile>

        <!-- Appender for request/response logs -->
        <RollingFile name="REQUEST_RESPONSE_APPENDER"
                     fileName="/apps/logs/myapp/request_response.log"
                     filePattern="/apps/logs/myapp/request_response-%d{MM-dd-yyyy}-%i.log.gz"
                     ignoreExceptions="false">
            <PatternLayout charset="UTF-8">
                <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
            </PatternLayout>
            <Policies>
                <SizeBasedTriggeringPolicy size="100 MB" />
            </Policies>
            <DefaultRolloverStrategy max="100"/>
        </RollingFile>

        <!-- Appender for commission run logs -->
        <RollingFile name="COMMISSION_RUN_APPENDER"
                     fileName="/apps/logs/myapp/commissionrun.log"
                     filePattern="/apps/logs/myapp/commissionrun-%d{MM-dd-yyyy}-%i.log.gz"
                     ignoreExceptions="false">
            <PatternLayout charset="UTF-8">
                <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
            </PatternLayout>
            <Policies>
                <SizeBasedTriggeringPolicy size="100 MB" />
            </Policies>
            <DefaultRolloverStrategy max="100"/>
        </RollingFile>

        <!-- Appender for integration logs -->
        <RollingFile name="INT_APPENDER"
                     fileName="/apps/logs/myapp/integration.log"
                     filePattern="/apps/logs/myapp/integration-%d{MM-dd-yyyy}-%i.log.gz"
                     ignoreExceptions="false">
            <PatternLayout charset="UTF-8">
                <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
            </PatternLayout>
            <Policies>
                <SizeBasedTriggeringPolicy size="100 MB" />
            </Policies>
            <DefaultRolloverStrategy max="100"/>
        </RollingFile>
    </Appenders>

    <!-- ========== Loggers ========== -->
    <Loggers>

        <!-- Framework and system loggers (filtered to reduce noise) -->
        <Logger name="org.springframework" level="WARN" additivity="false">
            <AppenderRef ref="FILEAPPENDER" />
        </Logger>

        <Logger name="org.apache.http" level="INFO" additivity="false">
            <AppenderRef ref="FILEAPPENDER" />
        </Logger>

        <Logger name="org.quartz.core.QuartzSchedulerThread" level="INFO" additivity="false">
            <AppenderRef ref="FILEAPPENDER" />
        </Logger>

        <Logger name="springfox.documentation.spring.web.readers.operation.CachingOperationNameGenerator" level="WARN" additivity="false">
            <AppenderRef ref="FILEAPPENDER" />
        </Logger>

        <Logger name="org.apache.velocity" level="FATAL" additivity="false">
            <AppenderRef ref="FILEAPPENDER" />
        </Logger>

        <Logger name="org.thymeleaf" level="WARN" additivity="false">
            <AppenderRef ref="FILEAPPENDER" />
        </Logger>

        <!-- Custom named logger: request_response β†’ writes to request_response.log -->
        <Logger name="request_response" level="INFO" additivity="false">
            <AppenderRef ref="REQUEST_RESPONSE_APPENDER" />
        </Logger>

        <!-- Custom named logger: commissionRun β†’ writes to commissionrun.log -->
        <Logger name="commissionRun" level="INFO" additivity="false">
            <AppenderRef ref="COMMISSION_RUN_APPENDER" />
        </Logger>

        <!-- Custom named logger: integration β†’ writes to integration.log -->
        <Logger name="integration" level="INFO" additivity="false">
            <AppenderRef ref="INT_APPENDER" />
        </Logger>

        <!-- Root logger for fallback logging -->
        <Root level="info">
            <AppenderRef ref="FILEAPPENDER" />
            <!-- Optional: Uncomment to also print to console -->
            <!-- <AppenderRef ref="Console" /> -->
        </Root>
    </Loggers>
</Configuration>

πŸ§‘β€πŸ’» Step 3: Usage in Code

Example Log Statements:

private static final Logger PELOG = LoggerFactory.getLogger("commissionRun");
PELOG.info("Started Preparing Data Sets {} millisecond", System.currentTimeMillis() - stTime);

private static final Logger AUDIT = LoggerFactory.getLogger("request_response");
AUDIT.info("createTransaction request submitted for {}", transaction.getOrderId());

private static final Logger LOG = LoggerFactory.getLogger("integration");
LOG.info("=====  PL:JpaIntegrationActor :: PaymentUtil =====");

πŸ“„ Sample Log Output

# commissionrun.log
2025-05-23 14:55:57,212 INFO commissionRun [Thread-10] Started Preparing Data Sets 0 millisecond

# request_response.log
2024-12-19 11:09:37,069 INFO request_response [http-nio-8080-exec-1] createTransaction request submitted for K8690181

# integration.log
2024-12-31 06:18:13,135 INFO integration [main] =====  PL:JpaIntegrationActor :: PaymentUtil =====

πŸ”„ How It Works

  • SLF4J Logger calls (e.g. LoggerFactory.getLogger("commissionRun")) are routed to Log4j2.
  • Log4j2 uses log4j2.xml to match logger name β†’ appender.
  • The RollingFileAppender writes to the designated log file and rotates it based on policy.
⚠️ **GitHub.com Fallback** ⚠️