Dash0 Raises $110M Series B at $1B Valuation

Last updated: May 30, 2026

Operations

Learn how Dash0 assigns standardized operation names and types to reduce cardinality.

In Dash0, operations provide a structured way to categorize and analyze application behaviors across various APIs and services.

OpenTelemetry provides a broad set of semantic conventions for telemetry data, but it lacks a consistent and unified way to represent operations across different telemetry types. This inconsistency can lead to high-cardinality span names and fragmented observability data, making it difficult to analyze and troubleshoot issues effectively.

Dash0 fills this gap through the concept of an operation. Whether dealing with HTTP requests, messaging systems, databases, or cloud services, Dash0 assigns each span a meaningful operation name and type. Operations help you detect performance issues, set alerts, and improve observability by reducing high-cardinality attributes like span names into more generalized, consistent values.

Key Takeaways

  • Standardized categorization: Dash0 automatically assigns dash0.operation.name and dash0.operation.type attributes to spans and metric data points through rules defined on the basis of OpenTelemetry semantic conventions.
  • Override support: You can override operation names by setting dash0.operation.name on spans and metric data points before the data is sent to Dash0. The dash0.operation.type attribute cannot be overridden.
  • Reduced cardinality: By grouping spans into meaningful operations, Dash0 avoids excessive cardinality that can make analysis more difficult.
  • Cross-service consistency: The same operation names are assigned to telemetry with comparable attributes, ensuring consistency across your data.

How Operations Are Assigned

During telemetry ingestion, Dash0 automatically assigns operations following a structured set of rules. These attributes are added only if dash0.operation.name is not already present in the incoming telemetry, so you can override them when necessary.

If you specify dash0.operation.name, Dash0 will still calculate a value for dash0.operation.type. Unlike dash0.operation.name, any dash0.operation.type value you send will be ignored, as Dash0 requires it to be one of a fixed set of supported values.

What Dash0 assigns depends on the span's kind and whether it has a parent span:

  • Non-root SERVER or CONSUMER spans: Evaluated against semantic-convention rules. See section 1.
  • Root spans of any kind: Handled based on their span kind. See section 2.
  • Non-root CLIENT, PRODUCER, or INTERNAL spans: Not assigned any dash0.operation.* attributes.

1. Span categories based on OpenTelemetry conventions

Spans are categorized using predefined rules, evaluated from top to bottom. The first matching rule determines the operation name. This categorization applies only to non-root spans of kind SERVER or CONSUMER.

Each rule defines a pattern that constructs dash0.operation.name from span attributes (e.g., ${http.request.method} ${http.route}). The pattern applies only if all required attributes are present.

TypePattern
GraphQL${graphql.operation.type} ${graphql.operation.name}
Object Storage (AWS S3)${rpc.method} ${aws.s3.bucket}
FaaS: Database Trigger${faas.document.collection} ${faas.document.operation} ${faas.document.name}
FaaS: Timer TriggerCron ${faas.cron}
FaaS: FaaS Name${faas.name}
Databases: AWS DynamoDB${rpc.method} ${aws.dynamodb.table_names}
Database: Namespace and Query${db.namespace} ${db.query.text}
Database: Query${db.query.text}
Database: Namespace, Operation, and Collection${db.namespace} ${db.operation.name} ${db.collection.name}
Database: Operation and Collection${db.operation.name} ${db.collection.name}
Messaging: Operation Type, Operation Name, and Destination${messaging.operation.type} ${messaging.operation.name | messaging.operation} ${messaging.destination.template | messaging.destination.name | messaging.destination_publish.name}
Messaging: Operation Type and Destination${messaging.operation.type} ${messaging.destination.template | messaging.destination.name | messaging.destination_publish.name}
Messaging: Operation and Destination${messaging.operation.name | messaging.operation} ${messaging.destination.template | messaging.destination.name | messaging.destination_publish.name}
Messaging: Type and Name${messaging.operation.type} ${messaging.operation.name | messaging.operation}
RPC: Service and Method${rpc.service} ${rpc.method}
RPC: System${rpc.system}
HTTP: Route${http.request.method | http.method} ${http.route}
HTTP: URL${http.request.method | http.method} ${url.path | http.target | http.url | url.full}
Backward compatibility

Some patterns above include deprecated attribute names as fallbacks (e.g., http.method, messaging.operation). These fallbacks exist to ensure operation names are assigned correctly for instrumentation libraries that have not yet migrated to the stable OpenTelemetry HTTP and messaging semantic conventions introduced in v1.23.0. The current attribute name is always listed first and takes precedence when present.

If no rule matches, the span name is used as dash0.operation.name.

2. Root spans (spans with no parent)

  • If span.kind is SERVER, CONSUMER, or INTERNAL, the operation type is set to headless and the operation name is derived from the span name.
  • If span.kind is CLIENT or PRODUCER, dash0.operation.type is set to unknown and dash0.operation.name to Unknown operation, because these outgoing operations lack the parent context that would explain what triggered them.

FAQs

Can I override operation names?

Yes. If an incoming span already has dash0.operation.name, Dash0 will not override it, allowing you to define your own naming scheme when necessary.

Can I override operation types?

Operation types are determined automatically and cannot be overridden. This keeps them aligned with OpenTelemetry conventions and ensures consistency across your data.

Why does my operation have the type Unknown?

An Unknown operation occurs when a root span has span.kind CLIENT or PRODUCER. These span kinds cannot represent an API invoked on the system; instead, they indicate the trace is malformed and missing the parent span that should describe what API was actually called. This typically happens with scheduled tasks or background workers that lack proper instrumentation, or when trace context propagation fails between services.

Why does UNKNOWN exist as an operation type rather than just leaving those spans unnamed?

Absence is ambiguous. A span with no operation name could be a legitimate non-root CLIENT span, or it could indicate broken trace context. UNKNOWN is a deliberate diagnostic signal, not a fallback.

The fixed name Unknown operation is also intentional: every root CLIENT or PRODUCER span in your dataset gets the exact same string, keeping cardinality at exactly one for that bucket and leaving your RED metrics clean.

Further Reading