在pastebin中添加了同样的问题:https://pastebin.com/QtZKcBic (我发现粘贴时缺少一些xml标签)
我需要从持续运行的日志中读取数据,该日志以毫秒为单位刷新,因为每分钟都会有数千人访问。我的要求是:
假设有一个这样的xml请求:
<dataReq>
<id>1</id>
<name>test</name>
<reqId>ddaabyy234</reqid>
....
...
....
</dataReq>
上述请求的响应是:
<dataRes>
<id>1</id>
<dept>railway</dept>
<reqId>ddaabyy234</reqid>
.......
.......
<errcode>
<errNum>404</errNum>
</errcode>
</dataRes>
如果<errNum>
不是200
,那么我需要捕获<dataReq>..</dataReq>
并<dataRes>..</dataRes>
这里的问题是,可以有多个<dataReq>...</dataReq>
标签。因为,为了生成响应,后端系统需要一些时间,同时许多用户将从 webUI(或)移动(或)应用程序发送请求到同一个应用程序。
日志还将每 5 分钟归档到归档文件中,因为日志文件的大小每 5 分钟就会变得巨大。
答案1
这TXR语言其库中具有“尾流”功能:这些是跟随动态日志文件的流对象,与tail -f
实用程序类似。
该函数调用(open-tail "/path/to/it")
创建并返回尾流。该文件不必存在。如果文件确实存在,则流将读取它直到结束,然后监视它的增长、突然收缩或消失/重新出现,从而给应用程序带来平坦、永无止境的数据流的错觉。当然,应用程序必须足够快地从流中读取数据,这与文件轮换的频率有关。
在下面的程序中,我们定义一个数据结构来跟踪每个事务(请求-响应对)的信息,并使用尾流来扫描data
使用 TXR 模式语言调用的日志文件。
当我们匹配请求时,我们创建一个新的交易对象并将其放入以 ID 为键的哈希表中。
当我们看到失败的响应(代码不是 200)时,我们会检索该 ID 的交易。如果存在,那么我们用响应信息更新它并打印它(使用对象的自定义打印函数重新生成 XML 请求-响应对)。
匹配响应后,无论成功与否,我们都会从哈希表中删除匹配的交易。
@(do
(defstruct xact nil
id
req-inner-xml
res-inner-xml
(:method print (me *stdout* pretty-p)
(cond
(pretty-p
(put-line "<dataReq>")
[mapdo put-line me.req-inner-xml]
(put-line "</dataReq>")
(put-line "<dataRes>")
[mapdo put-line me.res-inner-xml]
(put-line "</dataRes>"))
(t :))))
(defvarl xact (hash)))
@(next (open-tail "data"))
@(repeat)
@ (cases)
<dataReq>
@ (all)
<id>@id</id>
@ (and)
@ (collect)
@lines
@ (until)
</dataReq>
@ (end)
@ (end)
@ (do (set [xact id] (new xact
id id
req-inner-xml lines)))
@ (or)
<dataRes>
@ (all)
<id>@id</id>
@ (and)
@ (skip)
<errcode>
<errNum>@err</errNum>
</errcode>
@ (and)
@ (collect)
@lines
@ (until)
</dataRes>
@ (end)
@ (end)
@ (do
(whenlet ((x (del [xact id])))
(when (nequal err "200")
(set x.res-inner-xml lines)
(pprint x))))
@ (end)
@(end)