You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

配置Log4j实现ERROR日志单独存储及全级别日志多端输出问题

Log4j配置问题:com.foo包ERROR日志仅写入文件,全级别日志输出到控制台和文件

需求

  • com.foo及其子包的所有ERROR级别日志写入logs/main.log文件;
  • 所有级别(DEBUG、TRACE、INFO、WARN、ERROR)日志同时输出到标准输出(stdout)和文件追加器。

问题现状

尝试了两种Log4j 1.x配置方案,但logs/main.log始终包含所有级别日志,而非仅ERROR级别。

第一次尝试的配置

#Define root logger options
log4j.rootLogger=TRACE, file, stdout

#Define stdout appender
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
logrj.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%-5p %c{1} - %m%n

#Define rolling file appender
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=logs/main.log
log4j.appender.file.Append=true
log4j.appender.file.ImmediateFlush=true
log4j.appender.file.MaxFileSize=10MB
log4j.appender.file.MaxBackupIndex=5
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d %d{Z} [%t] %-5p (%F:%L) - %m%n
log4j.appender.error-log.filter.b=org.apache.log4j.varia.LevelMatchFilter
log4j.appender.error-log.filter.LevelToMatch = ERROR
log4j.appender.error-log.filter.AcceptOnMatch = true
log4j.appender.error-log.Threshold = ERROR


#Define loggers
log4j.logger.com.foo.log4j=TRACE, file, stdout

第二次尝试的配置

#Define root logger options
log4j.rootLogger=TRACE, file, stdout

#Define stdout appender
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
logrj.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%-5p %c{1} - %m%n

#Define rolling file appender
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=logs/main.log
log4j.appender.file.Append=true
log4j.appender.file.ImmediateFlush=true
log4j.appender.file.MaxFileSize=10MB
log4j.appender.file.MaxBackupIndex=5
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d %d{Z} [%t] %-5p (%F:%L) - %m%n
log4j.appender.error-log.filter.b=org.apache.log4j.varia.LevelRangeFilter
log4j.appender.error-log.filter.LevelMin = ERROR
log4j.appender.error-log.filter.LevelMax = ERROR
log4j.appender.error-log.filter.AcceptOnMatch = true
log4j.appender.error-log.Threshold = ERROR


#Define loggers
log4j.logger.com.foo.log4j=TRACE, file, stdout

构建依赖(Gradle)

plugins {
    // Apply the scala plugin to add support for Scala
    id 'scala'

    // Apply the java-library plugin for API and implementation separation.
    id 'java-library'
}

repositories {
    // Use jcenter for resolving dependencies.
    // You can declare any Maven/Ivy/file repository here.
    jcenter()
}

dependencies {
    // Use Scala 2.13 in our library project
    implementation 'org.scala-lang:scala-library:2.13.2'
    implementation 'org.apache.logging.log4j:log4j-api:2.17.0'
    implementation 'org.apache.logging.log4j:log4j-core:2.17.0'

    // Use Scalatest for testing our library
    testImplementation 'junit:junit:null'
    testImplementation 'org.scalatest:scalatest_2.13:3.1.2'
    testImplementation 'org.scalatestplus:junit-4-12_2.13:3.1.2.0'
    implementation 'log4j:log4j:1.2.17'

    // Need scala-xml at test runtime
    testRuntimeOnly 'org.scala-lang.modules:scala-xml_2.13:1.2.0'
}

应用代码

com.foo.Application

package com.foo

import com.foo.server.Server
import com.foo.ui.UI

object Application extends App {
  val server = Server()
  val ui = new UI(server)
  ui.message("hello")
}

com.foo.ui.UI

package com.foo.ui

import com.foo.server.Server
import org.apache.log4j.LogManager

class UI(server: Server) {
  val log = LogManager.getLogger(this.getClass)

  def message(string: String): Unit = {
    log.trace("ui got message " + string)
    server.message(string)
  }
}

com.foo.server.Server

package com.foo.server

import org.apache.log4j.LogManager

case class Server() {
  val log = LogManager.getLogger(this.getClass)

  def message(string: String): Unit = {
    log.info("server got message "+ "message")
    log.error("server raised error on message "+ "message")
  }
}

问题分析

  1. 过滤器绑定错误:两次尝试中,过滤器都配置在不存在的error-log Appender上,实际文件Appender是file,过滤器未生效;
  2. Logger路径错误:配置的log4j.logger.com.foo.log4j是错误包路径,应为com.foo;
  3. 依赖冲突:同时引入Log4j 1.x和2.x依赖,导致日志系统行为异常;
  4. 拼写错误:控制台Appender的Target配置写成logrj.appender.stdout.Target,正确应为log4j.appender.stdout.Target。

正确配置方案

方案1:升级到Log4j 2.x(推荐)

步骤1:清理依赖

移除Log4j 1.x依赖,添加Log4j 1.x API桥接包以兼容现有代码:

dependencies {
    implementation 'org.scala-lang:scala-library:2.13.2'
    // 使用Log4j 2.x核心包
    implementation 'org.apache.logging.log4j:log4j-api:2.17.0'
    implementation 'org.apache.logging.log4j:log4j-core:2.17.0'
    // 桥接Log4j 1.x API
    implementation 'org.apache.logging.log4j:log4j-1.2-api:2.17.0'

    testImplementation 'org.scalatest:scalatest_2.13:3.1.2'
    testImplementation 'org.scalatestplus:junit-4-12_2.13:3.1.2.0'
    testRuntimeOnly 'org.scala-lang.modules:scala-xml_2.13:1.2.0'
}

步骤2:Log4j 2.x配置文件(log4j2.xml 放在src/main/resources下)

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <!-- 控制台Appender:输出所有级别日志 -->
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%-5p %c{1} - %m%n"/>
        </Console>

        <!-- 文件Appender:仅输出ERROR级别日志 -->
        <RollingFile name="File" fileName="logs/main.log" filePattern="logs/main-%d{yyyy-MM-dd}-%i.log">
            <ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout pattern="%d %d{Z} [%t] %-5p (%F:%L) - %m%n"/>
            <Policies>
                <SizeBasedTriggeringPolicy size="10MB"/>
            </Policies>
            <DefaultRolloverStrategy max="5"/>
        </RollingFile>
    </Appenders>
    <Loggers>
        <!-- com.foo包及其子包:输出所有级别到控制台,仅ERROR到文件 -->
        <Logger name="com.foo" level="TRACE" additivity="false">
            <AppenderRef ref="Console"/>
            <AppenderRef ref="File" level="ERROR"/>
        </Logger>
        <!-- Root Logger:默认输出到控制台 -->
        <Root level="TRACE">
            <AppenderRef ref="Console"/>
        </Root>
    </Loggers>
</Configuration>

方案2:修正Log4j 1.x配置

# Root Logger:输出所有级别到控制台
log4j.rootLogger=TRACE, stdout

# 控制台Appender
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%-5p %c{1} - %m%n

# 文件Appender:仅保留ERROR级别
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=logs/main.log
log4j.appender.file.Append=true
log4j.appender.file.ImmediateFlush=true
log4j.appender.file.MaxFileSize=10MB
log4j.appender.file.MaxBackupIndex=5
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d %d{Z} [%t] %-5p (%F:%L) - %m%n
# 添加LevelMatchFilter,仅接受ERROR
log4j.appender.file.filter.1=org.apache.log4j.varia.LevelMatchFilter
log4j.appender.file.filter.1.LevelToMatch=ERROR
log4j.appender.file.filter.1.AcceptOnMatch=true
# 添加DenyAllFilter,拒绝其他所有日志
log4j.appender.file.filter.2=org.apache.log4j.varia.DenyAllFilter

# com.foo包Logger:输出所有级别到控制台,同时将ERROR输出到文件
log4j.logger.com.foo=TRACE, file
# 关闭additivity,避免重复输出到root的Appender
log4j.additivity.com.foo=false

验证结果

运行应用后:

  • 控制台会输出TRACE、INFO、ERROR等所有级别的日志;
  • logs/main.log中仅会出现ERROR级别的日志。

内容的提问来源于stack exchange,提问作者Chris Bedford

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 22:37:01