From 8524d24fd6fc68d720732ff6a30cbd4bc74d2085 Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Tue, 25 Aug 2026 17:41:23 +0200 Subject: [PATCH] feat(nuxt)!: Emit low cardinality db span names With span streaming, `db0` query spans are named after their `db.query.summary` (`SELECT users`) instead of the full SQL statement, and report that summary as a new `db.query.summary` attribute. The statement is sanitized before it is summarized, so a string literal containing `from`/`join` cannot leak a value into the name. db0 reports no db system, so a statement that cannot be summarized falls back to `db.namespace` and then to the static `Database operation`. `traceLifecycle: 'static'` keeps the existing names. Refs #23523 Co-Authored-By: Claude Opus 5 (1M context) --- .../src/runtime/utils/instrumentDatabase.ts | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/packages/nuxt/src/runtime/utils/instrumentDatabase.ts b/packages/nuxt/src/runtime/utils/instrumentDatabase.ts index 9f7d320fe390..859739e208ba 100644 --- a/packages/nuxt/src/runtime/utils/instrumentDatabase.ts +++ b/packages/nuxt/src/runtime/utils/instrumentDatabase.ts @@ -1,8 +1,13 @@ import { + _INTERNAL_getSqlQuerySummary, + _INTERNAL_sanitizeSqlQuery, addBreadcrumb, captureException, + DB_SPAN_NAME_FALLBACK, debug, flushIfServerless, + getClient, + hasSpanStreamingEnabled, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, type Span, @@ -220,10 +225,23 @@ function createBreadcrumb(query: string): void { * Creates a start span options object. */ function createStartSpanOptions(query: string, data: DatabaseSpanData): StartSpanOptions { + const client = getClient(); + // The statement is sanitized before it is summarized, so that a string literal containing + // `from`/`join` can't leak a value into the summary. + const querySummary = query ? _INTERNAL_getSqlQuerySummary(_INTERNAL_sanitizeSqlQuery(query)) : undefined; + // With span streaming, span names have to be low cardinality, so `{db.query.summary}` is used + // instead of the full statement, falling back to `{db.namespace}` when there is no statement to + // summarize. + const streamedName = + client && hasSpanStreamingEnabled(client) + ? querySummary || (data['db.namespace'] as string | undefined) || DB_SPAN_NAME_FALLBACK + : undefined; + return { - name: query, + name: streamedName ?? query, attributes: { 'db.query.text': query, + 'db.query.summary': querySummary, [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: SENTRY_ORIGIN, [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'db.query', ...data,