我正在梳理一个webapp的日志文件,以查找突出的语句。
大多数线条相似且无趣。我会通过Unix uniq
传递它们,但是没有过滤,因为所有行都略有不同:它们都有不同的时间戳,类似的语句可能会打印不同的用户ID等。
有什么方法和/或工具可以获得与其他线条明显不同的线条? (但是,再次,不是精确的重复)
我正在考虑使用Python的difflib,但这似乎是为了区分两个文件,而不是同一个文件中的所有线对。
[编辑]
我认为解决方案会为每一行提供唯一性分数。因此,通过“显着不同”,我选择一个阈值,唯一性分数必须超过输出中包含的任何行。
基于此,如果还有其他可行的方法来定义它,请讨论。此外,该方法不必具有100%的准确性和召回率。
[/编辑]
示例:
我更喜欢尽可能通用的答案。我知道我可以在开头删除时间戳。剥离结束更具挑战性,因为它的语言可能绝对不同于文件中的任何其他内容。这些细节是我之前从具体例子中回避的原因,但是因为有些人问过......
类似1:
2009-04-20 00:03:57 INFO com.foo.Bar - URL:/graph?id=1234
2009-04-20 00:04:02 INFO com.foo.Bar - URL:/graph?id=asdfghjk
类似2:
2009-04-20 00:05:59 INFO com.baz.abc.Accessor - Cache /path/to/some/dir hits: 3466 / 16534, 0.102818% misses
2009-04-20 00:06:00 INFO com.baz.abc.Accessor - Cache /path/to/some/different/dir hits: 4352685 / 271315, 0.004423% misses
不同的1:
2009-04-20 00:03:57 INFO com.foo.Bar - URL:/graph?id=1234
2009-04-20 00:05:59 INFO com.baz.abc.Accessor - Cache /path/to/some/dir hits: 3466 / 16534, 0.102818% misses
在不同的情况下,我想要返回两行,但不喜欢其他行。换句话说,那两行是不同的类型(之后我可以只询问统计上罕见的线型)。一方面,这两者之间的编辑距离要大得多。
答案 0 :(得分:3)
定义“明显不同”。然后看看"edit distance" measures。
答案 1 :(得分:2)
您可以尝试一些计算单词的代码,然后按那些具有最少常用单词的行排序。
如果这不起作用,您可以添加一些智能来过滤掉时间戳和数字。
您的问题类似于generating summaries of news stories上的早期问题。
答案 2 :(得分:2)
我不知道一个适合你的工具,但是如果我要自己推出,我就会这样做:
据推测,原木线结构清晰,不是吗?所以
如果您熟悉unix工具procmail
,我建议为您的数据量身定制类似的处理。
正如评论中的zacherates说明,您的过滤器通常会忽略时间戳(可能还有IP地址),只关注内容:例如真正长的http请求可能代表攻击。 。或任何适用于您的域名的内容。
您的分箱过滤器可能与几个选定字段上的哈希一样简单,或者您可能尝试对Charlie Martin's suggestion执行某些操作并使用编辑距离度量。
答案 3 :(得分:1)
也许你可以对“单词相同”/“所有单词”进行基本计算?
e.g。 (包括一个偏移量,允许你忽略时间戳和单词'INFO',如果它总是相同的话):
def score(s1, s2, offset=26):
words1 = re.findall('\w+', s1[offset:])
words2 = re.findall('\w+', s2[offset:])
return float(len(set(words1) & set(words2)))/max(len(set(words1)), len(set(words2)))
假设:
>>> s1
'2009-04-20 00:03:57 INFO com.foo.Bar - URL:/graph?id=1234'
>>> s2
'2009-04-20 00:04:02 INFO com.foo.Bar - URL:/graph?id=asdfghjk'
>>> s3
'2009-04-20 00:05:59 INFO com.baz.abc.Accessor - Cache /path/to/some/dir hits: 3466 / 16534, 0.102818% misses'
>>> s4
'2009-04-20 00:06:00 INFO com.baz.abc.Accessor - Cache /path/to/some/different/dir hits: 4352685 / 271315, 0.004423% misses'
这会产生:
>>> score(s1,s2)
0.8571428571428571
>>> score(s3,s4)
0.75
>>> score(s1,s3)
0.066666666666666666
您仍然需要决定要比较哪些行。此外,使用set()可能会略微扭曲分数 - 一个简单算法的价格: - )
答案 4 :(得分:0)
我想知道你是否可以专注于为你定义唯一性的部分。在这种情况下,似乎定义唯一性的部分只是中间部分:
2009-04-20 00:03:57 INFO com.foo.Bar - URL:/graph?id=1234 ^---------------------^ 2009-04-20 00:05:59 INFO com.baz.abc.Accessor - Cache /path/to/some/dir hits: 3466 / 16534, 0.102818% misses ^--------------------------------^
然后我会比较这个部分,也许是使用正则表达式(只是带括号的组;如何访问像这样的子匹配依赖于语言):
/^.{20}(\w+\s+[\w\.-]+\s+-\s+\w+)/
答案 5 :(得分:0)
我认为您希望将其分解为字段,按“严重性级别”字段和下一个字段(看起来像“类”)排序。我会用Haskell:
module Main where import Data.List (nubBy, sortBy) sortAndNub s = nubBy fields2and3 $ sortBy fields2and3comp $ map words $ lines s fields2and3 a b = fieldEq 2 a b && fieldEq 3 a b fieldEq f a b = a!!f == (b!!f) fields2and3comp a b = case compare (a!!2) (b!!2) of LT -> LT GT -> GT EQ -> compare (a!!3) (b!!3) main = interact $ unlines.(map unwords).sortAndNub