Подтвердить что ты не робот

Как Sentry агрегирует ошибки?

Я использую Sentry (в проекте django), и я хотел бы знать, как я могу правильно собрать ошибки. Я регистрирую определенные действия пользователя как ошибки, поэтому нет основного системного исключения, и я использую атрибут culprit для установки дружественного имени ошибки. Сообщение шаблонизировано и содержит общее сообщение ( "Пользователь" x "не смог выполнить действие, потому что" y "), но никогда не бывает точно таким же (разные пользователи, разные условия).

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

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

[ОБНОВЛЕНИЕ 1: группировка событий]

Эта строка появляется в sendry.models.Group:

class Group(MessageBase):
    """
    Aggregated message which summarizes a set of Events.
    """
    ...

    class Meta:
        unique_together = (('project', 'logger', 'culprit', 'checksum'),)
    ...

Что имеет смысл - проект, регистратор и виновник, который я устанавливаю на данный момент - проблема checksum. Я буду исследовать далее, однако "контрольная сумма" предполагает, что бинарная эквивалентность, которая никогда не сработает - должна быть возможность группировать экземпляры одного и того же исключения с атрибутами differenct?

[ОБНОВЛЕНИЕ 2: контрольные суммы событий]

Контрольная сумма события исходит из метода sentry.manager.get_checksum_from_event:

def get_checksum_from_event(event):
    for interface in event.interfaces.itervalues():
        result = interface.get_hash()
        if result:
            hash = hashlib.md5()
            for r in result:
                hash.update(to_string(r))
            return hash.hexdigest()
    return hashlib.md5(to_string(event.message)).hexdigest()

Следующая остановка - откуда происходит событие interfaces?

[ОБНОВЛЕНИЕ 3: интерфейсы событий]

Я разработал, что interfaces ссылается на стандартный механизм описания данных, передаваемых в часовые события, и что я использую стандартные sentry.interfaces.Message и sentry.interfaces.User.

Оба они будут содержать разные данные в зависимости от экземпляра исключения - и поэтому контрольная сумма никогда не будет соответствовать. Есть ли способ, который я могу исключить из расчета контрольной суммы? (Или, по крайней мере, значение интерфейса User, поскольку это должно быть другим - значение интерфейса Message, которое я мог бы стандартизировать.)

[ОБНОВЛЕНИЕ 4: решение]

Вот две функции get_hash для интерфейсов Message и User соответственно:

# sentry.interfaces.Message
def get_hash(self):
    return [self.message]

# sentry.interfaces.User
def get_hash(self):
    return []

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

Я ответил на свой собственный вопрос здесь, но, надеюсь, мое исследование полезно другим, имеющим ту же проблему. (В стороне, я также представил запрос на тягу к документации Sentry как часть этого; -))

(Обратите внимание на тех, кто использует/расширяя Sentry с пользовательскими интерфейсами - если вы хотите, чтобы ваш интерфейс не использовался для группировки исключений, верните пустой список.)

4b9b3361

Ответ 1

Посмотрите мое последнее обновление в самом вопросе. События объединяются в комбинации свойств "project", "logger", "culprit" и "checksum". Первые три из них относительно просты в управлении - четвертая, контрольная сумма - это функция типа данных, отправленных как часть события.

Sentry использует концепцию "интерфейсов" для управления структурой передаваемых данных, и каждый интерфейс поставляется с реализацией get_hash, которая используется для возврата хэш-значения для переданных данных. Sentry поставляется с количество стандартных интерфейсов ( "Message", "User", "HTTP", "Stacktrace", "Query", "Exception" ), и каждый из них имеет собственную реализацию get_hash. По умолчанию (унаследованный от базового класса интерфейса) есть пустой список, который не влияет на контрольную сумму.

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

Ответ 2

У меня была общая проблема с Exceptions. В настоящее время наша система захватывает только исключения, и я был смущен, почему некоторые из них слились в одну ошибку, другие - нет. С вашей информацией выше я добавил методы "get_hash" и попытался найти различия, "поднимающие" мои ошибки. То, что я узнал, состоит в том, что сгруппированные ошибки исходили из самонаписанного типа исключения, у которого есть пустое значение Exception.message.

вывод get_hash:

[<class 'StorageException'>, StorageException()]

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

[<class 'jinja2.exceptions.UndefinedError'>, UndefinedError('dict object has no attribute LISTza_*XYZ*',)]

Различные сообщения об исключении запускают разные отчеты, в моем случае слияние было вызвано отсутствием значения Exception.message.

Реализация:

class StorageException(Exception):

def __init__(self, value):
    Exception.__init__(self)
    self.value = value