python - 如何向 Sentry 报告当前登录的用户?

标签 python sentry raven

我在面向用户的 Python/Pyramid 网络应用程序上使用 Sentry (Raven 3.4.1)。 Sentry 似乎有能力跟踪哪些用户以及有多少用户遇到了某种异常。 (例如参见 Sentry 6.2.0 changelog ,其中提到:“记录了用户数据的流现在将显示发生事件的唯一用户数。”) 我如何将此信息提供给 Raven,以便它显示在 Sentry 中?

如果我手动将异常传递给 Raven,我只能这样做吗?现在,我正在使用 SentryHandler 日志记录处理程序,附加到根记录器,并在 PasteDeploy 管道中使用 egg:raven#raven 过滤器。 (密切关注官方Raven configuration docs for Pyramid。)

有什么好的技巧可以将这些信息传递给 Raven?我是否可以在我的堆栈底部的某处设置一个具有特定名称的局部变量,一旦我加载了用户的 session ,Raven 就会自动拾取它?这里的最佳做法是什么?

我怀疑this与我正在尝试做的事情有关,但我在 Raven 文档中找不到任何相关信息。

最佳答案

我发现这样做的唯一方法是覆盖 Raven 的一些内部方法。

基本思路是我们要修改Raven的Sentry类的handle_exception()方法。在那里,我可以注入(inject)问题中已经提到的 sentry.interfaces.User 接口(interface)。 为此,我需要自己的过滤器工厂,然后我可以使用它来代替 Raven 附带的默认粘贴过滤器,它使用我自己的 Sentry 子类。

在我的项目中,我有一个文件sentry.py:

from raven.middleware import Sentry
from raven.utils.wsgi import get_current_url, get_headers, get_environ
from raven.base import Client

def sentry_filter_factory(app, global_conf, **kwargs):
    """ Overwritten just to override the 'Sentry' class being used. """ 
    client = Client(**kwargs)
    return UserEnhancedSentry(app, client)

class UserEnhancedSentry(Sentry):
    """ Overriding raven.middleware.Sentry's handle_exception() method to inject
        the sentry.interfaces.User interface. This relies on the data previously
        being injected into the environ by our custom tween. """
    def handle_exception(self, environ):
        data={}
        data['sentry.interfaces.Http'] = {
            'method': environ.get('REQUEST_METHOD'),
            'url': get_current_url(environ, strip_querystring=True),
            'query_string': environ.get('QUERY_STRING'),
            # TODO
            # 'data': environ.get('wsgi.input'),
            'headers': dict(get_headers(environ)),
            'env': dict(get_environ(environ)),
        }
        if environ.has_key('myapp.user'):
            user_id, username, email = environ.get('myapp.user')
            ip_address = environ.get('HTTP_X_FORWARDED_FOR', environ.get('REMOTE_ADDR'))
            data['sentry.interfaces.User'] = {
                'id': user_id,
                'username': username,
                'email': email,
                'ip_address': ip_address,
            }
        event_id = self.client.captureException(data=data)
        return event_id

在我的 setup.py 中,我将过滤器工厂声明为入口点:

entry_points = """\
[paste.app_factory]
main = myapp:main
[paste.filter_app_factory]
raven = myapp.sentry:sentry_filter_factory
""",

现在我可以使用入口点在我的配置 .ini 文件中声明一个过滤器并将其集成到粘贴管道中,就像 Paste docs 中描述的那样:

[pipeline:main]
pipeline =
    sentry
    myapp

[filter:sentry]
use = egg:myapp#raven
dsn = https://abc:def@app.getsentry.com/123

现在,每当 Sentry 过滤器捕捉到异常时,它不仅会存储有关 HTTP 请求的数据,还会存储有关用户的数据——假设它可以在 environ 中找到有关该信息的信息。我现在所要做的就是从那里的 session 中注入(inject)用户信息,这是我使用自定义补间所做的:

def sentry_user_tween_factory(handler, registry):
    """ Returns a tween that does nothing but enhance the environ by information about the currently
        logged in user, which will be useful for the Sentry report in case there's an exception """ 
    def sentry_user_tween(request):
        user = request.session.get('user')
        if user:
            request.environ['myapp.user'] = (user.token, user.name, user.email)
        else:
            request.environ['myapp.user'] = (0, 'anonymous', None)
        # proceed with the next tween/handler
        response = handler(request)
        return response
    return sentry_user_tween

config.add_tween('myapp.sentry_user_tween_factory')

这一切看起来复杂得不合理,但我很高兴我终于找到了一种让它发挥作用的方法。

关于python - 如何向 Sentry 报告当前登录的用户?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18596881/

相关文章:

python - 如何在 Pyramid 中为友好的错误页面配置异常 View ,但仍将错误传递给记录器?

django - 当根记录器配置为使用 raven 时,Celery 定期任务不会运行

python - 如何从变量或文本将日期设置到QDateEdit?

python - 如何修复计数查询 mysql 中的输出(flask)

Python 模块初始化顺序?

javascript - 覆盖 Meteor 的异常处理

.net - Azure 上的 Sentry 发布跟踪

javascript - _oldOnerrorHandler 未定义; if 语句仍然运行

python - 为 raven-python( Sentry 客户端)添加一个钩子(Hook)到 Gunicorn

python - Pandas:将一列的值统一为另一列的每个值