diff --git a/docs/span_attribute_schema/v0.md b/docs/span_attribute_schema/v0.md index 8da9454b424a..1ae1eb8c0084 100644 --- a/docs/span_attribute_schema/v0.md +++ b/docs/span_attribute_schema/v0.md @@ -1,922 +1,1117 @@ # Span Metadata -This file is intended for development purposes only. The markdown is generated from assertions authored in files /tracer/test/Datadog.Trace.TestHelpers/SpanMetadata*Rules.cs and the assertions are actively tested in the tracing integration tests. + +This file is intended for development purposes only. The markdown is generated from assertions authored in files /tracer/test/Datadog.Trace.TestHelpers/SpanMetadata\*Rules.cs and the assertions are actively tested in the tracing integration tests. The Integration Name (used for configuring individual integrations) of each span corresponds to the markdown header, with the following exceptions: + - The `AspNetCoreMvc` span has the Integration Name `AspNetCore` + ## AdoNet + ### Span properties -Name | Required | ----------|----------------| -Type | `sql` + +| Name | Required | +| ---- | -------- | +| Type | `sql` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -component | `AdoNet` -db.name | No -db.type | Yes -span.kind | `client` + +| Name | Required | +| ----------------- | -------- | +| \_dd.base_service | No | +| component | `AdoNet` | +| db.name | No | +| db.type | Yes | +| span.kind | `client` | ## Aerospike + ### Span properties -Name | Required | ----------|----------------| -Name | `aerospike.command` -Type | `aerospike` -### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -aerospike.key | No -aerospike.namespace | No -aerospike.setname | No -aerospike.userkey | No -component | `aerospike` -span.kind | `client` + +| Name | Required | +| ---- | ------------------- | +| Name | `aerospike.command` | +| Type | `aerospike` | + +### Tags + +| Name | Required | +| ------------------- | ----------- | +| \_dd.base_service | No | +| aerospike.key | No | +| aerospike.namespace | No | +| aerospike.setname | No | +| aerospike.userkey | No | +| component | `aerospike` | +| span.kind | `client` | ## AspNet + ### Span properties -Name | Required | ----------|----------------| -Name | `aspnet.request` -Type | `web` -### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -http.client_ip | No -http.method | Yes -http.request.headers.host | Yes -http.route | No -http.status_code | Yes -http.url | Yes -http.useragent | Yes -network.client.ip | No -span.kind | `server` + +| Name | Required | +| ---- | ---------------- | +| Name | `aspnet.request` | +| Type | `web` | + +### Tags + +| Name | Required | +| ------------------------- | -------- | +| \_dd.base_service | No | +| http.client_ip | No | +| http.method | Yes | +| http.request.headers.host | Yes | +| http.route | No | +| http.status_code | Yes | +| http.url | Yes | +| http.useragent | Yes | +| network.client.ip | No | +| span.kind | `server` | ## AspNetMvc + ### Span properties -Name | Required | ----------|----------------| -Name | `aspnet-mvc.request` -Type | `web` -### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -aspnet.action | Yes -aspnet.area | No -aspnet.controller | Yes -aspnet.route | Yes -http.method | Yes -http.request.headers.host | Yes -http.status_code | Yes -http.url | Yes -http.useragent | Yes -span.kind | `server` + +| Name | Required | +| ---- | -------------------- | +| Name | `aspnet-mvc.request` | +| Type | `web` | + +### Tags + +| Name | Required | +| ------------------------- | -------- | +| \_dd.base_service | No | +| aspnet.action | Yes | +| aspnet.area | No | +| aspnet.controller | Yes | +| aspnet.route | Yes | +| http.method | Yes | +| http.request.headers.host | Yes | +| http.status_code | Yes | +| http.url | Yes | +| http.useragent | Yes | +| span.kind | `server` | ## AspNetWebApi2 + ### Span properties -Name | Required | ----------|----------------| -Name | `aspnet-webapi.request` -Type | `web` -### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -aspnet.action | No -aspnet.controller | No -aspnet.route | Yes -http.client_ip | No -http.method | Yes -http.request.headers.host | Yes -http.route | No -http.status_code | No -http.url | Yes -http.useragent | Yes -network.client.ip | No -span.kind | `server` + +| Name | Required | +| ---- | ----------------------- | +| Name | `aspnet-webapi.request` | +| Type | `web` | + +### Tags + +| Name | Required | +| ------------------------- | -------- | +| \_dd.base_service | No | +| aspnet.action | No | +| aspnet.controller | No | +| aspnet.route | Yes | +| http.client_ip | No | +| http.method | Yes | +| http.request.headers.host | Yes | +| http.route | No | +| http.status_code | No | +| http.url | Yes | +| http.useragent | Yes | +| network.client.ip | No | +| span.kind | `server` | ## AspNetCore + ### Span properties -Name | Required | ----------|----------------| -Name | `aspnet_core.request` -Type | `web` -### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -aspnet_core.endpoint | No -aspnet_core.route | No -component | `aspnet_core` -http.client_ip | No -http.method | Yes -http.request.headers.host | Yes -http.route | No -http.status_code | Yes -http.url | Yes -http.useragent | Yes -network.client.ip | No -span.kind | `server` + +| Name | Required | +| ---- | --------------------- | +| Name | `aspnet_core.request` | +| Type | `web` | + +### Tags + +| Name | Required | +| ------------------------- | ------------- | +| \_dd.base_service | No | +| aspnet_core.endpoint | No | +| aspnet_core.route | No | +| component | `aspnet_core` | +| http.client_ip | No | +| http.method | Yes | +| http.request.headers.host | Yes | +| http.route | No | +| http.status_code | Yes | +| http.url | Yes | +| http.useragent | Yes | +| network.client.ip | No | +| span.kind | `server` | ## AspNetCoreMvc + > ⚠️ Note: This span is controlled by integration name `AspNetCore` + ### Span properties -Name | Required | ----------|----------------| -Name | `aspnet_core_mvc.request` -Type | `web` -### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -aspnet_core.action | Yes -aspnet_core.area | No -aspnet_core.controller | Yes -aspnet_core.page | No -aspnet_core.route | Yes -component | `aspnet_core` -span.kind | `server` + +| Name | Required | +| ---- | ------------------------- | +| Name | `aspnet_core_mvc.request` | +| Type | `web` | + +### Tags + +| Name | Required | +| ---------------------- | ------------- | +| \_dd.base_service | No | +| aspnet_core.action | Yes | +| aspnet_core.area | No | +| aspnet_core.controller | Yes | +| aspnet_core.page | No | +| aspnet_core.route | Yes | +| component | `aspnet_core` | +| span.kind | `server` | ## AwsDynamoDb + ### Span properties -Name | Required | ----------|----------------| -Name | `aws.dynamodb.request` -Type | `dynamodb` -### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -aws_service | `DynamoDB` -aws.agent | `dotnet-aws-sdk` -aws.operation | Yes -aws.region | No -aws.requestId | Yes -aws.service | `DynamoDB` -component | `aws-sdk` -http.method | Yes -http.status_code | Yes -http.url | Yes -region | No -span.kind | `client` -tablename | Yes + +| Name | Required | +| ---- | ---------------------- | +| Name | `aws.dynamodb.request` | +| Type | `dynamodb` | + +### Tags + +| Name | Required | +| ----------------- | ---------------- | +| \_dd.base_service | No | +| aws_service | `DynamoDB` | +| aws.agent | `dotnet-aws-sdk` | +| aws.operation | Yes | +| aws.region | No | +| aws.requestId | Yes | +| aws.service | `DynamoDB` | +| component | `aws-sdk` | +| http.method | Yes | +| http.status_code | Yes | +| http.url | Yes | +| region | No | +| span.kind | `client` | +| tablename | Yes | ## AwsKinesisOutbound + ### Span properties -Name | Required | ----------|----------------| -Name | `aws.kinesis.produce` -Type | `http` -### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -aws_service | `Kinesis` -aws.agent | `dotnet-aws-sdk` -aws.operation | Yes -aws.region | No -aws.requestId | Yes -aws.service | `Kinesis` -aws.stream.url | No -component | `aws-sdk` -http.method | Yes -http.status_code | Yes -http.url | Yes -region | No -span.kind | `producer` -streamname | Yes + +| Name | Required | +| ---- | --------------------- | +| Name | `aws.kinesis.produce` | +| Type | `http` | + +### Tags + +| Name | Required | +| ----------------- | ---------------- | +| \_dd.base_service | No | +| aws_service | `Kinesis` | +| aws.agent | `dotnet-aws-sdk` | +| aws.operation | Yes | +| aws.region | No | +| aws.requestId | Yes | +| aws.service | `Kinesis` | +| aws.stream.url | No | +| component | `aws-sdk` | +| http.method | Yes | +| http.status_code | Yes | +| http.url | Yes | +| region | No | +| span.kind | `producer` | +| streamname | Yes | ## AwsS3Request + ### Span properties -Name | Required | ----------|----------------| -Name | `s3.request` -Type | `http` -### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -aws_service | `S3` -aws.agent | `dotnet-aws-sdk` -aws.operation | Yes -aws.region | No -aws.requestId | Yes -aws.service | `S3` -bucketname | No -component | `aws-sdk` -http.method | Yes -http.status_code | Yes -http.url | Yes -objectkey | No -region | No -span.kind | `client` + +| Name | Required | +| ---- | ------------ | +| Name | `s3.request` | +| Type | `http` | + +### Tags + +| Name | Required | +| ----------------- | ---------------- | +| \_dd.base_service | No | +| aws_service | `S3` | +| aws.agent | `dotnet-aws-sdk` | +| aws.operation | Yes | +| aws.region | No | +| aws.requestId | Yes | +| aws.service | `S3` | +| bucketname | No | +| component | `aws-sdk` | +| http.method | Yes | +| http.status_code | Yes | +| http.url | Yes | +| objectkey | No | +| region | No | +| span.kind | `client` | ## AwsSqsRequest + ### Span properties -Name | Required | ----------|----------------| -Name | `sqs.request` -Type | `http` -### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -aws_service | `SQS` -aws.agent | `dotnet-aws-sdk` -aws.operation | Yes -aws.queue.name | Yes -aws.queue.url | No -aws.region | No -aws.requestId | Yes -aws.service | `SQS` -component | `aws-sdk` -http.method | Yes -http.status_code | Yes -http.url | Yes -queuename | Yes -region | No -span.kind | `client` + +| Name | Required | +| ---- | ------------- | +| Name | `sqs.request` | +| Type | `http` | + +### Tags + +| Name | Required | +| ----------------- | ---------------- | +| \_dd.base_service | No | +| aws_service | `SQS` | +| aws.agent | `dotnet-aws-sdk` | +| aws.operation | Yes | +| aws.queue.name | Yes | +| aws.queue.url | No | +| aws.region | No | +| aws.requestId | Yes | +| aws.service | `SQS` | +| component | `aws-sdk` | +| http.method | Yes | +| http.status_code | Yes | +| http.url | Yes | +| queuename | Yes | +| region | No | +| span.kind | `client` | ## AwsSnsRequest + ### Span properties -Name | Required | ----------|----------------| -Name | `sns.request` -Type | `http` -### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -aws_service | `SNS` -aws.agent | `dotnet-aws-sdk` -aws.operation | Yes -aws.region | No -aws.requestId | Yes -aws.service | `SNS` -aws.topic.arn | No -aws.topic.name | Yes -component | `aws-sdk` -http.method | Yes -http.status_code | Yes -http.url | Yes -region | No -span.kind | `client` -topicname | Yes + +| Name | Required | +| ---- | ------------- | +| Name | `sns.request` | +| Type | `http` | + +### Tags + +| Name | Required | +| ----------------- | ---------------- | +| \_dd.base_service | No | +| aws_service | `SNS` | +| aws.agent | `dotnet-aws-sdk` | +| aws.operation | Yes | +| aws.region | No | +| aws.requestId | Yes | +| aws.service | `SNS` | +| aws.topic.arn | No | +| aws.topic.name | Yes | +| component | `aws-sdk` | +| http.method | Yes | +| http.status_code | Yes | +| http.url | Yes | +| region | No | +| span.kind | `client` | +| topicname | Yes | ## AwsEventBridgeRequest + ### Span properties -Name | Required | ----------|----------------| -Name | `eventbridge.request` -Type | `http` -### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -aws_service | `EventBridge` -aws.agent | `dotnet-aws-sdk` -aws.operation | Yes -aws.region | No -aws.requestId | Yes -aws.service | `EventBridge` -component | `aws-sdk` -http.method | Yes -http.status_code | Yes -http.url | Yes -region | No -rulename | Yes -span.kind | `client` + +| Name | Required | +| ---- | --------------------- | +| Name | `eventbridge.request` | +| Type | `http` | + +### Tags + +| Name | Required | +| ----------------- | ---------------- | +| \_dd.base_service | No | +| aws_service | `EventBridge` | +| aws.agent | `dotnet-aws-sdk` | +| aws.operation | Yes | +| aws.region | No | +| aws.requestId | Yes | +| aws.service | `EventBridge` | +| component | `aws-sdk` | +| http.method | Yes | +| http.status_code | Yes | +| http.url | Yes | +| region | No | +| rulename | Yes | +| span.kind | `client` | ## AwsStepFunctionsRequest + ### Span properties -Name | Required | ----------|----------------| -Name | `stepfunctions.request` -Type | `http` -### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -aws_service | `StepFunctions` -aws.agent | `dotnet-aws-sdk` -aws.operation | Yes -aws.region | No -aws.requestId | Yes -aws.service | `StepFunctions` -component | `aws-sdk` -http.method | Yes -http.status_code | Yes -http.url | Yes -region | No -span.kind | `producer` -statemachinename | Yes + +| Name | Required | +| ---- | ----------------------- | +| Name | `stepfunctions.request` | +| Type | `http` | + +### Tags + +| Name | Required | +| ----------------- | ---------------- | +| \_dd.base_service | No | +| aws_service | `StepFunctions` | +| aws.agent | `dotnet-aws-sdk` | +| aws.operation | Yes | +| aws.region | No | +| aws.requestId | Yes | +| aws.service | `StepFunctions` | +| component | `aws-sdk` | +| http.method | Yes | +| http.status_code | Yes | +| http.url | Yes | +| region | No | +| span.kind | `producer` | +| statemachinename | Yes | ## AzureServiceBusInbound + ### Span properties -Name | Required | ----------|----------------| -Name | `servicebus.receive`; `servicebus.process`; `consumer` -Type | `http`; `custom` -### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -az.namespace | `Microsoft.ServiceBus` -az.schema_url | No -component | Optional: `servicebus` -kind | Optional: `consumer` -messaging.destination.name | No -messaging.operation | Optional: `receive`; `process` -messaging.source.name | No -messaging.system | Optional: `servicebus` -net.peer.name | No -otel.library.name | Yes -otel.library.version | No -otel.status_code | `STATUS_CODE_UNSET`; `STATUS_CODE_OK`; `STATUS_CODE_ERROR` -otel.status_description | No -otel.trace_id | Yes -peer.address | No -server.address | No -span.kind | `consumer` + +| Name | Required | +| ---- | ------------------------------------------------------ | +| Name | `servicebus.receive`; `servicebus.process`; `consumer` | +| Type | `http`; `custom` | + +### Tags + +| Name | Required | +| -------------------------- | ---------------------------------------------------------- | +| \_dd.base_service | No | +| az.namespace | `Microsoft.ServiceBus` | +| az.schema_url | No | +| component | Optional: `servicebus` | +| kind | Optional: `consumer` | +| messaging.destination.name | No | +| messaging.operation | Optional: `receive`; `process` | +| messaging.source.name | No | +| messaging.system | Optional: `servicebus` | +| net.peer.name | No | +| otel.library.name | Yes | +| otel.library.version | No | +| otel.status_code | `STATUS_CODE_UNSET`; `STATUS_CODE_OK`; `STATUS_CODE_ERROR` | +| otel.status_description | No | +| otel.trace_id | Yes | +| peer.address | No | +| server.address | No | +| span.kind | `consumer` | ## AzureServiceBusOutbound + ### Span properties -Name | Required | ----------|----------------| -Name | `producer` -Type | `custom` -### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -az.namespace | `Microsoft.ServiceBus` -az.schema_url | No -component | Optional: `servicebus` -kind | Optional: `producer` -messaging.destination.name | Yes -messaging.system | Optional: `servicebus` -net.peer.name | No -otel.library.name | Yes -otel.library.version | No -otel.status_code | `STATUS_CODE_UNSET`; `STATUS_CODE_OK`; `STATUS_CODE_ERROR` -otel.status_description | No -otel.trace_id | Yes -peer.address | No -server.address | No -span.kind | `producer` + +| Name | Required | +| ---- | ---------- | +| Name | `producer` | +| Type | `custom` | + +### Tags + +| Name | Required | +| -------------------------- | ---------------------------------------------------------- | +| \_dd.base_service | No | +| az.namespace | `Microsoft.ServiceBus` | +| az.schema_url | No | +| component | Optional: `servicebus` | +| kind | Optional: `producer` | +| messaging.destination.name | Yes | +| messaging.system | Optional: `servicebus` | +| net.peer.name | No | +| otel.library.name | Yes | +| otel.library.version | No | +| otel.status_code | `STATUS_CODE_UNSET`; `STATUS_CODE_OK`; `STATUS_CODE_ERROR` | +| otel.status_description | No | +| otel.trace_id | Yes | +| peer.address | No | +| server.address | No | +| span.kind | `producer` | ## AzureServiceBusRequest + ### Span properties -Name | Required | ----------|----------------| -Name | `servicebus.publish`; `servicebus.settle`; `client.request` -Type | `http` -### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -az.namespace | `Microsoft.ServiceBus` -az.schema_url | No -component | Optional: `servicebus` -kind | Optional: `client` -messaging.destination.name | No -messaging.operation | Optional: `publish`; `settle` -messaging.source.name | No -messaging.system | Optional: `servicebus` -net.peer.name | No -otel.library.name | Yes -otel.library.version | No -otel.status_code | `STATUS_CODE_UNSET`; `STATUS_CODE_OK`; `STATUS_CODE_ERROR` -otel.status_description | No -otel.trace_id | Yes -peer.address | No -server.address | No -span.kind | `client` + +| Name | Required | +| ---- | ----------------------------------------------------------- | +| Name | `servicebus.publish`; `servicebus.settle`; `client.request` | +| Type | `http` | + +### Tags + +| Name | Required | +| -------------------------- | ---------------------------------------------------------- | +| \_dd.base_service | No | +| az.namespace | `Microsoft.ServiceBus` | +| az.schema_url | No | +| component | Optional: `servicebus` | +| kind | Optional: `client` | +| messaging.destination.name | No | +| messaging.operation | Optional: `publish`; `settle` | +| messaging.source.name | No | +| messaging.system | Optional: `servicebus` | +| net.peer.name | No | +| otel.library.name | Yes | +| otel.library.version | No | +| otel.status_code | `STATUS_CODE_UNSET`; `STATUS_CODE_OK`; `STATUS_CODE_ERROR` | +| otel.status_description | No | +| otel.trace_id | Yes | +| peer.address | No | +| server.address | No | +| span.kind | `client` | ## CosmosDb + ### Span properties -Name | Required | ----------|----------------| -Name | `cosmosdb.query` -Type | `sql` -### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -component | `CosmosDb` -cosmosdb.container | No -db.name | No -db.type | `cosmosdb` -out.host | Yes -span.kind | `client` + +| Name | Required | +| ---- | ---------------- | +| Name | `cosmosdb.query` | +| Type | `sql` | + +### Tags + +| Name | Required | +| ------------------ | ---------- | +| \_dd.base_service | No | +| component | `CosmosDb` | +| cosmosdb.container | No | +| db.name | No | +| db.type | `cosmosdb` | +| out.host | Yes | +| span.kind | `client` | ## Couchbase + ### Span properties -Name | Required | ----------|----------------| -Name | `couchbase.query` -Type | `db` -### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -component | `Couchbase` -couchbase.operation.bucket | No -couchbase.operation.code | Yes -couchbase.operation.key | Yes -db.couchbase.seed.nodes | Yes -out.host | No -out.port | No -span.kind | `client` + +| Name | Required | +| ---- | ----------------- | +| Name | `couchbase.query` | +| Type | `db` | + +### Tags + +| Name | Required | +| -------------------------- | ----------- | +| \_dd.base_service | No | +| component | `Couchbase` | +| couchbase.operation.bucket | No | +| couchbase.operation.code | Yes | +| couchbase.operation.key | Yes | +| db.couchbase.seed.nodes | Yes | +| out.host | No | +| out.port | No | +| span.kind | `client` | ## ElasticsearchNet + ### Span properties -Name | Required | ----------|----------------| -Name | `elasticsearch.query` -Type | `elasticsearch` -### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -component | `elasticsearch-net` -elasticsearch.action | Yes -elasticsearch.method | Yes -elasticsearch.url | Yes -out.host | Yes -span.kind | `client` + +| Name | Required | +| ---- | --------------------- | +| Name | `elasticsearch.query` | +| Type | `elasticsearch` | + +### Tags + +| Name | Required | +| -------------------- | ------------------- | +| \_dd.base_service | No | +| component | `elasticsearch-net` | +| elasticsearch.action | Yes | +| elasticsearch.method | Yes | +| elasticsearch.url | Yes | +| out.host | Yes | +| span.kind | `client` | ## GraphQL + ### Span properties -Name | Required | ----------|----------------| -Name | `graphql.execute`; `graphql.validate` -Type | `graphql` + +| Name | Required | +| ---- | ------------------------------------- | +| Name | `graphql.execute`; `graphql.validate` | +| Type | `graphql` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -component | `GraphQL` -graphql.operation.name | No -graphql.operation.type | No -graphql.source | Yes -span.kind | `server` + +| Name | Required | +| ---------------------- | --------- | +| \_dd.base_service | No | +| component | `GraphQL` | +| graphql.operation.name | No | +| graphql.operation.type | No | +| graphql.source | Yes | +| span.kind | `server` | ## gRPC Client + ### Span properties -Name | Required | ----------|----------------| -Name | `grpc.request` -Type | `grpc` -### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -component | `Grpc` -grpc.method.kind | Yes -grpc.method.name | Yes -grpc.method.package | Yes -grpc.method.path | Yes -grpc.method.service | Yes -grpc.status.code | Yes -out.host | Yes -peer.hostname | Yes -span.kind | `client` + +| Name | Required | +| ---- | -------------- | +| Name | `grpc.request` | +| Type | `grpc` | + +### Tags + +| Name | Required | +| ------------------- | -------- | +| \_dd.base_service | No | +| component | `Grpc` | +| grpc.method.kind | Yes | +| grpc.method.name | Yes | +| grpc.method.package | Yes | +| grpc.method.path | Yes | +| grpc.method.service | Yes | +| grpc.status.code | Yes | +| out.host | Yes | +| peer.hostname | Yes | +| span.kind | `client` | ## gRPC Server + ### Span properties -Name | Required | ----------|----------------| -Name | `grpc.request` -Type | `grpc` -### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -component | `Grpc` -grpc.method.kind | Yes -grpc.method.name | Yes -grpc.method.package | Yes -grpc.method.path | Yes -grpc.method.service | Yes -grpc.status.code | Yes -span.kind | `server` + +| Name | Required | +| ---- | -------------- | +| Name | `grpc.request` | +| Type | `grpc` | + +### Tags + +| Name | Required | +| ------------------- | -------- | +| \_dd.base_service | No | +| component | `Grpc` | +| grpc.method.kind | Yes | +| grpc.method.name | Yes | +| grpc.method.package | Yes | +| grpc.method.path | Yes | +| grpc.method.service | Yes | +| grpc.status.code | Yes | +| span.kind | `server` | ## HotChocolate + ### Span properties -Name | Required | ----------|----------------| -Name | `graphql.execute`; `graphql.validate` -Type | `graphql` + +| Name | Required | +| ---- | ------------------------------------- | +| Name | `graphql.execute`; `graphql.validate` | +| Type | `graphql` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -component | `HotChocolate` -graphql.operation.name | No -graphql.operation.type | No -graphql.source | Yes -span.kind | `server` + +| Name | Required | +| ---------------------- | -------------- | +| \_dd.base_service | No | +| component | `HotChocolate` | +| graphql.operation.name | No | +| graphql.operation.type | No | +| graphql.source | Yes | +| span.kind | `server` | ## HttpMessageHandler + ### Span properties -Name | Required | ----------|----------------| -Name | `http.request` -Type | `http` -### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -component | Yes -http-client-handler-type | Yes -http.method | Yes -http.status_code | Yes -http.url | Yes -out.host | Yes -span.kind | `client` + +| Name | Required | +| ---- | -------------- | +| Name | `http.request` | +| Type | `http` | + +### Tags + +| Name | Required | +| ------------------------ | -------- | +| \_dd.base_service | No | +| component | Yes | +| http-client-handler-type | Yes | +| http.method | Yes | +| http.status_code | Yes | +| http.url | Yes | +| out.host | Yes | +| span.kind | `client` | ## Kafka - Inbound + ### Span properties -Name | Required | ----------|----------------| -Name | `kafka.consume` -Type | `queue` -### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -component | `kafka` -kafka.group | No -kafka.offset | No -kafka.partition | No -kafka.tombstone | No -messaging.destination.name | Yes -messaging.kafka.bootstrap.servers | Yes -span.kind | `consumer` + +| Name | Required | +| ---- | --------------- | +| Name | `kafka.consume` | +| Type | `queue` | + +### Tags + +| Name | Required | +| --------------------------------- | ---------- | +| \_dd.base_service | No | +| component | `kafka` | +| kafka.group | No | +| kafka.offset | No | +| kafka.partition | No | +| kafka.tombstone | No | +| messaging.destination.name | Yes | +| messaging.kafka.bootstrap.servers | Yes | +| messaging.kafka.cluster_id | No | +| span.kind | `consumer` | + ### Metrics -Name | Required | ----------|----------------| -_dd.measured | Yes -message.queue_time_ms | No + +| Name | Required | +| --------------------- | -------- | +| \_dd.measured | Yes | +| message.queue_time_ms | No | ## Kafka - Outbound + ### Span properties -Name | Required | ----------|----------------| -Name | `kafka.produce` -Type | `queue` -### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -component | `kafka` -kafka.group | No -kafka.offset | No -kafka.partition | No -kafka.tombstone | No -messaging.destination.name | Yes -messaging.kafka.bootstrap.servers | Yes -span.kind | `producer` + +| Name | Required | +| ---- | --------------- | +| Name | `kafka.produce` | +| Type | `queue` | + +### Tags + +| Name | Required | +| --------------------------------- | ---------- | +| \_dd.base_service | No | +| component | `kafka` | +| kafka.group | No | +| kafka.offset | No | +| kafka.partition | No | +| kafka.tombstone | No | +| messaging.destination.name | Yes | +| messaging.kafka.bootstrap.servers | Yes | +| messaging.kafka.cluster_id | No | +| span.kind | `producer` | + ### Metrics -Name | Required | ----------|----------------| -_dd.measured | Yes -message.queue_time_ms | No + +| Name | Required | +| --------------------- | -------- | +| \_dd.measured | Yes | +| message.queue_time_ms | No | ## MongoDb + ### Span properties -Name | Required | ----------|----------------| -Name | `mongodb.query` -Type | `mongodb` -### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -component | `MongoDb` -db.name | No -mongodb.collection | No -mongodb.query | No -out.host | Yes -out.port | Yes -span.kind | `client` + +| Name | Required | +| ---- | --------------- | +| Name | `mongodb.query` | +| Type | `mongodb` | + +### Tags + +| Name | Required | +| ------------------ | --------- | +| \_dd.base_service | No | +| component | `MongoDb` | +| db.name | No | +| mongodb.collection | No | +| mongodb.query | No | +| out.host | Yes | +| out.port | Yes | +| span.kind | `client` | ## Msmq + ### Span properties -Name | Required | ----------|----------------| -Name | `msmq.command` -Type | `queue` -### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -component | `msmq` -msmq.command | Yes -msmq.message.transactional | No -msmq.queue.path | Yes -msmq.queue.transactional | No -out.host | Yes -span.kind | `client`; `producer`; `consumer` + +| Name | Required | +| ---- | -------------- | +| Name | `msmq.command` | +| Type | `queue` | + +### Tags + +| Name | Required | +| -------------------------- | -------------------------------- | +| \_dd.base_service | No | +| component | `msmq` | +| msmq.command | Yes | +| msmq.message.transactional | No | +| msmq.queue.path | Yes | +| msmq.queue.transactional | No | +| out.host | Yes | +| span.kind | `client`; `producer`; `consumer` | ## MySql + ### Span properties -Name | Required | ----------|----------------| -Name | `mysql.query` -Type | `sql` -### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -_dd.dbm_trace_injected | No -component | `MySql` -db.name | Yes -db.type | `mysql` -db.user | Yes -out.host | Yes -span.kind | `client` + +| Name | Required | +| ---- | ------------- | +| Name | `mysql.query` | +| Type | `sql` | + +### Tags + +| Name | Required | +| ----------------------- | -------- | +| \_dd.base_service | No | +| \_dd.dbm_trace_injected | No | +| component | `MySql` | +| db.name | Yes | +| db.type | `mysql` | +| db.user | Yes | +| out.host | Yes | +| span.kind | `client` | ## Npgsql + ### Span properties -Name | Required | ----------|----------------| -Name | `postgres.query` -Type | `sql` -### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -_dd.dbm_trace_injected | No -component | `Npgsql` -db.name | Yes -db.type | `postgres` -out.host | Yes -span.kind | `client` + +| Name | Required | +| ---- | ---------------- | +| Name | `postgres.query` | +| Type | `sql` | + +### Tags + +| Name | Required | +| ----------------------- | ---------- | +| \_dd.base_service | No | +| \_dd.dbm_trace_injected | No | +| component | `Npgsql` | +| db.name | Yes | +| db.type | `postgres` | +| out.host | Yes | +| span.kind | `client` | ## OpenTelemetry + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -otel.library.name | Yes -otel.library.version | No -otel.status_code | `STATUS_CODE_UNSET`; `STATUS_CODE_OK`; `STATUS_CODE_ERROR` -otel.status_description | No -otel.trace_id | Yes -span.kind | `internal`; `server`; `client`; `producer`; `consumer` + +| Name | Required | +| ----------------------- | ---------------------------------------------------------- | +| \_dd.base_service | No | +| otel.library.name | Yes | +| otel.library.version | No | +| otel.status_code | `STATUS_CODE_UNSET`; `STATUS_CODE_OK`; `STATUS_CODE_ERROR` | +| otel.status_description | No | +| otel.trace_id | Yes | +| span.kind | `internal`; `server`; `client`; `producer`; `consumer` | + ### AdditionalTags -Source | Operation | Required | ----------|-----------|----------------| -OTEL Resource Attributes | PassThru | No + +| Source | Operation | Required | +| ------------------------ | --------- | -------- | +| OTEL Resource Attributes | PassThru | No | ## Oracle + ### Span properties -Name | Required | ----------|----------------| -Name | `oracle.query` -Type | `sql` + +| Name | Required | +| ---- | -------------- | +| Name | `oracle.query` | +| Type | `sql` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -component | `Oracle` -db.name | Yes -db.type | `oracle` -out.host | Yes -span.kind | `client` + +| Name | Required | +| ----------------- | -------- | +| \_dd.base_service | No | +| component | `Oracle` | +| db.name | Yes | +| db.type | `oracle` | +| out.host | Yes | +| span.kind | `client` | ## Process + ### Span properties -Name | Required | ----------|----------------| -Name | `command_execution` -Type | `system` -### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -cmd.environment_variables | No -cmd.exec | No -cmd.shell | No -cmd.truncated | No -component | `process` -span.kind | `internal` + +| Name | Required | +| ---- | ------------------- | +| Name | `command_execution` | +| Type | `system` | + +### Tags + +| Name | Required | +| ------------------------- | ---------- | +| \_dd.base_service | No | +| cmd.environment_variables | No | +| cmd.exec | No | +| cmd.shell | No | +| cmd.truncated | No | +| component | `process` | +| span.kind | `internal` | ## Protobuf + ### Tags -Name | Required | ----------|----------------| -Tags.SchemaDefinition | Yes -Tags.SchemaId | Yes -Tags.SchemaName | Yes -Tags.SchemaOperation | Yes -Tags.SchemaType | `protobuf` -Tags.SchemaWeight | Yes + +| Name | Required | +| --------------------- | ---------- | +| Tags.SchemaDefinition | Yes | +| Tags.SchemaId | Yes | +| Tags.SchemaName | Yes | +| Tags.SchemaOperation | Yes | +| Tags.SchemaType | `protobuf` | +| Tags.SchemaWeight | Yes | ## RabbitMQ + ### Span properties -Name | Required | ----------|----------------| -Name | `amqp.command` -Type | `queue` -### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -amqp.command | Yes -amqp.delivery_mode | No -amqp.exchange | No -amqp.queue | No -amqp.routing_key | No -component | `RabbitMQ` -message.size | No -out.host | No -span.kind | Yes + +| Name | Required | +| ---- | -------------- | +| Name | `amqp.command` | +| Type | `queue` | + +### Tags + +| Name | Required | +| ------------------ | ---------- | +| \_dd.base_service | No | +| amqp.command | Yes | +| amqp.delivery_mode | No | +| amqp.exchange | No | +| amqp.queue | No | +| amqp.routing_key | No | +| component | `RabbitMQ` | +| message.size | No | +| out.host | No | +| span.kind | Yes | ## RemotingClient + ### Span properties -Name | Required | ----------|----------------| -Name | `dotnet_remoting.client.request` + +| Name | Required | +| ---- | -------------------------------- | +| Name | `dotnet_remoting.client.request` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -component | `Remoting` -rpc.method | Yes -rpc.system | `dotnet_remoting` -span.kind | `client` + +| Name | Required | +| ----------------- | ----------------- | +| \_dd.base_service | No | +| component | `Remoting` | +| rpc.method | Yes | +| rpc.system | `dotnet_remoting` | +| span.kind | `client` | ## RemotingServer + ### Span properties -Name | Required | ----------|----------------| -Name | `dotnet_remoting.server.request` + +| Name | Required | +| ---- | -------------------------------- | +| Name | `dotnet_remoting.server.request` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -component | `Remoting` -rpc.method | Yes -rpc.system | `dotnet_remoting` -span.kind | `server` + +| Name | Required | +| ----------------- | ----------------- | +| \_dd.base_service | No | +| component | `Remoting` | +| rpc.method | Yes | +| rpc.system | `dotnet_remoting` | +| span.kind | `server` | ## Service Remoting - Client + ### Span properties -Name | Required | ----------|----------------| -Name | `service_remoting.client` -### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -service-fabric.application-id | No -service-fabric.application-name | No -service-fabric.node-id | No -service-fabric.node-name | No -service-fabric.partition-id | No -service-fabric.service-name | No -service-fabric.service-remoting.interface-id | No -service-fabric.service-remoting.invocation-id | No -service-fabric.service-remoting.method-id | No -service-fabric.service-remoting.method-name | Yes -service-fabric.service-remoting.service | No -service-fabric.service-remoting.uri | Yes -span.kind | `client` + +| Name | Required | +| ---- | ------------------------- | +| Name | `service_remoting.client` | + +### Tags + +| Name | Required | +| --------------------------------------------- | -------- | +| \_dd.base_service | No | +| service-fabric.application-id | No | +| service-fabric.application-name | No | +| service-fabric.node-id | No | +| service-fabric.node-name | No | +| service-fabric.partition-id | No | +| service-fabric.service-name | No | +| service-fabric.service-remoting.interface-id | No | +| service-fabric.service-remoting.invocation-id | No | +| service-fabric.service-remoting.method-id | No | +| service-fabric.service-remoting.method-name | Yes | +| service-fabric.service-remoting.service | No | +| service-fabric.service-remoting.uri | Yes | +| span.kind | `client` | ## Service Remoting - Server + ### Span properties -Name | Required | ----------|----------------| -Name | `service_remoting.server` -### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -service-fabric.application-id | No -service-fabric.application-name | No -service-fabric.node-id | No -service-fabric.node-name | No -service-fabric.partition-id | No -service-fabric.service-name | No -service-fabric.service-remoting.interface-id | No -service-fabric.service-remoting.invocation-id | No -service-fabric.service-remoting.method-id | No -service-fabric.service-remoting.method-name | Yes -service-fabric.service-remoting.service | No -service-fabric.service-remoting.uri | Yes -span.kind | `server` + +| Name | Required | +| ---- | ------------------------- | +| Name | `service_remoting.server` | + +### Tags + +| Name | Required | +| --------------------------------------------- | -------- | +| \_dd.base_service | No | +| service-fabric.application-id | No | +| service-fabric.application-name | No | +| service-fabric.node-id | No | +| service-fabric.node-name | No | +| service-fabric.partition-id | No | +| service-fabric.service-name | No | +| service-fabric.service-remoting.interface-id | No | +| service-fabric.service-remoting.invocation-id | No | +| service-fabric.service-remoting.method-id | No | +| service-fabric.service-remoting.method-name | Yes | +| service-fabric.service-remoting.service | No | +| service-fabric.service-remoting.uri | Yes | +| span.kind | `server` | ## ServiceStackRedis + ### Span properties -Name | Required | ----------|----------------| -Name | `redis.command` -Type | `redis` -### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -component | `ServiceStackRedis` -out.host | Yes -out.port | Yes -redis.raw_command | Yes -span.kind | `client` + +| Name | Required | +| ---- | --------------- | +| Name | `redis.command` | +| Type | `redis` | + +### Tags + +| Name | Required | +| ----------------- | ------------------- | +| \_dd.base_service | No | +| component | `ServiceStackRedis` | +| out.host | Yes | +| out.port | Yes | +| redis.raw_command | Yes | +| span.kind | `client` | + ### Metrics -Name | Required | ----------|----------------| -db.redis.database_index | Yes + +| Name | Required | +| ----------------------- | -------- | +| db.redis.database_index | Yes | ## StackExchangeRedis + ### Span properties -Name | Required | ----------|----------------| -Name | `redis.command` -Type | `redis` -### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -component | `StackExchangeRedis` -out.host | Yes -out.port | Yes -redis.raw_command | Yes -span.kind | `client` + +| Name | Required | +| ---- | --------------- | +| Name | `redis.command` | +| Type | `redis` | + +### Tags + +| Name | Required | +| ----------------- | -------------------- | +| \_dd.base_service | No | +| component | `StackExchangeRedis` | +| out.host | Yes | +| out.port | Yes | +| redis.raw_command | Yes | +| span.kind | `client` | + ### Metrics -Name | Required | ----------|----------------| -db.redis.database_index | No + +| Name | Required | +| ----------------------- | -------- | +| db.redis.database_index | No | ## Sqlite + ### Span properties -Name | Required | ----------|----------------| -Name | `sqlite.query` -Type | `sql` + +| Name | Required | +| ---- | -------------- | +| Name | `sqlite.query` | +| Type | `sql` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -component | `Sqlite` -db.name | No -db.type | `sqlite` -out.host | Yes -span.kind | `client` + +| Name | Required | +| ----------------- | -------- | +| \_dd.base_service | No | +| component | `Sqlite` | +| db.name | No | +| db.type | `sqlite` | +| out.host | Yes | +| span.kind | `client` | ## SqlClient + ### Span properties -Name | Required | ----------|----------------| -Name | `sql-server.query` -Type | `sql` -### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -_dd.dbm_trace_injected | No -component | `SqlClient` -db.name | No -db.type | `sql-server` -dd.instrumentation.time_ms | No -out.host | Yes -span.kind | `client` + +| Name | Required | +| ---- | ------------------ | +| Name | `sql-server.query` | +| Type | `sql` | + +### Tags + +| Name | Required | +| -------------------------- | ------------ | +| \_dd.base_service | No | +| \_dd.dbm_trace_injected | No | +| component | `SqlClient` | +| db.name | No | +| db.type | `sql-server` | +| dd.instrumentation.time_ms | No | +| out.host | Yes | +| span.kind | `client` | ## Wcf + ### Span properties -Name | Required | ----------|----------------| -Name | `wcf.request` -Type | `web` + +| Name | Required | +| ---- | ------------- | +| Name | `wcf.request` | +| Type | `web` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -component | `Wcf` -http.method | No -http.request.headers.host | No -http.url | Yes -span.kind | `server` + +| Name | Required | +| ------------------------- | -------- | +| \_dd.base_service | No | +| component | `Wcf` | +| http.method | No | +| http.request.headers.host | No | +| http.url | Yes | +| span.kind | `server` | ## WebRequest + ### Span properties -Name | Required | ----------|----------------| -Name | `http.request` -Type | `http` -### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -component | `HttpMessageHandler`; `WebRequest` -http-client-handler-type | No -http.method | Yes -http.status_code | Yes -http.url | Yes -out.host | Yes -span.kind | `client` +| Name | Required | +| ---- | -------------- | +| Name | `http.request` | +| Type | `http` | + +### Tags + +| Name | Required | +| ------------------------ | ---------------------------------- | +| \_dd.base_service | No | +| component | `HttpMessageHandler`; `WebRequest` | +| http-client-handler-type | No | +| http.method | Yes | +| http.status_code | Yes | +| http.url | Yes | +| out.host | Yes | +| span.kind | `client` | diff --git a/docs/span_attribute_schema/v1.md b/docs/span_attribute_schema/v1.md index f3367d53ad0d..73d566e1a1f6 100644 --- a/docs/span_attribute_schema/v1.md +++ b/docs/span_attribute_schema/v1.md @@ -1,1300 +1,1543 @@ # Span Metadata -This file is intended for development purposes only. The markdown is generated from assertions authored in files /tracer/test/Datadog.Trace.TestHelpers/SpanMetadata*Rules.cs and the assertions are actively tested in the tracing integration tests. + +This file is intended for development purposes only. The markdown is generated from assertions authored in files /tracer/test/Datadog.Trace.TestHelpers/SpanMetadata\*Rules.cs and the assertions are actively tested in the tracing integration tests. The Integration Name (used for configuring individual integrations) of each span corresponds to the markdown header, with the following exceptions: + - The `AspNetCoreMvc` span has the Integration Name `AspNetCore` + ## AdoNet + ### Span properties -Name | Required | ----------|----------------| -Type | `sql` + +| Name | Required | +| ---- | -------- | +| Type | `sql` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -_dd.peer.service.source | `db.name`; `out.host`; `peer.service` -component | `AdoNet` -db.name | No -db.type | Yes -peer.service | Yes -peer.service.remapped_from | No -span.kind | `client` + +| Name | Required | +| -------------------------- | ------------------------------------- | +| \_dd.base_service | No | +| \_dd.peer.service.source | `db.name`; `out.host`; `peer.service` | +| component | `AdoNet` | +| db.name | No | +| db.type | Yes | +| peer.service | Yes | +| peer.service.remapped_from | No | +| span.kind | `client` | ## Aerospike + ### Span properties -Name | Required | ----------|----------------| -Name | `aerospike.command` -Type | `aerospike` + +| Name | Required | +| ---- | ------------------- | +| Name | `aerospike.command` | +| Type | `aerospike` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -_dd.peer.service.source | No -aerospike.key | No -aerospike.namespace | No -aerospike.setname | No -aerospike.userkey | No -component | `aerospike` -peer.service | No -span.kind | `client` + +| Name | Required | +| ------------------------ | ----------- | +| \_dd.base_service | No | +| \_dd.peer.service.source | No | +| aerospike.key | No | +| aerospike.namespace | No | +| aerospike.setname | No | +| aerospike.userkey | No | +| component | `aerospike` | +| peer.service | No | +| span.kind | `client` | ## AspNet + ### Span properties -Name | Required | ----------|----------------| -Name | `aspnet.request` -Type | `web` + +| Name | Required | +| ---- | ---------------- | +| Name | `aspnet.request` | +| Type | `web` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -http.client_ip | No -http.method | Yes -http.request.headers.host | Yes -http.route | No -http.status_code | Yes -http.url | Yes -http.useragent | Yes -network.client.ip | No -span.kind | `server` + +| Name | Required | +| ------------------------- | -------- | +| \_dd.base_service | No | +| http.client_ip | No | +| http.method | Yes | +| http.request.headers.host | Yes | +| http.route | No | +| http.status_code | Yes | +| http.url | Yes | +| http.useragent | Yes | +| network.client.ip | No | +| span.kind | `server` | ## AspNetMvc + ### Span properties -Name | Required | ----------|----------------| -Name | `aspnet-mvc.request` -Type | `web` + +| Name | Required | +| ---- | -------------------- | +| Name | `aspnet-mvc.request` | +| Type | `web` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -aspnet.action | Yes -aspnet.area | No -aspnet.controller | Yes -aspnet.route | Yes -http.method | Yes -http.request.headers.host | Yes -http.status_code | Yes -http.url | Yes -http.useragent | Yes -span.kind | `server` + +| Name | Required | +| ------------------------- | -------- | +| \_dd.base_service | No | +| aspnet.action | Yes | +| aspnet.area | No | +| aspnet.controller | Yes | +| aspnet.route | Yes | +| http.method | Yes | +| http.request.headers.host | Yes | +| http.status_code | Yes | +| http.url | Yes | +| http.useragent | Yes | +| span.kind | `server` | ## AspNetWebApi2 + ### Span properties -Name | Required | ----------|----------------| -Name | `aspnet-webapi.request` -Type | `web` + +| Name | Required | +| ---- | ----------------------- | +| Name | `aspnet-webapi.request` | +| Type | `web` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -aspnet.action | No -aspnet.controller | No -aspnet.route | Yes -http.client_ip | No -http.method | Yes -http.request.headers.host | Yes -http.route | No -http.status_code | No -http.url | Yes -http.useragent | Yes -network.client.ip | No -span.kind | `server` + +| Name | Required | +| ------------------------- | -------- | +| \_dd.base_service | No | +| aspnet.action | No | +| aspnet.controller | No | +| aspnet.route | Yes | +| http.client_ip | No | +| http.method | Yes | +| http.request.headers.host | Yes | +| http.route | No | +| http.status_code | No | +| http.url | Yes | +| http.useragent | Yes | +| network.client.ip | No | +| span.kind | `server` | ## AspNetCore + ### Span properties -Name | Required | ----------|----------------| -Name | `aspnet_core.request` -Type | `web` + +| Name | Required | +| ---- | --------------------- | +| Name | `aspnet_core.request` | +| Type | `web` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -aspnet_core.endpoint | No -aspnet_core.route | No -component | `aspnet_core` -http.client_ip | No -http.method | Yes -http.request.headers.host | Yes -http.route | No -http.status_code | Yes -http.url | Yes -http.useragent | Yes -network.client.ip | No -span.kind | `server` + +| Name | Required | +| ------------------------- | ------------- | +| \_dd.base_service | No | +| aspnet_core.endpoint | No | +| aspnet_core.route | No | +| component | `aspnet_core` | +| http.client_ip | No | +| http.method | Yes | +| http.request.headers.host | Yes | +| http.route | No | +| http.status_code | Yes | +| http.url | Yes | +| http.useragent | Yes | +| network.client.ip | No | +| span.kind | `server` | ## AspNetCoreMvc + > ⚠️ Note: This span is controlled by integration name `AspNetCore` + ### Span properties -Name | Required | ----------|----------------| -Name | `aspnet_core_mvc.request` -Type | `web` + +| Name | Required | +| ---- | ------------------------- | +| Name | `aspnet_core_mvc.request` | +| Type | `web` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -aspnet_core.action | Yes -aspnet_core.area | No -aspnet_core.controller | Yes -aspnet_core.page | No -aspnet_core.route | Yes -component | `aspnet_core` -span.kind | `server` + +| Name | Required | +| ---------------------- | ------------- | +| \_dd.base_service | No | +| aspnet_core.action | Yes | +| aspnet_core.area | No | +| aspnet_core.controller | Yes | +| aspnet_core.page | No | +| aspnet_core.route | Yes | +| component | `aspnet_core` | +| span.kind | `server` | ## AwsDynamoDb + ### Span properties -Name | Required | ----------|----------------| -Name | `aws.dynamodb.request` -Type | `dynamodb` + +| Name | Required | +| ---- | ---------------------- | +| Name | `aws.dynamodb.request` | +| Type | `dynamodb` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -_dd.peer.service.source | `tablename`; `peer.service` -aws_service | `DynamoDB` -aws.agent | `dotnet-aws-sdk` -aws.operation | Yes -aws.region | No -aws.requestId | Yes -aws.service | `DynamoDB` -component | `aws-sdk` -http.method | Yes -http.status_code | Yes -http.url | Yes -peer.service | Yes -peer.service.remapped_from | No -region | No -span.kind | `client` -tablename | Yes + +| Name | Required | +| -------------------------- | --------------------------- | +| \_dd.base_service | No | +| \_dd.peer.service.source | `tablename`; `peer.service` | +| aws_service | `DynamoDB` | +| aws.agent | `dotnet-aws-sdk` | +| aws.operation | Yes | +| aws.region | No | +| aws.requestId | Yes | +| aws.service | `DynamoDB` | +| component | `aws-sdk` | +| http.method | Yes | +| http.status_code | Yes | +| http.url | Yes | +| peer.service | Yes | +| peer.service.remapped_from | No | +| region | No | +| span.kind | `client` | +| tablename | Yes | ## AwsKinesisOutbound + ### Span properties -Name | Required | ----------|----------------| -Name | `aws.kinesis.send` -Type | `http` + +| Name | Required | +| ---- | ------------------ | +| Name | `aws.kinesis.send` | +| Type | `http` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -_dd.peer.service.source | `streamname`; `peer.service` -aws_service | `Kinesis` -aws.agent | `dotnet-aws-sdk` -aws.operation | Yes -aws.region | No -aws.requestId | Yes -aws.service | `Kinesis` -aws.stream.url | No -component | `aws-sdk` -http.method | Yes -http.status_code | Yes -http.url | Yes -peer.service | Yes -peer.service.remapped_from | No -region | No -span.kind | `producer` -streamname | Yes + +| Name | Required | +| -------------------------- | ---------------------------- | +| \_dd.base_service | No | +| \_dd.peer.service.source | `streamname`; `peer.service` | +| aws_service | `Kinesis` | +| aws.agent | `dotnet-aws-sdk` | +| aws.operation | Yes | +| aws.region | No | +| aws.requestId | Yes | +| aws.service | `Kinesis` | +| aws.stream.url | No | +| component | `aws-sdk` | +| http.method | Yes | +| http.status_code | Yes | +| http.url | Yes | +| peer.service | Yes | +| peer.service.remapped_from | No | +| region | No | +| span.kind | `producer` | +| streamname | Yes | ## AwsS3Request + ### Span properties -Name | Required | ----------|----------------| -Name | `aws.s3.request` -Type | `http` + +| Name | Required | +| ---- | ---------------- | +| Name | `aws.s3.request` | +| Type | `http` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -_dd.peer.service.source | No -aws_service | `S3` -aws.agent | `dotnet-aws-sdk` -aws.operation | Yes -aws.region | No -aws.requestId | Yes -aws.service | `S3` -bucketname | No -component | `aws-sdk` -http.method | Yes -http.status_code | Yes -http.url | Yes -objectkey | No -peer.service | No -peer.service.remapped_from | No -region | No -span.kind | `client` + +| Name | Required | +| -------------------------- | ---------------- | +| \_dd.base_service | No | +| \_dd.peer.service.source | No | +| aws_service | `S3` | +| aws.agent | `dotnet-aws-sdk` | +| aws.operation | Yes | +| aws.region | No | +| aws.requestId | Yes | +| aws.service | `S3` | +| bucketname | No | +| component | `aws-sdk` | +| http.method | Yes | +| http.status_code | Yes | +| http.url | Yes | +| objectkey | No | +| peer.service | No | +| peer.service.remapped_from | No | +| region | No | +| span.kind | `client` | ## AwsSqsInbound + ### Span properties -Name | Required | ----------|----------------| -Name | `aws.sqs.process` -Type | `http` + +| Name | Required | +| ---- | ----------------- | +| Name | `aws.sqs.process` | +| Type | `http` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -aws_service | `SQS` -aws.agent | `dotnet-aws-sdk` -aws.operation | Yes -aws.queue.name | Yes -aws.queue.url | No -aws.region | No -aws.requestId | Yes -aws.service | `SQS` -component | `aws-sdk` -http.method | Yes -http.status_code | Yes -http.url | Yes -queuename | Yes -region | No -span.kind | `consumer` + +| Name | Required | +| ----------------- | ---------------- | +| \_dd.base_service | No | +| aws_service | `SQS` | +| aws.agent | `dotnet-aws-sdk` | +| aws.operation | Yes | +| aws.queue.name | Yes | +| aws.queue.url | No | +| aws.region | No | +| aws.requestId | Yes | +| aws.service | `SQS` | +| component | `aws-sdk` | +| http.method | Yes | +| http.status_code | Yes | +| http.url | Yes | +| queuename | Yes | +| region | No | +| span.kind | `consumer` | ## AwsSqsOutbound + ### Span properties -Name | Required | ----------|----------------| -Name | `aws.sqs.send` -Type | `http` + +| Name | Required | +| ---- | -------------- | +| Name | `aws.sqs.send` | +| Type | `http` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -_dd.peer.service.source | `queuename`; `peer.service` -aws_service | `SQS` -aws.agent | `dotnet-aws-sdk` -aws.operation | Yes -aws.queue.name | Yes -aws.queue.url | No -aws.region | No -aws.requestId | Yes -aws.service | `SQS` -component | `aws-sdk` -http.method | Yes -http.status_code | Yes -http.url | Yes -peer.service | Yes -peer.service.remapped_from | No -queuename | Yes -region | No -span.kind | `producer` + +| Name | Required | +| -------------------------- | --------------------------- | +| \_dd.base_service | No | +| \_dd.peer.service.source | `queuename`; `peer.service` | +| aws_service | `SQS` | +| aws.agent | `dotnet-aws-sdk` | +| aws.operation | Yes | +| aws.queue.name | Yes | +| aws.queue.url | No | +| aws.region | No | +| aws.requestId | Yes | +| aws.service | `SQS` | +| component | `aws-sdk` | +| http.method | Yes | +| http.status_code | Yes | +| http.url | Yes | +| peer.service | Yes | +| peer.service.remapped_from | No | +| queuename | Yes | +| region | No | +| span.kind | `producer` | ## AwsSqsRequest + ### Span properties -Name | Required | ----------|----------------| -Name | `aws.sqs.request` -Type | `http` + +| Name | Required | +| ---- | ----------------- | +| Name | `aws.sqs.request` | +| Type | `http` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -_dd.peer.service.source | `queuename`; `peer.service` -aws_service | `SQS` -aws.agent | `dotnet-aws-sdk` -aws.operation | Yes -aws.queue.name | Yes -aws.queue.url | No -aws.region | No -aws.requestId | Yes -aws.service | `SQS` -component | `aws-sdk` -http.method | Yes -http.status_code | Yes -http.url | Yes -peer.service | Yes -peer.service.remapped_from | No -queuename | Yes -region | No -span.kind | `client` + +| Name | Required | +| -------------------------- | --------------------------- | +| \_dd.base_service | No | +| \_dd.peer.service.source | `queuename`; `peer.service` | +| aws_service | `SQS` | +| aws.agent | `dotnet-aws-sdk` | +| aws.operation | Yes | +| aws.queue.name | Yes | +| aws.queue.url | No | +| aws.region | No | +| aws.requestId | Yes | +| aws.service | `SQS` | +| component | `aws-sdk` | +| http.method | Yes | +| http.status_code | Yes | +| http.url | Yes | +| peer.service | Yes | +| peer.service.remapped_from | No | +| queuename | Yes | +| region | No | +| span.kind | `client` | ## AwsSnsInbound + ### Span properties -Name | Required | ----------|----------------| -Name | `aws.sns.process` -Type | `http` + +| Name | Required | +| ---- | ----------------- | +| Name | `aws.sns.process` | +| Type | `http` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -aws_service | `SNS` -aws.agent | `dotnet-aws-sdk` -aws.operation | Yes -aws.region | No -aws.requestId | Yes -aws.service | `SNS` -aws.topic.arn | No -aws.topic.name | Yes -component | `aws-sdk` -http.method | Yes -http.status_code | Yes -http.url | Yes -region | No -span.kind | `consumer` -topicname | Yes + +| Name | Required | +| ----------------- | ---------------- | +| \_dd.base_service | No | +| aws_service | `SNS` | +| aws.agent | `dotnet-aws-sdk` | +| aws.operation | Yes | +| aws.region | No | +| aws.requestId | Yes | +| aws.service | `SNS` | +| aws.topic.arn | No | +| aws.topic.name | Yes | +| component | `aws-sdk` | +| http.method | Yes | +| http.status_code | Yes | +| http.url | Yes | +| region | No | +| span.kind | `consumer` | +| topicname | Yes | ## AwsSnsOutbound + ### Span properties -Name | Required | ----------|----------------| -Name | `aws.sns.send` -Type | `http` + +| Name | Required | +| ---- | -------------- | +| Name | `aws.sns.send` | +| Type | `http` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -_dd.peer.service.source | `topicname`; `peer.service` -aws_service | `SNS` -aws.agent | `dotnet-aws-sdk` -aws.operation | Yes -aws.region | No -aws.requestId | Yes -aws.service | `SNS` -aws.topic.arn | No -aws.topic.name | Yes -component | `aws-sdk` -http.method | Yes -http.status_code | Yes -http.url | Yes -peer.service | Yes -peer.service.remapped_from | No -region | No -span.kind | `producer` -topicname | Yes + +| Name | Required | +| -------------------------- | --------------------------- | +| \_dd.base_service | No | +| \_dd.peer.service.source | `topicname`; `peer.service` | +| aws_service | `SNS` | +| aws.agent | `dotnet-aws-sdk` | +| aws.operation | Yes | +| aws.region | No | +| aws.requestId | Yes | +| aws.service | `SNS` | +| aws.topic.arn | No | +| aws.topic.name | Yes | +| component | `aws-sdk` | +| http.method | Yes | +| http.status_code | Yes | +| http.url | Yes | +| peer.service | Yes | +| peer.service.remapped_from | No | +| region | No | +| span.kind | `producer` | +| topicname | Yes | ## AwsSnsRequest + ### Span properties -Name | Required | ----------|----------------| -Name | `aws.sns.request` -Type | `http` + +| Name | Required | +| ---- | ----------------- | +| Name | `aws.sns.request` | +| Type | `http` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -_dd.peer.service.source | `topicname`; `peer.service` -aws_service | `SNS` -aws.agent | `dotnet-aws-sdk` -aws.operation | Yes -aws.region | No -aws.requestId | Yes -aws.service | `SNS` -aws.topic.arn | No -aws.topic.name | Yes -component | `aws-sdk` -http.method | Yes -http.status_code | Yes -http.url | Yes -peer.service | Yes -peer.service.remapped_from | No -region | No -span.kind | `client` -topicname | Yes + +| Name | Required | +| -------------------------- | --------------------------- | +| \_dd.base_service | No | +| \_dd.peer.service.source | `topicname`; `peer.service` | +| aws_service | `SNS` | +| aws.agent | `dotnet-aws-sdk` | +| aws.operation | Yes | +| aws.region | No | +| aws.requestId | Yes | +| aws.service | `SNS` | +| aws.topic.arn | No | +| aws.topic.name | Yes | +| component | `aws-sdk` | +| http.method | Yes | +| http.status_code | Yes | +| http.url | Yes | +| peer.service | Yes | +| peer.service.remapped_from | No | +| region | No | +| span.kind | `client` | +| topicname | Yes | ## AwsEventBridgeInbound + ### Span properties -Name | Required | ----------|----------------| -Name | `aws.eventbridge.process` -Type | `http` + +| Name | Required | +| ---- | ------------------------- | +| Name | `aws.eventbridge.process` | +| Type | `http` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -aws_service | `EventBridge` -aws.agent | `dotnet-aws-sdk` -aws.operation | Yes -aws.region | No -aws.requestId | Yes -aws.service | `EventBridge` -component | `aws-sdk` -http.method | Yes -http.status_code | Yes -http.url | Yes -region | No -rulename | Yes -span.kind | `consumer` + +| Name | Required | +| ----------------- | ---------------- | +| \_dd.base_service | No | +| aws_service | `EventBridge` | +| aws.agent | `dotnet-aws-sdk` | +| aws.operation | Yes | +| aws.region | No | +| aws.requestId | Yes | +| aws.service | `EventBridge` | +| component | `aws-sdk` | +| http.method | Yes | +| http.status_code | Yes | +| http.url | Yes | +| region | No | +| rulename | Yes | +| span.kind | `consumer` | ## AwsEventBridgeOutbound + ### Span properties -Name | Required | ----------|----------------| -Name | `aws.eventbridge.send` -Type | `http` + +| Name | Required | +| ---- | ---------------------- | +| Name | `aws.eventbridge.send` | +| Type | `http` | + ### Tags -Name | Required | ----------|----------------| -_dd.peer.service.source | `rulename`; `peer.service` -aws_service | `EventBridge` -aws.agent | `dotnet-aws-sdk` -aws.operation | Yes -aws.region | No -aws.requestId | Yes -aws.service | `EventBridge` -component | `aws-sdk` -http.method | Yes -http.status_code | Yes -http.url | Yes -peer.service | Yes -peer.service.remapped_from | No -region | No -rulename | Yes -span.kind | `producer` + +| Name | Required | +| -------------------------- | -------------------------- | +| \_dd.peer.service.source | `rulename`; `peer.service` | +| aws_service | `EventBridge` | +| aws.agent | `dotnet-aws-sdk` | +| aws.operation | Yes | +| aws.region | No | +| aws.requestId | Yes | +| aws.service | `EventBridge` | +| component | `aws-sdk` | +| http.method | Yes | +| http.status_code | Yes | +| http.url | Yes | +| peer.service | Yes | +| peer.service.remapped_from | No | +| region | No | +| rulename | Yes | +| span.kind | `producer` | ## AwsEventBridgeRequest + ### Span properties -Name | Required | ----------|----------------| -Name | `aws.eventbridge.request` -Type | `http` + +| Name | Required | +| ---- | ------------------------- | +| Name | `aws.eventbridge.request` | +| Type | `http` | + ### Tags -Name | Required | ----------|----------------| -aws_service | `EventBridge` -aws.agent | `dotnet-aws-sdk` -aws.operation | Yes -aws.region | No -aws.requestId | Yes -aws.service | `EventBridge` -component | `aws-sdk` -http.method | Yes -http.status_code | Yes -http.url | Yes -peer.service | Yes -peer.service.remapped_from | No -region | No -rulename | Yes -span.kind | `client` + +| Name | Required | +| -------------------------- | ---------------- | +| aws_service | `EventBridge` | +| aws.agent | `dotnet-aws-sdk` | +| aws.operation | Yes | +| aws.region | No | +| aws.requestId | Yes | +| aws.service | `EventBridge` | +| component | `aws-sdk` | +| http.method | Yes | +| http.status_code | Yes | +| http.url | Yes | +| peer.service | Yes | +| peer.service.remapped_from | No | +| region | No | +| rulename | Yes | +| span.kind | `client` | ## AwsStepFunctionsInbound + ### Span properties -Name | Required | ----------|----------------| -Name | `aws.stepfunctions.process` -Type | `http` + +| Name | Required | +| ---- | --------------------------- | +| Name | `aws.stepfunctions.process` | +| Type | `http` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -aws_service | `StepFunctions` -aws.agent | `dotnet-aws-sdk` -aws.operation | Yes -aws.region | No -aws.requestId | Yes -aws.service | `StepFunctions` -component | `aws-sdk` -http.method | Yes -http.status_code | Yes -http.url | Yes -region | No -span.kind | `consumer` + +| Name | Required | +| ----------------- | ---------------- | +| \_dd.base_service | No | +| aws_service | `StepFunctions` | +| aws.agent | `dotnet-aws-sdk` | +| aws.operation | Yes | +| aws.region | No | +| aws.requestId | Yes | +| aws.service | `StepFunctions` | +| component | `aws-sdk` | +| http.method | Yes | +| http.status_code | Yes | +| http.url | Yes | +| region | No | +| span.kind | `consumer` | ## AwsStepFunctionsOutbound + ### Span properties -Name | Required | ----------|----------------| -Name | `aws.stepfunctions.send` -Type | `http` + +| Name | Required | +| ---- | ------------------------ | +| Name | `aws.stepfunctions.send` | +| Type | `http` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -_dd.peer.service.source | `statemachinename`; `peer.service` -aws_service | `StepFunctions` -aws.agent | `dotnet-aws-sdk` -aws.operation | Yes -aws.region | No -aws.requestId | Yes -aws.service | `StepFunctions` -component | `aws-sdk` -http.method | Yes -http.status_code | Yes -http.url | Yes -peer.service | Yes -peer.service.remapped_from | No -region | No -span.kind | `producer` -statemachinename | Yes + +| Name | Required | +| -------------------------- | ---------------------------------- | +| \_dd.base_service | No | +| \_dd.peer.service.source | `statemachinename`; `peer.service` | +| aws_service | `StepFunctions` | +| aws.agent | `dotnet-aws-sdk` | +| aws.operation | Yes | +| aws.region | No | +| aws.requestId | Yes | +| aws.service | `StepFunctions` | +| component | `aws-sdk` | +| http.method | Yes | +| http.status_code | Yes | +| http.url | Yes | +| peer.service | Yes | +| peer.service.remapped_from | No | +| region | No | +| span.kind | `producer` | +| statemachinename | Yes | ## AwsStepFunctionsRequest + ### Span properties -Name | Required | ----------|----------------| -Name | `aws.stepfunctions.request` -Type | `http` + +| Name | Required | +| ---- | --------------------------- | +| Name | `aws.stepfunctions.request` | +| Type | `http` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -_dd.peer.service.source | `statemachinename`; `peer.service` -aws_service | `StepFunctions` -aws.agent | `dotnet-aws-sdk` -aws.operation | Yes -aws.region | No -aws.requestId | Yes -aws.service | `StepFunctions` -component | `aws-sdk` -http.method | Yes -http.status_code | Yes -http.url | Yes -peer.service | Yes -peer.service.remapped_from | No -region | No -span.kind | `client` + +| Name | Required | +| -------------------------- | ---------------------------------- | +| \_dd.base_service | No | +| \_dd.peer.service.source | `statemachinename`; `peer.service` | +| aws_service | `StepFunctions` | +| aws.agent | `dotnet-aws-sdk` | +| aws.operation | Yes | +| aws.region | No | +| aws.requestId | Yes | +| aws.service | `StepFunctions` | +| component | `aws-sdk` | +| http.method | Yes | +| http.status_code | Yes | +| http.url | Yes | +| peer.service | Yes | +| peer.service.remapped_from | No | +| region | No | +| span.kind | `client` | ## AzureServiceBusInbound + ### Span properties -Name | Required | ----------|----------------| -Name | `servicebus.receive`; `servicebus.process`; `consumer` -Type | `http`; `custom` + +| Name | Required | +| ---- | ------------------------------------------------------ | +| Name | `servicebus.receive`; `servicebus.process`; `consumer` | +| Type | `http`; `custom` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -az.namespace | `Microsoft.ServiceBus` -az.schema_url | No -component | Optional: `servicebus` -kind | Optional: `consumer` -messaging.destination.name | No -messaging.operation | Optional: `receive`; `process` -messaging.source.name | No -messaging.system | Optional: `servicebus` -net.peer.name | No -otel.library.name | Yes -otel.library.version | No -otel.status_code | `STATUS_CODE_UNSET`; `STATUS_CODE_OK`; `STATUS_CODE_ERROR` -otel.status_description | No -otel.trace_id | Yes -peer.address | No -server.address | No -span.kind | `consumer` + +| Name | Required | +| -------------------------- | ---------------------------------------------------------- | +| \_dd.base_service | No | +| az.namespace | `Microsoft.ServiceBus` | +| az.schema_url | No | +| component | Optional: `servicebus` | +| kind | Optional: `consumer` | +| messaging.destination.name | No | +| messaging.operation | Optional: `receive`; `process` | +| messaging.source.name | No | +| messaging.system | Optional: `servicebus` | +| net.peer.name | No | +| otel.library.name | Yes | +| otel.library.version | No | +| otel.status_code | `STATUS_CODE_UNSET`; `STATUS_CODE_OK`; `STATUS_CODE_ERROR` | +| otel.status_description | No | +| otel.trace_id | Yes | +| peer.address | No | +| server.address | No | +| span.kind | `consumer` | ## AzureServiceBusOutbound + ### Span properties -Name | Required | ----------|----------------| -Name | `producer` -Type | `custom` + +| Name | Required | +| ---- | ---------- | +| Name | `producer` | +| Type | `custom` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -_dd.peer.service.source | `messaging.destination.name`; `message_bus.destination`; `peer.service` -az.namespace | `Microsoft.ServiceBus` -az.schema_url | No -component | Optional: `servicebus` -kind | Optional: `producer` -messaging.destination.name | Yes -messaging.system | Optional: `servicebus` -net.peer.name | No -otel.library.name | Yes -otel.library.version | No -otel.status_code | `STATUS_CODE_UNSET`; `STATUS_CODE_OK`; `STATUS_CODE_ERROR` -otel.status_description | No -otel.trace_id | Yes -peer.address | No -peer.service | Yes -peer.service.remapped_from | No -server.address | No -span.kind | `producer` + +| Name | Required | +| -------------------------- | ----------------------------------------------------------------------- | +| \_dd.base_service | No | +| \_dd.peer.service.source | `messaging.destination.name`; `message_bus.destination`; `peer.service` | +| az.namespace | `Microsoft.ServiceBus` | +| az.schema_url | No | +| component | Optional: `servicebus` | +| kind | Optional: `producer` | +| messaging.destination.name | Yes | +| messaging.system | Optional: `servicebus` | +| net.peer.name | No | +| otel.library.name | Yes | +| otel.library.version | No | +| otel.status_code | `STATUS_CODE_UNSET`; `STATUS_CODE_OK`; `STATUS_CODE_ERROR` | +| otel.status_description | No | +| otel.trace_id | Yes | +| peer.address | No | +| peer.service | Yes | +| peer.service.remapped_from | No | +| server.address | No | +| span.kind | `producer` | ## AzureServiceBusRequest + ### Span properties -Name | Required | ----------|----------------| -Name | `servicebus.publish`; `servicebus.settle`; `client.request` -Type | `http` + +| Name | Required | +| ---- | ----------------------------------------------------------- | +| Name | `servicebus.publish`; `servicebus.settle`; `client.request` | +| Type | `http` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -_dd.peer.service.source | `messaging.destination.name`; `message_bus.destination`; `peer.service` -az.namespace | `Microsoft.ServiceBus` -az.schema_url | No -component | Optional: `servicebus` -kind | Optional: `client` -messaging.destination.name | No -messaging.operation | Optional: `publish`; `settle` -messaging.source.name | No -messaging.system | Optional: `servicebus` -net.peer.name | No -otel.library.name | Yes -otel.library.version | No -otel.status_code | `STATUS_CODE_UNSET`; `STATUS_CODE_OK`; `STATUS_CODE_ERROR` -otel.status_description | No -otel.trace_id | Yes -peer.address | No -peer.service | Yes -peer.service.remapped_from | No -server.address | No -span.kind | `client` + +| Name | Required | +| -------------------------- | ----------------------------------------------------------------------- | +| \_dd.base_service | No | +| \_dd.peer.service.source | `messaging.destination.name`; `message_bus.destination`; `peer.service` | +| az.namespace | `Microsoft.ServiceBus` | +| az.schema_url | No | +| component | Optional: `servicebus` | +| kind | Optional: `client` | +| messaging.destination.name | No | +| messaging.operation | Optional: `publish`; `settle` | +| messaging.source.name | No | +| messaging.system | Optional: `servicebus` | +| net.peer.name | No | +| otel.library.name | Yes | +| otel.library.version | No | +| otel.status_code | `STATUS_CODE_UNSET`; `STATUS_CODE_OK`; `STATUS_CODE_ERROR` | +| otel.status_description | No | +| otel.trace_id | Yes | +| peer.address | No | +| peer.service | Yes | +| peer.service.remapped_from | No | +| server.address | No | +| span.kind | `client` | ## CosmosDb + ### Span properties -Name | Required | ----------|----------------| -Name | `cosmosdb.query` -Type | `sql` + +| Name | Required | +| ---- | ---------------- | +| Name | `cosmosdb.query` | +| Type | `sql` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -_dd.peer.service.source | `db.name`; `out.host`; `peer.service` -component | `CosmosDb` -cosmosdb.container | No -db.name | No -db.type | `cosmosdb` -out.host | Yes -out.port | Yes -peer.service | Yes -peer.service.remapped_from | No -span.kind | `client` + +| Name | Required | +| -------------------------- | ------------------------------------- | +| \_dd.base_service | No | +| \_dd.peer.service.source | `db.name`; `out.host`; `peer.service` | +| component | `CosmosDb` | +| cosmosdb.container | No | +| db.name | No | +| db.type | `cosmosdb` | +| out.host | Yes | +| out.port | Yes | +| peer.service | Yes | +| peer.service.remapped_from | No | +| span.kind | `client` | ## Couchbase + ### Span properties -Name | Required | ----------|----------------| -Name | `couchbase.query` -Type | `db` + +| Name | Required | +| ---- | ----------------- | +| Name | `couchbase.query` | +| Type | `db` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -_dd.peer.service.source | `db.couchbase.seed.nodes`; `out.host`; `peer.service` -component | `Couchbase` -couchbase.operation.bucket | No -couchbase.operation.code | Yes -couchbase.operation.key | Yes -db.couchbase.seed.nodes | Yes -out.host | No -out.port | No -peer.service | Yes -peer.service.remapped_from | No -span.kind | `client` + +| Name | Required | +| -------------------------- | ----------------------------------------------------- | +| \_dd.base_service | No | +| \_dd.peer.service.source | `db.couchbase.seed.nodes`; `out.host`; `peer.service` | +| component | `Couchbase` | +| couchbase.operation.bucket | No | +| couchbase.operation.code | Yes | +| couchbase.operation.key | Yes | +| db.couchbase.seed.nodes | Yes | +| out.host | No | +| out.port | No | +| peer.service | Yes | +| peer.service.remapped_from | No | +| span.kind | `client` | ## ElasticsearchNet + ### Span properties -Name | Required | ----------|----------------| -Name | `elasticsearch.query` -Type | `elasticsearch` + +| Name | Required | +| ---- | --------------------- | +| Name | `elasticsearch.query` | +| Type | `elasticsearch` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -_dd.peer.service.source | `out.host`; `peer.service` -component | `elasticsearch-net` -elasticsearch.action | Yes -elasticsearch.method | Yes -elasticsearch.url | Yes -out.host | Yes -peer.service | Yes -peer.service.remapped_from | No -span.kind | `client` + +| Name | Required | +| -------------------------- | -------------------------- | +| \_dd.base_service | No | +| \_dd.peer.service.source | `out.host`; `peer.service` | +| component | `elasticsearch-net` | +| elasticsearch.action | Yes | +| elasticsearch.method | Yes | +| elasticsearch.url | Yes | +| out.host | Yes | +| peer.service | Yes | +| peer.service.remapped_from | No | +| span.kind | `client` | ## GraphQL + ### Span properties -Name | Required | ----------|----------------| -Name | `graphql.execute`; `graphql.validate` -Type | `graphql` + +| Name | Required | +| ---- | ------------------------------------- | +| Name | `graphql.execute`; `graphql.validate` | +| Type | `graphql` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -component | `GraphQL` -graphql.operation.name | No -graphql.operation.type | No -graphql.source | Yes -span.kind | `server` + +| Name | Required | +| ---------------------- | --------- | +| \_dd.base_service | No | +| component | `GraphQL` | +| graphql.operation.name | No | +| graphql.operation.type | No | +| graphql.source | Yes | +| span.kind | `server` | ## gRPC Client + ### Span properties -Name | Required | ----------|----------------| -Name | `grpc.client.request` -Type | `grpc` + +| Name | Required | +| ---- | --------------------- | +| Name | `grpc.client.request` | +| Type | `grpc` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -_dd.peer.service.source | `rpc.service`; `out.host`; `peer.service` -component | `Grpc` -grpc.method.kind | Yes -grpc.method.name | Yes -grpc.method.package | Yes -grpc.method.path | Yes -grpc.method.service | Yes -grpc.status.code | Yes -out.host | Yes -peer.hostname | Yes -peer.service | Yes -peer.service.remapped_from | No -span.kind | `client` + +| Name | Required | +| -------------------------- | ----------------------------------------- | +| \_dd.base_service | No | +| \_dd.peer.service.source | `rpc.service`; `out.host`; `peer.service` | +| component | `Grpc` | +| grpc.method.kind | Yes | +| grpc.method.name | Yes | +| grpc.method.package | Yes | +| grpc.method.path | Yes | +| grpc.method.service | Yes | +| grpc.status.code | Yes | +| out.host | Yes | +| peer.hostname | Yes | +| peer.service | Yes | +| peer.service.remapped_from | No | +| span.kind | `client` | ## gRPC Server + ### Span properties -Name | Required | ----------|----------------| -Name | `grpc.server.request` -Type | `grpc` + +| Name | Required | +| ---- | --------------------- | +| Name | `grpc.server.request` | +| Type | `grpc` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -component | `Grpc` -grpc.method.kind | Yes -grpc.method.name | Yes -grpc.method.package | Yes -grpc.method.path | Yes -grpc.method.service | Yes -grpc.status.code | Yes -span.kind | `server` + +| Name | Required | +| ------------------- | -------- | +| \_dd.base_service | No | +| component | `Grpc` | +| grpc.method.kind | Yes | +| grpc.method.name | Yes | +| grpc.method.package | Yes | +| grpc.method.path | Yes | +| grpc.method.service | Yes | +| grpc.status.code | Yes | +| span.kind | `server` | ## HotChocolate + ### Span properties -Name | Required | ----------|----------------| -Name | `graphql.execute`; `graphql.validate` -Type | `graphql` + +| Name | Required | +| ---- | ------------------------------------- | +| Name | `graphql.execute`; `graphql.validate` | +| Type | `graphql` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -component | `HotChocolate` -graphql.operation.name | No -graphql.operation.type | No -graphql.source | Yes -span.kind | `server` + +| Name | Required | +| ---------------------- | -------------- | +| \_dd.base_service | No | +| component | `HotChocolate` | +| graphql.operation.name | No | +| graphql.operation.type | No | +| graphql.source | Yes | +| span.kind | `server` | ## HttpMessageHandler + ### Span properties -Name | Required | ----------|----------------| -Name | `http.client.request` -Type | `http` + +| Name | Required | +| ---- | --------------------- | +| Name | `http.client.request` | +| Type | `http` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -_dd.peer.service.source | `out.host`; `peer.service` -component | Yes -http-client-handler-type | Yes -http.method | Yes -http.status_code | Yes -http.url | Yes -out.host | Yes -peer.service | Yes -peer.service.remapped_from | No -span.kind | `client` + +| Name | Required | +| -------------------------- | -------------------------- | +| \_dd.base_service | No | +| \_dd.peer.service.source | `out.host`; `peer.service` | +| component | Yes | +| http-client-handler-type | Yes | +| http.method | Yes | +| http.status_code | Yes | +| http.url | Yes | +| out.host | Yes | +| peer.service | Yes | +| peer.service.remapped_from | No | +| span.kind | `client` | ## Kafka - Inbound + ### Span properties -Name | Required | ----------|----------------| -Name | `kafka.process` -Type | `queue` + +| Name | Required | +| ---- | --------------- | +| Name | `kafka.process` | +| Type | `queue` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -component | `kafka` -kafka.group | No -kafka.offset | No -kafka.partition | No -kafka.tombstone | No -messaging.destination.name | Yes -messaging.kafka.bootstrap.servers | Yes -span.kind | `consumer` + +| Name | Required | +| --------------------------------- | ---------- | +| \_dd.base_service | No | +| component | `kafka` | +| kafka.group | No | +| kafka.offset | No | +| kafka.partition | No | +| kafka.tombstone | No | +| messaging.destination.name | Yes | +| messaging.kafka.bootstrap.servers | Yes | +| messaging.kafka.cluster_id | No | +| span.kind | `consumer` | + ### Metrics -Name | Required | ----------|----------------| -_dd.measured | Yes -message.queue_time_ms | No + +| Name | Required | +| --------------------- | -------- | +| \_dd.measured | Yes | +| message.queue_time_ms | No | ## Kafka - Outbound + ### Span properties -Name | Required | ----------|----------------| -Name | `kafka.send` -Type | `queue` + +| Name | Required | +| ---- | ------------ | +| Name | `kafka.send` | +| Type | `queue` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -_dd.peer.service.source | `messaging.kafka.bootstrap.servers`; `peer.service` -component | `kafka` -kafka.group | No -kafka.offset | No -kafka.partition | No -kafka.tombstone | No -messaging.destination.name | Yes -messaging.kafka.bootstrap.servers | Yes -peer.service | Yes -peer.service.remapped_from | No -span.kind | `producer` + +| Name | Required | +| --------------------------------- | --------------------------------------------------- | +| \_dd.base_service | No | +| \_dd.peer.service.source | `messaging.kafka.bootstrap.servers`; `peer.service` | +| component | `kafka` | +| kafka.group | No | +| kafka.offset | No | +| kafka.partition | No | +| kafka.tombstone | No | +| messaging.destination.name | Yes | +| messaging.kafka.bootstrap.servers | Yes | +| messaging.kafka.cluster_id | No | +| peer.service | Yes | +| peer.service.remapped_from | No | +| span.kind | `producer` | + ### Metrics -Name | Required | ----------|----------------| -_dd.measured | Yes -message.queue_time_ms | No + +| Name | Required | +| --------------------- | -------- | +| \_dd.measured | Yes | +| message.queue_time_ms | No | ## MongoDb + ### Span properties -Name | Required | ----------|----------------| -Name | `mongodb.query` -Type | `mongodb` + +| Name | Required | +| ---- | --------------- | +| Name | `mongodb.query` | +| Type | `mongodb` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -_dd.peer.service.source | `db.name`; `out.host`; `peer.service` -component | `MongoDb` -db.name | No -mongodb.collection | No -mongodb.query | No -out.host | Yes -out.port | Yes -peer.service | Yes -peer.service.remapped_from | No -span.kind | `client` + +| Name | Required | +| -------------------------- | ------------------------------------- | +| \_dd.base_service | No | +| \_dd.peer.service.source | `db.name`; `out.host`; `peer.service` | +| component | `MongoDb` | +| db.name | No | +| mongodb.collection | No | +| mongodb.query | No | +| out.host | Yes | +| out.port | Yes | +| peer.service | Yes | +| peer.service.remapped_from | No | +| span.kind | `client` | ## Msmq - Inbound + ### Span properties -Name | Required | ----------|----------------| -Name | `msmq.process` -Type | `queue` + +| Name | Required | +| ---- | -------------- | +| Name | `msmq.process` | +| Type | `queue` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -component | `msmq` -msmq.command | Yes -msmq.message.transactional | No -msmq.queue.path | Yes -msmq.queue.transactional | No -out.host | Yes -span.kind | `consumer` + +| Name | Required | +| -------------------------- | ---------- | +| \_dd.base_service | No | +| component | `msmq` | +| msmq.command | Yes | +| msmq.message.transactional | No | +| msmq.queue.path | Yes | +| msmq.queue.transactional | No | +| out.host | Yes | +| span.kind | `consumer` | ## Msmq - Outbound + ### Span properties -Name | Required | ----------|----------------| -Name | `msmq.send` -Type | `queue` + +| Name | Required | +| ---- | ----------- | +| Name | `msmq.send` | +| Type | `queue` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -_dd.peer.service.source | `out.host`; `peer.service` -component | `msmq` -msmq.command | Yes -msmq.message.transactional | No -msmq.queue.path | Yes -msmq.queue.transactional | No -out.host | Yes -peer.service | Yes -peer.service.remapped_from | No -span.kind | `producer` + +| Name | Required | +| -------------------------- | -------------------------- | +| \_dd.base_service | No | +| \_dd.peer.service.source | `out.host`; `peer.service` | +| component | `msmq` | +| msmq.command | Yes | +| msmq.message.transactional | No | +| msmq.queue.path | Yes | +| msmq.queue.transactional | No | +| out.host | Yes | +| peer.service | Yes | +| peer.service.remapped_from | No | +| span.kind | `producer` | ## Msmq - Client + ### Span properties -Name | Required | ----------|----------------| -Name | `msmq.command` -Type | `queue` + +| Name | Required | +| ---- | -------------- | +| Name | `msmq.command` | +| Type | `queue` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -_dd.peer.service.source | `out.host`; `peer.service` -component | `msmq` -msmq.command | Yes -msmq.message.transactional | No -msmq.queue.path | Yes -msmq.queue.transactional | No -out.host | Yes -peer.service | Yes -peer.service.remapped_from | No -span.kind | `client` + +| Name | Required | +| -------------------------- | -------------------------- | +| \_dd.base_service | No | +| \_dd.peer.service.source | `out.host`; `peer.service` | +| component | `msmq` | +| msmq.command | Yes | +| msmq.message.transactional | No | +| msmq.queue.path | Yes | +| msmq.queue.transactional | No | +| out.host | Yes | +| peer.service | Yes | +| peer.service.remapped_from | No | +| span.kind | `client` | ## MySql + ### Span properties -Name | Required | ----------|----------------| -Name | `mysql.query` -Type | `sql` + +| Name | Required | +| ---- | ------------- | +| Name | `mysql.query` | +| Type | `sql` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -_dd.dbm_trace_injected | No -_dd.peer.service.source | `db.name`; `out.host`; `peer.service` -component | `MySql` -db.name | Yes -db.type | `mysql` -db.user | Yes -out.host | Yes -peer.service | Yes -peer.service.remapped_from | No -span.kind | `client` + +| Name | Required | +| -------------------------- | ------------------------------------- | +| \_dd.base_service | No | +| \_dd.dbm_trace_injected | No | +| \_dd.peer.service.source | `db.name`; `out.host`; `peer.service` | +| component | `MySql` | +| db.name | Yes | +| db.type | `mysql` | +| db.user | Yes | +| out.host | Yes | +| peer.service | Yes | +| peer.service.remapped_from | No | +| span.kind | `client` | ## Npgsql + ### Span properties -Name | Required | ----------|----------------| -Name | `postgres.query` -Type | `sql` + +| Name | Required | +| ---- | ---------------- | +| Name | `postgres.query` | +| Type | `sql` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -_dd.dbm_trace_injected | No -_dd.peer.service.source | `db.name`; `out.host`; `peer.service` -component | `Npgsql` -db.name | Yes -db.type | `postgres` -out.host | Yes -peer.service | Yes -peer.service.remapped_from | No -span.kind | `client` + +| Name | Required | +| -------------------------- | ------------------------------------- | +| \_dd.base_service | No | +| \_dd.dbm_trace_injected | No | +| \_dd.peer.service.source | `db.name`; `out.host`; `peer.service` | +| component | `Npgsql` | +| db.name | Yes | +| db.type | `postgres` | +| out.host | Yes | +| peer.service | Yes | +| peer.service.remapped_from | No | +| span.kind | `client` | ## OpenTelemetry + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -otel.library.name | Yes -otel.library.version | No -otel.status_code | `STATUS_CODE_UNSET`; `STATUS_CODE_OK`; `STATUS_CODE_ERROR` -otel.status_description | No -otel.trace_id | Yes -span.kind | `internal`; `server`; `client`; `producer`; `consumer` + +| Name | Required | +| ----------------------- | ---------------------------------------------------------- | +| \_dd.base_service | No | +| otel.library.name | Yes | +| otel.library.version | No | +| otel.status_code | `STATUS_CODE_UNSET`; `STATUS_CODE_OK`; `STATUS_CODE_ERROR` | +| otel.status_description | No | +| otel.trace_id | Yes | +| span.kind | `internal`; `server`; `client`; `producer`; `consumer` | + ### AdditionalTags -Source | Operation | Required | ----------|-----------|----------------| -OTEL Resource Attributes | PassThru | No + +| Source | Operation | Required | +| ------------------------ | --------- | -------- | +| OTEL Resource Attributes | PassThru | No | ## Oracle + ### Span properties -Name | Required | ----------|----------------| -Name | `oracle.query` -Type | `sql` + +| Name | Required | +| ---- | -------------- | +| Name | `oracle.query` | +| Type | `sql` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -_dd.peer.service.source | `db.name`; `out.host`; `peer.service` -component | `Oracle` -db.name | Yes -db.type | `oracle` -out.host | Yes -peer.service | Yes -peer.service.remapped_from | No -span.kind | `client` + +| Name | Required | +| -------------------------- | ------------------------------------- | +| \_dd.base_service | No | +| \_dd.peer.service.source | `db.name`; `out.host`; `peer.service` | +| component | `Oracle` | +| db.name | Yes | +| db.type | `oracle` | +| out.host | Yes | +| peer.service | Yes | +| peer.service.remapped_from | No | +| span.kind | `client` | ## Process + ### Span properties -Name | Required | ----------|----------------| -Name | `command_execution` -Type | `system` + +| Name | Required | +| ---- | ------------------- | +| Name | `command_execution` | +| Type | `system` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -cmd.environment_variables | No -cmd.exec | No -cmd.shell | No -cmd.truncated | No -component | `process` -span.kind | `internal` + +| Name | Required | +| ------------------------- | ---------- | +| \_dd.base_service | No | +| cmd.environment_variables | No | +| cmd.exec | No | +| cmd.shell | No | +| cmd.truncated | No | +| component | `process` | +| span.kind | `internal` | ## Protobuf + ### Tags -Name | Required | ----------|----------------| -Tags.SchemaDefinition | Yes -Tags.SchemaId | Yes -Tags.SchemaName | Yes -Tags.SchemaOperation | Yes -Tags.SchemaType | `protobuf` -Tags.SchemaWeight | Yes + +| Name | Required | +| --------------------- | ---------- | +| Tags.SchemaDefinition | Yes | +| Tags.SchemaId | Yes | +| Tags.SchemaName | Yes | +| Tags.SchemaOperation | Yes | +| Tags.SchemaType | `protobuf` | +| Tags.SchemaWeight | Yes | ## Rabbit - Admin + ### Span properties -Name | Required | ----------|----------------| -Name | `amqp.command` -Type | `queue` + +| Name | Required | +| ---- | -------------- | +| Name | `amqp.command` | +| Type | `queue` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -_dd.peer.service.source | `out.host`; `peer.service` -amqp.command | Yes -amqp.delivery_mode | No -amqp.exchange | No -amqp.queue | No -amqp.routing_key | No -component | `RabbitMQ` -message.size | No -out.host | Yes -peer.service | Yes -peer.service.remapped_from | No -span.kind | `client` + +| Name | Required | +| -------------------------- | -------------------------- | +| \_dd.base_service | No | +| \_dd.peer.service.source | `out.host`; `peer.service` | +| amqp.command | Yes | +| amqp.delivery_mode | No | +| amqp.exchange | No | +| amqp.queue | No | +| amqp.routing_key | No | +| component | `RabbitMQ` | +| message.size | No | +| out.host | Yes | +| peer.service | Yes | +| peer.service.remapped_from | No | +| span.kind | `client` | ## Rabbit - Inbound + ### Span properties -Name | Required | ----------|----------------| -Name | `amqp.process` -Type | `queue` + +| Name | Required | +| ---- | -------------- | +| Name | `amqp.process` | +| Type | `queue` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -amqp.command | Yes -amqp.delivery_mode | No -amqp.exchange | No -amqp.queue | No -amqp.routing_key | No -component | `RabbitMQ` -message.size | No -span.kind | `consumer` + +| Name | Required | +| ------------------ | ---------- | +| \_dd.base_service | No | +| amqp.command | Yes | +| amqp.delivery_mode | No | +| amqp.exchange | No | +| amqp.queue | No | +| amqp.routing_key | No | +| component | `RabbitMQ` | +| message.size | No | +| span.kind | `consumer` | ## Rabbit - Outbound + ### Span properties -Name | Required | ----------|----------------| -Name | `amqp.send` -Type | `queue` + +| Name | Required | +| ---- | ----------- | +| Name | `amqp.send` | +| Type | `queue` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -_dd.peer.service.source | `out.host`; `peer.service` -amqp.command | Yes -amqp.delivery_mode | No -amqp.exchange | No -amqp.queue | No -amqp.routing_key | No -component | `RabbitMQ` -message.size | No -out.host | Yes -peer.service | Yes -peer.service.remapped_from | No -span.kind | `producer` + +| Name | Required | +| -------------------------- | -------------------------- | +| \_dd.base_service | No | +| \_dd.peer.service.source | `out.host`; `peer.service` | +| amqp.command | Yes | +| amqp.delivery_mode | No | +| amqp.exchange | No | +| amqp.queue | No | +| amqp.routing_key | No | +| component | `RabbitMQ` | +| message.size | No | +| out.host | Yes | +| peer.service | Yes | +| peer.service.remapped_from | No | +| span.kind | `producer` | ## RemotingClient + ### Span properties -Name | Required | ----------|----------------| -Name | `dotnet_remoting.client.request` + +| Name | Required | +| ---- | -------------------------------- | +| Name | `dotnet_remoting.client.request` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -_dd.peer.service.source | Optional: `peer.service`; `rpc.service` -component | `Remoting` -peer.service | No -peer.service.remapped_from | No -rpc.method | Yes -rpc.system | `dotnet_remoting` -span.kind | `client`; `server` + +| Name | Required | +| -------------------------- | --------------------------------------- | +| \_dd.base_service | No | +| \_dd.peer.service.source | Optional: `peer.service`; `rpc.service` | +| component | `Remoting` | +| peer.service | No | +| peer.service.remapped_from | No | +| rpc.method | Yes | +| rpc.system | `dotnet_remoting` | +| span.kind | `client`; `server` | ## RemotingServer + ### Span properties -Name | Required | ----------|----------------| -Name | `dotnet_remoting.server.request` + +| Name | Required | +| ---- | -------------------------------- | +| Name | `dotnet_remoting.server.request` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -component | `Remoting` -rpc.method | Yes -rpc.system | `dotnet_remoting` -span.kind | `client`; `server` + +| Name | Required | +| ----------------- | ------------------ | +| \_dd.base_service | No | +| component | `Remoting` | +| rpc.method | Yes | +| rpc.system | `dotnet_remoting` | +| span.kind | `client`; `server` | ## Service Remoting - Client + ### Span properties -Name | Required | ----------|----------------| -Name | `service_remoting.client` + +| Name | Required | +| ---- | ------------------------- | +| Name | `service_remoting.client` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -_dd.peer.service.source | `service-fabric.service-remoting.service`; `service-fabric.service-remoting.uri`; `peer.service` -peer.service | Yes -peer.service.remapped_from | No -service-fabric.application-id | No -service-fabric.application-name | No -service-fabric.node-id | No -service-fabric.node-name | No -service-fabric.partition-id | No -service-fabric.service-name | No -service-fabric.service-remoting.interface-id | No -service-fabric.service-remoting.invocation-id | No -service-fabric.service-remoting.method-id | No -service-fabric.service-remoting.method-name | Yes -service-fabric.service-remoting.service | No -service-fabric.service-remoting.uri | Yes -span.kind | `client` + +| Name | Required | +| --------------------------------------------- | ------------------------------------------------------------------------------------------------ | +| \_dd.base_service | No | +| \_dd.peer.service.source | `service-fabric.service-remoting.service`; `service-fabric.service-remoting.uri`; `peer.service` | +| peer.service | Yes | +| peer.service.remapped_from | No | +| service-fabric.application-id | No | +| service-fabric.application-name | No | +| service-fabric.node-id | No | +| service-fabric.node-name | No | +| service-fabric.partition-id | No | +| service-fabric.service-name | No | +| service-fabric.service-remoting.interface-id | No | +| service-fabric.service-remoting.invocation-id | No | +| service-fabric.service-remoting.method-id | No | +| service-fabric.service-remoting.method-name | Yes | +| service-fabric.service-remoting.service | No | +| service-fabric.service-remoting.uri | Yes | +| span.kind | `client` | ## Service Remoting - Server + ### Span properties -Name | Required | ----------|----------------| -Name | `service_remoting.server` + +| Name | Required | +| ---- | ------------------------- | +| Name | `service_remoting.server` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -service-fabric.application-id | No -service-fabric.application-name | No -service-fabric.node-id | No -service-fabric.node-name | No -service-fabric.partition-id | No -service-fabric.service-name | No -service-fabric.service-remoting.interface-id | No -service-fabric.service-remoting.invocation-id | No -service-fabric.service-remoting.method-id | No -service-fabric.service-remoting.method-name | Yes -service-fabric.service-remoting.service | No -service-fabric.service-remoting.uri | Yes -span.kind | `server` + +| Name | Required | +| --------------------------------------------- | -------- | +| \_dd.base_service | No | +| service-fabric.application-id | No | +| service-fabric.application-name | No | +| service-fabric.node-id | No | +| service-fabric.node-name | No | +| service-fabric.partition-id | No | +| service-fabric.service-name | No | +| service-fabric.service-remoting.interface-id | No | +| service-fabric.service-remoting.invocation-id | No | +| service-fabric.service-remoting.method-id | No | +| service-fabric.service-remoting.method-name | Yes | +| service-fabric.service-remoting.service | No | +| service-fabric.service-remoting.uri | Yes | +| span.kind | `server` | ## ServiceStackRedis + ### Span properties -Name | Required | ----------|----------------| -Name | `redis.command` -Type | `redis` + +| Name | Required | +| ---- | --------------- | +| Name | `redis.command` | +| Type | `redis` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -_dd.peer.service.source | `out.host`; `peer.service` -component | `ServiceStackRedis` -out.host | Yes -out.port | Yes -peer.service | Yes -peer.service.remapped_from | No -redis.raw_command | Yes -span.kind | `client` + +| Name | Required | +| -------------------------- | -------------------------- | +| \_dd.base_service | No | +| \_dd.peer.service.source | `out.host`; `peer.service` | +| component | `ServiceStackRedis` | +| out.host | Yes | +| out.port | Yes | +| peer.service | Yes | +| peer.service.remapped_from | No | +| redis.raw_command | Yes | +| span.kind | `client` | + ### Metrics -Name | Required | ----------|----------------| -db.redis.database_index | Yes + +| Name | Required | +| ----------------------- | -------- | +| db.redis.database_index | Yes | ## StackExchangeRedis + ### Span properties -Name | Required | ----------|----------------| -Name | `redis.command` -Type | `redis` + +| Name | Required | +| ---- | --------------- | +| Name | `redis.command` | +| Type | `redis` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -_dd.peer.service.source | `out.host`; `peer.service` -component | `StackExchangeRedis` -out.host | Yes -out.port | Yes -peer.service | Yes -peer.service.remapped_from | No -redis.raw_command | Yes -span.kind | `client` + +| Name | Required | +| -------------------------- | -------------------------- | +| \_dd.base_service | No | +| \_dd.peer.service.source | `out.host`; `peer.service` | +| component | `StackExchangeRedis` | +| out.host | Yes | +| out.port | Yes | +| peer.service | Yes | +| peer.service.remapped_from | No | +| redis.raw_command | Yes | +| span.kind | `client` | + ### Metrics -Name | Required | ----------|----------------| -db.redis.database_index | No + +| Name | Required | +| ----------------------- | -------- | +| db.redis.database_index | No | ## Sqlite + ### Span properties -Name | Required | ----------|----------------| -Name | `sqlite.query` -Type | `sql` + +| Name | Required | +| ---- | -------------- | +| Name | `sqlite.query` | +| Type | `sql` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -_dd.peer.service.source | `db.name`; `out.host`; `peer.service` -component | `Sqlite` -db.name | No -db.type | `sqlite` -out.host | Yes -peer.service | Yes -peer.service.remapped_from | No -span.kind | `client` + +| Name | Required | +| -------------------------- | ------------------------------------- | +| \_dd.base_service | No | +| \_dd.peer.service.source | `db.name`; `out.host`; `peer.service` | +| component | `Sqlite` | +| db.name | No | +| db.type | `sqlite` | +| out.host | Yes | +| peer.service | Yes | +| peer.service.remapped_from | No | +| span.kind | `client` | ## SqlClient + ### Span properties -Name | Required | ----------|----------------| -Name | `sql-server.query` -Type | `sql` + +| Name | Required | +| ---- | ------------------ | +| Name | `sql-server.query` | +| Type | `sql` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -_dd.dbm_trace_injected | No -_dd.peer.service.source | `db.name`; `out.host`; `peer.service` -component | `SqlClient` -db.name | No -db.type | `sql-server` -dd.instrumentation.time_ms | No -out.host | Yes -peer.service | Yes -peer.service.remapped_from | No -span.kind | `client` + +| Name | Required | +| -------------------------- | ------------------------------------- | +| \_dd.base_service | No | +| \_dd.dbm_trace_injected | No | +| \_dd.peer.service.source | `db.name`; `out.host`; `peer.service` | +| component | `SqlClient` | +| db.name | No | +| db.type | `sql-server` | +| dd.instrumentation.time_ms | No | +| out.host | Yes | +| peer.service | Yes | +| peer.service.remapped_from | No | +| span.kind | `client` | ## Wcf + ### Span properties -Name | Required | ----------|----------------| -Name | `http.server.request` -Type | `web` + +| Name | Required | +| ---- | --------------------- | +| Name | `http.server.request` | +| Type | `web` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -component | `Wcf` -http.method | No -http.request.headers.host | No -http.url | Yes -span.kind | `server` + +| Name | Required | +| ------------------------- | -------- | +| \_dd.base_service | No | +| component | `Wcf` | +| http.method | No | +| http.request.headers.host | No | +| http.url | Yes | +| span.kind | `server` | ## WebRequest + ### Span properties -Name | Required | ----------|----------------| -Name | `http.client.request` -Type | `http` + +| Name | Required | +| ---- | --------------------- | +| Name | `http.client.request` | +| Type | `http` | + ### Tags -Name | Required | ----------|----------------| -_dd.base_service | No -_dd.peer.service.source | `out.host`; `peer.service` -component | `HttpMessageHandler`; `WebRequest` -http-client-handler-type | No -http.method | Yes -http.status_code | Yes -http.url | Yes -out.host | Yes -peer.service | Yes -peer.service.remapped_from | No -span.kind | `client` +| Name | Required | +| -------------------------- | ---------------------------------- | +| \_dd.base_service | No | +| \_dd.peer.service.source | `out.host`; `peer.service` | +| component | `HttpMessageHandler`; `WebRequest` | +| http-client-handler-type | No | +| http.method | Yes | +| http.status_code | Yes | +| http.url | Yes | +| out.host | Yes | +| peer.service | Yes | +| peer.service.remapped_from | No | +| span.kind | `client` | diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Kafka/ConsumerCache.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Kafka/ConsumerCache.cs index 7effc6c20a42..5e249309cda4 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Kafka/ConsumerCache.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Kafka/ConsumerCache.cs @@ -15,31 +15,38 @@ internal static class ConsumerCache // A map between Kafka Consumer and the corresponding consumer group private static readonly ConditionalWeakTable ConsumerToGroupIdMap = new(); private static readonly ConditionalWeakTable ConsumerToBootstrapServersMap = new(); + private static readonly ConditionalWeakTable ConsumerToClusterIdMap = new(); private static readonly ConditionalWeakTable ConsumerToOffsetsCommittedHandlerMap = new(); - public static void SetConsumerGroup(object consumer, string groupId, string bootstrapServers) + public static void SetConsumerGroup(object consumer, string groupId, string bootstrapServers, string clusterId) { #if NETCOREAPP3_1_OR_GREATER ConsumerToGroupIdMap.AddOrUpdate(consumer, groupId); ConsumerToBootstrapServersMap.AddOrUpdate(consumer, bootstrapServers); + ConsumerToClusterIdMap.AddOrUpdate(consumer, clusterId); #else ConsumerToGroupIdMap.GetValue(consumer, _ => groupId); ConsumerToBootstrapServersMap.GetValue(consumer, _ => bootstrapServers); + ConsumerToClusterIdMap.GetValue(consumer, _ => clusterId); #endif } - public static bool TryGetConsumerGroup(object consumer, out string? groupId, out string? bootstrapServers) + public static bool TryGetConsumerGroup(object consumer, out string? groupId, out string? bootstrapServers, out string? clusterId) { groupId = null; bootstrapServers = null; + clusterId = null; - return ConsumerToGroupIdMap.TryGetValue(consumer, out groupId) && ConsumerToBootstrapServersMap.TryGetValue(consumer, out bootstrapServers); + return ConsumerToGroupIdMap.TryGetValue(consumer, out groupId) + && ConsumerToBootstrapServersMap.TryGetValue(consumer, out bootstrapServers) + && ConsumerToClusterIdMap.TryGetValue(consumer, out clusterId); } public static void RemoveConsumerGroup(object consumer) { ConsumerToGroupIdMap.Remove(consumer); ConsumerToBootstrapServersMap.Remove(consumer); + ConsumerToClusterIdMap.Remove(consumer); ConsumerToOffsetsCommittedHandlerMap.Remove(consumer); } } diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Kafka/IAdminClient.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Kafka/IAdminClient.cs new file mode 100644 index 000000000000..b9b938366a01 --- /dev/null +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Kafka/IAdminClient.cs @@ -0,0 +1,24 @@ +// +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. +// + +#nullable enable + +using System; +using Datadog.Trace.DuckTyping; + +namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.Kafka; + +/// +/// Duck Type for Confluent.Kafka.IAdminClient +/// +internal interface IAdminClient : IDuckType, IDisposable +{ + /// + /// Describes the cluster metadata including the cluster ID + /// + /// Optional configuration options + /// Duck typed task containing the cluster description result + IDuckTypeTask DescribeClusterAsync(IDescribeClusterOptions? options = null); +} diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Kafka/IAdminClientBuilder.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Kafka/IAdminClientBuilder.cs new file mode 100644 index 000000000000..f0e5b277d652 --- /dev/null +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Kafka/IAdminClientBuilder.cs @@ -0,0 +1,17 @@ +// +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. +// + +#nullable enable + +namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.Kafka; + +/// +/// Duck Type for Confluent.Kafka.AdminClientBuilder +/// Used to build an AdminClient for cluster_id extraction +/// +internal interface IAdminClientBuilder +{ + IAdminClient Build(); +} diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Kafka/IAdminClientConfig.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Kafka/IAdminClientConfig.cs new file mode 100644 index 000000000000..1118d93d89f6 --- /dev/null +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Kafka/IAdminClientConfig.cs @@ -0,0 +1,17 @@ +// +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. +// + +#nullable enable + +namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.Kafka; + +/// +/// Duck Type for Confluent.Kafka.AdminClientConfig +/// Used to create an AdminClient for cluster_id extraction +/// +internal interface IAdminClientConfig +{ + string BootstrapServers { get; set; } +} diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Kafka/IAdminClientExtensions.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Kafka/IAdminClientExtensions.cs new file mode 100644 index 000000000000..88add88a8e26 --- /dev/null +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Kafka/IAdminClientExtensions.cs @@ -0,0 +1,21 @@ +// +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. +// + +#nullable enable + +using System; +using System.Threading.Tasks; +using Datadog.Trace.DuckTyping; + +namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.Kafka; + +/// +/// Duck Type for Confluent.Kafka.IAdminClientExtensions +/// We only need this to get the underlying instance for reflection calls to extension methods +/// +internal interface IAdminClientExtensions : IDuckType +{ + Task DescribeClusterAsync(IAdminClient adminClient, IDescribeClusterOptions? options = null); +} diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Kafka/IDescribeClusterOptions.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Kafka/IDescribeClusterOptions.cs new file mode 100644 index 000000000000..41349c17fbdf --- /dev/null +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Kafka/IDescribeClusterOptions.cs @@ -0,0 +1,16 @@ +// +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. +// + +#nullable enable + +namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.Kafka; + +/// +/// Duck Type for Confluent.Kafka.Admin.DescribeClusterOptions +/// Used as an optional parameter for DescribeClusterAsync extension method +/// +internal interface IDescribeClusterOptions +{ +} diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Kafka/IDescribeClusterResult.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Kafka/IDescribeClusterResult.cs new file mode 100644 index 000000000000..a022849bb392 --- /dev/null +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Kafka/IDescribeClusterResult.cs @@ -0,0 +1,17 @@ +// +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. +// + +#nullable enable + +namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.Kafka; + +/// +/// Duck Type for Confluent.Kafka.Admin.DescribeClusterResult +/// Used to access ClusterId from cluster description +/// +internal interface IDescribeClusterResult +{ + string ClusterId { get; } +} diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Kafka/KafkaConsumerCommitAllIntegration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Kafka/KafkaConsumerCommitAllIntegration.cs index a28bee453c17..aa6a7b5d04ce 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Kafka/KafkaConsumerCommitAllIntegration.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Kafka/KafkaConsumerCommitAllIntegration.cs @@ -32,7 +32,7 @@ internal static CallTargetReturn OnMethodEnd(TTar var dataStreams = Tracer.Instance.TracerManager.DataStreamsManager; if (exception is null && response.Instance is not null && dataStreams.IsEnabled && instance != null) { - ConsumerCache.TryGetConsumerGroup(instance, out var groupId, out var _); + ConsumerCache.TryGetConsumerGroup(instance, out var groupId, out var _, out var _); for (var i = 0; i < response.Count; i++) { diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Kafka/KafkaConsumerCommitIntegration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Kafka/KafkaConsumerCommitIntegration.cs index 5d2f4d489787..0afb157f61e3 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Kafka/KafkaConsumerCommitIntegration.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Kafka/KafkaConsumerCommitIntegration.cs @@ -37,7 +37,7 @@ internal static CallTargetReturn OnMethodEnd(TTarget instance, Exceptio var dataStreams = Tracer.Instance.TracerManager.DataStreamsManager; if (exception is null && state.State is IEnumerable offsets && dataStreams.IsEnabled && instance != null) { - ConsumerCache.TryGetConsumerGroup(instance, out var groupId, out var _); + ConsumerCache.TryGetConsumerGroup(instance, out var groupId, out var _, out var _); foreach (var offset in offsets) { diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Kafka/KafkaConsumerConstructorIntegration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Kafka/KafkaConsumerConstructorIntegration.cs index 691b9f445382..98a6628e2093 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Kafka/KafkaConsumerConstructorIntegration.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Kafka/KafkaConsumerConstructorIntegration.cs @@ -7,7 +7,9 @@ using System.ComponentModel; using Datadog.Trace.ClrProfiler.CallTarget; using Datadog.Trace.DuckTyping; +using Datadog.Trace.Logging; using Datadog.Trace.Util.Delegates; +using Console = System.Console; namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.Kafka; @@ -27,6 +29,8 @@ namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.Kafka; [EditorBrowsable(EditorBrowsableState.Never)] public class KafkaConsumerConstructorIntegration { + private static readonly IDatadogLogger Log = DatadogLogging.GetLoggerFor(typeof(KafkaConsumerConstructorIntegration)); + internal static CallTargetState OnMethodBegin(TTarget instance, TConsumerBuilder consumer) where TConsumerBuilder : IConsumerBuilder { @@ -63,8 +67,22 @@ internal static CallTargetState OnMethodBegin(TTarget // Only config setting "group.id" is required, so assert that the value is non-null before adding to the ConsumerGroup cache if (groupId is not null) { - // Save the map between this consumer and a consumer group - ConsumerCache.SetConsumerGroup(instance, groupId, bootstrapServers); + // Extract cluster_id using AdminClient API with bootstrap servers + var clusterId = KafkaHelper.GetClusterId(bootstrapServers) ?? string.Empty; + + if (!string.IsNullOrEmpty(clusterId)) + { + Log.Information("ROBC: Kafka consumer config retrieved - GroupId: {GroupId}, BootstrapServers: {BootstrapServers}, ClusterId: {ClusterId}", groupId, bootstrapServers, clusterId); + Console.WriteLine($"ROBC: Kafka consumer config retrieved - GroupId: {groupId}, BootstrapServers: {bootstrapServers}, ClusterId: {clusterId}"); + } + else + { + Log.Information("ROBC: Kafka consumer config retrieved but no cluster_id could be obtained - GroupId: {GroupId}, BootstrapServers: {BootstrapServers}", groupId, bootstrapServers); + Console.WriteLine($"ROBC: Kafka consumer config retrieved but no cluster_id could be obtained - GroupId: {groupId}, BootstrapServers: {bootstrapServers}"); + } + + // Save the map between this consumer and its metadata + ConsumerCache.SetConsumerGroup(instance, groupId, bootstrapServers, clusterId); return new CallTargetState(scope: null, state: instance); } } diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Kafka/KafkaHelper.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Kafka/KafkaHelper.cs index f8300ca20656..3f647942797c 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Kafka/KafkaHelper.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Kafka/KafkaHelper.cs @@ -6,6 +6,7 @@ #nullable enable using System; +using System.Reflection; using System.Text; using Datadog.Trace.DataStreamsMonitoring; using Datadog.Trace.DataStreamsMonitoring.Utils; @@ -13,6 +14,7 @@ using Datadog.Trace.Logging; using Datadog.Trace.Propagators; using Datadog.Trace.Tagging; +using Console = System.Console; namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.Kafka { @@ -26,6 +28,10 @@ internal static class KafkaHelper private static readonly string[] DefaultProduceEdgeTags = ["direction:out", "type:kafka"]; private static bool _headersInjectionEnabled = true; + // Thread-local flag to prevent infinite recursion when AdminClient creates internal Producer + [ThreadStatic] + private static bool _isGettingClusterId; + internal static Scope? CreateProducerScope( Tracer tracer, object producer, @@ -72,9 +78,20 @@ internal static class KafkaHelper tags.Partition = (topicPartition?.Partition).ToString(); } - if (ProducerCache.TryGetProducer(producer, out var bootstrapServers)) + if (ProducerCache.TryGetProducer(producer, out var bootstrapServers, out var clusterId)) { tags.BootstrapServers = bootstrapServers; + if (!string.IsNullOrEmpty(clusterId)) + { + tags.ClusterId = clusterId; + Log.Information("ROBC: Added cluster_id tag to Kafka producer span: {ClusterId}", clusterId); + Console.WriteLine($"ROBC: Added cluster_id tag to Kafka producer span: {clusterId}"); + } + else + { + Log.Information("ROBC: No cluster_id available for Kafka producer span"); + Console.WriteLine("ROBC: No cluster_id available for Kafka producer span"); + } } if (isTombstone) @@ -212,10 +229,21 @@ private static long GetMessageSize(T message) tags.Offset = offset.ToString(); } - if (ConsumerCache.TryGetConsumerGroup(consumer, out var groupId, out var bootstrapServers)) + if (ConsumerCache.TryGetConsumerGroup(consumer, out var groupId, out var bootstrapServers, out var clusterId)) { tags.ConsumerGroup = groupId; tags.BootstrapServers = bootstrapServers; + if (!string.IsNullOrEmpty(clusterId)) + { + tags.ClusterId = clusterId; + Log.Information("ROBC: Added cluster_id tag to Kafka consumer span: {ClusterId}", clusterId); + Console.WriteLine($"ROBC: Added cluster_id tag to Kafka consumer span: {clusterId}"); + } + else + { + Log.Information("ROBC: No cluster_id available for Kafka consumer span"); + Console.WriteLine("ROBC: No cluster_id available for Kafka consumer span"); + } } if (message?.Instance is not null && message.Timestamp.Type != 0) @@ -364,6 +392,132 @@ internal static void TryInjectHeaders( } } + internal static string? GetClusterId(string bootstrapServers) + { + string clusterId = string.Empty; + + // Prevent re-entrancy: AdminClient internally creates a Producer, which would trigger our instrumentation again + if (_isGettingClusterId) + { + Log.Information("ROBC: Skipping cluster_id retrieval to prevent re-entrancy (AdminClient internal Producer creation)"); + Console.WriteLine("ROBC: Skipping cluster_id retrieval to prevent re-entrancy (AdminClient internal Producer creation)"); + return null; + } + + if (string.IsNullOrEmpty(bootstrapServers)) + { + Log.Information("ROBC: Cannot retrieve cluster_id - bootstrap servers is null or empty"); + Console.WriteLine("ROBC: Cannot retrieve cluster_id - bootstrap servers is null or empty"); + return null; + } + + try + { + _isGettingClusterId = true; + Log.Information("ROBC: Attempting to retrieve cluster_id from Kafka using bootstrap servers: {BootstrapServers}", bootstrapServers); + Console.WriteLine($"ROBC: Attempting to retrieve cluster_id from Kafka using bootstrap servers: {bootstrapServers}"); + + // Create AdminClientConfig + var configType = Type.GetType("Confluent.Kafka.AdminClientConfig, Confluent.Kafka"); + if (configType == null) + { + Log.Information("ROBC: Unable to find Confluent.Kafka.AdminClientConfig type"); + Console.WriteLine("ROBC: Unable to find Confluent.Kafka.AdminClientConfig type"); + return null; + } + + // TODO(FIX!) Type names for Confluent.Kafka are fixed/hardcoded + var config = Activator.CreateInstance(configType); + + if (config == null || !config.TryDuckCast(out var adminConfig)) + { + Log.Information("ROBC: Unable to create or duck-cast AdminClientConfig"); + Console.WriteLine("ROBC: Unable to create or duck-cast AdminClientConfig"); + return null; + } + + adminConfig.BootstrapServers = bootstrapServers; + + // Create AdminClientBuilder + var builderType = Type.GetType("Confluent.Kafka.AdminClientBuilder, Confluent.Kafka"); + if (builderType == null) + { + Log.Information("ROBC: Unable to find Confluent.Kafka.AdminClientBuilder type"); + Console.WriteLine("ROBC: Unable to find Confluent.Kafka.AdminClientBuilder type"); + return null; + } + + // TODO(FIX!) Type names for Confluent.Kafka are fixed/hardcoded + var builder = Activator.CreateInstance(builderType, new object[] { config }) ?? throw new InvalidOperationException("Unable to create AdminClientBuilder"); + if (builder == null || !builder.TryDuckCast(out var adminBuilder)) + { + Log.Information("ROBC: Unable to create or duck-cast AdminClientBuilder"); + Console.WriteLine("ROBC: Unable to create or duck-cast AdminClientBuilder"); + return null; + } + + // Build and use AdminClient + using (var adminClient = adminBuilder.Build()) + { + Console.WriteLine("ROBC: Calling DescribeClusterAsync via duck typing"); + var clusterOptionsType = Type.GetType("Confluent.Kafka.Admin.DescribeClusterOptions, Confluent.Kafka"); + if (clusterOptionsType == null) + { + Log.Information("ROBC: Unable to find DescribeClusterOptions type"); + Console.WriteLine("ROBC: Unable to find DescribeClusterOptions type"); + return null; + } + + var clusterOptionsObj = Activator.CreateInstance(clusterOptionsType); + if (clusterOptionsObj == null || !clusterOptionsObj.TryDuckCast(out var clusterOptions)) + { + Log.Information("ROBC: Unable to create or duck-cast DescribeClusterOptions"); + Console.WriteLine("ROBC: Unable to create or duck-cast DescribeClusterOptions"); + return null; + } + + // Call DescribeClusterAsync directly on the duck-typed AdminClient + var result = adminClient.DescribeClusterAsync(clusterOptions); + var describeClusterResult = result.GetAwaiter().GetResult(); + + Console.WriteLine($"ROBC: DescribeClusterAsync completed successfully"); + Console.WriteLine($"ROBC: Result type: {result.GetType().FullName}"); + + // Extract the ClusterId from the result + clusterId = describeClusterResult.ClusterId; + Console.WriteLine($"ROBC: ClusterId extracted (raw): {clusterId}"); + + // Check if the clusterId is wrapped in "Some(...)" pattern and unwrap it + if (!string.IsNullOrEmpty(clusterId) && clusterId.StartsWith("Some(") && clusterId.EndsWith(")")) + { + clusterId = clusterId.Substring(5, clusterId.Length - 6); + Console.WriteLine($"ROBC: Unwrapped ClusterId from Some(...) pattern: {clusterId}"); + } + + if (!string.IsNullOrEmpty(clusterId)) + { + Log.Information("ROBC: Kafka cluster_id extracted successfully: {ClusterId}", clusterId); + Console.WriteLine($"ROBC: Kafka cluster_id extracted successfully: {clusterId}"); + } + else + { + Console.WriteLine("ROBC: ClusterId is null or empty"); + } + } + } + catch (Exception ex) + { + Log.Warning(ex, "ROBC: Error extracting cluster_id from Kafka metadata"); + Console.WriteLine($"ROBC: Error extracting cluster_id from Kafka metadata: {ex}"); + } + finally + { + _isGettingClusterId = false; + } + + return clusterId; + } + internal static void DisableHeadersIfUnsupportedBroker(Exception exception) { if (_headersInjectionEnabled && exception is not null && exception.Message.IndexOf("Unknown broker error", StringComparison.OrdinalIgnoreCase) != -1) diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Kafka/KafkaProducerConstructorIntegration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Kafka/KafkaProducerConstructorIntegration.cs index 3d3c737e3cd2..c6912e1a9b21 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Kafka/KafkaProducerConstructorIntegration.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Kafka/KafkaProducerConstructorIntegration.cs @@ -6,6 +6,8 @@ using System; using System.ComponentModel; using Datadog.Trace.ClrProfiler.CallTarget; +using Datadog.Trace.Logging; +using Console = System.Console; namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.Kafka; @@ -25,6 +27,8 @@ namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.Kafka; [EditorBrowsable(EditorBrowsableState.Never)] public class KafkaProducerConstructorIntegration { + private static readonly IDatadogLogger Log = DatadogLogging.GetLoggerFor(typeof(KafkaProducerConstructorIntegration)); + internal static CallTargetState OnMethodBegin(TTarget instance, TProducerBuilder consumer) where TProducerBuilder : IProducerBuilder { @@ -58,8 +62,22 @@ internal static CallTargetState OnMethodBegin(TTarget if (!string.IsNullOrEmpty(bootstrapServers)) { - // Save the map between this producer and its bootstrap server config - ProducerCache.AddBootstrapServers(instance, bootstrapServers); + // Extract cluster_id using AdminClient API with bootstrap servers + var clusterId = KafkaHelper.GetClusterId(bootstrapServers) ?? string.Empty; + + if (!string.IsNullOrEmpty(clusterId)) + { + Log.Information("ROBC: Kafka producer config retrieved - BootstrapServers: {BootstrapServers}, ClusterId: {ClusterId}", bootstrapServers, clusterId); + Console.WriteLine($"ROBC: Kafka producer config retrieved - BootstrapServers: {bootstrapServers}, ClusterId: {clusterId}"); + } + else + { + Log.Information("ROBC: Kafka producer config retrieved but no cluster_id could be obtained - BootstrapServers: {BootstrapServers}", bootstrapServers); + Console.WriteLine($"ROBC: Kafka producer config retrieved but no cluster_id could be obtained - BootstrapServers: {bootstrapServers}"); + } + + // Save the map between this producer and its metadata + ProducerCache.AddBootstrapServers(instance, bootstrapServers, clusterId); return new CallTargetState(scope: null, state: instance); } } diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Kafka/ProducerCache.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Kafka/ProducerCache.cs index c7e6f6833d70..122d46da6e25 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Kafka/ProducerCache.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Kafka/ProducerCache.cs @@ -16,14 +16,17 @@ internal static class ProducerCache { // A map between Kafka Producer and the corresponding producer bootstrap servers private static readonly ConditionalWeakTable ProducerToBootstrapServersMap = new(); + private static readonly ConditionalWeakTable ProducerToClusterIdMap = new(); private static readonly ConditionalWeakTable ProducerToDefaultDeliveryHandlerMap = new(); - public static void AddBootstrapServers(object producer, string bootstrapServers) + public static void AddBootstrapServers(object producer, string bootstrapServers, string clusterId) { #if NETCOREAPP3_1_OR_GREATER ProducerToBootstrapServersMap.AddOrUpdate(producer, bootstrapServers); + ProducerToClusterIdMap.AddOrUpdate(producer, clusterId); #else ProducerToBootstrapServersMap.GetValue(producer, x => bootstrapServers); + ProducerToClusterIdMap.GetValue(producer, x => clusterId); #endif } @@ -55,8 +58,14 @@ public static void AddDefaultDeliveryHandler(object producer) return null; } - public static bool TryGetProducer(object producer, out string? bootstrapServers) - => ProducerToBootstrapServersMap.TryGetValue(producer, out bootstrapServers); + public static bool TryGetProducer(object producer, out string? bootstrapServers, out string? clusterId) + { + bootstrapServers = null; + clusterId = null; + + return ProducerToBootstrapServersMap.TryGetValue(producer, out bootstrapServers) + && ProducerToClusterIdMap.TryGetValue(producer, out clusterId); + } public static bool TryGetDefaultDeliveryHandler(object producer, out Delegate? handler) { @@ -66,6 +75,7 @@ public static bool TryGetDefaultDeliveryHandler(object producer, out Delegate? h public static void RemoveProducer(object producer) { ProducerToBootstrapServersMap.Remove(producer); + ProducerToClusterIdMap.Remove(producer); ProducerToDefaultDeliveryHandlerMap.Remove(producer); } } diff --git a/tracer/src/Datadog.Trace/DataStreamsMonitoring/DataStreamsManager.cs b/tracer/src/Datadog.Trace/DataStreamsMonitoring/DataStreamsManager.cs index 7636d59d82bf..ec305e47eb8f 100644 --- a/tracer/src/Datadog.Trace/DataStreamsMonitoring/DataStreamsManager.cs +++ b/tracer/src/Datadog.Trace/DataStreamsMonitoring/DataStreamsManager.cs @@ -59,6 +59,9 @@ public static DataStreamsManager Create( ? DataStreamsWriter.Create(settings, profilerSettings, discoveryService, defaultServiceName) : null; + Log.Information("ROBC Cluster ID Branch DataStreamsManager Create"); + Console.WriteLine("ROBC Cluster ID Branch DataStreamsManager Create"); + return new DataStreamsManager(settings.Environment, defaultServiceName, writer, settings.IsDataStreamsMonitoringInDefaultState); } diff --git a/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/TagListGenerator/KafkaTags.g.cs b/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/TagListGenerator/KafkaTags.g.cs index 10ba2d7c56db..d6d897c7a5ce 100644 --- a/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/TagListGenerator/KafkaTags.g.cs +++ b/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/TagListGenerator/KafkaTags.g.cs @@ -22,6 +22,8 @@ partial class KafkaTags private static ReadOnlySpan InstrumentationNameBytes => new byte[] { 169, 99, 111, 109, 112, 111, 110, 101, 110, 116 }; // BootstrapServersBytes = MessagePack.Serialize("messaging.kafka.bootstrap.servers"); private static ReadOnlySpan BootstrapServersBytes => new byte[] { 217, 33, 109, 101, 115, 115, 97, 103, 105, 110, 103, 46, 107, 97, 102, 107, 97, 46, 98, 111, 111, 116, 115, 116, 114, 97, 112, 46, 115, 101, 114, 118, 101, 114, 115 }; + // ClusterIdBytes = MessagePack.Serialize("messaging.kafka.cluster_id"); + private static ReadOnlySpan ClusterIdBytes => new byte[] { 186, 109, 101, 115, 115, 97, 103, 105, 110, 103, 46, 107, 97, 102, 107, 97, 46, 99, 108, 117, 115, 116, 101, 114, 95, 105, 100 }; // TopicBytes = MessagePack.Serialize("messaging.destination.name"); private static ReadOnlySpan TopicBytes => new byte[] { 186, 109, 101, 115, 115, 97, 103, 105, 110, 103, 46, 100, 101, 115, 116, 105, 110, 97, 116, 105, 111, 110, 46, 110, 97, 109, 101 }; // PartitionBytes = MessagePack.Serialize("kafka.partition"); @@ -40,6 +42,7 @@ partial class KafkaTags "span.kind" => SpanKind, "component" => InstrumentationName, "messaging.kafka.bootstrap.servers" => BootstrapServers, + "messaging.kafka.cluster_id" => ClusterId, "messaging.destination.name" => Topic, "kafka.partition" => Partition, "kafka.offset" => Offset, @@ -56,6 +59,9 @@ public override void SetTag(string key, string value) case "messaging.kafka.bootstrap.servers": BootstrapServers = value; break; + case "messaging.kafka.cluster_id": + ClusterId = value; + break; case "messaging.destination.name": Topic = value; break; @@ -98,6 +104,11 @@ public override void EnumerateTags(ref TProcessor processor) processor.Process(new TagItem("messaging.kafka.bootstrap.servers", BootstrapServers, BootstrapServersBytes)); } + if (ClusterId is not null) + { + processor.Process(new TagItem("messaging.kafka.cluster_id", ClusterId, ClusterIdBytes)); + } + if (Topic is not null) { processor.Process(new TagItem("messaging.destination.name", Topic, TopicBytes)); @@ -149,6 +160,13 @@ protected override void WriteAdditionalTags(System.Text.StringBuilder sb) .Append(','); } + if (ClusterId is not null) + { + sb.Append("messaging.kafka.cluster_id (tag):") + .Append(ClusterId) + .Append(','); + } + if (Topic is not null) { sb.Append("messaging.destination.name (tag):") diff --git a/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/TagListGenerator/KafkaTags.g.cs b/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/TagListGenerator/KafkaTags.g.cs index 10ba2d7c56db..d6d897c7a5ce 100644 --- a/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/TagListGenerator/KafkaTags.g.cs +++ b/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/TagListGenerator/KafkaTags.g.cs @@ -22,6 +22,8 @@ partial class KafkaTags private static ReadOnlySpan InstrumentationNameBytes => new byte[] { 169, 99, 111, 109, 112, 111, 110, 101, 110, 116 }; // BootstrapServersBytes = MessagePack.Serialize("messaging.kafka.bootstrap.servers"); private static ReadOnlySpan BootstrapServersBytes => new byte[] { 217, 33, 109, 101, 115, 115, 97, 103, 105, 110, 103, 46, 107, 97, 102, 107, 97, 46, 98, 111, 111, 116, 115, 116, 114, 97, 112, 46, 115, 101, 114, 118, 101, 114, 115 }; + // ClusterIdBytes = MessagePack.Serialize("messaging.kafka.cluster_id"); + private static ReadOnlySpan ClusterIdBytes => new byte[] { 186, 109, 101, 115, 115, 97, 103, 105, 110, 103, 46, 107, 97, 102, 107, 97, 46, 99, 108, 117, 115, 116, 101, 114, 95, 105, 100 }; // TopicBytes = MessagePack.Serialize("messaging.destination.name"); private static ReadOnlySpan TopicBytes => new byte[] { 186, 109, 101, 115, 115, 97, 103, 105, 110, 103, 46, 100, 101, 115, 116, 105, 110, 97, 116, 105, 111, 110, 46, 110, 97, 109, 101 }; // PartitionBytes = MessagePack.Serialize("kafka.partition"); @@ -40,6 +42,7 @@ partial class KafkaTags "span.kind" => SpanKind, "component" => InstrumentationName, "messaging.kafka.bootstrap.servers" => BootstrapServers, + "messaging.kafka.cluster_id" => ClusterId, "messaging.destination.name" => Topic, "kafka.partition" => Partition, "kafka.offset" => Offset, @@ -56,6 +59,9 @@ public override void SetTag(string key, string value) case "messaging.kafka.bootstrap.servers": BootstrapServers = value; break; + case "messaging.kafka.cluster_id": + ClusterId = value; + break; case "messaging.destination.name": Topic = value; break; @@ -98,6 +104,11 @@ public override void EnumerateTags(ref TProcessor processor) processor.Process(new TagItem("messaging.kafka.bootstrap.servers", BootstrapServers, BootstrapServersBytes)); } + if (ClusterId is not null) + { + processor.Process(new TagItem("messaging.kafka.cluster_id", ClusterId, ClusterIdBytes)); + } + if (Topic is not null) { processor.Process(new TagItem("messaging.destination.name", Topic, TopicBytes)); @@ -149,6 +160,13 @@ protected override void WriteAdditionalTags(System.Text.StringBuilder sb) .Append(','); } + if (ClusterId is not null) + { + sb.Append("messaging.kafka.cluster_id (tag):") + .Append(ClusterId) + .Append(','); + } + if (Topic is not null) { sb.Append("messaging.destination.name (tag):") diff --git a/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/TagListGenerator/KafkaTags.g.cs b/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/TagListGenerator/KafkaTags.g.cs index 10ba2d7c56db..d6d897c7a5ce 100644 --- a/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/TagListGenerator/KafkaTags.g.cs +++ b/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/TagListGenerator/KafkaTags.g.cs @@ -22,6 +22,8 @@ partial class KafkaTags private static ReadOnlySpan InstrumentationNameBytes => new byte[] { 169, 99, 111, 109, 112, 111, 110, 101, 110, 116 }; // BootstrapServersBytes = MessagePack.Serialize("messaging.kafka.bootstrap.servers"); private static ReadOnlySpan BootstrapServersBytes => new byte[] { 217, 33, 109, 101, 115, 115, 97, 103, 105, 110, 103, 46, 107, 97, 102, 107, 97, 46, 98, 111, 111, 116, 115, 116, 114, 97, 112, 46, 115, 101, 114, 118, 101, 114, 115 }; + // ClusterIdBytes = MessagePack.Serialize("messaging.kafka.cluster_id"); + private static ReadOnlySpan ClusterIdBytes => new byte[] { 186, 109, 101, 115, 115, 97, 103, 105, 110, 103, 46, 107, 97, 102, 107, 97, 46, 99, 108, 117, 115, 116, 101, 114, 95, 105, 100 }; // TopicBytes = MessagePack.Serialize("messaging.destination.name"); private static ReadOnlySpan TopicBytes => new byte[] { 186, 109, 101, 115, 115, 97, 103, 105, 110, 103, 46, 100, 101, 115, 116, 105, 110, 97, 116, 105, 111, 110, 46, 110, 97, 109, 101 }; // PartitionBytes = MessagePack.Serialize("kafka.partition"); @@ -40,6 +42,7 @@ partial class KafkaTags "span.kind" => SpanKind, "component" => InstrumentationName, "messaging.kafka.bootstrap.servers" => BootstrapServers, + "messaging.kafka.cluster_id" => ClusterId, "messaging.destination.name" => Topic, "kafka.partition" => Partition, "kafka.offset" => Offset, @@ -56,6 +59,9 @@ public override void SetTag(string key, string value) case "messaging.kafka.bootstrap.servers": BootstrapServers = value; break; + case "messaging.kafka.cluster_id": + ClusterId = value; + break; case "messaging.destination.name": Topic = value; break; @@ -98,6 +104,11 @@ public override void EnumerateTags(ref TProcessor processor) processor.Process(new TagItem("messaging.kafka.bootstrap.servers", BootstrapServers, BootstrapServersBytes)); } + if (ClusterId is not null) + { + processor.Process(new TagItem("messaging.kafka.cluster_id", ClusterId, ClusterIdBytes)); + } + if (Topic is not null) { processor.Process(new TagItem("messaging.destination.name", Topic, TopicBytes)); @@ -149,6 +160,13 @@ protected override void WriteAdditionalTags(System.Text.StringBuilder sb) .Append(','); } + if (ClusterId is not null) + { + sb.Append("messaging.kafka.cluster_id (tag):") + .Append(ClusterId) + .Append(','); + } + if (Topic is not null) { sb.Append("messaging.destination.name (tag):") diff --git a/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/TagListGenerator/KafkaTags.g.cs b/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/TagListGenerator/KafkaTags.g.cs index 10ba2d7c56db..d6d897c7a5ce 100644 --- a/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/TagListGenerator/KafkaTags.g.cs +++ b/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/TagListGenerator/KafkaTags.g.cs @@ -22,6 +22,8 @@ partial class KafkaTags private static ReadOnlySpan InstrumentationNameBytes => new byte[] { 169, 99, 111, 109, 112, 111, 110, 101, 110, 116 }; // BootstrapServersBytes = MessagePack.Serialize("messaging.kafka.bootstrap.servers"); private static ReadOnlySpan BootstrapServersBytes => new byte[] { 217, 33, 109, 101, 115, 115, 97, 103, 105, 110, 103, 46, 107, 97, 102, 107, 97, 46, 98, 111, 111, 116, 115, 116, 114, 97, 112, 46, 115, 101, 114, 118, 101, 114, 115 }; + // ClusterIdBytes = MessagePack.Serialize("messaging.kafka.cluster_id"); + private static ReadOnlySpan ClusterIdBytes => new byte[] { 186, 109, 101, 115, 115, 97, 103, 105, 110, 103, 46, 107, 97, 102, 107, 97, 46, 99, 108, 117, 115, 116, 101, 114, 95, 105, 100 }; // TopicBytes = MessagePack.Serialize("messaging.destination.name"); private static ReadOnlySpan TopicBytes => new byte[] { 186, 109, 101, 115, 115, 97, 103, 105, 110, 103, 46, 100, 101, 115, 116, 105, 110, 97, 116, 105, 111, 110, 46, 110, 97, 109, 101 }; // PartitionBytes = MessagePack.Serialize("kafka.partition"); @@ -40,6 +42,7 @@ partial class KafkaTags "span.kind" => SpanKind, "component" => InstrumentationName, "messaging.kafka.bootstrap.servers" => BootstrapServers, + "messaging.kafka.cluster_id" => ClusterId, "messaging.destination.name" => Topic, "kafka.partition" => Partition, "kafka.offset" => Offset, @@ -56,6 +59,9 @@ public override void SetTag(string key, string value) case "messaging.kafka.bootstrap.servers": BootstrapServers = value; break; + case "messaging.kafka.cluster_id": + ClusterId = value; + break; case "messaging.destination.name": Topic = value; break; @@ -98,6 +104,11 @@ public override void EnumerateTags(ref TProcessor processor) processor.Process(new TagItem("messaging.kafka.bootstrap.servers", BootstrapServers, BootstrapServersBytes)); } + if (ClusterId is not null) + { + processor.Process(new TagItem("messaging.kafka.cluster_id", ClusterId, ClusterIdBytes)); + } + if (Topic is not null) { processor.Process(new TagItem("messaging.destination.name", Topic, TopicBytes)); @@ -149,6 +160,13 @@ protected override void WriteAdditionalTags(System.Text.StringBuilder sb) .Append(','); } + if (ClusterId is not null) + { + sb.Append("messaging.kafka.cluster_id (tag):") + .Append(ClusterId) + .Append(','); + } + if (Topic is not null) { sb.Append("messaging.destination.name (tag):") diff --git a/tracer/src/Datadog.Trace/Tagging/KafkaTags.cs b/tracer/src/Datadog.Trace/Tagging/KafkaTags.cs index c8cdd4b257c6..62c456b74cc8 100644 --- a/tracer/src/Datadog.Trace/Tagging/KafkaTags.cs +++ b/tracer/src/Datadog.Trace/Tagging/KafkaTags.cs @@ -36,6 +36,9 @@ public KafkaTags(string spanKind) [Tag(Trace.Tags.KafkaBootstrapServers)] public string BootstrapServers { get; set; } + [Tag(Trace.Tags.KafkaClusterId)] + public string ClusterId { get; set; } + [Tag(Trace.Tags.MessagingDestinationName)] public string Topic { get; set; } diff --git a/tracer/src/Datadog.Trace/Tags.cs b/tracer/src/Datadog.Trace/Tags.cs index 4a4e930f9ba2..5cb25fb7e035 100644 --- a/tracer/src/Datadog.Trace/Tags.cs +++ b/tracer/src/Datadog.Trace/Tags.cs @@ -376,6 +376,11 @@ public static partial class Tags /// internal const string KafkaBootstrapServers = "messaging.kafka.bootstrap.servers"; + /// + /// The unique identifier for the Kafka cluster + /// + internal const string KafkaClusterId = "messaging.kafka.cluster_id"; + /// /// The partition associated with a record /// diff --git a/tracer/src/Datadog.Trace/TracerManager.cs b/tracer/src/Datadog.Trace/TracerManager.cs index 319bac0d53f6..88cbabb6b75e 100644 --- a/tracer/src/Datadog.Trace/TracerManager.cs +++ b/tracer/src/Datadog.Trace/TracerManager.cs @@ -593,6 +593,8 @@ void WriteDictionary(IReadOnlyDictionary dictionary) } Log.Information("DATADOG TRACER CONFIGURATION - {Configuration}", stringWriter.ToString()); + Log.Information("ROBC CLUSTER ID BRANCH"); + Console.Out.WriteLine("ROBC CLUSTER ID BRANCH"); OverrideErrorLog.Instance.ProcessAndClearActions(Log, TelemetryFactory.Metrics); // global errors, only logged once instanceSettings.ErrorLog.ProcessAndClearActions(Log, TelemetryFactory.Metrics); // global errors, only logged once }