valve必须配置在标签内才能实现虚拟主机日志隔离;pattern推荐combined或自定义含%d,directory中${hostname}无效需手动指定prefix,启用滚动需同时设置rotatable="true"和filedateformat="yyyy-mm-dd"。

Valve配置必须放在<host></host>标签内部,不能写在<engine></engine>或<server></server>里
Tomcat的AccessLogValve作用域是层级敏感的:只有放在<host></host>节点内,日志才会只记录该虚拟主机的请求。如果误配到<engine></engine>下,所有Host共享同一份日志,失去隔离性。
- 检查
conf/server.xml,定位目标<host name="example.com"></host>块 - 在
闭合前插入Valve,位置必须在<context></context>之外、之内 - 不要复用
localhostHost下的默认Valve——它不生效于其他Host
pattern参数决定日志字段,别直接抄默认值
默认pattern="common"只输出基础字段(IP、时间、路径、状态码),但实际排查常需Referer、User-Agent或响应耗时。用pattern="combined"或自定义格式更实用。
-
combined等价于:%h %l %u %t "%r" %s %b "%{Referer}i" "%{User-Agent}i" - 要加响应时间,用
%D(毫秒)或%T(秒),例如:%h %l %u %t "%r" %s %b %D - 中文路径可能乱码,确保
resolveHosts="false"(避免DNS反查引入编码问题)
日志文件名里的${hostname}不会自动替换,得手动写死或用系统属性
很多人以为directory="logs" prefix="access_log.${hostname}." suffix=".log"能按Host名生成不同文件,但${hostname}不是内置变量,Tomcat不解析它——结果所有Host都往同一个文件写,或者报错。
- 安全做法:为每个Host指定明确的
prefix,比如prefix="example_com_access_log." - 若想动态化,改用JVM系统属性:
prefix="access_log.${sys:HOST_NAME}.",启动时加-DHOST_NAME=example.com -
suffix建议固定为.log,避免和滚动策略(如.yyyy-MM-dd)冲突
滚动策略依赖rotatable和fileDateFormat,缺一不可
默认日志不滚动,单个文件越滚越大。启用按天滚动需要两个参数配合:rotatable="true"(开启滚动) + fileDateFormat="yyyy-MM-dd"(定义日期格式)。
- 漏掉
rotatable="true":日志永远写进access_log.yyyy-MM-dd.log,不生成新文件 -
fileDateFormat格式必须严格匹配Java SimpleDateFormat,YYYY(周年度)会导致跨年错误,务必用yyyy - 滚动后旧日志不会自动压缩,如需.gz,得靠外部脚本或Log4j2替代方案
复杂点在于Host间日志完全独立,但共享同一套rotatable逻辑——这意味着每个Host的滚动时间点一致,但文件路径、内容互不干扰。容易被忽略的是:修改server.xml后必须重启Tomcat,热加载不生效。










