-
-
Notifications
You must be signed in to change notification settings - Fork 956
/
errors.py
130 lines (108 loc) · 4.02 KB
/
errors.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# Copyright © Michal Čihař <michal@weblate.org>
#
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import annotations
import logging
import sys
from json import JSONDecodeError
import sentry_sdk
from django.conf import settings
from django.utils.translation import get_language
from sentry_sdk.integrations.celery import CeleryIntegration
from sentry_sdk.integrations.django import DjangoIntegration
from sentry_sdk.integrations.logging import ignore_logger
from sentry_sdk.integrations.redis import RedisIntegration
import weblate.utils.version
ERROR_LOGGER = "weblate.errors"
LOGGER = logging.getLogger(ERROR_LOGGER)
try:
import rollbar
HAS_ROLLBAR = True
except ImportError:
HAS_ROLLBAR = False
def report_error(
level: str = "warning",
cause: str = "Handled exception",
*,
skip_sentry: bool = False,
print_tb: bool = False,
extra_log: str | None = None,
project=None,
message: bool = False,
) -> None:
"""
Report errors.
This can be used for store exceptions in error reporting solutions as rollbar while
handling error gracefully and giving user cleaner message.
"""
__traceback_hide__ = True # noqa: F841
if HAS_ROLLBAR and hasattr(settings, "ROLLBAR"):
rollbar.report_exc_info(level=level)
if not skip_sentry and settings.SENTRY_DSN:
sentry_sdk.set_tag("cause", cause)
if project is not None:
sentry_sdk.set_tag("project", project.slug)
sentry_sdk.set_tag("user.locale", get_language())
sentry_sdk.level = level
if message:
sentry_sdk.capture_message(cause)
else:
sentry_sdk.capture_exception()
log = getattr(LOGGER, level)
error = sys.exc_info()[1]
# Include JSON document if available. It might be missing
# when the error is raised from requests.
if isinstance(error, JSONDecodeError) and not extra_log and hasattr(error, "doc"):
extra_log = repr(error.doc)
if error:
log("%s: %s: %s", cause, error.__class__.__name__, error)
if extra_log:
if error:
log("%s: %s: %s", cause, error.__class__.__name__, extra_log)
else:
log("%s: %s", cause, extra_log)
if print_tb:
LOGGER.exception(cause)
def add_breadcrumb(category: str, message: str, level: str = "info", **data) -> None:
# Add breadcrumb only if settings are already loaded,
# we do not want to force loading settings early
if not settings.configured or not getattr(settings, "SENTRY_DSN", None):
return
sentry_sdk.add_breadcrumb(
category=category, message=message, level=level, data=data
)
def celery_base_data_hook(request, data) -> None:
data["framework"] = "celery"
def init_error_collection(celery=False) -> None:
if settings.SENTRY_DSN:
sentry_sdk.init(
dsn=settings.SENTRY_DSN,
integrations=[
CeleryIntegration(),
DjangoIntegration(),
RedisIntegration(),
],
send_default_pii=settings.SENTRY_SEND_PII,
release=weblate.utils.version.GIT_REVISION
or weblate.utils.version.TAG_NAME,
environment=settings.SENTRY_ENVIRONMENT,
traces_sample_rate=settings.SENTRY_TRACES_SAMPLE_RATE,
profiles_sample_rate=settings.SENTRY_PROFILES_SAMPLE_RATE,
in_app_include=[
"weblate",
"wlhosted",
"wllegal",
"weblate_fedora_messaging",
"weblate_language_data",
"translate",
],
attach_stacktrace=True,
_experiments={"max_spans": 2000},
**settings.SENTRY_EXTRA_ARGS,
)
# Ignore Weblate logging, those are reported using capture_exception
ignore_logger(ERROR_LOGGER)
if celery and HAS_ROLLBAR and hasattr(settings, "ROLLBAR"):
rollbar.init(**settings.ROLLBAR)
rollbar.BASE_DATA_HOOK = celery_base_data_hook
LOGGER.info("configured Rollbar error collection")