Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ export function instrumentDurableObjectStorage(
{
// Use underscore naming to match Cloudflare's native instrumentation (e.g., "durable_object_storage_get")
name: `durable_object_storage_${methodName}`,
onlyIfParent: true,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alarm link stores dropped span

Low Severity

setAlarm now starts with onlyIfParent, so a call without a parent creates a non-recording placeholder. storeSpanContext still runs inside that callback and persists the placeholder via getActiveSpan. When the alarm later fires, it links to a span that was never sent.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 88ae1fa. Configure here.

attributes: {
[SENTRY_OP]: DB,
[SENTRY_ORIGIN]: 'auto.db.cloudflare.durable_object',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export function instrumentDurableObjectSyncKvStorage(syncKv: SyncKvStorage): Syn
return startSpan(
{
name: `durable_object_storage_kv_${methodName}`,
onlyIfParent: true,
attributes: {
[SENTRY_OP]: DB,
[SENTRY_ORIGIN]: 'auto.db.cloudflare.durable_object',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export function instrumentSqlStorage(sql: SqlStorage): SqlStorage {
// steps. We still start the span so it records its dropped span
// outcome. A query that may target a `cf_` or `pi_` table takes the full path,
// because an internal query must start no span.
return startSpan({ name: 'exec', attributes: SPAN_ATTRIBUTES }, callOriginal);
return startSpan({ name: 'exec', onlyIfParent: true, attributes: SPAN_ATTRIBUTES }, callOriginal);
}

const sanitizedQuery = sanitizeSqlQuery(query);
Expand All @@ -64,6 +64,7 @@ export function instrumentSqlStorage(sql: SqlStorage): SqlStorage {
return startSpan(
{
name: querySummary || sanitizedQuery,
onlyIfParent: true,
attributes: {
...SPAN_ATTRIBUTES,
[DB_QUERY_TEXT]: sanitizedQuery,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ function createStartSpanOptions(queryText: string | undefined, type: D1QueryType

return {
name,
onlyIfParent: true,
attributes: {
[SENTRY_OP]: DB_QUERY,
[DB_SYSTEM_NAME]: 'cloudflare-d1',
Expand Down Expand Up @@ -185,6 +186,7 @@ function instrumentBatch(
return startSpan(
{
name: 'D1 batch',
onlyIfParent: true,
attributes: {
[SENTRY_OP]: DB_QUERY,
[DB_SYSTEM_NAME]: 'cloudflare-d1',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ function createSpanOptions(bindingName: string, operation: KVOperation, args: un
const keys = getCacheKeys(operation, args);
return {
name: cacheOperation,
onlyIfParent: true,
attributes: {
[SENTRY_OP]: cacheOperation,
[CACHE_OPERATION]: cacheOperationName,
Expand Down
12 changes: 12 additions & 0 deletions packages/cloudflare/test/instrumentDurableObjectStorage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ describe('instrumentDurableObjectStorage', () => {

expect(startSpanSpy).toHaveBeenCalledWith(
{
onlyIfParent: true,
name: 'durable_object_storage_get',
attributes: {
'sentry.op': 'db',
Expand All @@ -50,6 +51,7 @@ describe('instrumentDurableObjectStorage', () => {

expect(startSpanSpy).toHaveBeenCalledWith(
{
onlyIfParent: true,
name: 'durable_object_storage_get',
attributes: {
'sentry.op': 'db',
Expand All @@ -73,6 +75,7 @@ describe('instrumentDurableObjectStorage', () => {

expect(startSpanSpy).toHaveBeenCalledWith(
{
onlyIfParent: true,
name: 'durable_object_storage_put',
attributes: {
'sentry.op': 'db',
Expand All @@ -94,6 +97,7 @@ describe('instrumentDurableObjectStorage', () => {

expect(startSpanSpy).toHaveBeenCalledWith(
{
onlyIfParent: true,
name: 'durable_object_storage_put',
attributes: {
'sentry.op': 'db',
Expand All @@ -117,6 +121,7 @@ describe('instrumentDurableObjectStorage', () => {

expect(startSpanSpy).toHaveBeenCalledWith(
{
onlyIfParent: true,
name: 'durable_object_storage_delete',
attributes: {
'sentry.op': 'db',
Expand All @@ -138,6 +143,7 @@ describe('instrumentDurableObjectStorage', () => {

expect(startSpanSpy).toHaveBeenCalledWith(
{
onlyIfParent: true,
name: 'durable_object_storage_delete',
attributes: {
'sentry.op': 'db',
Expand All @@ -161,6 +167,7 @@ describe('instrumentDurableObjectStorage', () => {

expect(startSpanSpy).toHaveBeenCalledWith(
{
onlyIfParent: true,
name: 'durable_object_storage_list',
attributes: {
'sentry.op': 'db',
Expand All @@ -184,6 +191,7 @@ describe('instrumentDurableObjectStorage', () => {

expect(startSpanSpy).toHaveBeenCalledWith(
{
onlyIfParent: true,
name: 'durable_object_storage_setAlarm',
attributes: {
'sentry.op': 'db',
Expand Down Expand Up @@ -268,6 +276,7 @@ describe('instrumentDurableObjectStorage', () => {

expect(startSpanSpy).toHaveBeenCalledWith(
{
onlyIfParent: true,
name: 'durable_object_storage_getAlarm',
attributes: {
'sentry.op': 'db',
Expand All @@ -289,6 +298,7 @@ describe('instrumentDurableObjectStorage', () => {

expect(startSpanSpy).toHaveBeenCalledWith(
{
onlyIfParent: true,
name: 'durable_object_storage_deleteAlarm',
attributes: {
'sentry.op': 'db',
Expand All @@ -312,6 +322,7 @@ describe('instrumentDurableObjectStorage', () => {

expect(startSpanSpy).toHaveBeenCalledWith(
{
onlyIfParent: true,
name: 'SELECT',
attributes: {
'sentry.op': 'db.query',
Expand Down Expand Up @@ -436,6 +447,7 @@ describe('instrumentDurableObjectStorage', () => {

expect(startSpanSpy).toHaveBeenCalledWith(
{
onlyIfParent: true,
name: 'durable_object_storage_kv_get',
attributes: {
'sentry.op': 'db',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ describe('instrumentDurableObjectSyncKvStorage', () => {

expect(startSpanSpy).toHaveBeenCalledWith(
{
onlyIfParent: true,
name: 'durable_object_storage_kv_get',
attributes: {
'sentry.op': 'db',
Expand Down Expand Up @@ -61,6 +62,7 @@ describe('instrumentDurableObjectSyncKvStorage', () => {

expect(startSpanSpy).toHaveBeenCalledWith(
{
onlyIfParent: true,
name: 'durable_object_storage_kv_put',
attributes: {
'sentry.op': 'db',
Expand Down Expand Up @@ -93,6 +95,7 @@ describe('instrumentDurableObjectSyncKvStorage', () => {

expect(startSpanSpy).toHaveBeenCalledWith(
{
onlyIfParent: true,
name: 'durable_object_storage_kv_delete',
attributes: {
'sentry.op': 'db',
Expand Down Expand Up @@ -126,6 +129,7 @@ describe('instrumentDurableObjectSyncKvStorage', () => {

expect(startSpanSpy).toHaveBeenCalledWith(
{
onlyIfParent: true,
name: 'durable_object_storage_kv_list',
attributes: {
'sentry.op': 'db',
Expand Down
4 changes: 4 additions & 0 deletions packages/cloudflare/test/instrumentSqlStorage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ describe('instrumentSqlStorage', () => {

expect(startSpanSpy).toHaveBeenCalledWith(
{
onlyIfParent: true,
name: 'SELECT users',
attributes: {
'sentry.op': 'db.query',
Expand All @@ -48,6 +49,7 @@ describe('instrumentSqlStorage', () => {

expect(startSpanSpy).toHaveBeenCalledWith(
{
onlyIfParent: true,
name: 'SELECT users',
attributes: {
'sentry.op': 'db.query',
Expand Down Expand Up @@ -81,6 +83,7 @@ describe('instrumentSqlStorage', () => {

expect(startSpanSpy).toHaveBeenCalledWith(
{
onlyIfParent: true,
name: 'INSERT users',
attributes: {
'sentry.op': 'db.query',
Expand Down Expand Up @@ -301,6 +304,7 @@ describe('instrumentSqlStorage', () => {

expect(startSpanSpy).toHaveBeenCalledWith(
{
onlyIfParent: true,
name: 'exec',
attributes: {
'sentry.op': 'db.query',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ describe('instrumentD1', () => {
expect(startSpanSpy).toHaveBeenCalledTimes(1);
expect(startSpanSpy).toHaveBeenLastCalledWith(
{
onlyIfParent: true,
attributes: {
'sentry.op': 'db.query',
'db.system.name': 'cloudflare-d1',
Expand Down Expand Up @@ -176,6 +177,7 @@ describe('instrumentD1', () => {
expect(startSpanSpy).toHaveBeenCalledTimes(1);
expect(startSpanSpy).toHaveBeenLastCalledWith(
{
onlyIfParent: true,
attributes: {
'sentry.op': 'db.query',
'db.system.name': 'cloudflare-d1',
Expand Down Expand Up @@ -230,6 +232,7 @@ describe('instrumentD1', () => {
expect(startSpanSpy).toHaveBeenCalledTimes(1);
expect(startSpanSpy).toHaveBeenLastCalledWith(
{
onlyIfParent: true,
attributes: {
'sentry.op': 'db.query',
'db.system.name': 'cloudflare-d1',
Expand Down Expand Up @@ -284,6 +287,7 @@ describe('instrumentD1', () => {
expect(startSpanSpy).toHaveBeenCalledTimes(1);
expect(startSpanSpy).toHaveBeenLastCalledWith(
{
onlyIfParent: true,
attributes: {
'sentry.op': 'db.query',
'db.system.name': 'cloudflare-d1',
Expand Down Expand Up @@ -335,6 +339,7 @@ describe('instrumentD1', () => {
expect(startSpanSpy).toHaveBeenCalledTimes(1);
expect(startSpanSpy).toHaveBeenLastCalledWith(
{
onlyIfParent: true,
attributes: {
'sentry.op': 'db.query',
'db.system.name': 'cloudflare-d1',
Expand Down Expand Up @@ -374,6 +379,7 @@ describe('instrumentD1', () => {
expect(startSpanSpy).toHaveBeenCalledTimes(1);
expect(startSpanSpy).toHaveBeenLastCalledWith(
{
onlyIfParent: true,
attributes: {
'sentry.op': 'db.query',
'db.system.name': 'cloudflare-d1',
Expand Down Expand Up @@ -403,6 +409,7 @@ describe('instrumentD1', () => {
expect(startSpanSpy).toHaveBeenCalledTimes(1);
expect(startSpanSpy).toHaveBeenLastCalledWith(
{
onlyIfParent: true,
attributes: {
'sentry.op': 'db.query',
'db.system.name': 'cloudflare-d1',
Expand Down Expand Up @@ -441,6 +448,7 @@ describe('instrumentD1', () => {
expect(startSpanSpy).toHaveBeenCalledTimes(1);
expect(startSpanSpy).toHaveBeenLastCalledWith(
{
onlyIfParent: true,
attributes: {
'sentry.op': 'db.query',
'db.system.name': 'cloudflare-d1',
Expand Down Expand Up @@ -478,6 +486,7 @@ describe('instrumentD1', () => {
expect(startSpanSpy).toHaveBeenCalledTimes(1);
expect(startSpanSpy).toHaveBeenLastCalledWith(
{
onlyIfParent: true,
attributes: {
'sentry.op': 'db.query',
'db.system.name': 'cloudflare-d1',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ describe('instrumentKV', () => {

expect(startSpanSpy).toHaveBeenCalledWith(
{
onlyIfParent: true,
name: CACHE_GET,
attributes: {
[SENTRY_OP]: CACHE_GET,
Expand Down Expand Up @@ -81,6 +82,7 @@ describe('instrumentKV', () => {
expect(get).toHaveBeenCalledWith(keys, 'text');
expect(startSpanSpy).toHaveBeenCalledWith(
{
onlyIfParent: true,
name: CACHE_GET,
attributes: {
[SENTRY_OP]: CACHE_GET,
Expand All @@ -105,6 +107,7 @@ describe('instrumentKV', () => {
expect(kv.getWithMetadata).toHaveBeenCalledWith('test-key', 'json');
expect(startSpanSpy).toHaveBeenCalledWith(
{
onlyIfParent: true,
name: CACHE_GET,
attributes: {
[SENTRY_OP]: CACHE_GET,
Expand Down Expand Up @@ -132,6 +135,7 @@ describe('instrumentKV', () => {
expect(startSpanSpy).toHaveBeenNthCalledWith(
1,
{
onlyIfParent: true,
name: CACHE_PUT,
attributes: {
[SENTRY_OP]: CACHE_PUT,
Expand All @@ -148,6 +152,7 @@ describe('instrumentKV', () => {
expect(startSpanSpy).toHaveBeenNthCalledWith(
2,
{
onlyIfParent: true,
name: CACHE_REMOVE,
attributes: {
[SENTRY_OP]: CACHE_REMOVE,
Expand All @@ -164,6 +169,7 @@ describe('instrumentKV', () => {
expect(startSpanSpy).toHaveBeenNthCalledWith(
3,
{
onlyIfParent: true,
name: CACHE_GET,
attributes: {
[SENTRY_OP]: CACHE_GET,
Expand Down
1 change: 1 addition & 0 deletions packages/nuxt/src/runtime/utils/instrumentDatabase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ function createStartSpanOptions(

return {
name,
onlyIfParent: true,
attributes: {
[DB_QUERY_TEXT]: queryText,
[DB_QUERY_SUMMARY]: querySummary,
Expand Down
1 change: 1 addition & 0 deletions packages/nuxt/src/runtime/utils/instrumentStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ function createSpanStartOptions(
return {
// With span streaming, span names have to be low cardinality, so we can't fall back to the cache keys.
name: client && hasSpanStreamingEnabled(client) ? cacheOperation : keys.join(', '),
onlyIfParent: true,
attributes,
};
}
Expand Down
3 changes: 2 additions & 1 deletion packages/server-utils/src/integrations/aws-sdk/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
HTTP_RESPONSE_STATUS_CODE,
SENTRY_ORIGIN,
} from '@sentry/conventions/attributes';
import { RPC } from '@sentry/conventions/op';
import { DB, RPC } from '@sentry/conventions/op';
import type { OrchestrionChannelContext } from '../../orchestrion/types';
import { CHANNELS } from '../../orchestrion/channels';
import { awsSdkModuleNames } from '../../orchestrion/config/aws-sdk';
Expand Down Expand Up @@ -116,6 +116,7 @@ function instrumentAwsSdk(servicesExtensions: ServicesExtensions): void {
const span = startInactiveSpan({
name: requestMetadata.spanName ?? `${normalizedRequest.serviceName}.${normalizedRequest.commandName}`,
op,
onlyIfParent: op === DB,
attributes: {
[SENTRY_KIND]: 'client',
[SENTRY_ORIGIN]: getSpanOrigin(op),
Expand Down
5 changes: 1 addition & 4 deletions packages/server-utils/src/integrations/knex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,10 +150,6 @@ function subscribeQuery(): void {
// The builder captures the span active when it was created (see `subscribeBuilder`).
// `onlyIfParent`: only instrument queries that run as part of an existing trace, matching OTel.
const parentSpan = builder?.[parentSpanSymbol] ?? getActiveSpan();
if (!parentSpan) {
return undefined;
}

const query = data.arguments[0];
const client = runner?.client;
const connection = client?.config?.connection;
Expand Down Expand Up @@ -193,6 +189,7 @@ function subscribeQuery(): void {
: (dbStatement ?? getName(dbNameSpace, operation, table) ?? 'knex.query');

return startInactiveSpan({
onlyIfParent: true,
name: spanName,
parentSpan,
attributes,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ function setupChannel(tracingChannel: MongooseTracingChannelFactory, channelName
: `mongoose.${data.operation}`;

return startInactiveSpan({
onlyIfParent: true,
name,
attributes: {
[SENTRY_ORIGIN]: ORIGIN,
Expand Down
Loading
Loading