Строки, которые выделяются в файле, но не являются точными дубликатами - PullRequest
3 голосов
/ 20 апреля 2009

Я прочесываю лог-файл веб-приложения для выделенных операторов.

Большинство строк похожи и неинтересны. Я бы пропустил их через Unix uniq, но это ничего не фильтрует, так как все строки немного отличаются: у всех разная временная метка, похожие операторы могут печатать другой идентификатор пользователя и т. Д.

Какой способ и / или инструмент, чтобы получить только линии, которые заметно отличаются от любых других? (Но, опять же, не точные дубликаты)

Я думал о том, чтобы поиграть с difflib в Python, но это похоже на различие двух файлов, а не всех пар строк в одном файле.

[EDIT]

Я предполагал, что решение даст оценку уникальности для каждой строки. Таким образом, под «заметно отличающимся» я имел в виду, я выбираю порог, который должен превышать показатель уникальности для любой строки, которая будет включена в вывод.

Исходя из этого, если есть другие жизнеспособные способы его определения, пожалуйста, обсудите. Кроме того, метод не должен иметь 100% точность и отзыв.

[/ EDIT]

Примеры:

Я бы предпочел ответы как можно более общего назначения. Я знаю, что могу убрать метку времени в начале. Разбор конца более сложен, так как его язык может быть совершенно не похож ни на что в этом файле. Такого рода детали объясняют, почему я раньше избегал конкретных примеров, а потому, что некоторые люди спрашивали ...

Аналог 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

В случае «Разное 1» я хотел бы, чтобы обе строки возвращались, но не такие, как они. Другими словами, эти две линии являются разными типами (тогда я могу позже запросить только статистически редкие типы линий). С одной стороны, расстояние редактирования между этими двумя значениями намного больше.

Ответы [ 6 ]

3 голосов
/ 20 апреля 2009

Определите «заметно отличается». Затем взгляните на «редактировать расстояние» меры .

2 голосов
/ 20 апреля 2009

Я не знаю, какой инструмент для вас, но если бы Я собирался накатить свой собственный, я бы подошел к нему так:

Предположительно, строки журнала имеют четко определенную структуру, нет? Так

  • разобрать строки в этой структуре
  • написать несколько очень простых фильтров релевантности (функции, которые просто возвращают простое число из проанализированной структуры)
  • пропустить проанализированные строки через набор фильтров и сократить на основе общего балла
  • возможно отсортировать оставшиеся строки в различные ячейки по результатам дополнительных фильтров
  • генерация отчетов, дампов в файлы или другой вывод

Если вы знакомы с инструментом Unix procmail, я предлагаю аналогичный режим, настроенный для ваших данных.


Как закерирует примечания в комментариях, ваши фильтры обычно игнорируют метки времени (и, возможно, IP-адрес) и просто концентрируются на контенте: например, действительно длинные http-запросы могут представлять атаку ... или все, что относится к вашему домену.

Ваши фильтры биннинга могут быть такими же простыми, как хеш для нескольких выбранных полей, или вы можете попытаться что-то сделать с предложением Чарли Мартина и использовать редактирование мер расстояния.

2 голосов
/ 20 апреля 2009

Вы можете попробовать немного кода, который подсчитывает слова, а затем сортирует строки по тем, у кого наименее распространенные слова.

Если это не помогает, вы можете добавить некоторые смарты, чтобы отфильтровать метки времени и числа.

Ваша проблема похожа на предыдущий вопрос о генерации сводок новостей .

1 голос
/ 21 апреля 2009

Возможно, вы могли бы сделать базовый расчет "слова одинаковые" / "все слова"?

например. (включая смещение, позволяющее игнорировать метку времени и слово «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 () может немного исказить оценки - цена простого алгоритма: -)

0 голосов
/ 21 апреля 2009

Я думаю, что вы хотите разбить это на поля, отсортировать по полю «уровень серьезности» и следующему полю (выглядит как «класс»). Я бы использовал 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
0 голосов
/ 21 апреля 2009

Интересно, не могли бы вы сосредоточиться на той части, которая определяет уникальность для вас? В этом случае кажется, что часть, определяющая уникальность, является только средней частью:

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+)/
...