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,