mirror of
https://github.com/zulip/zulip.git
synced 2025-10-26 09:34:02 +00:00
This increases the possible maximum wait time to send exceptions during shutdown. The larger value makes it possible to send larger exceptions, and weather larger network hiccups, during shutdown. In instances where a service is crash-looping, it is already not serving requests reliably, and better ensuring those exceptions are captured is of significant value.
98 lines
4.2 KiB
Python
98 lines
4.2 KiB
Python
from typing import TYPE_CHECKING, Optional
|
|
|
|
import sentry_sdk
|
|
from django.utils.translation import override as override_language
|
|
from sentry_sdk.integrations.django import DjangoIntegration
|
|
from sentry_sdk.integrations.logging import ignore_logger
|
|
from sentry_sdk.integrations.redis import RedisIntegration
|
|
from sentry_sdk.integrations.sqlalchemy import SqlalchemyIntegration
|
|
from sentry_sdk.utils import capture_internal_exceptions
|
|
|
|
from version import ZULIP_VERSION
|
|
|
|
if TYPE_CHECKING:
|
|
from sentry_sdk._types import Event, Hint
|
|
|
|
|
|
def add_context(event: "Event", hint: "Hint") -> Optional["Event"]:
|
|
if "exc_info" in hint:
|
|
_, exc_value, _ = hint["exc_info"]
|
|
# Ignore GeneratorExit, KeyboardInterrupt, and SystemExit exceptions
|
|
if not isinstance(exc_value, Exception):
|
|
return None
|
|
from django.conf import settings
|
|
|
|
from zerver.lib.request import RequestNotes, get_current_request
|
|
from zerver.models import get_user_profile_by_id
|
|
|
|
with capture_internal_exceptions():
|
|
# event.user is the user context, from Sentry, which is
|
|
# pre-populated with some keys via its Django integration:
|
|
# https://docs.sentry.io/platforms/python/guides/django/enriching-error-data/additional-data/identify-user/
|
|
event.setdefault("tags", {})
|
|
user_info = event.get("user", {})
|
|
if user_info.get("id"):
|
|
user_profile = get_user_profile_by_id(user_info["id"])
|
|
event["tags"]["realm"] = user_info["realm"] = user_profile.realm.string_id or "root"
|
|
with override_language(settings.LANGUAGE_CODE):
|
|
# str() to force the lazy-translation to apply now,
|
|
# since it won't serialize into json for Sentry otherwise
|
|
user_info["role"] = str(user_profile.get_role_name())
|
|
|
|
# These are PII, and should be scrubbed
|
|
if "username" in user_info:
|
|
del user_info["username"]
|
|
if "email" in user_info:
|
|
del user_info["email"]
|
|
|
|
request = get_current_request()
|
|
if request:
|
|
request_notes = RequestNotes.get_notes(request)
|
|
if request_notes.client is not None:
|
|
event["tags"]["client"] = request_notes.client.name
|
|
if request_notes.realm is not None:
|
|
event["tags"].setdefault("realm", request_notes.realm.string_id)
|
|
return event
|
|
|
|
|
|
def setup_sentry(dsn: Optional[str], environment: str) -> None:
|
|
if not dsn:
|
|
return
|
|
sentry_sdk.init(
|
|
dsn=dsn,
|
|
environment=environment,
|
|
release=ZULIP_VERSION,
|
|
integrations=[
|
|
DjangoIntegration(),
|
|
RedisIntegration(),
|
|
SqlalchemyIntegration(),
|
|
],
|
|
before_send=add_context,
|
|
# Increase possible max wait to send exceptions during
|
|
# shutdown, from 2 to 10; potentially-large exceptions are of
|
|
# value to catch during shutdown.
|
|
shutdown_timeout=10,
|
|
# Because we strip the email/username from the Sentry data
|
|
# above, the effect of this flag is that the requests/users
|
|
# involved in exceptions will be identified in Sentry only by
|
|
# their IP address, user ID, realm, and role. We consider
|
|
# this an appropriate balance between avoiding Sentry getting
|
|
# PII while having the identifiers needed to determine that an
|
|
# exception only affects a small subset of users or realms.
|
|
send_default_pii=True,
|
|
)
|
|
|
|
# Ignore all of the loggers from django.security that are for user
|
|
# errors; see https://docs.djangoproject.com/en/3.2/ref/exceptions/#suspiciousoperation
|
|
ignore_logger("django.security.SuspiciousOperation")
|
|
ignore_logger("django.security.DisallowedHost")
|
|
ignore_logger("django.security.DisallowedModelAdminLookup")
|
|
ignore_logger("django.security.DisallowedModelAdminToField")
|
|
ignore_logger("django.security.DisallowedRedirect")
|
|
ignore_logger("django.security.InvalidSessionKey")
|
|
ignore_logger("django.security.RequestDataTooBig")
|
|
ignore_logger("django.security.SuspiciousFileOperation")
|
|
ignore_logger("django.security.SuspiciousMultipartForm")
|
|
ignore_logger("django.security.SuspiciousSession")
|
|
ignore_logger("django.security.TooManyFieldsSent")
|