snapshot of https://github.com/zulip/zulip.git @ 48c69911c7dd4e03b20552eb3bd77ad8151c1357 (2026-09-15)
Some checks failed
Code scanning / CodeQL (push) Failing after 15s
Zulip production suite / Ubuntu 22.04 production build (push) Failing after 26s
Zulip production suite / Debian 12 production install with custom db name and user (push) Has been skipped
Zulip production suite / Ubuntu 22.04 production install and PostgreSQL upgrade with pgroonga (push) Has been skipped
Zulip production suite / Ubuntu 24.04 production install (push) Has been skipped
Zulip production suite / Ubuntu 26.04 production install (push) Has been skipped
Zulip production suite / Debian 13 production install (push) Has been skipped
Zulip production suite / 7.0 Version Upgrade (push) Has been skipped
Zulip production suite / 8.0 Version Upgrade (push) Has been skipped
Zulip production suite / 6.0 Version Upgrade (push) Has been skipped
Zulip production suite / 10.0 Version Upgrade (push) Has been skipped
Zulip production suite / 9.0 Version Upgrade (push) Has been skipped
Zulip production suite / 12.0 Version Upgrade (push) Has been skipped
Zulip production suite / 11.0 Version Upgrade (push) Has been skipped
GitHub Actions Security Analysis with zizmor / zizmor (push) Failing after 3s
Zulip CI / Debian 12 (Python 3.11, backend + documentation) (push) Failing after 26s
Zulip CI / Ubuntu 22.04 (Python 3.10, backend + frontend) (push) Failing after 3s
Zulip CI / Ubuntu 24.04 (Python 3.12, backend) (push) Failing after 25s
Zulip CI / Ubuntu 26.04 (Python 3.14, backend) (push) Failing after 25s
Zulip CI / Debian 13 (Python 3.13, backend) (push) Failing after 28s
Zulip production suite / Required jobs (push) Has been cancelled
Zulip CI / Required jobs (push) Has been cancelled
API Documentation Update Check / check-feature-level-updated (push) Has been cancelled
API Documentation Update Check / notify-if-api-docs-changed (push) Has been cancelled

This commit is contained in:
upstream-mirror
2026-09-15 15:05:30 +05:00
commit 64898b2c79
8999 changed files with 1757358 additions and 0 deletions

121
zproject/sentry.py Normal file
View File

@@ -0,0 +1,121 @@
import os
from typing import TYPE_CHECKING, Any, Optional
import sentry_sdk
from django.utils.translation import override as override_language
from sentry_sdk.integrations import Integration
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.tornado import TornadoIntegration
from sentry_sdk.utils import capture_internal_exceptions
from version import ZULIP_VERSION
from zproject.config import DEPLOY_ROOT
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.models.users 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", {})
user_id = user_info.get("id")
if isinstance(user_id, str):
user_profile = get_user_profile_by_id(int(user_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"]
return event
def traces_sampler(sampling_context: dict[str, Any]) -> float | bool:
from django.conf import settings
queue = sampling_context.get("queue")
if queue is not None and isinstance(queue, str):
if isinstance(settings.SENTRY_TRACE_WORKER_RATE, dict):
return settings.SENTRY_TRACE_WORKER_RATE.get(queue, 0.0)
else:
return settings.SENTRY_TRACE_WORKER_RATE
else:
return settings.SENTRY_TRACE_RATE
def setup_sentry(dsn: str | None, environment: str) -> None:
from django.conf import settings
if not dsn:
return
sentry_release = ZULIP_VERSION
if os.path.exists(os.path.join(DEPLOY_ROOT, "sentry-release")):
with open(os.path.join(DEPLOY_ROOT, "sentry-release")) as sentry_release_file:
sentry_release = sentry_release_file.readline().strip()
integrations: list[Integration] = [
RedisIntegration(),
]
disabled_integrations = []
if settings.RUNNING_INSIDE_TORNADO:
integrations.append(TornadoIntegration())
disabled_integrations.append(DjangoIntegration())
else:
integrations.append(DjangoIntegration())
sentry_sdk.init(
dsn=dsn,
environment=environment,
release=sentry_release,
integrations=integrations,
disabled_integrations=disabled_integrations,
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,
traces_sampler=traces_sampler,
profiles_sample_rate=settings.SENTRY_PROFILE_RATE,
)
# Ignore all of the loggers from django.security that are for user
# errors; see https://docs.djangoproject.com/en/5.0/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")