Skip to content

Clean up span operations #22446

Description

@Lms24

Description

Currently, many of our instrumentations send span ops that are not defined in conventions. This has two reasons:

  1. The span op is simply still missing in conventions and needs to be added
  2. SDKs sent suboptimal, maybe, too fragmented ops. For example, ops that include the framework or library name (e.g. middleware.express or function.sveltekit). Ops should be a bit more general than that.

I (okay, mostly my clanker, followed by a manual review) audited our instrumentations and these are the places we should make changes to:

Add to conventions

Effort Priority Category Current op(s) Replacement or conventions action Registry status Rationale / other findings Preserve detail in Production locations
XS High Routing router Add generic router to conventions Missing This is the common framework-neutral replacement target for frontend and backend router spans. Router work is distinct from both navigation roots and generic middleware. ui.framework; navigation.phase; code.namespace or framework; router.name; route attributes packages/angular/src/tracing.ts
packages/sveltekit/src/client/svelte4BrowserTracing.ts
packages/sveltekit/src/client/svelte5BrowserTracing.ts
packages/ember/addon/utils/instrumentEmberAppInstanceForPerformance.ts
packages/core/src/integrations/express/patch-layer.ts
packages/server-utils/src/integrations/tracing-channel/express/instrumentation.ts
packages/node/src/integrations/tracing/koa/vendored/instrumentation.ts
packages/server-utils/src/integrations/tracing-channel/koa.ts
packages/node/src/integrations/tracing/hapi/vendored/instrumentation.ts
packages/server-utils/src/integrations/tracing-channel/hapi-utils.ts
XS High UI ui.interaction.click|hover|drag|press Keep ui.interaction.* and add all four leaves to conventions Missing Event Timing and INP interaction spans remain distinct from ui.action roots. Register click, hover, drag, and press as the finite interaction taxonomy. Keep DOM event type and INP metric identity as attributes packages/browser-utils/src/metrics/browserMetrics.ts
packages/browser-utils/src/metrics/inp.ts
packages/browser-utils/src/metrics/webVitalSpans.ts
packages/browser/src/tracing/browserTracingIntegration.ts
XS High UI ui.long-task / ui.long-animation-frame Keep both operations and add them to conventions Missing; ui.task is not equivalent Long Task and Long Animation Frame are distinct browser performance APIs. The generic ui.task operation is not a semantic replacement. browser.performance.entry_type=long-task|long-animation-frame packages/browser-utils/src/metrics/browserMetrics.ts
XS Medium Browser browser.${timingPhase} Keep the browser timing-phase ops and add them to conventions Only browser is currently registered Current finite values include browser.unloadEvent, redirect, domContentLoadedEvent, loadEvent, connect, TLS/SSL, cache, DNS, request, and response. These phases remain useful as distinct operations. Keep browser.performance.phase as complementary detail packages/browser-utils/src/metrics/browserMetrics.ts
XS Medium Browser measure Keep measure and add it to conventions Missing PerformanceMeasure is a distinct, fixed, useful category. Keep the PerformanceEntry name in the span name packages/browser-utils/src/metrics/browserMetrics.ts
XS Medium Browser resource.${initiatorType} Keep initiator-type leaves, add them to conventions, and retain resource.other as fallback Partially registered Register the browser-standard initiator types, including currently undocumented values such as worker, icon, frame, object, ping, or track. Values outside the recognized browser set must still map to resource.other. resource.initiator_type packages/browser-utils/src/metrics/browserMetrics.ts
XS Medium HTTP navigation.redirect Keep navigation.redirect and add it to conventions Missing Redirect timing is a stable navigation category worth retaining as its own operation. navigation.type=redirect packages/browser/src/tracing/browserTracingIntegration.ts
XS Medium Storage object.get|head|put|delete|list|upload_part|multipart_upload.abort|create|complete Keep object.* and add an object-storage category to conventions Missing Unlike framework suffixes, these are a finite, provider-neutral API taxonomy for a domain not represented by current conventions. If a smaller taxonomy is preferred, normalize to object.read/write/delete before registration. cloud provider and bucket/object identity remain attributes packages/cloudflare/src/instrumentations/worker/instrumentR2.ts
XS Medium UI ui.mount / ui.update / ui.unmount Add ui.mount, ui.update, and ui.unmount to conventions; ui.render already exists Generic lifecycle leaves are incomplete These are framework-neutral replacement targets for equivalent React, Vue, and Svelte lifecycle work. ui.framework; ui.component_name; ui.lifecycle_phase packages/react/src/profiler.tsx
packages/vue/src/tracing.ts
packages/svelte/src/performance.ts
XS Medium UI ui.webvital.lcp / ui.webvital.cls Keep and add both to conventions Missing These are fixed, cross-framework browser concepts. They are better convention candidates than framework-specific lifecycle leaves. web_vital.name and measurement value remain authoritative packages/browser-utils/src/metrics/lcp.ts
packages/browser-utils/src/metrics/cls.ts
packages/browser-utils/src/metrics/webVitalSpans.ts
XL High Gen AI gen_ai.embeddings / gen_ai.generate_content / gen_ai.rerank embeddings / generate_content / rerank Missing These are fixed, provider-neutral, semantically distinct model operations. Add their unprefixed forms to conventions, then migrate SDK emission consistently. gen_ai.operation.name and gen_ai.operation.type packages/core/src/tracing/langchain/embeddings.ts
packages/core/src/tracing/openai/index.ts
packages/core/src/tracing/google-genai/index.ts
packages/core/src/tracing/workers-ai/index.ts
packages/core/src/tracing/vercel-ai/index.ts
packages/server-utils/src/integrations/tracing-channel/openai.ts
packages/server-utils/src/integrations/tracing-channel/google-genai.ts
packages/server-utils/src/vercel-ai/vercel-ai-dc-subscriber.ts

Replace with another op

Effort Priority Category Current op(s) Replacement or conventions action Registry status Rationale / other findings Preserve detail in Production locations
S High FaaS http.request (Firebase Functions) function.gcp http.request missing The wrapper instruments all Firebase function trigger types, not only HTTP. A fixed http.request op is semantically wrong. faas.trigger already exists; keep faas.provider=firebase packages/node/src/integrations/tracing/firebase/otel/patches/functions.ts
S High HTTP http.client.${serviceIdentifier} http.client Dynamic suffix missing Service identity belongs in attributes; endpoint-derived suffixes fragment grouping and can be high-cardinality. rpc.service or server.address / cloud.service.name packages/google-cloud-serverless/src/integrations/google-cloud-http.ts
S High HTTP http.client.prefetch / http.server.prefetch http.client / http.server Missing; base ops exist OTel inference fabricates unregistered suffixes. Preserve direction and move prefetch to data. sentry.http.prefetch=true packages/opentelemetry/src/utils/parseSpanDescription.ts
S High Messaging faas.queue plus sentry.op=queue.process on one span queue.process only queue.process exact; faas.queue missing Cloudflare passes conflicting values. The sentry.op attribute wins, so faas.queue is effectively dead and should be removed. packages/cloudflare/src/instrumentations/worker/instrumentQueue.ts
S High RPC grpc.${serviceIdentifier} grpc Dynamic suffix missing Service identity can be high-cardinality and already has standard RPC attributes. rpc.service; rpc.method packages/google-cloud-serverless/src/integrations/google-cloud-grpc.ts
S High UI ui.angular.init / ui.angular.${methodKey} ui.mount for init; function for TraceMethod Parent ui.angular exists The method-key suffix is user-controlled and unbounded. Component initialization is a mount; arbitrary decorated methods are functions. ui.framework=angular; code.function.name packages/angular/src/tracing.ts
S High UI ui.ember.route.before_model|model|after_model|setup_controller function Missing These are route-hook functions. The hook name is already available and should not be encoded in sentry.op. code.function.name; ember.route.hook packages/ember/addon/index.ts
S High UI ui.ember.runloop.${queue} ui.task Missing; ui.task exists Queue values are phase details and Ember can be configured with custom queues. ui.framework=ember; ember.runloop.queue packages/ember/addon/utils/instrumentEmberGlobals.ts
S Medium Browser paint browser.paint browser.paint exists Rename the raw paint operation to the registered browser-specific operation. Keep the PerformanceEntry name in the span name packages/browser-utils/src/metrics/browserMetrics.ts
S Medium FaaS function.aws.lambda function.aws function.aws exists Lambda is already implied by provider/runtime attributes; use the registered provider-level operation. faas.name; cloud.provider=aws; cloud.platform=aws_lambda packages/aws-serverless/src/requestSpanOptions.ts
S Medium HTTP http.client.stream http.client Missing; parent exists Streaming changes response behavior but not the HTTP operation category. http.response.body.streaming=true packages/browser/src/integrations/fetchStreamPerformance.ts
S Medium UI ui.ember.component.render / component.definition / init ui.render / function / ui.mount Only parent ui.ember exists Map render and initialization to cross-framework lifecycle ops. Component definition lookup is generic function work. ui.framework=ember; ui.component_name; code.function.name packages/ember/addon/utils/instrumentEmberGlobals.ts
M High Cache cache.has_item|get_item|get_item_raw|get_items|get_keys|set_item|set_item_raw|set_items|remove_item|clear cache.get / cache.put / cache.remove Only target ops exist This is the exact over-granularity the cache conventions avoid. Map has/get/list to get; set variants to put; remove/clear to remove. db.operation.name already preserves the unstorage method packages/nuxt/src/runtime/utils/instrumentStorage.ts
packages/nitro/src/runtime/hooks/captureStorageEvents.ts
M High Database db.redis / db.redis.connect db.query for commands; db for connect Missing; db and db.query exist The datastore belongs in db.system.name. Library/system-specific op leaves are redundant. db.system.name=redis; db.operation.name packages/server-utils/src/redis/redis-dc-subscriber.ts
packages/server-utils/src/integrations/tracing-channel/redis.ts
M High FaaS faas.cron / faas.email / function.step.do function Missing Cloudflare trigger/workflow phase belongs in attributes. Do not add a new op per trigger. faas.trigger=timer|email; code.function.name; workflow.step.name packages/cloudflare/src/instrumentations/worker/instrumentScheduled.ts
packages/cloudflare/src/instrumentations/worker/instrumentEmail.ts
packages/cloudflare/src/workflows.ts
M High FaaS faas.trigger.toString() inferred as op Infer function.<provider>, http.server, or queue.process from semantic evidence Arbitrary values OTel inference currently promotes an attribute value directly into sentry.op. Custom trigger strings can create unbounded ops. Retain faas.trigger as data; never use it verbatim as op packages/opentelemetry/src/utils/parseSpanDescription.ts
M High Gen AI rpc on AWS Bedrock inference spans chat or generate_content rpc exists but is semantically wrong here Bedrock adds GenAI attributes but inherits the generic AWS SDK rpc op. Select the GenAI operation from the Bedrock request type. packages/server-utils/src/integrations/tracing-channel/aws-sdk/index.ts
packages/server-utils/src/integrations/tracing-channel/aws-sdk/services/bedrock-runtime.ts
M High Middleware app_creation.nestjs / request_context.nestjs / event.nestjs / plugin.hapi function Missing These represent executable functions or setup work. Keep lifecycle/event/plugin identity in attributes. code.function.name; nestjs.type; hapi.type; event.name packages/nestjs/src/integrations/wrap-route.ts
packages/nestjs/src/integrations/helpers.ts
packages/node/src/integrations/tracing/hapi/vendored/instrumentation.ts
packages/server-utils/src/integrations/tracing-channel/hapi-utils.ts
M High RPC rpc.server / mcp.server / mcp.notification.client_to_server|server_to_client rpc Only rpc exists MCP is JSON-RPC and tRPC is RPC. Direction, method, notification kind, and protocol belong in attributes rather than op suffixes. rpc.system=mcp|trpc; rpc.method; jsonrpc.*; messaging direction packages/core/src/trpc.ts
packages/core/src/integrations/mcp-server/spans.ts
packages/core/src/integrations/mcp-server/attributes.ts
M Medium FaaS function.gcp.http / event / cloud_event function.gcp function.gcp exists Trigger type belongs in faas.trigger. The existing suffixes split one provider category. faas.trigger packages/google-cloud-serverless/src/gcpfunction/http.ts
packages/google-cloud-serverless/src/gcpfunction/events.ts
packages/google-cloud-serverless/src/gcpfunction/cloud_events.ts
M Medium Gaps No op on Cloudflare rate-limit and Durable Object WebSocket handler spans rpc for rate-limit binding calls; websocket for WebSocket handlers Both target categories exist These wrappers create spans but only set sentry.origin. Rate-limit binding calls are RPC-like; Durable Object message/close/error callbacks are explicitly WebSocket work. rpc.service=cloudflare.rate_limit; websocket event type packages/cloudflare/src/instrumentations/worker/instrumentRateLimit.ts
packages/cloudflare/src/durableobject.ts
M Medium Gaps No op on DataLoader prime / clear / clearAll cache.put for prime; cache.remove for clear and clearAll Target cache ops exist These spans are created, but getSpanOp deliberately returns undefined. Classifying the write/removal paths completes the same cache taxonomy already used for DataLoader reads. cache.key where available; db.operation.name packages/node/src/integrations/tracing/dataloader/vendored/instrumentation.ts
packages/server-utils/src/integrations/tracing-channel/dataloader.ts
M Medium Gaps No op on some GraphQL, generic-pool, and Effect spans graphql where applicable; function or no op only by deliberate policy Instrumentation gap Vendored GraphQL parse/validate/execute/resolver spans can remain undefined because OTel inference has no matching attributes. Generic pool and Effect similarly set origin without a category. This is separate from cleanup but creates inconsistent grouping. packages/node/src/integrations/tracing/graphql/vendored/instrumentation.ts
packages/node/src/integrations/tracing/graphql/vendored/utils.ts
packages/node/src/integrations/tracing/genericPool/vendored/instrumentation.ts
packages/effect/src/tracer.ts
L High Gen AI gen_ai.create_agent / gen_ai.models / gen_ai.unknown / ai.run function for create/models/unknown fallback; map ai.run to a known AI op when evidence exists Missing Agent compilation and model metadata calls are not inference operations. Unknown strings should not become conventions. Vercel AI's fallback should use an explicit mapping or a generic function op. gen_ai.operation.name; code.function.name; retain provider SDK method packages/core/src/tracing/langgraph/index.ts
packages/core/src/tracing/anthropic-ai/index.ts
packages/core/src/tracing/openai/index.ts
packages/core/src/tracing/vercel-ai/index.ts
L High Messaging message / message.produce / message.consume queue.publish / queue.receive / queue.process message* missing; queue.* exists Kafka, AMQP, and Deno use a parallel non-convention taxonomy. Use messaging.operation.type to distinguish publish, receive, and process. Deno must not infer all ops from SpanKind alone. messaging.system; messaging.operation.type packages/server-utils/src/integrations/tracing-channel/kafkajs/spans.ts
packages/server-utils/src/integrations/tracing-channel/amqplib.ts
packages/opentelemetry/src/utils/parseSpanDescription.ts
packages/deno/src/opentelemetry/tracer.ts
L High Middleware request_handler.<library> / handler.nestjs / hono.request function; use http.server only for a true inbound/internal HTTP boundary Missing Terminal framework handlers are functions, not new op categories. Hono app.request() is an in-process HTTP dispatch and should use http.server with HTTP attributes. code.function.name; framework handler type; HTTP attributes for Hono dispatch packages/core/src/integrations/express/patch-layer.ts
packages/server-utils/src/integrations/tracing-channel/express/instrumentation.ts
packages/node/src/integrations/tracing/connect/vendored/instrumentation.ts
packages/node/src/integrations/tracing/hono/index.ts
packages/node/src/integrations/tracing/fastify/v3/instrumentation.ts
packages/server-utils/src/integrations/tracing-channel/fastify/instrumentation.ts
packages/elysia/src/withElysia.ts
packages/nestjs/src/integrations/wrap-route.ts
packages/hono/src/shared/patchAppRequest.ts
L High Middleware router.express / router.koa / router.hapi router (conventions addition tracked in the first table) router is currently missing Backend router layers should share one framework-neutral operation. They are semantically distinct from generic middleware. code.namespace or framework; router.name; route attributes packages/core/src/integrations/express/patch-layer.ts
packages/server-utils/src/integrations/tracing-channel/express/instrumentation.ts
packages/node/src/integrations/tracing/koa/vendored/instrumentation.ts
packages/server-utils/src/integrations/tracing-channel/koa.ts
packages/node/src/integrations/tracing/hapi/vendored/instrumentation.ts
packages/server-utils/src/integrations/tracing-channel/hapi-utils.ts
L Medium UI ui.angular.routing / ui.sveltekit.routing / ui.ember.transition router (conventions addition tracked in the first table) router must be added to conventions All three measure router execution. Collapse framework identity while keeping router work distinct from the broader navigation root. ui.framework; navigation.phase packages/angular/src/tracing.ts
packages/sveltekit/src/client/svelte4BrowserTracing.ts
packages/sveltekit/src/client/svelte5BrowserTracing.ts
packages/ember/addon/utils/instrumentEmberAppInstanceForPerformance.ts
L Medium UI ui.react.* / ui.vue.* / ui.svelte.* lifecycle ops ui.mount / ui.render / ui.update / ui.unmount (missing generic leaves tracked in the first table) React leaves exist; generic leaves are incomplete Preferred cleanup: normalize equivalent lifecycle work across frameworks. Current values include React mount/render/update; Vue render/activate/create/unmount/destroy/mount/update; Svelte init/update. Keeping React-specific leaves while collapsing other frameworks would preserve an arbitrary asymmetry. ui.framework; ui.component_name; ui.lifecycle_phase packages/react/src/profiler.tsx
packages/vue/src/tracing.ts
packages/svelte/src/performance.ts
XL High Framework functions function.<framework>(.<phase>) and loader.remix / action.remix function function exists; function.nextjs/remix are legacy leaves Collapse all framework and phase suffixes. This also resolves Remix's three competing loader/action taxonomies. Includes Next.js, Remix, React Router client/server, SvelteKit client/server, SolidStart, TanStack Start, and Cloudflare workflow steps. code.function.name; code.namespace; framework-specific phase/type attributes packages/nextjs/src/common/utils/tracingUtils.ts
packages/nextjs/src/common/withServerActionInstrumentation.ts
packages/remix/src/server/instrumentServer.ts
packages/remix/src/server/integrations/tracing-channel.ts
packages/remix/src/server/integrations/opentelemetry.ts
packages/react-router/src/server/createServerInstrumentation.ts
packages/react-router/src/server/wrapServerLoader.ts
packages/react-router/src/server/wrapServerAction.ts
packages/react-router/src/server/instrumentation/reactRouter.ts
packages/react-router/src/server/instrumentation/util.ts
packages/react-router/src/client/createClientInstrumentation.ts
packages/react-router/src/client/hydratedRouter.ts
packages/sveltekit/src/client/load.ts
packages/sveltekit/src/server-common/load.ts
packages/sveltekit/src/server-common/serverRoute.ts
packages/sveltekit/src/server-common/integrations/svelteKitSpans.ts
packages/solidstart/src/server/withServerActionInstrumentation.ts
packages/tanstackstart-react/src/server/wrapFetchWithSentry.ts
packages/cloudflare/src/workflows.ts
XL High Gen AI gen_ai.chat / gen_ai.execute_tool / gen_ai.invoke_agent chat / execute_tool / invoke_agent Registry values are unprefixed The SDK and source-of-truth registry disagree. Migrate to the exact convention values, or explicitly change the registry—but do not leave both. Before migration, replace SDK internals which identify AI spans via op.startsWith('gen_ai.') with gen_ai.operation.type/name. gen_ai.operation.name and gen_ai.operation.type packages/core/src/tracing/langchain/index.ts
packages/core/src/tracing/langgraph/index.ts
packages/core/src/tracing/langgraph/utils.ts
packages/core/src/tracing/openai/index.ts
packages/core/src/tracing/anthropic-ai/index.ts
packages/core/src/tracing/google-genai/index.ts
packages/core/src/tracing/workers-ai/index.ts
packages/core/src/tracing/vercel-ai/index.ts
packages/server-utils/src/integrations/tracing-channel/openai.ts
packages/server-utils/src/integrations/tracing-channel/anthropic.ts
packages/server-utils/src/integrations/tracing-channel/google-genai.ts
packages/server-utils/src/vercel-ai/vercel-ai-dc-subscriber.ts
XL High Middleware middleware.<library> / hook.fastify / http.server.middleware middleware middleware exists Collapse framework identity for middleware and request-pipeline hooks. Router layers are handled separately as router. code.namespace or framework; middleware.type; middleware.name packages/core/src/integrations/express/patch-layer.ts
packages/server-utils/src/integrations/tracing-channel/express/instrumentation.ts
packages/node/src/integrations/tracing/connect/vendored/instrumentation.ts
packages/node/src/integrations/tracing/koa/vendored/instrumentation.ts
packages/server-utils/src/integrations/tracing-channel/koa.ts
packages/node/src/integrations/tracing/hapi/vendored/instrumentation.ts
packages/server-utils/src/integrations/tracing-channel/hapi-utils.ts
packages/node/src/integrations/tracing/fastify/v3/instrumentation.ts
packages/server-utils/src/integrations/tracing-channel/fastify/instrumentation.ts
packages/node/src/integrations/tracing/hono/index.ts
packages/hono/src/shared/wrapMiddlewareSpan.ts
packages/elysia/src/withElysia.ts
packages/nestjs/src/integrations/helpers.ts
packages/nuxt/src/runtime/hooks/wrapMiddlewareHandler.ts
packages/nitro/src/runtime/hooks/captureTracingEvents.ts
packages/tanstackstart-react/src/server/utils.ts
packages/nextjs/src/common/wrapMiddlewareWithSentry.ts
packages/nextjs/src/common/enhanceMiddlewareRootSpan.ts
packages/nextjs/src/server/enhanceHandleRequestRootSpan.ts
packages/nextjs/src/edge/index.ts

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions