Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Logging on Exceptions #117

Open
colinhowe opened this issue Jul 24, 2017 · 5 comments
Open

Logging on Exceptions #117

colinhowe opened this issue Jul 24, 2017 · 5 comments

Comments

@colinhowe
Copy link

We use Sentry to capture exceptions. At the moment django_cron captures all unhandled exceptions and logs them to its own error model. Would you accept a PR that also records the unhandled exception using the standard logging framework? This would allow django_cron to integrate with anything that listens to logs.

@MaZZly
Copy link

MaZZly commented Oct 15, 2017

I'd be interested in something similar to get my cronjob failuers to also log into Sentry

@cjsoftuk
Copy link

cjsoftuk commented Feb 5, 2018

+1 on this. I understand why it captures all exceptions though (as this avoids Cron jobs crashing the django_cron internals and preventing jobs running).

What is probably needed is to find a way to allow Raven (or a.n.other monitoring framework) to hook a job failure.

@lauritzen
Copy link

lauritzen commented Aug 14, 2018

I've accomplished this by adding a post_save hook on the job object which pushes the cron exception message to Sentry:

from django_cron.models import CronJobLog
from django.db.models.signals import post_save
from django.dispatch import receiver
from raven.contrib.django.raven_compat.models import client


@receiver(post_save, sender=CronJobLog, dispatch_uid="propagate_cron_exception")
def propagate_cron_exception(sender, instance, **kwargs):
    if not instance.is_success:
        client.captureMessage("Exception in cron\n\n{}".format(instance.message))

@will-emmerson
Copy link

The post_save hook above is clever but unfortunately returns exception as text which doesn't look great in Sentry. I ended up catching the exception, logging it and re-raising it, which definitely is not clever:

from sentry_sdk import capture_exception

class GetPriceImbalance(CronJobBase):
    RUN_EVERY_MINS = 60 * 3

    schedule = Schedule(run_every_mins=RUN_EVERY_MINS)
    code = 'price_imbalance'

    def do(self):
        try:
            get_price_imbalance_data()
        except Exception as e:
            capture_exception(e)
            raise

@lauritzen
Copy link

True, which is actually a big shortcoming. You could create a decorator to streamline the code a bit:

from functools import wraps
def sentry_exceptions(func):
    @wraps(func)
    def inner(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except Exception as e:
            capture_exception(e)
            raise

    return inner

Which lets you:

class GetPriceImbalance(CronJobBase):
    RUN_EVERY_MINS = 60 * 3

    schedule = Schedule(run_every_mins=RUN_EVERY_MINS)
    code = 'price_imbalance'

    @sentry_exceptions
    def do(self):
        get_price_imbalance_data()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants