rollbar/pyrollbar

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:

image

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.

request = getattr(record, "request", None) or rollbar.get_request()

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.

bxsx commented

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!