Sentry如何聚合错误?

26

我正在使用 Sentry(在 Django 项目中),想知道如何使错误正确地聚合。我将某些用户操作记录为错误,因此没有基础系统异常,并使用“culprit”属性设置友好的错误名称。消息已建模,包含常见消息(“用户‘x’由于‘y’无法执行操作”),但永远不完全相同(不同的用户,不同的条件)。

Sentry 明显使用某些属性集来确定是否将错误聚合为相同的异常,但尽管查看了代码,我也无法弄清楚如何做到这一点。

有人可以帮忙告诉我需要设置哪些属性以按照我的要求进行聚合吗?

[更新1:事件分组]

以下行出现在 sentry.models.Group 中:

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

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

这很有意义-目前我设置的项目、记录器和罪犯-问题在于checksum。我会进一步调查,然而'checksum'表明二进制等价性,这永远不会起作用-必须能够将具有不同属性��相同异常实例分组吗?

[更新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]

我已经弄清楚了interfaces是指用于描述传递到Sentry事件中的数据的标准机制,并且我正在使用标准的sentry.interfaces.Messagesentry.interfaces.User接口。

这两个接口都将包含根据异常实例而异的不同数据 - 因此校验和永远不会匹配。有没有办法可以从校验和计算中排除这些内容?(或者至少是User接口值,因为它必须是不同的 - Message接口值我可以标准化。)

[更新4:解决方案]

以下是MessageUser接口的两个get_hash函数:

# 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 自定义接口并且想避免将您的接口用于分组异常,请返回空列表。)

警告!覆盖get_hash可能过度。如果您使用适当的字符串格式化,Sentry将智能地分组消息。也许您只需要正确格式化错误 https://docs.getsentry.com/hosted/clients/python/integrations/logging/ - andilabs
2个回答

20
在问题本身中可以看到我的最终更新。事件被聚合在“project”、“logger”、“culprit”和“checksum”属性的组合上。前三个属性相对容易控制,而第四个“checksum”是作为事件发送的数据类型的函数。
Sentry使用“接口”的概念来控制传递的数据结构,每个接口都带有一个get_hash实现,用于返回传递数据的哈希值。Sentry带有许多标准接口(例如“Message”、“User”、“HTTP”、“Stacktrace”、“Query”、“Exception”),它们各自都有自己的get_hash实现。默认情况下(从基类Interface继承),为空列表,这不会影响校验和。
如果没有任何有效的接口,则事件消息本身将被散列并返回为校验和,这意味着消息需要是唯一的,以便对事件进行分组。

1
在http://raven.readthedocs.org/en/latest/config/logging.html#usage上写道:“如果您使用正确的字符串格式化,Sentry将智能地分组消息。”并提供了一个示例,其中日志消息字符串格式保持不变,而参数则有所变化。这与校验和机制有什么关系? - akaihola
@akaihola - 我不知道。从代码本身来看,Message.get_hash() 方法返回的是消息本身 - 这是后格式化的。 - Hugo Rodger-Brown
2
@HugoRodger-Brown @akaihola 我相信接口sentry.interfaces.Message具有属性messageparams,并且消息是预格式化的。有关详细信息,请参见此处 - Nick
很好的发现 - 我实际上不再使用Sentry了,但知道它如何工作还是很不错的。 - Hugo Rodger-Brown
@akaihola 更新 url https://docs.getsentry.com/hosted/clients/python/integrations/logging/ - andilabs

1
我曾经遇到过一个常见的异常问题。目前我们的系统只捕获异常,我感到困惑的是为什么有些异常会合并成一个错误,而另一些则不会。根据你提供的信息,我提取了“get_hash”方法,并尝试找出引发错误的差异。我发现所有分组的错误都来自于一个自编写的异常类型,该类型具有空异常消息值。
“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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接