如何向 Sentry 报告当前登录的用户?
Posted
技术标签:
【中文标题】如何向 Sentry 报告当前登录的用户?【英文标题】:How do I report the currently logged in user to Sentry? 【发布时间】:2013-09-03 16:10:46 【问题描述】:我在面向用户的 Python/Pyramid webapp 上使用 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?我是否可以在我的堆栈底部某处设置一个具有特定名称的局部变量,一旦我加载了用户的会话,Raven 会自动拾取它?这里的最佳做法是什么?
我怀疑 this 与我正在尝试做的事情有关,但我在 Raven 文档中找不到任何相关信息。
【问题讨论】:
【参考方案1】:我发现这样做的唯一方法是覆盖 Raven 的一些内部方法。
基本思想是我们要修改Raven的Sentry
类上的handle_exception()
方法。在那里,我可以注入问题中已经提到的sentry.interfaces.User
接口。
为此,我需要自己的过滤器工厂,然后我可以使用它来代替 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
中找到有关该信息的信息。我现在要做的就是从那里的会话中注入用户信息,我正在使用自定义补间:
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')
这一切看起来都非常复杂,但我很高兴我终于找到了让它发挥作用的方法。
【讨论】:
返回错误:LookupError: Ambiguous section names ['app:main', 'pipeline:main'] for section 'main'(前缀为 'app' 或 'application' 或 'composite' 或'composit' 或 'pipeline' 或 'filter-app')在配置中找到 ..../development.ini @PaulYin 这是您遇到的错误吗?好像和上面的没有关系。显然,您的 PYTHONPATH 中有多个“主要”部分,但未指定您在 development.ini 中某处指的是哪一个。如果这对您没有帮助,请为它打开一个新问题!以上是关于如何向 Sentry 报告当前登录的用户?的主要内容,如果未能解决你的问题,请参考以下文章