如何使用Apache Tomcat Valve Component创建健壮的访问日志?

时间:2012-11-28 09:11:33

标签: http tomcat http-headers

我们正在使用Apache Tomcat 7并尝试设置Valve Component以存储我们的访问日志,以便在SnowPlow中进行处理。

我们遇到的问题是如何使这些日志健壮。举个例子 - 我们可以用制表符分隔字段并提取用户代理字符串,如下所示:

pattern="%{yyyy-MM-dd}t	%{hh:mm:ss}t	%{User-Agent}i	"

问题是Valve Component没有(据我所知)转义%{User-Agent}i,因此useragent中的一个迷路选项卡会破坏数据(行看起来像包含四个字段,而不是三个)。

就解决方案而言,除非有办法逃避我错过的使用者,否则我可以看到几个解决方案:

  1. 使用非常模糊的字段分隔符(或字段分隔符的组合),这种分隔符不太可能在useragent字符串中出现。我们尝试过Ctrl-A(HTML ?),但这似乎不起作用
  2. 编写一个支持转义或清理标签的自定义AccessLogValve - 可能类似于此帖Sanitizing Tomcat access log entries
  3. 有点疑惑,我在网上找不到任何其他内容 - 没有人解析他们的Tomcat访问日志吗?

    你推荐什么?我们有点卡住......

2 个答案:

答案 0 :(得分:1)

RFC2616将用户代理字符串定义为

User-Agent     = "User-Agent" ":" 1*( product | comment )

然后将产品定义为

product         = token ["/" product-version]
product-version = token

在此之后,令牌被定义为

token          = 1*<any CHAR except CTLs or separators>

和分隔符/ CTL为

separators     = "(" | ")" | "<" | ">" | "@"
                      | "," | ";" | ":" | "\" | <">
                      | "/" | "[" | "]" | "?" | "="
                      | "{" | "}" | SP | HT
CTL            = <any US-ASCII control character
                    (octets 0 - 31) and DEL (127)>

我们不必忘记comment,它被定义为

comment    = "(" *( ctext | quoted-pair | comment ) ")" 
ctext      = <any TEXT excluding "(" and ")">
quoted-pair    = "\" CHAR
CHAR           = <any US-ASCII character (octets 0 - 127)>

因此,如果我理解正确,您应该可以使用任何separatorCTL,只要您可以区分comment,其中包含() {1}}。如果评论中显示(,则应使用\进行转义。

答案 1 :(得分:0)

最后,我写了一个custom Tomcat AccessLogValve

  • 引入了一个新模式'I',以逃避传入的标题
  • 引入了一个新模式“C”来获取存储在响应中的cookie
  • 重新实施模式'i'以确保将“”(空字符串)替换为“ - ”
  • 重新实施模式'q'以删除“?”并确保“”(空字符串)替换为“ - ”
  • 覆盖'v'模式,编写此AccessLogValve的版本,而不是本地服务器名称

它看起来非常强大 - 我对未转义的值没有任何进一步的问题。