Not seeing username in my Rollbar People (django)
mgalgs opened this issue · 8 comments
I'm using pyrollbar with Django (configured as per the docs) but I'm only seeing user IDs, not usernames or emails:
Do I need to configure something to get usernames in my People with Django?
See also: https://docs.rollbar.com/docs/person-tracking#setup-instructions
Have the same problem
I also had this issue. I am using rollbar==0.15.1, Django==3.0.8, for reference.
The problem seems to be that the request object that the RollbarHandler has access to for Django is a socket.socket
instance and not a django.http.HttpRequest
instance, so it does not actually have access to the user information.
Line 132 in 6db0a9c
Django doesn't offer any obvious way of getting the current request, so my hacky solution is to use middleware to store the request on thread locals (a solution that has been floating around the internet for a while), and then replace rollbar.BASE_DATA_HOOK with my own function that pulls the request from thread locals and populates the rollbar data with it's own person information, and then calls the original hook.
settings.py:
...
MIDDLEWARE = (
...
'middleware.request.ThreadLocalMiddleware',
'middleware.rollbar.MyRollbarMiddleware'
)
...
middleware/request.py:
"""
threadlocals middleware
~~~~~~~~~~~~~~~~~~~~~~~
make the request object everywhere available (e.g. in model instance).
based on: http://code.djangoproject.com/wiki/CookBookThreadlocalsAndUser
Put this into your settings:
--------------------------------------------------------------------------
MIDDLEWARE_CLASSES = (
...
'django_tools.middlewares.ThreadLocal.ThreadLocalMiddleware',
...
)
--------------------------------------------------------------------------
Usage:
--------------------------------------------------------------------------
from django_tools.middlewares import get_current_request
# Get the current request object:
request = get_current_request()
--------------------------------------------------------------------------
:copyleft: 2009-2017 by the django-tools team, see AUTHORS for more details.
:license: GNU GPL v3 or above, see LICENSE for more details.
"""
try:
from threading import local
except ImportError:
from django.utils._threading_local import local
try:
from django.utils.deprecation import MiddlewareMixin
except ImportError:
MiddlewareMixin = object # fallback for Django < 1.10
_thread_locals = local()
def get_current_request():
""" returns the request object for this thread """
return getattr(_thread_locals, "request", None)
def get_current_user():
""" returns the current user, if exist, otherwise returns None """
request = get_current_request()
if request:
return getattr(request, "user", None)
class ThreadLocalMiddleware(MiddlewareMixin):
def __init__(self, get_response=None):
super(ThreadLocalMiddleware, self).__init__(get_response)
def __call__(self, request):
_thread_locals.request = request
return self.get_response(request)
middleware/rollbar.py
import rollbar
from rollbar.contrib.django.middleware import RollbarNotifierMiddleware
from .request import get_current_request
class MyRollbarMiddleware(RollbarNotifierMiddleware):
def __init__(self, get_response=None, *args, **kwargs):
super(MyRollbarMiddleware, self).__init__(get_response=get_response, *args, **kwargs)
original_rollbar_hook = rollbar.BASE_DATA_HOOK
def hook(request, data, *hook_args, **hook_kwargs):
if 'person' not in data:
django_request = get_current_request()
if django_request and hasattr(django_request, 'user'):
user = django_request.user
data['person'] = {
'id': user.id,
'username': user.username,
'email': user.email
}
return original_rollbar_hook(request, data, *hook_args, **hook_kwargs)
rollbar.BASE_DATA_HOOK = hook
Of course it would be nice if pyrollbar could handle this on its own.
It's also important to note that if you're using RollbarHandler in your logging config and not calling rollbar.init yourself, you have to pass your rollbar settings via the handler config, because RollbarHandler will call rollbar.init with whatever kwargs that it is given. I struggled with this for a while before I realized that it was not being given an access_token, as I thought setting the ROLLBAR dict would be enough.
ROLLBAR = {
'access_token': ...,
'environment': ...
}
LOGGING = {
'handlers': {
'rollbar': {
'class': 'rollbar.logger.RollbarHandler',
**ROLLBAR
},
....
}
I imagine the problem the OP was seeing is not an issue with the request object. Since they are getting the user ID they most likely have not enabled capture_username
or capture_email
which both default to false.
See: https://docs.rollbar.com/docs/python#configuration-reference
Well, after stepping through the pyrollbar codes, I found out that it requires starlette
to be installed before it can record user info (id, username, email). Of course, you have to set capture_email
and capture_username
to True
in your ROLLBAR config in settings.py
@bbrighttaer that's a bug that I fixed in #385
Great and thanks @terencehonles. I had to spend a lot of time figuring it out. I hope it gets merged soon.
Hey all!
Thanks for reporting this and all your comments. Let me clarify a few things first, as I believe we have three independent issues under the same hood.
I imagine the problem the OP was seeing is not an issue with the request object. Since they are getting the user ID they most likely have not enabled capture_username or capture_email which both default to false.--
See: https://docs.rollbar.com/docs/python#configuration-reference
Thanks @terencehonles. Yes, it looks like this could be it.
@mgalgs @zavada are you still occurring the issue? Have you tried the solution suggested by @terencehonles in the #347 (comment) ?
The problem seems to be that the request object that the RollbarHandler has access to for Django is a socket.socket instance and not a django.http.HttpRequest instance, so it does not actually have access to the user information.
Thanks @tfaris for the code snippets! You're right, there is no easy way to access Django request objects from a global namespace. Your solution looks reasonable and we actually provided quite a similar one for Starlette (based on local context) and it may be reasonable to support Django in a similar way with using threads. In fact, it is already on our backlog and we plan to support it :)
Well, after stepping through the pyrollbar codes, I found out that it requires starlette to be installed before it can record user info (id, username, email). Of course, you have to set capture_email and capture_username to True in your ROLLBAR config in settings.py
@bbrighttaer this issue was originally reported before Rollbar added Starlette support. We have PR #385 (already approved, should be released soon) regarding your problem. I believe that the problem you are referring to is not related to the original issue.
Great and thanks @terencehonles. I had to spend a lot of time figuring it out. I hope it gets merged soon.
Sorry for the inconvenience @bbrighttaer ! To save your time next time, I suggest you downgrade the SDK version to verify if the issue only occurs due to the new version. You can also report any issues with the SDK you have on GitHub or support@rollbar.com
Thanks to everyone for the contribution! I'm waiting for your confirmation but I believe everything is solved here now and we are ready to close this issue :)
@mgalgs @zavada are you still occurring the issue? Have you tried the solution suggested by @terencehonles in the #347 (comment) ?
This looks like the fix! Just pushed it out to production, will report back if I'm still not seeing usernames. Thanks!