The new Python SDK for Sentry.io

Overview

Bad software is everywhere, and we're tired of it. Sentry is on a mission to help developers write better software faster, so we can get back to enjoying technology. If you want to join us Check out our open positions

sentry-python - Sentry SDK for Python

Build Status PyPi page link -- version Discord

This is the next line of the Python SDK for Sentry, intended to replace the raven package on PyPI.

from sentry_sdk import init, capture_message

init("https://[email protected]/123")

capture_message("Hello World")  # Will create an event.

raise ValueError()  # Will also create an event.

Contributing to the SDK

Please refer to CONTRIBUTING.md.

License

Licensed under the BSD license, see LICENSE

Comments
  • Azure Function doesn't capture exceptions on Azure

    Azure Function doesn't capture exceptions on Azure

    I have a Queue Trigger Azure Function in Python with the following code:

    import logging
    import os
    
    import azure.functions as func
    import sentry_sdk
    from sentry_sdk.api import capture_exception, flush, push_scope
    from sentry_sdk.integrations.serverless import serverless_function
    
    # Sentry configuration
    sentry_dsn = "my-dsn"
    environment = "DEV"
    logger = logging.getLogger(__name__)
    sentry_sdk.init(
        sentry_dsn,
        environment=environment,
        send_default_pii=True,
        request_bodies="always",
        with_locals=True,
    )
    sentry_sdk.utils.MAX_STRING_LENGTH = 2048
    
    
    @serverless_function
    def main(msg: func.QueueMessage) -> None:
    
        with push_scope() as scope:
            scope.set_tag("function.name", "ProcessHeadersFile")
            scope.set_context(
                "Queue Message",
                {
                    "id": msg.id,
                    "dequeue_count": msg.dequeue_count,
                    "insertion_time": msg.insertion_time,
                    "expiration_time": msg.expiration_time,
                    "pop_receipt": msg.pop_receipt,
                },
            )
    
            try:
                # code that might raise exceptions here
                function_that_raise()
            except Exception as ex:
                print(ex)
                # Rethrow to fail the execution
                raise
    
    def function_that_raise():
        return 5 / 0
    

    Works locally, but not on Azure. I run multiple invocations, I get all the failures, but then nothing shows on Sentry.

    I have also try manually capturing and flushing, but doesn't work either:

    try:
        # code that might raise exceptions here
        function_that_raise()
    except Exception as ex:
        capture_exception(ex)
        flush(2)
        raise
    

    Using sentry-sdk==0.19.5.

    How can I troubleshoot what's happening? What can be the causes that it works when running the function locally, but not when running on Azure?

    needs-information Integration: Serverless Status: Stale 
    opened by empz 36
  • SentryAsgiMiddleware not compatible with Uvicorn 0.13.0

    SentryAsgiMiddleware not compatible with Uvicorn 0.13.0

    On December 8th Uvicorn updated from 0.12.3 to 0.13.0. This results in an error at startup, see output with minimal example. When downgrading Uvicorn to 0.12.3 the example runs fine.

    Why this error is thrown or which changes resulted in the error, I have no clue. Could you help me with this?

    app.py

    from sanic import Sanic
    from sentry_sdk.integrations.asgi import SentryAsgiMiddleware
    
    app = SentryAsgiMiddleware(Sanic(__name__))
    

    requirements.txt

    sanic==20.9.1
    sentry-sdk==0.19.4
    uvicorn==0.13.0
    

    Command to run:

    uvicorn app:app --port 5000 --workers=1 --debug --reload
    

    Output:

    INFO:     Uvicorn running on http://127.0.0.1:5000 (Press CTRL+C to quit)
    INFO:     Started reloader process [614068] using statreload
    Process SpawnProcess-1:
    Traceback (most recent call last):
      File "/usr/lib/python3.9/multiprocessing/process.py", line 315, in _bootstrap
        self.run()
      File "/usr/lib/python3.9/multiprocessing/process.py", line 108, in run
        self._target(*self._args, **self._kwargs)
      File "/home/lander/.local/share/virtualenvs/san-iJ5wdX60/lib/python3.9/site-packages/uvicorn/subprocess.py", line 61, in subprocess_started
        target(sockets=sockets)
      File "/home/lander/.local/share/virtualenvs/san-iJ5wdX60/lib/python3.9/site-packages/uvicorn/server.py", line 48, in run
        loop.run_until_complete(self.serve(sockets=sockets))
      File "uvloop/loop.pyx", line 1456, in uvloop.loop.Loop.run_until_complete
      File "/home/lander/.local/share/virtualenvs/san-iJ5wdX60/lib/python3.9/site-packages/uvicorn/server.py", line 55, in serve
        config.load()
      File "/home/lander/.local/share/virtualenvs/san-iJ5wdX60/lib/python3.9/site-packages/uvicorn/config.py", line 319, in load
        elif not inspect.signature(self.loaded_app).parameters:
      File "/usr/lib/python3.9/inspect.py", line 3118, in signature
        return Signature.from_callable(obj, follow_wrapped=follow_wrapped)
      File "/usr/lib/python3.9/inspect.py", line 2867, in from_callable
        return _signature_from_callable(obj, sigcls=cls,
      File "/usr/lib/python3.9/inspect.py", line 2409, in _signature_from_callable
        sig = _signature_from_callable(
      File "/usr/lib/python3.9/inspect.py", line 2242, in _signature_from_callable
        raise TypeError('{!r} is not a callable object'.format(obj))
    TypeError: <member '__call__' of 'SentryAsgiMiddleware' objects> is not a callable object
    
    bug 
    opened by LanderMoerkerke 33
  • Version 0.17.8 broke Celery tasks with custom Task class

    Version 0.17.8 broke Celery tasks with custom Task class

    I am using tenant-schemas-celery package, which generates it's own TenantTask (extends celery.app.task.Task) class in it's own CeleryApp (extends celery.Celery). After updating from sentry-sdk from 0.17.7 to 0.17.8 the TenantTask's tenant context switching stopped working. I suspect this is because of the following change in 0.17.8:

    diff --git a/sentry_sdk/integrations/celery.py b/sentry_sdk/integrations/celery.py
    index 1a11d4a..2b51fe1 100644
    --- a/sentry_sdk/integrations/celery.py
    +++ b/sentry_sdk/integrations/celery.py
    @@ -60,9 +60,8 @@ class CeleryIntegration(Integration):
                     # Need to patch both methods because older celery sometimes
                     # short-circuits to task.run if it thinks it's safe.
                     task.__call__ = _wrap_task_call(task, task.__call__)
                     task.run = _wrap_task_call(task, task.run)
    -                task.apply_async = _wrap_apply_async(task, task.apply_async)
    
                     # `build_tracer` is apparently called for every task
                     # invocation. Can't wrap every celery task for every invocation
                     # or we will get infinitely nested wrapper functions.
    @@ -71,8 +70,12 @@ class CeleryIntegration(Integration):
                 return _wrap_tracer(task, old_build_tracer(name, task, *args, **kwargs))
    
             trace.build_tracer = sentry_build_tracer
    
    +        from celery.app.task import Task  # type: ignore
    +
    +        Task.apply_async = _wrap_apply_async(Task.apply_async)
    +
             _patch_worker_exit()
    
             # This logger logs every status of every task that ran on the worker.
             # Meaning that every task's breadcrumbs are full of stuff like "Task
    

    I think this problem has to do with this new way of importing celery.app.task.Task. Even though TenantTask extends the celery.app.task.Task, for some reason this change broke the TenantTask logic.

    I'm not sure which package this should be fixed in, but I'm bit skeptical about this new import in sentry-sdk, so I'm reporting it here.

    Here is my celery.py:

    from tenant_schemas_celery.app import CeleryApp as TenantAwareCeleryApp
    
    
    app = TenantAwareCeleryApp()
    app.config_from_object('django.conf:settings')
    app.autodiscover_tasks()
    
    bug Integration: Celery Status: Stale needs-repro 
    opened by akifd 29
  • document ignore_errors

    document ignore_errors

    The old raven library had this functionality, implemented for Django by declaring a list of names of errors in the settings file.

    This kind of functionality is necessary to control error reporting spam.

    enhancement doc stabilization Status: Backlog 
    opened by biblicabeebli 29
  • Integration for FastAPI

    Integration for FastAPI

    FastAPI is just Starlette which is just ASGI. We have an ASGI integration that should work fine. However, it would be nice to have deeper integration than we currently provide, particularly around Performance monitoring.

    Please vote with πŸ‘ on this post if you're interested in this. I would also like to hear what currently doesn't work out well with the ASGI middleware applied to your FastAPI app.

    enhancement new-integration Status: Backlog Jira 
    opened by untitaker 25
  • Provide a means for capturing stack trace for messages that are not errors

    Provide a means for capturing stack trace for messages that are not errors

    ... without relying on the logging integration.

    SDK v0.7.10

    Currently, the only way to do this is via the logging integration and issuing a log at the configured level or higher with exc_info=True. I don't think this is a good substitute because:

    • I don't want to classify these events as errors (the end goal being errors should drive alerts)
    • Sometimes there are interesting or unexpected events that I want to debug more and leveraging Sentry's stack traces with locals helps in this regard
    • I don't want to lower our logging integration level to warning or similar, as that may spam our project with a lot of warnings/events that are not interesting or useful

    Ideally, the Sentry SDK could add an additional argument to the and capture_message APIs to make this simple from a user perspective:

    sentry_sdk.capture_message("Unexpected event", level="warning", stack_trace=True)
    

    I'm trying to get this working locally with the SDK, and it's leading to incomplete event data (see picture) and also leading to pretty hairy code.

    sentry_sdk.capture_event({"message": "oops 2", "level": "warning", "threads": [{"stacktrace": sentry_sdk.utils.current_stacktrace(with_locals=True), "crashed": False, "current": True}])
    

    This was more or less copied from the code I see for adding stack traces in Client._prepare_event.

    Screenshot from 2019-04-13 14-39-24

    opened by goodspark 25
  • Celery integration not capturing error with max_tasks_per_child = 1

    Celery integration not capturing error with max_tasks_per_child = 1

    The celery integration is failing to capture the exception when I use a celery factory pattern which patches the celery task with Flask's context.

    This is web/celery_factory.py

    # Source: https://stackoverflow.com/questions/12044776/how-to-use-flask-sqlalchemy-in-a-celery-task
    
    from celery import Celery
    import flask
    
    
    class FlaskCelery(Celery):
    
        def __init__(self, *args, **kwargs):
            super(FlaskCelery, self).__init__(*args, **kwargs)
            self.patch_task()
    
            if 'app' in kwargs:
                self.init_app(kwargs['app'])
    
        def patch_task(self):
            TaskBase = self.Task
            _celery = self
    
            class ContextTask(TaskBase):
                abstract = True
    
                def __call__(self, *args, **kwargs):
                    if flask.has_app_context():
                        return TaskBase.__call__(self, *args, **kwargs)
                    else:
                        with _celery.app.app_context():
                            return TaskBase.__call__(self, *args, **kwargs)
    
            self.Task = ContextTask
    
        def init_app(self, app):
            self.app = app
            self.config_from_object(app.config)
    
    
    celery_app = FlaskCelery()
    

    I am adding a random raise inside a simple task

    import celery_app from celery_factory.py
    @celery_app.task
    def simple_task():
        raise Exception("Testing Celery exception")
    

    The error I get printed is:

    [2019-03-08 21:24:21,117: ERROR/ForkPoolWorker-31] Task simple_task[d6e959b1-7253-4e55-861d-c1968ae14e1c] raised unexpected: RuntimeError('No active exception to reraise')
    Traceback (most recent call last):
      File "/Users/okomarov/.virtualenvs/myenv/lib/python3.7/site-packages/celery/app/trace.py", line 382, in trace_task
        R = retval = fun(*args, **kwargs)
      File "/Users/okomarov/Documents/repos/myproject/web/celery_factory.py", line 28, in __call__
        return TaskBase.__call__(self, *args, **kwargs)
      File "/Users/okomarov/.virtualenvs/myenv/lib/python3.7/site-packages/celery/app/trace.py", line 641, in __protected_call__
        return self.run(*args, **kwargs)
      File "/Users/okomarov/.virtualenvs/myenv/lib/python3.7/site-packages/sentry_sdk/integrations/celery.py", line 66, in _inner
        reraise(*_capture_exception())
      File "/Users/okomarov/.virtualenvs/myenv/lib/python3.7/site-packages/sentry_sdk/_compat.py", line 52, in reraise
        raise value
      File "/Users/okomarov/.virtualenvs/myenv/lib/python3.7/site-packages/sentry_sdk/integrations/celery.py", line 64, in _inner
        return f(*args, **kwargs)
      File "/Users/okomarov/.virtualenvs/myenv/lib/python3.7/site-packages/sentry_sdk/integrations/celery.py", line 66, in _inner
        reraise(*_capture_exception())
      File "/Users/okomarov/.virtualenvs/myenv/lib/python3.7/site-packages/sentry_sdk/_compat.py", line 52, in reraise
        raise value
      File "/Users/okomarov/.virtualenvs/myenv/lib/python3.7/site-packages/sentry_sdk/integrations/celery.py", line 64, in _inner
        return f(*args, **kwargs)
      File "/Users/okomarov/Documents/repos/myproject/web/simple_task.py", line 4, in simple_task
        raise Exception("Testing Celery exception")
    RuntimeError: No active exception to reraise
    

    Relevant pip packages:

    Celery==4.2.1
    Flask==1.0.2
    sentry-sdk==0.7.4
    

    The integration is called as following (flask integration works as expected):

    from flask import Flask
    from celery_factory import celery_app
    from config import config_to_use
    
    
    def create_app():
        app = Flask()
        app.config.from_object(config_to_use)
    
        init_logging(app)
    
        register_extensions(app)
        register_blueprints(app)
        register_jinja_extras(app)
    
        return app
    
    
    def init_logging(app):
        import sentry_sdk
        from sentry_sdk.integrations.flask import FlaskIntegration
        from sentry_sdk.integrations.celery import CeleryIntegration
    
        sentry_sdk.init(
            dsn=app.config.get('FLASK_SENTRY_DSN'),
            integrations=[FlaskIntegration(), CeleryIntegration()]
            )
    
    ...
    
    bug 
    opened by okomarov 23
  • No IPv4 fallback and no error reporting on failed connection

    No IPv4 fallback and no error reporting on failed connection

    If you self-host a sentry instance and have a broken IPv6 setup on the server (i.e., you have an AAAA record set up for the domain, but it points at the wrong IP), but a working IPv4 setup, sentry-python will attempt to deliver the issue via IPv6 (if the network supports it), fail, and not retry with IPv4.

    If this isn't intended behavior, I would recommend implementing an IPv4 fallback. At a minimum, it would be nice if the system would report an error if the connection failed - even with debug enabled, the log does not indicate that the connection failed, and is more or less indistinguishable from a log where the reporting worked.

    In my eyes, an IPv4 fallback would be desirable either way, because some places have broken IPv6 networks (they provide v6 IPs, but do not let them access the internet). This is another scenario where the robustness of reporting would be improved with a v4 fallback.

    Steps to reproduce:

    • Set up Sentry with working A record, but AAAA record pointing at an incorrect IP
    • Run the following code:
    import sentry_sdk
    
    sentry_sdk.init(YOUR_DSN, debug=True)
    
    # Produce an exception:
    1/0
    
    bug help wanted Status: Backlog 
    opened by malexmave 23
  • Django channels + ASGI leaks memory

    Django channels + ASGI leaks memory

    I expended around 3 days trying to figure out what was leaking in my Django app and I was only able to fix it by disabling sentry Django integration (on a very isolated test using memory profiler, tracemalloc and docker). To give more context before profiling information, that's how my memory usage graph looked on a production server (killing the app and/or a worker after a certain threshold): image

    Now the data I gathered:

    By performing 100,000 requests on this endpoint:

    class SimpleView(APIView):
        def get(self, request):
            return Response(status=status.HTTP_204_NO_CONTENT)
    

    A tracemalloc snapshot, grouped by filename, showed sentry django integration using 9MB of memory after a 217 seconds test with 459 requests per second. (using NGINX and Hypercorn with 3 workers):

    /usr/local/lib/python3.7/site-packages/sentry_sdk/integrations/django/__init__.py:0: size=8845 KiB (+8845 KiB), count=102930 (+102930), average=88 B
    /usr/local/lib/python3.7/site-packages/django/urls/resolvers.py:0: size=630 KiB (+630 KiB), count=5840 (+5840), average=110 B
    /usr/local/lib/python3.7/linecache.py:0: size=503 KiB (+503 KiB), count=5311 (+5311), average=97 B
    /usr/local/lib/python3.7/asyncio/selector_events.py:0: size=465 KiB (+465 KiB), count=6498 (+6498), average=73 B
    /usr/local/lib/python3.7/site-packages/sentry_sdk/scope.py:0: size=325 KiB (+325 KiB), count=373 (+373), average=892 B
    

    tracemalloc probe endpoint:

    import tracemalloc
    tracemalloc.start()
    
    start = tracemalloc.take_snapshot()
    
    @api_view(['GET'])
    def PrintMemoryInformation(request):
        current = tracemalloc.take_snapshot()
    
        top_stats = current.compare_to(start, 'filename')
        for stat in top_stats[:5]:
            print(stat)
    
        return Response(status=status.HTTP_204_NO_CONTENT)
    

    I have performed longers tests and the sentry django integration memory usage only grows, never releases, this is just a scaled-down version of the tests I've been performing to identify this leak.

    This is how my sentry settings looks like on settings.py: image

    Memory profile after disabling the Django Integration (same test and endpoint), no sentry sdk at top 5 most consuming files:

    /usr/local/lib/python3.7/site-packages/django/urls/resolvers.py:0: size=1450 KiB (+1450 KiB), count=15123 (+15123), average=98 B
    /usr/local/lib/python3.7/site-packages/hypercorn/protocol/h11.py:0: size=1425 KiB (+1425 KiB), count=8868 (+8868), average=165 B
    /usr/local/lib/python3.7/site-packages/channels/http.py:0: size=1398 KiB (+1398 KiB), count=14848 (+14848), average=96 B
    /usr/local/lib/python3.7/site-packages/h11/_state.py:0: size=1242 KiB (+1242 KiB), count=13998 (+13998), average=91 B
    /usr/local/lib/python3.7/site-packages/h11/_connection.py:0: size=1226 KiB (+1226 KiB), count=15957 (+15957), average=79 B
    

    settings.py for the above profile: image

    Memory profile grouped by line number (more verbose):

    /usr/local/lib/python3.7/site-packages/sentry_sdk/integrations/django/__init__.py:272: size=4512 KiB (+4512 KiB), count=33972 (+33972), average=136 B
    /usr/local/lib/python3.7/site-packages/sentry_sdk/integrations/django/__init__.py:134: size=4247 KiB (+4247 KiB), count=67945 (+67945), average=64 B
    /usr/local/lib/python3.7/linecache.py:137: size=492 KiB (+492 KiB), count=4850 (+4850), average=104 B
    /usr/local/lib/python3.7/asyncio/selector_events.py:716: size=415 KiB (+415 KiB), count=2530 (+2530), average=168 B
    /usr/local/lib/python3.7/site-packages/sentry_sdk/scope.py:198: size=279 KiB (+279 KiB), count=1 (+1), average=279 KiB
    /usr/local/lib/python3.7/site-packages/django/views/generic/base.py:65: size=262 KiB (+262 KiB), count=4783 (+4783), average=56 B
    /usr/local/lib/python3.7/socket.py:213: size=237 KiB (+237 KiB), count=2530 (+2530), average=96 B
    /usr/local/lib/python3.7/site-packages/ddtrace/span.py:149: size=229 KiB (+229 KiB), count=1765 (+1765), average=133 B
    /usr/local/lib/python3.7/site-packages/django/urls/resolvers.py:537: size=229 KiB (+229 KiB), count=390 (+390), average=600 B
    /usr/local/lib/python3.7/site-packages/h11/_state.py:261: size=224 KiB (+224 KiB), count=3170 (+3170), average=72 B
    /usr/local/lib/python3.7/site-packages/django/contrib/messages/storage/session.py:21: size=211 KiB (+211 KiB), count=3863 (+3863), average=56 B
    /usr/local/lib/python3.7/site-packages/rest_framework/request.py:414: size=195 KiB (+195 KiB), count=3565 (+3565), average=56 B
    /usr/local/lib/python3.7/functools.py:60: size=194 KiB (+194 KiB), count=1611 (+1611), average=124 B
    /usr/local/lib/python3.7/site-packages/ddtrace/vendor/msgpack/fallback.py:847: size=192 KiB (+192 KiB), count=542 (+542), average=363 B
    /usr/local/lib/python3.7/site-packages/django/http/request.py:427: size=183 KiB (+183 KiB), count=3335 (+3335), average=56 B
    /usr/local/lib/python3.7/site-packages/ddtrace/encoding.py:114: size=171 KiB (+171 KiB), count=6 (+6), average=28.5 KiB
    /usr/local/lib/python3.7/site-packages/rest_framework/views.py:478: size=166 KiB (+166 KiB), count=3002 (+3002), average=57 B
    /usr/local/lib/python3.7/site-packages/django/utils/datastructures.py:67: size=164 KiB (+164 KiB), count=3006 (+3006), average=56 B
    /usr/local/lib/python3.7/asyncio/selector_events.py:581: size=163 KiB (+163 KiB), count=2530 (+2530), average=66 B
    /usr/local/lib/python3.7/site-packages/h11/_connection.py:233: size=159 KiB (+159 KiB), count=2263 (+2263), average=72 B
    

    my pip freeze output:

    aioredis==1.2.0
    amqp==2.5.0
    appdirs==1.4.3
    asgiref==3.1.4
    asn1crypto==0.24.0
    astroid==2.2.5
    async-timeout==3.0.1
    atomicwrites==1.3.0
    attrs==19.1.0
    autobahn==19.7.1
    Automat==0.7.0
    autopep8==1.4.4
    Babel==2.7.0
    billiard==3.6.0.0
    boto3==1.9.185
    botocore==1.12.185
    celery==4.3.0
    certifi==2019.6.16
    cffi==1.12.3
    channels==2.2.0
    channels-redis==2.4.0
    chardet==3.0.4
    Click==7.0
    colorama==0.4.1
    constantly==15.1.0
    coverage==4.5.3
    cryptography==2.7
    daphne==2.3.0
    ddtrace==0.26.0
    dj-database-url==0.5.0
    Django==2.2.3
    django-anymail==6.1.0
    django-cors-headers==3.0.2
    django-filter==2.1.0
    django-ipware==2.1.0
    django-money==0.15
    django-nose==1.4.6
    django-redis==4.10.0
    django-storages==1.7.1
    django-templated-mail==1.1.1
    djangorestframework==3.9.4
    djoser==1.7.0
    docopt==0.6.2
    docutils==0.14
    factory-boy==2.12.0
    Faker==1.0.7
    flower==0.9.3
    geoip2==2.9.0
    gprof2dot==2017.9.19
    graphviz==0.11
    green==2.16.1
    gunicorn==19.9.0
    h11==0.9.0
    h2==3.1.0
    hiredis==1.0.0
    hpack==3.0.0
    httptools==0.0.13
    Hypercorn==0.7.0
    hyperframe==5.2.0
    hyperlink==19.0.0
    idna==2.8
    importlib-metadata==0.18
    incremental==17.5.0
    isort==4.3.21
    jedi==0.14.0
    Jinja2==2.10.1
    jmespath==0.9.4
    kombu==4.6.3
    lazy-object-proxy==1.4.1
    lxml==4.3.4
    MarkupSafe==1.1.1
    maxminddb==1.4.1
    mccabe==0.6.1
    more-itertools==7.1.0
    msgpack==0.6.1
    nose==1.3.7
    objgraph==3.4.1
    packaging==19.0
    parso==0.5.0
    pendulum==2.0.5
    Pillow==6.1.0
    pipdate==0.3.2
    pluggy==0.12.0
    prompt-toolkit==2.0.9
    psutil==5.6.3
    psycopg2-binary==2.8.3
    ptpython==2.0.4
    py==1.8.0
    py-moneyed==0.8.0
    pycodestyle==2.5.0
    pycparser==2.19
    Pygments==2.4.2
    PyHamcrest==1.9.0
    PyJWT==1.7.1
    pylint==2.3.1
    pylint-django==2.0.10
    pylint-plugin-utils==0.5
    pyparsing==2.4.0
    python-dateutil==2.8.0
    pytoml==0.1.20
    pytz==2019.1
    pytzdata==2019.2
    redis==3.2.1
    requests==2.22.0
    s3transfer==0.2.1
    sentry-sdk==0.10.1
    six==1.12.0
    sqlparse==0.3.0
    text-unidecode==1.2
    toml==0.10.0
    tornado==5.1.1
    Twisted==19.2.1
    txaio==18.8.1
    typed-ast==1.4.0
    typing-extensions==3.7.4
    Unidecode==1.1.1
    urllib3==1.25.3
    uvloop==0.12.2
    vine==1.3.0
    wcwidth==0.1.7
    websockets==7.0
    whitenoise==4.1.2
    wrapt==1.11.2
    wsproto==0.14.1
    zipp==0.5.2
    zope.interface==4.6.0
    

    I used the official python docker image with the label 3.7, meaning latest 3.7 version.

    Hope you guys can figure the problem with this data, I'm not sure if I'll have the time to contribute myself!

    Bonus, memory profiling after 1,000,000 requests (Django Integration using 44MB):

    /usr/local/lib/python3.7/site-packages/sentry_sdk/integrations/django/__init__.py:272: size=43.9 MiB (+43.9 MiB), count=338647 (+338647), average=136 B
    /usr/local/lib/python3.7/site-packages/sentry_sdk/integrations/django/__init__.py:134: size=41.3 MiB (+41.3 MiB), count=677294 (+677294), average=64 B
    /usr/local/lib/python3.7/site-packages/sentry_sdk/scope.py:198: size=2942 KiB (+2942 KiB), count=1 (+1), average=2942 KiB
    /usr/local/lib/python3.7/site-packages/django/views/generic/base.py:65: size=2584 KiB (+2584 KiB), count=47252 (+47252), average=56 B
    /usr/local/lib/python3.7/site-packages/django/contrib/messages/storage/session.py:21: size=2079 KiB (+2079 KiB), count=38013 (+38013), average=56 B
    /usr/local/lib/python3.7/site-packages/rest_framework/request.py:414: size=2006 KiB (+2006 KiB), count=36684 (+36684), average=56 B
    /usr/local/lib/python3.7/site-packages/django/http/request.py:427: size=1857 KiB (+1857 KiB), count=33946 (+33946), average=56 B
    /usr/local/lib/python3.7/site-packages/django/utils/datastructures.py:67: size=1670 KiB (+1670 KiB), count=30546 (+30546), average=56 B
    /usr/local/lib/python3.7/site-packages/rest_framework/views.py:478: size=1547 KiB (+1547 KiB), count=28237 (+28237), average=56 B
    /usr/local/lib/python3.7/site-packages/django/contrib/auth/middleware.py:24: size=1518 KiB (+1518 KiB), count=27752 (+27752), average=56 B
    /usr/local/lib/python3.7/importlib/__init__.py:118: size=1398 KiB (+1398 KiB), count=25571 (+25571), average=56 B
    /usr/local/lib/python3.7/site-packages/django/contrib/messages/storage/__init__.py:12: size=930 KiB (+930 KiB), count=17000 (+17000), average=56 B
    /usr/local/lib/python3.7/site-packages/sentry_sdk/tracing.py:123: size=885 KiB (+885 KiB), count=5985 (+5985), average=151 B
    /usr/local/lib/python3.7/asyncio/selector_events.py:716: size=664 KiB (+664 KiB), count=4049 (+4049), average=168 B
    /usr/local/lib/python3.7/site-packages/django/urls/resolvers.py:541: size=662 KiB (+662 KiB), count=12107 (+12107), average=56 B
    /usr/local/lib/python3.7/site-packages/django/http/request.py:584: size=601 KiB (+601 KiB), count=10986 (+10986), average=56 B
    /usr/local/lib/python3.7/site-packages/django/core/handlers/exception.py:34: size=592 KiB (+592 KiB), count=10618 (+10618), average=57 B
    /usr/local/lib/python3.7/linecache.py:137: size=493 KiB (+493 KiB), count=4875 (+4875), average=104 B
    /usr/local/lib/python3.7/site-packages/h11/_state.py:261: size=434 KiB (+434 KiB), count=6142 (+6142), average=72 B
    /usr/local/lib/python3.7/site-packages/ddtrace/span.py:149: size=406 KiB (+406 KiB), count=3124 (+3124), average=133 B
    
    bug 
    opened by astutejoe 22
  • celery integration RecursionError

    celery integration RecursionError

    Hi there, I upgraded sentry_sdk to 0.7.0 and started getting RecursionError if there's an issue with celery task. Sentry record doesn't contain any stack trace for that but found that error in my apm system (can attach screenshot only, text data is a real mess there). I'm running celery 4.2.1 on Ubuntu 18.

    2019-02-14 15 04 54 bug needs-information 
    opened by chemiron 22
  • Using multiple DSNs, choosing based on the logger

    Using multiple DSNs, choosing based on the logger

    I'm looking to upgrade from raven-python[flask] to sentry-sdk[flask]. We previous had two DSNs for our backend: one for errors and one to log performance issues (e.g. slow requests / high DB query count).

    We were previously able to configure this via:

    from raven.contrib.flask import Sentry
    from raven.handlers.logging import SentryHandler
    
    performance_logger = logging.getLogger("benchling.performance")
    performance_logger.setLevel(logging.WARNING)
    sentry = Sentry(logging=True, level=logging.WARNING)
    
    def init_sentry(app):
        sentry.init_app(app, dsn=app.config["SENTRY_DSN_SERVER"])
        performance_handler = SentryHandler(dsn=app.config["SENTRY_DSN_BACKEND_PERFORMANCE"])
        performance_logger.addHandler(performance_handler)
    

    With the new architecture, this seems hard to do since the DSN is configured once via sentry_sdk.init where the LoggingIntegration simply listens to the root logger. I was able to hack around this by monkey-patching the logging_integration's handler as follows:

    import logging
    
    import sentry_sdk
    from sentry_sdk.client import Client
    from sentry_sdk.hub import Hub
    from sentry_sdk.integrations.celery import CeleryIntegration
    from sentry_sdk.integrations.flask import FlaskIntegration
    from sentry_sdk.integrations.logging import LoggingIntegration
    
    
    def register_clients_for_loggers(logger_name_to_client):
        """Monkeypatch LoggingIntegration's EventHandler to override the Client based on the record's logger"""
        hub = Hub.current
        logging_integration = hub.get_integration(LoggingIntegration)
        if not logging_integration:
            return
        handler = logging_integration._handler
        old_emit = handler.emit
    
        def new_emit(record):
            new_client = logger_name_to_client.get(record.name)
            previous_client = hub.client
            should_bind = new_client is not None
            try:
                if should_bind:
                    hub.bind_client(new_client)
                old_emit(record)
            finally:
                if should_bind:
                    hub.bind_client(previous_client)
    
        handler.emit = new_emit
    
    def init_sentry(app):
        sentry_sdk.init(
            dsn=app.config["SENTRY_DSN_SERVER"],
            release=app.config["SENTRY_RELEASE"],
            environment=app.config["SENTRY_ENVIRONMENT"],
            integrations=[
                LoggingIntegration(
                    level=logging.WARNING,  # Capture info and above as breadcrumbs
                    event_level=logging.WARNING,  # Send warnings and errors as events
                ),
                CeleryIntegration(),
                FlaskIntegration(),
            ],
        )
    
        performance_logger = logging.getLogger("benchling.performance")
        performance_logger.setLevel(logging.WARNING)
    
        perf_client = Client(
            dsn=app.config["SENTRY_DSN_BACKEND_PERFORMANCE"],
            release=app.config["SENTRY_RELEASE"],
            environment=app.config["SENTRY_ENVIRONMENT"],
        )
        register_clients_for_loggers({performance_logger.name: perf_client})
    

    Two questions:

    1. Does this approach seem reasonable, or is there a better way to handle this?
    2. If there isn't a better way, would it be possible to have sentry_sdk.init let you specify this mapping?
    question 
    opened by saifelse 22
  • Support for Sanic 22.12.0

    Support for Sanic 22.12.0

    Problem Statement

    We'd like to upgrade from prior LTS release of sanic (21.12.2) to the new LTS release and just want to make sure everything will work reliably.

    Could you please verify that sentry-python works with the latest LTS release of sanic?

    Solution Brainstorm

    Just want clarification

    enhancement Status: Untriaged 
    opened by robd003 0
  • Profiles will not work with a `traces_sampler` instead of `traces_sample_rate`

    Profiles will not work with a `traces_sampler` instead of `traces_sample_rate`

    How do you use Sentry?

    Sentry Saas (sentry.io)

    Version

    1.12.1

    Steps to Reproduce

    1. Pass a TracesSampler instead of setting traces_sample_rate
    2. Set _experiments['profiles_sample_rate'] to 1.0

    Expected Result

    Every request with a trace also has a corresponding profile

    Actual Result

    No profiles are being recorded

    P.S. From glancing at the code it doesn't look like there is a hard dependency on the more "dumb" traces_sample_rate over a TracesSampler. It's just that init checks for traces_sample_rate instead of doing the more thorough check of has_tracing_enabled which will check either option.

    As a workaround I seem to be able to just pass a dummy fixed sampling rate, since the TracesSampler always takes priority.

    P.P.S. Looks like the workaround might not actually work, since I'm still seeing no profiles for traced transactions. Unless they take a while to process. But I will try some alternative sampling methods for the profiler before giving up.

    Status: Untriaged 
    opened by Daverball 1
  • SQLAlchemy integration fails to parse version `2.0.0rc1`

    SQLAlchemy integration fails to parse version `2.0.0rc1`

    How do you use Sentry?

    Sentry Saas (sentry.io)

    Version

    1.12.1

    Steps to Reproduce

    Call sentry_sdk.init() with SQLAlchemy integration and install SQLAlchemy==2.0.0rc1.

    Expected Result

    no error

    Actual Result

          @staticmethod
          def setup_once():
              # type: () -> None
          
              try:
                  version = tuple(map(int, SQLALCHEMY_VERSION.split("b")[0].split(".")))
              except (TypeError, ValueError):
      >           raise DidNotEnable(
                      "Unparsable SQLAlchemy version: {}".format(SQLALCHEMY_VERSION)
                  )
      E           sentry_sdk.integrations.DidNotEnable: Unparsable SQLAlchemy version: 2.0.0rc1
    
    Status: Untriaged 
    opened by peterschutt 0
  • feat(integrations): Add method and path pattern transaction style for the Django integration

    feat(integrations): Add method and path pattern transaction style for the Django integration

    The method and path pattern for transaction styles includes the HTTP method as well as request path. This new transaction style for Django allows events to be grouped by this segmentation.

    opened by rynmlng 0
Releases(1.12.1)
Owner
Sentry
Real-time crash reporting for your web apps, mobile apps, and games.
Sentry
A Django app to initialize Sentry client for your Django applications

Dj_sentry This Django application intialize Sentry SDK to your Django application. How to install You can install this packaging by using: pip install

Gandi 1 Dec 9, 2021
A drop-in replacement for django's ImageField that provides a flexible, intuitive and easily-extensible interface for quickly creating new images from the one assigned to the field.

django-versatileimagefield A drop-in replacement for django's ImageField that provides a flexible, intuitive and easily-extensible interface for creat

Jonathan Ellenberger 490 Dec 13, 2022
Tweak the form field rendering in templates, not in python-level form definitions. CSS classes and HTML attributes can be altered.

django-widget-tweaks Tweak the form field rendering in templates, not in python-level form definitions. Altering CSS classes and HTML attributes is su

Jazzband 1.8k Jan 2, 2023
A django model and form field for normalised phone numbers using python-phonenumbers

django-phonenumber-field A Django library which interfaces with python-phonenumbers to validate, pretty print and convert phone numbers. python-phonen

Stefan Foulis 1.3k Dec 31, 2022
Stream Framework is a Python library, which allows you to build news feed, activity streams and notification systems using Cassandra and/or Redis. The authors of Stream-Framework also provide a cloud service for feed technology:

Stream Framework Activity Streams & Newsfeeds Stream Framework is a Python library which allows you to build activity streams & newsfeeds using Cassan

Thierry Schellenbach 4.7k Jan 2, 2023
Learn Python and the Django Framework by building a e-commerce website

The Django-Ecommerce is an open-source project initiative and tutorial series built with Python and the Django Framework.

Very Academy 275 Jan 8, 2023
Build reusable components in Django without writing a single line of Python.

Build reusable components in Django without writing a single line of Python. {% #quote %} {% quote_photo src="/project-hail-mary.jpg" %} {% #quot

Mitchel Cabuloy 277 Jan 2, 2023
Sampling profiler for Python programs

py-spy: Sampling profiler for Python programs py-spy is a sampling profiler for Python programs. It lets you visualize what your Python program is spe

Ben Frederickson 9.5k Jan 1, 2023
A django model and form field for normalised phone numbers using python-phonenumbers

django-phonenumber-field A Django library which interfaces with python-phonenumbers to validate, pretty print and convert phone numbers. python-phonen

Stefan Foulis 1.3k Dec 31, 2022
Python port of Google's libphonenumber

phonenumbers Python Library This is a Python port of Google's libphonenumber library It supports Python 2.5-2.7 and Python 3.x (in the same codebase,

David Drysdale 3.1k Jan 8, 2023
The uncompromising Python code formatter

The Uncompromising Code Formatter β€œAny color you like.” Black is the uncompromising Python code formatter. By using it, you agree to cede control over

Python Software Foundation 30.7k Jan 3, 2023
Code coverage measurement for Python

Coverage.py Code coverage testing for Python. Coverage.py measures code coverage, typically during test execution. It uses the code analysis tools and

Ned Batchelder 2.3k Jan 5, 2023
Faker is a Python package that generates fake data for you.

Faker is a Python package that generates fake data for you. Whether you need to bootstrap your database, create good-looking XML documents, fill-in yo

Daniele Faraglia 15.2k Jan 1, 2023
a little task queue for python

a lightweight alternative. huey is: a task queue (2019-04-01: version 2.0 released) written in python (2.7+, 3.4+) clean and simple API redis, sqlite,

Charles Leifer 4.3k Dec 29, 2022
Auto-detecting the n+1 queries problem in Python

nplusone nplusone is a library for detecting the n+1 queries problem in Python ORMs, including SQLAlchemy, Peewee, and the Django ORM. The Problem Man

Joshua Carp 837 Dec 29, 2022
The friendly PIL fork (Python Imaging Library)

Pillow Python Imaging Library (Fork) Pillow is the friendly PIL fork by Alex Clark and Contributors. PIL is the Python Imaging Library by Fredrik Lund

Pillow 10.4k Jan 3, 2023
Radically simplified static file serving for Python web apps

WhiteNoise Radically simplified static file serving for Python web apps With a couple of lines of config WhiteNoise allows your web app to serve its o

Dave Evans 2.1k Dec 15, 2022
this is a simple backend for instagram with python and django

simple_instagram_backend this is a simple backend for instagram with python and django it has simple realations and api in 4 diffrent apps: 1-users: a

null 2 Oct 20, 2021
Show how the redis works with Python (Django).

Redis Leaderboard Python (Django) Show how the redis works with Python (Django). Try it out deploying on Heroku (See notes: How to run on Google Cloud

Tom Xu 4 Nov 16, 2021