From 87af80c936866fd6db5486e841a014d85a5015f6 Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Wed, 8 Jul 2026 11:45:30 +0200 Subject: [PATCH 1/2] feat: Add `navigation.route.id` and use it in description rule --- .../sentry-conventions/src/attributes.ts | 36 +++++++++++++++++++ .../navigation/navigation__route__id.json | 17 +++++++++ model/description/browser.json | 8 ++--- python/src/sentry_conventions/attributes.py | 25 +++++++++++++ 4 files changed, 82 insertions(+), 4 deletions(-) create mode 100644 model/attributes/navigation/navigation__route__id.json diff --git a/javascript/sentry-conventions/src/attributes.ts b/javascript/sentry-conventions/src/attributes.ts index d0ae03d6..8d22e181 100644 --- a/javascript/sentry-conventions/src/attributes.ts +++ b/javascript/sentry-conventions/src/attributes.ts @@ -10520,6 +10520,27 @@ export const NAVIGATION_ORIGIN = 'navigation.origin'; */ export type NAVIGATION_ORIGIN_TYPE = string; +// Path: model/attributes/navigation/navigation__route__id.json + +/** + * The identifier of the matched client-side route, as assigned by the routing framework (e.g., vue-router name, react-router id). `navigation.route.id` + * + * Attribute Value Type: `string` {@link NAVIGATION_ROUTE_ID_TYPE} + * + * Apply Scrubbing: auto + * + * Attribute defined in OTEL: No + * Visibility: public + * + * @example "AboutView" + */ +export const NAVIGATION_ROUTE_ID = 'navigation.route.id'; + +/** + * Type for {@link NAVIGATION_ROUTE_ID} navigation.route.id + */ +export type NAVIGATION_ROUTE_ID_TYPE = string; + // Path: model/attributes/navigation/navigation__type.json /** @@ -16502,6 +16523,7 @@ export const ATTRIBUTE_TYPE: Record = { method: 'string', 'middleware.name': 'string', 'navigation.origin': 'string', + 'navigation.route.id': 'string', 'navigation.type': 'string', 'nel.elapsed_time': 'integer', 'nel.phase': 'string', @@ -17227,6 +17249,7 @@ export type AttributeName = | typeof METHOD | typeof MIDDLEWARE_NAME | typeof NAVIGATION_ORIGIN + | typeof NAVIGATION_ROUTE_ID | typeof NAVIGATION_TYPE | typeof NEL_ELAPSED_TIME | typeof NEL_PHASE @@ -23947,6 +23970,18 @@ export const ATTRIBUTE_METADATA: Record = { aliases: ['sentry.sveltekit.navigation.from'], changelog: [{ version: 'next', prs: [467], description: 'Added navigation.origin attribute' }], }, + 'navigation.route.id': { + brief: + 'The identifier of the matched client-side route, as assigned by the routing framework (e.g., vue-router name, react-router id).', + type: 'string', + applyScrubbing: { + key: 'auto', + }, + isInOtel: false, + visibility: 'public', + example: 'AboutView', + changelog: [{ version: 'next', description: 'Added navigation.route.id attribute' }], + }, 'navigation.type': { brief: 'The type of navigation done by a client-side router.', type: 'string', @@ -27554,6 +27589,7 @@ export type Attributes = { [METHOD]?: METHOD_TYPE; [MIDDLEWARE_NAME]?: MIDDLEWARE_NAME_TYPE; [NAVIGATION_ORIGIN]?: NAVIGATION_ORIGIN_TYPE; + [NAVIGATION_ROUTE_ID]?: NAVIGATION_ROUTE_ID_TYPE; [NAVIGATION_TYPE]?: NAVIGATION_TYPE_TYPE; [NEL_ELAPSED_TIME]?: NEL_ELAPSED_TIME_TYPE; [NEL_PHASE]?: NEL_PHASE_TYPE; diff --git a/model/attributes/navigation/navigation__route__id.json b/model/attributes/navigation/navigation__route__id.json new file mode 100644 index 00000000..d6869eeb --- /dev/null +++ b/model/attributes/navigation/navigation__route__id.json @@ -0,0 +1,17 @@ +{ + "key": "navigation.route.id", + "brief": "The identifier of the matched client-side route, as assigned by the routing framework (e.g., vue-router name, react-router id).", + "type": "string", + "apply_scrubbing": { + "key": "auto" + }, + "is_in_otel": false, + "example": "AboutView", + "visibility": "public", + "changelog": [ + { + "version": "next", + "description": "Added navigation.route.id attribute" + } + ] +} diff --git a/model/description/browser.json b/model/description/browser.json index ed7133b9..4c6b03b6 100644 --- a/model/description/browser.json +++ b/model/description/browser.json @@ -5,15 +5,15 @@ "name": "Pageload", "brief": "A full page load of a web application.", "ops": ["pageload"], - "templates": ["{{url.template}}", "{{url.path}}", "{{url.full}}"], - "examples": ["/users/:id", "/users/123", "http://example.com/users/123"] + "templates": ["{{navigation.route.id}}", "{{url.template}}", "{{url.path}}", "{{url.full}}"], + "examples": ["user-profile", "/users/:id", "/users/123", "http://example.com/users/123"] }, { "name": "Navigation", "brief": "Client-side browser history change in a web application.", "ops": ["navigation"], - "templates": ["{{url.template}}", "{{url.path}}", "{{url.full}}"], - "examples": ["/users/:id", "/users/123", "http://example.com/users/123"] + "templates": ["{{navigation.route.id}}", "{{url.template}}", "{{url.path}}", "{{url.full}}"], + "examples": ["user-profile", "/users/:id", "/users/123", "http://example.com/users/123"] } ] } diff --git a/python/src/sentry_conventions/attributes.py b/python/src/sentry_conventions/attributes.py index 6718f0a9..ab36e302 100644 --- a/python/src/sentry_conventions/attributes.py +++ b/python/src/sentry_conventions/attributes.py @@ -6224,6 +6224,17 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): Example: "/users/:id" """ + # Path: model/attributes/navigation/navigation__route__id.json + NAVIGATION_ROUTE_ID: Literal["navigation.route.id"] = "navigation.route.id" + """The identifier of the matched client-side route, as assigned by the routing framework (e.g., vue-router name, react-router id). + + Type: str + Apply Scrubbing: auto + Defined in OTEL: No + Visibility: public + Example: "AboutView" + """ + # Path: model/attributes/navigation/navigation__type.json NAVIGATION_TYPE: Literal["navigation.type"] = "navigation.type" """The type of navigation done by a client-side router. @@ -16269,6 +16280,19 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): ), ], ), + "navigation.route.id": AttributeMetadata( + brief="The identifier of the matched client-side route, as assigned by the routing framework (e.g., vue-router name, react-router id).", + type=AttributeType.STRING, + apply_scrubbing=ApplyScrubbingInfo(key=ApplyScrubbing.AUTO), + is_in_otel=False, + visibility=Visibility.PUBLIC, + example="AboutView", + changelog=[ + ChangelogEntry( + version="next", description="Added navigation.route.id attribute" + ), + ], + ), "navigation.type": AttributeMetadata( brief="The type of navigation done by a client-side router.", type=AttributeType.STRING, @@ -19985,6 +20009,7 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta): "method": str, "middleware.name": str, "navigation.origin": str, + "navigation.route.id": str, "navigation.type": str, "nel.elapsed_time": int, "nel.phase": str, From 7ec911957a95ca7f64492cb9cacb7d6169e0da1c Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Mon, 13 Jul 2026 10:26:11 +0200 Subject: [PATCH 2/2] better example --- model/description/browser.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/model/description/browser.json b/model/description/browser.json index 4c6b03b6..437a6275 100644 --- a/model/description/browser.json +++ b/model/description/browser.json @@ -6,14 +6,14 @@ "brief": "A full page load of a web application.", "ops": ["pageload"], "templates": ["{{navigation.route.id}}", "{{url.template}}", "{{url.path}}", "{{url.full}}"], - "examples": ["user-profile", "/users/:id", "/users/123", "http://example.com/users/123"] + "examples": ["UserProfile", "/users/:id", "/users/123", "http://example.com/users/123"] }, { "name": "Navigation", "brief": "Client-side browser history change in a web application.", "ops": ["navigation"], "templates": ["{{navigation.route.id}}", "{{url.template}}", "{{url.path}}", "{{url.full}}"], - "examples": ["user-profile", "/users/:id", "/users/123", "http://example.com/users/123"] + "examples": ["UserProfile", "/users/:id", "/users/123", "http://example.com/users/123"] } ] }