让我们来聊聊Tomcat访问日志那些事儿。作为Java开发者,你可能每天都在和Tomcat打交道,但你真的把访问日志玩明白了吗?今天我们就来深入探讨如何通过Access Log Valve实现精细化的请求日志记录。

一、Access Log Valve基础回顾

Tomcat自带的Access Log Valve其实是个非常强大的组件,它默认就能记录基本的HTTP请求信息。在server.xml里配置起来大概长这样:

<Valve className="org.apache.catalina.valves.AccessLogValve" 
       directory="logs"
       prefix="localhost_access_log" 
       suffix=".txt"
       pattern="%h %l %u %t &quot;%r&quot; %s %b" />

这个配置会记录客户端IP、远程逻辑用户名、本地认证用户名、时间戳、请求行、状态码和返回字节数。但实际生产中,这样的日志往往不够用。

二、高级模式定制实战

Tomcat提供了丰富的模式变量让我们自定义日志内容。来看个更实用的配置示例:

<Valve className="org.apache.catalina.valves.AccessLogValve"
       directory="/var/log/tomcat"
       prefix="api_access_"
       suffix=".log"
       fileDateFormat="yyyy-MM-dd"
       pattern="%{yyyy-MM-dd HH:mm:ss}t|%{X-Forwarded-For}i|%m|%U%q|%s|%D|%{User-Agent}i|%{Referer}i|%{Accept}i"
       rotatable="true"
       renameOnRotate="true"/>

这个配置做了几件重要的事:

  1. 使用管道符分隔字段,便于后续日志分析
  2. 捕获X-Forwarded-For头,这在反向代理场景下特别有用
  3. 记录请求处理时间(%D),单位是毫秒
  4. 收集User-Agent、Referer等请求头信息

三、条件日志记录技巧

有时候我们不需要记录所有请求,比如健康检查或静态资源。这时可以用ConditionalAccessLogValve:

<Valve className="org.apache.catalina.valves.RemoteIpValve" />
<Valve className="org.apache.catalina.valves.ConditionalAccessLogValve"
       condition="unless(requestURI matches '^/healthcheck|^/static/')"
       directory="logs"
       prefix="conditional_access_"
       suffix=".log"
       pattern="%h %l %u %t &quot;%r&quot; %s %b %D" />

这个配置会:

  1. 先通过RemoteIpValve处理代理IP
  2. 然后只记录非/healthcheck和非/static/开头的请求
  3. 使用了SpEL表达式作为条件判断

四、性能优化与日志轮转

高频日志记录可能影响性能,这里有几个优化建议:

  1. 使用异步日志记录:
<Valve className="org.apache.catalina.valves.AccessLogValve"
       asyncSupported="true"
       buffered="true"
       directory="logs"
       prefix="async_access_"
       suffix=".log"
       pattern="%h %l %u %t &quot;%r&quot; %s %b" />
  1. 合理的日志轮转策略:
<Valve className="org.apache.catalina.valves.AccessLogValve"
       directory="logs"
       prefix="rotated_access_"
       suffix=".log"
       fileDateFormat="yyyy-MM-dd.HH"
       rotatable="true"
       maxDays="7"
       pattern="..." />

这个配置会每小时生成一个新日志文件,并保留最近7天的日志。

五、实战:结合ELK的日志分析

配置好日志后,我们通常需要将其导入ELK进行分析。这里给出一个Logstash配置示例:

input {
  file {
    path => "/var/log/tomcat/api_access_*.log"
    start_position => "beginning"
    sincedb_path => "/dev/null"
  }
}

filter {
  dissect {
    mapping => {
      "message" => "%{timestamp}|%{client_ip}|%{method}|%{url}|%{status}|%{duration}|%{user_agent}|%{referer}|%{accept}"
    }
  }
  
  date {
    match => ["timestamp", "yyyy-MM-dd HH:mm:ss"]
    target => "@timestamp"
  }
  
  geoip {
    source => "client_ip"
  }
}

output {
  elasticsearch {
    hosts => ["localhost:9200"]
    index => "tomcat-access-%{+YYYY.MM.dd}"
  }
}

六、安全与隐私注意事项

记录详细日志时要注意:

  1. 避免记录敏感信息如Authorization头
  2. 对密码等敏感参数进行过滤
  3. 考虑GDPR等合规要求

可以通过修改pattern实现过滤:

pattern="%h %l %u %t &quot;%r&quot; %s %b %{password}o"

然后在代码中对password参数进行脱敏处理。

七、总结与最佳实践

经过以上探索,我们总结出几个最佳实践:

  1. 根据业务需求定制日志格式,不要盲目记录所有信息
  2. 在高并发场景使用异步日志
  3. 实现合理的日志轮转策略
  4. 注意日志中的敏感信息
  5. 将日志集成到现有监控系统

合理的访问日志配置不仅能帮助排查问题,还能为业务分析提供宝贵数据。希望这些进阶技巧能帮你更好地利用Tomcat的日志功能。