diff --git a/Cargo.lock b/Cargo.lock index 7b4e7e976..3b7094cba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5704,6 +5704,7 @@ dependencies = [ "tempfile", "thiserror 2.0.18", "ureq", + "url", "walkdir", "zip", ] @@ -5855,6 +5856,7 @@ dependencies = [ "rayon", "serde", "serde_json", + "serde_yaml", "thiserror 2.0.18", "walkdir", "weaver_common", diff --git a/crates/weaver_common/Cargo.toml b/crates/weaver_common/Cargo.toml index b9c10ef4c..61a100d97 100644 --- a/crates/weaver_common/Cargo.toml +++ b/crates/weaver_common/Cargo.toml @@ -23,6 +23,7 @@ once_cell.workspace = true schemars.workspace = true ureq.workspace = true log.workspace = true +url.workspace = true tempfile.workspace = true dirs = "6.0.0" diff --git a/crates/weaver_common/src/lib.rs b/crates/weaver_common/src/lib.rs index 0d503b7cf..fecbe92fe 100644 --- a/crates/weaver_common/src/lib.rs +++ b/crates/weaver_common/src/lib.rs @@ -17,6 +17,7 @@ use miette::Diagnostic; use paris::formatter::colorize_string; use serde::Serialize; use std::io::Write; +use std::path::Path; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::{Arc, Mutex}; @@ -295,3 +296,36 @@ pub fn warn_flare(message: T) -> String { pub fn log_warn(message: T) { log::warn!("{}", warn_flare(message)); } + +/// Types of path strings we can support. +pub enum PathType { + /// A URL path, like http://server/ + URL, + /// A relative path, like ../some-file + RelativePath, + /// An absolute path, like /my/file/location + AbsolutePath, + /// Weaver-special. A reference to a file + /// in a git repo or other. + WeaverPath, +} + +/// Returns the type of path we're dealing with. +#[must_use] +pub fn get_path_type(input: &str) -> PathType { + match url::Url::parse(input) { + Ok(_) => PathType::URL, + Err(url::ParseError::RelativeUrlWithoutBase) => { + let test_path = Path::new(input); + if test_path.is_absolute() { + PathType::AbsolutePath + } else { + PathType::RelativePath + } + } + // TODO - we can learn more from error, we may be able + // to determine if this is a git-relative path or + // in-archive file reference. + Err(_) => PathType::WeaverPath, + } +} diff --git a/crates/weaver_common/src/vdir.rs b/crates/weaver_common/src/vdir.rs index 77a37a7dd..2e3c633e5 100644 --- a/crates/weaver_common/src/vdir.rs +++ b/crates/weaver_common/src/vdir.rs @@ -130,6 +130,50 @@ pub enum VirtualDirectoryPath { }, } +// Helper to allow mapping an Option via a function that works with empty strings. +// Empty is replaced with None and vice versa. +fn map_option String>(opt: Option, f: F) -> Option { + let result = f(opt.unwrap_or_default()); + if result.is_empty() { + None + } else { + Some(result) + } +} + +impl VirtualDirectoryPath { + /// Converts a virtual directory path by manipulating the "sub folder". + /// + /// Returning an empty string means no sub_folder will be used in resulting path. + /// + /// Sub folder will be modified as follows: + /// + /// - LocalFolder: will see the entire path + /// - others: will see the path inside the archive or empty string if none. + pub fn map_sub_folder String>(self, f: F) -> VirtualDirectoryPath { + match self { + LocalFolder { path } => LocalFolder { path: f(path) }, + LocalArchive { path, sub_folder } => LocalArchive { + path, + sub_folder: map_option(sub_folder, f), + }, + RemoteArchive { url, sub_folder } => RemoteArchive { + url, + sub_folder: map_option(sub_folder, f), + }, + GitRepo { + url, + refspec, + sub_folder, + } => GitRepo { + url, + refspec, + sub_folder: map_option(sub_folder, f), + }, + } + } +} + /// Enables parsing a [`VirtualDirectoryPath`] from a string representation. /// /// This implementation allows easy deserialization from strings (e.g. configuration files, command-line arguments). @@ -686,10 +730,18 @@ impl VirtualDirectory { /// Returns the original string representation that was used to create this `VirtualDirectory`. #[must_use] - pub fn vdir_path(&self) -> &str { + pub fn vdir_path_str(&self) -> &str { &self.vdir_path } + /// Returns the original `VirtualDirectoryRef` that was used to create this `VirtualDirectory`. + #[must_use] + pub fn vdir_path(&self) -> VirtualDirectoryPath { + self.vdir_path_str() + .try_into() + .expect("VirtualDirectory should not have invalid `vdir_path`.") + } + /// Creates and returns a new temporary directory within `.weaver/vdir_cache`. /// /// The created directory and its contents are automatically deleted when dropped. diff --git a/crates/weaver_resolved_schema/src/catalog.rs b/crates/weaver_resolved_schema/src/catalog.rs index c84bbb887..28aea7d48 100644 --- a/crates/weaver_resolved_schema/src/catalog.rs +++ b/crates/weaver_resolved_schema/src/catalog.rs @@ -15,12 +15,12 @@ use weaver_semconv::stability::Stability; /// Attribute references are used to refer to attributes in the catalog. /// /// Note : In the future, this catalog could be extended with other entities. -#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema, Default)] +#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema, Default, PartialEq, Eq)] #[serde(deny_unknown_fields)] #[must_use] pub struct Catalog { /// Catalog of attributes used in the schema. - #[serde(skip_serializing_if = "Vec::is_empty")] + #[serde(default, skip_serializing_if = "Vec::is_empty")] pub(crate) attributes: Vec, } diff --git a/crates/weaver_resolved_schema/src/lib.rs b/crates/weaver_resolved_schema/src/lib.rs index 7ef9dec17..cde4f4947 100644 --- a/crates/weaver_resolved_schema/src/lib.rs +++ b/crates/weaver_resolved_schema/src/lib.rs @@ -32,6 +32,8 @@ pub mod tags; pub mod v2; pub mod value; +pub use error::Error; + /// The registry ID for the OpenTelemetry semantic conventions. /// This ID is reserved and should not be used by any other registry. pub const OTEL_REGISTRY_ID: &str = "OTEL"; diff --git a/crates/weaver_resolver/Cargo.toml b/crates/weaver_resolver/Cargo.toml index 95673806c..c72bce413 100644 --- a/crates/weaver_resolver/Cargo.toml +++ b/crates/weaver_resolver/Cargo.toml @@ -21,6 +21,7 @@ thiserror.workspace = true rayon.workspace = true serde.workspace = true serde_json.workspace = true +serde_yaml.workspace = true walkdir.workspace = true miette.workspace = true itertools.workspace = true diff --git a/crates/weaver_resolver/data/registry-test-1-single-attr-ref/expected-attribute-catalog.json b/crates/weaver_resolver/data/registry-test-1-single-attr-ref/expected-attribute-catalog.json index 5bde7c6fc..f455a0080 100644 --- a/crates/weaver_resolver/data/registry-test-1-single-attr-ref/expected-attribute-catalog.json +++ b/crates/weaver_resolver/data/registry-test-1-single-attr-ref/expected-attribute-catalog.json @@ -1,28 +1,30 @@ -[ - { - "name": "messaging.destination.name", - "type": "string", - "brief": "The message destination name", - "examples": [ - "MyQueue", - "MyTopic" - ], - "requirement_level": "recommended", - "note": "Destination name SHOULD uniquely identify a specific queue, topic or other entity within the broker. If\nthe broker doesn't have such notion, the destination name SHOULD uniquely identify the broker.\n", - "stability": "stable" - }, - { - "name": "messaging.destination.name", - "type": "string", - "brief": "The message destination name", - "examples": [ - "MyQueue", - "MyTopic" - ], - "requirement_level": { - "conditionally_required": "if and only if `messaging.destination.name` is known to have low cardinality. Otherwise, `messaging.destination.template` MAY be populated." +{ + "attributes": [ + { + "name": "messaging.destination.name", + "type": "string", + "brief": "The message destination name", + "examples": [ + "MyQueue", + "MyTopic" + ], + "requirement_level": "recommended", + "note": "Destination name SHOULD uniquely identify a specific queue, topic or other entity within the broker. If\nthe broker doesn't have such notion, the destination name SHOULD uniquely identify the broker.\n", + "stability": "stable" }, - "note": "Destination name SHOULD uniquely identify a specific queue, topic or other entity within the broker. If\nthe broker doesn't have such notion, the destination name SHOULD uniquely identify the broker.\n", - "stability": "stable" - } -] \ No newline at end of file + { + "name": "messaging.destination.name", + "type": "string", + "brief": "The message destination name", + "examples": [ + "MyQueue", + "MyTopic" + ], + "requirement_level": { + "conditionally_required": "if and only if `messaging.destination.name` is known to have low cardinality. Otherwise, `messaging.destination.template` MAY be populated." + }, + "note": "Destination name SHOULD uniquely identify a specific queue, topic or other entity within the broker. If\nthe broker doesn't have such notion, the destination name SHOULD uniquely identify the broker.\n", + "stability": "stable" + } + ] +} \ No newline at end of file diff --git a/crates/weaver_resolver/data/registry-test-10-prefix-refs/expected-attribute-catalog.json b/crates/weaver_resolver/data/registry-test-10-prefix-refs/expected-attribute-catalog.json index 5a2e2c0db..a8a6b4fe0 100644 --- a/crates/weaver_resolver/data/registry-test-10-prefix-refs/expected-attribute-catalog.json +++ b/crates/weaver_resolver/data/registry-test-10-prefix-refs/expected-attribute-catalog.json @@ -1,63 +1,65 @@ -[ - { - "name": "client.geo.lat", - "type": "string", - "brief": "My own latitude", - "examples": [ - "123.456" - ], - "requirement_level": "recommended", - "stability": "development", - "prefix": true - }, - { - "name": "client.geo.lat", - "type": "string", - "brief": "this is embedded attribute", - "examples": [ - "123.456" - ], - "requirement_level": "recommended", - "stability": "development" - }, - { - "name": "client.id", - "type": "string", - "brief": "some client id\n", - "examples": [ - "a.einstein" - ], - "requirement_level": "recommended", - "stability": "development" - }, - { - "name": "geo.lat", - "type": "string", - "brief": "latitude of the geo coordinates.\n", - "examples": [ - "123.456" - ], - "requirement_level": "recommended", - "stability": "development" - }, - { - "name": "geo.lat", - "type": "string", - "brief": "this is ref attribute", - "examples": [ - "123.456" - ], - "requirement_level": "recommended", - "stability": "development" - }, - { - "name": "geo.lon", - "type": "string", - "brief": "longitude of the geo coordinates.\n", - "examples": [ - "234.456" - ], - "requirement_level": "recommended", - "stability": "development" - } -] \ No newline at end of file +{ + "attributes": [ + { + "name": "client.geo.lat", + "type": "string", + "brief": "My own latitude", + "examples": [ + "123.456" + ], + "requirement_level": "recommended", + "stability": "development", + "prefix": true + }, + { + "name": "client.geo.lat", + "type": "string", + "brief": "this is embedded attribute", + "examples": [ + "123.456" + ], + "requirement_level": "recommended", + "stability": "development" + }, + { + "name": "client.id", + "type": "string", + "brief": "some client id\n", + "examples": [ + "a.einstein" + ], + "requirement_level": "recommended", + "stability": "development" + }, + { + "name": "geo.lat", + "type": "string", + "brief": "latitude of the geo coordinates.\n", + "examples": [ + "123.456" + ], + "requirement_level": "recommended", + "stability": "development" + }, + { + "name": "geo.lat", + "type": "string", + "brief": "this is ref attribute", + "examples": [ + "123.456" + ], + "requirement_level": "recommended", + "stability": "development" + }, + { + "name": "geo.lon", + "type": "string", + "brief": "longitude of the geo coordinates.\n", + "examples": [ + "234.456" + ], + "requirement_level": "recommended", + "stability": "development" + } + ] +} \ No newline at end of file diff --git a/crates/weaver_resolver/data/registry-test-11-prefix-refs-extends/expected-attribute-catalog.json b/crates/weaver_resolver/data/registry-test-11-prefix-refs-extends/expected-attribute-catalog.json index cd38507a0..32c61f106 100644 --- a/crates/weaver_resolver/data/registry-test-11-prefix-refs-extends/expected-attribute-catalog.json +++ b/crates/weaver_resolver/data/registry-test-11-prefix-refs-extends/expected-attribute-catalog.json @@ -1,83 +1,85 @@ -[ - { - "name": "client.geo.lat", - "type": "string", - "brief": "My own latitude", - "examples": [ - "123.456" - ], - "requirement_level": "recommended", - "stability": "development", - "prefix": true - }, - { - "name": "client.geo.lat", - "type": "string", - "brief": "this is embedded attribute", - "examples": [ - "123.456" - ], - "requirement_level": "recommended", - "stability": "development" - }, - { - "name": "client.id", - "type": "string", - "brief": "some client id\n", - "examples": [ - "a.einstein" - ], - "requirement_level": "recommended", - "stability": "development" - }, - { - "name": "geo.country", - "type": "string", - "brief": "country of the geo coordinates.\n", - "examples": [ - "US" - ], - "requirement_level": "recommended", - "stability": "development" - }, - { - "name": "geo.country", - "type": "string", - "brief": "this is ref country attribute", - "examples": [ - "US" - ], - "requirement_level": "recommended", - "stability": "development" - }, - { - "name": "geo.lat", - "type": "string", - "brief": "latitude of the geo coordinates.\n", - "examples": [ - "123.456" - ], - "requirement_level": "recommended", - "stability": "development" - }, - { - "name": "geo.lat", - "type": "string", - "brief": "this is ref attribute", - "examples": [ - "123.456" - ], - "requirement_level": "recommended", - "stability": "development" - }, - { - "name": "geo.lon", - "type": "string", - "brief": "longitude of the geo coordinates.\n", - "examples": [ - "234.456" - ], - "requirement_level": "recommended", - "stability": "development" - } -] \ No newline at end of file +{ + "attributes": [ + { + "name": "client.geo.lat", + "type": "string", + "brief": "My own latitude", + "examples": [ + "123.456" + ], + "requirement_level": "recommended", + "stability": "development", + "prefix": true + }, + { + "name": "client.geo.lat", + "type": "string", + "brief": "this is embedded attribute", + "examples": [ + "123.456" + ], + "requirement_level": "recommended", + "stability": "development" + }, + { + "name": "client.id", + "type": "string", + "brief": "some client id\n", + "examples": [ + "a.einstein" + ], + "requirement_level": "recommended", + "stability": "development" + }, + { + "name": "geo.country", + "type": "string", + "brief": "country of the geo coordinates.\n", + "examples": [ + "US" + ], + "requirement_level": "recommended", + "stability": "development" + }, + { + "name": "geo.country", + "type": "string", + "brief": "this is ref country attribute", + "examples": [ + "US" + ], + "requirement_level": "recommended", + "stability": "development" + }, + { + "name": "geo.lat", + "type": "string", + "brief": "latitude of the geo coordinates.\n", + "examples": [ + "123.456" + ], + "requirement_level": "recommended", + "stability": "development" + }, + { + "name": "geo.lat", + "type": "string", + "brief": "this is ref attribute", + "examples": [ + "123.456" + ], + "requirement_level": "recommended", + "stability": "development" + }, + { + "name": "geo.lon", + "type": "string", + "brief": "longitude of the geo coordinates.\n", + "examples": [ + "234.456" + ], + "requirement_level": "recommended", + "stability": "development" + } + ] +} \ No newline at end of file diff --git a/crates/weaver_resolver/data/registry-test-14-annotations/expected-attribute-catalog.json b/crates/weaver_resolver/data/registry-test-14-annotations/expected-attribute-catalog.json index d185206bd..09677c257 100644 --- a/crates/weaver_resolver/data/registry-test-14-annotations/expected-attribute-catalog.json +++ b/crates/weaver_resolver/data/registry-test-14-annotations/expected-attribute-catalog.json @@ -1,83 +1,85 @@ -[ - { - "name": "attr1", - "type": "string", - "brief": "Brief", - "examples": "eu-central-1", - "requirement_level": "required", - "note": "Note", - "stability": "stable", - "annotations": { - "code_generation": { - "exclude": true - }, - "complex": { - "key1": "string", - "key2": 234, - "key3": true, - "key4": { - "key4.1": "string", - "key4.2": 234 +{ + "attributes": [ + { + "name": "attr1", + "type": "string", + "brief": "Brief", + "examples": "eu-central-1", + "requirement_level": "required", + "note": "Note", + "stability": "stable", + "annotations": { + "code_generation": { + "exclude": true }, - "key5": [ - 12, - 45, - 67 - ], - "key6": null - }, - "privacy_sensitivity": "PII + PHI" - } - }, - { - "name": "attr1", - "type": "string", - "brief": "Brief", - "examples": "eu-central-1", - "requirement_level": "required", - "note": "Note", - "stability": "stable", - "annotations": { - "code_generation": { - "exclude": true - }, - "privacy_sensitivity": "PII" - } - }, - { - "name": "attr2", - "type": { - "members": [ - { - "id": "first", - "value": "first", - "brief": "First", - "stability": "stable" + "complex": { + "key1": "string", + "key2": 234, + "key3": true, + "key4": { + "key4.1": "string", + "key4.2": 234 + }, + "key5": [ + 12, + 45, + 67 + ], + "key6": null }, - { - "id": "second", - "value": "second", - "brief": "Second", - "stability": "stable", - "annotations": { - "code_generation": { - "exclude": true - }, - "privacy_sensitivity": "PII + PHI" - } - } - ] + "privacy_sensitivity": "PII + PHI" + } + }, + { + "name": "attr1", + "type": "string", + "brief": "Brief", + "examples": "eu-central-1", + "requirement_level": "required", + "note": "Note", + "stability": "stable", + "annotations": { + "code_generation": { + "exclude": true + }, + "privacy_sensitivity": "PII" + } }, - "brief": "Brief", - "examples": "eu-central-1", - "requirement_level": "required", - "note": "Note", - "stability": "stable", - "annotations": { - "code_generation": { - "exclude": true + { + "name": "attr2", + "type": { + "members": [ + { + "id": "first", + "value": "first", + "brief": "First", + "stability": "stable" + }, + { + "id": "second", + "value": "second", + "brief": "Second", + "stability": "stable", + "annotations": { + "code_generation": { + "exclude": true + }, + "privacy_sensitivity": "PII + PHI" + } + } + ] }, - "privacy_sensitivity": "PII" + "brief": "Brief", + "examples": "eu-central-1", + "requirement_level": "required", + "note": "Note", + "stability": "stable", + "annotations": { + "code_generation": { + "exclude": true + }, + "privacy_sensitivity": "PII" + } } - } -] \ No newline at end of file + ] +} \ No newline at end of file diff --git a/crates/weaver_resolver/data/registry-test-15-attr-any/expected-attribute-catalog.json b/crates/weaver_resolver/data/registry-test-15-attr-any/expected-attribute-catalog.json index c1a9b0ca3..e54473610 100644 --- a/crates/weaver_resolver/data/registry-test-15-attr-any/expected-attribute-catalog.json +++ b/crates/weaver_resolver/data/registry-test-15-attr-any/expected-attribute-catalog.json @@ -1,27 +1,29 @@ -[ - { - "name": "test.any", - "type": "any", - "brief": "any attribute", - "examples": [ - "zero", - 1, - 2.0, - true - ], - "note": "any attribute.\n", - "stability": "stable", - "requirement_level": "recommended" - }, - { - "name": "test.template.any", - "type": "template[any]", - "brief": "template[any] attribute", - "examples": [ - "test.template.any.my-custom-metadata-attribute=[\"zero\", 1, 2.0, true]" - ], - "requirement_level": "recommended", - "note": "template[any] attribute.\n", - "stability": "stable" - } -] \ No newline at end of file +{ + "attributes": [ + { + "name": "test.any", + "type": "any", + "brief": "any attribute", + "examples": [ + "zero", + 1, + 2.0, + true + ], + "requirement_level": "recommended", + "note": "any attribute.\n", + "stability": "stable" + }, + { + "name": "test.template.any", + "type": "template[any]", + "brief": "template[any] attribute", + "examples": [ + "test.template.any.my-custom-metadata-attribute=[\"zero\", 1, 2.0, true]" + ], + "requirement_level": "recommended", + "note": "template[any] attribute.\n", + "stability": "stable" + } + ] +} \ No newline at end of file diff --git a/crates/weaver_resolver/data/registry-test-2-multi-attr-refs/expected-attribute-catalog.json b/crates/weaver_resolver/data/registry-test-2-multi-attr-refs/expected-attribute-catalog.json index 43222934d..8b5ecbdf9 100644 --- a/crates/weaver_resolver/data/registry-test-2-multi-attr-refs/expected-attribute-catalog.json +++ b/crates/weaver_resolver/data/registry-test-2-multi-attr-refs/expected-attribute-catalog.json @@ -1,423 +1,425 @@ -[ - { - "name": "messaging.batch.message_count", - "type": "int", - "brief": "The number of messages sent, received, or processed in the scope of the batching operation.", - "examples": [ - 0, - 1, - 2 - ], - "requirement_level": "recommended", - "note": "Instrumentations SHOULD NOT set `messaging.batch.message_count` on spans that operate with a single message. When a messaging client library supports both batch and single-message API for the same operation, instrumentations SHOULD use `messaging.batch.message_count` for batching APIs and SHOULD NOT use it for single-message APIs.\n", - "stability": "stable" - }, - { - "name": "messaging.client_id", - "type": "string", - "brief": "A unique identifier for the client that consumes or produces a message.\n", - "examples": [ - "client-5", - "myhost@8742@s8083jm" - ], - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "messaging.destination.anonymous", - "type": "boolean", - "brief": "A boolean that is true if the message destination is anonymous (could be unnamed or have auto-generated name).", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "messaging.destination.name", - "type": "string", - "brief": "The message destination name", - "examples": [ - "MyQueue", - "MyTopic" - ], - "requirement_level": "recommended", - "note": "Destination name SHOULD uniquely identify a specific queue, topic or other entity within the broker. If\nthe broker doesn't have such notion, the destination name SHOULD uniquely identify the broker.\n", - "stability": "stable" - }, - { - "name": "messaging.destination.name", - "type": "string", - "brief": "The message destination name", - "examples": [ - "MyQueue", - "MyTopic" - ], - "requirement_level": { - "conditionally_required": "if and only if `messaging.destination.name` is known to have low cardinality. Otherwise, `messaging.destination.template` MAY be populated." +{ + "attributes": [ + { + "name": "messaging.batch.message_count", + "type": "int", + "brief": "The number of messages sent, received, or processed in the scope of the batching operation.", + "examples": [ + 0, + 1, + 2 + ], + "requirement_level": "recommended", + "note": "Instrumentations SHOULD NOT set `messaging.batch.message_count` on spans that operate with a single message. When a messaging client library supports both batch and single-message API for the same operation, instrumentations SHOULD use `messaging.batch.message_count` for batching APIs and SHOULD NOT use it for single-message APIs.\n", + "stability": "stable" + }, + { + "name": "messaging.client_id", + "type": "string", + "brief": "A unique identifier for the client that consumes or produces a message.\n", + "examples": [ + "client-5", + "myhost@8742@s8083jm" + ], + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "messaging.destination.anonymous", + "type": "boolean", + "brief": "A boolean that is true if the message destination is anonymous (could be unnamed or have auto-generated name).", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "messaging.destination.name", + "type": "string", + "brief": "The message destination name", + "examples": [ + "MyQueue", + "MyTopic" + ], + "requirement_level": "recommended", + "note": "Destination name SHOULD uniquely identify a specific queue, topic or other entity within the broker. If\nthe broker doesn't have such notion, the destination name SHOULD uniquely identify the broker.\n", + "stability": "stable" + }, + { + "name": "messaging.destination.name", + "type": "string", + "brief": "The message destination name", + "examples": [ + "MyQueue", + "MyTopic" + ], + "requirement_level": { + "conditionally_required": "if and only if `messaging.destination.name` is known to have low cardinality. Otherwise, `messaging.destination.template` MAY be populated." + }, + "note": "Destination name SHOULD uniquely identify a specific queue, topic or other entity within the broker. If\nthe broker doesn't have such notion, the destination name SHOULD uniquely identify the broker.\n", + "stability": "stable" + }, + { + "name": "messaging.destination.template", + "type": "string", + "brief": "Low cardinality representation of the messaging destination name", + "examples": [ + "/customers/{customerId}" + ], + "requirement_level": "recommended", + "note": "Destination names could be constructed from templates. An example would be a destination name involving a user name or product id. Although the destination name in this case is of high cardinality, the underlying template is of low cardinality and can be effectively used for grouping and aggregation.\n", + "stability": "stable" + }, + { + "name": "messaging.destination.template", + "type": "string", + "brief": "Low cardinality representation of the messaging destination name", + "examples": [ + "/customers/{customerId}" + ], + "requirement_level": { + "conditionally_required": "if available." + }, + "note": "Destination names could be constructed from templates. An example would be a destination name involving a user name or product id. Although the destination name in this case is of high cardinality, the underlying template is of low cardinality and can be effectively used for grouping and aggregation.\n", + "stability": "stable" + }, + { + "name": "messaging.destination.temporary", + "type": "boolean", + "brief": "A boolean that is true if the message destination is temporary and might not exist anymore after messages are processed.", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "messaging.destination_publish.anonymous", + "type": "boolean", + "brief": "A boolean that is true if the publish message destination is anonymous (could be unnamed or have auto-generated name).", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "messaging.destination_publish.name", + "type": "string", + "brief": "The name of the original destination the message was published to", + "examples": [ + "MyQueue", + "MyTopic" + ], + "requirement_level": "recommended", + "note": "The name SHOULD uniquely identify a specific queue, topic, or other entity within the broker. If\nthe broker doesn't have such notion, the original destination name SHOULD uniquely identify the broker.\n", + "stability": "stable" }, - "note": "Destination name SHOULD uniquely identify a specific queue, topic or other entity within the broker. If\nthe broker doesn't have such notion, the destination name SHOULD uniquely identify the broker.\n", - "stability": "stable" - }, - { - "name": "messaging.destination.template", - "type": "string", - "brief": "Low cardinality representation of the messaging destination name", - "examples": [ - "/customers/{customerId}" - ], - "requirement_level": "recommended", - "note": "Destination names could be constructed from templates. An example would be a destination name involving a user name or product id. Although the destination name in this case is of high cardinality, the underlying template is of low cardinality and can be effectively used for grouping and aggregation.\n", - "stability": "stable" - }, - { - "name": "messaging.destination.template", - "type": "string", - "brief": "Low cardinality representation of the messaging destination name", - "examples": [ - "/customers/{customerId}" - ], - "requirement_level": { - "conditionally_required": "if available." + { + "name": "messaging.gcp_pubsub.message.ordering_key", + "type": "string", + "brief": "The ordering key for a given message. If the attribute is not present, the message does not have an ordering key.\n", + "examples": "ordering_key", + "requirement_level": "recommended", + "stability": "stable" }, - "note": "Destination names could be constructed from templates. An example would be a destination name involving a user name or product id. Although the destination name in this case is of high cardinality, the underlying template is of low cardinality and can be effectively used for grouping and aggregation.\n", - "stability": "stable" - }, - { - "name": "messaging.destination.temporary", - "type": "boolean", - "brief": "A boolean that is true if the message destination is temporary and might not exist anymore after messages are processed.", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "messaging.destination_publish.anonymous", - "type": "boolean", - "brief": "A boolean that is true if the publish message destination is anonymous (could be unnamed or have auto-generated name).", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "messaging.destination_publish.name", - "type": "string", - "brief": "The name of the original destination the message was published to", - "examples": [ - "MyQueue", - "MyTopic" - ], - "requirement_level": "recommended", - "note": "The name SHOULD uniquely identify a specific queue, topic, or other entity within the broker. If\nthe broker doesn't have such notion, the original destination name SHOULD uniquely identify the broker.\n", - "stability": "stable" - }, - { - "name": "messaging.gcp_pubsub.message.ordering_key", - "type": "string", - "brief": "The ordering key for a given message. If the attribute is not present, the message does not have an ordering key.\n", - "examples": "ordering_key", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "messaging.kafka.consumer.group", - "type": "string", - "brief": "Name of the Kafka Consumer Group that is handling the message. Only applies to consumers, not producers.\n", - "examples": "my-group", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "messaging.kafka.destination.partition", - "type": "int", - "brief": "Partition the message is sent to.\n", - "examples": 2, - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "messaging.kafka.message.key", - "type": "string", - "brief": "Message keys in Kafka are used for grouping alike messages to ensure they're processed on the same partition. They differ from `messaging.message.id` in that they're not unique. If the key is `null`, the attribute MUST NOT be set.\n", - "examples": "myKey", - "requirement_level": "recommended", - "note": "If the key type is not string, it's string representation has to be supplied for the attribute. If the key has no unambiguous, canonical string form, don't include its value.\n", - "stability": "stable" - }, - { - "name": "messaging.kafka.message.offset", - "type": "int", - "brief": "The offset of a record in the corresponding Kafka partition.\n", - "examples": 42, - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "messaging.kafka.message.tombstone", - "type": "boolean", - "brief": "A boolean that is true if the message is a tombstone.", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "messaging.message.body.size", - "type": "int", - "brief": "The size of the message body in bytes.\n", - "examples": 1439, - "requirement_level": "recommended", - "note": "This can refer to both the compressed or uncompressed body size. If both sizes are known, the uncompressed\nbody size should be used.\n", - "stability": "stable" - }, - { - "name": "messaging.message.conversation_id", - "type": "string", - "brief": "The conversation ID identifying the conversation to which the message belongs, represented as a string. Sometimes called \"Correlation ID\".\n", - "examples": "MyConversationId", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "messaging.message.envelope.size", - "type": "int", - "brief": "The size of the message body and metadata in bytes.\n", - "examples": 2738, - "requirement_level": "recommended", - "note": "This can refer to both the compressed or uncompressed size. If both sizes are known, the uncompressed\nsize should be used.\n", - "stability": "stable" - }, - { - "name": "messaging.message.id", - "type": "string", - "brief": "A value used by the messaging system as an identifier for the message, represented as a string.", - "examples": "452a7c7c7c7048c2f887f61572b18fc2", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "messaging.operation", - "type": { - "members": [ - { - "id": "publish", - "value": "publish", - "brief": "One or more messages are provided for publishing to an intermediary. If a single message is published, the context of the \"Publish\" span can be used as the creation context and no \"Create\" span needs to be created.\n", - "stability": "stable" - }, - { - "id": "create", - "value": "create", - "brief": "A message is created. \"Create\" spans always refer to a single message and are used to provide a unique creation context for messages in batch publishing scenarios.\n", - "stability": "stable" - }, - { - "id": "receive", - "value": "receive", - "brief": "One or more messages are requested by a consumer. This operation refers to pull-based scenarios, where consumers explicitly call methods of messaging SDKs to receive messages.\n", - "stability": "stable" - }, - { - "id": "deliver", - "value": "deliver", - "brief": "One or more messages are passed to a consumer. This operation refers to push-based scenarios, where consumer register callbacks which get called by messaging SDKs.\n", - "stability": "stable" - } - ] + { + "name": "messaging.kafka.consumer.group", + "type": "string", + "brief": "Name of the Kafka Consumer Group that is handling the message. Only applies to consumers, not producers.\n", + "examples": "my-group", + "requirement_level": "recommended", + "stability": "stable" }, - "brief": "A string identifying the kind of messaging operation.\n", - "requirement_level": "recommended", - "note": "If a custom value is used, it MUST be of low cardinality.", - "stability": "stable" - }, - { - "name": "messaging.rabbitmq.destination.routing_key", - "type": "string", - "brief": "RabbitMQ message routing key.\n", - "examples": "myKey", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "messaging.rocketmq.client_group", - "type": "string", - "brief": "Name of the RocketMQ producer/consumer group that is handling the message. The client type is identified by the SpanKind.\n", - "examples": "myConsumerGroup", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "messaging.rocketmq.consumption_model", - "type": { - "members": [ - { - "id": "clustering", - "value": "clustering", - "brief": "Clustering consumption model", - "stability": "stable" - }, - { - "id": "broadcasting", - "value": "broadcasting", - "brief": "Broadcasting consumption model", - "stability": "stable" - } - ] + { + "name": "messaging.kafka.destination.partition", + "type": "int", + "brief": "Partition the message is sent to.\n", + "examples": 2, + "requirement_level": "recommended", + "stability": "stable" }, - "brief": "Model of message consumption. This only applies to consumer spans.\n", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "messaging.rocketmq.message.delay_time_level", - "type": "int", - "brief": "The delay time level for delay message, which determines the message delay time.\n", - "examples": 3, - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "messaging.rocketmq.message.delivery_timestamp", - "type": "int", - "brief": "The timestamp in milliseconds that the delay message is expected to be delivered to consumer.\n", - "examples": 1665987217045, - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "messaging.rocketmq.message.group", - "type": "string", - "brief": "It is essential for FIFO message. Messages that belong to the same message group are always processed one by one within the same consumer group.\n", - "examples": "myMessageGroup", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "messaging.rocketmq.message.keys", - "type": "string[]", - "brief": "Key(s) of message, another way to mark message besides message id.\n", - "examples": [ - [ - "keyA" + { + "name": "messaging.kafka.message.key", + "type": "string", + "brief": "Message keys in Kafka are used for grouping alike messages to ensure they're processed on the same partition. They differ from `messaging.message.id` in that they're not unique. If the key is `null`, the attribute MUST NOT be set.\n", + "examples": "myKey", + "requirement_level": "recommended", + "note": "If the key type is not string, it's string representation has to be supplied for the attribute. If the key has no unambiguous, canonical string form, don't include its value.\n", + "stability": "stable" + }, + { + "name": "messaging.kafka.message.offset", + "type": "int", + "brief": "The offset of a record in the corresponding Kafka partition.\n", + "examples": 42, + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "messaging.kafka.message.tombstone", + "type": "boolean", + "brief": "A boolean that is true if the message is a tombstone.", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "messaging.message.body.size", + "type": "int", + "brief": "The size of the message body in bytes.\n", + "examples": 1439, + "requirement_level": "recommended", + "note": "This can refer to both the compressed or uncompressed body size. If both sizes are known, the uncompressed\nbody size should be used.\n", + "stability": "stable" + }, + { + "name": "messaging.message.conversation_id", + "type": "string", + "brief": "The conversation ID identifying the conversation to which the message belongs, represented as a string. Sometimes called \"Correlation ID\".\n", + "examples": "MyConversationId", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "messaging.message.envelope.size", + "type": "int", + "brief": "The size of the message body and metadata in bytes.\n", + "examples": 2738, + "requirement_level": "recommended", + "note": "This can refer to both the compressed or uncompressed size. If both sizes are known, the uncompressed\nsize should be used.\n", + "stability": "stable" + }, + { + "name": "messaging.message.id", + "type": "string", + "brief": "A value used by the messaging system as an identifier for the message, represented as a string.", + "examples": "452a7c7c7c7048c2f887f61572b18fc2", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "messaging.operation", + "type": { + "members": [ + { + "id": "publish", + "value": "publish", + "brief": "One or more messages are provided for publishing to an intermediary. If a single message is published, the context of the \"Publish\" span can be used as the creation context and no \"Create\" span needs to be created.\n", + "stability": "stable" + }, + { + "id": "create", + "value": "create", + "brief": "A message is created. \"Create\" spans always refer to a single message and are used to provide a unique creation context for messages in batch publishing scenarios.\n", + "stability": "stable" + }, + { + "id": "receive", + "value": "receive", + "brief": "One or more messages are requested by a consumer. This operation refers to pull-based scenarios, where consumers explicitly call methods of messaging SDKs to receive messages.\n", + "stability": "stable" + }, + { + "id": "deliver", + "value": "deliver", + "brief": "One or more messages are passed to a consumer. This operation refers to push-based scenarios, where consumer register callbacks which get called by messaging SDKs.\n", + "stability": "stable" + } + ] + }, + "brief": "A string identifying the kind of messaging operation.\n", + "requirement_level": "recommended", + "note": "If a custom value is used, it MUST be of low cardinality.", + "stability": "stable" + }, + { + "name": "messaging.rabbitmq.destination.routing_key", + "type": "string", + "brief": "RabbitMQ message routing key.\n", + "examples": "myKey", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "messaging.rocketmq.client_group", + "type": "string", + "brief": "Name of the RocketMQ producer/consumer group that is handling the message. The client type is identified by the SpanKind.\n", + "examples": "myConsumerGroup", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "messaging.rocketmq.consumption_model", + "type": { + "members": [ + { + "id": "clustering", + "value": "clustering", + "brief": "Clustering consumption model", + "stability": "stable" + }, + { + "id": "broadcasting", + "value": "broadcasting", + "brief": "Broadcasting consumption model", + "stability": "stable" + } + ] + }, + "brief": "Model of message consumption. This only applies to consumer spans.\n", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "messaging.rocketmq.message.delay_time_level", + "type": "int", + "brief": "The delay time level for delay message, which determines the message delay time.\n", + "examples": 3, + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "messaging.rocketmq.message.delivery_timestamp", + "type": "int", + "brief": "The timestamp in milliseconds that the delay message is expected to be delivered to consumer.\n", + "examples": 1665987217045, + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "messaging.rocketmq.message.group", + "type": "string", + "brief": "It is essential for FIFO message. Messages that belong to the same message group are always processed one by one within the same consumer group.\n", + "examples": "myMessageGroup", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "messaging.rocketmq.message.keys", + "type": "string[]", + "brief": "Key(s) of message, another way to mark message besides message id.\n", + "examples": [ + [ + "keyA" + ], + [ + "keyB" + ] ], - [ - "keyB" - ] - ], - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "messaging.rocketmq.message.tag", - "type": "string", - "brief": "The secondary classifier of message besides topic.\n", - "examples": "tagA", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "messaging.rocketmq.message.type", - "type": { - "members": [ - { - "id": "normal", - "value": "normal", - "brief": "Normal message", - "stability": "stable" - }, - { - "id": "fifo", - "value": "fifo", - "brief": "FIFO message", - "stability": "stable" - }, - { - "id": "delay", - "value": "delay", - "brief": "Delay message", - "stability": "stable" - }, - { - "id": "transaction", - "value": "transaction", - "brief": "Transaction message", - "stability": "stable" - } - ] + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "messaging.rocketmq.message.tag", + "type": "string", + "brief": "The secondary classifier of message besides topic.\n", + "examples": "tagA", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "messaging.rocketmq.message.type", + "type": { + "members": [ + { + "id": "normal", + "value": "normal", + "brief": "Normal message", + "stability": "stable" + }, + { + "id": "fifo", + "value": "fifo", + "brief": "FIFO message", + "stability": "stable" + }, + { + "id": "delay", + "value": "delay", + "brief": "Delay message", + "stability": "stable" + }, + { + "id": "transaction", + "value": "transaction", + "brief": "Transaction message", + "stability": "stable" + } + ] + }, + "brief": "Type of message.\n", + "requirement_level": "recommended", + "stability": "stable" }, - "brief": "Type of message.\n", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "messaging.rocketmq.namespace", - "type": "string", - "brief": "Namespace of RocketMQ resources, resources in different namespaces are individual.\n", - "examples": "myNamespace", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "messaging.system", - "type": { - "members": [ - { - "id": "activemq", - "value": "activemq", - "brief": "Apache ActiveMQ", - "stability": "stable" - }, - { - "id": "aws_sqs", - "value": "aws_sqs", - "brief": "Amazon Simple Queue Service (SQS)", - "stability": "stable" - }, - { - "id": "azure_eventgrid", - "value": "azure_eventgrid", - "brief": "Azure Event Grid", - "stability": "stable" - }, - { - "id": "azure_eventhubs", - "value": "azure_eventhubs", - "brief": "Azure Event Hubs", - "stability": "stable" - }, - { - "id": "azure_servicebus", - "value": "azure_servicebus", - "brief": "Azure Service Bus", - "stability": "stable" - }, - { - "id": "gcp_pubsub", - "value": "gcp_pubsub", - "brief": "Google Cloud Pub/Sub", - "stability": "stable" - }, - { - "id": "jms", - "value": "jms", - "brief": "Java Message Service", - "stability": "stable" - }, - { - "id": "kafka", - "value": "kafka", - "brief": "Apache Kafka", - "stability": "stable" - }, - { - "id": "rabbitmq", - "value": "rabbitmq", - "brief": "RabbitMQ", - "stability": "stable" - }, - { - "id": "rocketmq", - "value": "rocketmq", - "brief": "Apache RocketMQ", - "stability": "stable" - } - ] + { + "name": "messaging.rocketmq.namespace", + "type": "string", + "brief": "Namespace of RocketMQ resources, resources in different namespaces are individual.\n", + "examples": "myNamespace", + "requirement_level": "recommended", + "stability": "stable" }, - "brief": "An identifier for the messaging system being used. See below for a list of well-known identifiers.\n", - "requirement_level": "recommended", - "stability": "stable" - } -] \ No newline at end of file + { + "name": "messaging.system", + "type": { + "members": [ + { + "id": "activemq", + "value": "activemq", + "brief": "Apache ActiveMQ", + "stability": "stable" + }, + { + "id": "aws_sqs", + "value": "aws_sqs", + "brief": "Amazon Simple Queue Service (SQS)", + "stability": "stable" + }, + { + "id": "azure_eventgrid", + "value": "azure_eventgrid", + "brief": "Azure Event Grid", + "stability": "stable" + }, + { + "id": "azure_eventhubs", + "value": "azure_eventhubs", + "brief": "Azure Event Hubs", + "stability": "stable" + }, + { + "id": "azure_servicebus", + "value": "azure_servicebus", + "brief": "Azure Service Bus", + "stability": "stable" + }, + { + "id": "gcp_pubsub", + "value": "gcp_pubsub", + "brief": "Google Cloud Pub/Sub", + "stability": "stable" + }, + { + "id": "jms", + "value": "jms", + "brief": "Java Message Service", + "stability": "stable" + }, + { + "id": "kafka", + "value": "kafka", + "brief": "Apache Kafka", + "stability": "stable" + }, + { + "id": "rabbitmq", + "value": "rabbitmq", + "brief": "RabbitMQ", + "stability": "stable" + }, + { + "id": "rocketmq", + "value": "rocketmq", + "brief": "Apache RocketMQ", + "stability": "stable" + } + ] + }, + "brief": "An identifier for the messaging system being used. See below for a list of well-known identifiers.\n", + "requirement_level": "recommended", + "stability": "stable" + } + ] +} \ No newline at end of file diff --git a/crates/weaver_resolver/data/registry-test-3-extends/expected-attribute-catalog.json b/crates/weaver_resolver/data/registry-test-3-extends/expected-attribute-catalog.json index 2b2d1349d..f3c429525 100644 --- a/crates/weaver_resolver/data/registry-test-3-extends/expected-attribute-catalog.json +++ b/crates/weaver_resolver/data/registry-test-3-extends/expected-attribute-catalog.json @@ -1,1418 +1,1420 @@ -[ - { - "name": "error.type", - "type": { - "members": [ - { - "id": "other", - "value": "_OTHER", - "brief": "A fallback error value to be used when the instrumentation doesn't define a custom value.\n", - "stability": "stable" - } - ] - }, - "brief": "Describes a class of error the operation ended with.\n", - "examples": [ - "amqp:decode-error", - "KAFKA_STORAGE_ERROR", - "channel-error" - ], - "requirement_level": { - "conditionally_required": "If and only if the messaging operation has failed." - }, - "note": "The `error.type` SHOULD be predictable and SHOULD have low cardinality.\nInstrumentations SHOULD document the list of errors they report.\n\nThe cardinality of `error.type` within one instrumentation library SHOULD be low.\nTelemetry consumers that aggregate data from multiple instrumentation libraries and applications\nshould be prepared for `error.type` to have high cardinality at query time when no\nadditional filters are applied.\n\nIf the operation has completed successfully, instrumentations SHOULD NOT set `error.type`.\n\nIf a specific domain defines its own set of error identifiers (such as HTTP or gRPC status codes),\nit's RECOMMENDED to:\n\n* Use a domain-specific attribute\n* Set `error.type` to capture all errors, regardless of whether they are defined within the domain-specific set or not\n\nAnd something more.", - "stability": "stable" - }, - { - "name": "error.type", - "type": { - "members": [ - { - "id": "other", - "value": "_OTHER", - "brief": "A fallback error value to be used when the instrumentation doesn't define a custom value.\n", - "stability": "stable" - } - ] - }, - "brief": "Describes a class of error the operation ended with.\n", - "examples": [ - "timeout", - "java.net.UnknownHostException", - "server_certificate_invalid", - "500" - ], - "requirement_level": "recommended", - "note": "The `error.type` SHOULD be predictable and SHOULD have low cardinality.\nInstrumentations SHOULD document the list of errors they report.\n\nThe cardinality of `error.type` within one instrumentation library SHOULD be low.\nTelemetry consumers that aggregate data from multiple instrumentation libraries and applications\nshould be prepared for `error.type` to have high cardinality at query time when no\nadditional filters are applied.\n\nIf the operation has completed successfully, instrumentations SHOULD NOT set `error.type`.\n\nIf a specific domain defines its own set of error identifiers (such as HTTP or gRPC status codes),\nit's RECOMMENDED to:\n\n* Use a domain-specific attribute\n* Set `error.type` to capture all errors, regardless of whether they are defined within the domain-specific set or not\n\nAnd something more.", - "stability": "stable" - }, - { - "name": "error.type", - "type": { - "members": [ - { - "id": "other", - "value": "_OTHER", - "brief": "A fallback error value to be used when the instrumentation doesn't define a custom value.\n", - "stability": "stable" - } - ] - }, - "brief": "Describes a class of error the operation ended with.\n", - "examples": [ - "timeout", - "java.net.UnknownHostException", - "server_certificate_invalid", - "500" - ], - "requirement_level": { - "conditionally_required": "If request has ended with an error." - }, - "note": "If the request fails with an error before response status code was sent or received,\n`error.type` SHOULD be set to exception type (its fully-qualified class name, if applicable)\nor a component-specific low cardinality error identifier.\n\nIf response status code was sent or received and status indicates an error according to [HTTP span status definition](/docs/http/http-spans.md),\n`error.type` SHOULD be set to the status code number (represented as a string), an exception type (if thrown) or a component-specific error identifier.\n\nThe `error.type` value SHOULD be predictable and SHOULD have low cardinality.\nInstrumentations SHOULD document the list of errors they report.\n\nThe cardinality of `error.type` within one instrumentation library SHOULD be low, but\ntelemetry consumers that aggregate data from multiple instrumentation libraries and applications\nshould be prepared for `error.type` to have high cardinality at query time, when no\nadditional filters are applied.\n\nIf the request has completed successfully, instrumentations SHOULD NOT set `error.type`.\n", - "stability": "stable" - }, - { - "name": "http.request.body.size", - "type": "int", - "brief": "The size of the request payload body in bytes. This is the number of bytes transferred excluding headers and is often, but not always, present as the [Content-Length](https://www.rfc-editor.org/rfc/rfc9110.html#field.content-length) header. For requests using transport encoding, this should be the compressed size.\n", - "examples": 3495, - "requirement_level": "recommended", - "stability": "development" - }, - { - "name": "http.request.header", - "type": "template[string[]]", - "brief": "HTTP request headers, `` being the normalized HTTP Header name (lowercase), the value being the header values.\n", - "examples": [ - [ - "application/json" +{ + "attributes": [ + { + "name": "error.type", + "type": { + "members": [ + { + "id": "other", + "value": "_OTHER", + "brief": "A fallback error value to be used when the instrumentation doesn't define a custom value.\n", + "stability": "stable" + } + ] + }, + "brief": "Describes a class of error the operation ended with.\n", + "examples": [ + "amqp:decode-error", + "KAFKA_STORAGE_ERROR", + "channel-error" ], - [ - "1.2.3.4", - "1.2.3.5" - ] - ], - "requirement_level": "recommended", - "note": "Instrumentations SHOULD require an explicit configuration of which headers are to be captured. Including all request headers can be a security risk - explicit configuration helps avoid leaking sensitive information.\nThe `User-Agent` header is already captured in the `user_agent.original` attribute. Users MAY explicitly configure instrumentations to capture them even though it is not recommended.\nThe attribute value MUST consist of either multiple header values as an array of strings or a single-item array containing a possibly comma-concatenated string, depending on the way the HTTP library provides access to headers.\n", - "stability": "stable" - }, - { - "name": "http.request.method", - "type": { - "members": [ - { - "id": "connect", - "value": "CONNECT", - "brief": "CONNECT method.", - "stability": "stable" - }, - { - "id": "delete", - "value": "DELETE", - "brief": "DELETE method.", - "stability": "stable" - }, - { - "id": "get", - "value": "GET", - "brief": "GET method.", - "stability": "stable" - }, - { - "id": "head", - "value": "HEAD", - "brief": "HEAD method.", - "stability": "stable" - }, - { - "id": "options", - "value": "OPTIONS", - "brief": "OPTIONS method.", - "stability": "stable" - }, - { - "id": "patch", - "value": "PATCH", - "brief": "PATCH method.", - "stability": "stable" - }, - { - "id": "post", - "value": "POST", - "brief": "POST method.", - "stability": "stable" - }, - { - "id": "put", - "value": "PUT", - "brief": "PUT method.", - "stability": "stable" - }, - { - "id": "trace", - "value": "TRACE", - "brief": "TRACE method.", - "stability": "stable" - }, - { - "id": "other", - "value": "_OTHER", - "brief": "Any HTTP method that the instrumentation has no prior knowledge of.", - "stability": "stable" - } - ] - }, - "brief": "HTTP request method.", - "examples": [ - "GET", - "POST", - "HEAD" - ], - "requirement_level": "required", - "note": "HTTP request method value SHOULD be \"known\" to the instrumentation.\nBy default, this convention defines \"known\" methods as the ones listed in [RFC9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-methods)\nand the PATCH method defined in [RFC5789](https://www.rfc-editor.org/rfc/rfc5789.html).\n\nIf the HTTP request method is not known to instrumentation, it MUST set the `http.request.method` attribute to `_OTHER`.\n\nIf the HTTP instrumentation could end up converting valid HTTP request methods to `_OTHER`, then it MUST provide a way to override\nthe list of known HTTP methods. If this override is done via environment variable, then the environment variable MUST be named\nOTEL_INSTRUMENTATION_HTTP_KNOWN_METHODS and support a comma-separated list of case-sensitive known HTTP methods\n(this list MUST be a full override of the default known method, it is not a list of known methods in addition to the defaults).\n\nHTTP method names are case-sensitive and `http.request.method` attribute value MUST match a known HTTP method name exactly.\nInstrumentations for specific web frameworks that consider HTTP methods to be case insensitive, SHOULD populate a canonical equivalent.\nTracing instrumentations that do so, MUST also set `http.request.method_original` to the original value.\n", - "stability": "stable" - }, - { - "name": "http.request.method", - "type": { - "members": [ - { - "id": "connect", - "value": "CONNECT", - "brief": "CONNECT method.", - "stability": "stable" - }, - { - "id": "delete", - "value": "DELETE", - "brief": "DELETE method.", - "stability": "stable" - }, - { - "id": "get", - "value": "GET", - "brief": "GET method.", - "stability": "stable" - }, - { - "id": "head", - "value": "HEAD", - "brief": "HEAD method.", - "stability": "stable" - }, - { - "id": "options", - "value": "OPTIONS", - "brief": "OPTIONS method.", - "stability": "stable" - }, - { - "id": "patch", - "value": "PATCH", - "brief": "PATCH method.", - "stability": "stable" - }, - { - "id": "post", - "value": "POST", - "brief": "POST method.", - "stability": "stable" - }, - { - "id": "put", - "value": "PUT", - "brief": "PUT method.", - "stability": "stable" - }, - { - "id": "trace", - "value": "TRACE", - "brief": "TRACE method.", - "stability": "stable" - }, - { - "id": "other", - "value": "_OTHER", - "brief": "Any HTTP method that the instrumentation has no prior knowledge of.", - "stability": "stable" - } - ] - }, - "brief": "HTTP request method.", - "examples": [ - "GET", - "POST", - "HEAD" - ], - "requirement_level": "recommended", - "note": "HTTP request method value SHOULD be \"known\" to the instrumentation.\nBy default, this convention defines \"known\" methods as the ones listed in [RFC9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-methods)\nand the PATCH method defined in [RFC5789](https://www.rfc-editor.org/rfc/rfc5789.html).\n\nIf the HTTP request method is not known to instrumentation, it MUST set the `http.request.method` attribute to `_OTHER`.\n\nIf the HTTP instrumentation could end up converting valid HTTP request methods to `_OTHER`, then it MUST provide a way to override\nthe list of known HTTP methods. If this override is done via environment variable, then the environment variable MUST be named\nOTEL_INSTRUMENTATION_HTTP_KNOWN_METHODS and support a comma-separated list of case-sensitive known HTTP methods\n(this list MUST be a full override of the default known method, it is not a list of known methods in addition to the defaults).\n\nHTTP method names are case-sensitive and `http.request.method` attribute value MUST match a known HTTP method name exactly.\nInstrumentations for specific web frameworks that consider HTTP methods to be case insensitive, SHOULD populate a canonical equivalent.\nTracing instrumentations that do so, MUST also set `http.request.method_original` to the original value.\n", - "stability": "stable" - }, - { - "name": "http.request.method_original", - "type": "string", - "brief": "Original HTTP method sent by the client in the request line.", - "examples": [ - "GeT", - "ACL", - "foo" - ], - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "http.request.resend_count", - "type": "int", - "brief": "The ordinal number of request resending attempt (for any reason, including redirects).\n", - "examples": 3, - "requirement_level": "recommended", - "note": "The resend count SHOULD be updated each time an HTTP request gets resent by the client, regardless of what was the cause of the resending (e.g. redirection, authorization failure, 503 Server Unavailable, network issues, or any other).\n", - "stability": "stable" - }, - { - "name": "http.response.body.size", - "type": "int", - "brief": "The size of the response payload body in bytes. This is the number of bytes transferred excluding headers and is often, but not always, present as the [Content-Length](https://www.rfc-editor.org/rfc/rfc9110.html#field.content-length) header. For requests using transport encoding, this should be the compressed size.\n", - "examples": 3495, - "requirement_level": "recommended", - "stability": "development" - }, - { - "name": "http.response.header", - "type": "template[string[]]", - "brief": "HTTP response headers, `` being the normalized HTTP Header name (lowercase), the value being the header values.\n", - "examples": [ - [ - "application/json" + "requirement_level": { + "conditionally_required": "If and only if the messaging operation has failed." + }, + "note": "The `error.type` SHOULD be predictable and SHOULD have low cardinality.\nInstrumentations SHOULD document the list of errors they report.\n\nThe cardinality of `error.type` within one instrumentation library SHOULD be low.\nTelemetry consumers that aggregate data from multiple instrumentation libraries and applications\nshould be prepared for `error.type` to have high cardinality at query time when no\nadditional filters are applied.\n\nIf the operation has completed successfully, instrumentations SHOULD NOT set `error.type`.\n\nIf a specific domain defines its own set of error identifiers (such as HTTP or gRPC status codes),\nit's RECOMMENDED to:\n\n* Use a domain-specific attribute\n* Set `error.type` to capture all errors, regardless of whether they are defined within the domain-specific set or not\n\nAnd something more.", + "stability": "stable" + }, + { + "name": "error.type", + "type": { + "members": [ + { + "id": "other", + "value": "_OTHER", + "brief": "A fallback error value to be used when the instrumentation doesn't define a custom value.\n", + "stability": "stable" + } + ] + }, + "brief": "Describes a class of error the operation ended with.\n", + "examples": [ + "timeout", + "java.net.UnknownHostException", + "server_certificate_invalid", + "500" + ], + "requirement_level": "recommended", + "note": "The `error.type` SHOULD be predictable and SHOULD have low cardinality.\nInstrumentations SHOULD document the list of errors they report.\n\nThe cardinality of `error.type` within one instrumentation library SHOULD be low.\nTelemetry consumers that aggregate data from multiple instrumentation libraries and applications\nshould be prepared for `error.type` to have high cardinality at query time when no\nadditional filters are applied.\n\nIf the operation has completed successfully, instrumentations SHOULD NOT set `error.type`.\n\nIf a specific domain defines its own set of error identifiers (such as HTTP or gRPC status codes),\nit's RECOMMENDED to:\n\n* Use a domain-specific attribute\n* Set `error.type` to capture all errors, regardless of whether they are defined within the domain-specific set or not\n\nAnd something more.", + "stability": "stable" + }, + { + "name": "error.type", + "type": { + "members": [ + { + "id": "other", + "value": "_OTHER", + "brief": "A fallback error value to be used when the instrumentation doesn't define a custom value.\n", + "stability": "stable" + } + ] + }, + "brief": "Describes a class of error the operation ended with.\n", + "examples": [ + "timeout", + "java.net.UnknownHostException", + "server_certificate_invalid", + "500" + ], + "requirement_level": { + "conditionally_required": "If request has ended with an error." + }, + "note": "If the request fails with an error before response status code was sent or received,\n`error.type` SHOULD be set to exception type (its fully-qualified class name, if applicable)\nor a component-specific low cardinality error identifier.\n\nIf response status code was sent or received and status indicates an error according to [HTTP span status definition](/docs/http/http-spans.md),\n`error.type` SHOULD be set to the status code number (represented as a string), an exception type (if thrown) or a component-specific error identifier.\n\nThe `error.type` value SHOULD be predictable and SHOULD have low cardinality.\nInstrumentations SHOULD document the list of errors they report.\n\nThe cardinality of `error.type` within one instrumentation library SHOULD be low, but\ntelemetry consumers that aggregate data from multiple instrumentation libraries and applications\nshould be prepared for `error.type` to have high cardinality at query time, when no\nadditional filters are applied.\n\nIf the request has completed successfully, instrumentations SHOULD NOT set `error.type`.\n", + "stability": "stable" + }, + { + "name": "http.request.body.size", + "type": "int", + "brief": "The size of the request payload body in bytes. This is the number of bytes transferred excluding headers and is often, but not always, present as the [Content-Length](https://www.rfc-editor.org/rfc/rfc9110.html#field.content-length) header. For requests using transport encoding, this should be the compressed size.\n", + "examples": 3495, + "requirement_level": "recommended", + "stability": "development" + }, + { + "name": "http.request.header", + "type": "template[string[]]", + "brief": "HTTP request headers, `` being the normalized HTTP Header name (lowercase), the value being the header values.\n", + "examples": [ + [ + "application/json" + ], + [ + "1.2.3.4", + "1.2.3.5" + ] + ], + "requirement_level": "recommended", + "note": "Instrumentations SHOULD require an explicit configuration of which headers are to be captured. Including all request headers can be a security risk - explicit configuration helps avoid leaking sensitive information.\nThe `User-Agent` header is already captured in the `user_agent.original` attribute. Users MAY explicitly configure instrumentations to capture them even though it is not recommended.\nThe attribute value MUST consist of either multiple header values as an array of strings or a single-item array containing a possibly comma-concatenated string, depending on the way the HTTP library provides access to headers.\n", + "stability": "stable" + }, + { + "name": "http.request.method", + "type": { + "members": [ + { + "id": "connect", + "value": "CONNECT", + "brief": "CONNECT method.", + "stability": "stable" + }, + { + "id": "delete", + "value": "DELETE", + "brief": "DELETE method.", + "stability": "stable" + }, + { + "id": "get", + "value": "GET", + "brief": "GET method.", + "stability": "stable" + }, + { + "id": "head", + "value": "HEAD", + "brief": "HEAD method.", + "stability": "stable" + }, + { + "id": "options", + "value": "OPTIONS", + "brief": "OPTIONS method.", + "stability": "stable" + }, + { + "id": "patch", + "value": "PATCH", + "brief": "PATCH method.", + "stability": "stable" + }, + { + "id": "post", + "value": "POST", + "brief": "POST method.", + "stability": "stable" + }, + { + "id": "put", + "value": "PUT", + "brief": "PUT method.", + "stability": "stable" + }, + { + "id": "trace", + "value": "TRACE", + "brief": "TRACE method.", + "stability": "stable" + }, + { + "id": "other", + "value": "_OTHER", + "brief": "Any HTTP method that the instrumentation has no prior knowledge of.", + "stability": "stable" + } + ] + }, + "brief": "HTTP request method.", + "examples": [ + "GET", + "POST", + "HEAD" + ], + "requirement_level": "required", + "note": "HTTP request method value SHOULD be \"known\" to the instrumentation.\nBy default, this convention defines \"known\" methods as the ones listed in [RFC9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-methods)\nand the PATCH method defined in [RFC5789](https://www.rfc-editor.org/rfc/rfc5789.html).\n\nIf the HTTP request method is not known to instrumentation, it MUST set the `http.request.method` attribute to `_OTHER`.\n\nIf the HTTP instrumentation could end up converting valid HTTP request methods to `_OTHER`, then it MUST provide a way to override\nthe list of known HTTP methods. If this override is done via environment variable, then the environment variable MUST be named\nOTEL_INSTRUMENTATION_HTTP_KNOWN_METHODS and support a comma-separated list of case-sensitive known HTTP methods\n(this list MUST be a full override of the default known method, it is not a list of known methods in addition to the defaults).\n\nHTTP method names are case-sensitive and `http.request.method` attribute value MUST match a known HTTP method name exactly.\nInstrumentations for specific web frameworks that consider HTTP methods to be case insensitive, SHOULD populate a canonical equivalent.\nTracing instrumentations that do so, MUST also set `http.request.method_original` to the original value.\n", + "stability": "stable" + }, + { + "name": "http.request.method", + "type": { + "members": [ + { + "id": "connect", + "value": "CONNECT", + "brief": "CONNECT method.", + "stability": "stable" + }, + { + "id": "delete", + "value": "DELETE", + "brief": "DELETE method.", + "stability": "stable" + }, + { + "id": "get", + "value": "GET", + "brief": "GET method.", + "stability": "stable" + }, + { + "id": "head", + "value": "HEAD", + "brief": "HEAD method.", + "stability": "stable" + }, + { + "id": "options", + "value": "OPTIONS", + "brief": "OPTIONS method.", + "stability": "stable" + }, + { + "id": "patch", + "value": "PATCH", + "brief": "PATCH method.", + "stability": "stable" + }, + { + "id": "post", + "value": "POST", + "brief": "POST method.", + "stability": "stable" + }, + { + "id": "put", + "value": "PUT", + "brief": "PUT method.", + "stability": "stable" + }, + { + "id": "trace", + "value": "TRACE", + "brief": "TRACE method.", + "stability": "stable" + }, + { + "id": "other", + "value": "_OTHER", + "brief": "Any HTTP method that the instrumentation has no prior knowledge of.", + "stability": "stable" + } + ] + }, + "brief": "HTTP request method.", + "examples": [ + "GET", + "POST", + "HEAD" + ], + "requirement_level": "recommended", + "note": "HTTP request method value SHOULD be \"known\" to the instrumentation.\nBy default, this convention defines \"known\" methods as the ones listed in [RFC9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-methods)\nand the PATCH method defined in [RFC5789](https://www.rfc-editor.org/rfc/rfc5789.html).\n\nIf the HTTP request method is not known to instrumentation, it MUST set the `http.request.method` attribute to `_OTHER`.\n\nIf the HTTP instrumentation could end up converting valid HTTP request methods to `_OTHER`, then it MUST provide a way to override\nthe list of known HTTP methods. If this override is done via environment variable, then the environment variable MUST be named\nOTEL_INSTRUMENTATION_HTTP_KNOWN_METHODS and support a comma-separated list of case-sensitive known HTTP methods\n(this list MUST be a full override of the default known method, it is not a list of known methods in addition to the defaults).\n\nHTTP method names are case-sensitive and `http.request.method` attribute value MUST match a known HTTP method name exactly.\nInstrumentations for specific web frameworks that consider HTTP methods to be case insensitive, SHOULD populate a canonical equivalent.\nTracing instrumentations that do so, MUST also set `http.request.method_original` to the original value.\n", + "stability": "stable" + }, + { + "name": "http.request.method_original", + "type": "string", + "brief": "Original HTTP method sent by the client in the request line.", + "examples": [ + "GeT", + "ACL", + "foo" + ], + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "http.request.resend_count", + "type": "int", + "brief": "The ordinal number of request resending attempt (for any reason, including redirects).\n", + "examples": 3, + "requirement_level": "recommended", + "note": "The resend count SHOULD be updated each time an HTTP request gets resent by the client, regardless of what was the cause of the resending (e.g. redirection, authorization failure, 503 Server Unavailable, network issues, or any other).\n", + "stability": "stable" + }, + { + "name": "http.response.body.size", + "type": "int", + "brief": "The size of the response payload body in bytes. This is the number of bytes transferred excluding headers and is often, but not always, present as the [Content-Length](https://www.rfc-editor.org/rfc/rfc9110.html#field.content-length) header. For requests using transport encoding, this should be the compressed size.\n", + "examples": 3495, + "requirement_level": "recommended", + "stability": "development" + }, + { + "name": "http.response.header", + "type": "template[string[]]", + "brief": "HTTP response headers, `` being the normalized HTTP Header name (lowercase), the value being the header values.\n", + "examples": [ + [ + "application/json" + ], + [ + "abc", + "def" + ] + ], + "requirement_level": "recommended", + "note": "Instrumentations SHOULD require an explicit configuration of which headers are to be captured. Including all response headers can be a security risk - explicit configuration helps avoid leaking sensitive information.\nUsers MAY explicitly configure instrumentations to capture them even though it is not recommended.\nThe attribute value MUST consist of either multiple header values as an array of strings or a single-item array containing a possibly comma-concatenated string, depending on the way the HTTP library provides access to headers.\n", + "stability": "stable" + }, + { + "name": "http.response.status_code", + "type": "int", + "brief": "[HTTP response status code](https://tools.ietf.org/html/rfc7231#section-6).", + "examples": [ + 200 + ], + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "http.response.status_code", + "type": "int", + "brief": "[HTTP response status code](https://tools.ietf.org/html/rfc7231#section-6).", + "examples": [ + 200 + ], + "requirement_level": { + "conditionally_required": "If and only if one was received/sent." + }, + "stability": "stable" + }, + { + "name": "http.route", + "type": "string", + "brief": "The matched route, that is, the path template in the format used by the respective server framework.\n", + "examples": [ + "/users/:userID?", + "{controller}/{action}/{id?}" + ], + "requirement_level": "recommended", + "note": "MUST NOT be populated when this is not supported by the HTTP server framework as the route attribute should have low-cardinality and the URI path can NOT substitute it.\nSHOULD include the [application root](/docs/http/http-spans.md#http-server-definitions) if there is one.", + "stability": "stable" + }, + { + "name": "http.route", + "type": "string", + "brief": "The matched route, that is, the path template in the format used by the respective server framework.\n", + "examples": [ + "/users/:userID?", + "{controller}/{action}/{id?}" + ], + "requirement_level": { + "conditionally_required": "If and only if it's available" + }, + "note": "MUST NOT be populated when this is not supported by the HTTP server framework as the route attribute should have low-cardinality and the URI path can NOT substitute it.\nSHOULD include the [application root](/docs/http/http-spans.md#http-server-definitions) if there is one.", + "stability": "stable" + }, + { + "name": "messaging.batch.message_count", + "type": "int", + "brief": "The number of messages sent, received, or processed in the scope of the batching operation.", + "examples": [ + 0, + 1, + 2 + ], + "requirement_level": "recommended", + "note": "Instrumentations SHOULD NOT set `messaging.batch.message_count` on spans that operate with a single message. When a messaging client library supports both batch and single-message API for the same operation, instrumentations SHOULD use `messaging.batch.message_count` for batching APIs and SHOULD NOT use it for single-message APIs.\n", + "stability": "stable" + }, + { + "name": "messaging.client_id", + "type": "string", + "brief": "A unique identifier for the client that consumes or produces a message.\n", + "examples": [ + "client-5", + "myhost@8742@s8083jm" + ], + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "messaging.destination.anonymous", + "type": "boolean", + "brief": "A boolean that is true if the message destination is anonymous (could be unnamed or have auto-generated name).", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "messaging.destination.name", + "type": "string", + "brief": "The message destination name", + "examples": [ + "MyQueue", + "MyTopic" + ], + "requirement_level": "recommended", + "note": "Destination name SHOULD uniquely identify a specific queue, topic or other entity within the broker. If\nthe broker doesn't have such notion, the destination name SHOULD uniquely identify the broker.\n", + "stability": "stable" + }, + { + "name": "messaging.destination.name", + "type": "string", + "brief": "The message destination name", + "examples": [ + "MyQueue", + "MyTopic" + ], + "requirement_level": { + "conditionally_required": "if and only if `messaging.destination.name` is known to have low cardinality. Otherwise, `messaging.destination.template` MAY be populated." + }, + "note": "Destination name SHOULD uniquely identify a specific queue, topic or other entity within the broker. If\nthe broker doesn't have such notion, the destination name SHOULD uniquely identify the broker.\n", + "stability": "stable" + }, + { + "name": "messaging.destination.template", + "type": "string", + "brief": "Low cardinality representation of the messaging destination name", + "examples": [ + "/customers/{customerId}" + ], + "requirement_level": "recommended", + "note": "Destination names could be constructed from templates. An example would be a destination name involving a user name or product id. Although the destination name in this case is of high cardinality, the underlying template is of low cardinality and can be effectively used for grouping and aggregation.\n", + "stability": "stable" + }, + { + "name": "messaging.destination.template", + "type": "string", + "brief": "Low cardinality representation of the messaging destination name", + "examples": [ + "/customers/{customerId}" + ], + "requirement_level": { + "conditionally_required": "if available." + }, + "note": "Destination names could be constructed from templates. An example would be a destination name involving a user name or product id. Although the destination name in this case is of high cardinality, the underlying template is of low cardinality and can be effectively used for grouping and aggregation.\n", + "stability": "stable" + }, + { + "name": "messaging.destination.temporary", + "type": "boolean", + "brief": "A boolean that is true if the message destination is temporary and might not exist anymore after messages are processed.", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "messaging.destination_publish.anonymous", + "type": "boolean", + "brief": "A boolean that is true if the publish message destination is anonymous (could be unnamed or have auto-generated name).", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "messaging.destination_publish.name", + "type": "string", + "brief": "The name of the original destination the message was published to", + "examples": [ + "MyQueue", + "MyTopic" + ], + "requirement_level": "recommended", + "note": "The name SHOULD uniquely identify a specific queue, topic, or other entity within the broker. If\nthe broker doesn't have such notion, the original destination name SHOULD uniquely identify the broker.\n", + "stability": "stable" + }, + { + "name": "messaging.gcp_pubsub.message.ordering_key", + "type": "string", + "brief": "The ordering key for a given message. If the attribute is not present, the message does not have an ordering key.\n", + "examples": "ordering_key", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "messaging.kafka.consumer.group", + "type": "string", + "brief": "Name of the Kafka Consumer Group that is handling the message. Only applies to consumers, not producers.\n", + "examples": "my-group", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "messaging.kafka.destination.partition", + "type": "int", + "brief": "Partition the message is sent to.\n", + "examples": 2, + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "messaging.kafka.message.key", + "type": "string", + "brief": "Message keys in Kafka are used for grouping alike messages to ensure they're processed on the same partition. They differ from `messaging.message.id` in that they're not unique. If the key is `null`, the attribute MUST NOT be set.\n", + "examples": "myKey", + "requirement_level": "recommended", + "note": "If the key type is not string, it's string representation has to be supplied for the attribute. If the key has no unambiguous, canonical string form, don't include its value.\n", + "stability": "stable" + }, + { + "name": "messaging.kafka.message.offset", + "type": "int", + "brief": "The offset of a record in the corresponding Kafka partition.\n", + "examples": 42, + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "messaging.kafka.message.tombstone", + "type": "boolean", + "brief": "A boolean that is true if the message is a tombstone.", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "messaging.message.body.size", + "type": "int", + "brief": "The size of the message body in bytes.\n", + "examples": 1439, + "requirement_level": "recommended", + "note": "This can refer to both the compressed or uncompressed body size. If both sizes are known, the uncompressed\nbody size should be used.\n", + "stability": "stable" + }, + { + "name": "messaging.message.conversation_id", + "type": "string", + "brief": "The conversation ID identifying the conversation to which the message belongs, represented as a string. Sometimes called \"Correlation ID\".\n", + "examples": "MyConversationId", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "messaging.message.envelope.size", + "type": "int", + "brief": "The size of the message body and metadata in bytes.\n", + "examples": 2738, + "requirement_level": "recommended", + "note": "This can refer to both the compressed or uncompressed size. If both sizes are known, the uncompressed\nsize should be used.\n", + "stability": "stable" + }, + { + "name": "messaging.message.id", + "type": "string", + "brief": "A value used by the messaging system as an identifier for the message, represented as a string.", + "examples": "452a7c7c7c7048c2f887f61572b18fc2", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "messaging.operation", + "type": { + "members": [ + { + "id": "publish", + "value": "publish", + "brief": "One or more messages are provided for publishing to an intermediary. If a single message is published, the context of the \"Publish\" span can be used as the creation context and no \"Create\" span needs to be created.\n", + "stability": "stable" + }, + { + "id": "create", + "value": "create", + "brief": "A message is created. \"Create\" spans always refer to a single message and are used to provide a unique creation context for messages in batch publishing scenarios.\n", + "stability": "stable" + }, + { + "id": "receive", + "value": "receive", + "brief": "One or more messages are requested by a consumer. This operation refers to pull-based scenarios, where consumers explicitly call methods of messaging SDKs to receive messages.\n", + "stability": "stable" + }, + { + "id": "deliver", + "value": "deliver", + "brief": "One or more messages are passed to a consumer. This operation refers to push-based scenarios, where consumer register callbacks which get called by messaging SDKs.\n", + "stability": "stable" + } + ] + }, + "brief": "A string identifying the kind of messaging operation.\n", + "requirement_level": "recommended", + "note": "If a custom value is used, it MUST be of low cardinality.", + "stability": "stable" + }, + { + "name": "messaging.rabbitmq.destination.routing_key", + "type": "string", + "brief": "RabbitMQ message routing key.\n", + "examples": "myKey", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "messaging.rocketmq.client_group", + "type": "string", + "brief": "Name of the RocketMQ producer/consumer group that is handling the message. The client type is identified by the SpanKind.\n", + "examples": "myConsumerGroup", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "messaging.rocketmq.consumption_model", + "type": { + "members": [ + { + "id": "clustering", + "value": "clustering", + "brief": "Clustering consumption model", + "stability": "stable" + }, + { + "id": "broadcasting", + "value": "broadcasting", + "brief": "Broadcasting consumption model", + "stability": "stable" + } + ] + }, + "brief": "Model of message consumption. This only applies to consumer spans.\n", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "messaging.rocketmq.message.delay_time_level", + "type": "int", + "brief": "The delay time level for delay message, which determines the message delay time.\n", + "examples": 3, + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "messaging.rocketmq.message.delivery_timestamp", + "type": "int", + "brief": "The timestamp in milliseconds that the delay message is expected to be delivered to consumer.\n", + "examples": 1665987217045, + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "messaging.rocketmq.message.group", + "type": "string", + "brief": "It is essential for FIFO message. Messages that belong to the same message group are always processed one by one within the same consumer group.\n", + "examples": "myMessageGroup", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "messaging.rocketmq.message.keys", + "type": "string[]", + "brief": "Key(s) of message, another way to mark message besides message id.\n", + "examples": [ + [ + "keyA" + ], + [ + "keyB" + ] + ], + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "messaging.rocketmq.message.tag", + "type": "string", + "brief": "The secondary classifier of message besides topic.\n", + "examples": "tagA", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "messaging.rocketmq.message.type", + "type": { + "members": [ + { + "id": "normal", + "value": "normal", + "brief": "Normal message", + "stability": "stable" + }, + { + "id": "fifo", + "value": "fifo", + "brief": "FIFO message", + "stability": "stable" + }, + { + "id": "delay", + "value": "delay", + "brief": "Delay message", + "stability": "stable" + }, + { + "id": "transaction", + "value": "transaction", + "brief": "Transaction message", + "stability": "stable" + } + ] + }, + "brief": "Type of message.\n", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "messaging.rocketmq.namespace", + "type": "string", + "brief": "Namespace of RocketMQ resources, resources in different namespaces are individual.\n", + "examples": "myNamespace", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "messaging.system", + "type": { + "members": [ + { + "id": "activemq", + "value": "activemq", + "brief": "Apache ActiveMQ", + "stability": "stable" + }, + { + "id": "aws_sqs", + "value": "aws_sqs", + "brief": "Amazon Simple Queue Service (SQS)", + "stability": "stable" + }, + { + "id": "azure_eventgrid", + "value": "azure_eventgrid", + "brief": "Azure Event Grid", + "stability": "stable" + }, + { + "id": "azure_eventhubs", + "value": "azure_eventhubs", + "brief": "Azure Event Hubs", + "stability": "stable" + }, + { + "id": "azure_servicebus", + "value": "azure_servicebus", + "brief": "Azure Service Bus", + "stability": "stable" + }, + { + "id": "gcp_pubsub", + "value": "gcp_pubsub", + "brief": "Google Cloud Pub/Sub", + "stability": "stable" + }, + { + "id": "jms", + "value": "jms", + "brief": "Java Message Service", + "stability": "stable" + }, + { + "id": "kafka", + "value": "kafka", + "brief": "Apache Kafka", + "stability": "stable" + }, + { + "id": "rabbitmq", + "value": "rabbitmq", + "brief": "RabbitMQ", + "stability": "stable" + }, + { + "id": "rocketmq", + "value": "rocketmq", + "brief": "Apache RocketMQ", + "stability": "stable" + } + ] + }, + "brief": "An identifier for the messaging system being used. See below for a list of well-known identifiers.\n", + "requirement_level": "required", + "stability": "stable" + }, + { + "name": "messaging.system", + "type": { + "members": [ + { + "id": "activemq", + "value": "activemq", + "brief": "Apache ActiveMQ", + "stability": "stable" + }, + { + "id": "aws_sqs", + "value": "aws_sqs", + "brief": "Amazon Simple Queue Service (SQS)", + "stability": "stable" + }, + { + "id": "azure_eventgrid", + "value": "azure_eventgrid", + "brief": "Azure Event Grid", + "stability": "stable" + }, + { + "id": "azure_eventhubs", + "value": "azure_eventhubs", + "brief": "Azure Event Hubs", + "stability": "stable" + }, + { + "id": "azure_servicebus", + "value": "azure_servicebus", + "brief": "Azure Service Bus", + "stability": "stable" + }, + { + "id": "gcp_pubsub", + "value": "gcp_pubsub", + "brief": "Google Cloud Pub/Sub", + "stability": "stable" + }, + { + "id": "jms", + "value": "jms", + "brief": "Java Message Service", + "stability": "stable" + }, + { + "id": "kafka", + "value": "kafka", + "brief": "Apache Kafka", + "stability": "stable" + }, + { + "id": "rabbitmq", + "value": "rabbitmq", + "brief": "RabbitMQ", + "stability": "stable" + }, + { + "id": "rocketmq", + "value": "rocketmq", + "brief": "Apache RocketMQ", + "stability": "stable" + } + ] + }, + "brief": "An identifier for the messaging system being used. See below for a list of well-known identifiers.\n", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "network.carrier.icc", + "type": "string", + "brief": "The ISO 3166-1 alpha-2 2-character country code associated with the mobile carrier network.", + "examples": "DE", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "network.carrier.mcc", + "type": "string", + "brief": "The mobile carrier country code.", + "examples": "310", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "network.carrier.mnc", + "type": "string", + "brief": "The mobile carrier network code.", + "examples": "001", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "network.carrier.name", + "type": "string", + "brief": "The name of the mobile carrier.", + "examples": "sprint", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "network.connection.subtype", + "type": { + "members": [ + { + "id": "gprs", + "value": "gprs", + "brief": "GPRS", + "stability": "stable" + }, + { + "id": "edge", + "value": "edge", + "brief": "EDGE", + "stability": "stable" + }, + { + "id": "umts", + "value": "umts", + "brief": "UMTS", + "stability": "stable" + }, + { + "id": "cdma", + "value": "cdma", + "brief": "CDMA", + "stability": "stable" + }, + { + "id": "evdo_0", + "value": "evdo_0", + "brief": "EVDO Rel. 0", + "stability": "stable" + }, + { + "id": "evdo_a", + "value": "evdo_a", + "brief": "EVDO Rev. A", + "stability": "stable" + }, + { + "id": "cdma2000_1xrtt", + "value": "cdma2000_1xrtt", + "brief": "CDMA2000 1XRTT", + "stability": "stable" + }, + { + "id": "hsdpa", + "value": "hsdpa", + "brief": "HSDPA", + "stability": "stable" + }, + { + "id": "hsupa", + "value": "hsupa", + "brief": "HSUPA", + "stability": "stable" + }, + { + "id": "hspa", + "value": "hspa", + "brief": "HSPA", + "stability": "stable" + }, + { + "id": "iden", + "value": "iden", + "brief": "IDEN", + "stability": "stable" + }, + { + "id": "evdo_b", + "value": "evdo_b", + "brief": "EVDO Rev. B", + "stability": "stable" + }, + { + "id": "lte", + "value": "lte", + "brief": "LTE", + "stability": "stable" + }, + { + "id": "ehrpd", + "value": "ehrpd", + "brief": "EHRPD", + "stability": "stable" + }, + { + "id": "hspap", + "value": "hspap", + "brief": "HSPAP", + "stability": "stable" + }, + { + "id": "gsm", + "value": "gsm", + "brief": "GSM", + "stability": "stable" + }, + { + "id": "td_scdma", + "value": "td_scdma", + "brief": "TD-SCDMA", + "stability": "stable" + }, + { + "id": "iwlan", + "value": "iwlan", + "brief": "IWLAN", + "stability": "stable" + }, + { + "id": "nr", + "value": "nr", + "brief": "5G NR (New Radio)", + "stability": "stable" + }, + { + "id": "nrnsa", + "value": "nrnsa", + "brief": "5G NRNSA (New Radio Non-Standalone)", + "stability": "stable" + }, + { + "id": "lte_ca", + "value": "lte_ca", + "brief": "LTE CA", + "stability": "stable" + } + ] + }, + "brief": "This describes more details regarding the connection.type. It may be the type of cell technology connection, but it could be used for describing details about a wifi connection.", + "examples": "LTE", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "network.connection.type", + "type": { + "members": [ + { + "id": "wifi", + "value": "wifi", + "stability": "stable" + }, + { + "id": "wired", + "value": "wired", + "stability": "stable" + }, + { + "id": "cell", + "value": "cell", + "stability": "stable" + }, + { + "id": "unavailable", + "value": "unavailable", + "stability": "stable" + }, + { + "id": "unknown", + "value": "unknown", + "stability": "stable" + } + ] + }, + "brief": "The internet connection type.", + "examples": "wifi", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "network.io.direction", + "type": { + "members": [ + { + "id": "transmit", + "value": "transmit", + "stability": "stable" + }, + { + "id": "receive", + "value": "receive", + "stability": "stable" + } + ] + }, + "brief": "The network IO operation direction.", + "examples": [ + "transmit" + ], + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "network.local.address", + "type": "string", + "brief": "Local address of the network connection - IP address or Unix domain socket name.", + "examples": [ + "10.1.2.80", + "/tmp/my.sock" + ], + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "network.local.port", + "type": "int", + "brief": "Local port number of the network connection.", + "examples": [ + 65123 ], - [ - "abc", - "def" - ] - ], - "requirement_level": "recommended", - "note": "Instrumentations SHOULD require an explicit configuration of which headers are to be captured. Including all response headers can be a security risk - explicit configuration helps avoid leaking sensitive information.\nUsers MAY explicitly configure instrumentations to capture them even though it is not recommended.\nThe attribute value MUST consist of either multiple header values as an array of strings or a single-item array containing a possibly comma-concatenated string, depending on the way the HTTP library provides access to headers.\n", - "stability": "stable" - }, - { - "name": "http.response.status_code", - "type": "int", - "brief": "[HTTP response status code](https://tools.ietf.org/html/rfc7231#section-6).", - "examples": [ - 200 - ], - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "http.response.status_code", - "type": "int", - "brief": "[HTTP response status code](https://tools.ietf.org/html/rfc7231#section-6).", - "examples": [ - 200 - ], - "requirement_level": { - "conditionally_required": "If and only if one was received/sent." - }, - "stability": "stable" - }, - { - "name": "http.route", - "type": "string", - "brief": "The matched route, that is, the path template in the format used by the respective server framework.\n", - "examples": [ - "/users/:userID?", - "{controller}/{action}/{id?}" - ], - "requirement_level": "recommended", - "note": "MUST NOT be populated when this is not supported by the HTTP server framework as the route attribute should have low-cardinality and the URI path can NOT substitute it.\nSHOULD include the [application root](/docs/http/http-spans.md#http-server-definitions) if there is one.", - "stability": "stable" - }, - { - "name": "http.route", - "type": "string", - "brief": "The matched route, that is, the path template in the format used by the respective server framework.\n", - "examples": [ - "/users/:userID?", - "{controller}/{action}/{id?}" - ], - "requirement_level": { - "conditionally_required": "If and only if it's available" - }, - "note": "MUST NOT be populated when this is not supported by the HTTP server framework as the route attribute should have low-cardinality and the URI path can NOT substitute it.\nSHOULD include the [application root](/docs/http/http-spans.md#http-server-definitions) if there is one.", - "stability": "stable" - }, - { - "name": "messaging.batch.message_count", - "type": "int", - "brief": "The number of messages sent, received, or processed in the scope of the batching operation.", - "examples": [ - 0, - 1, - 2 - ], - "requirement_level": "recommended", - "note": "Instrumentations SHOULD NOT set `messaging.batch.message_count` on spans that operate with a single message. When a messaging client library supports both batch and single-message API for the same operation, instrumentations SHOULD use `messaging.batch.message_count` for batching APIs and SHOULD NOT use it for single-message APIs.\n", - "stability": "stable" - }, - { - "name": "messaging.client_id", - "type": "string", - "brief": "A unique identifier for the client that consumes or produces a message.\n", - "examples": [ - "client-5", - "myhost@8742@s8083jm" - ], - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "messaging.destination.anonymous", - "type": "boolean", - "brief": "A boolean that is true if the message destination is anonymous (could be unnamed or have auto-generated name).", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "messaging.destination.name", - "type": "string", - "brief": "The message destination name", - "examples": [ - "MyQueue", - "MyTopic" - ], - "requirement_level": "recommended", - "note": "Destination name SHOULD uniquely identify a specific queue, topic or other entity within the broker. If\nthe broker doesn't have such notion, the destination name SHOULD uniquely identify the broker.\n", - "stability": "stable" - }, - { - "name": "messaging.destination.name", - "type": "string", - "brief": "The message destination name", - "examples": [ - "MyQueue", - "MyTopic" - ], - "requirement_level": { - "conditionally_required": "if and only if `messaging.destination.name` is known to have low cardinality. Otherwise, `messaging.destination.template` MAY be populated." - }, - "note": "Destination name SHOULD uniquely identify a specific queue, topic or other entity within the broker. If\nthe broker doesn't have such notion, the destination name SHOULD uniquely identify the broker.\n", - "stability": "stable" - }, - { - "name": "messaging.destination.template", - "type": "string", - "brief": "Low cardinality representation of the messaging destination name", - "examples": [ - "/customers/{customerId}" - ], - "requirement_level": "recommended", - "note": "Destination names could be constructed from templates. An example would be a destination name involving a user name or product id. Although the destination name in this case is of high cardinality, the underlying template is of low cardinality and can be effectively used for grouping and aggregation.\n", - "stability": "stable" - }, - { - "name": "messaging.destination.template", - "type": "string", - "brief": "Low cardinality representation of the messaging destination name", - "examples": [ - "/customers/{customerId}" - ], - "requirement_level": { - "conditionally_required": "if available." - }, - "note": "Destination names could be constructed from templates. An example would be a destination name involving a user name or product id. Although the destination name in this case is of high cardinality, the underlying template is of low cardinality and can be effectively used for grouping and aggregation.\n", - "stability": "stable" - }, - { - "name": "messaging.destination.temporary", - "type": "boolean", - "brief": "A boolean that is true if the message destination is temporary and might not exist anymore after messages are processed.", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "messaging.destination_publish.anonymous", - "type": "boolean", - "brief": "A boolean that is true if the publish message destination is anonymous (could be unnamed or have auto-generated name).", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "messaging.destination_publish.name", - "type": "string", - "brief": "The name of the original destination the message was published to", - "examples": [ - "MyQueue", - "MyTopic" - ], - "requirement_level": "recommended", - "note": "The name SHOULD uniquely identify a specific queue, topic, or other entity within the broker. If\nthe broker doesn't have such notion, the original destination name SHOULD uniquely identify the broker.\n", - "stability": "stable" - }, - { - "name": "messaging.gcp_pubsub.message.ordering_key", - "type": "string", - "brief": "The ordering key for a given message. If the attribute is not present, the message does not have an ordering key.\n", - "examples": "ordering_key", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "messaging.kafka.consumer.group", - "type": "string", - "brief": "Name of the Kafka Consumer Group that is handling the message. Only applies to consumers, not producers.\n", - "examples": "my-group", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "messaging.kafka.destination.partition", - "type": "int", - "brief": "Partition the message is sent to.\n", - "examples": 2, - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "messaging.kafka.message.key", - "type": "string", - "brief": "Message keys in Kafka are used for grouping alike messages to ensure they're processed on the same partition. They differ from `messaging.message.id` in that they're not unique. If the key is `null`, the attribute MUST NOT be set.\n", - "examples": "myKey", - "requirement_level": "recommended", - "note": "If the key type is not string, it's string representation has to be supplied for the attribute. If the key has no unambiguous, canonical string form, don't include its value.\n", - "stability": "stable" - }, - { - "name": "messaging.kafka.message.offset", - "type": "int", - "brief": "The offset of a record in the corresponding Kafka partition.\n", - "examples": 42, - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "messaging.kafka.message.tombstone", - "type": "boolean", - "brief": "A boolean that is true if the message is a tombstone.", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "messaging.message.body.size", - "type": "int", - "brief": "The size of the message body in bytes.\n", - "examples": 1439, - "requirement_level": "recommended", - "note": "This can refer to both the compressed or uncompressed body size. If both sizes are known, the uncompressed\nbody size should be used.\n", - "stability": "stable" - }, - { - "name": "messaging.message.conversation_id", - "type": "string", - "brief": "The conversation ID identifying the conversation to which the message belongs, represented as a string. Sometimes called \"Correlation ID\".\n", - "examples": "MyConversationId", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "messaging.message.envelope.size", - "type": "int", - "brief": "The size of the message body and metadata in bytes.\n", - "examples": 2738, - "requirement_level": "recommended", - "note": "This can refer to both the compressed or uncompressed size. If both sizes are known, the uncompressed\nsize should be used.\n", - "stability": "stable" - }, - { - "name": "messaging.message.id", - "type": "string", - "brief": "A value used by the messaging system as an identifier for the message, represented as a string.", - "examples": "452a7c7c7c7048c2f887f61572b18fc2", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "messaging.operation", - "type": { - "members": [ - { - "id": "publish", - "value": "publish", - "brief": "One or more messages are provided for publishing to an intermediary. If a single message is published, the context of the \"Publish\" span can be used as the creation context and no \"Create\" span needs to be created.\n", - "stability": "stable" - }, - { - "id": "create", - "value": "create", - "brief": "A message is created. \"Create\" spans always refer to a single message and are used to provide a unique creation context for messages in batch publishing scenarios.\n", - "stability": "stable" - }, - { - "id": "receive", - "value": "receive", - "brief": "One or more messages are requested by a consumer. This operation refers to pull-based scenarios, where consumers explicitly call methods of messaging SDKs to receive messages.\n", - "stability": "stable" - }, - { - "id": "deliver", - "value": "deliver", - "brief": "One or more messages are passed to a consumer. This operation refers to push-based scenarios, where consumer register callbacks which get called by messaging SDKs.\n", - "stability": "stable" - } - ] - }, - "brief": "A string identifying the kind of messaging operation.\n", - "requirement_level": "recommended", - "note": "If a custom value is used, it MUST be of low cardinality.", - "stability": "stable" - }, - { - "name": "messaging.rabbitmq.destination.routing_key", - "type": "string", - "brief": "RabbitMQ message routing key.\n", - "examples": "myKey", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "messaging.rocketmq.client_group", - "type": "string", - "brief": "Name of the RocketMQ producer/consumer group that is handling the message. The client type is identified by the SpanKind.\n", - "examples": "myConsumerGroup", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "messaging.rocketmq.consumption_model", - "type": { - "members": [ - { - "id": "clustering", - "value": "clustering", - "brief": "Clustering consumption model", - "stability": "stable" - }, - { - "id": "broadcasting", - "value": "broadcasting", - "brief": "Broadcasting consumption model", - "stability": "stable" - } - ] - }, - "brief": "Model of message consumption. This only applies to consumer spans.\n", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "messaging.rocketmq.message.delay_time_level", - "type": "int", - "brief": "The delay time level for delay message, which determines the message delay time.\n", - "examples": 3, - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "messaging.rocketmq.message.delivery_timestamp", - "type": "int", - "brief": "The timestamp in milliseconds that the delay message is expected to be delivered to consumer.\n", - "examples": 1665987217045, - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "messaging.rocketmq.message.group", - "type": "string", - "brief": "It is essential for FIFO message. Messages that belong to the same message group are always processed one by one within the same consumer group.\n", - "examples": "myMessageGroup", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "messaging.rocketmq.message.keys", - "type": "string[]", - "brief": "Key(s) of message, another way to mark message besides message id.\n", - "examples": [ - [ - "keyA" + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "network.peer.address", + "type": "string", + "brief": "Peer address of the network connection - IP address or Unix domain socket name.", + "examples": [ + "10.1.2.80", + "/tmp/my.sock" + ], + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "network.peer.port", + "type": "int", + "brief": "Peer port number of the network connection.", + "examples": [ + 65123 + ], + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "network.protocol.name", + "type": "string", + "brief": "[OSI application layer](https://osi-model.com/application-layer/) or non-OSI equivalent.", + "examples": [ + "amqp", + "http", + "mqtt" + ], + "requirement_level": "recommended", + "note": "The value SHOULD be normalized to lowercase.", + "stability": "stable" + }, + { + "name": "network.protocol.name", + "type": "string", + "brief": "[OSI application layer](https://osi-model.com/application-layer/) or non-OSI equivalent.", + "examples": [ + "amqp", + "mqtt" + ], + "tag": "connection-level", + "requirement_level": "recommended", + "note": "The value SHOULD be normalized to lowercase.", + "stability": "stable" + }, + { + "name": "network.protocol.name", + "type": "string", + "brief": "[OSI application layer](https://osi-model.com/application-layer/) or non-OSI equivalent.", + "examples": [ + "http", + "spdy" + ], + "requirement_level": { + "conditionally_required": "If not `http` and `network.protocol.version` is set." + }, + "note": "The value SHOULD be normalized to lowercase.", + "stability": "stable" + }, + { + "name": "network.protocol.version", + "type": "string", + "brief": "Version of the protocol specified in `network.protocol.name`.", + "examples": "3.1.1", + "requirement_level": "recommended", + "note": "`network.protocol.version` refers to the version of the protocol used and might be different from the protocol client's version. If the HTTP client has a version of `0.27.2`, but sends HTTP version `1.1`, this attribute should be set to `1.1`.\n", + "stability": "stable" + }, + { + "name": "network.protocol.version", + "type": "string", + "brief": "Version of the protocol specified in `network.protocol.name`.", + "examples": "3.1.1", + "tag": "connection-level", + "requirement_level": "recommended", + "note": "`network.protocol.version` refers to the version of the protocol used and might be different from the protocol client's version. If the HTTP client has a version of `0.27.2`, but sends HTTP version `1.1`, this attribute should be set to `1.1`.\n", + "stability": "stable" + }, + { + "name": "network.protocol.version", + "type": "string", + "brief": "Version of the protocol specified in `network.protocol.name`.", + "examples": [ + "1.0", + "1.1", + "2", + "3" + ], + "requirement_level": "recommended", + "note": "`network.protocol.version` refers to the version of the protocol used and might be different from the protocol client's version. If the HTTP client has a version of `0.27.2`, but sends HTTP version `1.1`, this attribute should be set to `1.1`.\n", + "stability": "stable" + }, + { + "name": "network.transport", + "type": { + "members": [ + { + "id": "tcp", + "value": "tcp", + "brief": "TCP", + "stability": "stable" + }, + { + "id": "udp", + "value": "udp", + "brief": "UDP", + "stability": "stable" + }, + { + "id": "pipe", + "value": "pipe", + "brief": "Named or anonymous pipe.", + "stability": "stable" + }, + { + "id": "unix", + "value": "unix", + "brief": "Unix domain socket", + "stability": "stable" + } + ] + }, + "brief": "[OSI transport layer](https://osi-model.com/transport-layer/) or [inter-process communication method](https://wikipedia.org/wiki/Inter-process_communication).\n", + "examples": [ + "tcp", + "udp" + ], + "requirement_level": "recommended", + "note": "The value SHOULD be normalized to lowercase.\n\nConsider always setting the transport when setting a port number, since\na port number is ambiguous without knowing the transport. For example\ndifferent processes could be listening on TCP port 12345 and UDP port 12345.\n", + "stability": "stable" + }, + { + "name": "network.type", + "type": { + "members": [ + { + "id": "ipv4", + "value": "ipv4", + "brief": "IPv4", + "stability": "stable" + }, + { + "id": "ipv6", + "value": "ipv6", + "brief": "IPv6", + "stability": "stable" + } + ] + }, + "brief": "[OSI network layer](https://osi-model.com/network-layer/) or non-OSI equivalent.", + "examples": [ + "ipv4", + "ipv6" + ], + "requirement_level": "recommended", + "note": "The value SHOULD be normalized to lowercase.", + "stability": "stable" + }, + { + "name": "server.address", + "type": "string", + "brief": "Host identifier of the [\"URI origin\"](https://www.rfc-editor.org/rfc/rfc9110.html#name-uri-origin) HTTP request is sent to.\n", + "examples": [ + "example.com", + "10.1.2.80", + "/tmp/my.sock" + ], + "requirement_level": "required", + "note": "If an HTTP client request is explicitly made to an IP address, e.g. `http://x.x.x.x:8080`, then `server.address` SHOULD be the IP address `x.x.x.x`. A DNS lookup SHOULD NOT be used.\n", + "stability": "stable" + }, + { + "name": "server.address", + "type": "string", + "brief": "Name of the local HTTP server that received the request.\n", + "examples": [ + "example.com", + "10.1.2.80", + "/tmp/my.sock" + ], + "requirement_level": "recommended", + "note": "See [Setting `server.address` and `server.port` attributes](/docs/http/http-spans.md#setting-serveraddress-and-serverport-attributes).\n", + "stability": "stable" + }, + { + "name": "server.address", + "type": "string", + "brief": "Server domain name if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name.", + "examples": [ + "example.com", + "10.1.2.80", + "/tmp/my.sock" + ], + "requirement_level": "recommended", + "note": "When observed from the client side, and when communicating through an intermediary, `server.address` SHOULD represent the server address behind any intermediaries, for example proxies, if it's available.\n", + "stability": "stable" + }, + { + "name": "server.address", + "type": "string", + "brief": "Server domain name if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name.", + "examples": [ + "example.com", + "10.1.2.80", + "/tmp/my.sock" + ], + "requirement_level": { + "conditionally_required": "If available." + }, + "note": "This should be the IP/hostname of the broker (or other network-level peer) this specific message is sent to/received from.\n", + "stability": "stable" + }, + { + "name": "server.port", + "type": "int", + "brief": "Port identifier of the [\"URI origin\"](https://www.rfc-editor.org/rfc/rfc9110.html#name-uri-origin) HTTP request is sent to.\n", + "examples": [ + 80, + 8080, + 443 + ], + "requirement_level": "required", + "note": "When observed from the client side, and when communicating through an intermediary, `server.port` SHOULD represent the server port behind any intermediaries, for example proxies, if it's available.\n", + "stability": "stable" + }, + { + "name": "server.port", + "type": "int", + "brief": "Port of the local HTTP server that received the request.\n", + "examples": [ + 80, + 8080, + 443 + ], + "requirement_level": { + "conditionally_required": "If `server.address` is set." + }, + "note": "See [Setting `server.address` and `server.port` attributes](/docs/http/http-spans.md#setting-serveraddress-and-serverport-attributes).\n", + "stability": "stable" + }, + { + "name": "server.port", + "type": "int", + "brief": "Server port number.", + "examples": [ + 80, + 8080, + 443 + ], + "requirement_level": "recommended", + "note": "When observed from the client side, and when communicating through an intermediary, `server.port` SHOULD represent the server port behind any intermediaries, for example proxies, if it's available.\n", + "stability": "stable" + }, + { + "name": "url.fragment", + "type": "string", + "brief": "The [URI fragment](https://www.rfc-editor.org/rfc/rfc3986#section-3.5) component", + "examples": [ + "SemConv" + ], + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "url.full", + "type": "string", + "brief": "Absolute URL describing a network resource according to [RFC3986](https://www.rfc-editor.org/rfc/rfc3986)", + "examples": [ + "https://www.foo.bar/search?q=OpenTelemetry#SemConv", + "//localhost" + ], + "requirement_level": "recommended", + "note": "For network calls, URL usually has `scheme://host[:port][path][?query][#fragment]` format, where the fragment is not transmitted over HTTP, but if it is known, it SHOULD be included nevertheless.\n`url.full` MUST NOT contain credentials passed via URL in form of `https://username:password@www.example.com/`. In such case username and password SHOULD be redacted and attribute's value SHOULD be `https://REDACTED:REDACTED@www.example.com/`.\n`url.full` SHOULD capture the absolute URL when it is available (or can be reconstructed) and SHOULD NOT be validated or modified except for sanitizing purposes.\n", + "stability": "stable" + }, + { + "name": "url.path", + "type": "string", + "brief": "The [URI path](https://www.rfc-editor.org/rfc/rfc3986#section-3.3) component", + "examples": [ + "/search" + ], + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "url.query", + "type": "string", + "brief": "The [URI query](https://www.rfc-editor.org/rfc/rfc3986#section-3.4) component", + "examples": [ + "q=OpenTelemetry" + ], + "requirement_level": "recommended", + "note": "Sensitive content provided in query string SHOULD be scrubbed when instrumentations can identify it.", + "stability": "stable" + }, + { + "name": "url.scheme", + "type": "string", + "brief": "The [URI scheme](https://www.rfc-editor.org/rfc/rfc3986#section-3.1) component identifying the used protocol.", + "examples": [ + "http", + "https" + ], + "requirement_level": "required", + "note": "The scheme of the original client request, if known (e.g. from [Forwarded#proto](https://developer.mozilla.org/docs/Web/HTTP/Headers/Forwarded#proto), [X-Forwarded-Proto](https://developer.mozilla.org/docs/Web/HTTP/Headers/X-Forwarded-Proto), or a similar header). Otherwise, the scheme of the immediate peer request.", + "stability": "stable" + }, + { + "name": "url.scheme", + "type": "string", + "brief": "The [URI scheme](https://www.rfc-editor.org/rfc/rfc3986#section-3.1) component identifying the used protocol.", + "examples": [ + "http", + "https" + ], + "requirement_level": "opt_in", + "stability": "stable" + }, + { + "name": "url.scheme", + "type": "string", + "brief": "The [URI scheme](https://www.rfc-editor.org/rfc/rfc3986#section-3.1) component identifying the used protocol.", + "examples": [ + "https", + "ftp", + "telnet" ], - [ - "keyB" - ] - ], - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "messaging.rocketmq.message.tag", - "type": "string", - "brief": "The secondary classifier of message besides topic.\n", - "examples": "tagA", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "messaging.rocketmq.message.type", - "type": { - "members": [ - { - "id": "normal", - "value": "normal", - "brief": "Normal message", - "stability": "stable" - }, - { - "id": "fifo", - "value": "fifo", - "brief": "FIFO message", - "stability": "stable" - }, - { - "id": "delay", - "value": "delay", - "brief": "Delay message", - "stability": "stable" - }, - { - "id": "transaction", - "value": "transaction", - "brief": "Transaction message", - "stability": "stable" - } - ] - }, - "brief": "Type of message.\n", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "messaging.rocketmq.namespace", - "type": "string", - "brief": "Namespace of RocketMQ resources, resources in different namespaces are individual.\n", - "examples": "myNamespace", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "messaging.system", - "type": { - "members": [ - { - "id": "activemq", - "value": "activemq", - "brief": "Apache ActiveMQ", - "stability": "stable" - }, - { - "id": "aws_sqs", - "value": "aws_sqs", - "brief": "Amazon Simple Queue Service (SQS)", - "stability": "stable" - }, - { - "id": "azure_eventgrid", - "value": "azure_eventgrid", - "brief": "Azure Event Grid", - "stability": "stable" - }, - { - "id": "azure_eventhubs", - "value": "azure_eventhubs", - "brief": "Azure Event Hubs", - "stability": "stable" - }, - { - "id": "azure_servicebus", - "value": "azure_servicebus", - "brief": "Azure Service Bus", - "stability": "stable" - }, - { - "id": "gcp_pubsub", - "value": "gcp_pubsub", - "brief": "Google Cloud Pub/Sub", - "stability": "stable" - }, - { - "id": "jms", - "value": "jms", - "brief": "Java Message Service", - "stability": "stable" - }, - { - "id": "kafka", - "value": "kafka", - "brief": "Apache Kafka", - "stability": "stable" - }, - { - "id": "rabbitmq", - "value": "rabbitmq", - "brief": "RabbitMQ", - "stability": "stable" - }, - { - "id": "rocketmq", - "value": "rocketmq", - "brief": "Apache RocketMQ", - "stability": "stable" - } - ] - }, - "brief": "An identifier for the messaging system being used. See below for a list of well-known identifiers.\n", - "requirement_level": "required", - "stability": "stable" - }, - { - "name": "messaging.system", - "type": { - "members": [ - { - "id": "activemq", - "value": "activemq", - "brief": "Apache ActiveMQ", - "stability": "stable" - }, - { - "id": "aws_sqs", - "value": "aws_sqs", - "brief": "Amazon Simple Queue Service (SQS)", - "stability": "stable" - }, - { - "id": "azure_eventgrid", - "value": "azure_eventgrid", - "brief": "Azure Event Grid", - "stability": "stable" - }, - { - "id": "azure_eventhubs", - "value": "azure_eventhubs", - "brief": "Azure Event Hubs", - "stability": "stable" - }, - { - "id": "azure_servicebus", - "value": "azure_servicebus", - "brief": "Azure Service Bus", - "stability": "stable" - }, - { - "id": "gcp_pubsub", - "value": "gcp_pubsub", - "brief": "Google Cloud Pub/Sub", - "stability": "stable" - }, - { - "id": "jms", - "value": "jms", - "brief": "Java Message Service", - "stability": "stable" - }, - { - "id": "kafka", - "value": "kafka", - "brief": "Apache Kafka", - "stability": "stable" - }, - { - "id": "rabbitmq", - "value": "rabbitmq", - "brief": "RabbitMQ", - "stability": "stable" - }, - { - "id": "rocketmq", - "value": "rocketmq", - "brief": "Apache RocketMQ", - "stability": "stable" - } - ] - }, - "brief": "An identifier for the messaging system being used. See below for a list of well-known identifiers.\n", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "network.carrier.icc", - "type": "string", - "brief": "The ISO 3166-1 alpha-2 2-character country code associated with the mobile carrier network.", - "examples": "DE", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "network.carrier.mcc", - "type": "string", - "brief": "The mobile carrier country code.", - "examples": "310", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "network.carrier.mnc", - "type": "string", - "brief": "The mobile carrier network code.", - "examples": "001", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "network.carrier.name", - "type": "string", - "brief": "The name of the mobile carrier.", - "examples": "sprint", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "network.connection.subtype", - "type": { - "members": [ - { - "id": "gprs", - "value": "gprs", - "brief": "GPRS", - "stability": "stable" - }, - { - "id": "edge", - "value": "edge", - "brief": "EDGE", - "stability": "stable" - }, - { - "id": "umts", - "value": "umts", - "brief": "UMTS", - "stability": "stable" - }, - { - "id": "cdma", - "value": "cdma", - "brief": "CDMA", - "stability": "stable" - }, - { - "id": "evdo_0", - "value": "evdo_0", - "brief": "EVDO Rel. 0", - "stability": "stable" - }, - { - "id": "evdo_a", - "value": "evdo_a", - "brief": "EVDO Rev. A", - "stability": "stable" - }, - { - "id": "cdma2000_1xrtt", - "value": "cdma2000_1xrtt", - "brief": "CDMA2000 1XRTT", - "stability": "stable" - }, - { - "id": "hsdpa", - "value": "hsdpa", - "brief": "HSDPA", - "stability": "stable" - }, - { - "id": "hsupa", - "value": "hsupa", - "brief": "HSUPA", - "stability": "stable" - }, - { - "id": "hspa", - "value": "hspa", - "brief": "HSPA", - "stability": "stable" - }, - { - "id": "iden", - "value": "iden", - "brief": "IDEN", - "stability": "stable" - }, - { - "id": "evdo_b", - "value": "evdo_b", - "brief": "EVDO Rev. B", - "stability": "stable" - }, - { - "id": "lte", - "value": "lte", - "brief": "LTE", - "stability": "stable" - }, - { - "id": "ehrpd", - "value": "ehrpd", - "brief": "EHRPD", - "stability": "stable" - }, - { - "id": "hspap", - "value": "hspap", - "brief": "HSPAP", - "stability": "stable" - }, - { - "id": "gsm", - "value": "gsm", - "brief": "GSM", - "stability": "stable" - }, - { - "id": "td_scdma", - "value": "td_scdma", - "brief": "TD-SCDMA", - "stability": "stable" - }, - { - "id": "iwlan", - "value": "iwlan", - "brief": "IWLAN", - "stability": "stable" - }, - { - "id": "nr", - "value": "nr", - "brief": "5G NR (New Radio)", - "stability": "stable" - }, - { - "id": "nrnsa", - "value": "nrnsa", - "brief": "5G NRNSA (New Radio Non-Standalone)", - "stability": "stable" - }, - { - "id": "lte_ca", - "value": "lte_ca", - "brief": "LTE CA", - "stability": "stable" - } - ] - }, - "brief": "This describes more details regarding the connection.type. It may be the type of cell technology connection, but it could be used for describing details about a wifi connection.", - "examples": "LTE", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "network.connection.type", - "type": { - "members": [ - { - "id": "wifi", - "value": "wifi", - "stability": "stable" - }, - { - "id": "wired", - "value": "wired", - "stability": "stable" - }, - { - "id": "cell", - "value": "cell", - "stability": "stable" - }, - { - "id": "unavailable", - "value": "unavailable", - "stability": "stable" - }, - { - "id": "unknown", - "value": "unknown", - "stability": "stable" - } - ] - }, - "brief": "The internet connection type.", - "examples": "wifi", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "network.io.direction", - "type": { - "members": [ - { - "id": "transmit", - "value": "transmit", - "stability": "stable" - }, - { - "id": "receive", - "value": "receive", - "stability": "stable" - } - ] - }, - "brief": "The network IO operation direction.", - "examples": [ - "transmit" - ], - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "network.local.address", - "type": "string", - "brief": "Local address of the network connection - IP address or Unix domain socket name.", - "examples": [ - "10.1.2.80", - "/tmp/my.sock" - ], - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "network.local.port", - "type": "int", - "brief": "Local port number of the network connection.", - "examples": [ - 65123 - ], - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "network.peer.address", - "type": "string", - "brief": "Peer address of the network connection - IP address or Unix domain socket name.", - "examples": [ - "10.1.2.80", - "/tmp/my.sock" - ], - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "network.peer.port", - "type": "int", - "brief": "Peer port number of the network connection.", - "examples": [ - 65123 - ], - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "network.protocol.name", - "type": "string", - "brief": "[OSI application layer](https://osi-model.com/application-layer/) or non-OSI equivalent.", - "examples": [ - "amqp", - "http", - "mqtt" - ], - "requirement_level": "recommended", - "note": "The value SHOULD be normalized to lowercase.", - "stability": "stable" - }, - { - "name": "network.protocol.name", - "type": "string", - "brief": "[OSI application layer](https://osi-model.com/application-layer/) or non-OSI equivalent.", - "examples": [ - "amqp", - "mqtt" - ], - "tag": "connection-level", - "requirement_level": "recommended", - "note": "The value SHOULD be normalized to lowercase.", - "stability": "stable" - }, - { - "name": "network.protocol.name", - "type": "string", - "brief": "[OSI application layer](https://osi-model.com/application-layer/) or non-OSI equivalent.", - "examples": [ - "http", - "spdy" - ], - "requirement_level": { - "conditionally_required": "If not `http` and `network.protocol.version` is set." - }, - "note": "The value SHOULD be normalized to lowercase.", - "stability": "stable" - }, - { - "name": "network.protocol.version", - "type": "string", - "brief": "Version of the protocol specified in `network.protocol.name`.", - "examples": "3.1.1", - "requirement_level": "recommended", - "note": "`network.protocol.version` refers to the version of the protocol used and might be different from the protocol client's version. If the HTTP client has a version of `0.27.2`, but sends HTTP version `1.1`, this attribute should be set to `1.1`.\n", - "stability": "stable" - }, - { - "name": "network.protocol.version", - "type": "string", - "brief": "Version of the protocol specified in `network.protocol.name`.", - "examples": "3.1.1", - "tag": "connection-level", - "requirement_level": "recommended", - "note": "`network.protocol.version` refers to the version of the protocol used and might be different from the protocol client's version. If the HTTP client has a version of `0.27.2`, but sends HTTP version `1.1`, this attribute should be set to `1.1`.\n", - "stability": "stable" - }, - { - "name": "network.protocol.version", - "type": "string", - "brief": "Version of the protocol specified in `network.protocol.name`.", - "examples": [ - "1.0", - "1.1", - "2", - "3" - ], - "requirement_level": "recommended", - "note": "`network.protocol.version` refers to the version of the protocol used and might be different from the protocol client's version. If the HTTP client has a version of `0.27.2`, but sends HTTP version `1.1`, this attribute should be set to `1.1`.\n", - "stability": "stable" - }, - { - "name": "network.transport", - "type": { - "members": [ - { - "id": "tcp", - "value": "tcp", - "brief": "TCP", - "stability": "stable" - }, - { - "id": "udp", - "value": "udp", - "brief": "UDP", - "stability": "stable" - }, - { - "id": "pipe", - "value": "pipe", - "brief": "Named or anonymous pipe.", - "stability": "stable" - }, - { - "id": "unix", - "value": "unix", - "brief": "Unix domain socket", - "stability": "stable" - } - ] - }, - "brief": "[OSI transport layer](https://osi-model.com/transport-layer/) or [inter-process communication method](https://wikipedia.org/wiki/Inter-process_communication).\n", - "examples": [ - "tcp", - "udp" - ], - "requirement_level": "recommended", - "note": "The value SHOULD be normalized to lowercase.\n\nConsider always setting the transport when setting a port number, since\na port number is ambiguous without knowing the transport. For example\ndifferent processes could be listening on TCP port 12345 and UDP port 12345.\n", - "stability": "stable" - }, - { - "name": "network.type", - "type": { - "members": [ - { - "id": "ipv4", - "value": "ipv4", - "brief": "IPv4", - "stability": "stable" - }, - { - "id": "ipv6", - "value": "ipv6", - "brief": "IPv6", - "stability": "stable" - } - ] - }, - "brief": "[OSI network layer](https://osi-model.com/network-layer/) or non-OSI equivalent.", - "examples": [ - "ipv4", - "ipv6" - ], - "requirement_level": "recommended", - "note": "The value SHOULD be normalized to lowercase.", - "stability": "stable" - }, - { - "name": "server.address", - "type": "string", - "brief": "Host identifier of the [\"URI origin\"](https://www.rfc-editor.org/rfc/rfc9110.html#name-uri-origin) HTTP request is sent to.\n", - "examples": [ - "example.com", - "10.1.2.80", - "/tmp/my.sock" - ], - "requirement_level": "required", - "note": "If an HTTP client request is explicitly made to an IP address, e.g. `http://x.x.x.x:8080`, then `server.address` SHOULD be the IP address `x.x.x.x`. A DNS lookup SHOULD NOT be used.\n", - "stability": "stable" - }, - { - "name": "server.address", - "type": "string", - "brief": "Name of the local HTTP server that received the request.\n", - "examples": [ - "example.com", - "10.1.2.80", - "/tmp/my.sock" - ], - "requirement_level": "recommended", - "note": "See [Setting `server.address` and `server.port` attributes](/docs/http/http-spans.md#setting-serveraddress-and-serverport-attributes).\n", - "stability": "stable" - }, - { - "name": "server.address", - "type": "string", - "brief": "Server domain name if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name.", - "examples": [ - "example.com", - "10.1.2.80", - "/tmp/my.sock" - ], - "requirement_level": "recommended", - "note": "When observed from the client side, and when communicating through an intermediary, `server.address` SHOULD represent the server address behind any intermediaries, for example proxies, if it's available.\n", - "stability": "stable" - }, - { - "name": "server.address", - "type": "string", - "brief": "Server domain name if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name.", - "examples": [ - "example.com", - "10.1.2.80", - "/tmp/my.sock" - ], - "requirement_level": { - "conditionally_required": "If available." - }, - "note": "This should be the IP/hostname of the broker (or other network-level peer) this specific message is sent to/received from.\n", - "stability": "stable" - }, - { - "name": "server.port", - "type": "int", - "brief": "Port identifier of the [\"URI origin\"](https://www.rfc-editor.org/rfc/rfc9110.html#name-uri-origin) HTTP request is sent to.\n", - "examples": [ - 80, - 8080, - 443 - ], - "requirement_level": "required", - "note": "When observed from the client side, and when communicating through an intermediary, `server.port` SHOULD represent the server port behind any intermediaries, for example proxies, if it's available.\n", - "stability": "stable" - }, - { - "name": "server.port", - "type": "int", - "brief": "Port of the local HTTP server that received the request.\n", - "examples": [ - 80, - 8080, - 443 - ], - "requirement_level": { - "conditionally_required": "If `server.address` is set." - }, - "note": "See [Setting `server.address` and `server.port` attributes](/docs/http/http-spans.md#setting-serveraddress-and-serverport-attributes).\n", - "stability": "stable" - }, - { - "name": "server.port", - "type": "int", - "brief": "Server port number.", - "examples": [ - 80, - 8080, - 443 - ], - "requirement_level": "recommended", - "note": "When observed from the client side, and when communicating through an intermediary, `server.port` SHOULD represent the server port behind any intermediaries, for example proxies, if it's available.\n", - "stability": "stable" - }, - { - "name": "url.fragment", - "type": "string", - "brief": "The [URI fragment](https://www.rfc-editor.org/rfc/rfc3986#section-3.5) component", - "examples": [ - "SemConv" - ], - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "url.full", - "type": "string", - "brief": "Absolute URL describing a network resource according to [RFC3986](https://www.rfc-editor.org/rfc/rfc3986)", - "examples": [ - "https://www.foo.bar/search?q=OpenTelemetry#SemConv", - "//localhost" - ], - "requirement_level": "recommended", - "note": "For network calls, URL usually has `scheme://host[:port][path][?query][#fragment]` format, where the fragment is not transmitted over HTTP, but if it is known, it SHOULD be included nevertheless.\n`url.full` MUST NOT contain credentials passed via URL in form of `https://username:password@www.example.com/`. In such case username and password SHOULD be redacted and attribute's value SHOULD be `https://REDACTED:REDACTED@www.example.com/`.\n`url.full` SHOULD capture the absolute URL when it is available (or can be reconstructed) and SHOULD NOT be validated or modified except for sanitizing purposes.\n", - "stability": "stable" - }, - { - "name": "url.path", - "type": "string", - "brief": "The [URI path](https://www.rfc-editor.org/rfc/rfc3986#section-3.3) component", - "examples": [ - "/search" - ], - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "url.query", - "type": "string", - "brief": "The [URI query](https://www.rfc-editor.org/rfc/rfc3986#section-3.4) component", - "examples": [ - "q=OpenTelemetry" - ], - "requirement_level": "recommended", - "note": "Sensitive content provided in query string SHOULD be scrubbed when instrumentations can identify it.", - "stability": "stable" - }, - { - "name": "url.scheme", - "type": "string", - "brief": "The [URI scheme](https://www.rfc-editor.org/rfc/rfc3986#section-3.1) component identifying the used protocol.", - "examples": [ - "http", - "https" - ], - "requirement_level": "required", - "note": "The scheme of the original client request, if known (e.g. from [Forwarded#proto](https://developer.mozilla.org/docs/Web/HTTP/Headers/Forwarded#proto), [X-Forwarded-Proto](https://developer.mozilla.org/docs/Web/HTTP/Headers/X-Forwarded-Proto), or a similar header). Otherwise, the scheme of the immediate peer request.", - "stability": "stable" - }, - { - "name": "url.scheme", - "type": "string", - "brief": "The [URI scheme](https://www.rfc-editor.org/rfc/rfc3986#section-3.1) component identifying the used protocol.", - "examples": [ - "http", - "https" - ], - "requirement_level": "opt_in", - "stability": "stable" - }, - { - "name": "url.scheme", - "type": "string", - "brief": "The [URI scheme](https://www.rfc-editor.org/rfc/rfc3986#section-3.1) component identifying the used protocol.", - "examples": [ - "https", - "ftp", - "telnet" - ], - "requirement_level": "recommended", - "stability": "stable" - } -] \ No newline at end of file + "requirement_level": "recommended", + "stability": "stable" + } + ] +} \ No newline at end of file diff --git a/crates/weaver_resolver/data/registry-test-4-events/expected-attribute-catalog.json b/crates/weaver_resolver/data/registry-test-4-events/expected-attribute-catalog.json index 823eceead..a0806005b 100644 --- a/crates/weaver_resolver/data/registry-test-4-events/expected-attribute-catalog.json +++ b/crates/weaver_resolver/data/registry-test-4-events/expected-attribute-catalog.json @@ -1,319 +1,321 @@ -[ - { - "name": "android.state", - "type": { - "members": [ - { - "id": "created", - "value": "created", - "brief": "Any time before Activity.onResume() or, if the app has no Activity, Context.startService() has been called in the app for the first time.\n", - "stability": "stable" - }, - { - "id": "background", - "value": "background", - "brief": "Any time after Activity.onPause() or, if the app has no Activity, Context.stopService() has been called when the app was in the foreground state.\n", - "stability": "stable" - }, - { - "id": "foreground", - "value": "foreground", - "brief": "Any time after Activity.onResume() or, if the app has no Activity, Context.startService() has been called when the app was in either the created or background states.", - "stability": "stable" - } - ] +{ + "attributes": [ + { + "name": "android.state", + "type": { + "members": [ + { + "id": "created", + "value": "created", + "brief": "Any time before Activity.onResume() or, if the app has no Activity, Context.startService() has been called in the app for the first time.\n", + "stability": "stable" + }, + { + "id": "background", + "value": "background", + "brief": "Any time after Activity.onPause() or, if the app has no Activity, Context.stopService() has been called when the app was in the foreground state.\n", + "stability": "stable" + }, + { + "id": "foreground", + "value": "foreground", + "brief": "Any time after Activity.onResume() or, if the app has no Activity, Context.startService() has been called when the app was in either the created or background states.", + "stability": "stable" + } + ] + }, + "brief": "This attribute represents the state the application has transitioned into at the occurrence of the event.\n", + "requirement_level": "required", + "note": "The Android lifecycle states are defined in [Activity lifecycle callbacks](https://developer.android.com/guide/components/activities/activity-lifecycle#lc), and from which the `OS identifiers` are derived.\n", + "stability": "stable" }, - "brief": "This attribute represents the state the application has transitioned into at the occurrence of the event.\n", - "requirement_level": "required", - "note": "The Android lifecycle states are defined in [Activity lifecycle callbacks](https://developer.android.com/guide/components/activities/activity-lifecycle#lc), and from which the `OS identifiers` are derived.\n", - "stability": "stable" - }, - { - "name": "browser.brands", - "type": "string[]", - "brief": "Array of brand name and version separated by a space", - "examples": [ - [ - " Not A;Brand 99", - "Chromium 99", - "Chrome 99" - ] - ], - "requirement_level": "recommended", - "note": "This value is intended to be taken from the [UA client hints API](https://wicg.github.io/ua-client-hints/#interface) (`navigator.userAgentData.brands`).\n", - "stability": "stable" - }, - { - "name": "browser.language", - "type": "string", - "brief": "Preferred language of the user using the browser", - "examples": [ - "en", - "en-US", - "en-AU", - "fr", - "fr-FR" - ], - "requirement_level": "recommended", - "note": "This value is intended to be taken from the Navigator API `navigator.language`.\n", - "stability": "stable" - }, - { - "name": "browser.mobile", - "type": "boolean", - "brief": "A boolean that is true if the browser is running on a mobile device", - "requirement_level": "recommended", - "note": "This value is intended to be taken from the [UA client hints API](https://wicg.github.io/ua-client-hints/#interface) (`navigator.userAgentData.mobile`). If unavailable, this attribute SHOULD be left unset.\n", - "stability": "stable" - }, - { - "name": "browser.platform", - "type": "string", - "brief": "The platform on which the browser is running", - "examples": [ - "Windows", - "macOS", - "Android", - "iOS", - "Linux" - ], - "requirement_level": "recommended", - "note": "This value is intended to be taken from the [UA client hints API](https://wicg.github.io/ua-client-hints/#interface) (`navigator.userAgentData.platform`). \n", - "stability": "stable" - }, - { - "name": "client.address", - "type": "string", - "brief": "Test Client address ....", - "examples": [ - "client.example.com", - "10.1.2.80", - "/tmp/my.sock" - ], - "requirement_level": "recommended", - "note": "Test client address note\n", - "stability": "stable" - }, - { - "name": "client.name", - "type": "string", - "brief": "The name of the client that reported the exception.\n", - "examples": [ - "myclient" - ], - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "client.port", - "type": "int", - "brief": "Client port number.", - "examples": [ - 65123 - ], - "requirement_level": "recommended", - "note": "Test client port", - "stability": "stable" - }, - { - "name": "exception.escaped", - "type": "boolean", - "brief": "SHOULD be set to true if the exception event is recorded at a point where it is known that the exception is escaping the scope of the span.\n", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "exception.message", - "type": "string", - "brief": "The exception message.", - "examples": [ - "Division by zero", - "Can't convert 'int' object to str implicitly" - ], - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "exception.message", - "type": "string", - "brief": "The exception message.", - "examples": [ - "Division by zero", - "Can't convert 'int' object to str implicitly" - ], - "requirement_level": { - "conditionally_required": "Required if `exception.type` is not set, recommended otherwise." + { + "name": "browser.brands", + "type": "string[]", + "brief": "Array of brand name and version separated by a space", + "examples": [ + [ + " Not A;Brand 99", + "Chromium 99", + "Chrome 99" + ] + ], + "requirement_level": "recommended", + "note": "This value is intended to be taken from the [UA client hints API](https://wicg.github.io/ua-client-hints/#interface) (`navigator.userAgentData.brands`).\n", + "stability": "stable" }, - "stability": "stable" - }, - { - "name": "exception.stacktrace", - "type": "string", - "brief": ".", - "examples": "Exception in thread \"main\" java.lang.RuntimeException: Test exception\\n", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "exception.type", - "type": "string", - "brief": "The type of the exception (its fully-qualified class name, if applicable).\n", - "examples": [ - "java.net.ConnectException", - "OSError" - ], - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "exception.type", - "type": "string", - "brief": "The type of the exception (its fully-qualified class name, if applicable).\n", - "examples": [ - "java.net.ConnectException", - "OSError" - ], - "requirement_level": { - "conditionally_required": "Required if `exception.message` is not set, recommended otherwise." + { + "name": "browser.language", + "type": "string", + "brief": "Preferred language of the user using the browser", + "examples": [ + "en", + "en-US", + "en-AU", + "fr", + "fr-FR" + ], + "requirement_level": "recommended", + "note": "This value is intended to be taken from the Navigator API `navigator.language`.\n", + "stability": "stable" }, - "stability": "stable" - }, - { - "name": "feature_flag.key", - "type": "string", - "brief": "The unique identifier of the feature flag.", - "examples": [ - "logo-color" - ], - "requirement_level": "required", - "stability": "stable" - }, - { - "name": "feature_flag.provider_name", - "type": "string", - "brief": "The name of the service provider that performs the flag evaluation.", - "examples": [ - "Flag Manager" - ], - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "feature_flag.variant", - "type": "string", - "brief": "SHOULD be a semantic identifier for a value. If one is unavailable, a stringified version of the value can be used.\n", - "examples": [ - "red", - "true", - "on" - ], - "requirement_level": "recommended", - "note": "A semantic identifier, commonly referred to as a variant, provides a means\nfor referring to a value without including the value itself. This can\nprovide additional context for understanding the meaning behind a value.\nFor example, the variant `red` maybe be used for the value `#c05543`.\n\nA stringified version of the value can be used in situations where a\nsemantic identifier is unavailable. String representation of the value\nshould be determined by the implementer.", - "stability": "stable" - }, - { - "name": "ios.state", - "type": { - "members": [ - { - "id": "active", - "value": "active", - "brief": "The app has become `active`. Associated with UIKit notification `applicationDidBecomeActive`.\n", - "stability": "stable" - }, - { - "id": "inactive", - "value": "inactive", - "brief": "The app is now `inactive`. Associated with UIKit notification `applicationWillResignActive`.\n", - "stability": "stable" - }, - { - "id": "background", - "value": "background", - "brief": "The app is now in the background. This value is associated with UIKit notification `applicationDidEnterBackground`.\n", - "stability": "stable" - }, - { - "id": "foreground", - "value": "foreground", - "brief": "The app is now in the foreground. This value is associated with UIKit notification `applicationWillEnterForeground`.\n", - "stability": "stable" - }, - { - "id": "terminate", - "value": "terminate", - "brief": "The app is about to terminate. Associated with UIKit notification `applicationWillTerminate`.\n", - "stability": "stable" - } - ] + { + "name": "browser.mobile", + "type": "boolean", + "brief": "A boolean that is true if the browser is running on a mobile device", + "requirement_level": "recommended", + "note": "This value is intended to be taken from the [UA client hints API](https://wicg.github.io/ua-client-hints/#interface) (`navigator.userAgentData.mobile`). If unavailable, this attribute SHOULD be left unset.\n", + "stability": "stable" }, - "brief": "This attribute represents the state the application has transitioned into at the occurrence of the event.\n", - "requirement_level": "required", - "note": "The iOS lifecycle states are defined in the [UIApplicationDelegate documentation](https://developer.apple.com/documentation/uikit/uiapplicationdelegate#1656902), and from which the `OS terminology` column values are derived.\n", - "stability": "stable" - }, - { - "name": "test_attr.event.attr", - "type": "string", - "brief": "Just making sure the referenced attributes are defined", - "examples": "some value", - "requirement_level": "recommended", - "note": "Test value.", - "stability": "stable" - }, - { - "name": "test_attr.event.attr", - "type": "string", - "brief": "Just making sure the referenced attributes are defined", - "examples": "some value", - "requirement_level": { - "conditionally_required": "if and only if corresponding event is enabled" + { + "name": "browser.platform", + "type": "string", + "brief": "The platform on which the browser is running", + "examples": [ + "Windows", + "macOS", + "Android", + "iOS", + "Linux" + ], + "requirement_level": "recommended", + "note": "This value is intended to be taken from the [UA client hints API](https://wicg.github.io/ua-client-hints/#interface) (`navigator.userAgentData.platform`). \n", + "stability": "stable" }, - "note": "test attribute\n", - "stability": "stable" - }, - { - "name": "test_attr.http.url", - "type": "string", - "brief": "The Url", - "examples": [ - "https://example.com" - ], - "requirement_level": "recommended", - "note": "Test url value.", - "stability": "stable" - }, - { - "name": "test_attr.platform", - "type": "string", - "brief": "The browser platform", - "examples": [ - "Windows", - "macOS", - "Android" - ], - "requirement_level": "recommended", - "note": "Test value.", - "stability": "stable" - }, - { - "name": "test_attr.session.id", - "type": "string", - "brief": "The session id", - "examples": "127836abcdef98", - "requirement_level": "recommended", - "note": "Test value.", - "stability": "stable" - }, - { - "name": "test_attr.session.id", - "type": "string", - "brief": "The session id", - "examples": "127836abcdef98", - "requirement_level": { - "conditionally_required": "if and only if corresponding event is enabled" + { + "name": "client.address", + "type": "string", + "brief": "Test Client address ....", + "examples": [ + "client.example.com", + "10.1.2.80", + "/tmp/my.sock" + ], + "requirement_level": "recommended", + "note": "Test client address note\n", + "stability": "stable" }, - "note": "Another test attribute\n", - "stability": "stable" - } -] \ No newline at end of file + { + "name": "client.name", + "type": "string", + "brief": "The name of the client that reported the exception.\n", + "examples": [ + "myclient" + ], + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "client.port", + "type": "int", + "brief": "Client port number.", + "examples": [ + 65123 + ], + "requirement_level": "recommended", + "note": "Test client port", + "stability": "stable" + }, + { + "name": "exception.escaped", + "type": "boolean", + "brief": "SHOULD be set to true if the exception event is recorded at a point where it is known that the exception is escaping the scope of the span.\n", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "exception.message", + "type": "string", + "brief": "The exception message.", + "examples": [ + "Division by zero", + "Can't convert 'int' object to str implicitly" + ], + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "exception.message", + "type": "string", + "brief": "The exception message.", + "examples": [ + "Division by zero", + "Can't convert 'int' object to str implicitly" + ], + "requirement_level": { + "conditionally_required": "Required if `exception.type` is not set, recommended otherwise." + }, + "stability": "stable" + }, + { + "name": "exception.stacktrace", + "type": "string", + "brief": ".", + "examples": "Exception in thread \"main\" java.lang.RuntimeException: Test exception\\n", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "exception.type", + "type": "string", + "brief": "The type of the exception (its fully-qualified class name, if applicable).\n", + "examples": [ + "java.net.ConnectException", + "OSError" + ], + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "exception.type", + "type": "string", + "brief": "The type of the exception (its fully-qualified class name, if applicable).\n", + "examples": [ + "java.net.ConnectException", + "OSError" + ], + "requirement_level": { + "conditionally_required": "Required if `exception.message` is not set, recommended otherwise." + }, + "stability": "stable" + }, + { + "name": "feature_flag.key", + "type": "string", + "brief": "The unique identifier of the feature flag.", + "examples": [ + "logo-color" + ], + "requirement_level": "required", + "stability": "stable" + }, + { + "name": "feature_flag.provider_name", + "type": "string", + "brief": "The name of the service provider that performs the flag evaluation.", + "examples": [ + "Flag Manager" + ], + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "feature_flag.variant", + "type": "string", + "brief": "SHOULD be a semantic identifier for a value. If one is unavailable, a stringified version of the value can be used.\n", + "examples": [ + "red", + "true", + "on" + ], + "requirement_level": "recommended", + "note": "A semantic identifier, commonly referred to as a variant, provides a means\nfor referring to a value without including the value itself. This can\nprovide additional context for understanding the meaning behind a value.\nFor example, the variant `red` maybe be used for the value `#c05543`.\n\nA stringified version of the value can be used in situations where a\nsemantic identifier is unavailable. String representation of the value\nshould be determined by the implementer.", + "stability": "stable" + }, + { + "name": "ios.state", + "type": { + "members": [ + { + "id": "active", + "value": "active", + "brief": "The app has become `active`. Associated with UIKit notification `applicationDidBecomeActive`.\n", + "stability": "stable" + }, + { + "id": "inactive", + "value": "inactive", + "brief": "The app is now `inactive`. Associated with UIKit notification `applicationWillResignActive`.\n", + "stability": "stable" + }, + { + "id": "background", + "value": "background", + "brief": "The app is now in the background. This value is associated with UIKit notification `applicationDidEnterBackground`.\n", + "stability": "stable" + }, + { + "id": "foreground", + "value": "foreground", + "brief": "The app is now in the foreground. This value is associated with UIKit notification `applicationWillEnterForeground`.\n", + "stability": "stable" + }, + { + "id": "terminate", + "value": "terminate", + "brief": "The app is about to terminate. Associated with UIKit notification `applicationWillTerminate`.\n", + "stability": "stable" + } + ] + }, + "brief": "This attribute represents the state the application has transitioned into at the occurrence of the event.\n", + "requirement_level": "required", + "note": "The iOS lifecycle states are defined in the [UIApplicationDelegate documentation](https://developer.apple.com/documentation/uikit/uiapplicationdelegate#1656902), and from which the `OS terminology` column values are derived.\n", + "stability": "stable" + }, + { + "name": "test_attr.event.attr", + "type": "string", + "brief": "Just making sure the referenced attributes are defined", + "examples": "some value", + "requirement_level": "recommended", + "note": "Test value.", + "stability": "stable" + }, + { + "name": "test_attr.event.attr", + "type": "string", + "brief": "Just making sure the referenced attributes are defined", + "examples": "some value", + "requirement_level": { + "conditionally_required": "if and only if corresponding event is enabled" + }, + "note": "test attribute\n", + "stability": "stable" + }, + { + "name": "test_attr.http.url", + "type": "string", + "brief": "The Url", + "examples": [ + "https://example.com" + ], + "requirement_level": "recommended", + "note": "Test url value.", + "stability": "stable" + }, + { + "name": "test_attr.platform", + "type": "string", + "brief": "The browser platform", + "examples": [ + "Windows", + "macOS", + "Android" + ], + "requirement_level": "recommended", + "note": "Test value.", + "stability": "stable" + }, + { + "name": "test_attr.session.id", + "type": "string", + "brief": "The session id", + "examples": "127836abcdef98", + "requirement_level": "recommended", + "note": "Test value.", + "stability": "stable" + }, + { + "name": "test_attr.session.id", + "type": "string", + "brief": "The session id", + "examples": "127836abcdef98", + "requirement_level": { + "conditionally_required": "if and only if corresponding event is enabled" + }, + "note": "Another test attribute\n", + "stability": "stable" + } + ] +} \ No newline at end of file diff --git a/crates/weaver_resolver/data/registry-test-5-metrics/expected-attribute-catalog.json b/crates/weaver_resolver/data/registry-test-5-metrics/expected-attribute-catalog.json index f7afd07fb..8a60a4f77 100644 --- a/crates/weaver_resolver/data/registry-test-5-metrics/expected-attribute-catalog.json +++ b/crates/weaver_resolver/data/registry-test-5-metrics/expected-attribute-catalog.json @@ -1,103 +1,105 @@ -[ - { - "name": "faas.invoked_name", - "type": "string", - "brief": "The name of the invoked function.\n", - "examples": "my-function", - "requirement_level": "required", - "note": "SHOULD be equal to the `faas.name` resource attribute of the invoked function.\n", - "stability": "stable" - }, - { - "name": "faas.invoked_provider", - "type": { - "members": [ - { - "id": "alibaba_cloud", - "value": "alibaba_cloud", - "brief": "Alibaba Cloud", - "stability": "stable" - }, - { - "id": "aws", - "value": "aws", - "brief": "Amazon Web Services", - "stability": "stable" - }, - { - "id": "azure", - "value": "azure", - "brief": "Microsoft Azure", - "stability": "stable" - }, - { - "id": "gcp", - "value": "gcp", - "brief": "Google Cloud Platform", - "stability": "stable" - }, - { - "id": "tencent_cloud", - "value": "tencent_cloud", - "brief": "Tencent Cloud", - "stability": "stable" - } - ] +{ + "attributes": [ + { + "name": "faas.invoked_name", + "type": "string", + "brief": "The name of the invoked function.\n", + "examples": "my-function", + "requirement_level": "required", + "note": "SHOULD be equal to the `faas.name` resource attribute of the invoked function.\n", + "stability": "stable" }, - "brief": "The cloud provider of the invoked function.\n", - "requirement_level": "required", - "note": "SHOULD be equal to the `cloud.provider` resource attribute of the invoked function.\n", - "stability": "stable" - }, - { - "name": "faas.invoked_region", - "type": "string", - "brief": "The cloud region of the invoked function.\n", - "examples": "eu-central-1", - "requirement_level": { - "conditionally_required": "For some cloud providers, like AWS or GCP, the region in which a function is hosted is essential to uniquely identify the function and also part of its endpoint. Since it's part of the endpoint being called, the region is always known to clients. In these cases, `faas.invoked_region` MUST be set accordingly. If the region is unknown to the client or not required for identifying the invoked function, setting `faas.invoked_region` is optional.\n" + { + "name": "faas.invoked_provider", + "type": { + "members": [ + { + "id": "alibaba_cloud", + "value": "alibaba_cloud", + "brief": "Alibaba Cloud", + "stability": "stable" + }, + { + "id": "aws", + "value": "aws", + "brief": "Amazon Web Services", + "stability": "stable" + }, + { + "id": "azure", + "value": "azure", + "brief": "Microsoft Azure", + "stability": "stable" + }, + { + "id": "gcp", + "value": "gcp", + "brief": "Google Cloud Platform", + "stability": "stable" + }, + { + "id": "tencent_cloud", + "value": "tencent_cloud", + "brief": "Tencent Cloud", + "stability": "stable" + } + ] + }, + "brief": "The cloud provider of the invoked function.\n", + "requirement_level": "required", + "note": "SHOULD be equal to the `cloud.provider` resource attribute of the invoked function.\n", + "stability": "stable" }, - "note": "SHOULD be equal to the `cloud.region` resource attribute of the invoked function.\n", - "stability": "stable" - }, - { - "name": "faas.trigger", - "type": { - "members": [ - { - "id": "datasource", - "value": "datasource", - "brief": "A response to some data source operation such as a database or filesystem read/write", - "stability": "stable" - }, - { - "id": "http", - "value": "http", - "brief": "To provide an answer to an inbound HTTP request", - "stability": "stable" - }, - { - "id": "pubsub", - "value": "pubsub", - "brief": "A function is set to be executed when messages are sent to a messaging system", - "stability": "stable" - }, - { - "id": "timer", - "value": "timer", - "brief": "A function is scheduled to be executed regularly", - "stability": "stable" - }, - { - "id": "other", - "value": "other", - "brief": "If none of the others apply", - "stability": "stable" - } - ] + { + "name": "faas.invoked_region", + "type": "string", + "brief": "The cloud region of the invoked function.\n", + "examples": "eu-central-1", + "requirement_level": { + "conditionally_required": "For some cloud providers, like AWS or GCP, the region in which a function is hosted is essential to uniquely identify the function and also part of its endpoint. Since it's part of the endpoint being called, the region is always known to clients. In these cases, `faas.invoked_region` MUST be set accordingly. If the region is unknown to the client or not required for identifying the invoked function, setting `faas.invoked_region` is optional.\n" + }, + "note": "SHOULD be equal to the `cloud.region` resource attribute of the invoked function.\n", + "stability": "stable" }, - "brief": "Type of the trigger which caused this function invocation.", - "requirement_level": "recommended", - "stability": "stable" - } -] \ No newline at end of file + { + "name": "faas.trigger", + "type": { + "members": [ + { + "id": "datasource", + "value": "datasource", + "brief": "A response to some data source operation such as a database or filesystem read/write", + "stability": "stable" + }, + { + "id": "http", + "value": "http", + "brief": "To provide an answer to an inbound HTTP request", + "stability": "stable" + }, + { + "id": "pubsub", + "value": "pubsub", + "brief": "A function is set to be executed when messages are sent to a messaging system", + "stability": "stable" + }, + { + "id": "timer", + "value": "timer", + "brief": "A function is scheduled to be executed regularly", + "stability": "stable" + }, + { + "id": "other", + "value": "other", + "brief": "If none of the others apply", + "stability": "stable" + } + ] + }, + "brief": "Type of the trigger which caused this function invocation.", + "requirement_level": "recommended", + "stability": "stable" + } + ] +} \ No newline at end of file diff --git a/crates/weaver_resolver/data/registry-test-6-resources/expected-attribute-catalog.json b/crates/weaver_resolver/data/registry-test-6-resources/expected-attribute-catalog.json index dac952bcf..bd025f313 100644 --- a/crates/weaver_resolver/data/registry-test-6-resources/expected-attribute-catalog.json +++ b/crates/weaver_resolver/data/registry-test-6-resources/expected-attribute-catalog.json @@ -1,78 +1,80 @@ -[ - { - "name": "browser.brands", - "type": "string[]", - "brief": "Array of brand name and version separated by a space", - "examples": [ - [ - "Not A;Brand 99" +{ + "attributes": [ + { + "name": "browser.brands", + "type": "string[]", + "brief": "Array of brand name and version separated by a space", + "examples": [ + [ + "Not A;Brand 99" + ], + [ + "Chromium 99" + ], + [ + "Chrome 99" + ] ], - [ - "Chromium 99" + "requirement_level": "recommended", + "note": "This value is intended to be taken from the [UA client hints API](https://wicg.github.io/ua-client-hints/#interface) (`navigator.userAgentData.brands`).\n", + "stability": "stable" + }, + { + "name": "browser.language", + "type": "string", + "brief": "Preferred language of the user using the browser", + "examples": [ + "en", + "en-US", + "fr", + "fr-FR" ], - [ - "Chrome 99" - ] - ], - "requirement_level": "recommended", - "note": "This value is intended to be taken from the [UA client hints API](https://wicg.github.io/ua-client-hints/#interface) (`navigator.userAgentData.brands`).\n", - "stability": "stable" - }, - { - "name": "browser.language", - "type": "string", - "brief": "Preferred language of the user using the browser", - "examples": [ - "en", - "en-US", - "fr", - "fr-FR" - ], - "requirement_level": "recommended", - "note": "This value is intended to be taken from the Navigator API `navigator.language`.\n", - "stability": "stable" - }, - { - "name": "browser.mobile", - "type": "boolean", - "brief": "A boolean that is true if the browser is running on a mobile device", - "requirement_level": "recommended", - "note": "This value is intended to be taken from the [UA client hints API](https://wicg.github.io/ua-client-hints/#interface) (`navigator.userAgentData.mobile`). If unavailable, this attribute SHOULD be left unset.\n", - "stability": "stable" - }, - { - "name": "browser.platform", - "type": "string", - "brief": "The platform on which the browser is running", - "examples": [ - "Windows", - "macOS", - "Android" - ], - "requirement_level": "recommended", - "note": "This value is intended to be taken from the [UA client hints API](https://wicg.github.io/ua-client-hints/#interface) (`navigator.userAgentData.platform`). If unavailable, the legacy `navigator.platform` API SHOULD NOT be used instead and this attribute SHOULD be left unset in order for the values to be consistent.\nThe list of possible values is defined in the [W3C User-Agent Client Hints specification](https://wicg.github.io/ua-client-hints/#sec-ch-ua-platform). Note that some (but not all) of these values can overlap with values in the [`os.type` and `os.name` attributes](./os.md). However, for consistency, the values in the `browser.platform` attribute should capture the exact value that the user agent provides.\n", - "stability": "stable" - }, - { - "name": "user_agent.original", - "type": "string", - "brief": "Full user-agent string provided by the browser", - "examples": [ - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36" - ], - "requirement_level": "recommended", - "note": "The user-agent value SHOULD be provided only from browsers that do not have a mechanism to retrieve brands and platform individually from the User-Agent Client Hints API. To retrieve the value, the legacy `navigator.userAgent` API can be used.\n", - "stability": "stable" - }, - { - "name": "user_agent.original", - "type": "string", - "brief": "Value of the [HTTP User-Agent](https://www.rfc-editor.org/rfc/rfc9110.html#field.user-agent) header sent by the client.\n", - "examples": [ - "CERN-LineMode/2.15 libwww/2.17b3", - "Mozilla/5.0 (iPhone; CPU iPhone OS 14_7_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Mobile/15E148 Safari/604.1" - ], - "requirement_level": "recommended", - "stability": "stable" - } -] \ No newline at end of file + "requirement_level": "recommended", + "note": "This value is intended to be taken from the Navigator API `navigator.language`.\n", + "stability": "stable" + }, + { + "name": "browser.mobile", + "type": "boolean", + "brief": "A boolean that is true if the browser is running on a mobile device", + "requirement_level": "recommended", + "note": "This value is intended to be taken from the [UA client hints API](https://wicg.github.io/ua-client-hints/#interface) (`navigator.userAgentData.mobile`). If unavailable, this attribute SHOULD be left unset.\n", + "stability": "stable" + }, + { + "name": "browser.platform", + "type": "string", + "brief": "The platform on which the browser is running", + "examples": [ + "Windows", + "macOS", + "Android" + ], + "requirement_level": "recommended", + "note": "This value is intended to be taken from the [UA client hints API](https://wicg.github.io/ua-client-hints/#interface) (`navigator.userAgentData.platform`). If unavailable, the legacy `navigator.platform` API SHOULD NOT be used instead and this attribute SHOULD be left unset in order for the values to be consistent.\nThe list of possible values is defined in the [W3C User-Agent Client Hints specification](https://wicg.github.io/ua-client-hints/#sec-ch-ua-platform). Note that some (but not all) of these values can overlap with values in the [`os.type` and `os.name` attributes](./os.md). However, for consistency, the values in the `browser.platform` attribute should capture the exact value that the user agent provides.\n", + "stability": "stable" + }, + { + "name": "user_agent.original", + "type": "string", + "brief": "Full user-agent string provided by the browser", + "examples": [ + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36" + ], + "requirement_level": "recommended", + "note": "The user-agent value SHOULD be provided only from browsers that do not have a mechanism to retrieve brands and platform individually from the User-Agent Client Hints API. To retrieve the value, the legacy `navigator.userAgent` API can be used.\n", + "stability": "stable" + }, + { + "name": "user_agent.original", + "type": "string", + "brief": "Value of the [HTTP User-Agent](https://www.rfc-editor.org/rfc/rfc9110.html#field.user-agent) header sent by the client.\n", + "examples": [ + "CERN-LineMode/2.15 libwww/2.17b3", + "Mozilla/5.0 (iPhone; CPU iPhone OS 14_7_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Mobile/15E148 Safari/604.1" + ], + "requirement_level": "recommended", + "stability": "stable" + } + ] +} \ No newline at end of file diff --git a/crates/weaver_resolver/data/registry-test-7-spans/expected-attribute-catalog.json b/crates/weaver_resolver/data/registry-test-7-spans/expected-attribute-catalog.json index b034b210e..8885bda66 100644 --- a/crates/weaver_resolver/data/registry-test-7-spans/expected-attribute-catalog.json +++ b/crates/weaver_resolver/data/registry-test-7-spans/expected-attribute-catalog.json @@ -1,2552 +1,2554 @@ -[ - { - "name": "db.cassandra.consistency_level", - "type": { - "members": [ - { - "id": "all", - "value": "all", - "stability": "stable" - }, - { - "id": "each_quorum", - "value": "each_quorum", - "stability": "stable" - }, - { - "id": "quorum", - "value": "quorum", - "stability": "stable" - }, - { - "id": "local_quorum", - "value": "local_quorum", - "stability": "stable" - }, - { - "id": "one", - "value": "one", - "stability": "stable" - }, - { - "id": "two", - "value": "two", - "stability": "stable" - }, - { - "id": "three", - "value": "three", - "stability": "stable" - }, - { - "id": "local_one", - "value": "local_one", - "stability": "stable" - }, - { - "id": "any", - "value": "any", - "stability": "stable" - }, - { - "id": "serial", - "value": "serial", - "stability": "stable" - }, - { - "id": "local_serial", - "value": "local_serial", - "stability": "stable" - } - ] - }, - "brief": "The consistency level of the query. Based on consistency values from [CQL](https://docs.datastax.com/en/cassandra-oss/3.0/cassandra/dml/dmlConfigConsistency.html).\n", - "tag": "call-level-tech-specific-cassandra", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "db.cassandra.consistency_level", - "type": { - "members": [ - { - "id": "all", - "value": "all", - "stability": "stable" - }, - { - "id": "each_quorum", - "value": "each_quorum", - "stability": "stable" - }, - { - "id": "quorum", - "value": "quorum", - "stability": "stable" - }, - { - "id": "local_quorum", - "value": "local_quorum", - "stability": "stable" - }, - { - "id": "one", - "value": "one", - "stability": "stable" - }, - { - "id": "two", - "value": "two", - "stability": "stable" - }, - { - "id": "three", - "value": "three", - "stability": "stable" - }, - { - "id": "local_one", - "value": "local_one", - "stability": "stable" - }, - { - "id": "any", - "value": "any", - "stability": "stable" - }, - { - "id": "serial", - "value": "serial", - "stability": "stable" - }, - { - "id": "local_serial", - "value": "local_serial", - "stability": "stable" - } - ] - }, - "brief": "The consistency level of the query. Based on consistency values from [CQL](https://docs.datastax.com/en/cassandra-oss/3.0/cassandra/dml/dmlConfigConsistency.html).\n", - "tag": "tech-specific-cassandra", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "db.cassandra.coordinator.dc", - "type": "string", - "brief": "The data center of the coordinating node for a query.\n", - "examples": "us-west-2", - "tag": "call-level-tech-specific-cassandra", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "db.cassandra.coordinator.dc", - "type": "string", - "brief": "The data center of the coordinating node for a query.\n", - "examples": "us-west-2", - "tag": "tech-specific-cassandra", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "db.cassandra.coordinator.id", - "type": "string", - "brief": "The ID of the coordinating node for a query.\n", - "examples": "be13faa2-8574-4d71-926d-27f16cf8a7af", - "tag": "call-level-tech-specific-cassandra", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "db.cassandra.coordinator.id", - "type": "string", - "brief": "The ID of the coordinating node for a query.\n", - "examples": "be13faa2-8574-4d71-926d-27f16cf8a7af", - "tag": "tech-specific-cassandra", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "db.cassandra.idempotence", - "type": "boolean", - "brief": "Whether or not the query is idempotent.\n", - "tag": "call-level-tech-specific-cassandra", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "db.cassandra.idempotence", - "type": "boolean", - "brief": "Whether or not the query is idempotent.\n", - "tag": "tech-specific-cassandra", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "db.cassandra.page_size", - "type": "int", - "brief": "The fetch size used for paging, i.e. how many rows will be returned at once.\n", - "examples": [ - 5000 - ], - "tag": "call-level-tech-specific-cassandra", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "db.cassandra.page_size", - "type": "int", - "brief": "The fetch size used for paging, i.e. how many rows will be returned at once.\n", - "examples": [ - 5000 - ], - "tag": "tech-specific-cassandra", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "db.cassandra.speculative_execution_count", - "type": "int", - "brief": "The number of times a query was speculatively executed. Not set or `0` if the query was not executed speculatively.\n", - "examples": [ - 0, - 2 - ], - "tag": "call-level-tech-specific-cassandra", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "db.cassandra.speculative_execution_count", - "type": "int", - "brief": "The number of times a query was speculatively executed. Not set or `0` if the query was not executed speculatively.\n", - "examples": [ - 0, - 2 - ], - "tag": "tech-specific-cassandra", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "db.cassandra.table", - "type": "string", - "brief": "The name of the primary Cassandra table that the operation is acting upon, including the keyspace name (if applicable).", - "examples": "mytable", - "tag": "call-level-tech-specific-cassandra", - "requirement_level": "recommended", - "note": "This mirrors the db.sql.table attribute but references cassandra rather than sql. It is not recommended to attempt any client-side parsing of `db.statement` just to get this property, but it should be set if it is provided by the library being instrumented. If the operation is acting upon an anonymous table, or more than one table, this value MUST NOT be set.\n", - "stability": "stable" - }, - { - "name": "db.cassandra.table", - "type": "string", - "brief": "The name of the primary Cassandra table that the operation is acting upon, including the keyspace name (if applicable).", - "examples": "mytable", - "tag": "tech-specific-cassandra", - "requirement_level": "recommended", - "note": "This mirrors the db.sql.table attribute but references cassandra rather than sql. It is not recommended to attempt any client-side parsing of `db.statement` just to get this property, but it should be set if it is provided by the library being instrumented. If the operation is acting upon an anonymous table, or more than one table, this value MUST NOT be set.\n", - "stability": "stable" - }, - { - "name": "db.connection_string", - "type": "string", - "brief": "The connection string used to connect to the database. It is recommended to remove embedded credentials.\n", - "examples": "Server=(localdb)\\v11.0;Integrated Security=true;", - "tag": "connection-level", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "db.connection_string", - "type": "string", - "brief": "The connection string used to connect to the database. It is recommended to remove embedded credentials.\n", - "examples": "Server=(localdb)\\v11.0;Integrated Security=true;", - "tag": "db-generic", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "db.cosmosdb.client_id", - "type": "string", - "brief": "Unique Cosmos client instance id.", - "examples": "3ba4827d-4422-483f-b59f-85b74211c11d", - "tag": "call-level-tech-specific", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "db.cosmosdb.client_id", - "type": "string", - "brief": "Unique Cosmos client instance id.", - "examples": "3ba4827d-4422-483f-b59f-85b74211c11d", - "tag": "tech-specific-cosmosdb", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "db.cosmosdb.connection_mode", - "type": { - "members": [ - { - "id": "gateway", - "value": "gateway", - "brief": "Gateway (HTTP) connections mode", - "stability": "stable" - }, - { - "id": "direct", - "value": "direct", - "brief": "Direct connection.", - "stability": "stable" - } - ] - }, - "brief": "Cosmos client connection mode.", - "tag": "call-level-tech-specific", - "requirement_level": { - "conditionally_required": "if not `direct` (or pick gw as default)" - }, - "stability": "stable" - }, - { - "name": "db.cosmosdb.connection_mode", - "type": { - "members": [ - { - "id": "gateway", - "value": "gateway", - "brief": "Gateway (HTTP) connections mode", - "stability": "stable" - }, - { - "id": "direct", - "value": "direct", - "brief": "Direct connection.", - "stability": "stable" - } - ] - }, - "brief": "Cosmos client connection mode.", - "tag": "tech-specific-cosmosdb", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "db.cosmosdb.container", - "type": "string", - "brief": "Cosmos DB container name.", - "examples": "anystring", - "tag": "call-level-tech-specific", - "requirement_level": { - "conditionally_required": "if available" - }, - "stability": "stable" - }, - { - "name": "db.cosmosdb.container", - "type": "string", - "brief": "Cosmos DB container name.", - "examples": "anystring", - "tag": "tech-specific-cosmosdb", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "db.cosmosdb.operation_type", - "type": { - "members": [ - { - "id": "invalid", - "value": "Invalid", - "stability": "stable" - }, - { - "id": "create", - "value": "Create", - "stability": "stable" - }, - { - "id": "patch", - "value": "Patch", - "stability": "stable" - }, - { - "id": "read", - "value": "Read", - "stability": "stable" - }, - { - "id": "read_feed", - "value": "ReadFeed", - "stability": "stable" - }, - { - "id": "delete", - "value": "Delete", - "stability": "stable" - }, - { - "id": "replace", - "value": "Replace", - "stability": "stable" - }, - { - "id": "execute", - "value": "Execute", - "stability": "stable" - }, - { - "id": "query", - "value": "Query", - "stability": "stable" - }, - { - "id": "head", - "value": "Head", - "stability": "stable" - }, - { - "id": "head_feed", - "value": "HeadFeed", - "stability": "stable" - }, - { - "id": "upsert", - "value": "Upsert", - "stability": "stable" - }, - { - "id": "batch", - "value": "Batch", - "stability": "stable" - }, - { - "id": "query_plan", - "value": "QueryPlan", - "stability": "stable" - }, - { - "id": "execute_javascript", - "value": "ExecuteJavaScript", - "stability": "stable" - } - ] - }, - "brief": "CosmosDB Operation Type.", - "tag": "call-level-tech-specific", - "requirement_level": { - "conditionally_required": "when performing one of the operations in this list" - }, - "stability": "stable" - }, - { - "name": "db.cosmosdb.operation_type", - "type": { - "members": [ - { - "id": "invalid", - "value": "Invalid", - "stability": "stable" - }, - { - "id": "create", - "value": "Create", - "stability": "stable" - }, - { - "id": "patch", - "value": "Patch", - "stability": "stable" - }, - { - "id": "read", - "value": "Read", - "stability": "stable" - }, - { - "id": "read_feed", - "value": "ReadFeed", - "stability": "stable" - }, - { - "id": "delete", - "value": "Delete", - "stability": "stable" - }, - { - "id": "replace", - "value": "Replace", - "stability": "stable" - }, - { - "id": "execute", - "value": "Execute", - "stability": "stable" - }, - { - "id": "query", - "value": "Query", - "stability": "stable" - }, - { - "id": "head", - "value": "Head", - "stability": "stable" - }, - { - "id": "head_feed", - "value": "HeadFeed", - "stability": "stable" - }, - { - "id": "upsert", - "value": "Upsert", - "stability": "stable" - }, - { - "id": "batch", - "value": "Batch", - "stability": "stable" - }, - { - "id": "query_plan", - "value": "QueryPlan", - "stability": "stable" - }, - { - "id": "execute_javascript", - "value": "ExecuteJavaScript", - "stability": "stable" - } - ] - }, - "brief": "CosmosDB Operation Type.", - "tag": "tech-specific-cosmosdb", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "db.cosmosdb.request_charge", - "type": "double", - "brief": "RU consumed for that operation", - "examples": [ - 46.18, - 1.0 - ], - "tag": "call-level-tech-specific", - "requirement_level": { - "conditionally_required": "when available" - }, - "stability": "stable" - }, - { - "name": "db.cosmosdb.request_charge", - "type": "double", - "brief": "RU consumed for that operation", - "examples": [ - 46.18, - 1.0 - ], - "tag": "tech-specific-cosmosdb", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "db.cosmosdb.request_content_length", - "type": "int", - "brief": "Request payload size in bytes", - "tag": "call-level-tech-specific", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "db.cosmosdb.request_content_length", - "type": "int", - "brief": "Request payload size in bytes", - "tag": "tech-specific-cosmosdb", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "db.cosmosdb.status_code", - "type": "int", - "brief": "Cosmos DB status code.", - "examples": [ - 200, - 201 - ], - "tag": "call-level-tech-specific", - "requirement_level": { - "conditionally_required": "if response was received" - }, - "stability": "stable" - }, - { - "name": "db.cosmosdb.status_code", - "type": "int", - "brief": "Cosmos DB status code.", - "examples": [ - 200, - 201 - ], - "tag": "tech-specific-cosmosdb", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "db.cosmosdb.sub_status_code", - "type": "int", - "brief": "Cosmos DB sub status code.", - "examples": [ - 1000, - 1002 - ], - "tag": "call-level-tech-specific", - "requirement_level": { - "conditionally_required": "when response was received and contained sub-code." - }, - "stability": "stable" - }, - { - "name": "db.cosmosdb.sub_status_code", - "type": "int", - "brief": "Cosmos DB sub status code.", - "examples": [ - 1000, - 1002 - ], - "tag": "tech-specific-cosmosdb", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "db.elasticsearch.cluster.name", - "type": "string", - "brief": "Represents the identifier of an Elasticsearch cluster.\n", - "examples": [ - "e9106fc68e3044f0b1475b04bf4ffd5f" - ], - "tag": "call-level-tech-specific", - "requirement_level": { - "recommended": "When communicating with an Elastic Cloud deployment, this should be collected from the \"X-Found-Handling-Cluster\" HTTP response header.\n" - }, - "stability": "stable" - }, - { - "name": "db.elasticsearch.cluster.name", - "type": "string", - "brief": "Represents the identifier of an Elasticsearch cluster.\n", - "examples": [ - "e9106fc68e3044f0b1475b04bf4ffd5f" - ], - "tag": "tech-specific-elasticsearch", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "db.elasticsearch.node.name", - "type": "string", - "brief": "Represents the human-readable identifier of the node/instance to which a request was routed.\n", - "examples": [ - "instance-0000000001" - ], - "tag": "call-level-tech-specific", - "requirement_level": { - "recommended": "When communicating with an Elastic Cloud deployment, this should be collected from the \"X-Found-Handling-Instance\" HTTP response header.\n" - }, - "stability": "stable" - }, - { - "name": "db.elasticsearch.node.name", - "type": "string", - "brief": "Represents the human-readable identifier of the node/instance to which a request was routed.\n", - "examples": [ - "instance-0000000001" - ], - "tag": "tech-specific-elasticsearch", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "db.elasticsearch.path_parts", - "type": "template[string]", - "brief": "A dynamic value in the url path.\n", - "examples": [ - "db.elasticsearch.path_parts.index=test-index", - "db.elasticsearch.path_parts.doc_id=123" - ], - "tag": "call-level-tech-specific", - "requirement_level": { - "conditionally_required": "when the url has dynamic values" - }, - "note": "Many Elasticsearch url paths allow dynamic values. These SHOULD be recorded in span attributes in the format `db.elasticsearch.path_parts.`, where `` is the url path part name. The implementation SHOULD reference the [elasticsearch schema](https://raw.githubusercontent.com/elastic/elasticsearch-specification/main/output/schema/schema.json) in order to map the path part values to their names.\n", - "stability": "stable" - }, - { - "name": "db.elasticsearch.path_parts", - "type": "template[string]", - "brief": "A dynamic value in the url path.\n", - "examples": [ - "db.elasticsearch.path_parts.index=test-index", - "db.elasticsearch.path_parts.doc_id=123" - ], - "tag": "tech-specific-elasticsearch", - "requirement_level": "recommended", - "note": "Many Elasticsearch url paths allow dynamic values. These SHOULD be recorded in span attributes in the format `db.elasticsearch.path_parts.`, where `` is the url path part name. The implementation SHOULD reference the [elasticsearch schema](https://raw.githubusercontent.com/elastic/elasticsearch-specification/main/output/schema/schema.json) in order to map the path part values to their names.\n", - "stability": "stable" - }, - { - "name": "db.instance.id", - "type": "string", - "brief": "An identifier (address, unique name, or any other identifier) of the database instance that is executing queries or mutations on the current connection. This is useful in cases where the database is running in a clustered environment and the instrumentation is able to record the node executing the query. The client may obtain this value in databases like MySQL using queries like `select @@hostname`.\n", - "examples": "mysql-e26b99z.example.com", - "tag": "connection-level", - "requirement_level": { - "recommended": "If different from the `server.address`" - }, - "stability": "stable" - }, - { - "name": "db.instance.id", - "type": "string", - "brief": "An identifier (address, unique name, or any other identifier) of the database instance that is executing queries or mutations on the current connection. This is useful in cases where the database is running in a clustered environment and the instrumentation is able to record the node executing the query. The client may obtain this value in databases like MySQL using queries like `select @@hostname`.\n", - "examples": "mysql-e26b99z.example.com", - "tag": "db-generic", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "db.jdbc.driver_classname", - "type": "string", - "brief": "The fully-qualified class name of the [Java Database Connectivity (JDBC)](https://docs.oracle.com/javase/8/docs/technotes/guides/jdbc/) driver used to connect.\n", - "examples": [ - "org.postgresql.Driver", - "com.microsoft.sqlserver.jdbc.SQLServerDriver" - ], - "tag": "connection-level-tech-specific", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "db.jdbc.driver_classname", - "type": "string", - "brief": "The fully-qualified class name of the [Java Database Connectivity (JDBC)](https://docs.oracle.com/javase/8/docs/technotes/guides/jdbc/) driver used to connect.\n", - "examples": [ - "org.postgresql.Driver", - "com.microsoft.sqlserver.jdbc.SQLServerDriver" - ], - "tag": "tech-specific-jdbc", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "db.mongodb.collection", - "type": "string", - "brief": "The MongoDB collection being accessed within the database stated in `db.name`.\n", - "examples": [ - "customers", - "products" - ], - "tag": "call-level-tech-specific", - "requirement_level": "required", - "stability": "stable" - }, - { - "name": "db.mongodb.collection", - "type": "string", - "brief": "The MongoDB collection being accessed within the database stated in `db.name`.\n", - "examples": [ - "customers", - "products" - ], - "tag": "tech-specific-mongodb", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "db.mssql.instance_name", - "type": "string", - "brief": "The Microsoft SQL Server [instance name](https://docs.microsoft.com/sql/connect/jdbc/building-the-connection-url?view=sql-server-ver15) connecting to. This name is used to determine the port of a named instance.\n", - "examples": "MSSQLSERVER", - "tag": "connection-level-tech-specific", - "requirement_level": "recommended", - "note": "If setting a `db.mssql.instance_name`, `server.port` is no longer required (but still recommended if non-standard).\n", - "stability": "stable" - }, - { - "name": "db.mssql.instance_name", - "type": "string", - "brief": "The Microsoft SQL Server [instance name](https://docs.microsoft.com/sql/connect/jdbc/building-the-connection-url?view=sql-server-ver15) connecting to. This name is used to determine the port of a named instance.\n", - "examples": "MSSQLSERVER", - "tag": "tech-specific-mssql", - "requirement_level": "recommended", - "note": "If setting a `db.mssql.instance_name`, `server.port` is no longer required (but still recommended if non-standard).\n", - "stability": "stable" - }, - { - "name": "db.name", - "type": "string", - "brief": "The HBase namespace.\n", - "examples": [ - "mynamespace" - ], - "tag": "call-level-tech-specific", - "requirement_level": { - "conditionally_required": "If applicable." - }, - "note": "For HBase the `db.name` should be set to the HBase namespace.", - "stability": "stable" - }, - { - "name": "db.name", - "type": "string", - "brief": "The keyspace name in Cassandra.\n", - "examples": [ - "mykeyspace" - ], - "tag": "call-level-tech-specific-cassandra", - "requirement_level": { - "conditionally_required": "If applicable." - }, - "note": "For Cassandra the `db.name` should be set to the Cassandra keyspace name.", - "stability": "stable" - }, - { - "name": "db.name", - "type": "string", - "brief": "This attribute is used to report the name of the database being accessed. For commands that switch the database, this should be set to the target database (even if the command fails).\n", - "examples": [ - "customers", - "main" - ], - "tag": "call-level", - "requirement_level": { - "conditionally_required": "If applicable." - }, - "note": "In some SQL databases, the database name to be used is called \"schema name\". In case there are multiple layers that could be considered for database name (e.g. Oracle instance name and schema name), the database name to be used is the more specific layer (e.g. Oracle schema name).\n", - "stability": "stable" - }, - { - "name": "db.name", - "type": "string", - "brief": "This attribute is used to report the name of the database being accessed. For commands that switch the database, this should be set to the target database (even if the command fails).\n", - "examples": [ - "customers", - "main" - ], - "tag": "db-generic", - "requirement_level": "recommended", - "note": "In some SQL databases, the database name to be used is called \"schema name\". In case there are multiple layers that could be considered for database name (e.g. Oracle instance name and schema name), the database name to be used is the more specific layer (e.g. Oracle schema name).\n", - "stability": "stable" - }, - { - "name": "db.operation", - "type": "string", - "brief": "The HTTP method + the target REST route.\n", - "examples": [ - "GET /{db}/{docid}" - ], - "tag": "call-level-tech-specific", - "requirement_level": { - "conditionally_required": "If `db.statement` is not applicable." - }, - "note": "In **CouchDB**, `db.operation` should be set to the HTTP method + the target REST route according to the API reference documentation. For example, when retrieving a document, `db.operation` would be set to (literally, i.e., without replacing the placeholders with concrete values): [`GET /{db}/{docid}`](http://docs.couchdb.org/en/stable/api/document/common.html#get--db-docid).\n", - "stability": "stable" - }, - { - "name": "db.operation", - "type": "string", - "brief": "The endpoint identifier for the request.", - "examples": [ - "search", - "ml.close_job", - "cat.aliases" - ], - "tag": "call-level-tech-specific", - "requirement_level": "required", - "note": "When setting this to an SQL keyword, it is not recommended to attempt any client-side parsing of `db.statement` just to get this property, but it should be set if the operation name is provided by the library being instrumented. If the SQL statement has an ambiguous operation, or performs more than one operation, this value may be omitted.\n", - "stability": "stable" - }, - { - "name": "db.operation", - "type": "string", - "brief": "The name of the operation being executed, e.g. the [MongoDB command name](https://docs.mongodb.com/manual/reference/command/#database-operations) such as `findAndModify`, or the SQL keyword.\n", - "examples": [ - "findAndModify", - "HMSET", - "SELECT" - ], - "tag": "call-level", - "requirement_level": { - "conditionally_required": "If `db.statement` is not applicable." - }, - "note": "When setting this to an SQL keyword, it is not recommended to attempt any client-side parsing of `db.statement` just to get this property, but it should be set if the operation name is provided by the library being instrumented. If the SQL statement has an ambiguous operation, or performs more than one operation, this value may be omitted.\n", - "stability": "stable" - }, - { - "name": "db.operation", - "type": "string", - "brief": "The name of the operation being executed, e.g. the [MongoDB command name](https://docs.mongodb.com/manual/reference/command/#database-operations) such as `findAndModify`, or the SQL keyword.\n", - "examples": [ - "findAndModify", - "HMSET", - "SELECT" - ], - "tag": "db-generic", - "requirement_level": "recommended", - "note": "When setting this to an SQL keyword, it is not recommended to attempt any client-side parsing of `db.statement` just to get this property, but it should be set if the operation name is provided by the library being instrumented. If the SQL statement has an ambiguous operation, or performs more than one operation, this value may be omitted.\n", - "stability": "stable" - }, - { - "name": "db.redis.database_index", - "type": "int", - "brief": "The index of the database being accessed as used in the [`SELECT` command](https://redis.io/commands/select), provided as an integer. To be used instead of the generic `db.name` attribute.\n", - "examples": [ - 0, - 1, - 15 - ], - "tag": "call-level-tech-specific", - "requirement_level": { - "conditionally_required": "If other than the default database (`0`)." - }, - "stability": "stable" - }, - { - "name": "db.redis.database_index", - "type": "int", - "brief": "The index of the database being accessed as used in the [`SELECT` command](https://redis.io/commands/select), provided as an integer. To be used instead of the generic `db.name` attribute.\n", - "examples": [ - 0, - 1, - 15 - ], - "tag": "tech-specific-redis", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "db.sql.table", - "type": "string", - "brief": "The name of the primary table that the operation is acting upon, including the database name (if applicable).", - "examples": [ - "public.users", - "customers" - ], - "tag": "call-level-tech-specific", - "requirement_level": "recommended", - "note": "It is not recommended to attempt any client-side parsing of `db.statement` just to get this property, but it should be set if it is provided by the library being instrumented. If the operation is acting upon an anonymous table, or more than one table, this value MUST NOT be set.\n", - "stability": "stable" - }, - { - "name": "db.sql.table", - "type": "string", - "brief": "The name of the primary table that the operation is acting upon, including the database name (if applicable).", - "examples": [ - "public.users", - "customers" - ], - "tag": "tech-specific-sql", - "requirement_level": "recommended", - "note": "It is not recommended to attempt any client-side parsing of `db.statement` just to get this property, but it should be set if it is provided by the library being instrumented. If the operation is acting upon an anonymous table, or more than one table, this value MUST NOT be set.\n", - "stability": "stable" - }, - { - "name": "db.statement", - "type": "string", - "brief": "The database statement being executed.\n", - "examples": [ - "SELECT * FROM wuser_table", - "SET mykey \"WuValue\"" - ], - "tag": "call-level", - "requirement_level": { - "recommended": "Should be collected by default only if there is sanitization that excludes sensitive information.\n" - }, - "stability": "stable" - }, - { - "name": "db.statement", - "type": "string", - "brief": "The database statement being executed.\n", - "examples": [ - "SELECT * FROM wuser_table", - "SET mykey \"WuValue\"" - ], - "tag": "db-generic", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "db.statement", - "type": "string", - "brief": "The full syntax of the Redis CLI command.\n", - "examples": [ - "HMSET myhash field1 'Hello' field2 'World'" - ], - "tag": "call-level-tech-specific", - "requirement_level": { - "recommended": "Should be collected by default only if there is sanitization that excludes sensitive information.\n" - }, - "note": "For **Redis**, the value provided for `db.statement` SHOULD correspond to the syntax of the Redis CLI. If, for example, the [`HMSET` command](https://redis.io/commands/hmset) is invoked, `\"HMSET myhash field1 'Hello' field2 'World'\"` would be a suitable value for `db.statement`.\n", - "stability": "stable" - }, - { - "name": "db.statement", - "type": "string", - "brief": "The request body for a [search-type query](https://www.elastic.co/guide/en/elasticsearch/reference/current/search.html), as a json string.", - "examples": [ - "\"{\\\"query\\\":{\\\"term\\\":{\\\"user.id\\\":\\\"kimchy\\\"}}}\"" - ], - "tag": "call-level-tech-specific", - "requirement_level": { - "recommended": "Should be collected by default for search-type queries and only if there is sanitization that excludes sensitive information.\n" - }, - "stability": "stable" - }, - { - "name": "db.system", - "type": { - "members": [ - { - "id": "other_sql", - "value": "other_sql", - "brief": "Some other SQL database. Fallback only. See notes.", - "stability": "stable" - }, - { - "id": "mssql", - "value": "mssql", - "brief": "Microsoft SQL Server", - "stability": "stable" - }, - { - "id": "mssqlcompact", - "value": "mssqlcompact", - "brief": "Microsoft SQL Server Compact", - "stability": "stable" - }, - { - "id": "mysql", - "value": "mysql", - "brief": "MySQL", - "stability": "stable" - }, - { - "id": "oracle", - "value": "oracle", - "brief": "Oracle Database", - "stability": "stable" - }, - { - "id": "db2", - "value": "db2", - "brief": "IBM Db2", - "stability": "stable" - }, - { - "id": "postgresql", - "value": "postgresql", - "brief": "PostgreSQL", - "stability": "stable" - }, - { - "id": "redshift", - "value": "redshift", - "brief": "Amazon Redshift", - "stability": "stable" - }, - { - "id": "hive", - "value": "hive", - "brief": "Apache Hive", - "stability": "stable" - }, - { - "id": "cloudscape", - "value": "cloudscape", - "brief": "Cloudscape", - "stability": "stable" - }, - { - "id": "hsqldb", - "value": "hsqldb", - "brief": "HyperSQL DataBase", - "stability": "stable" - }, - { - "id": "progress", - "value": "progress", - "brief": "Progress Database", - "stability": "stable" - }, - { - "id": "maxdb", - "value": "maxdb", - "brief": "SAP MaxDB", - "stability": "stable" - }, - { - "id": "hanadb", - "value": "hanadb", - "brief": "SAP HANA", - "stability": "stable" - }, - { - "id": "ingres", - "value": "ingres", - "brief": "Ingres", - "stability": "stable" - }, - { - "id": "firstsql", - "value": "firstsql", - "brief": "FirstSQL", - "stability": "stable" - }, - { - "id": "edb", - "value": "edb", - "brief": "EnterpriseDB", - "stability": "stable" - }, - { - "id": "cache", - "value": "cache", - "brief": "InterSystems Caché", - "stability": "stable" - }, - { - "id": "adabas", - "value": "adabas", - "brief": "Adabas (Adaptable Database System)", - "stability": "stable" - }, - { - "id": "firebird", - "value": "firebird", - "brief": "Firebird", - "stability": "stable" - }, - { - "id": "derby", - "value": "derby", - "brief": "Apache Derby", - "stability": "stable" - }, - { - "id": "filemaker", - "value": "filemaker", - "brief": "FileMaker", - "stability": "stable" - }, - { - "id": "informix", - "value": "informix", - "brief": "Informix", - "stability": "stable" - }, - { - "id": "instantdb", - "value": "instantdb", - "brief": "InstantDB", - "stability": "stable" - }, - { - "id": "interbase", - "value": "interbase", - "brief": "InterBase", - "stability": "stable" - }, - { - "id": "mariadb", - "value": "mariadb", - "brief": "MariaDB", - "stability": "stable" - }, - { - "id": "netezza", - "value": "netezza", - "brief": "Netezza", - "stability": "stable" - }, - { - "id": "pervasive", - "value": "pervasive", - "brief": "Pervasive PSQL", - "stability": "stable" - }, - { - "id": "pointbase", - "value": "pointbase", - "brief": "PointBase", - "stability": "stable" - }, - { - "id": "sqlite", - "value": "sqlite", - "brief": "SQLite", - "stability": "stable" - }, - { - "id": "sybase", - "value": "sybase", - "brief": "Sybase", - "stability": "stable" - }, - { - "id": "teradata", - "value": "teradata", - "brief": "Teradata", - "stability": "stable" - }, - { - "id": "vertica", - "value": "vertica", - "brief": "Vertica", - "stability": "stable" - }, - { - "id": "h2", - "value": "h2", - "brief": "H2", - "stability": "stable" - }, - { - "id": "coldfusion", - "value": "coldfusion", - "brief": "ColdFusion IMQ", - "stability": "stable" - }, - { - "id": "cassandra", - "value": "cassandra", - "brief": "Apache Cassandra", - "stability": "stable" - }, - { - "id": "hbase", - "value": "hbase", - "brief": "Apache HBase", - "stability": "stable" - }, - { - "id": "mongodb", - "value": "mongodb", - "brief": "MongoDB", - "stability": "stable" - }, - { - "id": "redis", - "value": "redis", - "brief": "Redis", - "stability": "stable" - }, - { - "id": "couchbase", - "value": "couchbase", - "brief": "Couchbase", - "stability": "stable" - }, - { - "id": "couchdb", - "value": "couchdb", - "brief": "CouchDB", - "stability": "stable" - }, - { - "id": "cosmosdb", - "value": "cosmosdb", - "brief": "Microsoft Azure Cosmos DB", - "stability": "stable" - }, - { - "id": "dynamodb", - "value": "dynamodb", - "brief": "Amazon DynamoDB", - "stability": "stable" - }, - { - "id": "neo4j", - "value": "neo4j", - "brief": "Neo4j", - "stability": "stable" - }, - { - "id": "geode", - "value": "geode", - "brief": "Apache Geode", - "stability": "stable" - }, - { - "id": "elasticsearch", - "value": "elasticsearch", - "brief": "Elasticsearch", - "stability": "stable" - }, - { - "id": "memcached", - "value": "memcached", - "brief": "Memcached", - "stability": "stable" - }, - { - "id": "cockroachdb", - "value": "cockroachdb", - "brief": "CockroachDB", - "stability": "stable" - }, - { - "id": "opensearch", - "value": "opensearch", - "brief": "OpenSearch", - "stability": "stable" - }, - { - "id": "clickhouse", - "value": "clickhouse", - "brief": "ClickHouse", - "stability": "stable" - }, - { - "id": "spanner", - "value": "spanner", - "brief": "Cloud Spanner", - "stability": "stable" - }, - { - "id": "trino", - "value": "trino", - "brief": "Trino", - "stability": "stable" - } - ] - }, - "brief": "An identifier for the database management system (DBMS) product being used. See below for a list of well-known identifiers.", - "tag": "connection-level", - "requirement_level": "required", - "stability": "stable" - }, - { - "name": "db.system", - "type": { - "members": [ - { - "id": "other_sql", - "value": "other_sql", - "brief": "Some other SQL database. Fallback only. See notes.", - "stability": "stable" - }, - { - "id": "mssql", - "value": "mssql", - "brief": "Microsoft SQL Server", - "stability": "stable" - }, - { - "id": "mssqlcompact", - "value": "mssqlcompact", - "brief": "Microsoft SQL Server Compact", - "stability": "stable" - }, - { - "id": "mysql", - "value": "mysql", - "brief": "MySQL", - "stability": "stable" - }, - { - "id": "oracle", - "value": "oracle", - "brief": "Oracle Database", - "stability": "stable" - }, - { - "id": "db2", - "value": "db2", - "brief": "IBM Db2", - "stability": "stable" - }, - { - "id": "postgresql", - "value": "postgresql", - "brief": "PostgreSQL", - "stability": "stable" - }, - { - "id": "redshift", - "value": "redshift", - "brief": "Amazon Redshift", - "stability": "stable" - }, - { - "id": "hive", - "value": "hive", - "brief": "Apache Hive", - "stability": "stable" - }, - { - "id": "cloudscape", - "value": "cloudscape", - "brief": "Cloudscape", - "stability": "stable" - }, - { - "id": "hsqldb", - "value": "hsqldb", - "brief": "HyperSQL DataBase", - "stability": "stable" - }, - { - "id": "progress", - "value": "progress", - "brief": "Progress Database", - "stability": "stable" - }, - { - "id": "maxdb", - "value": "maxdb", - "brief": "SAP MaxDB", - "stability": "stable" - }, - { - "id": "hanadb", - "value": "hanadb", - "brief": "SAP HANA", - "stability": "stable" - }, - { - "id": "ingres", - "value": "ingres", - "brief": "Ingres", - "stability": "stable" - }, - { - "id": "firstsql", - "value": "firstsql", - "brief": "FirstSQL", - "stability": "stable" - }, - { - "id": "edb", - "value": "edb", - "brief": "EnterpriseDB", - "stability": "stable" - }, - { - "id": "cache", - "value": "cache", - "brief": "InterSystems Caché", - "stability": "stable" - }, - { - "id": "adabas", - "value": "adabas", - "brief": "Adabas (Adaptable Database System)", - "stability": "stable" - }, - { - "id": "firebird", - "value": "firebird", - "brief": "Firebird", - "stability": "stable" - }, - { - "id": "derby", - "value": "derby", - "brief": "Apache Derby", - "stability": "stable" - }, - { - "id": "filemaker", - "value": "filemaker", - "brief": "FileMaker", - "stability": "stable" - }, - { - "id": "informix", - "value": "informix", - "brief": "Informix", - "stability": "stable" - }, - { - "id": "instantdb", - "value": "instantdb", - "brief": "InstantDB", - "stability": "stable" - }, - { - "id": "interbase", - "value": "interbase", - "brief": "InterBase", - "stability": "stable" - }, - { - "id": "mariadb", - "value": "mariadb", - "brief": "MariaDB", - "stability": "stable" - }, - { - "id": "netezza", - "value": "netezza", - "brief": "Netezza", - "stability": "stable" - }, - { - "id": "pervasive", - "value": "pervasive", - "brief": "Pervasive PSQL", - "stability": "stable" - }, - { - "id": "pointbase", - "value": "pointbase", - "brief": "PointBase", - "stability": "stable" - }, - { - "id": "sqlite", - "value": "sqlite", - "brief": "SQLite", - "stability": "stable" - }, - { - "id": "sybase", - "value": "sybase", - "brief": "Sybase", - "stability": "stable" - }, - { - "id": "teradata", - "value": "teradata", - "brief": "Teradata", - "stability": "stable" - }, - { - "id": "vertica", - "value": "vertica", - "brief": "Vertica", - "stability": "stable" - }, - { - "id": "h2", - "value": "h2", - "brief": "H2", - "stability": "stable" - }, - { - "id": "coldfusion", - "value": "coldfusion", - "brief": "ColdFusion IMQ", - "stability": "stable" - }, - { - "id": "cassandra", - "value": "cassandra", - "brief": "Apache Cassandra", - "stability": "stable" - }, - { - "id": "hbase", - "value": "hbase", - "brief": "Apache HBase", - "stability": "stable" - }, - { - "id": "mongodb", - "value": "mongodb", - "brief": "MongoDB", - "stability": "stable" - }, - { - "id": "redis", - "value": "redis", - "brief": "Redis", - "stability": "stable" - }, - { - "id": "couchbase", - "value": "couchbase", - "brief": "Couchbase", - "stability": "stable" - }, - { - "id": "couchdb", - "value": "couchdb", - "brief": "CouchDB", - "stability": "stable" - }, - { - "id": "cosmosdb", - "value": "cosmosdb", - "brief": "Microsoft Azure Cosmos DB", - "stability": "stable" - }, - { - "id": "dynamodb", - "value": "dynamodb", - "brief": "Amazon DynamoDB", - "stability": "stable" - }, - { - "id": "neo4j", - "value": "neo4j", - "brief": "Neo4j", - "stability": "stable" - }, - { - "id": "geode", - "value": "geode", - "brief": "Apache Geode", - "stability": "stable" - }, - { - "id": "elasticsearch", - "value": "elasticsearch", - "brief": "Elasticsearch", - "stability": "stable" - }, - { - "id": "memcached", - "value": "memcached", - "brief": "Memcached", - "stability": "stable" - }, - { - "id": "cockroachdb", - "value": "cockroachdb", - "brief": "CockroachDB", - "stability": "stable" - }, - { - "id": "opensearch", - "value": "opensearch", - "brief": "OpenSearch", - "stability": "stable" - }, - { - "id": "clickhouse", - "value": "clickhouse", - "brief": "ClickHouse", - "stability": "stable" - }, - { - "id": "spanner", - "value": "spanner", - "brief": "Cloud Spanner", - "stability": "stable" - }, - { - "id": "trino", - "value": "trino", - "brief": "Trino", - "stability": "stable" - } - ] - }, - "brief": "An identifier for the database management system (DBMS) product being used. See below for a list of well-known identifiers.", - "tag": "db-generic", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "db.user", - "type": "string", - "brief": "Username for accessing the database.\n", - "examples": [ - "readonly_user", - "reporting_user" - ], - "tag": "connection-level", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "db.user", - "type": "string", - "brief": "Username for accessing the database.\n", - "examples": [ - "readonly_user", - "reporting_user" - ], - "tag": "db-generic", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "http.request.body.size", - "type": "int", - "brief": "The size of the request payload body in bytes. This is the number of bytes transferred excluding headers and is often, but not always, present as the [Content-Length](https://www.rfc-editor.org/rfc/rfc9110.html#field.content-length) header. For requests using transport encoding, this should be the compressed size.\n", - "examples": 3495, - "requirement_level": "recommended", - "stability": "development" - }, - { - "name": "http.request.header", - "type": "template[string[]]", - "brief": "HTTP request headers, `` being the normalized HTTP Header name (lowercase), the value being the header values.\n", - "examples": [ - [ - "application/json" - ], - [ - "1.2.3.4", - "1.2.3.5" - ] - ], - "requirement_level": "recommended", - "note": "Instrumentations SHOULD require an explicit configuration of which headers are to be captured. Including all request headers can be a security risk - explicit configuration helps avoid leaking sensitive information.\nThe `User-Agent` header is already captured in the `user_agent.original` attribute. Users MAY explicitly configure instrumentations to capture them even though it is not recommended.\nThe attribute value MUST consist of either multiple header values as an array of strings or a single-item array containing a possibly comma-concatenated string, depending on the way the HTTP library provides access to headers.\n", - "stability": "stable" - }, - { - "name": "http.request.method", - "type": { - "members": [ - { - "id": "connect", - "value": "CONNECT", - "brief": "CONNECT method.", - "stability": "stable" - }, - { - "id": "delete", - "value": "DELETE", - "brief": "DELETE method.", - "stability": "stable" - }, - { - "id": "get", - "value": "GET", - "brief": "GET method.", - "stability": "stable" - }, - { - "id": "head", - "value": "HEAD", - "brief": "HEAD method.", - "stability": "stable" - }, - { - "id": "options", - "value": "OPTIONS", - "brief": "OPTIONS method.", - "stability": "stable" - }, - { - "id": "patch", - "value": "PATCH", - "brief": "PATCH method.", - "stability": "stable" - }, - { - "id": "post", - "value": "POST", - "brief": "POST method.", - "stability": "stable" - }, - { - "id": "put", - "value": "PUT", - "brief": "PUT method.", - "stability": "stable" - }, - { - "id": "trace", - "value": "TRACE", - "brief": "TRACE method.", - "stability": "stable" - }, - { - "id": "other", - "value": "_OTHER", - "brief": "Any HTTP method that the instrumentation has no prior knowledge of.", - "stability": "stable" - } - ] - }, - "brief": "HTTP request method.", - "examples": [ - "GET", - "POST", - "HEAD" - ], - "requirement_level": "recommended", - "note": "HTTP request method value SHOULD be \"known\" to the instrumentation.\nBy default, this convention defines \"known\" methods as the ones listed in [RFC9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-methods)\nand the PATCH method defined in [RFC5789](https://www.rfc-editor.org/rfc/rfc5789.html).\n\nIf the HTTP request method is not known to instrumentation, it MUST set the `http.request.method` attribute to `_OTHER`.\n\nIf the HTTP instrumentation could end up converting valid HTTP request methods to `_OTHER`, then it MUST provide a way to override\nthe list of known HTTP methods. If this override is done via environment variable, then the environment variable MUST be named\nOTEL_INSTRUMENTATION_HTTP_KNOWN_METHODS and support a comma-separated list of case-sensitive known HTTP methods\n(this list MUST be a full override of the default known method, it is not a list of known methods in addition to the defaults).\n\nHTTP method names are case-sensitive and `http.request.method` attribute value MUST match a known HTTP method name exactly.\nInstrumentations for specific web frameworks that consider HTTP methods to be case insensitive, SHOULD populate a canonical equivalent.\nTracing instrumentations that do so, MUST also set `http.request.method_original` to the original value.\n", - "stability": "stable" - }, - { - "name": "http.request.method", - "type": { - "members": [ - { - "id": "connect", - "value": "CONNECT", - "brief": "CONNECT method.", - "stability": "stable" - }, - { - "id": "delete", - "value": "DELETE", - "brief": "DELETE method.", - "stability": "stable" - }, - { - "id": "get", - "value": "GET", - "brief": "GET method.", - "stability": "stable" - }, - { - "id": "head", - "value": "HEAD", - "brief": "HEAD method.", - "stability": "stable" - }, - { - "id": "options", - "value": "OPTIONS", - "brief": "OPTIONS method.", - "stability": "stable" - }, - { - "id": "patch", - "value": "PATCH", - "brief": "PATCH method.", - "stability": "stable" - }, - { - "id": "post", - "value": "POST", - "brief": "POST method.", - "stability": "stable" - }, - { - "id": "put", - "value": "PUT", - "brief": "PUT method.", - "stability": "stable" - }, - { - "id": "trace", - "value": "TRACE", - "brief": "TRACE method.", - "stability": "stable" - }, - { - "id": "other", - "value": "_OTHER", - "brief": "Any HTTP method that the instrumentation has no prior knowledge of.", - "stability": "stable" - } - ] - }, - "brief": "HTTP request method.", - "examples": [ - "GET", - "POST", - "HEAD" - ], - "tag": "call-level-tech-specific", - "requirement_level": "required", - "note": "HTTP request method value SHOULD be \"known\" to the instrumentation.\nBy default, this convention defines \"known\" methods as the ones listed in [RFC9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-methods)\nand the PATCH method defined in [RFC5789](https://www.rfc-editor.org/rfc/rfc5789.html).\n\nIf the HTTP request method is not known to instrumentation, it MUST set the `http.request.method` attribute to `_OTHER`.\n\nIf the HTTP instrumentation could end up converting valid HTTP request methods to `_OTHER`, then it MUST provide a way to override\nthe list of known HTTP methods. If this override is done via environment variable, then the environment variable MUST be named\nOTEL_INSTRUMENTATION_HTTP_KNOWN_METHODS and support a comma-separated list of case-sensitive known HTTP methods\n(this list MUST be a full override of the default known method, it is not a list of known methods in addition to the defaults).\n\nHTTP method names are case-sensitive and `http.request.method` attribute value MUST match a known HTTP method name exactly.\nInstrumentations for specific web frameworks that consider HTTP methods to be case insensitive, SHOULD populate a canonical equivalent.\nTracing instrumentations that do so, MUST also set `http.request.method_original` to the original value.\n", - "stability": "stable" - }, - { - "name": "http.request.method_original", - "type": "string", - "brief": "Original HTTP method sent by the client in the request line.", - "examples": [ - "GeT", - "ACL", - "foo" - ], - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "http.request.resend_count", - "type": "int", - "brief": "The ordinal number of request resending attempt (for any reason, including redirects).\n", - "examples": 3, - "requirement_level": "recommended", - "note": "The resend count SHOULD be updated each time an HTTP request gets resent by the client, regardless of what was the cause of the resending (e.g. redirection, authorization failure, 503 Server Unavailable, network issues, or any other).\n", - "stability": "stable" - }, - { - "name": "http.response.body.size", - "type": "int", - "brief": "The size of the response payload body in bytes. This is the number of bytes transferred excluding headers and is often, but not always, present as the [Content-Length](https://www.rfc-editor.org/rfc/rfc9110.html#field.content-length) header. For requests using transport encoding, this should be the compressed size.\n", - "examples": 3495, - "requirement_level": "recommended", - "stability": "development" - }, - { - "name": "http.response.header", - "type": "template[string[]]", - "brief": "HTTP response headers, `` being the normalized HTTP Header name (lowercase), the value being the header values.\n", - "examples": [ - [ - "application/json" - ], - [ - "abc", - "def" - ] - ], - "requirement_level": "recommended", - "note": "Instrumentations SHOULD require an explicit configuration of which headers are to be captured. Including all response headers can be a security risk - explicit configuration helps avoid leaking sensitive information.\nUsers MAY explicitly configure instrumentations to capture them even though it is not recommended.\nThe attribute value MUST consist of either multiple header values as an array of strings or a single-item array containing a possibly comma-concatenated string, depending on the way the HTTP library provides access to headers.\n", - "stability": "stable" - }, - { - "name": "http.response.status_code", - "type": "int", - "brief": "[HTTP response status code](https://tools.ietf.org/html/rfc7231#section-6).", - "examples": [ - 200 - ], - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "http.route", - "type": "string", - "brief": "The matched route, that is, the path template in the format used by the respective server framework.\n", - "examples": [ - "/users/:userID?", - "{controller}/{action}/{id?}" - ], - "requirement_level": "recommended", - "note": "MUST NOT be populated when this is not supported by the HTTP server framework as the route attribute should have low-cardinality and the URI path can NOT substitute it.\nSHOULD include the [application root](/docs/http/http-spans.md#http-server-definitions) if there is one.", - "stability": "stable" - }, - { - "name": "network.carrier.icc", - "type": "string", - "brief": "The ISO 3166-1 alpha-2 2-character country code associated with the mobile carrier network.", - "examples": "DE", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "network.carrier.mcc", - "type": "string", - "brief": "The mobile carrier country code.", - "examples": "310", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "network.carrier.mnc", - "type": "string", - "brief": "The mobile carrier network code.", - "examples": "001", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "network.carrier.name", - "type": "string", - "brief": "The name of the mobile carrier.", - "examples": "sprint", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "network.connection.subtype", - "type": { - "members": [ - { - "id": "gprs", - "value": "gprs", - "brief": "GPRS", - "stability": "stable" - }, - { - "id": "edge", - "value": "edge", - "brief": "EDGE", - "stability": "stable" - }, - { - "id": "umts", - "value": "umts", - "brief": "UMTS", - "stability": "stable" - }, - { - "id": "cdma", - "value": "cdma", - "brief": "CDMA", - "stability": "stable" - }, - { - "id": "evdo_0", - "value": "evdo_0", - "brief": "EVDO Rel. 0", - "stability": "stable" - }, - { - "id": "evdo_a", - "value": "evdo_a", - "brief": "EVDO Rev. A", - "stability": "stable" - }, - { - "id": "cdma2000_1xrtt", - "value": "cdma2000_1xrtt", - "brief": "CDMA2000 1XRTT", - "stability": "stable" - }, - { - "id": "hsdpa", - "value": "hsdpa", - "brief": "HSDPA", - "stability": "stable" - }, - { - "id": "hsupa", - "value": "hsupa", - "brief": "HSUPA", - "stability": "stable" - }, - { - "id": "hspa", - "value": "hspa", - "brief": "HSPA", - "stability": "stable" - }, - { - "id": "iden", - "value": "iden", - "brief": "IDEN", - "stability": "stable" - }, - { - "id": "evdo_b", - "value": "evdo_b", - "brief": "EVDO Rev. B", - "stability": "stable" - }, - { - "id": "lte", - "value": "lte", - "brief": "LTE", - "stability": "stable" - }, - { - "id": "ehrpd", - "value": "ehrpd", - "brief": "EHRPD", - "stability": "stable" - }, - { - "id": "hspap", - "value": "hspap", - "brief": "HSPAP", - "stability": "stable" - }, - { - "id": "gsm", - "value": "gsm", - "brief": "GSM", - "stability": "stable" - }, - { - "id": "td_scdma", - "value": "td_scdma", - "brief": "TD-SCDMA", - "stability": "stable" - }, - { - "id": "iwlan", - "value": "iwlan", - "brief": "IWLAN", - "stability": "stable" - }, - { - "id": "nr", - "value": "nr", - "brief": "5G NR (New Radio)", - "stability": "stable" - }, - { - "id": "nrnsa", - "value": "nrnsa", - "brief": "5G NRNSA (New Radio Non-Standalone)", - "stability": "stable" - }, - { - "id": "lte_ca", - "value": "lte_ca", - "brief": "LTE CA", - "stability": "stable" - } - ] - }, - "brief": "This describes more details regarding the connection.type. It may be the type of cell technology connection, but it could be used for describing details about a wifi connection.", - "examples": "LTE", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "network.connection.type", - "type": { - "members": [ - { - "id": "wifi", - "value": "wifi", - "stability": "stable" - }, - { - "id": "wired", - "value": "wired", - "stability": "stable" - }, - { - "id": "cell", - "value": "cell", - "stability": "stable" - }, - { - "id": "unavailable", - "value": "unavailable", - "stability": "stable" - }, - { - "id": "unknown", - "value": "unknown", - "stability": "stable" - } - ] - }, - "brief": "The internet connection type.", - "examples": "wifi", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "network.io.direction", - "type": { - "members": [ - { - "id": "transmit", - "value": "transmit", - "stability": "stable" - }, - { - "id": "receive", - "value": "receive", - "stability": "stable" - } - ] - }, - "brief": "The network IO operation direction.", - "examples": [ - "transmit" - ], - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "network.local.address", - "type": "string", - "brief": "Local address of the network connection - IP address or Unix domain socket name.", - "examples": [ - "10.1.2.80", - "/tmp/my.sock" - ], - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "network.local.port", - "type": "int", - "brief": "Local port number of the network connection.", - "examples": [ - 65123 - ], - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "network.peer.address", - "type": "string", - "brief": "Peer address of the network connection - IP address or Unix domain socket name.", - "examples": [ - "10.1.2.80", - "/tmp/my.sock" - ], - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "network.peer.address", - "type": "string", - "brief": "Peer address of the network connection - IP address or Unix domain socket name.", - "examples": [ - "10.1.2.80", - "/tmp/my.sock" - ], - "tag": "connection-level", - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "network.peer.port", - "type": "int", - "brief": "Peer port number of the network connection.", - "examples": [ - 65123 - ], - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "network.peer.port", - "type": "int", - "brief": "Peer port number of the network connection.", - "examples": [ - 65123 - ], - "tag": "connection-level", - "requirement_level": { - "recommended": "If `network.peer.address` is set." - }, - "stability": "stable" - }, - { - "name": "network.protocol.name", - "type": "string", - "brief": "[OSI application layer](https://osi-model.com/application-layer/) or non-OSI equivalent.", - "examples": [ - "amqp", - "http", - "mqtt" - ], - "requirement_level": "recommended", - "note": "The value SHOULD be normalized to lowercase.", - "stability": "stable" - }, - { - "name": "network.protocol.version", - "type": "string", - "brief": "Version of the protocol specified in `network.protocol.name`.", - "examples": "3.1.1", - "requirement_level": "recommended", - "note": "`network.protocol.version` refers to the version of the protocol used and might be different from the protocol client's version. If the HTTP client has a version of `0.27.2`, but sends HTTP version `1.1`, this attribute should be set to `1.1`.\n", - "stability": "stable" - }, - { - "name": "network.transport", - "type": { - "members": [ - { - "id": "tcp", - "value": "tcp", - "brief": "TCP", - "stability": "stable" - }, - { - "id": "udp", - "value": "udp", - "brief": "UDP", - "stability": "stable" - }, - { - "id": "pipe", - "value": "pipe", - "brief": "Named or anonymous pipe.", - "stability": "stable" - }, - { - "id": "unix", - "value": "unix", - "brief": "Unix domain socket", - "stability": "stable" - } - ] - }, - "brief": "[OSI transport layer](https://osi-model.com/transport-layer/) or [inter-process communication method](https://wikipedia.org/wiki/Inter-process_communication).\n", - "examples": [ - "tcp", - "udp" - ], - "requirement_level": "recommended", - "note": "The value SHOULD be normalized to lowercase.\n\nConsider always setting the transport when setting a port number, since\na port number is ambiguous without knowing the transport. For example\ndifferent processes could be listening on TCP port 12345 and UDP port 12345.\n", - "stability": "stable" - }, - { - "name": "network.transport", - "type": { - "members": [ - { - "id": "tcp", - "value": "tcp", - "brief": "TCP", - "stability": "stable" - }, - { - "id": "udp", - "value": "udp", - "brief": "UDP", - "stability": "stable" - }, - { - "id": "pipe", - "value": "pipe", - "brief": "Named or anonymous pipe.", - "stability": "stable" - }, - { - "id": "unix", - "value": "unix", - "brief": "Unix domain socket", - "stability": "stable" - } - ] - }, - "brief": "[OSI transport layer](https://osi-model.com/transport-layer/) or [inter-process communication method](https://wikipedia.org/wiki/Inter-process_communication).\n", - "examples": [ - "tcp", - "udp" - ], - "tag": "connection-level", - "requirement_level": "recommended", - "note": "The value SHOULD be normalized to lowercase.\n\nConsider always setting the transport when setting a port number, since\na port number is ambiguous without knowing the transport. For example\ndifferent processes could be listening on TCP port 12345 and UDP port 12345.\n", - "stability": "stable" - }, - { - "name": "network.type", - "type": { - "members": [ - { - "id": "ipv4", - "value": "ipv4", - "brief": "IPv4", - "stability": "stable" - }, - { - "id": "ipv6", - "value": "ipv6", - "brief": "IPv6", - "stability": "stable" - } - ] - }, - "brief": "[OSI network layer](https://osi-model.com/network-layer/) or non-OSI equivalent.", - "examples": [ - "ipv4", - "ipv6" - ], - "requirement_level": "recommended", - "note": "The value SHOULD be normalized to lowercase.", - "stability": "stable" - }, - { - "name": "network.type", - "type": { - "members": [ - { - "id": "ipv4", - "value": "ipv4", - "brief": "IPv4", - "stability": "stable" - }, - { - "id": "ipv6", - "value": "ipv6", - "brief": "IPv6", - "stability": "stable" - } - ] - }, - "brief": "[OSI network layer](https://osi-model.com/network-layer/) or non-OSI equivalent.", - "examples": [ - "ipv4", - "ipv6" - ], - "tag": "connection-level", - "requirement_level": "recommended", - "note": "The value SHOULD be normalized to lowercase.", - "stability": "stable" - }, - { - "name": "server.address", - "type": "string", - "brief": "Name of the database host.\n", - "examples": [ - "example.com", - "10.1.2.80", - "/tmp/my.sock" - ], - "tag": "call-level-tech-specific", - "requirement_level": "recommended", - "note": "When observed from the client side, and when communicating through an intermediary, `server.address` SHOULD represent the server address behind any intermediaries, for example proxies, if it's available.\n", - "stability": "stable" - }, - { - "name": "server.address", - "type": "string", - "brief": "Name of the database host.\n", - "examples": [ - "example.com", - "10.1.2.80", - "/tmp/my.sock" - ], - "tag": "connection-level", - "requirement_level": "recommended", - "note": "When observed from the client side, and when communicating through an intermediary, `server.address` SHOULD represent the server address behind any intermediaries, for example proxies, if it's available.\n", - "stability": "stable" - }, - { - "name": "server.address", - "type": "string", - "brief": "Server domain name if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name.", - "examples": [ - "example.com", - "10.1.2.80", - "/tmp/my.sock" - ], - "requirement_level": "recommended", - "note": "When observed from the client side, and when communicating through an intermediary, `server.address` SHOULD represent the server address behind any intermediaries, for example proxies, if it's available.\n", - "stability": "stable" - }, - { - "name": "server.port", - "type": "int", - "brief": "Server port number.", - "examples": [ - 80, - 8080, - 443 - ], - "requirement_level": "recommended", - "note": "When observed from the client side, and when communicating through an intermediary, `server.port` SHOULD represent the server port behind any intermediaries, for example proxies, if it's available.\n", - "stability": "stable" - }, - { - "name": "server.port", - "type": "int", - "brief": "Server port number.", - "examples": [ - 80, - 8080, - 443 - ], - "tag": "call-level-tech-specific", - "requirement_level": { - "conditionally_required": "If using a port other than the default port for this DBMS and if `server.address` is set." - }, - "note": "When observed from the client side, and when communicating through an intermediary, `server.port` SHOULD represent the server port behind any intermediaries, for example proxies, if it's available.\n", - "stability": "stable" - }, - { - "name": "server.port", - "type": "int", - "brief": "Server port number.", - "examples": [ - 80, - 8080, - 443 - ], - "tag": "connection-level", - "requirement_level": { - "conditionally_required": "If using a port other than the default port for this DBMS and if `server.address` is set." - }, - "note": "When observed from the client side, and when communicating through an intermediary, `server.port` SHOULD represent the server port behind any intermediaries, for example proxies, if it's available.\n", - "stability": "stable" - }, - { - "name": "url.fragment", - "type": "string", - "brief": "The [URI fragment](https://www.rfc-editor.org/rfc/rfc3986#section-3.5) component", - "examples": [ - "SemConv" - ], - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "url.full", - "type": "string", - "brief": "Absolute URL describing a network resource according to [RFC3986](https://www.rfc-editor.org/rfc/rfc3986)", - "examples": [ - "https://localhost:9200/index/_search?q=user.id:kimchy" - ], - "tag": "call-level-tech-specific", - "requirement_level": "required", - "note": "For network calls, URL usually has `scheme://host[:port][path][?query][#fragment]` format, where the fragment is not transmitted over HTTP, but if it is known, it SHOULD be included nevertheless.\n`url.full` MUST NOT contain credentials passed via URL in form of `https://username:password@www.example.com/`. In such case username and password SHOULD be redacted and attribute's value SHOULD be `https://REDACTED:REDACTED@www.example.com/`.\n`url.full` SHOULD capture the absolute URL when it is available (or can be reconstructed) and SHOULD NOT be validated or modified except for sanitizing purposes.\n", - "stability": "stable" - }, - { - "name": "url.full", - "type": "string", - "brief": "Absolute URL describing a network resource according to [RFC3986](https://www.rfc-editor.org/rfc/rfc3986)", - "examples": [ - "https://www.foo.bar/search?q=OpenTelemetry#SemConv", - "//localhost" - ], - "requirement_level": "recommended", - "note": "For network calls, URL usually has `scheme://host[:port][path][?query][#fragment]` format, where the fragment is not transmitted over HTTP, but if it is known, it SHOULD be included nevertheless.\n`url.full` MUST NOT contain credentials passed via URL in form of `https://username:password@www.example.com/`. In such case username and password SHOULD be redacted and attribute's value SHOULD be `https://REDACTED:REDACTED@www.example.com/`.\n`url.full` SHOULD capture the absolute URL when it is available (or can be reconstructed) and SHOULD NOT be validated or modified except for sanitizing purposes.\n", - "stability": "stable" - }, - { - "name": "url.path", - "type": "string", - "brief": "The [URI path](https://www.rfc-editor.org/rfc/rfc3986#section-3.3) component", - "examples": [ - "/search" - ], - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "url.query", - "type": "string", - "brief": "The [URI query](https://www.rfc-editor.org/rfc/rfc3986#section-3.4) component", - "examples": [ - "q=OpenTelemetry" - ], - "requirement_level": "recommended", - "note": "Sensitive content provided in query string SHOULD be scrubbed when instrumentations can identify it.", - "stability": "stable" - }, - { - "name": "url.scheme", - "type": "string", - "brief": "The [URI scheme](https://www.rfc-editor.org/rfc/rfc3986#section-3.1) component identifying the used protocol.", - "examples": [ - "https", - "ftp", - "telnet" - ], - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "user_agent.original", - "type": "string", - "brief": "Full user-agent string is generated by Cosmos DB SDK", - "examples": [ - "cosmos-netstandard-sdk/3.23.0\\|3.23.1\\|1\\|X64\\|Linux 5.4.0-1098-azure 104 18\\|.NET Core 3.1.32\\|S\\|" - ], - "tag": "call-level-tech-specific", - "requirement_level": "recommended", - "note": "The user-agent value is generated by SDK which is a combination of
`sdk_version` : Current version of SDK. e.g. 'cosmos-netstandard-sdk/3.23.0'
`direct_pkg_version` : Direct package version used by Cosmos DB SDK. e.g. '3.23.1'
`number_of_client_instances` : Number of cosmos client instances created by the application. e.g. '1'
`type_of_machine_architecture` : Machine architecture. e.g. 'X64'
`operating_system` : Operating System. e.g. 'Linux 5.4.0-1098-azure 104 18'
`runtime_framework` : Runtime Framework. e.g. '.NET Core 3.1.32'
`failover_information` : Generated key to determine if region failover enabled.\n Format Reg-{D (Disabled discovery)}-S(application region)|L(List of preferred regions)|N(None, user did not configure it).\n Default value is \"NS\".\n", - "stability": "stable" - }, - { - "name": "user_agent.original", - "type": "string", - "brief": "Value of the [HTTP User-Agent](https://www.rfc-editor.org/rfc/rfc9110.html#field.user-agent) header sent by the client.\n", - "examples": [ - "CERN-LineMode/2.15 libwww/2.17b3", - "Mozilla/5.0 (iPhone; CPU iPhone OS 14_7_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Mobile/15E148 Safari/604.1" - ], - "requirement_level": "recommended", - "stability": "stable" - } -] \ No newline at end of file +{ + "attributes": [ + { + "name": "db.cassandra.consistency_level", + "type": { + "members": [ + { + "id": "all", + "value": "all", + "stability": "stable" + }, + { + "id": "each_quorum", + "value": "each_quorum", + "stability": "stable" + }, + { + "id": "quorum", + "value": "quorum", + "stability": "stable" + }, + { + "id": "local_quorum", + "value": "local_quorum", + "stability": "stable" + }, + { + "id": "one", + "value": "one", + "stability": "stable" + }, + { + "id": "two", + "value": "two", + "stability": "stable" + }, + { + "id": "three", + "value": "three", + "stability": "stable" + }, + { + "id": "local_one", + "value": "local_one", + "stability": "stable" + }, + { + "id": "any", + "value": "any", + "stability": "stable" + }, + { + "id": "serial", + "value": "serial", + "stability": "stable" + }, + { + "id": "local_serial", + "value": "local_serial", + "stability": "stable" + } + ] + }, + "brief": "The consistency level of the query. Based on consistency values from [CQL](https://docs.datastax.com/en/cassandra-oss/3.0/cassandra/dml/dmlConfigConsistency.html).\n", + "tag": "call-level-tech-specific-cassandra", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "db.cassandra.consistency_level", + "type": { + "members": [ + { + "id": "all", + "value": "all", + "stability": "stable" + }, + { + "id": "each_quorum", + "value": "each_quorum", + "stability": "stable" + }, + { + "id": "quorum", + "value": "quorum", + "stability": "stable" + }, + { + "id": "local_quorum", + "value": "local_quorum", + "stability": "stable" + }, + { + "id": "one", + "value": "one", + "stability": "stable" + }, + { + "id": "two", + "value": "two", + "stability": "stable" + }, + { + "id": "three", + "value": "three", + "stability": "stable" + }, + { + "id": "local_one", + "value": "local_one", + "stability": "stable" + }, + { + "id": "any", + "value": "any", + "stability": "stable" + }, + { + "id": "serial", + "value": "serial", + "stability": "stable" + }, + { + "id": "local_serial", + "value": "local_serial", + "stability": "stable" + } + ] + }, + "brief": "The consistency level of the query. Based on consistency values from [CQL](https://docs.datastax.com/en/cassandra-oss/3.0/cassandra/dml/dmlConfigConsistency.html).\n", + "tag": "tech-specific-cassandra", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "db.cassandra.coordinator.dc", + "type": "string", + "brief": "The data center of the coordinating node for a query.\n", + "examples": "us-west-2", + "tag": "call-level-tech-specific-cassandra", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "db.cassandra.coordinator.dc", + "type": "string", + "brief": "The data center of the coordinating node for a query.\n", + "examples": "us-west-2", + "tag": "tech-specific-cassandra", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "db.cassandra.coordinator.id", + "type": "string", + "brief": "The ID of the coordinating node for a query.\n", + "examples": "be13faa2-8574-4d71-926d-27f16cf8a7af", + "tag": "call-level-tech-specific-cassandra", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "db.cassandra.coordinator.id", + "type": "string", + "brief": "The ID of the coordinating node for a query.\n", + "examples": "be13faa2-8574-4d71-926d-27f16cf8a7af", + "tag": "tech-specific-cassandra", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "db.cassandra.idempotence", + "type": "boolean", + "brief": "Whether or not the query is idempotent.\n", + "tag": "call-level-tech-specific-cassandra", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "db.cassandra.idempotence", + "type": "boolean", + "brief": "Whether or not the query is idempotent.\n", + "tag": "tech-specific-cassandra", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "db.cassandra.page_size", + "type": "int", + "brief": "The fetch size used for paging, i.e. how many rows will be returned at once.\n", + "examples": [ + 5000 + ], + "tag": "call-level-tech-specific-cassandra", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "db.cassandra.page_size", + "type": "int", + "brief": "The fetch size used for paging, i.e. how many rows will be returned at once.\n", + "examples": [ + 5000 + ], + "tag": "tech-specific-cassandra", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "db.cassandra.speculative_execution_count", + "type": "int", + "brief": "The number of times a query was speculatively executed. Not set or `0` if the query was not executed speculatively.\n", + "examples": [ + 0, + 2 + ], + "tag": "call-level-tech-specific-cassandra", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "db.cassandra.speculative_execution_count", + "type": "int", + "brief": "The number of times a query was speculatively executed. Not set or `0` if the query was not executed speculatively.\n", + "examples": [ + 0, + 2 + ], + "tag": "tech-specific-cassandra", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "db.cassandra.table", + "type": "string", + "brief": "The name of the primary Cassandra table that the operation is acting upon, including the keyspace name (if applicable).", + "examples": "mytable", + "tag": "call-level-tech-specific-cassandra", + "requirement_level": "recommended", + "note": "This mirrors the db.sql.table attribute but references cassandra rather than sql. It is not recommended to attempt any client-side parsing of `db.statement` just to get this property, but it should be set if it is provided by the library being instrumented. If the operation is acting upon an anonymous table, or more than one table, this value MUST NOT be set.\n", + "stability": "stable" + }, + { + "name": "db.cassandra.table", + "type": "string", + "brief": "The name of the primary Cassandra table that the operation is acting upon, including the keyspace name (if applicable).", + "examples": "mytable", + "tag": "tech-specific-cassandra", + "requirement_level": "recommended", + "note": "This mirrors the db.sql.table attribute but references cassandra rather than sql. It is not recommended to attempt any client-side parsing of `db.statement` just to get this property, but it should be set if it is provided by the library being instrumented. If the operation is acting upon an anonymous table, or more than one table, this value MUST NOT be set.\n", + "stability": "stable" + }, + { + "name": "db.connection_string", + "type": "string", + "brief": "The connection string used to connect to the database. It is recommended to remove embedded credentials.\n", + "examples": "Server=(localdb)\\v11.0;Integrated Security=true;", + "tag": "connection-level", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "db.connection_string", + "type": "string", + "brief": "The connection string used to connect to the database. It is recommended to remove embedded credentials.\n", + "examples": "Server=(localdb)\\v11.0;Integrated Security=true;", + "tag": "db-generic", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "db.cosmosdb.client_id", + "type": "string", + "brief": "Unique Cosmos client instance id.", + "examples": "3ba4827d-4422-483f-b59f-85b74211c11d", + "tag": "call-level-tech-specific", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "db.cosmosdb.client_id", + "type": "string", + "brief": "Unique Cosmos client instance id.", + "examples": "3ba4827d-4422-483f-b59f-85b74211c11d", + "tag": "tech-specific-cosmosdb", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "db.cosmosdb.connection_mode", + "type": { + "members": [ + { + "id": "gateway", + "value": "gateway", + "brief": "Gateway (HTTP) connections mode", + "stability": "stable" + }, + { + "id": "direct", + "value": "direct", + "brief": "Direct connection.", + "stability": "stable" + } + ] + }, + "brief": "Cosmos client connection mode.", + "tag": "call-level-tech-specific", + "requirement_level": { + "conditionally_required": "if not `direct` (or pick gw as default)" + }, + "stability": "stable" + }, + { + "name": "db.cosmosdb.connection_mode", + "type": { + "members": [ + { + "id": "gateway", + "value": "gateway", + "brief": "Gateway (HTTP) connections mode", + "stability": "stable" + }, + { + "id": "direct", + "value": "direct", + "brief": "Direct connection.", + "stability": "stable" + } + ] + }, + "brief": "Cosmos client connection mode.", + "tag": "tech-specific-cosmosdb", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "db.cosmosdb.container", + "type": "string", + "brief": "Cosmos DB container name.", + "examples": "anystring", + "tag": "call-level-tech-specific", + "requirement_level": { + "conditionally_required": "if available" + }, + "stability": "stable" + }, + { + "name": "db.cosmosdb.container", + "type": "string", + "brief": "Cosmos DB container name.", + "examples": "anystring", + "tag": "tech-specific-cosmosdb", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "db.cosmosdb.operation_type", + "type": { + "members": [ + { + "id": "invalid", + "value": "Invalid", + "stability": "stable" + }, + { + "id": "create", + "value": "Create", + "stability": "stable" + }, + { + "id": "patch", + "value": "Patch", + "stability": "stable" + }, + { + "id": "read", + "value": "Read", + "stability": "stable" + }, + { + "id": "read_feed", + "value": "ReadFeed", + "stability": "stable" + }, + { + "id": "delete", + "value": "Delete", + "stability": "stable" + }, + { + "id": "replace", + "value": "Replace", + "stability": "stable" + }, + { + "id": "execute", + "value": "Execute", + "stability": "stable" + }, + { + "id": "query", + "value": "Query", + "stability": "stable" + }, + { + "id": "head", + "value": "Head", + "stability": "stable" + }, + { + "id": "head_feed", + "value": "HeadFeed", + "stability": "stable" + }, + { + "id": "upsert", + "value": "Upsert", + "stability": "stable" + }, + { + "id": "batch", + "value": "Batch", + "stability": "stable" + }, + { + "id": "query_plan", + "value": "QueryPlan", + "stability": "stable" + }, + { + "id": "execute_javascript", + "value": "ExecuteJavaScript", + "stability": "stable" + } + ] + }, + "brief": "CosmosDB Operation Type.", + "tag": "call-level-tech-specific", + "requirement_level": { + "conditionally_required": "when performing one of the operations in this list" + }, + "stability": "stable" + }, + { + "name": "db.cosmosdb.operation_type", + "type": { + "members": [ + { + "id": "invalid", + "value": "Invalid", + "stability": "stable" + }, + { + "id": "create", + "value": "Create", + "stability": "stable" + }, + { + "id": "patch", + "value": "Patch", + "stability": "stable" + }, + { + "id": "read", + "value": "Read", + "stability": "stable" + }, + { + "id": "read_feed", + "value": "ReadFeed", + "stability": "stable" + }, + { + "id": "delete", + "value": "Delete", + "stability": "stable" + }, + { + "id": "replace", + "value": "Replace", + "stability": "stable" + }, + { + "id": "execute", + "value": "Execute", + "stability": "stable" + }, + { + "id": "query", + "value": "Query", + "stability": "stable" + }, + { + "id": "head", + "value": "Head", + "stability": "stable" + }, + { + "id": "head_feed", + "value": "HeadFeed", + "stability": "stable" + }, + { + "id": "upsert", + "value": "Upsert", + "stability": "stable" + }, + { + "id": "batch", + "value": "Batch", + "stability": "stable" + }, + { + "id": "query_plan", + "value": "QueryPlan", + "stability": "stable" + }, + { + "id": "execute_javascript", + "value": "ExecuteJavaScript", + "stability": "stable" + } + ] + }, + "brief": "CosmosDB Operation Type.", + "tag": "tech-specific-cosmosdb", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "db.cosmosdb.request_charge", + "type": "double", + "brief": "RU consumed for that operation", + "examples": [ + 46.18, + 1.0 + ], + "tag": "call-level-tech-specific", + "requirement_level": { + "conditionally_required": "when available" + }, + "stability": "stable" + }, + { + "name": "db.cosmosdb.request_charge", + "type": "double", + "brief": "RU consumed for that operation", + "examples": [ + 46.18, + 1.0 + ], + "tag": "tech-specific-cosmosdb", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "db.cosmosdb.request_content_length", + "type": "int", + "brief": "Request payload size in bytes", + "tag": "call-level-tech-specific", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "db.cosmosdb.request_content_length", + "type": "int", + "brief": "Request payload size in bytes", + "tag": "tech-specific-cosmosdb", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "db.cosmosdb.status_code", + "type": "int", + "brief": "Cosmos DB status code.", + "examples": [ + 200, + 201 + ], + "tag": "call-level-tech-specific", + "requirement_level": { + "conditionally_required": "if response was received" + }, + "stability": "stable" + }, + { + "name": "db.cosmosdb.status_code", + "type": "int", + "brief": "Cosmos DB status code.", + "examples": [ + 200, + 201 + ], + "tag": "tech-specific-cosmosdb", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "db.cosmosdb.sub_status_code", + "type": "int", + "brief": "Cosmos DB sub status code.", + "examples": [ + 1000, + 1002 + ], + "tag": "call-level-tech-specific", + "requirement_level": { + "conditionally_required": "when response was received and contained sub-code." + }, + "stability": "stable" + }, + { + "name": "db.cosmosdb.sub_status_code", + "type": "int", + "brief": "Cosmos DB sub status code.", + "examples": [ + 1000, + 1002 + ], + "tag": "tech-specific-cosmosdb", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "db.elasticsearch.cluster.name", + "type": "string", + "brief": "Represents the identifier of an Elasticsearch cluster.\n", + "examples": [ + "e9106fc68e3044f0b1475b04bf4ffd5f" + ], + "tag": "call-level-tech-specific", + "requirement_level": { + "recommended": "When communicating with an Elastic Cloud deployment, this should be collected from the \"X-Found-Handling-Cluster\" HTTP response header.\n" + }, + "stability": "stable" + }, + { + "name": "db.elasticsearch.cluster.name", + "type": "string", + "brief": "Represents the identifier of an Elasticsearch cluster.\n", + "examples": [ + "e9106fc68e3044f0b1475b04bf4ffd5f" + ], + "tag": "tech-specific-elasticsearch", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "db.elasticsearch.node.name", + "type": "string", + "brief": "Represents the human-readable identifier of the node/instance to which a request was routed.\n", + "examples": [ + "instance-0000000001" + ], + "tag": "call-level-tech-specific", + "requirement_level": { + "recommended": "When communicating with an Elastic Cloud deployment, this should be collected from the \"X-Found-Handling-Instance\" HTTP response header.\n" + }, + "stability": "stable" + }, + { + "name": "db.elasticsearch.node.name", + "type": "string", + "brief": "Represents the human-readable identifier of the node/instance to which a request was routed.\n", + "examples": [ + "instance-0000000001" + ], + "tag": "tech-specific-elasticsearch", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "db.elasticsearch.path_parts", + "type": "template[string]", + "brief": "A dynamic value in the url path.\n", + "examples": [ + "db.elasticsearch.path_parts.index=test-index", + "db.elasticsearch.path_parts.doc_id=123" + ], + "tag": "call-level-tech-specific", + "requirement_level": { + "conditionally_required": "when the url has dynamic values" + }, + "note": "Many Elasticsearch url paths allow dynamic values. These SHOULD be recorded in span attributes in the format `db.elasticsearch.path_parts.`, where `` is the url path part name. The implementation SHOULD reference the [elasticsearch schema](https://raw.githubusercontent.com/elastic/elasticsearch-specification/main/output/schema/schema.json) in order to map the path part values to their names.\n", + "stability": "stable" + }, + { + "name": "db.elasticsearch.path_parts", + "type": "template[string]", + "brief": "A dynamic value in the url path.\n", + "examples": [ + "db.elasticsearch.path_parts.index=test-index", + "db.elasticsearch.path_parts.doc_id=123" + ], + "tag": "tech-specific-elasticsearch", + "requirement_level": "recommended", + "note": "Many Elasticsearch url paths allow dynamic values. These SHOULD be recorded in span attributes in the format `db.elasticsearch.path_parts.`, where `` is the url path part name. The implementation SHOULD reference the [elasticsearch schema](https://raw.githubusercontent.com/elastic/elasticsearch-specification/main/output/schema/schema.json) in order to map the path part values to their names.\n", + "stability": "stable" + }, + { + "name": "db.instance.id", + "type": "string", + "brief": "An identifier (address, unique name, or any other identifier) of the database instance that is executing queries or mutations on the current connection. This is useful in cases where the database is running in a clustered environment and the instrumentation is able to record the node executing the query. The client may obtain this value in databases like MySQL using queries like `select @@hostname`.\n", + "examples": "mysql-e26b99z.example.com", + "tag": "connection-level", + "requirement_level": { + "recommended": "If different from the `server.address`" + }, + "stability": "stable" + }, + { + "name": "db.instance.id", + "type": "string", + "brief": "An identifier (address, unique name, or any other identifier) of the database instance that is executing queries or mutations on the current connection. This is useful in cases where the database is running in a clustered environment and the instrumentation is able to record the node executing the query. The client may obtain this value in databases like MySQL using queries like `select @@hostname`.\n", + "examples": "mysql-e26b99z.example.com", + "tag": "db-generic", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "db.jdbc.driver_classname", + "type": "string", + "brief": "The fully-qualified class name of the [Java Database Connectivity (JDBC)](https://docs.oracle.com/javase/8/docs/technotes/guides/jdbc/) driver used to connect.\n", + "examples": [ + "org.postgresql.Driver", + "com.microsoft.sqlserver.jdbc.SQLServerDriver" + ], + "tag": "connection-level-tech-specific", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "db.jdbc.driver_classname", + "type": "string", + "brief": "The fully-qualified class name of the [Java Database Connectivity (JDBC)](https://docs.oracle.com/javase/8/docs/technotes/guides/jdbc/) driver used to connect.\n", + "examples": [ + "org.postgresql.Driver", + "com.microsoft.sqlserver.jdbc.SQLServerDriver" + ], + "tag": "tech-specific-jdbc", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "db.mongodb.collection", + "type": "string", + "brief": "The MongoDB collection being accessed within the database stated in `db.name`.\n", + "examples": [ + "customers", + "products" + ], + "tag": "call-level-tech-specific", + "requirement_level": "required", + "stability": "stable" + }, + { + "name": "db.mongodb.collection", + "type": "string", + "brief": "The MongoDB collection being accessed within the database stated in `db.name`.\n", + "examples": [ + "customers", + "products" + ], + "tag": "tech-specific-mongodb", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "db.mssql.instance_name", + "type": "string", + "brief": "The Microsoft SQL Server [instance name](https://docs.microsoft.com/sql/connect/jdbc/building-the-connection-url?view=sql-server-ver15) connecting to. This name is used to determine the port of a named instance.\n", + "examples": "MSSQLSERVER", + "tag": "connection-level-tech-specific", + "requirement_level": "recommended", + "note": "If setting a `db.mssql.instance_name`, `server.port` is no longer required (but still recommended if non-standard).\n", + "stability": "stable" + }, + { + "name": "db.mssql.instance_name", + "type": "string", + "brief": "The Microsoft SQL Server [instance name](https://docs.microsoft.com/sql/connect/jdbc/building-the-connection-url?view=sql-server-ver15) connecting to. This name is used to determine the port of a named instance.\n", + "examples": "MSSQLSERVER", + "tag": "tech-specific-mssql", + "requirement_level": "recommended", + "note": "If setting a `db.mssql.instance_name`, `server.port` is no longer required (but still recommended if non-standard).\n", + "stability": "stable" + }, + { + "name": "db.name", + "type": "string", + "brief": "The HBase namespace.\n", + "examples": [ + "mynamespace" + ], + "tag": "call-level-tech-specific", + "requirement_level": { + "conditionally_required": "If applicable." + }, + "note": "For HBase the `db.name` should be set to the HBase namespace.", + "stability": "stable" + }, + { + "name": "db.name", + "type": "string", + "brief": "The keyspace name in Cassandra.\n", + "examples": [ + "mykeyspace" + ], + "tag": "call-level-tech-specific-cassandra", + "requirement_level": { + "conditionally_required": "If applicable." + }, + "note": "For Cassandra the `db.name` should be set to the Cassandra keyspace name.", + "stability": "stable" + }, + { + "name": "db.name", + "type": "string", + "brief": "This attribute is used to report the name of the database being accessed. For commands that switch the database, this should be set to the target database (even if the command fails).\n", + "examples": [ + "customers", + "main" + ], + "tag": "call-level", + "requirement_level": { + "conditionally_required": "If applicable." + }, + "note": "In some SQL databases, the database name to be used is called \"schema name\". In case there are multiple layers that could be considered for database name (e.g. Oracle instance name and schema name), the database name to be used is the more specific layer (e.g. Oracle schema name).\n", + "stability": "stable" + }, + { + "name": "db.name", + "type": "string", + "brief": "This attribute is used to report the name of the database being accessed. For commands that switch the database, this should be set to the target database (even if the command fails).\n", + "examples": [ + "customers", + "main" + ], + "tag": "db-generic", + "requirement_level": "recommended", + "note": "In some SQL databases, the database name to be used is called \"schema name\". In case there are multiple layers that could be considered for database name (e.g. Oracle instance name and schema name), the database name to be used is the more specific layer (e.g. Oracle schema name).\n", + "stability": "stable" + }, + { + "name": "db.operation", + "type": "string", + "brief": "The HTTP method + the target REST route.\n", + "examples": [ + "GET /{db}/{docid}" + ], + "tag": "call-level-tech-specific", + "requirement_level": { + "conditionally_required": "If `db.statement` is not applicable." + }, + "note": "In **CouchDB**, `db.operation` should be set to the HTTP method + the target REST route according to the API reference documentation. For example, when retrieving a document, `db.operation` would be set to (literally, i.e., without replacing the placeholders with concrete values): [`GET /{db}/{docid}`](http://docs.couchdb.org/en/stable/api/document/common.html#get--db-docid).\n", + "stability": "stable" + }, + { + "name": "db.operation", + "type": "string", + "brief": "The endpoint identifier for the request.", + "examples": [ + "search", + "ml.close_job", + "cat.aliases" + ], + "tag": "call-level-tech-specific", + "requirement_level": "required", + "note": "When setting this to an SQL keyword, it is not recommended to attempt any client-side parsing of `db.statement` just to get this property, but it should be set if the operation name is provided by the library being instrumented. If the SQL statement has an ambiguous operation, or performs more than one operation, this value may be omitted.\n", + "stability": "stable" + }, + { + "name": "db.operation", + "type": "string", + "brief": "The name of the operation being executed, e.g. the [MongoDB command name](https://docs.mongodb.com/manual/reference/command/#database-operations) such as `findAndModify`, or the SQL keyword.\n", + "examples": [ + "findAndModify", + "HMSET", + "SELECT" + ], + "tag": "call-level", + "requirement_level": { + "conditionally_required": "If `db.statement` is not applicable." + }, + "note": "When setting this to an SQL keyword, it is not recommended to attempt any client-side parsing of `db.statement` just to get this property, but it should be set if the operation name is provided by the library being instrumented. If the SQL statement has an ambiguous operation, or performs more than one operation, this value may be omitted.\n", + "stability": "stable" + }, + { + "name": "db.operation", + "type": "string", + "brief": "The name of the operation being executed, e.g. the [MongoDB command name](https://docs.mongodb.com/manual/reference/command/#database-operations) such as `findAndModify`, or the SQL keyword.\n", + "examples": [ + "findAndModify", + "HMSET", + "SELECT" + ], + "tag": "db-generic", + "requirement_level": "recommended", + "note": "When setting this to an SQL keyword, it is not recommended to attempt any client-side parsing of `db.statement` just to get this property, but it should be set if the operation name is provided by the library being instrumented. If the SQL statement has an ambiguous operation, or performs more than one operation, this value may be omitted.\n", + "stability": "stable" + }, + { + "name": "db.redis.database_index", + "type": "int", + "brief": "The index of the database being accessed as used in the [`SELECT` command](https://redis.io/commands/select), provided as an integer. To be used instead of the generic `db.name` attribute.\n", + "examples": [ + 0, + 1, + 15 + ], + "tag": "call-level-tech-specific", + "requirement_level": { + "conditionally_required": "If other than the default database (`0`)." + }, + "stability": "stable" + }, + { + "name": "db.redis.database_index", + "type": "int", + "brief": "The index of the database being accessed as used in the [`SELECT` command](https://redis.io/commands/select), provided as an integer. To be used instead of the generic `db.name` attribute.\n", + "examples": [ + 0, + 1, + 15 + ], + "tag": "tech-specific-redis", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "db.sql.table", + "type": "string", + "brief": "The name of the primary table that the operation is acting upon, including the database name (if applicable).", + "examples": [ + "public.users", + "customers" + ], + "tag": "call-level-tech-specific", + "requirement_level": "recommended", + "note": "It is not recommended to attempt any client-side parsing of `db.statement` just to get this property, but it should be set if it is provided by the library being instrumented. If the operation is acting upon an anonymous table, or more than one table, this value MUST NOT be set.\n", + "stability": "stable" + }, + { + "name": "db.sql.table", + "type": "string", + "brief": "The name of the primary table that the operation is acting upon, including the database name (if applicable).", + "examples": [ + "public.users", + "customers" + ], + "tag": "tech-specific-sql", + "requirement_level": "recommended", + "note": "It is not recommended to attempt any client-side parsing of `db.statement` just to get this property, but it should be set if it is provided by the library being instrumented. If the operation is acting upon an anonymous table, or more than one table, this value MUST NOT be set.\n", + "stability": "stable" + }, + { + "name": "db.statement", + "type": "string", + "brief": "The database statement being executed.\n", + "examples": [ + "SELECT * FROM wuser_table", + "SET mykey \"WuValue\"" + ], + "tag": "call-level", + "requirement_level": { + "recommended": "Should be collected by default only if there is sanitization that excludes sensitive information.\n" + }, + "stability": "stable" + }, + { + "name": "db.statement", + "type": "string", + "brief": "The database statement being executed.\n", + "examples": [ + "SELECT * FROM wuser_table", + "SET mykey \"WuValue\"" + ], + "tag": "db-generic", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "db.statement", + "type": "string", + "brief": "The full syntax of the Redis CLI command.\n", + "examples": [ + "HMSET myhash field1 'Hello' field2 'World'" + ], + "tag": "call-level-tech-specific", + "requirement_level": { + "recommended": "Should be collected by default only if there is sanitization that excludes sensitive information.\n" + }, + "note": "For **Redis**, the value provided for `db.statement` SHOULD correspond to the syntax of the Redis CLI. If, for example, the [`HMSET` command](https://redis.io/commands/hmset) is invoked, `\"HMSET myhash field1 'Hello' field2 'World'\"` would be a suitable value for `db.statement`.\n", + "stability": "stable" + }, + { + "name": "db.statement", + "type": "string", + "brief": "The request body for a [search-type query](https://www.elastic.co/guide/en/elasticsearch/reference/current/search.html), as a json string.", + "examples": [ + "\"{\\\"query\\\":{\\\"term\\\":{\\\"user.id\\\":\\\"kimchy\\\"}}}\"" + ], + "tag": "call-level-tech-specific", + "requirement_level": { + "recommended": "Should be collected by default for search-type queries and only if there is sanitization that excludes sensitive information.\n" + }, + "stability": "stable" + }, + { + "name": "db.system", + "type": { + "members": [ + { + "id": "other_sql", + "value": "other_sql", + "brief": "Some other SQL database. Fallback only. See notes.", + "stability": "stable" + }, + { + "id": "mssql", + "value": "mssql", + "brief": "Microsoft SQL Server", + "stability": "stable" + }, + { + "id": "mssqlcompact", + "value": "mssqlcompact", + "brief": "Microsoft SQL Server Compact", + "stability": "stable" + }, + { + "id": "mysql", + "value": "mysql", + "brief": "MySQL", + "stability": "stable" + }, + { + "id": "oracle", + "value": "oracle", + "brief": "Oracle Database", + "stability": "stable" + }, + { + "id": "db2", + "value": "db2", + "brief": "IBM Db2", + "stability": "stable" + }, + { + "id": "postgresql", + "value": "postgresql", + "brief": "PostgreSQL", + "stability": "stable" + }, + { + "id": "redshift", + "value": "redshift", + "brief": "Amazon Redshift", + "stability": "stable" + }, + { + "id": "hive", + "value": "hive", + "brief": "Apache Hive", + "stability": "stable" + }, + { + "id": "cloudscape", + "value": "cloudscape", + "brief": "Cloudscape", + "stability": "stable" + }, + { + "id": "hsqldb", + "value": "hsqldb", + "brief": "HyperSQL DataBase", + "stability": "stable" + }, + { + "id": "progress", + "value": "progress", + "brief": "Progress Database", + "stability": "stable" + }, + { + "id": "maxdb", + "value": "maxdb", + "brief": "SAP MaxDB", + "stability": "stable" + }, + { + "id": "hanadb", + "value": "hanadb", + "brief": "SAP HANA", + "stability": "stable" + }, + { + "id": "ingres", + "value": "ingres", + "brief": "Ingres", + "stability": "stable" + }, + { + "id": "firstsql", + "value": "firstsql", + "brief": "FirstSQL", + "stability": "stable" + }, + { + "id": "edb", + "value": "edb", + "brief": "EnterpriseDB", + "stability": "stable" + }, + { + "id": "cache", + "value": "cache", + "brief": "InterSystems Caché", + "stability": "stable" + }, + { + "id": "adabas", + "value": "adabas", + "brief": "Adabas (Adaptable Database System)", + "stability": "stable" + }, + { + "id": "firebird", + "value": "firebird", + "brief": "Firebird", + "stability": "stable" + }, + { + "id": "derby", + "value": "derby", + "brief": "Apache Derby", + "stability": "stable" + }, + { + "id": "filemaker", + "value": "filemaker", + "brief": "FileMaker", + "stability": "stable" + }, + { + "id": "informix", + "value": "informix", + "brief": "Informix", + "stability": "stable" + }, + { + "id": "instantdb", + "value": "instantdb", + "brief": "InstantDB", + "stability": "stable" + }, + { + "id": "interbase", + "value": "interbase", + "brief": "InterBase", + "stability": "stable" + }, + { + "id": "mariadb", + "value": "mariadb", + "brief": "MariaDB", + "stability": "stable" + }, + { + "id": "netezza", + "value": "netezza", + "brief": "Netezza", + "stability": "stable" + }, + { + "id": "pervasive", + "value": "pervasive", + "brief": "Pervasive PSQL", + "stability": "stable" + }, + { + "id": "pointbase", + "value": "pointbase", + "brief": "PointBase", + "stability": "stable" + }, + { + "id": "sqlite", + "value": "sqlite", + "brief": "SQLite", + "stability": "stable" + }, + { + "id": "sybase", + "value": "sybase", + "brief": "Sybase", + "stability": "stable" + }, + { + "id": "teradata", + "value": "teradata", + "brief": "Teradata", + "stability": "stable" + }, + { + "id": "vertica", + "value": "vertica", + "brief": "Vertica", + "stability": "stable" + }, + { + "id": "h2", + "value": "h2", + "brief": "H2", + "stability": "stable" + }, + { + "id": "coldfusion", + "value": "coldfusion", + "brief": "ColdFusion IMQ", + "stability": "stable" + }, + { + "id": "cassandra", + "value": "cassandra", + "brief": "Apache Cassandra", + "stability": "stable" + }, + { + "id": "hbase", + "value": "hbase", + "brief": "Apache HBase", + "stability": "stable" + }, + { + "id": "mongodb", + "value": "mongodb", + "brief": "MongoDB", + "stability": "stable" + }, + { + "id": "redis", + "value": "redis", + "brief": "Redis", + "stability": "stable" + }, + { + "id": "couchbase", + "value": "couchbase", + "brief": "Couchbase", + "stability": "stable" + }, + { + "id": "couchdb", + "value": "couchdb", + "brief": "CouchDB", + "stability": "stable" + }, + { + "id": "cosmosdb", + "value": "cosmosdb", + "brief": "Microsoft Azure Cosmos DB", + "stability": "stable" + }, + { + "id": "dynamodb", + "value": "dynamodb", + "brief": "Amazon DynamoDB", + "stability": "stable" + }, + { + "id": "neo4j", + "value": "neo4j", + "brief": "Neo4j", + "stability": "stable" + }, + { + "id": "geode", + "value": "geode", + "brief": "Apache Geode", + "stability": "stable" + }, + { + "id": "elasticsearch", + "value": "elasticsearch", + "brief": "Elasticsearch", + "stability": "stable" + }, + { + "id": "memcached", + "value": "memcached", + "brief": "Memcached", + "stability": "stable" + }, + { + "id": "cockroachdb", + "value": "cockroachdb", + "brief": "CockroachDB", + "stability": "stable" + }, + { + "id": "opensearch", + "value": "opensearch", + "brief": "OpenSearch", + "stability": "stable" + }, + { + "id": "clickhouse", + "value": "clickhouse", + "brief": "ClickHouse", + "stability": "stable" + }, + { + "id": "spanner", + "value": "spanner", + "brief": "Cloud Spanner", + "stability": "stable" + }, + { + "id": "trino", + "value": "trino", + "brief": "Trino", + "stability": "stable" + } + ] + }, + "brief": "An identifier for the database management system (DBMS) product being used. See below for a list of well-known identifiers.", + "tag": "connection-level", + "requirement_level": "required", + "stability": "stable" + }, + { + "name": "db.system", + "type": { + "members": [ + { + "id": "other_sql", + "value": "other_sql", + "brief": "Some other SQL database. Fallback only. See notes.", + "stability": "stable" + }, + { + "id": "mssql", + "value": "mssql", + "brief": "Microsoft SQL Server", + "stability": "stable" + }, + { + "id": "mssqlcompact", + "value": "mssqlcompact", + "brief": "Microsoft SQL Server Compact", + "stability": "stable" + }, + { + "id": "mysql", + "value": "mysql", + "brief": "MySQL", + "stability": "stable" + }, + { + "id": "oracle", + "value": "oracle", + "brief": "Oracle Database", + "stability": "stable" + }, + { + "id": "db2", + "value": "db2", + "brief": "IBM Db2", + "stability": "stable" + }, + { + "id": "postgresql", + "value": "postgresql", + "brief": "PostgreSQL", + "stability": "stable" + }, + { + "id": "redshift", + "value": "redshift", + "brief": "Amazon Redshift", + "stability": "stable" + }, + { + "id": "hive", + "value": "hive", + "brief": "Apache Hive", + "stability": "stable" + }, + { + "id": "cloudscape", + "value": "cloudscape", + "brief": "Cloudscape", + "stability": "stable" + }, + { + "id": "hsqldb", + "value": "hsqldb", + "brief": "HyperSQL DataBase", + "stability": "stable" + }, + { + "id": "progress", + "value": "progress", + "brief": "Progress Database", + "stability": "stable" + }, + { + "id": "maxdb", + "value": "maxdb", + "brief": "SAP MaxDB", + "stability": "stable" + }, + { + "id": "hanadb", + "value": "hanadb", + "brief": "SAP HANA", + "stability": "stable" + }, + { + "id": "ingres", + "value": "ingres", + "brief": "Ingres", + "stability": "stable" + }, + { + "id": "firstsql", + "value": "firstsql", + "brief": "FirstSQL", + "stability": "stable" + }, + { + "id": "edb", + "value": "edb", + "brief": "EnterpriseDB", + "stability": "stable" + }, + { + "id": "cache", + "value": "cache", + "brief": "InterSystems Caché", + "stability": "stable" + }, + { + "id": "adabas", + "value": "adabas", + "brief": "Adabas (Adaptable Database System)", + "stability": "stable" + }, + { + "id": "firebird", + "value": "firebird", + "brief": "Firebird", + "stability": "stable" + }, + { + "id": "derby", + "value": "derby", + "brief": "Apache Derby", + "stability": "stable" + }, + { + "id": "filemaker", + "value": "filemaker", + "brief": "FileMaker", + "stability": "stable" + }, + { + "id": "informix", + "value": "informix", + "brief": "Informix", + "stability": "stable" + }, + { + "id": "instantdb", + "value": "instantdb", + "brief": "InstantDB", + "stability": "stable" + }, + { + "id": "interbase", + "value": "interbase", + "brief": "InterBase", + "stability": "stable" + }, + { + "id": "mariadb", + "value": "mariadb", + "brief": "MariaDB", + "stability": "stable" + }, + { + "id": "netezza", + "value": "netezza", + "brief": "Netezza", + "stability": "stable" + }, + { + "id": "pervasive", + "value": "pervasive", + "brief": "Pervasive PSQL", + "stability": "stable" + }, + { + "id": "pointbase", + "value": "pointbase", + "brief": "PointBase", + "stability": "stable" + }, + { + "id": "sqlite", + "value": "sqlite", + "brief": "SQLite", + "stability": "stable" + }, + { + "id": "sybase", + "value": "sybase", + "brief": "Sybase", + "stability": "stable" + }, + { + "id": "teradata", + "value": "teradata", + "brief": "Teradata", + "stability": "stable" + }, + { + "id": "vertica", + "value": "vertica", + "brief": "Vertica", + "stability": "stable" + }, + { + "id": "h2", + "value": "h2", + "brief": "H2", + "stability": "stable" + }, + { + "id": "coldfusion", + "value": "coldfusion", + "brief": "ColdFusion IMQ", + "stability": "stable" + }, + { + "id": "cassandra", + "value": "cassandra", + "brief": "Apache Cassandra", + "stability": "stable" + }, + { + "id": "hbase", + "value": "hbase", + "brief": "Apache HBase", + "stability": "stable" + }, + { + "id": "mongodb", + "value": "mongodb", + "brief": "MongoDB", + "stability": "stable" + }, + { + "id": "redis", + "value": "redis", + "brief": "Redis", + "stability": "stable" + }, + { + "id": "couchbase", + "value": "couchbase", + "brief": "Couchbase", + "stability": "stable" + }, + { + "id": "couchdb", + "value": "couchdb", + "brief": "CouchDB", + "stability": "stable" + }, + { + "id": "cosmosdb", + "value": "cosmosdb", + "brief": "Microsoft Azure Cosmos DB", + "stability": "stable" + }, + { + "id": "dynamodb", + "value": "dynamodb", + "brief": "Amazon DynamoDB", + "stability": "stable" + }, + { + "id": "neo4j", + "value": "neo4j", + "brief": "Neo4j", + "stability": "stable" + }, + { + "id": "geode", + "value": "geode", + "brief": "Apache Geode", + "stability": "stable" + }, + { + "id": "elasticsearch", + "value": "elasticsearch", + "brief": "Elasticsearch", + "stability": "stable" + }, + { + "id": "memcached", + "value": "memcached", + "brief": "Memcached", + "stability": "stable" + }, + { + "id": "cockroachdb", + "value": "cockroachdb", + "brief": "CockroachDB", + "stability": "stable" + }, + { + "id": "opensearch", + "value": "opensearch", + "brief": "OpenSearch", + "stability": "stable" + }, + { + "id": "clickhouse", + "value": "clickhouse", + "brief": "ClickHouse", + "stability": "stable" + }, + { + "id": "spanner", + "value": "spanner", + "brief": "Cloud Spanner", + "stability": "stable" + }, + { + "id": "trino", + "value": "trino", + "brief": "Trino", + "stability": "stable" + } + ] + }, + "brief": "An identifier for the database management system (DBMS) product being used. See below for a list of well-known identifiers.", + "tag": "db-generic", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "db.user", + "type": "string", + "brief": "Username for accessing the database.\n", + "examples": [ + "readonly_user", + "reporting_user" + ], + "tag": "connection-level", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "db.user", + "type": "string", + "brief": "Username for accessing the database.\n", + "examples": [ + "readonly_user", + "reporting_user" + ], + "tag": "db-generic", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "http.request.body.size", + "type": "int", + "brief": "The size of the request payload body in bytes. This is the number of bytes transferred excluding headers and is often, but not always, present as the [Content-Length](https://www.rfc-editor.org/rfc/rfc9110.html#field.content-length) header. For requests using transport encoding, this should be the compressed size.\n", + "examples": 3495, + "requirement_level": "recommended", + "stability": "development" + }, + { + "name": "http.request.header", + "type": "template[string[]]", + "brief": "HTTP request headers, `` being the normalized HTTP Header name (lowercase), the value being the header values.\n", + "examples": [ + [ + "application/json" + ], + [ + "1.2.3.4", + "1.2.3.5" + ] + ], + "requirement_level": "recommended", + "note": "Instrumentations SHOULD require an explicit configuration of which headers are to be captured. Including all request headers can be a security risk - explicit configuration helps avoid leaking sensitive information.\nThe `User-Agent` header is already captured in the `user_agent.original` attribute. Users MAY explicitly configure instrumentations to capture them even though it is not recommended.\nThe attribute value MUST consist of either multiple header values as an array of strings or a single-item array containing a possibly comma-concatenated string, depending on the way the HTTP library provides access to headers.\n", + "stability": "stable" + }, + { + "name": "http.request.method", + "type": { + "members": [ + { + "id": "connect", + "value": "CONNECT", + "brief": "CONNECT method.", + "stability": "stable" + }, + { + "id": "delete", + "value": "DELETE", + "brief": "DELETE method.", + "stability": "stable" + }, + { + "id": "get", + "value": "GET", + "brief": "GET method.", + "stability": "stable" + }, + { + "id": "head", + "value": "HEAD", + "brief": "HEAD method.", + "stability": "stable" + }, + { + "id": "options", + "value": "OPTIONS", + "brief": "OPTIONS method.", + "stability": "stable" + }, + { + "id": "patch", + "value": "PATCH", + "brief": "PATCH method.", + "stability": "stable" + }, + { + "id": "post", + "value": "POST", + "brief": "POST method.", + "stability": "stable" + }, + { + "id": "put", + "value": "PUT", + "brief": "PUT method.", + "stability": "stable" + }, + { + "id": "trace", + "value": "TRACE", + "brief": "TRACE method.", + "stability": "stable" + }, + { + "id": "other", + "value": "_OTHER", + "brief": "Any HTTP method that the instrumentation has no prior knowledge of.", + "stability": "stable" + } + ] + }, + "brief": "HTTP request method.", + "examples": [ + "GET", + "POST", + "HEAD" + ], + "requirement_level": "recommended", + "note": "HTTP request method value SHOULD be \"known\" to the instrumentation.\nBy default, this convention defines \"known\" methods as the ones listed in [RFC9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-methods)\nand the PATCH method defined in [RFC5789](https://www.rfc-editor.org/rfc/rfc5789.html).\n\nIf the HTTP request method is not known to instrumentation, it MUST set the `http.request.method` attribute to `_OTHER`.\n\nIf the HTTP instrumentation could end up converting valid HTTP request methods to `_OTHER`, then it MUST provide a way to override\nthe list of known HTTP methods. If this override is done via environment variable, then the environment variable MUST be named\nOTEL_INSTRUMENTATION_HTTP_KNOWN_METHODS and support a comma-separated list of case-sensitive known HTTP methods\n(this list MUST be a full override of the default known method, it is not a list of known methods in addition to the defaults).\n\nHTTP method names are case-sensitive and `http.request.method` attribute value MUST match a known HTTP method name exactly.\nInstrumentations for specific web frameworks that consider HTTP methods to be case insensitive, SHOULD populate a canonical equivalent.\nTracing instrumentations that do so, MUST also set `http.request.method_original` to the original value.\n", + "stability": "stable" + }, + { + "name": "http.request.method", + "type": { + "members": [ + { + "id": "connect", + "value": "CONNECT", + "brief": "CONNECT method.", + "stability": "stable" + }, + { + "id": "delete", + "value": "DELETE", + "brief": "DELETE method.", + "stability": "stable" + }, + { + "id": "get", + "value": "GET", + "brief": "GET method.", + "stability": "stable" + }, + { + "id": "head", + "value": "HEAD", + "brief": "HEAD method.", + "stability": "stable" + }, + { + "id": "options", + "value": "OPTIONS", + "brief": "OPTIONS method.", + "stability": "stable" + }, + { + "id": "patch", + "value": "PATCH", + "brief": "PATCH method.", + "stability": "stable" + }, + { + "id": "post", + "value": "POST", + "brief": "POST method.", + "stability": "stable" + }, + { + "id": "put", + "value": "PUT", + "brief": "PUT method.", + "stability": "stable" + }, + { + "id": "trace", + "value": "TRACE", + "brief": "TRACE method.", + "stability": "stable" + }, + { + "id": "other", + "value": "_OTHER", + "brief": "Any HTTP method that the instrumentation has no prior knowledge of.", + "stability": "stable" + } + ] + }, + "brief": "HTTP request method.", + "examples": [ + "GET", + "POST", + "HEAD" + ], + "tag": "call-level-tech-specific", + "requirement_level": "required", + "note": "HTTP request method value SHOULD be \"known\" to the instrumentation.\nBy default, this convention defines \"known\" methods as the ones listed in [RFC9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-methods)\nand the PATCH method defined in [RFC5789](https://www.rfc-editor.org/rfc/rfc5789.html).\n\nIf the HTTP request method is not known to instrumentation, it MUST set the `http.request.method` attribute to `_OTHER`.\n\nIf the HTTP instrumentation could end up converting valid HTTP request methods to `_OTHER`, then it MUST provide a way to override\nthe list of known HTTP methods. If this override is done via environment variable, then the environment variable MUST be named\nOTEL_INSTRUMENTATION_HTTP_KNOWN_METHODS and support a comma-separated list of case-sensitive known HTTP methods\n(this list MUST be a full override of the default known method, it is not a list of known methods in addition to the defaults).\n\nHTTP method names are case-sensitive and `http.request.method` attribute value MUST match a known HTTP method name exactly.\nInstrumentations for specific web frameworks that consider HTTP methods to be case insensitive, SHOULD populate a canonical equivalent.\nTracing instrumentations that do so, MUST also set `http.request.method_original` to the original value.\n", + "stability": "stable" + }, + { + "name": "http.request.method_original", + "type": "string", + "brief": "Original HTTP method sent by the client in the request line.", + "examples": [ + "GeT", + "ACL", + "foo" + ], + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "http.request.resend_count", + "type": "int", + "brief": "The ordinal number of request resending attempt (for any reason, including redirects).\n", + "examples": 3, + "requirement_level": "recommended", + "note": "The resend count SHOULD be updated each time an HTTP request gets resent by the client, regardless of what was the cause of the resending (e.g. redirection, authorization failure, 503 Server Unavailable, network issues, or any other).\n", + "stability": "stable" + }, + { + "name": "http.response.body.size", + "type": "int", + "brief": "The size of the response payload body in bytes. This is the number of bytes transferred excluding headers and is often, but not always, present as the [Content-Length](https://www.rfc-editor.org/rfc/rfc9110.html#field.content-length) header. For requests using transport encoding, this should be the compressed size.\n", + "examples": 3495, + "requirement_level": "recommended", + "stability": "development" + }, + { + "name": "http.response.header", + "type": "template[string[]]", + "brief": "HTTP response headers, `` being the normalized HTTP Header name (lowercase), the value being the header values.\n", + "examples": [ + [ + "application/json" + ], + [ + "abc", + "def" + ] + ], + "requirement_level": "recommended", + "note": "Instrumentations SHOULD require an explicit configuration of which headers are to be captured. Including all response headers can be a security risk - explicit configuration helps avoid leaking sensitive information.\nUsers MAY explicitly configure instrumentations to capture them even though it is not recommended.\nThe attribute value MUST consist of either multiple header values as an array of strings or a single-item array containing a possibly comma-concatenated string, depending on the way the HTTP library provides access to headers.\n", + "stability": "stable" + }, + { + "name": "http.response.status_code", + "type": "int", + "brief": "[HTTP response status code](https://tools.ietf.org/html/rfc7231#section-6).", + "examples": [ + 200 + ], + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "http.route", + "type": "string", + "brief": "The matched route, that is, the path template in the format used by the respective server framework.\n", + "examples": [ + "/users/:userID?", + "{controller}/{action}/{id?}" + ], + "requirement_level": "recommended", + "note": "MUST NOT be populated when this is not supported by the HTTP server framework as the route attribute should have low-cardinality and the URI path can NOT substitute it.\nSHOULD include the [application root](/docs/http/http-spans.md#http-server-definitions) if there is one.", + "stability": "stable" + }, + { + "name": "network.carrier.icc", + "type": "string", + "brief": "The ISO 3166-1 alpha-2 2-character country code associated with the mobile carrier network.", + "examples": "DE", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "network.carrier.mcc", + "type": "string", + "brief": "The mobile carrier country code.", + "examples": "310", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "network.carrier.mnc", + "type": "string", + "brief": "The mobile carrier network code.", + "examples": "001", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "network.carrier.name", + "type": "string", + "brief": "The name of the mobile carrier.", + "examples": "sprint", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "network.connection.subtype", + "type": { + "members": [ + { + "id": "gprs", + "value": "gprs", + "brief": "GPRS", + "stability": "stable" + }, + { + "id": "edge", + "value": "edge", + "brief": "EDGE", + "stability": "stable" + }, + { + "id": "umts", + "value": "umts", + "brief": "UMTS", + "stability": "stable" + }, + { + "id": "cdma", + "value": "cdma", + "brief": "CDMA", + "stability": "stable" + }, + { + "id": "evdo_0", + "value": "evdo_0", + "brief": "EVDO Rel. 0", + "stability": "stable" + }, + { + "id": "evdo_a", + "value": "evdo_a", + "brief": "EVDO Rev. A", + "stability": "stable" + }, + { + "id": "cdma2000_1xrtt", + "value": "cdma2000_1xrtt", + "brief": "CDMA2000 1XRTT", + "stability": "stable" + }, + { + "id": "hsdpa", + "value": "hsdpa", + "brief": "HSDPA", + "stability": "stable" + }, + { + "id": "hsupa", + "value": "hsupa", + "brief": "HSUPA", + "stability": "stable" + }, + { + "id": "hspa", + "value": "hspa", + "brief": "HSPA", + "stability": "stable" + }, + { + "id": "iden", + "value": "iden", + "brief": "IDEN", + "stability": "stable" + }, + { + "id": "evdo_b", + "value": "evdo_b", + "brief": "EVDO Rev. B", + "stability": "stable" + }, + { + "id": "lte", + "value": "lte", + "brief": "LTE", + "stability": "stable" + }, + { + "id": "ehrpd", + "value": "ehrpd", + "brief": "EHRPD", + "stability": "stable" + }, + { + "id": "hspap", + "value": "hspap", + "brief": "HSPAP", + "stability": "stable" + }, + { + "id": "gsm", + "value": "gsm", + "brief": "GSM", + "stability": "stable" + }, + { + "id": "td_scdma", + "value": "td_scdma", + "brief": "TD-SCDMA", + "stability": "stable" + }, + { + "id": "iwlan", + "value": "iwlan", + "brief": "IWLAN", + "stability": "stable" + }, + { + "id": "nr", + "value": "nr", + "brief": "5G NR (New Radio)", + "stability": "stable" + }, + { + "id": "nrnsa", + "value": "nrnsa", + "brief": "5G NRNSA (New Radio Non-Standalone)", + "stability": "stable" + }, + { + "id": "lte_ca", + "value": "lte_ca", + "brief": "LTE CA", + "stability": "stable" + } + ] + }, + "brief": "This describes more details regarding the connection.type. It may be the type of cell technology connection, but it could be used for describing details about a wifi connection.", + "examples": "LTE", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "network.connection.type", + "type": { + "members": [ + { + "id": "wifi", + "value": "wifi", + "stability": "stable" + }, + { + "id": "wired", + "value": "wired", + "stability": "stable" + }, + { + "id": "cell", + "value": "cell", + "stability": "stable" + }, + { + "id": "unavailable", + "value": "unavailable", + "stability": "stable" + }, + { + "id": "unknown", + "value": "unknown", + "stability": "stable" + } + ] + }, + "brief": "The internet connection type.", + "examples": "wifi", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "network.io.direction", + "type": { + "members": [ + { + "id": "transmit", + "value": "transmit", + "stability": "stable" + }, + { + "id": "receive", + "value": "receive", + "stability": "stable" + } + ] + }, + "brief": "The network IO operation direction.", + "examples": [ + "transmit" + ], + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "network.local.address", + "type": "string", + "brief": "Local address of the network connection - IP address or Unix domain socket name.", + "examples": [ + "10.1.2.80", + "/tmp/my.sock" + ], + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "network.local.port", + "type": "int", + "brief": "Local port number of the network connection.", + "examples": [ + 65123 + ], + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "network.peer.address", + "type": "string", + "brief": "Peer address of the network connection - IP address or Unix domain socket name.", + "examples": [ + "10.1.2.80", + "/tmp/my.sock" + ], + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "network.peer.address", + "type": "string", + "brief": "Peer address of the network connection - IP address or Unix domain socket name.", + "examples": [ + "10.1.2.80", + "/tmp/my.sock" + ], + "tag": "connection-level", + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "network.peer.port", + "type": "int", + "brief": "Peer port number of the network connection.", + "examples": [ + 65123 + ], + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "network.peer.port", + "type": "int", + "brief": "Peer port number of the network connection.", + "examples": [ + 65123 + ], + "tag": "connection-level", + "requirement_level": { + "recommended": "If `network.peer.address` is set." + }, + "stability": "stable" + }, + { + "name": "network.protocol.name", + "type": "string", + "brief": "[OSI application layer](https://osi-model.com/application-layer/) or non-OSI equivalent.", + "examples": [ + "amqp", + "http", + "mqtt" + ], + "requirement_level": "recommended", + "note": "The value SHOULD be normalized to lowercase.", + "stability": "stable" + }, + { + "name": "network.protocol.version", + "type": "string", + "brief": "Version of the protocol specified in `network.protocol.name`.", + "examples": "3.1.1", + "requirement_level": "recommended", + "note": "`network.protocol.version` refers to the version of the protocol used and might be different from the protocol client's version. If the HTTP client has a version of `0.27.2`, but sends HTTP version `1.1`, this attribute should be set to `1.1`.\n", + "stability": "stable" + }, + { + "name": "network.transport", + "type": { + "members": [ + { + "id": "tcp", + "value": "tcp", + "brief": "TCP", + "stability": "stable" + }, + { + "id": "udp", + "value": "udp", + "brief": "UDP", + "stability": "stable" + }, + { + "id": "pipe", + "value": "pipe", + "brief": "Named or anonymous pipe.", + "stability": "stable" + }, + { + "id": "unix", + "value": "unix", + "brief": "Unix domain socket", + "stability": "stable" + } + ] + }, + "brief": "[OSI transport layer](https://osi-model.com/transport-layer/) or [inter-process communication method](https://wikipedia.org/wiki/Inter-process_communication).\n", + "examples": [ + "tcp", + "udp" + ], + "requirement_level": "recommended", + "note": "The value SHOULD be normalized to lowercase.\n\nConsider always setting the transport when setting a port number, since\na port number is ambiguous without knowing the transport. For example\ndifferent processes could be listening on TCP port 12345 and UDP port 12345.\n", + "stability": "stable" + }, + { + "name": "network.transport", + "type": { + "members": [ + { + "id": "tcp", + "value": "tcp", + "brief": "TCP", + "stability": "stable" + }, + { + "id": "udp", + "value": "udp", + "brief": "UDP", + "stability": "stable" + }, + { + "id": "pipe", + "value": "pipe", + "brief": "Named or anonymous pipe.", + "stability": "stable" + }, + { + "id": "unix", + "value": "unix", + "brief": "Unix domain socket", + "stability": "stable" + } + ] + }, + "brief": "[OSI transport layer](https://osi-model.com/transport-layer/) or [inter-process communication method](https://wikipedia.org/wiki/Inter-process_communication).\n", + "examples": [ + "tcp", + "udp" + ], + "tag": "connection-level", + "requirement_level": "recommended", + "note": "The value SHOULD be normalized to lowercase.\n\nConsider always setting the transport when setting a port number, since\na port number is ambiguous without knowing the transport. For example\ndifferent processes could be listening on TCP port 12345 and UDP port 12345.\n", + "stability": "stable" + }, + { + "name": "network.type", + "type": { + "members": [ + { + "id": "ipv4", + "value": "ipv4", + "brief": "IPv4", + "stability": "stable" + }, + { + "id": "ipv6", + "value": "ipv6", + "brief": "IPv6", + "stability": "stable" + } + ] + }, + "brief": "[OSI network layer](https://osi-model.com/network-layer/) or non-OSI equivalent.", + "examples": [ + "ipv4", + "ipv6" + ], + "requirement_level": "recommended", + "note": "The value SHOULD be normalized to lowercase.", + "stability": "stable" + }, + { + "name": "network.type", + "type": { + "members": [ + { + "id": "ipv4", + "value": "ipv4", + "brief": "IPv4", + "stability": "stable" + }, + { + "id": "ipv6", + "value": "ipv6", + "brief": "IPv6", + "stability": "stable" + } + ] + }, + "brief": "[OSI network layer](https://osi-model.com/network-layer/) or non-OSI equivalent.", + "examples": [ + "ipv4", + "ipv6" + ], + "tag": "connection-level", + "requirement_level": "recommended", + "note": "The value SHOULD be normalized to lowercase.", + "stability": "stable" + }, + { + "name": "server.address", + "type": "string", + "brief": "Name of the database host.\n", + "examples": [ + "example.com", + "10.1.2.80", + "/tmp/my.sock" + ], + "tag": "call-level-tech-specific", + "requirement_level": "recommended", + "note": "When observed from the client side, and when communicating through an intermediary, `server.address` SHOULD represent the server address behind any intermediaries, for example proxies, if it's available.\n", + "stability": "stable" + }, + { + "name": "server.address", + "type": "string", + "brief": "Name of the database host.\n", + "examples": [ + "example.com", + "10.1.2.80", + "/tmp/my.sock" + ], + "tag": "connection-level", + "requirement_level": "recommended", + "note": "When observed from the client side, and when communicating through an intermediary, `server.address` SHOULD represent the server address behind any intermediaries, for example proxies, if it's available.\n", + "stability": "stable" + }, + { + "name": "server.address", + "type": "string", + "brief": "Server domain name if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name.", + "examples": [ + "example.com", + "10.1.2.80", + "/tmp/my.sock" + ], + "requirement_level": "recommended", + "note": "When observed from the client side, and when communicating through an intermediary, `server.address` SHOULD represent the server address behind any intermediaries, for example proxies, if it's available.\n", + "stability": "stable" + }, + { + "name": "server.port", + "type": "int", + "brief": "Server port number.", + "examples": [ + 80, + 8080, + 443 + ], + "requirement_level": "recommended", + "note": "When observed from the client side, and when communicating through an intermediary, `server.port` SHOULD represent the server port behind any intermediaries, for example proxies, if it's available.\n", + "stability": "stable" + }, + { + "name": "server.port", + "type": "int", + "brief": "Server port number.", + "examples": [ + 80, + 8080, + 443 + ], + "tag": "call-level-tech-specific", + "requirement_level": { + "conditionally_required": "If using a port other than the default port for this DBMS and if `server.address` is set." + }, + "note": "When observed from the client side, and when communicating through an intermediary, `server.port` SHOULD represent the server port behind any intermediaries, for example proxies, if it's available.\n", + "stability": "stable" + }, + { + "name": "server.port", + "type": "int", + "brief": "Server port number.", + "examples": [ + 80, + 8080, + 443 + ], + "tag": "connection-level", + "requirement_level": { + "conditionally_required": "If using a port other than the default port for this DBMS and if `server.address` is set." + }, + "note": "When observed from the client side, and when communicating through an intermediary, `server.port` SHOULD represent the server port behind any intermediaries, for example proxies, if it's available.\n", + "stability": "stable" + }, + { + "name": "url.fragment", + "type": "string", + "brief": "The [URI fragment](https://www.rfc-editor.org/rfc/rfc3986#section-3.5) component", + "examples": [ + "SemConv" + ], + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "url.full", + "type": "string", + "brief": "Absolute URL describing a network resource according to [RFC3986](https://www.rfc-editor.org/rfc/rfc3986)", + "examples": [ + "https://localhost:9200/index/_search?q=user.id:kimchy" + ], + "tag": "call-level-tech-specific", + "requirement_level": "required", + "note": "For network calls, URL usually has `scheme://host[:port][path][?query][#fragment]` format, where the fragment is not transmitted over HTTP, but if it is known, it SHOULD be included nevertheless.\n`url.full` MUST NOT contain credentials passed via URL in form of `https://username:password@www.example.com/`. In such case username and password SHOULD be redacted and attribute's value SHOULD be `https://REDACTED:REDACTED@www.example.com/`.\n`url.full` SHOULD capture the absolute URL when it is available (or can be reconstructed) and SHOULD NOT be validated or modified except for sanitizing purposes.\n", + "stability": "stable" + }, + { + "name": "url.full", + "type": "string", + "brief": "Absolute URL describing a network resource according to [RFC3986](https://www.rfc-editor.org/rfc/rfc3986)", + "examples": [ + "https://www.foo.bar/search?q=OpenTelemetry#SemConv", + "//localhost" + ], + "requirement_level": "recommended", + "note": "For network calls, URL usually has `scheme://host[:port][path][?query][#fragment]` format, where the fragment is not transmitted over HTTP, but if it is known, it SHOULD be included nevertheless.\n`url.full` MUST NOT contain credentials passed via URL in form of `https://username:password@www.example.com/`. In such case username and password SHOULD be redacted and attribute's value SHOULD be `https://REDACTED:REDACTED@www.example.com/`.\n`url.full` SHOULD capture the absolute URL when it is available (or can be reconstructed) and SHOULD NOT be validated or modified except for sanitizing purposes.\n", + "stability": "stable" + }, + { + "name": "url.path", + "type": "string", + "brief": "The [URI path](https://www.rfc-editor.org/rfc/rfc3986#section-3.3) component", + "examples": [ + "/search" + ], + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "url.query", + "type": "string", + "brief": "The [URI query](https://www.rfc-editor.org/rfc/rfc3986#section-3.4) component", + "examples": [ + "q=OpenTelemetry" + ], + "requirement_level": "recommended", + "note": "Sensitive content provided in query string SHOULD be scrubbed when instrumentations can identify it.", + "stability": "stable" + }, + { + "name": "url.scheme", + "type": "string", + "brief": "The [URI scheme](https://www.rfc-editor.org/rfc/rfc3986#section-3.1) component identifying the used protocol.", + "examples": [ + "https", + "ftp", + "telnet" + ], + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "user_agent.original", + "type": "string", + "brief": "Full user-agent string is generated by Cosmos DB SDK", + "examples": [ + "cosmos-netstandard-sdk/3.23.0\\|3.23.1\\|1\\|X64\\|Linux 5.4.0-1098-azure 104 18\\|.NET Core 3.1.32\\|S\\|" + ], + "tag": "call-level-tech-specific", + "requirement_level": "recommended", + "note": "The user-agent value is generated by SDK which is a combination of
`sdk_version` : Current version of SDK. e.g. 'cosmos-netstandard-sdk/3.23.0'
`direct_pkg_version` : Direct package version used by Cosmos DB SDK. e.g. '3.23.1'
`number_of_client_instances` : Number of cosmos client instances created by the application. e.g. '1'
`type_of_machine_architecture` : Machine architecture. e.g. 'X64'
`operating_system` : Operating System. e.g. 'Linux 5.4.0-1098-azure 104 18'
`runtime_framework` : Runtime Framework. e.g. '.NET Core 3.1.32'
`failover_information` : Generated key to determine if region failover enabled.\n Format Reg-{D (Disabled discovery)}-S(application region)|L(List of preferred regions)|N(None, user did not configure it).\n Default value is \"NS\".\n", + "stability": "stable" + }, + { + "name": "user_agent.original", + "type": "string", + "brief": "Value of the [HTTP User-Agent](https://www.rfc-editor.org/rfc/rfc9110.html#field.user-agent) header sent by the client.\n", + "examples": [ + "CERN-LineMode/2.15 libwww/2.17b3", + "Mozilla/5.0 (iPhone; CPU iPhone OS 14_7_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Mobile/15E148 Safari/604.1" + ], + "requirement_level": "recommended", + "stability": "stable" + } + ] +} \ No newline at end of file diff --git a/crates/weaver_resolver/data/registry-test-8-http/expected-attribute-catalog.json b/crates/weaver_resolver/data/registry-test-8-http/expected-attribute-catalog.json index db64c8203..0c3490c6e 100644 --- a/crates/weaver_resolver/data/registry-test-8-http/expected-attribute-catalog.json +++ b/crates/weaver_resolver/data/registry-test-8-http/expected-attribute-catalog.json @@ -1,70 +1,72 @@ -[ - { - "name": "network.protocol.name", - "type": "string", - "brief": "[OSI application layer](https://osi-model.com/application-layer/) or non-OSI equivalent.", - "examples": [ - "amqp", - "http", - "mqtt" - ], - "requirement_level": "recommended", - "note": "The value SHOULD be normalized to lowercase.", - "stability": "stable" - }, - { - "name": "network.protocol.name", - "type": "string", - "brief": "[OSI application layer](https://osi-model.com/application-layer/) or non-OSI equivalent.", - "examples": [ - "http", - "spdy" - ], - "requirement_level": { - "conditionally_required": "If not `http` and `network.protocol.version` is set." +{ + "attributes": [ + { + "name": "network.protocol.name", + "type": "string", + "brief": "[OSI application layer](https://osi-model.com/application-layer/) or non-OSI equivalent.", + "examples": [ + "amqp", + "http", + "mqtt" + ], + "requirement_level": "recommended", + "note": "The value SHOULD be normalized to lowercase.", + "stability": "stable" }, - "note": "The value SHOULD be normalized to lowercase.", - "stability": "stable" - }, - { - "name": "server.port", - "type": "int", - "brief": "Port of the local HTTP server that received the request.\n", - "examples": [ - 80, - 8080, - 443 - ], - "requirement_level": "opt_in", - "note": "See [Setting `server.address` and `server.port` attributes](/docs/http/http-spans.md#setting-serveraddress-and-serverport-attributes).\n> **Warning**\n> Since this attribute is based on HTTP headers, opting in to it may allow an attacker\n> to trigger cardinality limits, degrading the usefulness of the metric.\n", - "stability": "stable" - }, - { - "name": "server.port", - "type": "int", - "brief": "Port of the local HTTP server that received the request.\n", - "examples": [ - 80, - 8080, - 443 - ], - "requirement_level": { - "conditionally_required": "If `server.address` is set." + { + "name": "network.protocol.name", + "type": "string", + "brief": "[OSI application layer](https://osi-model.com/application-layer/) or non-OSI equivalent.", + "examples": [ + "http", + "spdy" + ], + "requirement_level": { + "conditionally_required": "If not `http` and `network.protocol.version` is set." + }, + "note": "The value SHOULD be normalized to lowercase.", + "stability": "stable" }, - "note": "See [Setting `server.address` and `server.port` attributes](/docs/http/http-spans.md#setting-serveraddress-and-serverport-attributes).\n", - "stability": "stable" - }, - { - "name": "server.port", - "type": "int", - "brief": "Server port number.", - "examples": [ - 80, - 8080, - 443 - ], - "requirement_level": "recommended", - "note": "When observed from the client side, and when communicating through an intermediary, `server.port` SHOULD represent the server port behind any intermediaries, for example proxies, if it's available.\n", - "stability": "stable" - } -] \ No newline at end of file + { + "name": "server.port", + "type": "int", + "brief": "Port of the local HTTP server that received the request.\n", + "examples": [ + 80, + 8080, + 443 + ], + "requirement_level": "opt_in", + "note": "See [Setting `server.address` and `server.port` attributes](/docs/http/http-spans.md#setting-serveraddress-and-serverport-attributes).\n> **Warning**\n> Since this attribute is based on HTTP headers, opting in to it may allow an attacker\n> to trigger cardinality limits, degrading the usefulness of the metric.\n", + "stability": "stable" + }, + { + "name": "server.port", + "type": "int", + "brief": "Port of the local HTTP server that received the request.\n", + "examples": [ + 80, + 8080, + 443 + ], + "requirement_level": { + "conditionally_required": "If `server.address` is set." + }, + "note": "See [Setting `server.address` and `server.port` attributes](/docs/http/http-spans.md#setting-serveraddress-and-serverport-attributes).\n", + "stability": "stable" + }, + { + "name": "server.port", + "type": "int", + "brief": "Server port number.", + "examples": [ + 80, + 8080, + 443 + ], + "requirement_level": "recommended", + "note": "When observed from the client side, and when communicating through an intermediary, `server.port` SHOULD represent the server port behind any intermediaries, for example proxies, if it's available.\n", + "stability": "stable" + } + ] +} \ No newline at end of file diff --git a/crates/weaver_resolver/data/registry-test-9-metric-extends/expected-attribute-catalog.json b/crates/weaver_resolver/data/registry-test-9-metric-extends/expected-attribute-catalog.json index 1a4128f49..6a4ade056 100644 --- a/crates/weaver_resolver/data/registry-test-9-metric-extends/expected-attribute-catalog.json +++ b/crates/weaver_resolver/data/registry-test-9-metric-extends/expected-attribute-catalog.json @@ -1,41 +1,43 @@ -[ - { - "name": "jvm.memory.pool.name", - "type": "string", - "brief": "Name of the memory pool.", - "examples": [ - "G1 Old Gen", - "G1 Eden space", - "G1 Survivor Space" - ], - "requirement_level": "recommended", - "note": "Pool names are generally obtained via [MemoryPoolMXBean#getName()](https://docs.oracle.com/en/java/javase/11/docs/api/java.management/java/lang/management/MemoryPoolMXBean.html#getName()).\n", - "stability": "stable" - }, - { - "name": "jvm.memory.type", - "type": { - "members": [ - { - "id": "heap", - "value": "heap", - "brief": "Heap memory.", - "stability": "stable" - }, - { - "id": "non_heap", - "value": "non_heap", - "brief": "Non-heap memory", - "stability": "stable" - } - ] +{ + "attributes": [ + { + "name": "jvm.memory.pool.name", + "type": "string", + "brief": "Name of the memory pool.", + "examples": [ + "G1 Old Gen", + "G1 Eden space", + "G1 Survivor Space" + ], + "requirement_level": "recommended", + "note": "Pool names are generally obtained via [MemoryPoolMXBean#getName()](https://docs.oracle.com/en/java/javase/11/docs/api/java.management/java/lang/management/MemoryPoolMXBean.html#getName()).\n", + "stability": "stable" }, - "brief": "The type of memory.", - "examples": [ - "heap", - "non_heap" - ], - "requirement_level": "recommended", - "stability": "stable" - } -] \ No newline at end of file + { + "name": "jvm.memory.type", + "type": { + "members": [ + { + "id": "heap", + "value": "heap", + "brief": "Heap memory.", + "stability": "stable" + }, + { + "id": "non_heap", + "value": "non_heap", + "brief": "Non-heap memory", + "stability": "stable" + } + ] + }, + "brief": "The type of memory.", + "examples": [ + "heap", + "non_heap" + ], + "requirement_level": "recommended", + "stability": "stable" + } + ] +} \ No newline at end of file diff --git a/crates/weaver_resolver/data/registry-test-lineage-0/expected-attribute-catalog.json b/crates/weaver_resolver/data/registry-test-lineage-0/expected-attribute-catalog.json index 62d1c226d..b05f31568 100644 --- a/crates/weaver_resolver/data/registry-test-lineage-0/expected-attribute-catalog.json +++ b/crates/weaver_resolver/data/registry-test-lineage-0/expected-attribute-catalog.json @@ -1,79 +1,81 @@ -[ - { - "name": "network.protocol.name", - "type": "string", - "brief": "Network protocol name", - "examples": [ - "http", - "spdy" - ], - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "network.protocol.name2", - "type": "string", - "brief": "Network protocol name", - "examples": [ - "http", - "spdy" - ], - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "network.protocol.version", - "type": "string", - "brief": "Network protocol version", - "examples": [ - "1.0", - "2.0" - ], - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "network.protocol.version", - "type": "string", - "brief": "Network protocol version", - "examples": [ - "1.0", - "2.0" - ], - "requirement_level": "opt_in", - "stability": "stable" - }, - { - "name": "network.type", - "type": "string", - "brief": "Network type", - "examples": [ - "ipv4", - "ipv6" - ], - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "server.port", - "type": "string", - "brief": "Server port", - "examples": [ - "80", - "443" - ], - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "server.port", - "type": "string", - "brief": "Server port", - "examples": [ - "80", - "443" - ], - "requirement_level": "opt_in", - "stability": "stable" - } -] \ No newline at end of file +{ + "attributes": [ + { + "name": "network.protocol.name", + "type": "string", + "brief": "Network protocol name", + "examples": [ + "http", + "spdy" + ], + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "network.protocol.name2", + "type": "string", + "brief": "Network protocol name", + "examples": [ + "http", + "spdy" + ], + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "network.protocol.version", + "type": "string", + "brief": "Network protocol version", + "examples": [ + "1.0", + "2.0" + ], + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "network.protocol.version", + "type": "string", + "brief": "Network protocol version", + "examples": [ + "1.0", + "2.0" + ], + "requirement_level": "opt_in", + "stability": "stable" + }, + { + "name": "network.type", + "type": "string", + "brief": "Network type", + "examples": [ + "ipv4", + "ipv6" + ], + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "server.port", + "type": "string", + "brief": "Server port", + "examples": [ + "80", + "443" + ], + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "server.port", + "type": "string", + "brief": "Server port", + "examples": [ + "80", + "443" + ], + "requirement_level": "opt_in", + "stability": "stable" + } + ] +} \ No newline at end of file diff --git a/crates/weaver_resolver/data/registry-test-lineage-1/expected-attribute-catalog.json b/crates/weaver_resolver/data/registry-test-lineage-1/expected-attribute-catalog.json index 04d0f57e1..3890cd13e 100644 --- a/crates/weaver_resolver/data/registry-test-lineage-1/expected-attribute-catalog.json +++ b/crates/weaver_resolver/data/registry-test-lineage-1/expected-attribute-catalog.json @@ -1,12 +1,14 @@ -[ - { - "name": "server.port", - "type": "string", - "brief": "Server port", - "examples": [ - "8080" - ], - "requirement_level": "recommended", - "stability": "stable" - } -] \ No newline at end of file +{ + "attributes": [ + { + "name": "server.port", + "type": "string", + "brief": "Server port", + "examples": [ + "8080" + ], + "requirement_level": "recommended", + "stability": "stable" + } + ] +} \ No newline at end of file diff --git a/crates/weaver_resolver/data/registry-test-lineage-2/expected-attribute-catalog.json b/crates/weaver_resolver/data/registry-test-lineage-2/expected-attribute-catalog.json index f207cfc25..533171013 100644 --- a/crates/weaver_resolver/data/registry-test-lineage-2/expected-attribute-catalog.json +++ b/crates/weaver_resolver/data/registry-test-lineage-2/expected-attribute-catalog.json @@ -1,104 +1,106 @@ -[ - { - "name": "network.protocol.name", - "type": "string", - "brief": "Network protocol name (registry)", - "examples": [ - "http", - "spdy" - ], - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "network.protocol.name", - "type": "string", - "brief": "Network protocol name (registry)", - "examples": [ - "http", - "spdy" - ], - "requirement_level": "opt_in", - "stability": "stable" - }, - { - "name": "network.protocol.name2", - "type": "string", - "brief": "Network protocol name", - "examples": [ - "http", - "spdy" - ], - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "network.protocol.version", - "type": "string", - "brief": "Network protocol version (registry)", - "examples": [ - "1.0", - "2.0" - ], - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "network.protocol.version", - "type": "string", - "brief": "Network protocol version (registry)", - "examples": [ - "1.0", - "2.0" - ], - "requirement_level": "opt_in", - "stability": "stable" - }, - { - "name": "network.type", - "type": "string", - "brief": "Network type (registry)", - "examples": [ - "ipv4", - "ipv6" - ], - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "server.port", - "type": "string", - "brief": "Brief of the top level", - "examples": [ - 80, - 8080, - 443 - ], - "requirement_level": "opt_in", - "stability": "stable" - }, - { - "name": "server.port", - "type": "string", - "brief": "Server port", - "examples": [ - "80", - "8080", - "443" - ], - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "server.port", - "type": "string", - "brief": "Server port", - "examples": [ - "80", - "8080", - "443" - ], - "requirement_level": "opt_in", - "stability": "stable" - } -] \ No newline at end of file +{ + "attributes": [ + { + "name": "network.protocol.name", + "type": "string", + "brief": "Network protocol name (registry)", + "examples": [ + "http", + "spdy" + ], + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "network.protocol.name", + "type": "string", + "brief": "Network protocol name (registry)", + "examples": [ + "http", + "spdy" + ], + "requirement_level": "opt_in", + "stability": "stable" + }, + { + "name": "network.protocol.name2", + "type": "string", + "brief": "Network protocol name", + "examples": [ + "http", + "spdy" + ], + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "network.protocol.version", + "type": "string", + "brief": "Network protocol version (registry)", + "examples": [ + "1.0", + "2.0" + ], + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "network.protocol.version", + "type": "string", + "brief": "Network protocol version (registry)", + "examples": [ + "1.0", + "2.0" + ], + "requirement_level": "opt_in", + "stability": "stable" + }, + { + "name": "network.type", + "type": "string", + "brief": "Network type (registry)", + "examples": [ + "ipv4", + "ipv6" + ], + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "server.port", + "type": "string", + "brief": "Brief of the top level", + "examples": [ + 80, + 8080, + 443 + ], + "requirement_level": "opt_in", + "stability": "stable" + }, + { + "name": "server.port", + "type": "string", + "brief": "Server port", + "examples": [ + "80", + "8080", + "443" + ], + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "server.port", + "type": "string", + "brief": "Server port", + "examples": [ + "80", + "8080", + "443" + ], + "requirement_level": "opt_in", + "stability": "stable" + } + ] +} \ No newline at end of file diff --git a/crates/weaver_resolver/data/registry-test-lineage-3/expected-attribute-catalog.json b/crates/weaver_resolver/data/registry-test-lineage-3/expected-attribute-catalog.json index c7dc6b107..004a42d2c 100644 --- a/crates/weaver_resolver/data/registry-test-lineage-3/expected-attribute-catalog.json +++ b/crates/weaver_resolver/data/registry-test-lineage-3/expected-attribute-catalog.json @@ -1,33 +1,35 @@ -[ - { - "name": "host.id", - "type": "string", - "brief": "Unique identifier for a host", - "examples": [ - "01556-1402034656" - ], - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "host.name", - "type": "string", - "brief": "Name of the host", - "examples": [ - "localhost" - ], - "requirement_level": "recommended", - "stability": "stable" - }, - { - "name": "host.name", - "type": "string", - "brief": "Name of the host", - "examples": [ - "localhost" - ], - "requirement_level": "recommended", - "stability": "stable", - "role": "descriptive" - } -] \ No newline at end of file +{ + "attributes": [ + { + "name": "host.id", + "type": "string", + "brief": "Unique identifier for a host", + "examples": [ + "01556-1402034656" + ], + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "host.name", + "type": "string", + "brief": "Name of the host", + "examples": [ + "localhost" + ], + "requirement_level": "recommended", + "stability": "stable" + }, + { + "name": "host.name", + "type": "string", + "brief": "Name of the host", + "examples": [ + "localhost" + ], + "requirement_level": "recommended", + "stability": "stable", + "role": "descriptive" + } + ] +} \ No newline at end of file diff --git a/crates/weaver_resolver/data/registry-test-published-1/expected-attribute-catalog.json b/crates/weaver_resolver/data/registry-test-published-1/expected-attribute-catalog.json new file mode 100644 index 000000000..0f72b718a --- /dev/null +++ b/crates/weaver_resolver/data/registry-test-published-1/expected-attribute-catalog.json @@ -0,0 +1,29 @@ +{ + "attributes": [ + { + "name": "a", + "type": "string", + "brief": "test a", + "requirement_level": "required", + "stability": "stable", + "annotations": {} + }, + { + "name": "a", + "type": "string", + "brief": "test a", + "requirement_level": "required", + "stability": "stable", + "annotations": {}, + "role": "identifying" + }, + { + "name": "a", + "type": "string", + "brief": "test a", + "requirement_level": "recommended", + "stability": "stable", + "annotations": {} + } + ] +} \ No newline at end of file diff --git a/crates/weaver_resolver/data/registry-test-published-1/expected-registry.json b/crates/weaver_resolver/data/registry-test-published-1/expected-registry.json new file mode 100644 index 000000000..0f2def153 --- /dev/null +++ b/crates/weaver_resolver/data/registry-test-published-1/expected-registry.json @@ -0,0 +1,82 @@ +{ + "registry_url": "https://127.0.0.1", + "groups": [ + { + "id": "imported.entity.a", + "type": "entity", + "brief": "a fun entity", + "note": "an entity note", + "stability": "stable", + "attributes": [ + 1 + ], + "name": "imported.entity.a", + "annotations": {} + }, + { + "id": "imported.event.a", + "type": "event", + "brief": "a fun event", + "note": "an event note", + "stability": "stable", + "attributes": [ + 2 + ], + "name": "imported.event.a", + "annotations": {}, + "entity_associations": [ + "imported.entity.a" + ] + }, + { + "id": "imported.metric.a", + "type": "metric", + "brief": "a fun metric", + "note": "a metric note", + "stability": "stable", + "attributes": [ + 0 + ], + "metric_name": "imported.metric.a", + "instrument": "histogram", + "unit": "s", + "annotations": {}, + "entity_associations": [ + "imported.entity.a" + ] + }, + { + "id": "span.my-span", + "type": "span", + "brief": "a fun span", + "note": "my fun span", + "stability": "beta", + "attributes": [ + 0 + ], + "span_kind": "client", + "name": "my-span", + "lineage": { + "provenance": { + "registry_id": "acme", + "path": "data/registry-test-published-1/registry/main.yaml" + }, + "attributes": { + "a": { + "source_group": "v2_dependency.published", + "inherited_fields": [ + "annotations", + "brief", + "note", + "requirement_level", + "stability" + ] + } + } + }, + "entity_associations": [ + "imported.entity.a" + ] + } + ] +} \ No newline at end of file diff --git a/crates/weaver_resolver/data/registry-test-published-1/published/registry_manifest.yaml b/crates/weaver_resolver/data/registry-test-published-1/published/registry_manifest.yaml new file mode 100644 index 000000000..f85d5ef60 --- /dev/null +++ b/crates/weaver_resolver/data/registry-test-published-1/published/registry_manifest.yaml @@ -0,0 +1,7 @@ +file_format: manifest/2.0.0 +name: resolved +description: Test repository that has been resolved. +version: 1.0.0 +repository_url: https://github.com/open-telemetry/weaver.git +stability: stable +resolved_schema_url: resolved_schema.yaml diff --git a/crates/weaver_resolver/data/registry-test-published-1/published/resolved_schema.yaml b/crates/weaver_resolver/data/registry-test-published-1/published/resolved_schema.yaml new file mode 100644 index 000000000..189cdb46f --- /dev/null +++ b/crates/weaver_resolver/data/registry-test-published-1/published/resolved_schema.yaml @@ -0,0 +1,60 @@ +file_format: resolved/2.0.0 +schema_url: http://todo +registry_id: published +attribute_catalog: +- key: a + type: string + brief: test a + stability: stable +registry: + registry_url: todo-why? + attributes: + - 0 + attribute_groups: + spans: + metrics: + - name: imported.metric.a + instrument: histogram + unit: s + attributes: + - base: 0 + requirement_level: required + entity_associations: + - imported.entity.a + brief: a fun metric + note: a metric note + stability: stable + events: + - name: imported.event.a + attributes: + - base: 0 + requirement_level: recommended + entity_associations: + - imported.entity.a + brief: a fun event + note: an event note + stability: stable + entities: + - type: imported.entity.a + identity: + - base: 0 + requirement_level: required + brief: a fun entity + note: an entity note + stability: stable +refinements: + spans: + metrics: + - id: imported.metric.a + name: imported.metric.a + instrument: histogram + unit: s + attributes: + - base: 0 + requirement_level: required + entity_associations: + - service + brief: a fun metric + note: a metric note + stability: stable + events: \ No newline at end of file diff --git a/crates/weaver_resolver/data/registry-test-published-1/registry/main.yaml b/crates/weaver_resolver/data/registry-test-published-1/registry/main.yaml new file mode 100644 index 000000000..988468d76 --- /dev/null +++ b/crates/weaver_resolver/data/registry-test-published-1/registry/main.yaml @@ -0,0 +1,21 @@ +version: '2' +spans: +- type: my-span + name: + note: how to make the name + brief: a fun span + note: my fun span + kind: client + stability: beta + attributes: + - ref: a + entity_associations: + - imported.entity.a +imports: + metrics: + - imported.* + events: + - imported.* + entities: + - imported.* + \ No newline at end of file diff --git a/crates/weaver_resolver/data/registry-test-published-1/registry/registry_manifest.yaml b/crates/weaver_resolver/data/registry-test-published-1/registry/registry_manifest.yaml new file mode 100644 index 000000000..ad5d44275 --- /dev/null +++ b/crates/weaver_resolver/data/registry-test-published-1/registry/registry_manifest.yaml @@ -0,0 +1,7 @@ +name: acme +description: This registry contains the semantic conventions for the Acme vendor. +semconv_version: 0.1.0 +schema_base_url: https://acme.com/schemas/ +dependencies: + - name: published + registry_path: data/registry-test-published-1/published diff --git a/crates/weaver_resolver/data/registry-test-v2-1-everything/expected-attribute-catalog.json b/crates/weaver_resolver/data/registry-test-v2-1-everything/expected-attribute-catalog.json index d2c44fad7..2bcb90528 100644 --- a/crates/weaver_resolver/data/registry-test-v2-1-everything/expected-attribute-catalog.json +++ b/crates/weaver_resolver/data/registry-test-v2-1-everything/expected-attribute-catalog.json @@ -1,55 +1,57 @@ -[ - { - "name": "network.protocol.name", - "type": "string", - "brief": "[OSI application layer](https://osi-model.com/application-layer/) or non-OSI equivalent.", - "examples": [ - "amqp", - "http", - "mqtt" - ], - "requirement_level": "recommended", - "note": "The value SHOULD be normalized to lowercase.", - "stability": "stable" - }, - { - "name": "network.protocol.name", - "type": "string", - "brief": "[OSI application layer](https://osi-model.com/application-layer/) or non-OSI equivalent.", - "examples": [ - "http", - "spdy" - ], - "requirement_level": { - "conditionally_required": "If not `http` and `network.protocol.version` is set." +{ + "attributes": [ + { + "name": "network.protocol.name", + "type": "string", + "brief": "[OSI application layer](https://osi-model.com/application-layer/) or non-OSI equivalent.", + "examples": [ + "amqp", + "http", + "mqtt" + ], + "requirement_level": "recommended", + "note": "The value SHOULD be normalized to lowercase.", + "stability": "stable" }, - "note": "The value SHOULD be normalized to lowercase.", - "stability": "stable" - }, - { - "name": "server.port", - "type": "int", - "brief": "Server port number.", - "examples": [ - 80, - 8080, - 443 - ], - "requirement_level": "recommended", - "note": "When observed from the client side, and when communicating through an intermediary, `server.port` SHOULD represent the server port behind any intermediaries, for example proxies, if it's available.\n", - "stability": "stable" - }, - { - "name": "server.port", - "type": "int", - "brief": "Server port number.", - "examples": [ - 80, - 8080, - 443 - ], - "requirement_level": "opt_in", - "note": "See [Setting `server.address` and `server.port` attributes](/docs/http/http-spans.md#setting-serveraddress-and-serverport-attributes).\n> **Warning**\n> Since this attribute is based on HTTP headers, opting in to it may allow an attacker\n> to trigger cardinality limits, degrading the usefulness of the metric.\n", - "stability": "stable" - } -] \ No newline at end of file + { + "name": "network.protocol.name", + "type": "string", + "brief": "[OSI application layer](https://osi-model.com/application-layer/) or non-OSI equivalent.", + "examples": [ + "http", + "spdy" + ], + "requirement_level": { + "conditionally_required": "If not `http` and `network.protocol.version` is set." + }, + "note": "The value SHOULD be normalized to lowercase.", + "stability": "stable" + }, + { + "name": "server.port", + "type": "int", + "brief": "Server port number.", + "examples": [ + 80, + 8080, + 443 + ], + "requirement_level": "recommended", + "note": "When observed from the client side, and when communicating through an intermediary, `server.port` SHOULD represent the server port behind any intermediaries, for example proxies, if it's available.\n", + "stability": "stable" + }, + { + "name": "server.port", + "type": "int", + "brief": "Server port number.", + "examples": [ + 80, + 8080, + 443 + ], + "requirement_level": "opt_in", + "note": "See [Setting `server.address` and `server.port` attributes](/docs/http/http-spans.md#setting-serveraddress-and-serverport-attributes).\n> **Warning**\n> Since this attribute is based on HTTP headers, opting in to it may allow an attacker\n> to trigger cardinality limits, degrading the usefulness of the metric.\n", + "stability": "stable" + } + ] +} \ No newline at end of file diff --git a/crates/weaver_resolver/data/registry-test-v2-2-multifile/expected-attribute-catalog.json b/crates/weaver_resolver/data/registry-test-v2-2-multifile/expected-attribute-catalog.json index d2c44fad7..2bcb90528 100644 --- a/crates/weaver_resolver/data/registry-test-v2-2-multifile/expected-attribute-catalog.json +++ b/crates/weaver_resolver/data/registry-test-v2-2-multifile/expected-attribute-catalog.json @@ -1,55 +1,57 @@ -[ - { - "name": "network.protocol.name", - "type": "string", - "brief": "[OSI application layer](https://osi-model.com/application-layer/) or non-OSI equivalent.", - "examples": [ - "amqp", - "http", - "mqtt" - ], - "requirement_level": "recommended", - "note": "The value SHOULD be normalized to lowercase.", - "stability": "stable" - }, - { - "name": "network.protocol.name", - "type": "string", - "brief": "[OSI application layer](https://osi-model.com/application-layer/) or non-OSI equivalent.", - "examples": [ - "http", - "spdy" - ], - "requirement_level": { - "conditionally_required": "If not `http` and `network.protocol.version` is set." +{ + "attributes": [ + { + "name": "network.protocol.name", + "type": "string", + "brief": "[OSI application layer](https://osi-model.com/application-layer/) or non-OSI equivalent.", + "examples": [ + "amqp", + "http", + "mqtt" + ], + "requirement_level": "recommended", + "note": "The value SHOULD be normalized to lowercase.", + "stability": "stable" }, - "note": "The value SHOULD be normalized to lowercase.", - "stability": "stable" - }, - { - "name": "server.port", - "type": "int", - "brief": "Server port number.", - "examples": [ - 80, - 8080, - 443 - ], - "requirement_level": "recommended", - "note": "When observed from the client side, and when communicating through an intermediary, `server.port` SHOULD represent the server port behind any intermediaries, for example proxies, if it's available.\n", - "stability": "stable" - }, - { - "name": "server.port", - "type": "int", - "brief": "Server port number.", - "examples": [ - 80, - 8080, - 443 - ], - "requirement_level": "opt_in", - "note": "See [Setting `server.address` and `server.port` attributes](/docs/http/http-spans.md#setting-serveraddress-and-serverport-attributes).\n> **Warning**\n> Since this attribute is based on HTTP headers, opting in to it may allow an attacker\n> to trigger cardinality limits, degrading the usefulness of the metric.\n", - "stability": "stable" - } -] \ No newline at end of file + { + "name": "network.protocol.name", + "type": "string", + "brief": "[OSI application layer](https://osi-model.com/application-layer/) or non-OSI equivalent.", + "examples": [ + "http", + "spdy" + ], + "requirement_level": { + "conditionally_required": "If not `http` and `network.protocol.version` is set." + }, + "note": "The value SHOULD be normalized to lowercase.", + "stability": "stable" + }, + { + "name": "server.port", + "type": "int", + "brief": "Server port number.", + "examples": [ + 80, + 8080, + 443 + ], + "requirement_level": "recommended", + "note": "When observed from the client side, and when communicating through an intermediary, `server.port` SHOULD represent the server port behind any intermediaries, for example proxies, if it's available.\n", + "stability": "stable" + }, + { + "name": "server.port", + "type": "int", + "brief": "Server port number.", + "examples": [ + 80, + 8080, + 443 + ], + "requirement_level": "opt_in", + "note": "See [Setting `server.address` and `server.port` attributes](/docs/http/http-spans.md#setting-serveraddress-and-serverport-attributes).\n> **Warning**\n> Since this attribute is based on HTTP headers, opting in to it may allow an attacker\n> to trigger cardinality limits, degrading the usefulness of the metric.\n", + "stability": "stable" + } + ] +} \ No newline at end of file diff --git a/crates/weaver_resolver/data/registry-test-v2-3-both-version/expected-attribute-catalog.json b/crates/weaver_resolver/data/registry-test-v2-3-both-version/expected-attribute-catalog.json index d2c44fad7..2bcb90528 100644 --- a/crates/weaver_resolver/data/registry-test-v2-3-both-version/expected-attribute-catalog.json +++ b/crates/weaver_resolver/data/registry-test-v2-3-both-version/expected-attribute-catalog.json @@ -1,55 +1,57 @@ -[ - { - "name": "network.protocol.name", - "type": "string", - "brief": "[OSI application layer](https://osi-model.com/application-layer/) or non-OSI equivalent.", - "examples": [ - "amqp", - "http", - "mqtt" - ], - "requirement_level": "recommended", - "note": "The value SHOULD be normalized to lowercase.", - "stability": "stable" - }, - { - "name": "network.protocol.name", - "type": "string", - "brief": "[OSI application layer](https://osi-model.com/application-layer/) or non-OSI equivalent.", - "examples": [ - "http", - "spdy" - ], - "requirement_level": { - "conditionally_required": "If not `http` and `network.protocol.version` is set." +{ + "attributes": [ + { + "name": "network.protocol.name", + "type": "string", + "brief": "[OSI application layer](https://osi-model.com/application-layer/) or non-OSI equivalent.", + "examples": [ + "amqp", + "http", + "mqtt" + ], + "requirement_level": "recommended", + "note": "The value SHOULD be normalized to lowercase.", + "stability": "stable" }, - "note": "The value SHOULD be normalized to lowercase.", - "stability": "stable" - }, - { - "name": "server.port", - "type": "int", - "brief": "Server port number.", - "examples": [ - 80, - 8080, - 443 - ], - "requirement_level": "recommended", - "note": "When observed from the client side, and when communicating through an intermediary, `server.port` SHOULD represent the server port behind any intermediaries, for example proxies, if it's available.\n", - "stability": "stable" - }, - { - "name": "server.port", - "type": "int", - "brief": "Server port number.", - "examples": [ - 80, - 8080, - 443 - ], - "requirement_level": "opt_in", - "note": "See [Setting `server.address` and `server.port` attributes](/docs/http/http-spans.md#setting-serveraddress-and-serverport-attributes).\n> **Warning**\n> Since this attribute is based on HTTP headers, opting in to it may allow an attacker\n> to trigger cardinality limits, degrading the usefulness of the metric.\n", - "stability": "stable" - } -] \ No newline at end of file + { + "name": "network.protocol.name", + "type": "string", + "brief": "[OSI application layer](https://osi-model.com/application-layer/) or non-OSI equivalent.", + "examples": [ + "http", + "spdy" + ], + "requirement_level": { + "conditionally_required": "If not `http` and `network.protocol.version` is set." + }, + "note": "The value SHOULD be normalized to lowercase.", + "stability": "stable" + }, + { + "name": "server.port", + "type": "int", + "brief": "Server port number.", + "examples": [ + 80, + 8080, + 443 + ], + "requirement_level": "recommended", + "note": "When observed from the client side, and when communicating through an intermediary, `server.port` SHOULD represent the server port behind any intermediaries, for example proxies, if it's available.\n", + "stability": "stable" + }, + { + "name": "server.port", + "type": "int", + "brief": "Server port number.", + "examples": [ + 80, + 8080, + 443 + ], + "requirement_level": "opt_in", + "note": "See [Setting `server.address` and `server.port` attributes](/docs/http/http-spans.md#setting-serveraddress-and-serverport-attributes).\n> **Warning**\n> Since this attribute is based on HTTP headers, opting in to it may allow an attacker\n> to trigger cardinality limits, degrading the usefulness of the metric.\n", + "stability": "stable" + } + ] +} \ No newline at end of file diff --git a/crates/weaver_resolver/src/attribute.rs b/crates/weaver_resolver/src/attribute.rs index ab7bd3986..99f782b3f 100644 --- a/crates/weaver_resolver/src/attribute.rs +++ b/crates/weaver_resolver/src/attribute.rs @@ -321,7 +321,35 @@ impl AttributeLookup for V1Schema { impl AttributeLookup for V2Schema { fn lookup_attribute(&self, key: &str) -> Option { - todo!("Lookup {key} on v2 schema.") + let fake_group_id = format!("v2_dependency.{}", self.registry_id); + self.attribute_catalog.iter().find_map(|attr| { + if attr.key == key { + Some(AttributeWithGroupId { + attribute: attribute::Attribute { + name: attr.key.clone(), + r#type: attr.r#type.clone(), + brief: attr.common.brief.clone(), + examples: attr.examples.clone(), + tag: None, + requirement_level: weaver_semconv::attribute::RequirementLevel::Basic( + weaver_semconv::attribute::BasicRequirementLevelSpec::Required, + ), + sampling_relevant: None, + note: attr.common.note.clone(), + stability: Some(attr.common.stability.clone()), + deprecated: attr.common.deprecated.clone(), + prefix: false, + tags: None, + annotations: Some(attr.common.annotations.clone()), + value: None, + role: None, + }, + group_id: fake_group_id.clone(), + }) + } else { + None + } + }) } } diff --git a/crates/weaver_resolver/src/dependency.rs b/crates/weaver_resolver/src/dependency.rs index 67755f189..24ead7e59 100644 --- a/crates/weaver_resolver/src/dependency.rs +++ b/crates/weaver_resolver/src/dependency.rs @@ -4,10 +4,13 @@ use globset::GlobSet; use serde::Deserialize; -use weaver_resolved_schema::attribute::UnresolvedAttribute; +use weaver_resolved_schema::attribute::Attribute; use weaver_resolved_schema::registry::Group; +use weaver_resolved_schema::v2::catalog::AttributeCatalog as V2Catalog; use weaver_resolved_schema::v2::ResolvedTelemetrySchema as V2Schema; use weaver_resolved_schema::ResolvedTelemetrySchema as V1Schema; +use weaver_resolved_schema::{attribute::UnresolvedAttribute, v2::Signal}; +use weaver_semconv::attribute::{AttributeRole, RequirementLevel}; use weaver_semconv::group::{GroupWildcard, ImportsWithProvenance}; use crate::{attribute::AttributeCatalog, Error}; @@ -49,18 +52,6 @@ impl ImportableDependency for V1Schema { include_all: bool, attribute_catalog: &mut AttributeCatalog, ) -> Result, Error> { - let build_globset = |wildcards: Option<&Vec>| { - let mut builder = GlobSet::builder(); - if let Some(wildcards_vec) = wildcards { - for wildcard in wildcards_vec.iter() { - _ = builder.add(wildcard.0.clone()); - } - } - builder.build().map_err(|e| Error::InvalidWildcard { - error: e.to_string(), - }) - }; - // Filter imports to only include those from the current registry let current_registry_imports: Vec<_> = imports.iter().collect(); @@ -130,14 +121,197 @@ impl ImportableDependency for V1Schema { } } +/// Converts a V2 attribute (with no requirement level) to a v1 attribute. +fn convert_v2_attribute( + attr: &weaver_resolved_schema::v2::attribute::Attribute, + requirement_level: RequirementLevel, + role: Option, +) -> Attribute { + Attribute { + name: attr.key.clone(), + r#type: attr.r#type.clone(), + brief: attr.common.brief.clone(), + examples: attr.examples.clone(), + tag: None, + requirement_level, + sampling_relevant: None, + note: attr.common.note.clone(), + stability: Some(attr.common.stability.clone()), + deprecated: attr.common.deprecated.clone(), + prefix: false, + tags: None, + annotations: Some(attr.common.annotations.clone()), + value: None, + role, + } +} + impl ImportableDependency for V2Schema { fn import_groups( &self, - _imports: &[ImportsWithProvenance], - _include_all: bool, - _attribute_catalog: &mut AttributeCatalog, + imports: &[ImportsWithProvenance], + include_all: bool, + attribute_catalog: &mut AttributeCatalog, ) -> Result, Error> { - todo!("Support V2 schema dependency resolution.") + let mut result = vec![]; + + // First import metrics. These are *by name* and come from the registry. + // This is the closest to V1 ref syntax we have. + let metrics_imports_matcher = + build_globset(imports.iter().find_map(|i| i.imports.metrics.as_ref()))?; + for m in self.registry.metrics.iter().filter(|m| { + let metric_name: &str = &m.name; + include_all || metrics_imports_matcher.is_match(metric_name) + }) { + let mut attributes = vec![]; + for ar in m.attributes.iter() { + let attr = self.attribute_catalog.attribute(&ar.base).ok_or( + Error::InvalidRegistryAttributeRef { + registry_id: self.registry_id.clone(), + attribute_ref: ar.base.0, + }, + )?; + attributes.push(attribute_catalog.attribute_ref(convert_v2_attribute( + attr, + ar.requirement_level.clone(), + None, + ))); + } + result.push(Group { + id: m.id().to_owned(), + r#type: weaver_semconv::group::GroupType::Metric, + brief: m.common.brief.clone(), + note: m.common.note.clone(), + prefix: "".to_owned(), + extends: None, + stability: Some(m.common.stability.clone()), + deprecated: m.common.deprecated.clone(), + attributes, + span_kind: None, + events: vec![], + metric_name: Some(m.name.to_string()), + instrument: Some(m.instrument.clone()), + unit: Some(m.unit.clone()), + name: None, + // TODO - fill this out. + lineage: None, + display_name: None, + body: None, + annotations: Some(m.common.annotations.clone()), + entity_associations: m.entity_associations.clone(), + visibility: None, + }); + } + + // Now event imports. + let events_imports_matcher = + build_globset(imports.iter().find_map(|i| i.imports.events.as_ref()))?; + for e in self.registry.events.iter().filter(|e| { + let event_name: &str = &e.name; + include_all || events_imports_matcher.is_match(event_name) + }) { + let mut attributes = vec![]; + for ar in e.attributes.iter() { + let attr = self.attribute_catalog.attribute(&ar.base).ok_or( + Error::InvalidRegistryAttributeRef { + registry_id: self.registry_id.clone(), + attribute_ref: ar.base.0, + }, + )?; + attributes.push(attribute_catalog.attribute_ref(convert_v2_attribute( + attr, + ar.requirement_level.clone(), + None, + ))); + } + result.push(Group { + id: e.id().to_owned(), + r#type: weaver_semconv::group::GroupType::Event, + brief: e.common.brief.clone(), + note: e.common.note.clone(), + prefix: "".to_owned(), + extends: None, + stability: Some(e.common.stability.clone()), + deprecated: e.common.deprecated.clone(), + attributes, + span_kind: None, + events: vec![], + metric_name: None, + instrument: None, + unit: None, + name: Some(e.name.to_string()), + // TODO - fill this out. + lineage: None, + display_name: None, + body: None, + annotations: Some(e.common.annotations.clone()), + entity_associations: e.entity_associations.clone(), + visibility: None, + }); + } + + // Now Entity imports. + let entities_imports_matcher = + build_globset(imports.iter().find_map(|i| i.imports.entities.as_ref()))?; + for e in self.registry.entities.iter().filter(|e| { + let entity_type: &str = &e.r#type; + include_all || entities_imports_matcher.is_match(entity_type) + }) { + let mut attributes = vec![]; + for ar in e.identity.iter() { + // TODO - this should be non-panic errors. + let attr = self.attribute_catalog.attribute(&ar.base).ok_or( + Error::InvalidRegistryAttributeRef { + registry_id: self.registry_id.clone(), + attribute_ref: ar.base.0, + }, + )?; + attributes.push(attribute_catalog.attribute_ref(convert_v2_attribute( + attr, + ar.requirement_level.clone(), + Some(AttributeRole::Identifying), + ))); + } + for ar in e.description.iter() { + // TODO - this should be non-panic errors. + let attr = self.attribute_catalog.attribute(&ar.base).ok_or( + Error::InvalidRegistryAttributeRef { + registry_id: self.registry_id.clone(), + attribute_ref: ar.base.0, + }, + )?; + attributes.push(attribute_catalog.attribute_ref(convert_v2_attribute( + attr, + ar.requirement_level.clone(), + Some(AttributeRole::Descriptive), + ))); + } + result.push(Group { + id: e.id().to_owned(), + r#type: weaver_semconv::group::GroupType::Entity, + brief: e.common.brief.clone(), + note: e.common.note.clone(), + prefix: "".to_owned(), + extends: None, + stability: Some(e.common.stability.clone()), + deprecated: e.common.deprecated.clone(), + attributes, + span_kind: None, + events: vec![], + metric_name: None, + instrument: None, + unit: None, + name: Some(e.r#type.to_string()), + // TODO - fill this out. + lineage: None, + display_name: None, + body: None, + annotations: Some(e.common.annotations.clone()), + entity_associations: vec![], + visibility: None, + }); + } + Ok(result) } } @@ -179,6 +353,8 @@ impl ImportableDependency for Vec { /// Helper trait for abstracting over V1 and V2 schema. trait UnresolvedAttributeLookup { /// Looks up group attributes on this repo. + /// id: The group id to find + /// return: The set of attributes the group defined, or None if the group was not found. fn lookup_group_attributes(&self, id: &str) -> Option>; } @@ -245,6 +421,19 @@ impl From for ResolvedDependency { } } +// Constructs a globset from a set of wildcards. +fn build_globset(wildcards: Option<&Vec>) -> Result { + let mut builder = GlobSet::builder(); + if let Some(wildcards_vec) = wildcards { + for wildcard in wildcards_vec.iter() { + _ = builder.add(wildcard.0.clone()); + } + } + builder.build().map_err(|e| Error::InvalidWildcard { + error: e.to_string(), + }) +} + #[cfg(test)] mod tests { use itertools::Itertools; diff --git a/crates/weaver_resolver/src/error.rs b/crates/weaver_resolver/src/error.rs index 50068164f..f2e01eb11 100644 --- a/crates/weaver_resolver/src/error.rs +++ b/crates/weaver_resolver/src/error.rs @@ -13,6 +13,27 @@ use weaver_semconv::provenance::Provenance; #[must_use] #[non_exhaustive] pub enum Error { + /// There was an issue resolving definition schema. + #[error(transparent)] + #[diagnostic(transparent)] + FailToResolveDefinition(#[from] weaver_semconv::Error), + + /// We discovered a circular dependency we cannot resolve. + #[error("Circular dependency detected: registry '{registry_id}' depends on itself through the chain: {chain}")] + CircularDependency { + /// The registry that depends on itself. + registry_id: String, + /// A string representing the dependency chain. + chain: String, + }, + + /// We've reached the maximum dependency depth for this registry. + #[error("Maximum dependency depth reached for registry `{registry}`. Cannot load further dependencies.")] + MaximumDependencyDepth { + /// The registry which has too many dependencies. + registry: String, + }, + /// An invalid URL. #[error("Invalid URL `{url:?}`, error: {error:?})")] #[diagnostic(help("Check the URL and try again."))] @@ -146,6 +167,15 @@ pub enum Error { error: String, }, + /// We + #[error("Invalid registry: {registry_id}. Unable to find attribute by index: {attribute_ref}")] + InvalidRegistryAttributeRef { + /// The registry with the issue. + registry_id: String, + /// The attribute index that does not exist in the registry. + attribute_ref: u32, + }, + /// A container for multiple errors. #[error("{:?}", format_errors(.0))] CompoundError(#[related] Vec), diff --git a/crates/weaver_resolver/src/lib.rs b/crates/weaver_resolver/src/lib.rs index 6c4f6c9be..940dc104a 100644 --- a/crates/weaver_resolver/src/lib.rs +++ b/crates/weaver_resolver/src/lib.rs @@ -125,7 +125,7 @@ impl SchemaResolver { pub fn load_semconv_repository( registry_repo: RegistryRepo, follow_symlinks: bool, - ) -> WResult { + ) -> WResult { loader::load_semconv_repository(registry_repo, follow_symlinks) } } diff --git a/crates/weaver_resolver/src/loader.rs b/crates/weaver_resolver/src/loader.rs index a7bbd4fe2..b00634e54 100644 --- a/crates/weaver_resolver/src/loader.rs +++ b/crates/weaver_resolver/src/loader.rs @@ -6,6 +6,7 @@ use rayon::iter::{IntoParallelIterator, ParallelBridge}; use std::collections::HashSet; use std::fmt::Display; use std::path::MAIN_SEPARATOR; +use weaver_common::vdir::{VirtualDirectory, VirtualDirectoryPath}; use weaver_semconv::registry::SemConvRegistry; use walkdir::DirEntry; @@ -16,6 +17,8 @@ use weaver_semconv::json_schema::JsonSchemaValidator; use weaver_semconv::registry_repo::{RegistryRepo, REGISTRY_MANIFEST}; use weaver_semconv::{group::ImportsWithProvenance, semconv::SemConvSpecWithProvenance}; +use crate::Error; + /// Maximum allowed depth for registry dependency chains. const MAX_DEPENDENCY_DEPTH: u32 = 10; @@ -41,19 +44,18 @@ pub enum LoadedSemconvRegistry { impl LoadedSemconvRegistry { /// Creates a loaded semconv registry from a single string. #[cfg(test)] - pub fn create_from_string(spec: &str) -> Result { + pub fn create_from_string(spec: &str) -> Result { use weaver_common::vdir::VirtualDirectoryPath; use weaver_semconv::provenance::Provenance; let path: VirtualDirectoryPath = "data".try_into().expect("Bad fake path for test"); - let repo = - RegistryRepo::try_new("default", &path).map_err(|e| crate::Error::InvalidUrl { - url: "test string".to_owned(), - error: format!("{e}"), - })?; + let repo = RegistryRepo::try_new("default", &path).map_err(|e| Error::InvalidUrl { + url: "test string".to_owned(), + error: format!("{e}"), + })?; let provenance = Provenance::new("default", ""); let spec_with_provenance = SemConvSpecWithProvenance::from_string(provenance, spec) .into_result_failing_non_fatal() - .map_err(|e| crate::Error::InvalidUrl { + .map_err(|e| Error::InvalidUrl { url: "test string".to_owned(), error: format!("{e}"), })?; @@ -146,7 +148,7 @@ impl Display for LoadedSemconvRegistry { pub(crate) fn load_semconv_repository( registry_repo: RegistryRepo, follow_symlinks: bool, -) -> WResult { +) -> WResult { // This method simply sets up the resolution state and delegates to the actual work. let mut visited_registries = HashSet::new(); let mut dependency_chain = Vec::new(); @@ -167,14 +169,11 @@ fn load_semconv_repository_recursive( max_dependency_depth: u32, visited_registries: &mut HashSet, dependency_chain: &mut Vec, -) -> WResult { +) -> WResult { // Make sure we don't go past our max dependency depth. if max_dependency_depth == 0 { - return WResult::FatalErr(weaver_semconv::Error::SemConvSpecError { - error: format!( - "Maximum dependency depth reached for registry `{}`. Cannot load further dependencies.", - registry_repo.registry_path_repr() - ), + return WResult::FatalErr(Error::MaximumDependencyDepth { + registry: registry_repo.registry_path_repr().to_owned(), }); } let registry_id = registry_repo.id().to_string(); @@ -182,10 +181,9 @@ fn load_semconv_repository_recursive( if visited_registries.contains(®istry_id) { dependency_chain.push(registry_id.clone()); let chain_str = dependency_chain.join(" → "); - return WResult::FatalErr(weaver_semconv::Error::SemConvSpecError { - error: format!( - "Circular dependency detected: registry '{registry_id}' depends on itself through the chain: {chain_str}" - ), + return WResult::FatalErr(Error::CircularDependency { + registry_id, + chain: chain_str, }); } // Add current registry to visited set and dependency chain @@ -194,8 +192,8 @@ fn load_semconv_repository_recursive( // Either load a fully resolved repository, or read in raw files. if let Some(manifest) = registry_repo.manifest() { - if let Some(resolved_url) = manifest.resolved_schema_url.as_ref() { - todo!("Loading resolved telemetry schema ({resolved_url}) is currently unsupported.\nSee https://github.com/open-telemetry/weaver/issues/1134"); + if let Some(resolved_url) = registry_repo.resolved_schema_url() { + load_resolved_repository(&resolved_url) } else { if manifest.dependencies.len() > 1 { todo!("Multiple dependencies is not supported yet.") @@ -222,7 +220,7 @@ fn load_semconv_repository_recursive( WResult::FatalErr(err) => return WResult::FatalErr(err), } } - Err(err) => return WResult::FatalErr(err), + Err(err) => return WResult::FatalErr(err.into()), } } // Now load the raw repository. @@ -237,12 +235,36 @@ fn load_semconv_repository_recursive( } } +/// Loads a resolved repository. +fn load_resolved_repository(path: &VirtualDirectoryPath) -> WResult { + // TODO - should we handle V1 and V2? + match from_vdir(path) { + Ok(resolved) => WResult::Ok(LoadedSemconvRegistry::ResolvedV2(resolved)), + Err(err) => WResult::FatalErr(err), + } +} + +/// Reads a serialized object with serde from the given virtual directory path. +fn from_vdir(f: &VirtualDirectoryPath) -> Result { + let path = VirtualDirectory::try_new(f).map_err(|e| Error::InvalidUrl { + url: f.to_string(), + error: format!("Invalid weaver path reference: {e}"), + })?; + let file = std::fs::File::open(path.path()).map_err(|_| Error::InvalidSchemaPath { + path: path.path().to_path_buf(), + })?; + let reader = std::io::BufReader::new(file); + serde_yaml::from_reader(reader).map_err(|e| Error::ConversionError { + message: format!("Unable to read resolved schema: {e}"), + }) +} + /// Loads a "raw" repository (composed of the original definition). fn load_definition_repository( registry_repo: RegistryRepo, follow_symlinks: bool, dependencies: Vec, -) -> WResult { +) -> WResult { // Define helper functions for filtering files. fn is_hidden(entry: &DirEntry) -> bool { entry @@ -326,7 +348,7 @@ fn load_definition_repository( specs.push(t); non_fatal_errors.extend(nfes); } - WResult::FatalErr(e) => return WResult::FatalErr(e), + WResult::FatalErr(e) => return WResult::FatalErr(Error::FailToResolveDefinition(e)), } } @@ -349,7 +371,10 @@ fn load_definition_repository( imports, dependencies, }, - non_fatal_errors, + non_fatal_errors + .into_iter() + .map(Error::FailToResolveDefinition) + .collect(), ) } @@ -364,11 +389,11 @@ mod tests { use crate::{ loader::{load_semconv_repository, load_semconv_repository_recursive}, - LoadedSemconvRegistry, + Error, LoadedSemconvRegistry, }; #[test] - fn test_load_unresolved_registry_with_dependencies() -> Result<(), weaver_semconv::Error> { + fn test_load_unresolved_registry_with_dependencies() -> Result<(), Error> { let registry_path = VirtualDirectoryPath::LocalFolder { path: "data/multi-registry/custom_registry".to_owned(), }; diff --git a/crates/weaver_resolver/src/registry.rs b/crates/weaver_resolver/src/registry.rs index 7d64f0042..3b6ae70a3 100644 --- a/crates/weaver_resolver/src/registry.rs +++ b/crates/weaver_resolver/src/registry.rs @@ -866,7 +866,6 @@ mod tests { use crate::attribute::AttributeCatalog; use crate::registry::cleanup_and_stabilize_catalog_and_registry; - use crate::registry::resolve_registry_with_dependencies; use crate::registry::UnresolvedGroup; use crate::registry::UnresolvedRegistry; use crate::LoadedSemconvRegistry; @@ -932,60 +931,40 @@ mod tests { test_dir.contains("prefix") && matches!( e, - weaver_semconv::Error::InvalidGroupUsesPrefix { - path_or_url: _, - group_id: _ - } + crate::Error::FailToResolveDefinition( + weaver_semconv::Error::InvalidGroupUsesPrefix { + path_or_url: _, + group_id: _ + } + ) ) }) .ignore(|e| { matches!( e, - weaver_semconv::Error::UnstableFileVersion { - version: _, - provenance: _, - } + crate::Error::FailToResolveDefinition( + weaver_semconv::Error::UnstableFileVersion { + version: _, + provenance: _, + } + ) ) }) .into_result_failing_non_fatal() .expect("Failed to load semconv specs"); - let LoadedSemconvRegistry::Unresolved { - repo, - specs, - imports, - dependencies, - } = loaded - else { - panic!("Should have loaded an unresolved registry") - }; - assert!( - dependencies.is_empty(), - "Unable to handle dependencies in resolution unit tests" - ); - let mut attr_catalog = AttributeCatalog::default(); - let observed_registry = resolve_registry_with_dependencies( - &mut attr_catalog, - repo, - specs, - imports, - vec![], - false, - ) - .into_result_failing_non_fatal(); - // Check that the resolved attribute catalog matches the expected attribute catalog. - let observed_attr_catalog = attr_catalog.drain_attributes(); + // We need to resolve dependencies. + let schema = SchemaResolver::resolve(loaded, false).into_result_failing_non_fatal(); // Check presence of an `expected-errors.json` file. // If the file is present, the test is expected to fail with the errors in the file. let expected_errors_file = format!("{test_dir}/expected-errors.json"); if PathBuf::from(&expected_errors_file).exists() { - assert!(observed_registry.is_err(), "This test is expected to fail"); + assert!(schema.is_err(), "This test is expected to fail"); let expected_errors: String = std::fs::read_to_string(&expected_errors_file) .expect("Failed to read expected errors file"); - let observed_errors = serde_json::to_string(&observed_registry).unwrap(); - // TODO - Write observed errors. - + let observed_errors = serde_json::to_string(&schema).unwrap(); + // Write observed errors. assert_eq!( canonicalize_json_string(&observed_errors).unwrap(), canonicalize_json_string(&expected_errors).unwrap(), @@ -996,21 +975,16 @@ mod tests { continue; } + let observed_schema = schema.expect("Failed to resolve the registry"); + let observed_attr_catalog = observed_schema.catalog; + // At this point, the normal behavior of this test is to pass. - let mut observed_registry = observed_registry.expect("Failed to resolve the registry"); + let mut observed_registry = observed_schema.registry; // Force registry URL to consistent string observed_registry.registry_url = "https://127.0.0.1".to_owned(); // Now sort groups so we don't get flaky tests. observed_registry.groups.sort_by_key(|g| g.id.to_owned()); - // Load the expected registry and attribute catalog. - let expected_attr_catalog_file = format!("{test_dir}/expected-attribute-catalog.json"); - let expected_attr_catalog: Vec = serde_json::from_reader( - std::fs::File::open(expected_attr_catalog_file) - .expect("Failed to open expected attribute catalog"), - ) - .expect("Failed to deserialize expected attribute catalog"); - // Write observed output. let observed_attr_catalog_file = OpenOptions::new() .create(true) @@ -1020,6 +994,16 @@ mod tests { .expect("Failed to open observed output file"); serde_json::to_writer_pretty(observed_attr_catalog_file, &observed_attr_catalog) .expect("Failed to write observed output."); + + // Load the expected registry and attribute catalog. + let expected_attr_catalog_file = format!("{test_dir}/expected-attribute-catalog.json"); + let expected_attr_catalog: weaver_resolved_schema::catalog::Catalog = + serde_json::from_reader( + std::fs::File::open(expected_attr_catalog_file) + .expect("Failed to open expected attribute catalog"), + ) + .expect("Failed to deserialize expected attribute catalog"); + // Compare values assert_eq!( observed_attr_catalog, expected_attr_catalog, diff --git a/crates/weaver_semconv/src/manifest.rs b/crates/weaver_semconv/src/manifest.rs index 28bbf9cb2..3619cd073 100644 --- a/crates/weaver_semconv/src/manifest.rs +++ b/crates/weaver_semconv/src/manifest.rs @@ -68,7 +68,11 @@ pub struct RegistryManifest { pub struct Dependency { /// The name of the dependency. pub name: String, - /// The registry path of the dependency. + /// The path to the dependency. + /// + /// This can be either: + /// - A manifest of a published registry + /// - A directory containing the raw definition. pub registry_path: VirtualDirectoryPath, } diff --git a/crates/weaver_semconv/src/registry_repo.rs b/crates/weaver_semconv/src/registry_repo.rs index f89c1acca..22c7c0eb0 100644 --- a/crates/weaver_semconv/src/registry_repo.rs +++ b/crates/weaver_semconv/src/registry_repo.rs @@ -8,16 +8,19 @@ use std::sync::Arc; use crate::manifest::RegistryManifest; use crate::Error; -use weaver_common::log_info; use weaver_common::vdir::{VirtualDirectory, VirtualDirectoryPath}; +use weaver_common::{get_path_type, log_info}; /// The name of the registry manifest file. pub const REGISTRY_MANIFEST: &str = "registry_manifest.yaml"; /// A semantic convention registry repository that can be: -/// - A simple wrapper around a local directory -/// - Initialized from a Git repository -/// - Initialized from a Git archive +/// - A definition repository, which is one of: +/// - A simple wrapper around a local directory +/// - Initialized from a Git repository +/// - Initialized from a Git archive +/// - A published repository, which is a manifest file +/// that denotes where to find aspects of the registry. #[derive(Default, Debug, Clone)] pub struct RegistryRepo { // A unique identifier for the registry (e.g. main, baseline, etc.) @@ -66,7 +69,7 @@ impl RegistryRepo { /// Returns the registry path textual representation. #[must_use] pub fn registry_path_repr(&self) -> &str { - self.registry.vdir_path() + self.registry.vdir_path_str() } /// Returns the registry manifest specified in the registry repo. @@ -75,9 +78,38 @@ impl RegistryRepo { self.manifest.as_ref() } + /// Returns the resolved schema URL, if available in the manifest. + #[must_use] + pub fn resolved_schema_url(&self) -> Option { + let manifest = self.manifest.as_ref()?; + let resolved_url: &str = manifest.resolved_schema_url.as_ref()?; + match get_path_type(resolved_url) { + weaver_common::PathType::RelativePath => { + // We need to understand if the manifest URL is the same as the registry URL. + let vdir_was_manifest_file = self.manifest_path()? == self.registry.path(); + Some(self.registry.vdir_path().map_sub_folder(|path| { + if vdir_was_manifest_file { + match Path::new(&path).parent() { + Some(parent) => format!("{}/{resolved_url}", parent.display()), + None => "".to_owned(), + } + } else { + format!("{path}/{resolved_url}") + } + })) + } + _ => resolved_url.try_into().ok(), + } + } + /// Returns the path to the `registry_manifest.yaml` file (if any). #[must_use] pub fn manifest_path(&self) -> Option { + // First check to see if we're pointing at a manifest. + if self.registry.path().is_file() { + // The VirtualDirectory *is* the registry. + return Some(self.registry.path().to_path_buf()); + } let manifest_path = self.registry.path().join(REGISTRY_MANIFEST); if manifest_path.exists() { log_info(format!( @@ -127,4 +159,60 @@ mod tests { // The local folder should not be deleted. assert!(repo_path.exists()); } + + #[test] + fn test_resolved_registry_path() { + // A RegistryRepo created from a local folder. + let registry_path = VirtualDirectoryPath::LocalFolder { + path: "tests/published_repository/resolved/1.0.0".to_owned(), + }; + let repo = + RegistryRepo::try_new("main", ®istry_path).expect("Failed to load test repository."); + let Some(manifest) = repo.manifest() else { + panic!("Did not resolve manifest for repo: {repo:?}"); + }; + assert_eq!(manifest.name, "resolved"); + + let Some(resolved_path) = repo.resolved_schema_url() else { + panic!( + "Should find a resolved schema path from manifest in {}", + repo.registry_path_repr() + ); + }; + assert_eq!( + "tests/published_repository/resolved/resolved_1.0.0.yaml", + format!("{resolved_path}") + ); + + // Now make sure a different repository with full URL works too. + let registry_path = VirtualDirectoryPath::LocalFolder { + path: "tests/published_repository/resolved/2.0.0".to_owned(), + }; + let repo = + RegistryRepo::try_new("main", ®istry_path).expect("Failed to load test repository."); + let Some(resolved_path) = repo.resolved_schema_url() else { + panic!( + "Should find a resolved schema path from manifest in {}", + repo.registry_path_repr() + ); + }; + assert_eq!("https://github.com/open-telemetry/weaver.git\\creates/weaver_semconv/tests/published_respository/resolved/resolved_2.0.0", format!("{resolved_path}")); + + // Now make sure when we publish a directory, we can find relative files in it. + let registry_path = VirtualDirectoryPath::LocalFolder { + path: "tests/published_repository/3.0.0".to_owned(), + }; + let repo = + RegistryRepo::try_new("main", ®istry_path).expect("Failed to load test repository."); + let Some(resolved_path) = repo.resolved_schema_url() else { + panic!( + "Should find a resolved schema path from manifest in {}", + repo.registry_path_repr() + ); + }; + assert_eq!( + "tests/published_repository/3.0.0/resolved_schema.yaml", + format!("{resolved_path}") + ); + } } diff --git a/crates/weaver_semconv/tests/published_repository/3.0.0/registry_manifest.yaml b/crates/weaver_semconv/tests/published_repository/3.0.0/registry_manifest.yaml new file mode 100644 index 000000000..eb2ca0198 --- /dev/null +++ b/crates/weaver_semconv/tests/published_repository/3.0.0/registry_manifest.yaml @@ -0,0 +1,7 @@ +file_format: manifest/2.0.0 +name: resolved +description: Test repository that has been resolved. +version: 3.0.0 +repository_url: https://github.com/open-telemetry/weaver.git +stability: stable +resolved_schema_url: resolved_schema.yaml diff --git a/crates/weaver_semconv/tests/published_repository/resolved/1.0.0 b/crates/weaver_semconv/tests/published_repository/resolved/1.0.0 new file mode 100644 index 000000000..1dc1d84e7 --- /dev/null +++ b/crates/weaver_semconv/tests/published_repository/resolved/1.0.0 @@ -0,0 +1,7 @@ +file_format: manifest/2.0.0 +name: resolved +description: Test repository that has been resolved. +version: 1.0.0 +repository_url: https://github.com/open-telemetry/weaver.git +stability: stable +resolved_schema_url: resolved_1.0.0.yaml diff --git a/crates/weaver_semconv/tests/published_repository/resolved/2.0.0 b/crates/weaver_semconv/tests/published_repository/resolved/2.0.0 new file mode 100644 index 000000000..681fa6400 --- /dev/null +++ b/crates/weaver_semconv/tests/published_repository/resolved/2.0.0 @@ -0,0 +1,7 @@ +file_format: manifest/2.0.0 +name: resolved +description: Test repository that has been resolved. +version: 2.0.0 +repository_url: https://github.com/open-telemetry/weaver.git +stability: stable +resolved_schema_url: https://github.com/open-telemetry/weaver.git\creates/weaver_semconv/tests/published_respository/resolved/resolved_2.0.0