Apache log4php 2.3.0 配置参数详解
基于Ubuntu 22.04实测详解log4php 2.3.0的INI、XML、数组三种配置格式与Appender、Layout、Filter全参数及生产模板。
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/properties | XML | PHP 数组 |
|---|---|---|---|
| 加载入口 | Logger::configure(文件路径) | Logger::configure(文件路径) | Logger::configure(array(...)) |
| 解析器 | LoggerConfigurationAdapterINI | LoggerConfigurationAdapterXML | 直接遍历 |
| 能力覆盖 | 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.<名> | 是否叠加父 Appender | true | 置 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 或 stderr | stdout |
| 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 | 实测追加 |
| maxFileSize | Rolling | 单文件阈值 | 10MB | 实测 10KB 触发 |
| maxBackupIndex | Rolling | 历史文件保留数 | 1 | 实测 3 |
| datePattern | DailyFile | 日期模板 | Y-m-d | DailyFile 用 |
滚动压测实测(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 页面调试用 |
| LoggerAppenderDailyFile | file、datePattern | 按日期切文件 |
| LoggerAppenderPDO | dsn、user、password、table | 参数化落库,需 pdo 扩展 |
| LoggerAppenderMail / MailEvent | to、from、subject | 攒批发送/逐条发送 |
| LoggerAppenderMongoDb | host、databaseName、collectionName | 结构化存储 |
| LoggerAppenderSocket | remoteHost、port | TCP 推送 |
| LoggerAppenderSyslog | ident、facility | 系统 syslog |
| LoggerAppenderPhp | 无 | error_log 通道 |
| LoggerAppenderNull | 无 | 丢弃(测试) |
五、Layout 参数详解
5.1 LoggerLayoutPattern 转换符
| 转换符 | 含义 | 实测输出示例 |
|---|---|---|
| %d{格式} | 时间戳,格式符同 date();默认格式 ISO8601 | 2026-10-14 16:55:10.444 |
| %t | 线程号(PHP 下即进程 PID) | 8364 |
| %p | 级别,%-5p 补齐 5 列 | INFO (补 1 空格) |
| %c | Logger 名 | OrderService.Dao |
| %m | 消息 | 滚动压测第 1 条 |
| %n | 换行 | — |
| %x | NDC 栈内容 | web-request-1001(XmlLayout 实测) |
| %X{key} | MDC 指定键 | admin(JSON 行实测) |
| %F / %L / %M | 文件/行号/方法 | demo3.php / 14 / main(XmlLayout 实测) |
| %r | 自启动毫秒 | — |
| %% | 字面百分号 | % |
5.2 其它内置 Layout
| Layout | 类名 | 说明 | 实测备注 |
|---|---|---|---|
| Simple | LoggerLayoutSimple | 级别 - 消息 | 默认兜底布局(警告回退指向它) |
| TTCC | LoggerLayoutTTCC | 时间/线程/类别/上下文 | — |
| Html | LoggerLayoutHtml | HTML 表格 | — |
| Xml | LoggerLayoutXml | log4php: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 | 类名 | 参数 | 默认值 |
|---|---|---|---|
| LevelMatch | LoggerFilterLevelMatch | levelToMatch、acceptOnMatch | 无、true |
| LevelRange | LoggerFilterLevelRange | levelMin、levelMax、acceptOnMatch | 无、无、true |
| StringMatch | LoggerFilterStringMatch | stringToMatch、acceptOnMatch | 无、true |
| DenyAll | LoggerFilterDenyAll | 无 | 无条件拒绝 |
实测验证(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="{"time":"%d{Y-m-d\ H:i:s}","level":"%p","logger":"%c","pid":"%t","message":"%m"}%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。排障时看到"级别 - 消息"极简输出,多半是布局配置没被解析到。
九、参考链接
- log4php 归档发行目录:https://archive.apache.org/dist/logging/log4php/2.3.0/
- Apache Attic(log4php 退役页):https://attic.apache.org/projects/log4php.html
- log4php 归档站点(配置文档快照):https://logging.apache.org/log4php/
- Monolog(替代方案)配置文档:https://github.com/Seldaek/monolog/blob/main/doc/README.md
- PSR-3 日志规范:https://www.php-fig.org/psr/psr-3/
- PHP date() 格式符(%d{...} 用):https://www.php.net/manual/function.date.php