Repository navigation
feat(workflow_engine): Document metric monitor aggregates in the API schema - #129451
sentry-junior[bot] wants to merge 5 commits into
Conversation
…schema The detector data_sources field was a plain ListField, so the generated OpenAPI schema typed it as an array of unknown items. Clients copied the accepted aggregate values from the backend source and drifted from it. Document each metric data source (errors, spans, logs, application metrics, crash rate) as a oneOf branch keyed by dataset and event types. Build each aggregate enum or pattern from the constants the validator checks against: EAP_FUNCTIONS intersected with the dataset definitions, TRANSLATABLE_COLUMNS, and CRASH_RATE_ALERT_AGGREGATE_RE. Drop the stale percentile() examples from the help text, since EAP spans don't define percentile. Refs #129450 Co-Authored-By: BYK <126780+BYK@users.noreply.github.com>
BYK
left a comment
There was a problem hiding this comment.
Transactions dataset left out. It's deprecated, and creating transaction alerts is already blocked behind discover-saved-queries-deprecation. A client that validates requests strictly against this schema could no longer send it. Should it get a loose branch?
Nope, this is good.
Only metric data sources are documented. The same request schema serves every detector type, but the public docs only advertise metric_issue, so cron and uptime payloads aren't described. Is that acceptable, or should there be a permissive fallback? A fallback would mean anyOf, which makes the union useless for validation.
Can you provide more context on this as I don't fully understand the implications.
Errors enum is the practical set, not an exhaustive allowlist. The backend accepts any Discover function whose column is empty or allowlisted, as long as the test query runs. Spans similarly accept a few Insights functions outside EAP_FUNCTIONS, such as http_response_rate(5). The schema documents the explicit alerting allowlist.
Is there a decision needs to be made here? If yes, I don't understand and need more context.
Nested properties are snake_case (event_types, time_window), which matches how drf-spectacular names every other field in this schema. The API accepts both cases.
What's the other case?
…rrides Detector validator subclasses override data_sources with their own ListField, which mypy rejected once the base field became DataSourcesField.
…n monitors The monitor UI offers both functions for span monitors since #112146, but they were missing from EAP_FUNCTIONS. opportunity_score fell through to legacy Discover validation and was rejected as an invalid function. performance_score passed only through the older Insights shortcut. Co-Authored-By: BYK <126780+BYK@users.noreply.github.com>
…hema Document why only metric data sources are described, and which aggregates the validator accepts that the schema leaves out on purpose. Co-Authored-By: BYK <126780+BYK@users.noreply.github.com>
…ource schema The monitor form lists its span and log aggregates in TypeScript, separately from EAP_FUNCTIONS, and the two drifted: the UI offered opportunity_score while the backend rejected it. Parse the frontend lists and check that each offered function matches the schema branch for its dataset. The schema is built from EAP_FUNCTIONS and the dataset definitions, so this covers both. The logs form also offers epm, eps, p100, performance_score, and opportunity_score, which the logs definitions don't define. They are listed as known gaps until the UI stops offering them. Co-Authored-By: BYK <126780+BYK@users.noreply.github.com>
BaseDetectorTypeValidator.data_sourcesis a plainListField, so the public schema types it asArray<unknown>. Clients such as@sentry/apiand the Sentry CLI copy the acceptedaggregatevalues from backend source, and their copies drift.This gives the field an explicit schema without changing how it is validated: each item is a
oneOfof the metric data sources (Errors, Spans, Logs, Application Metrics, Crash Rate). Each branch is keyed bydatasetandevent_types, and itsaggregategets an enum or pattern built from the constants the validator already checks against:aggregateevents)count(),count_unique(user|dist|release)and theirtags[sentry:*]formsTRANSLATABLE_COLUMNStrace_item_span)EAP_FUNCTIONScallsEAP_FUNCTIONS∩SPAN_DEFINITIONStrace_item_log)p100and the formulasEAP_FUNCTIONS∩OURLOG_DEFINITIONStrace_item_metric)equation|…TRACE_METRICS_DEFINITIONSmetrics)CRASH_RATE_ALERT_AGGREGATE_RECRASH_RATE_ALERT_AGGREGATE_REloses a redundant\,escape. Python treats\,and,the same, but ECMAScriptu-mode regexes (which ajv and other JSON Schema validators use) reject\,. The help text also drops thepercentile(...)examples, because EAP spans don't definepercentile. A test checks that every JSON example in the help text matches exactly one branch, so the prose and the schema can't drift apart again.EAP_FUNCTIONSgainsperformance_scoreandopportunity_score. The span monitor UI has offered both since #112146, but they were never added to the allowlist:opportunity_scorefell through to legacy Discover validation and was rejected as an invalid function, andperformance_scorepassed only through an older Insights shortcut.To stop this drift recurring, a test parses the monitor form's TypeScript aggregate lists (
ALLOWED_EXPLORE_VISUALIZE_AGGREGATES,ADDITIONAL_EAP_AGGREGATES,LOGS_EXCLUDED_AGGREGATES) and checks that each offered function matches the schema branch for its dataset, the same waytest_frontend_datadog_sites_match_backendchecks the Datadog site list. It found one more gap: the logs form offersepm,eps,p100,performance_score, andopportunity_score, which the logs definitions don't define, so building the subscription request fails with "Unknown function". The test lists those as known gaps until the frontend stops offering them.Scope decisions (also documented in the
metric_data_source_schemamodule docstring):metric_issuemonitors. Cron and uptime data sources are still accepted at runtime and aren't described. A catch-all branch would make theoneOfmatch anything, so clients couldn't use it to check aggregates.discover-saved-queries-deprecation.count()andcount_unique()over the allowlisted columns. The backend also accepts other Discover functions when the test query runs. Spans leaves outhttp_response_rate,cache_miss_rate, andcount_scores. They pass through a 2024 shortcut for span metrics alerts, but since 2025 Insights creates monitors with equivalentcount()queries instead, because Explore and alerts don't support these functions.event_types,time_window), the same as every other field drf-spectacular generates in this schema. The API accepts both cases.Fixes #129450
Fixes ENG-8945
via @BYK.
--
View Session in Sentry