【发布时间】:2017-11-24 01:39:24
【问题描述】:
描述很长,请多多包涵:
我的日志文件大小从 300 mb 到 1.5 Gb 不等,需要根据搜索键对其进行过滤。
日志的格式是这样的:
24 May 2017 17:00:06,827 [INFO] 123456 (Blah : Blah1) Service-name:: Single line content
24 May 2017 17:00:06,828 [INFO] 567890 (Blah : Blah1) Service-name:: Content( May span multiple lines)
24 May 2017 17:00:06,829 [INFO] 123456 (Blah : Blah2) Service-name: Multiple line content. Printing Object[ ID1=fac-adasd ID2=123231
ID3=123108 Status=Unknown
Code=530007 Dest=CA
]
24 May 2017 17:00:06,830 [INFO] 123456 (Blah : Blah1) Service-name:: Single line content
4 May 2017 17:00:06,831 [INFO] 567890 (Blah : Blah2) Service-name:: Content( May span multiple lines)
给定搜索键 123456,我需要获取以下内容:
24 May 2017 17:00:06,827 [INFO] 123456 (Blah : Blah1) Service-name:: Single line content
24 May 2017 17:00:06,829 [INFO] 123456 (Blah : Blah2) Service-name: Multiple line content. Printing Object[ ID1=fac-adasd ID2=123231
ID3=123108 Status=Unknown
Code=530007 Dest=CA
]
24 May 2017 17:00:06,830 [INFO] 123456 (Blah : Blah1) Service-name:: Single line content
以下 awk 脚本完成了我的工作(非常缓慢):
gawk '/([0-9]{1}|[0-9]{2})\s\w+\s[0-9]{4}/{n=0}/123456/{n=1} n'
搜索 1 GB 大小的日志文件大约需要 8 分钟。我需要为许多此类文件执行此操作。最重要的是,我有多个这样的搜索键,这使得整个任务变得不可能。
我最初的解决方案是使用多线程。我使用了一个fixedThreadPoolExecutor,为每个需要过滤的文件提交了一个任务。在任务描述中,我使用 java 的 Runtime() 生成了新进程,该进程将使用 bash 执行 gawk 脚本并将输出写入文件,然后合并所有文件。
虽然这似乎是一种糟糕的方法,但由于过滤依赖于 I/O 而不是 CPU,与按顺序在每个文件上执行脚本相比,它确实给了我一个加速。
但这仍然不够,因为整个过程需要 2 小时,对于单个搜索键,以及 27gb 的日志文件。平均而言,我有 4 个这样的搜索键,需要获取它们的所有结果并将它们放在一起。
我的方法效率不高,因为:
A) 当给定多个搜索键时,它会多次访问每个日志文件,并导致更多的 I/O 开销。
B) 它会产生在每个线程内创建进程的开销。
解决所有这些问题的一个简单方法是使用一些正则表达式库,从 awk 转移到 java 中完成所有事情。这里的问题是,可以为我提供所需输出的正则表达式库是什么?
使用 awk 我有 /filter/{action} 属性,它可以让我指定要捕获的多行范围(如上所示)。我怎样才能在 java 中做同样的事情?
我愿意接受各种建议。例如,一个极端的选择是将日志文件存储在像 S3 这样的共享文件系统中,并使用多台计算机处理输出。
我是 stackoverflow 的新手,我什至不知道我是否可以在这里发布。但过去一周我一直在做这件事,我需要有专业知识的人来指导我做这件事。提前致谢。
【问题讨论】:
-
logcheck 或 logwatch 或 graylog 有什么问题?您不需要自己实施此解决方案。
-
grep 对您没有帮助。如果您需要分布式系统即服务,那么您可以使用 lucene 等内容搜索技术。
-
读取整个 27gb 的日志文件需要多少时间?这将为您提供所需的最少时间,并据此决定是否进一步优化。 +1 清楚地写出一个好问题,顺便说一句
-
尝试添加锚点:
gawk '/^([0-9]{1}|[0-9]{2})\s\w+\s[0-9]{4}/{n=0}/123456/{n=1} n' -
@Michael 我目前正在研究logstash。我也需要看看你的建议。我不太确定是否能够解析日志文件。谷歌告诉我,使用 logwatch,我们可以自定义解析。如果成功了,我会告诉你的。
标签: java regex algorithm logging awk