如何解析Tomcat状态页且不淹没访问日志?搭建聚合状态页求助
看起来你已经搞定了聚合状态页的核心功能,现在卡在日志干扰的问题上对吧?我之前做过类似的监控项目,分享几个实用的解决思路:
1. 直接过滤状态页请求出access.log
Tomcat的AccessLogValve支持通过正则排除特定请求,完全不让这些请求出现在主访问日志里。
打开Tomcat的conf/server.xml,找到你的AccessLogValve配置块,添加excludePattern属性,匹配你的状态页路径。比如如果你的状态页是每个应用的/status或者Tomcat manager的/manager/status,配置可以改成这样:
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log" suffix=".txt" pattern="%h %l %u %t "%r" %s %b" excludePattern=".*(/status|/manager/status).*"/>
这样所有访问这些路径的请求都会被排除在access.log之外,完全不干扰正常日志。
2. 用JMX直接查询应用状态(推荐)
没必要走HTTP请求绕一圈,Tomcat本身通过JMX暴露了所有应用的状态信息,直接查MBean根本不会产生任何HTTP日志。
首先需要开启Tomcat的JMX远程访问:
在bin/catalina.sh(Windows是catalina.bat)里添加JVM启动参数:
CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9090 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false"
(生产环境一定要开启认证和SSL,别用上面的无认证配置!)
然后你可以用脚本语言(比如Python、Groovy)连接JMX端口,查询对应MBean的状态:
- 每个Web应用的Context MBean路径是
Catalina:type=Context,host=localhost,path=/你的应用名 - 查看
state属性就能知道应用是STARTED还是STOPPED
比如用Python的jmxquery库可以快速实现:
from jmxquery import JMXConnection, JMXQuery jmx_conn = JMXConnection("service:jmx:rmi:///jndi/rmi://localhost:9090/jmxrmi") queries = [JMXQuery("Catalina:type=Context,host=localhost,path=*", attribute="state")] results = jmx_conn.query(queries) for result in results: app_path = result.mbean_name.split("path=")[1] app_state = result.value print(f"应用 {app_path}: {app_state}")
这种方式不仅不会产生HTTP日志,还能获取更丰富的应用状态数据,比解析HTML页面靠谱多了。
3. 把状态页请求单独归档
如果需要保留这些请求的记录但不想混在主日志里,可以添加一个专门的AccessLogValve来单独记录状态页请求,同时主日志排除它们。
在server.xml里添加第二个AccessLogValve:
<!-- 主访问日志,排除状态页 --> <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log" suffix=".txt" pattern="%h %l %u %t "%r" %s %b" excludePattern=".*(/status|/manager/status).*"/> <!-- 专门记录状态页请求的日志 --> <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="status_check_access_log" suffix=".txt" pattern="%h %l %u %t "%r" %s %b" conditionIf="%{REQUEST_URI} =~ /status|/manager/status"/>
这样状态页的请求会单独存在status_check_access_log.*文件里,主日志干干净净。
内容的提问来源于stack exchange,提问作者Cameron Rosier

