Skip to main content

backend-conventions

Sentry backend conventions for logging, tracing/spans, span/tag attribute naming, metrics tags, and the options system. Use when adding or editing Python in src/ that logs (logger.info/exception), records metrics (metrics.incr/timing with tags), instruments spans/transactions, calls sentry_sdk.set_tag/set_attribute or set_span_tag/set_span_data, or reads registered options with options.get(). Trigger on "add logging", "log an error", "add a metric", "add a span", "instrument tracing", "set an attribute", "add a tag", "read an option", "LOG005", "LOG011", or metrics tag cardinality questions.

معلومات المصدر

المستودع
getsentry/sentry
آخر نشاط في المصدر
٢٣ سبتمبر ٢٠٢٦ في ٠٨:٤١
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
٤٥٬٥٧٤
التفرعات
٤٬٩٣٠

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
backend-conventions
description
Sentry backend conventions for logging, tracing/spans, span/tag attribute naming, metrics tags, and the options system. Use when adding or editing Python in src/ that logs (logger.info/exception), records metrics (metrics.incr/timing with tags), instruments spans/transactions, calls sentry_sdk.set_tag/set_attribute or set_span_tag/set_span_data, or reads registered options with options.get(). Trigger on "add logging", "log an error", "add a metric", "add a span", "instrument tracing", "set an attribute", "add a tag", "read an option", "LOG005", "LOG011", or metrics tag cardinality questions.
# Backend Conventions: Logging, Tracing, Metrics, Options ## Options System Sentry uses a centralized options system where all options are registered in `src/sentry/options/defaults.py` with required default values. ```python # CORRECT: options.get() without default - registered default is used from sentry import options batch_size = options.get("deletions.group-hash-metadata.batch-size") # WRONG: Redundant default value batch_size = options.get("deletions.group-hash-metadata.batch-size", 1000) ``` **Important**: Never add a default value to `options.get()` calls. All options are registered via `register()` in `defaults.py` which requires a default value. The options system always returns the registered default if no value is set, making a second default parameter redundant and potentially inconsistent. ## Logging Pattern ```python import logging from sentry import analytics from sentry.analytics.events.feature_used import FeatureUsedEvent # does not exist, only for demonstration purposes logger = logging.getLogger(__name__) # Structured logging logger.info( "user.action.complete", extra={ "user_id": user.id, "action": "login", "ip_address": request.META.get("REMOTE_ADDR"), } ) # IMPORTANT: LOG005 use exception() within an exception handler # WRONG: Calling logger.error() when capturing exception try: risky_operation() except ValidationError as e: logger.error("error.invalid_payload") # RIGHT: Use logger.exception() with a message when capturing an exception try: risky_operation() except ValidationError: logger.exception("error.invalid_payload") # IMPORTANT: Avoid LOG011 - Never pre-format log messages with f-strings or .format() # WRONG: Pre-formatting evaluates before logger call, even if logging is disabled logger.info(f"User {user.id} completed {action}") logger.info("User {} completed {}".format(user.id, action)) # RIGHT: Use logger's %-formatting for lazy evaluation logger.info("%s.user.action.complete", PREFIX) # ALSO RIGHT: Use structured logging with extra parameters only logger.info( "user.action.complete", extra={"user_id": user.id} ) # Analytics event analytics.record( FeatureUsedEvent( user_id=user.id, organization_id=org.id, feature="new-dashboard", ) ) ``` ## Span / Tag Attribute Names Before inventing a key for `sentry_sdk.set_tag`/`set_attribute`, `set_span_tag`, or `set_span_data`, check whether OTel or Sentry already has a standard name for it in `sentry_conventions.attributes.ATTRIBUTE_NAMES`. Reusing a convention name keeps the attribute queryable and consistent with what other producers (SDKs, Relay) already emit for the same concept — a bespoke name fragments the same data across two keys. ```python from sentry_conventions.attributes import ATTRIBUTE_NAMES # WRONG: inventing a name for a concept the conventions already cover sentry_sdk.set_attribute("request_user_agent", user_agent) # RIGHT: use the existing convention name sentry_sdk.set_attribute(ATTRIBUTE_NAMES.USER_AGENT_ORIGINAL, user_agent) ``` `ATTRIBUTE_NAMES` is generated from the OTel semantic conventions plus Sentry's own model (`.venv/lib/python*/site-packages/sentry_conventions/attributes.py`); grep it for candidate keywords before adding a new one. Only fall back to a custom key when the concept genuinely isn't covered, and prefer a namespaced, descriptive name over a generic one. A key kept behind a `_test`/POC suffix while a feature is unreleased is a separate, deliberate case — that's about hiding the field, not about picking its name. ## Metrics Tags Every distinct tag-value combination is a separate time series, so keep tags **low-cardinality, meaningful, and minimal**: - Add a tag only if you'll actually filter or group by it. Fewer is better. - Tag values must be bounded/enumerable (e.g. `status`, `platform`, `reason`) — never unbounded identifiers (IDs, emails, URLs, free text). The middleware (`src/sentry/metrics/middleware.py`) enforces this by denylisting tag keys that **end in `_id`** or that are exactly **`event`/`project`/`group`**. Such tags **will not work**: they're silently stripped by default, and raise `BadMetricTags` when `SENTRY_METRICS_DISALLOW_BAD_TAGS` is on (e.g. CI) — so a metric that looks fine locally can fail elsewhere. ```python metrics.incr("my.metric", tags={"project_id": project.id}) # WRONG: stripped / raises metrics.incr("my.metric", tags={"platform": project.platform}) # RIGHT: bounded values ``` A few keys are allowlisted despite the rule (see `_NOT_BAD_TAGS`); don't expand it to work around the constraint — pick a low-cardinality tag instead.
عرض على GitHub