Skip to content

Commit ef736ce

Browse files
authored
Merge pull request #1182 from typelevel/update/opentelemetry-semconv-1.40.0
Update opentelemetry-semconv to 1.40.0
2 parents a544f78 + 3ba0295 commit ef736ce

35 files changed

Lines changed: 1014 additions & 849 deletions

build.sbt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ val OpenTelemetryVersion = "1.59.0"
7979
val OpenTelemetryAlphaVersion = s"$OpenTelemetryVersion-alpha"
8080
val OpenTelemetryInstrumentationVersion = "2.25.0"
8181
val OpenTelemetryInstrumentationAlphaVersion = s"$OpenTelemetryInstrumentationVersion-alpha"
82-
val OpenTelemetrySemConvVersion = "1.39.0"
82+
val OpenTelemetrySemConvVersion = "1.40.0"
8383
val OpenTelemetrySemConvAlphaVersion = s"$OpenTelemetrySemConvVersion-alpha"
8484
val Otel4sAgentVersion = "2.22.0"
8585
val PekkoStreamVersion = "1.4.0"

buildscripts/semantic-convention/templates/registry/otel4s/metrics/SemanticMetrics.scala.j2

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
{%- elif type == "stable" -%} Stability.stable
6363
{%- elif type == "release_candidate" -%} Stability.releaseCandidate
6464
{%- elif type == "alpha" -%} Stability.alpha
65+
{%- elif type == "beta" -%} Stability.beta
6566
{%- else -%} _unknown_stability_type_{{ type }}
6667
{%- endif -%}
6768
{%- endmacro -%}

semconv/experimental/src/main/scala/org/typelevel/otel4s/semconv/experimental/attributes/DbExperimentalAttributes.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,10 @@ object DbExperimentalAttributes {
308308
* analyzing telemetry for database calls involving complex queries. <p> Summary may be available to the
309309
* instrumentation through instrumentation hooks or other means. If it is not available, instrumentations that
310310
* support query parsing SHOULD generate a summary following <a
311-
* href="/docs/db/database-spans.md#generating-a-summary-of-the-query">Generating query summary</a> section.
311+
* href="/docs/db/database-spans.md#generating-a-summary-of-the-query">Generating query summary</a> section. <p>
312+
* For batch operations, if the individual operations are known to have the same query summary then that query
313+
* summary SHOULD be used prepended by `BATCH `, otherwise `db.query.summary` SHOULD be `BATCH` or some other
314+
* database system specific term if more applicable.
312315
*/
313316
@deprecated(
314317
"use `org.typelevel.otel4s.semconv.attributes.DbAttributes.DbQuerySummary` instead.",

semconv/experimental/src/main/scala/org/typelevel/otel4s/semconv/experimental/attributes/ErrorExperimentalAttributes.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ object ErrorExperimentalAttributes {
2929
* `exception.message` in `error.message`. <p> `error.message` is NOT RECOMMENDED for metrics or spans due to its
3030
* unbounded cardinality and overlap with span status.
3131
*/
32+
@deprecated(
33+
"Use domain-specific error message attribute. For example, use `feature_flag.error.message` for feature flag errors.",
34+
""
35+
)
3236
val ErrorMessage: AttributeKey[String] =
3337
AttributeKey("error.message")
3438

semconv/experimental/src/main/scala/org/typelevel/otel4s/semconv/experimental/attributes/ExceptionExperimentalAttributes.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ package experimental.attributes
2222
object ExceptionExperimentalAttributes {
2323

2424
/** The exception message.
25+
*
26+
* @note
27+
* <blockquote> [!WARNING] <p> This attribute may contain sensitive information.</blockquote>
2528
*/
2629
@deprecated(
2730
"use `org.typelevel.otel4s.semconv.attributes.ExceptionAttributes.ExceptionMessage` instead.",

semconv/experimental/src/main/scala/org/typelevel/otel4s/semconv/experimental/attributes/FeatureFlagExperimentalAttributes.scala

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,15 @@ object FeatureFlagExperimentalAttributes {
2626
val FeatureFlagContextId: AttributeKey[String] =
2727
AttributeKey("feature_flag.context.id")
2828

29-
/** Deprecated, use `error.message` instead.
29+
/** A message providing more detail about an error that occurred during feature flag evaluation in human-readable
30+
* form.
3031
*/
31-
@deprecated("Replaced by `error.message`.", "")
32+
val FeatureFlagErrorMessage: AttributeKey[String] =
33+
AttributeKey("feature_flag.error.message")
34+
35+
/** Deprecated, use `feature_flag.error.message` instead.
36+
*/
37+
@deprecated("Replaced by `feature_flag.error.message`.", "")
3238
val FeatureFlagEvaluationErrorMessage: AttributeKey[String] =
3339
AttributeKey("feature_flag.evaluation.error.message")
3440

semconv/experimental/src/main/scala/org/typelevel/otel4s/semconv/experimental/attributes/GcpExperimentalAttributes.scala

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,23 @@ object GcpExperimentalAttributes {
168168
val GcpGceInstanceName: AttributeKey[String] =
169169
AttributeKey("gcp.gce.instance.name")
170170

171+
/** The name of the Instance Group Manager (IGM) that manages this VM, if any.
172+
*/
173+
val GcpGceInstanceGroupManagerName: AttributeKey[String] =
174+
AttributeKey("gcp.gce.instance_group_manager.name")
175+
176+
/** The region of a <strong>regional</strong> Instance Group Manager (e.g., `us-central1`). Set this
177+
* <strong>only</strong> when the IGM is regional.
178+
*/
179+
val GcpGceInstanceGroupManagerRegion: AttributeKey[String] =
180+
AttributeKey("gcp.gce.instance_group_manager.region")
181+
182+
/** The zone of a <strong>zonal</strong> Instance Group Manager (e.g., `us-central1-a`). Set this
183+
* <strong>only</strong> when the IGM is zonal.
184+
*/
185+
val GcpGceInstanceGroupManagerZone: AttributeKey[String] =
186+
AttributeKey("gcp.gce.instance_group_manager.zone")
187+
171188
/** Values for [[GcpApphubServiceCriticalityType]].
172189
*/
173190
abstract class GcpApphubServiceCriticalityTypeValue(val value: String)

semconv/experimental/src/main/scala/org/typelevel/otel4s/semconv/experimental/attributes/GenAiExperimentalAttributes.scala

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ object GenAiExperimentalAttributes {
3636
val GenAiAgentName: AttributeKey[String] =
3737
AttributeKey("gen_ai.agent.name")
3838

39+
/** The version of the GenAI agent.
40+
*/
41+
val GenAiAgentVersion: AttributeKey[String] =
42+
AttributeKey("gen_ai.agent.version")
43+
3944
/** Deprecated, use Event API to report completions contents.
4045
*/
4146
@deprecated("Removed, no replacement at this time.", "")
@@ -245,6 +250,14 @@ object GenAiExperimentalAttributes {
245250
val GenAiResponseModel: AttributeKey[String] =
246251
AttributeKey("gen_ai.response.model")
247252

253+
/** The query text used for retrieval.
254+
*
255+
* @note
256+
* <blockquote> [!Warning] This attribute may contain sensitive information.</blockquote>
257+
*/
258+
val GenAiRetrievalQueryText: AttributeKey[String] =
259+
AttributeKey("gen_ai.retrieval.query.text")
260+
248261
/** Deprecated, use `gen_ai.provider.name` instead.
249262
*/
250263
@deprecated("Replaced by `gen_ai.provider.name`.", "")
@@ -284,13 +297,34 @@ object GenAiExperimentalAttributes {
284297
val GenAiToolType: AttributeKey[String] =
285298
AttributeKey("gen_ai.tool.type")
286299

300+
/** The number of input tokens written to a provider-managed cache.
301+
*
302+
* @note
303+
* <p> The value SHOULD be included in `gen_ai.usage.input_tokens`.
304+
*/
305+
val GenAiUsageCacheCreationInputTokens: AttributeKey[Long] =
306+
AttributeKey("gen_ai.usage.cache_creation.input_tokens")
307+
308+
/** The number of input tokens served from a provider-managed cache.
309+
*
310+
* @note
311+
* <p> The value SHOULD be included in `gen_ai.usage.input_tokens`.
312+
*/
313+
val GenAiUsageCacheReadInputTokens: AttributeKey[Long] =
314+
AttributeKey("gen_ai.usage.cache_read.input_tokens")
315+
287316
/** Deprecated, use `gen_ai.usage.output_tokens` instead.
288317
*/
289318
@deprecated("Replaced by `gen_ai.usage.output_tokens`.", "")
290319
val GenAiUsageCompletionTokens: AttributeKey[Long] =
291320
AttributeKey("gen_ai.usage.completion_tokens")
292321

293322
/** The number of tokens used in the GenAI input (prompt).
323+
*
324+
* @note
325+
* <p> This value SHOULD include all types of input tokens, including cached tokens. Instrumentations SHOULD make a
326+
* best effort to populate this value, using a total provided by the provider when available or, depending on the
327+
* provider API, by summing different token types parsed from the provider output.
294328
*/
295329
val GenAiUsageInputTokens: AttributeKey[Long] =
296330
AttributeKey("gen_ai.usage.input_tokens")
@@ -372,6 +406,11 @@ object GenAiExperimentalAttributes {
372406
*/
373407
case object Embeddings extends GenAiOperationNameValue("embeddings")
374408

409+
/** Retrieval operation such as <a href="https://platform.openai.com/docs/api-reference/vector-stores/search">OpenAI
410+
* Search Vector Store API</a>
411+
*/
412+
case object Retrieval extends GenAiOperationNameValue("retrieval")
413+
375414
/** Create GenAI agent
376415
*/
377416
case object CreateAgent extends GenAiOperationNameValue("create_agent")

semconv/experimental/src/main/scala/org/typelevel/otel4s/semconv/experimental/attributes/HttpExperimentalAttributes.scala

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -96,12 +96,16 @@ object HttpExperimentalAttributes {
9696
* to `_OTHER`. <p> If the HTTP instrumentation could end up converting valid HTTP request methods to `_OTHER`,
9797
* then it MUST provide a way to override the list of known HTTP methods. If this override is done via environment
9898
* variable, then the environment variable MUST be named OTEL_INSTRUMENTATION_HTTP_KNOWN_METHODS and support a
99-
* comma-separated list of case-sensitive known HTTP methods (this list MUST be a full override of the default
100-
* known method, it is not a list of known methods in addition to the defaults). <p> HTTP method names are
101-
* case-sensitive and `http.request.method` attribute value MUST match a known HTTP method name exactly.
102-
* Instrumentations for specific web frameworks that consider HTTP methods to be case insensitive, SHOULD populate
103-
* a canonical equivalent. Tracing instrumentations that do so, MUST also set `http.request.method_original` to the
104-
* original value.
99+
* comma-separated list of case-sensitive known HTTP methods. <p>
100+
*
101+
* If this override is done via declarative configuration, then the list MUST be configurable via the `known_methods`
102+
* property (an array of case-sensitive strings with minimum items 0) under
103+
* `.instrumentation/development.general.http.client` and/or `.instrumentation/development.general.http.server`. <p>
104+
* In either case, this list MUST be a full override of the default known methods, it is not a list of known methods
105+
* in addition to the defaults. <p> HTTP method names are case-sensitive and `http.request.method` attribute value
106+
* MUST match a known HTTP method name exactly. Instrumentations for specific web frameworks that consider HTTP
107+
* methods to be case insensitive, SHOULD populate a canonical equivalent. Tracing instrumentations that do so, MUST
108+
* also set `http.request.method_original` to the original value.
105109
*/
106110
@deprecated(
107111
"use `org.typelevel.otel4s.semconv.attributes.HttpAttributes.HttpRequestMethod` instead.",

semconv/experimental/src/main/scala/org/typelevel/otel4s/semconv/experimental/attributes/K8sExperimentalAttributes.scala

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,122 @@ object K8sExperimentalAttributes {
489489
val K8sResourcequotaUid: AttributeKey[String] =
490490
AttributeKey("k8s.resourcequota.uid")
491491

492+
/** The annotation placed on the Service, the `<key>` being the annotation name, the value being the annotation value,
493+
* even if the value is empty.
494+
*
495+
* @note
496+
* <p> Examples: <ul> <li>An annotation `prometheus.io/scrape` with value `true` SHOULD be recorded as the
497+
* `k8s.service.annotation.prometheus.io/scrape` attribute with value `"true"`. <li>An annotation `data` with empty
498+
* string value SHOULD be recorded as the `k8s.service.annotation.data` attribute with value `""`. </ul>
499+
*/
500+
val K8sServiceAnnotation: AttributeKey[String] =
501+
AttributeKey("k8s.service.annotation")
502+
503+
/** The address type of the service endpoint.
504+
*
505+
* @note
506+
* <p> The network address family or type of the endpoint. This attribute aligns with the `addressType` field of
507+
* the <a href="https://kubernetes.io/docs/reference/kubernetes-api/service-resources/endpoint-slice-v1/">K8s
508+
* EndpointSlice</a>. It is used to differentiate metrics when a Service is backed by multiple address types (e.g.,
509+
* in dual-stack clusters).
510+
*/
511+
val K8sServiceEndpointAddressType: AttributeKey[String] =
512+
AttributeKey("k8s.service.endpoint.address_type")
513+
514+
/** The condition of the service endpoint.
515+
*
516+
* @note
517+
* <p> The current operational condition of the service endpoint. An endpoint can have multiple conditions set at
518+
* once (e.g., both `serving` and `terminating` during rollout). This attribute aligns with the condition fields in
519+
* the <a href="https://kubernetes.io/docs/reference/kubernetes-api/service-resources/endpoint-slice-v1/">K8s
520+
* EndpointSlice</a>.
521+
*/
522+
val K8sServiceEndpointCondition: AttributeKey[String] =
523+
AttributeKey("k8s.service.endpoint.condition")
524+
525+
/** The zone of the service endpoint.
526+
*
527+
* @note
528+
* <p> The zone where the endpoint is located, typically corresponding to a failure domain. This attribute aligns
529+
* with the `zone` field of endpoints in the <a
530+
* href="https://kubernetes.io/docs/reference/kubernetes-api/service-resources/endpoint-slice-v1/">K8s
531+
* EndpointSlice</a>. It enables zone-aware monitoring of service endpoint distribution and supports features like
532+
* <a href="https://kubernetes.io/docs/concepts/services-networking/topology-aware-routing/">Topology Aware
533+
* Routing</a>. <p> If the zone is not populated (e.g., nodes without the `topology.kubernetes.io/zone` label), the
534+
* attribute value will be an empty string.
535+
*/
536+
val K8sServiceEndpointZone: AttributeKey[String] =
537+
AttributeKey("k8s.service.endpoint.zone")
538+
539+
/** The label placed on the Service, the `<key>` being the label name, the value being the label value, even if the
540+
* value is empty.
541+
*
542+
* @note
543+
* <p> Examples: <ul> <li>A label `app` with value `my-service` SHOULD be recorded as the `k8s.service.label.app`
544+
* attribute with value `"my-service"`. <li>A label `data` with empty string value SHOULD be recorded as the
545+
* `k8s.service.label.data` attribute with value `""`. </ul>
546+
*/
547+
val K8sServiceLabel: AttributeKey[String] =
548+
AttributeKey("k8s.service.label")
549+
550+
/** The name of the Service.
551+
*/
552+
val K8sServiceName: AttributeKey[String] =
553+
AttributeKey("k8s.service.name")
554+
555+
/** Whether the Service publishes not-ready endpoints.
556+
*
557+
* @note
558+
* <p> Whether the Service is configured to publish endpoints before the pods are ready. This attribute is
559+
* typically used to indicate that a Service (such as a headless Service for a StatefulSet) allows peer discovery
560+
* before pods pass their readiness probes. It aligns with the `publishNotReadyAddresses` field of the <a
561+
* href="https://kubernetes.io/docs/reference/kubernetes-api/service-resources/service-v1/#ServiceSpec">K8s
562+
* ServiceSpec</a>.
563+
*/
564+
val K8sServicePublishNotReadyAddresses: AttributeKey[Boolean] =
565+
AttributeKey("k8s.service.publish_not_ready_addresses")
566+
567+
/** The selector key-value pair placed on the Service, the `<key>` being the selector key, the value being the
568+
* selector value.
569+
*
570+
* @note
571+
* <p> These selectors are used to correlate with pod labels. Each selector key-value pair becomes a separate
572+
* attribute. <p> Examples: <ul> <li>A selector `app=my-app` SHOULD be recorded as the `k8s.service.selector.app`
573+
* attribute with value `"my-app"`. <li>A selector `version=v1` SHOULD be recorded as the
574+
* `k8s.service.selector.version` attribute with value `"v1"`. </ul>
575+
*/
576+
val K8sServiceSelector: AttributeKey[String] =
577+
AttributeKey("k8s.service.selector")
578+
579+
/** The traffic distribution policy for the Service.
580+
*
581+
* @note
582+
* <p> Specifies how traffic is distributed to endpoints for this Service. This attribute aligns with the
583+
* `trafficDistribution` field of the <a
584+
* href="https://kubernetes.io/docs/reference/networking/virtual-ips/#traffic-distribution">K8s ServiceSpec</a>.
585+
* Known values include `PreferSameZone` (prefer endpoints in the same zone as the client) and `PreferSameNode`
586+
* (prefer endpoints on the same node, fallback to same zone, then cluster-wide). If this field is not set on the
587+
* Service, the attribute SHOULD NOT be emitted. When not set, Kubernetes distributes traffic evenly across all
588+
* endpoints cluster-wide.
589+
*/
590+
val K8sServiceTrafficDistribution: AttributeKey[String] =
591+
AttributeKey("k8s.service.traffic_distribution")
592+
593+
/** The type of the Kubernetes Service.
594+
*
595+
* @note
596+
* <p> This attribute aligns with the `type` field of the <a
597+
* href="https://kubernetes.io/docs/reference/kubernetes-api/service-resources/service-v1/#ServiceSpec">K8s
598+
* ServiceSpec</a>.
599+
*/
600+
val K8sServiceType: AttributeKey[String] =
601+
AttributeKey("k8s.service.type")
602+
603+
/** The UID of the Service.
604+
*/
605+
val K8sServiceUid: AttributeKey[String] =
606+
AttributeKey("k8s.service.uid")
607+
492608
/** The annotation placed on the StatefulSet, the `<key>` being the annotation name, the value being the annotation
493609
* value, even if the value is empty.
494610
*
@@ -725,6 +841,69 @@ object K8sExperimentalAttributes {
725841
case object UnexpectedAdmissionError extends K8sPodStatusReasonValue("UnexpectedAdmissionError")
726842
}
727843

844+
/** Values for [[K8sServiceEndpointAddressType]].
845+
*/
846+
abstract class K8sServiceEndpointAddressTypeValue(val value: String)
847+
object K8sServiceEndpointAddressTypeValue {
848+
implicit val attributeFromK8sServiceEndpointAddressTypeValue
849+
: Attribute.From[K8sServiceEndpointAddressTypeValue, String] = _.value
850+
851+
/** IPv4 address type
852+
*/
853+
case object Ipv4 extends K8sServiceEndpointAddressTypeValue("IPv4")
854+
855+
/** IPv6 address type
856+
*/
857+
case object Ipv6 extends K8sServiceEndpointAddressTypeValue("IPv6")
858+
859+
/** FQDN address type
860+
*/
861+
case object Fqdn extends K8sServiceEndpointAddressTypeValue("FQDN")
862+
}
863+
864+
/** Values for [[K8sServiceEndpointCondition]].
865+
*/
866+
abstract class K8sServiceEndpointConditionValue(val value: String)
867+
object K8sServiceEndpointConditionValue {
868+
implicit val attributeFromK8sServiceEndpointConditionValue
869+
: Attribute.From[K8sServiceEndpointConditionValue, String] = _.value
870+
871+
/** The endpoint is ready to receive new connections.
872+
*/
873+
case object Ready extends K8sServiceEndpointConditionValue("ready")
874+
875+
/** The endpoint is currently handling traffic.
876+
*/
877+
case object Serving extends K8sServiceEndpointConditionValue("serving")
878+
879+
/** The endpoint is in the process of shutting down.
880+
*/
881+
case object Terminating extends K8sServiceEndpointConditionValue("terminating")
882+
}
883+
884+
/** Values for [[K8sServiceType]].
885+
*/
886+
abstract class K8sServiceTypeValue(val value: String)
887+
object K8sServiceTypeValue {
888+
implicit val attributeFromK8sServiceTypeValue: Attribute.From[K8sServiceTypeValue, String] = _.value
889+
890+
/** ClusterIP service type
891+
*/
892+
case object ClusterIp extends K8sServiceTypeValue("ClusterIP")
893+
894+
/** NodePort service type
895+
*/
896+
case object NodePort extends K8sServiceTypeValue("NodePort")
897+
898+
/** LoadBalancer service type
899+
*/
900+
case object LoadBalancer extends K8sServiceTypeValue("LoadBalancer")
901+
902+
/** ExternalName service type
903+
*/
904+
case object ExternalName extends K8sServiceTypeValue("ExternalName")
905+
}
906+
728907
/** Values for [[K8sVolumeType]].
729908
*/
730909
abstract class K8sVolumeTypeValue(val value: String)

0 commit comments

Comments
 (0)