Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions sentry_sdk/integrations/celery.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from __future__ import absolute_import

import functools
import sys

from celery.exceptions import ( # type: ignore
Expand All @@ -11,7 +10,7 @@
)

from sentry_sdk.hub import Hub
from sentry_sdk.utils import capture_internal_exceptions, event_from_exception
from sentry_sdk.utils import capture_internal_exceptions, event_from_exception, wraps
from sentry_sdk.tracing import Span
from sentry_sdk._compat import reraise
from sentry_sdk.integrations import Integration
Expand Down Expand Up @@ -66,7 +65,7 @@ def sentry_build_tracer(name, task, *args, **kwargs):


def _wrap_apply_async(task, f):
@functools.wraps(f)
@wraps(f)
def apply_async(*args, **kwargs):
hub = Hub.current
integration = hub.get_integration(CeleryIntegration)
Expand Down Expand Up @@ -94,7 +93,7 @@ def _wrap_tracer(task, f):
# This is the reason we don't use signals for hooking in the first place.
# Also because in Celery 3, signal dispatch returns early if one handler
# crashes.
@functools.wraps(f)
@wraps(f)
def _inner(*args, **kwargs):
hub = Hub.current
if hub.get_integration(CeleryIntegration) is None:
Expand Down Expand Up @@ -127,7 +126,7 @@ def _wrap_task_call(task, f):
# functools.wraps is important here because celery-once looks at this
# method's name.
# https://github.com/getsentry/sentry-python/issues/421
@functools.wraps(f)
@wraps(f)
def _inner(*args, **kwargs):
try:
return f(*args, **kwargs)
Expand Down
11 changes: 11 additions & 0 deletions sentry_sdk/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import sys
import linecache
import logging
import functools

from contextlib import contextmanager
from datetime import datetime
Expand Down Expand Up @@ -768,3 +769,13 @@ def transaction_from_function(func):

# Possibly a lambda
return func_qualname


def wraps(f):
w = functools.wraps(f)
if PY2:
# Back port __wrapped_ attribute to Python 2. Present from Python > 3.2
# https://docs.python.org/3/library/functools.html#functools.update_wrapper
# https://github.com/getsentry/sentry-python/pull/475
w.__wrapped__ = f
return w
Empty file.
28 changes: 28 additions & 0 deletions tests/integrations/celery/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import pytest


@pytest.fixture
def init_celery(sentry_init):
pytest.importorskip("celery")

from sentry_sdk.integrations.celery import CeleryIntegration
from celery import Celery, VERSION

def inner(propagate_traces=True, **kwargs):
sentry_init(
integrations=[CeleryIntegration(propagate_traces=propagate_traces)],
**kwargs
)
celery = Celery(__name__)
if VERSION < (4,):
celery.conf.CELERY_ALWAYS_EAGER = True
else:
celery.conf.task_always_eager = True
return celery

return inner


@pytest.fixture
def celery(init_celery):
return init_celery()
25 changes: 1 addition & 24 deletions tests/integrations/celery/test_celery.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@
pytest.importorskip("celery")

from sentry_sdk import Hub, configure_scope
from sentry_sdk.integrations.celery import CeleryIntegration
from sentry_sdk._compat import text_type

from celery import Celery, VERSION
from celery import VERSION
from celery.bin import worker


Expand All @@ -21,28 +20,6 @@ def inner(signal, f):
return inner


@pytest.fixture
def init_celery(sentry_init):
def inner(propagate_traces=True, **kwargs):
sentry_init(
integrations=[CeleryIntegration(propagate_traces=propagate_traces)],
**kwargs
)
celery = Celery(__name__)
if VERSION < (4,):
celery.conf.CELERY_ALWAYS_EAGER = True
else:
celery.conf.task_always_eager = True
return celery

return inner


@pytest.fixture
def celery(init_celery):
return init_celery()


@pytest.fixture(
params=[
lambda task, x, y: (task.delay(x, y), {"args": [x, y], "kwargs": {}}),
Expand Down
36 changes: 36 additions & 0 deletions tests/integrations/celery/test_celery_once.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import pytest

pytest.importorskip("celery")
pytest.importorskip("celery_once")

from celery_once import QueueOnce


class DummyBackend(object):
def __init__(self, *args, **kwargs):
pass

def raise_or_lock(self, key, timeout):
assert key == "qo_tests.integrations.celery.test_celery_once.dummy_task_x-1_y-1"
assert timeout == 9001

def clear_lock(self, key):
assert key == "qo_tests.integrations.celery.test_celery_once.dummy_task_x-1_y-1"


@pytest.fixture
def celery_once(celery):
celery.conf.ONCE = {
"backend": "tests.integrations.celery.test_celery_once.DummyBackend",
"settings": {"default_timeout": 9001},
}


def test_celery_once(celery, celery_once):
# Ensure dummy backend is call with correct key to set and clear locks.

@celery.task(base=QueueOnce, once={"graceful": False})
def dummy_task(x, y):
pass

dummy_task.delay(1, 1)
1 change: 1 addition & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ deps =
beam-master: git+https://github.com/apache/beam#egg=apache-beam&subdirectory=sdks/python

celery-3: Celery>=3.1,<4.0
celery-3: celery_once>=3.0.1
celery-4.1: Celery>=4.1,<4.2
celery-4.2: Celery>=4.2,<4.3
celery-4.3: Celery>=4.3,<4.4
Expand Down