Apache log4php 2.3.0 配置参数详解

基于Ubuntu 22.04实测详解log4php 2.3.0的INI、XML、数组三种配置格式与Appender、Layout、Filter全参数及生产模板。

Apache log4phplog4phpApachePHP日志配置详解2026/10/15

Apache log4php 2.3.0 配置参数详解

目标:系统梳理 log4php 2.3.0 的三种配置格式(INI/properties、XML、PHP 数组),逐项解释 logger、Appender、Layout、Filter 参数含义与默认值并给出实测验证,最后提供生产配置模板。全部示例已在 Ubuntu 22.04 + PHP 8.1 实测通过。项目已进入 Apache Attic 退役,终版 2.3.0,仅建议存量维护参考,新项目请选 Monolog 等替代。

一、环境信息

项目说明
操作系统Ubuntu 22.04.5 LTS
架构x86_64
运行时PHP 8.1.2-1ubuntu2.26(php-cli)
组件版本Apache log4php 2.3.0(终版)
目录源码 /opt/log4php/apache-log4php-2.3.0,示例 /opt/log4php/demo

逐项说明:配置解析器位于 src/main/php/configurators/(LoggerConfigurationAdapterINI、LoggerConfigurationAdapterXML 与默认配置器),本篇参数均以实测行为为准;2.3.0 无配置热加载,改配置需重新执行 Logger::configure()。

二、配置体系概览

2.1 三种配置格式对比

维度INI/propertiesXMLPHP 数组
加载入口Logger::configure(文件路径)Logger::configure(文件路径)Logger::configure(array(...))
解析器LoggerConfigurationAdapterINILoggerConfigurationAdapterXML直接遍历
能力覆盖rootLogger/logger/additivity/Appender/Layout/Filter/Renderer同左同左
典型场景老项目外部配置需转义精细控制框架内嵌、无文件依赖
实测通过(demo1/demo2)通过(demo3/demo4)通过(Composer 工程)

2.2 加载方式

Logger::configure('/opt/log4php/demo/log4php.properties');  // INI
Logger::configure('/opt/log4php/demo/log4php.xml');         // XML
Logger::configure(array('rootLogger' => ...));              // 数组

逐项解说:configure 可重复调用,后一次整体替换前一次配置;不调用 configure 时框架以 root=ERROR + 单个 LoggerAppenderEcho 的最小配置兜底运行。2.3.0 无自动探测与热加载(这点不同于 log4j 的 configureAndWatch),配置变更必须重新调用 configure。

三、rootLogger 与 logger 参数

3.1 rootLogger(INI 格式)

log4php.rootLogger = DEBUG, console, rolling

语法:log4php.rootLogger = 级别, Appender名1, Appender名2。逐项解说:第一段级别是 root 的级别;后段为 Appender 名列表,须与 appender.<名> 定义对应。等价 XML:

<root>
  <level value="DEBUG" />
  <appender_ref ref="console" />
  <appender_ref ref="rolling" />
</root>

3.2 命名 logger 与 additivity

log4php.logger.OrderService.Dao = INFO
log4php.additivity.OrderService.Dao = false
键含义默认值实测验证
log4php.logger.<名>该 Logger 的级别与 Appender继承父链INFO 生效,DEBUG 被拦
log4php.additivity.<名>是否叠加父 Appendertrue置 false 后过滤泄漏消除

实测验证(关键缺陷规避,集成篇 5.1 节完整复现):仅配置 log4php.logger.OrderService.Dao = INFO 时,被过滤的 DEBUG 经 additivity 通道在 root 名下泄漏输出;追加 additivity=false 后彻底消除。这是 2.3.0 存量运维必配项。

XML 等价写法:

<logger name="OrderService.Dao" additivity="false">
  <level value="info" />
</logger>

四、Appender 参数详解

4.1 LoggerAppenderConsole

参数含义默认值
target输出流:stdout 或 stderrstdout
layout布局子配置LoggerLayoutSimple(实测未配 layout 时回退提示即指向默认布局)

INI 实测样例:

log4php.appender.console = LoggerAppenderConsole
log4php.appender.console.layout = LoggerLayoutPattern
log4php.appender.console.layout.conversionPattern = %d{Y-m-d H:i:s.u} [%t] %-5p %c - %m%n

实测输出:

2026-10-14 16:55:10.444 [8364] DEBUG OrderService - 调试信息:订单服务启动参数加载完成

4.2 LoggerAppenderFile 与 LoggerAppenderRollingFile

参数Appender含义默认值实测验证
file两者目标文件路径(建议绝对路径)无/opt/log4php/demo/roll.log 正常落盘
append两者追加或覆盖true实测追加
maxFileSizeRolling单文件阈值10MB实测 10KB 触发
maxBackupIndexRolling历史文件保留数1实测 3
datePatternDailyFile日期模板Y-m-dDailyFile 用

滚动压测实测(10KB、maxBackupIndex=3、150 条压测):

-rw-r--r-- 1 root root  6547 Oct 14 16:58 roll.log
-rw-r--r-- 1 root root 10295 Oct 14 16:58 roll.log.1

逐项解说:滚动文件命名"基名.序号"(roll.log.1 最新滚出);本次只滚 1 次故仅一个历史文件;绝对路径配置落盘位置可预期。

4.3 其它内置 Appender 速查

Appender关键参数说明
LoggerAppenderEcho无强制参数输出经 PHP echo,Web 页面调试用
LoggerAppenderDailyFilefile、datePattern按日期切文件
LoggerAppenderPDOdsn、user、password、table参数化落库,需 pdo 扩展
LoggerAppenderMail / MailEventto、from、subject攒批发送/逐条发送
LoggerAppenderMongoDbhost、databaseName、collectionName结构化存储
LoggerAppenderSocketremoteHost、portTCP 推送
LoggerAppenderSyslogident、facility系统 syslog
LoggerAppenderPhp无error_log 通道
LoggerAppenderNull无丢弃(测试)

五、Layout 参数详解

5.1 LoggerLayoutPattern 转换符

转换符含义实测输出示例
%d{格式}时间戳,格式符同 date();默认格式 ISO86012026-10-14 16:55:10.444
%t线程号(PHP 下即进程 PID)8364
%p级别,%-5p 补齐 5 列INFO (补 1 空格)
%cLogger 名OrderService.Dao
%m消息滚动压测第 1 条
%n换行—
%xNDC 栈内容web-request-1001(XmlLayout 实测)
%X{key}MDC 指定键admin(JSON 行实测)
%F / %L / %M文件/行号/方法demo3.php / 14 / main(XmlLayout 实测)
%r自启动毫秒—
%%字面百分号%

5.2 其它内置 Layout

Layout类名说明实测备注
SimpleLoggerLayoutSimple级别 - 消息默认兜底布局(警告回退指向它)
TTCCLoggerLayoutTTCC时间/线程/类别/上下文—
HtmlLoggerLayoutHtmlHTML 表格—
XmlLoggerLayoutXmllog4php:eventSet 事件集实测含 NDC/MDC/位置信息

重要实测结论:2.3.0 没有内置 JSON 布局。实测配置 LoggerLayoutJson 报警告并回退:

PHP Warning:  log4php: Nonexistant layout class [LoggerLayoutJson] specified for appender [jsonAppender]. Reverting to default layout. in /opt/log4php/apache-log4php-2.3.0/src/main/php/configurators/LoggerConfiguratorDefault.php on line 475

需要 JSON 行输出时用 PatternLayout 手拼(实测模板):

log4php.appender.console.layout.conversionPattern = {"time":"%d{Y-m-d H:i:s}","level":"%p","logger":"%c","userId":"%X{userId}","message":"%m"}%n

实测输出:

{"time":"2026-10-14 16:58:54","level":"INFO","logger":"JsonDemo","userId":"admin","message":"JSON 布局输出:订单 1001 已支付"}

💡 技术拓展:Pattern 与 JSON 的取舍——Pattern 行式文本人类可读、grep 友好;JSON 行字段自描述、采集零解析成本,但同信息量体积大 40% 左右。log4php 无原生 JSON 布局(上文实测警告),生产 JSON 需求可手拼或迁移到 Monolog 的 JsonFormatter。本文实测给出两种路线的可运行样例。

六、Filter 参数详解

Appender 内 Filter 按声明顺序成链,返回 NEUTRAL/ACCEPT/DENY;出现 ACCEPT 或 DENY 即终止,全 NEUTRAL 放行。

Filter类名参数默认值
LevelMatchLoggerFilterLevelMatchlevelToMatch、acceptOnMatch无、true
LevelRangeLoggerFilterLevelRangelevelMin、levelMax、acceptOnMatch无、无、true
StringMatchLoggerFilterStringMatchstringToMatch、acceptOnMatch无、true
DenyAllLoggerFilterDenyAll无无条件拒绝

实测验证(XML 配置,demo4):

<appender name="console" class="LoggerAppenderConsole">
  <layout class="LoggerLayoutPattern">
    <param name="conversionPattern" value="%-5p %c - %m%n" />
  </layout>
  <filter class="LoggerFilterLevelMatch">
    <param name="levelToMatch" value="warn" />
    <param name="acceptOnMatch" value="true" />
  </filter>
  <filter class="LoggerFilterDenyAll" />
</appender>

程序发 INFO/WARN/ERROR 三条,实测输出仅一条:

WARN  FilterDemo - WARN 消息:命中 LevelMatchFilter,应被放行

逐项解说:WARN 命中即 ACCEPT 终止链;INFO/ERROR 未命中 NEUTRAL 到 DenyAllFilter 被 DENY。acceptOnMatch=false 时同 Filter 反转为拒绝命中级别,语义天差地别。

七、生产配置模板

7.1 INI 模板(控制台 + 大小滚动,含防泄漏)

log4php.rootLogger = INFO, console, rolling
log4php.logger.Dao = INFO
log4php.additivity.Dao = false

log4php.appender.console = LoggerAppenderConsole
log4php.appender.console.layout = LoggerLayoutPattern
log4php.appender.console.layout.conversionPattern = %d{Y-m-d H:i:s.u} [%t] %-5p %c - %m%n

log4php.appender.rolling = LoggerAppenderRollingFile
log4php.appender.rolling.file = /var/log/myapp/app.log
log4php.appender.rolling.maxFileSize = 50MB
log4php.appender.rolling.maxBackupIndex = 8
log4php.appender.rolling.append = true
log4php.appender.rolling.layout = LoggerLayoutPattern
log4php.appender.rolling.layout.conversionPattern = %d [%t] %-5p %c - %m%n

逐项解说:root 收 INFO;Dao 模块单独定级并关闭叠加(2.3.0 防 DEBUG 泄漏的必配组合);滚动 50 MB 保留 8 份,磁盘上限约 400 MB,可按水位调整;所有文件参数写绝对路径。

7.2 XML 模板(JSON 行采集 + 级别白名单)

<?xml version="1.0" encoding="UTF-8"?>
<configuration xmlns="http://logging.apache.org/log4php/">
  <appender name="jsonFile" class="LoggerAppenderRollingFile">
    <param name="file" value="/var/log/myapp/app.json" />
    <param name="maxFileSize" value="50MB" />
    <param name="maxBackupIndex" value="8" />
    <param name="append" value="true" />
    <layout class="LoggerLayoutPattern">
      <param name="conversionPattern" value="{&quot;time&quot;:&quot;%d{Y-m-d\ H:i:s}&quot;,&quot;level&quot;:&quot;%p&quot;,&quot;logger&quot;:&quot;%c&quot;,&quot;pid&quot;:&quot;%t&quot;,&quot;message&quot;:&quot;%m&quot;}%n" />
    </layout>
  </appender>
  <appender name="errorOnly" class="LoggerAppenderConsole">
    <layout class="LoggerLayoutPattern">
      <param name="conversionPattern" value="%-5p %c - %m%n" />
    </layout>
    <filter class="LoggerFilterLevelRange">
      <param name="levelMin" value="error" />
      <param name="levelMax" value="fatal" />
    </filter>
  </appender>
  <root>
    <level value="info" />
    <appender_ref ref="jsonFile" />
    <appender_ref ref="errorOnly" />
  </root>
</configuration>

逐项解说:jsonFile 收全量 JSON 行供采集器入湖(时间值中用 \ 空格转义保证 XML 内合法);errorOnly 只在前台显示 ERROR/FATAL,值班视角聚焦;两模板共同点是全部绝对路径、显式滚动配额——2.3.0 无热加载,改配置后由业务侧重新调用 Logger::configure。

八、常见问题(FAQ)

Q1:三种配置格式里 Filter 都能用吗? A:能。INI 的 filter 键、XML 的 filter 元素、数组的 filter 数组三者等价,实测 XML 链(LevelMatch+DenyAll)行为与 log4j 一致。注意 Filter 挂在 Appender 下而非 Logger 下。

Q2:log4php.logger.X 只写了级别没写 appender,合法吗? A:合法,该 Logger 只做级别收紧、不挂输出端。但结合 2.3.0 的 additivity 缺陷(被过滤消息会漏到父输出),建议同时写 log4php.additivity.X = false,实测可彻底消除泄漏。

Q3:为什么我的 JSON 布局配置不生效还报警告? A:2.3.0 没有 LoggerLayoutJson。实测报 Nonexistant layout class [LoggerLayoutJson] ... Reverting to default layout,随后按 Simple 布局输出。方案:PatternLayout 手拼 JSON 行(本文 5.2 节实测模板),或迁移 Monolog 用 JsonFormatter。

Q4:maxFileSize 的单位与默认值? A:支持 KB/MB(实测 10KB 生效),无后缀按字节,默认 10MB;maxBackupIndex 默认 1。两个参数只对 LoggerAppenderRollingFile 有效,LoggerAppenderFile 永不滚动。

Q5:改了配置文件多久生效? A:立即生效于下一次 Logger::configure() 调用——2.3.0 没有文件监视热加载,FPM 环境下每次请求重新加载也不现实,典型做法是配置随代码发布、由框架启动流程调用 configure。

Q6:%t 显示的数字是什么? A:PHP 的进程 PID(实测 [8364] 与进程号一致)。PHP 无多线程,日志里它近似请求标识;需要精确请求追踪请用 MDC 写 requestId 并用 %X{requestId} 输出。

Q7:XML 里双引号怎么写? A:属性值内用 " 转义(实测 JSON 模板),元素文本可直接写;时间格式里的空格用 \ 空格转义。转义错误会导致 XML 解析失败,按报错行号修配置。

Q8:日志重复输出两条怎么排查? A:九成是 additivity——子 Logger 与父/根各挂了 Appender。实测 XmlDemo 的 ERROR 输出两次,加 additivity="false" 后恢复单条。排查口诀:先查叠加,再查 Filter acceptOnMatch 方向。

Q9:AcceptOnMatch 是 true 还是 false 常用? A:白名单场景(只放某级别)用 true+DenyAllFilter 收口(实测三条只出 WARN);黑名单场景(拒绝某级别)用 false。改错方向会导致级别完全放行或完全静默,建议每次修改后用三条不同级别消息回归验证(本文实测即此法)。

Q10:2.3.0 的默认布局和默认配置是什么? A:未配置 Appender 的 layout 时默认 LoggerLayoutSimple(实测警告回退输出 "INFO - 消息" 形态);完全未调用 configure 时 root 为 ERROR 级别挂 Echo。排障时看到"级别 - 消息"极简输出,多半是布局配置没被解析到。

九、参考链接

  1. log4php 归档发行目录:https://archive.apache.org/dist/logging/log4php/2.3.0/
  2. Apache Attic(log4php 退役页):https://attic.apache.org/projects/log4php.html
  3. log4php 归档站点(配置文档快照):https://logging.apache.org/log4php/
  4. Monolog(替代方案)配置文档:https://github.com/Seldaek/monolog/blob/main/doc/README.md
  5. PSR-3 日志规范:https://www.php-fig.org/psr/psr-3/
  6. PHP date() 格式符(%d{...} 用):https://www.php.net/manual/function.date.php