Giter VIP home page Giter VIP logo

raygun4py's Issues

How to stop sending environment variables with errors with flask

I've configured Raygun with flask as per the installation instructions:

from flask import Flask, current_app
from raygun4py.middleware import flask

app = Flask(__name__)

flask.Provider(app, 'your_apikey').attach()

How do you set the config options with this so that the environment variables don't get sent with the exception?

Update Documentation with Best Practices for subclassing an exception

This would be really helpful to new users, or users that are migrating from Python2 to Python3.

It would be nice to have an example of a subclassed Exception in the documentation, along with best practices for using the subclassed Exception and how those affect what shows up in Raygun.

After using Raygun for some time, we still find things like unique ID's in the message field, which prevents the Raygun interface from merging these as they come in.

Some helpful posts for us getting our reporting cleaned up are Proper way to declare custom exceptions in modern python and How to make a custom exception class picklable The latter, in particular, is helpful when stack overflow errors are generated while debugging an app that also reports to Raygun.

Update Documentation related to callback functions

If I have time, I'll open an MR for this later. Logging here though...

The on_before_send function on the RaygunSender and the before_send_callback option in the config are not immediately clear when reading the docs. It was only after I read the code that I understood that these are related.

It would be nice to ideally change the online documentation to split up the "Config and data functions" into two separate sections:

  1. Rename Config to "Passing a config object to the RaygunSender client"
    a. Lead with an example of passing in one large config object with all options included.
    b. Inside each option, outline the types of data you can pass, with examples
  2. Create a section called "Calling functions on the instantiated RaygunSender client"
    a. Show examples like client.on_before_send(callback) with similar example in here.

Accessing directly optional request argument in WSGI middleware

QUERY_STRING is an optional argument for environ, hence should probably be accessed using get. Moreover, I think exceptions should not be just pass-ed. Currently, if QUERY_STRING is absent, KeyError will result in request be equal to {} which will throw another exception when we try to access headers.

Valid for both python2 and python3

python2/raygun4py/middleware/wsgi.py:

try:
    request = {
        'httpMethod': environ['REQUEST_METHOD'],
        'url': environ['PATH_INFO'],
        'ipAddress': environ['REMOTE_ADDR'],
        'hostName': environ['HTTP_HOST'].replace(' ', ''),
        'queryString': environ['QUERY_STRING'],
        'headers': {},
        'form': {},
        'rawData': {}
    }
except Exception:
    pass

for key, value in environ.items():
    if key.startswith('HTTP_'):
       request['headers'][key] = value

WSGI middleware exception on close() looks broken.

Just on visual inspection the code at:

looks broken.

        finally:
            if chunk and hasattr(chunk, 'close') and callable(chunk.close):
                try:
                    chunk.close()
                except Exception as e:
                    request = build_request(environ)
                    self.send_exception(exception=e, request=request)

Shouldn't that be calling self.sender.send_exception()?

You also aren't reraising the exception.

Technically you also shouldn't be checking to see if close() is callable and instead should just call it. By checking to see if it is callable you are hiding to a higher layer that the close() method wasn't callable, which is actually an error in itself as far as the code satisfying the WSGI specification.

AttributeError: 'NoneType' object has no attribute 'set_user'

Recently upgraded from 3.1.6 to 4.1.0 and it looks like RaygunMessageBuilder.set_request_details is returning None in some situations, causing exception sending to fail with an AttributeError: 'NoneType' object has no attribute 'set_user'

https://github.com/MindscapeHQ/raygun4py/blob/v4.1.0/python3/raygun4py/raygunprovider.py#L124-L125
https://github.com/MindscapeHQ/raygun4py/blob/v4.1.0/python3/raygun4py/raygunmsgs.py#L92-L97

Stacktrace:

/usr/local/lib/python3.6/site-packages/raygun4py/raygunprovider.py:96: in send_exception
    message = self._create_message(errorMessage, tags, custom_data, http_request, extra_environment_data)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <raygun4py.raygunprovider.RaygunSender object at 0x7f6dbbbf0320>, raygunExceptionMessage = <raygun4py.raygunmsgs.RaygunErrorMessage object at 0x7f6dbbbccf60>
tags = ['django-novars'], user_custom_data = None
http_request = {'form': {}, 'headers': {'CONTENT_TYPE': 'application/octet-stream', 'HTTP_COOKIE': '', 'PATH_INFO': '/', 'QUERY_STRING': '', ...}, 'hostName': 'testserver', 'httpMethod': 'GET', ...}
extra_environment_data = {'frameworkVersion': '2.1.2'}

    def _create_message(self, raygunExceptionMessage, tags, user_custom_data, http_request, extra_environment_data):
        return raygunmsgs.RaygunMessageBuilder().new() \
            .set_machine_name(socket.gethostname()) \
            .set_version(self.userversion) \
            .set_client_details() \
            .set_exception_details(raygunExceptionMessage) \
            .set_environment_details(extra_environment_data) \
            .set_tags(tags) \
            .set_customdata(user_custom_data) \
>           .set_request_details(http_request) \
            .set_user(self.user) \
            .build()
E       AttributeError: 'NoneType' object has no attribute 'set_user'

/usr/local/lib/python3.6/site-packages/raygun4py/raygunprovider.py:124: AttributeError

Possible bug in RaygunSender._post?

It appears that the following line encounters a NameError when attempts to refer to log on the RaygunSender class without using the class or self to make the reference.

https://github.com/MindscapeHQ/raygun4py/blob/master/python2/raygun4py/raygunprovider.py#L167

It appears to me that this line should read self.log.error(...) as opposed to log.error(...).

I hit this, but I'm doing some rather hackish things with RaygunSender at the moment, and so I'm not confident the bug is on the raygun4py side as opposed to within my own usage of it.

Here's the traceback:

Traceback (most recent call last):
  File "code/manage.py", line 8, in <module>
    execute_from_command_line(sys.argv)
  File "/var/projects/myproject/virtualenv/local/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 354, in execute_from_command_line
    utility.execute()
  File "/var/projects/myproject/virtualenv/local/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 346, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/var/projects/myproject/virtualenv/local/local/lib/python2.7/site-packages/django/core/management/base.py", line 394, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/var/projects/myproject/virtualenv/local/local/lib/python2.7/site-packages/django/core/management/base.py", line 445, in execute
    output = self.handle(*args, **options)

  ... snip a few frames that basically just call myinstance.save() ...

  File "/var/projects/myproject/virtualenv/local/local/lib/python2.7/site-packages/django/db/models/base.py", line 734, in save
    force_update=force_update, update_fields=update_fields)
  File "/var/projects/myproject/virtualenv/local/local/lib/python2.7/site-packages/django/db/models/base.py", line 762, in save_base
    updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
  File "/var/projects/myproject/virtualenv/local/local/lib/python2.7/site-packages/django/db/models/base.py", line 827, in _save_table
    forced_update)
  File "/var/projects/myproject/virtualenv/local/local/lib/python2.7/site-packages/django/db/models/base.py", line 877, in _do_update
    return filtered._update(values) > 0
  File "/var/projects/myproject/virtualenv/local/local/lib/python2.7/site-packages/django/db/models/query.py", line 580, in _update
    return query.get_compiler(self.db).execute_sql(CURSOR)
  File "/var/projects/myproject/virtualenv/local/local/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 1062, in execute_sql
    cursor = super(SQLUpdateCompiler, self).execute_sql(result_type)
  File "/var/projects/myproject/virtualenv/local/local/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 829, in execute_sql
    sql, params = self.as_sql()
  File "/var/projects/myproject/virtualenv/local/local/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 1030, in as_sql
    val = field.get_db_prep_save(val, connection=self.connection)
  File "/var/projects/myproject/virtualenv/local/local/lib/python2.7/site-packages/django/db/models/fields/__init__.py", line 710, in get_db_prep_save
    prepared=False)
  File "/var/projects/myproject/virtualenv/local/local/lib/python2.7/site-packages/django/db/models/fields/__init__.py", line 1482, in get_db_prep_value
    value = self.get_prep_value(value)
  File "/var/projects/myproject/virtualenv/local/local/lib/python2.7/site-packages/django/db/models/fields/__init__.py", line 1474, in get_prep_value
    RuntimeWarning)
  File "/usr/lib/python2.7/logging/__init__.py", line 1720, in _showwarning
    logger.warning("%s", s)
  File "/usr/lib/python2.7/logging/__init__.py", line 1171, in warning
    self._log(WARNING, msg, args, **kwargs)
  File "/usr/lib/python2.7/logging/__init__.py", line 1278, in _log
    self.handle(record)
  File "/usr/lib/python2.7/logging/__init__.py", line 1288, in handle
    self.callHandlers(record)
  File "/usr/lib/python2.7/logging/__init__.py", line 1328, in callHandlers
    hdlr.handle(record)
  File "/usr/lib/python2.7/logging/__init__.py", line 751, in handle
    self.emit(record)
  File "/var/projects/myproject/code/myproject/logging_config.py", line 84, in emit
    self.sender.send_exception(exc_info=(exc_type, exc_value, None), frames=reversed(inspect.getouterframes(src_frame)))
  File "/var/projects/myproject/code/myproject/logging_config.py", line 32, in send_exception
    return raygunprovider.RaygunSender.send_exception(self, *args, **kwargs)
  File "/var/projects/myproject/virtualenv/local/local/lib/python2.7/site-packages/raygun4py/raygunprovider.py", line 109, in send_exception
    return self._post(message)
  File "/var/projects/myproject/virtualenv/local/local/lib/python2.7/site-packages/raygun4py/raygunprovider.py", line 167, in _post
    log.error(e)
NameError: global name 'log' is not defined

RaygunHandler fails when logging outside of an exception context.

Looking at the current Raygun logging handler:

class RaygunHandler(logging.Handler):
def __init__(self, api_key, version=None):
logging.Handler.__init__(self)
self.sender = RaygunSender(api_key)
self.version = version
def emit(self, record):
userCustomData = {
"Logger Message": record.msg
}
self.sender.send_exception(userCustomData=userCustomData)

it calls send_exception() unconditionally, and that function expects to run within an exception context.

However, if I add the Raygun handler to my logging hierarchy then it’s likely to be invoked for non-exception contexts as well which causes the following exception:

  File "/usr/local/lib/python3.7/site-packages/some_package/some_file.py", line X, in some_function
    logger.error("Here be an error message")
  File "/usr/local/lib/python3.7/logging/__init__.py", line 1407, in error
    self._log(ERROR, msg, args, **kwargs)
  File "/usr/local/lib/python3.7/logging/__init__.py", line 1514, in _log
    self.handle(record)
  File "/usr/local/lib/python3.7/logging/__init__.py", line 1524, in handle
    self.callHandlers(record)
  File "/usr/local/lib/python3.7/logging/__init__.py", line 1586, in callHandlers
    hdlr.handle(record)
  File "/usr/local/lib/python3.7/logging/__init__.py", line 894, in handle
    self.emit(record)
  File "/usr/local/lib/python3.7/site-packages/raygun4py/raygunprovider.py", line 178, in emit
    self.sender.send_exception(userCustomData=userCustomData)
  File "/usr/local/lib/python3.7/site-packages/raygun4py/raygunprovider.py", line 94, in send_exception
    errorMessage = raygunmsgs.RaygunErrorMessage(exc_type, exc_value, exc_traceback, options)
  File "/usr/local/lib/python3.7/site-packages/raygun4py/raygunmsgs.py", line 133, in __init__
    self.className = exc_type.__name__
AttributeError: 'NoneType' object has no attribute '__name__'

As per documentation, a Handler is expected to ignore messages below it’s current logging level (docs). Because there’s no dedicated “exception” level I think that in this case the Raygun handler should also ignore messages that don’t run in an exception context.

Thus, I’d like to propose the following change:

class RaygunHandler(logging.Handler):

    def emit(self, record):
        exc_type, _, _ = exc_info = sys.exc_info()
        if exc_type is not None:
            userCustomData = {
                "Logger Message": record.msg
            }
            self.sender.send_exception(exc_info=exc_info, userCustomData=userCustomData)

Graceful degradation of error logging

Hi all,

So I was just tailing our production logs and found a few of these errors:

172.17.42.1 - - [06/Oct/2016:12:29:45] "" 200 - "" ""
Exception in thread Thread-8:
Traceback (most recent call last):
  File "/usr/lib64/python2.7/threading.py", line 811, in __bootstrap_inner
    self.run()
  File "/usr/lib64/python2.7/threading.py", line 764, in run
    self.__target(*self.__args, **self.__kwargs)
  File "/var/www/a8_product/database/__init__.py", line 83, in _connection
    return f(*args, **kwargs)
  File "/var/www/a8_product/controllers/briefs/refresh.py", line 121, in _refresh_brief_articles
    populate_brief(db_brief, event=event)
  File "/var/www/a8_product/controllers/briefs/refresh.py", line 29, in populate_brief
    audit_brief(db_brief, event)
  File "/var/www/a8_product/controllers/briefs/audit.py", line 15, in audit_brief
    raygun_log(e.message, custom_data={'brief_uuid': str(db_brief.uuid)})
  File "/var/www/a8_product/lib/raygun_logging.py", line 10, in raygun_log
    return _raygun_log(*args, **kwargs)
  File "/usr/lib/python2.7/site-packages/hg_logging/raygun/logger.py", line 34, in raygun_log
    provider.sender.send_exception(**kwargs)
  File "/usr/lib/python2.7/site-packages/raygun4py/raygunprovider.py", line 106, in send_exception
    message = self._create_message(errorMessage, tags, custom_data, http_request, extra_environment_data)
  File "/usr/lib/python2.7/site-packages/raygun4py/raygunprovider.py", line 131, in _create_message
    .set_environment_details(extra_environment_data) \
  File "/usr/lib/python2.7/site-packages/raygun4py/raygunmsgs.py", line 35, in set_environment_details
    "architecture": platform.architecture()[0],
  File "/usr/lib64/python2.7/platform.py", line 1111, in architecture
    output = _syscmd_file(executable, '')
  File "/usr/lib64/python2.7/platform.py", line 1054, in _syscmd_file
    stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
  File "/usr/lib64/python2.7/site-packages/gevent/subprocess.py", line 534, in __init__
    reraise(*exc_info)
  File "/usr/lib64/python2.7/site-packages/gevent/subprocess.py", line 503, in __init__
    restore_signals, start_new_session)
  File "/usr/lib64/python2.7/site-packages/gevent/subprocess.py", line 1112, in _execute_child
    self.pid = fork_and_watch(self._on_child, self._loop, True, fork)
  File "/usr/lib64/python2.7/site-packages/gevent/os.py", line 341, in fork_and_watch
    watcher = loop.child(pid, ref=ref)
  File "gevent/corecext.pyx", line 511, in gevent.corecext.loop.child (gevent/gevent.corecext.c:9881)
  File "gevent/corecext.pyx", line 1876, in gevent.corecext.child.__init__ (gevent/gevent.corecext.c:32615)
TypeError: child watchers are only available on the default loop

This particular trace is from a background thread, launched as a part of a web request which altered an object which we audit out S3. Obviously have a bug somewhere that is causing that process to fail, now I see this error is stopping the original bug being recorded in raygun 👎

I'm in a bit of bind here, looks like the gevent bug (see warning at the top: http://www.gevent.org/gevent.subprocess.html) is a limitation that won't be fixed. I'm trying porting our background threads over to gevent but I figured I'd suggest a new feature too.

So we never really use the architecture stuff when debugging and I'd much rather have the error with less detail than no error whatsoever. So can I ask for either the ability to turn off/on feature enrichment manually and/or to have it gracefully fallback so it just get's the minimum it needs but can still log the error.

Cheers,
Alex

UnicodeEncodeError when traceback contains non-ascii character

Here's what I got:

Traceback (most recent call last):
  File "/home/fiatjaf/comp/wft/model-updates/reader.py", line 49, in process_messages
    done = process_message(payload)
  File "/home/fiatjaf/comp/wft/model-updates/reader.py", line 74, in process_message
    tags=['boardSetup']
  File "/home/fiatjaf/comp/wft/model-updates/venv/local/lib/python2.7/site-packages/raygun4py/raygunprovider.py", line 76, in send_exception
    errorMessage = raygunmsgs.RaygunErrorMessage(exc_type, exc_value, exc_traceback, options)
  File "/home/fiatjaf/comp/wft/model-updates/venv/local/lib/python2.7/site-packages/raygun4py/raygunmsgs.py", line 129, in __init__
    'localVariables': self._get_locals(frame[0]) if 'transmitLocalVariables' in options and options['transmitLocalVariables'] is True else None
  File "/home/fiatjaf/comp/wft/model-updates/venv/local/lib/python2.7/site-packages/raygun4py/raygunmsgs.py", line 145, in _get_locals
    result[key] = str(localVars[key])
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9' in position 2: ordinal not in range(128

My function call does not show entirely there, but it is

            raygun.set_user(payload['username'])
            raygun.send_exception(
                exc_info=sys.exc_info(),
                userCustomData={'board_id': payload['board_id']},
                tags=['boardSetup']
            )

So, there is nothing non-ascii there, but I know there would be non-ascii characters in the traceback if it was going to be printed to stdout (there is a variable holding the value idéias, which has the character u'\xe9' in position 2 as mentioned in the error above), so the problem is probably there.

Crashed on logging error from a POST in Django

I was testing the provider and forced an exception handling a POST using Django and Django REST Framework and it triggered the exception masked behind a fault:

You cannot access body after reading from request's data stream

Going into the code, this appears as "request.body" is being accessed. I fixed locally for test purposes favoring request.data or by just removing the data in favor of the fallback when request doesn't respond to body.

Documentation for Custom grouping logic has incorrect definition of the callback parameter

The documentation for Custom grouping logic states that:

The callback's one parameter is an instance of RaygunMessage (python[2/3]/raygunmsgs.py), and the callback should return a string.

But it appears that this is not the case. Instead it appears to be a dict object which is returned from RaygunSender._transform_message as a result of calling utilities.filter_keys.

The code at utilities.py Line 16 has this:

if isinstance(object, raygunmsgs.RaygunMessage):
        iteration_target = object.__dict__

which is the point where the RaygunMessage is converted to a dict.

The sample code return raygun_message.get_error().message[:100] therefore crashes with an AttributeError:

AttributeError: 'dict' object has no attribute 'get_error'

This however will work:

return raygun_message['details']['error'].message[:100]

The raygun_message['details']['error'] accesses the instance of RaygunErrorMessage

UnicodeDecodeError if local args contains byte string

With the python 2 implementation, I'm getting a UnicodeDecodeError when trying to use send_exception. Looks like the jsonpickle.encode() is blowing up, specifically when trying to encode the raygunMessage['details']['error'].stackTrace list. One of the stackTrace items has a localVariables dict with a key verification that contains the following value: \x8d\x80\x92uK!M\xed\x16u3\x0b\xcc\xb1r1N\xdfs\x13,>\x01\x87\xae\xd0E\xe8\x02\x05\xd0d\xaa\xbd\xc9wc}\x1b\xbd\x06\xf8R3\xb4\xf3_F\x1b\xac}\xba\x11gul%v9\xf8\x0cp\x03\t

If the config option transmitLocalVariables is set to False, the issue goes away, as you might expect. However, I'd really like to be able to send all local vars!

AttributeError: 'Provider' object has no attribute '_is_coroutine'

When I try to upgrade Django 3.2.16 to 4.1.4, I'm getting

AttributeError: 'Provider' object has no attribute '_is_coroutine'
  File "django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "django/utils/deprecation.py", line 131, in __call__
    if self._is_coroutine:

I'm using the following in my list of MIDDLEWAREs:

MIDDLEWARE = [
    ...
    'raygun4py.middleware.django.Provider'
]

AttributeError: class RaygunErrorMessage has no attribute '__mro__'

Using old-style classes causes this error:

Traceback (most recent call last):
  File "[..]/env/lib/python2.7/site-packages/[..]/raygun/logger.py", line 34, in raygun_log
    provider.sender.send_exception(**kwargs)
  File "[..]/env/lib/python2.7/site-packages/raygun4py/raygunprovider.py", line 110, in send_exception
    return self._post(message)
  File "[..]/env/lib/python2.7/site-packages/raygun4py/raygunprovider.py", line 156, in _post 
    json = jsonpickle.encode(raygunMessage, unpicklable=False)
  File "[..]/env/lib/python2.7/site-packages/jsonpickle/__init__.py", line 131, in encode
    warn=warn)
  File "[..]/env/lib/python2.7/site-packages/jsonpickle/pickler.py", line 42, in encode 
    return backend.encode(context.flatten(value, reset=reset))
  File "[..]/env/lib/python2.7/site-packages/jsonpickle/pickler.py", line 153, in flatten
    return self._flatten(obj)
  File "[..]/env/lib/python2.7/site-packages/jsonpickle/pickler.py", line 157, in _flatten
    return self._pop(self._flatten_obj(obj))
  File "[..]/env/lib/python2.7/site-packages/jsonpickle/pickler.py", line 173, in _flatten_obj
    return flatten_func(obj)
  File "[..]/env/lib/python2.7/site-packages/jsonpickle/pickler.py", line 425, in _flatten_dict_obj
    flatten(k, v, data)
  File "[..]/env/lib/python2.7/site-packages/jsonpickle/pickler.py", line 491, in _flatten_key_value_pair
    data[k] = self._flatten(v)
  File "[..]/env/lib/python2.7/site-packages/jsonpickle/pickler.py", line 157, in _flatten
    return self._pop(self._flatten_obj(obj))
  File "[..]/env/lib/python2.7/site-packages/jsonpickle/pickler.py", line 173, in _flatten_obj
    return flatten_func(obj)
  File "[..]/env/lib/python2.7/site-packages/jsonpickle/pickler.py", line 425, in _flatten_dict_obj
    flatten(k, v, data)
  File "[..]/env/lib/python2.7/site-packages/jsonpickle/pickler.py", line 491, in _flatten_key_value_pair
    data[k] = self._flatten(v)
  File "[..]/env/lib/python2.7/site-packages/jsonpickle/pickler.py", line 157, in _flatten
    return self._pop(self._flatten_obj(obj))
  File "[..]/env/lib/python2.7/site-packages/jsonpickle/pickler.py", line 173, in _flatten_obj
    return flatten_func(obj)
  File "[..]/env/lib/python2.7/site-packages/jsonpickle/pickler.py", line 231, in _ref_obj_instance
    return self._flatten_obj_instance(obj)
  File "[..]/env/lib/python2.7/site-packages/jsonpickle/pickler.py", line 361, in _flatten_obj_instance
    if util.is_iterator(obj):
  File "[..]/env/lib/python2.7/site-packages/jsonpickle/util.py", line 337, in is_iterator
    return (isinstance(obj, collections.Iterator) and
  File "[..]/env/lib/python2.7/abc.py", line 144, in __instancecheck__
    return cls.__subclasscheck__(subtype)
  File "[..]/env/lib/python2.7/abc.py", line 180, in __subclasscheck__
    if issubclass(subclass, scls):
  File "[..]/env/lib/python2.7/abc.py", line 161, in __subclasscheck__
    ok = cls.__subclasshook__(subclass)
  File "[..]/env/lib/python2.7/site-packages/backports_abc.py", line 66, in __subclasshook__
    mro = C.__mro__
  AttributeError: class RaygunErrorMessage has no attribute '__mro__'

raygun4py==3.1.3

AttributeError when running the example script from the Heroku docs

Using raygun4py 3.1.2 and Python 2.7.10, I was following the official getting started instructions from Heroku: https://devcenter.heroku.com/articles/raygun#using-with-python

Here's my entire test script (running locally, not on Heroku, with RAYGUN_APIKEY set):

import os, sys, logging
from raygun4py import raygunprovider

logger = logging.getLogger("mylogger")

rgHandler = raygunprovider.RaygunHandler(os.environ.get('RAYGUN_APIKEY'))

logger.addHandler(rgHandler)

def log_exception(exc_type, exc_value, exc_traceback):
    print "Logging: %s" % exc_value
    logger.error("A python error occurred", exc_info = (exc_type, exc_value, exc_traceback))

sys.excepthook = log_exception

(a, b) = (1, 2, 3,)

And here's the error I'm getting from raygun4py:

Error in sys.excepthook:
Logging: too many values to unpack
Traceback (most recent call last):
  File "test.py", line 11, in log_exception
    logger.error("A python error occurred", exc_info = (exc_type, exc_value, exc_traceback))
  File "C:\Python\2.7\lib\logging\__init__.py", line 1191, in error
    self._log(ERROR, msg, args, **kwargs)
  File "C:\Python\2.7\lib\logging\__init__.py", line 1284, in _log
    self.handle(record)
  File "C:\Python\2.7\lib\logging\__init__.py", line 1294, in handle
    self.callHandlers(record)
  File "C:\Python\2.7\lib\logging\__init__.py", line 1334, in callHandlers
    hdlr.handle(record)
  File "C:\Python\2.7\lib\logging\__init__.py", line 757, in handle
    self.emit(record)
  File "C:\Python\2.7\lib\site-packages\raygun4py\raygunprovider.py", line 183, in emit
    self.sender.send_exception(userCustomData=userCustomData)
  File "C:\Python\2.7\lib\site-packages\raygun4py\raygunprovider.py", line 97, in send_exception
    errorMessage = raygunmsgs.RaygunErrorMessage(exc_type, exc_value, exc_traceback, options)
  File "C:\Python\2.7\lib\site-packages\raygun4py\raygunmsgs.py", line 118, in __init__
    self.className = exc_type.__name__
AttributeError: 'NoneType' object has no attribute '__name__'

Original exception was:
Traceback (most recent call last):
  File "test.py", line 15, in <module>
    (a, b) = (1, 2, 3,)
ValueError: too many values to unpack

Obviously, the second exception is correct and to be expected, but the first one is not.

Any good reason to pin down the dependencies?

I notice the dependencies of this library are being aggressively pinned down.

'jsonpickle == 0.9.2',
'blinker == 1.3.0',
'requests == 2.9.1'

Now, while this is a very good practice for application-like projects, for libraries (such as raygun4py) this is actually not recommended, unless extremely good reasons exists.

Just to better explain a use case, in my flask powered project, I'm trying to use the latest flask today with the latest blinker today, but this library will force me to use blinker==1.3.0.

If there are no any other reasons to do that, can you please unlock the dependencies and let the clients of your library to worry about pinning the versions?

Add support for wildcard matching of environment variable blacklist

Related to #85, but a different functionality...

It would be nice to be able to provide wildcards around certain terms that you'd like to omit from environment variables. For example, right now our config contains a list of known ENV vars, but as more are added, they get sent through.

It would be nice to be able to specify wildcards like the following:

FILTERED_KEYS = [
  'AWS_*',
  '*PASSWORD*',
  '*KEY*'
]

transmit_global_variables is broken

The transmit_global_variables should transmit globals respective to the module of the bottom frame of the traceback (e.g. frame.f_globals much like frame.f_locals is used for local vars). Here's the code in question:

https://github.com/MindscapeHQ/raygun4py/blob/master/python2/raygun4py/raygunmsgs.py#L121

What this does is transmit the globals of the raygunmsgs.py module, which are almost certainly completely unrelated to the actual error being logged, unless I'm missing something?

Logging method does not work, at all

Sample code:

import sys
import os
import logging
import cratejoy.util.raygun as raygun

log = logging.getLogger(u"cratejoy")

raygun.init_raygun(os.environ.get('RAYGUN_STORE_KEY'))

try:
    log.debug(u"Sup")
except Exception as e:
    print "Caught exception on a regular log statement"
    print e
    sys.exit(1)

try:
    raise Exception(u"wtf")
except Exception as e:
    log.exception(u"error")

The first log statement should NOT except and it should get to the bottom try/catch. It dies at the first one.

(venv)amir-laptop:cratejoy aelaguiz$ foreman run python cratejoy/scripts/error.py
2014-01-02 15:47:04,055 [57104] [DEBUG] error: Sup
<LogRecord: cratejoy, 10, cratejoy/scripts/error.py, 11, "Sup">
Caught exception on a regular log statement
local variable 'exc' referenced before assignment

The code in question in the raygun library:

    def emit(self, record):
        print record
        if record.exc_info:
            exc = record.exc_info

        tags = None
        userCustomData = { "Logger Message" : record.msg }
        request = None
        className = None
        self.sender.send(exc[0], exc[1], exc[2], className, tags, userCustomData, request)

Clearly it will reference exc[0] if no exc_info is attached to a log record. So basically this only works for outputting errors.

AttributeError: 'dict' object has no attribute 'localVariables'

Traceback (most recent call last):
[..]
    client.send_exception(exception=exception, userCustomData=custom_data)
  File "[..]/env/lib/python2.7/site-packages/raygun4py/raygunprovider.py", line 95, in send_exception
    errorMessage = raygunmsgs.RaygunErrorMessage(type(exception), exception, exc_traceback, options)
  File "[..]/env/lib/python2.7/site-packages/raygun4py/raygunmsgs.py", line 152, in __init__
    if frame.localVariables:
AttributeError: 'dict' object has no attribute 'localVariables'

raygun4py==3.1.3

Chained exceptions

Dear developers,

Raygun REST API supports chained exceptions using nested innerError. Would be very nice to have Python3 chained exception support in raygun4py.

Thanks

Errors should be logged instead of printed to stderr

There's a few places (such as raygunprovider.py) that print error messages to stderr. It'd be better to log these as errors using standard Python logging so apps can filter them and log them to the correct place.

(In particular I'm hitting these messages while running tests in Django locally, where messages about not logging to Raygun don't matter.)

It'd also help categorize the errors; the message linked above would be better-suited as a warning rather than an error, since execution continues even if no API key is set.

I hope to submit a PR to fix this within the next few days when I can get to it. :D

Environment Variables are always sent to Raygun

Currently is not possible to prevent environment variables from being sent to Raygun's servers. It is common to have sensitive information like API keys on environment variables, and not have a way to disable this behavior could lead to a serious security breach via Raygun.

This problem doesn't exist on libs for other languages like raygun4java and raygun4ruby.

Add git tags when publishing

It looks like versions 4.2.0 and 4.2.1 aren't added as git tags here in the repo. It would be helpful if you could keep that up.

Thanks

Disable transmitting local/global variables by default

I was just integrating Raygun to a Flask API and trasmitting local/global variables caused a stackoverflow exception which took me quite some time to understand and fix.

The original error was a Mongo connection that failed because it was missing the connection parameters. When raygun4py tried to get local/global variables it re-triggered the connection initialization for some reason, which in turn caused the exception to be re-raised, etc.

I think these options should be disabled by default. Sending local/global variables automatically is of limited usefulness in real applications anyway. And as the Python Zen says "Explicit is better than implicit.", i.e. in this case this should be opt-in.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.