Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update opentelemetry to 0.25 #89

Merged
merged 2 commits into from
Sep 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

## [Unreleased]

- Upgrade `opentelemetry` dependencies to `v0.25`.

## [0.34.0] - 2024-07-20

- Upgrade `opentelemetry` and `opentelemetry_sdk` to `v0.24`.
Expand Down
16 changes: 8 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@ flate2 = "1"
http = "1"
once_cell = "1"
futures-util = { version = "0.3", default-features = false, optional = true }
opentelemetry = "0.24"
opentelemetry_sdk = "0.24"
opentelemetry-http = "0.13"
opentelemetry-semantic-conventions = "0.16"
opentelemetry = "0.25"
opentelemetry_sdk = "0.25"
opentelemetry-http = "0.25"
opentelemetry-semantic-conventions = "0.25"
reqwest = { version = "0.12", default-features = false, features = ["blocking"], optional = true }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
Expand All @@ -57,14 +57,14 @@ thiserror = "1"
sysinfo = { version = "0.30", optional = true }

[dev-dependencies]
async-std = { version = "1.12.0", features = ["attributes"] }
async-std = { version = "1.13.0", features = ["attributes"] }
doc-comment = "0.3.3"
env_logger = "0.11.3"
insta = "1.39.0"
log = { version = "0.4", features = ["kv", "kv_sval"] }
opentelemetry_sdk = { version = "0.24", features = ["rt-async-std", "rt-tokio", "rt-tokio-current-thread", "logs_level_enabled"] }
opentelemetry-http = { version = "0.13", features = ["reqwest"] }
opentelemetry-appender-log = { version = "0.5", features = ["with-serde"] }
opentelemetry_sdk = { version = "0.25", features = ["rt-async-std", "rt-tokio", "rt-tokio-current-thread", "logs_level_enabled"] }
opentelemetry-http = { version = "0.25", features = ["reqwest"] }
opentelemetry-appender-log = { version = "0.25", features = ["with-serde"] }
rand = "0.8.5"
regex = "1.10.5"
reqwest = { version = "0.12", features = ["blocking"] }
Expand Down
4 changes: 2 additions & 2 deletions examples/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ fn main() {
KeyValue::new(semcov::trace::SERVER_PORT, 8080),
KeyValue::new(semcov::trace::NETWORK_PEER_ADDRESS, "10.1.2.4"),
KeyValue::new(semcov::trace::HTTP_RESPONSE_STATUS_CODE, 200),
KeyValue::new(semcov::trace::ENDUSER_ID, "marry"),
KeyValue::new(semcov::attribute::USER_ID, "marry"),
])
.start(&client_tracer);
{
Expand All @@ -103,7 +103,7 @@ fn main() {
KeyValue::new(semcov::trace::CLIENT_ADDRESS, "10.1.2.3"),
KeyValue::new(semcov::trace::NETWORK_PEER_ADDRESS, "10.1.2.2"),
KeyValue::new(semcov::trace::USER_AGENT_ORIGINAL, "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0"),
KeyValue::new(semcov::trace::ENDUSER_ID, "marry"),
KeyValue::new(semcov::attribute::USER_ID, "marry"),
]);
let span = server_tracer.build_with_context(builder, &cx);
{
Expand Down
36 changes: 18 additions & 18 deletions src/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,17 @@ pub(crate) fn time_to_string(time: SystemTime) -> String {
}

#[cfg(any(feature = "trace", feature = "logs"))]
pub(crate) fn attrs_to_properties<'a, T>(
attributes: &'a [T],
pub(crate) fn attrs_to_properties<'a, A, T: 'a>(
attributes: A,
resource: Option<&Resource>,
#[cfg(feature = "trace")] links: &[Link],
) -> Option<Properties>
where
A: Iterator<Item = &'a T> + 'a,
&'a T: Into<AttrKeyValue<'a>>,
{
#[allow(unused_mut)]
let mut properties: Properties = attributes
.iter()
.map(|kv| kv.into())
.map(|kv| (kv.0, kv.1))
.chain(
Expand All @@ -68,12 +68,12 @@ where
}

#[cfg(any(feature = "trace", feature = "logs"))]
pub(crate) fn attrs_to_map<'a, T>(attributes: &'a [T]) -> HashMap<&str, &dyn AttrValue>
pub(crate) fn attrs_to_map<'a, A, T: 'a>(attributes: A) -> HashMap<&'a str, &'a dyn AttrValue>
where
A: Iterator<Item = &'a T> + 'a,
&'a T: Into<AttrKeyValue<'a>>,
{
attributes
.iter()
.map(|kv| kv.into())
.map(|kv| (kv.0, kv.1))
.collect()
Expand Down Expand Up @@ -156,7 +156,7 @@ impl AttrValue for AnyValue {
AnyValue::Bytes(bytes) => {
let mut s = String::new();
s.push('[');
for &b in bytes {
for &b in bytes.as_ref() {
s.push_str(&format!("{}", b));
s.push(',');
}
Expand All @@ -169,7 +169,7 @@ impl AttrValue for AnyValue {
AnyValue::ListAny(list) => {
let mut s = String::new();
s.push('[');
for v in list {
for v in list.as_ref() {
s.push_str(v.as_str().as_ref());
s.push(',');
}
Expand All @@ -182,7 +182,7 @@ impl AttrValue for AnyValue {
AnyValue::Map(map) => {
let mut s = String::new();
s.push('{');
for (k, v) in map {
for (k, v) in map.as_ref() {
s.push_str(k.as_str());
s.push(':');
s.push_str(v.as_str().as_ref());
Expand Down Expand Up @@ -214,7 +214,7 @@ mod tests {
fn attrs_to_properties_filters_ms() {
let attrs = vec![KeyValue::new("a", "b"), KeyValue::new("_MS.a", "b")];
let resource = Resource::new([KeyValue::new("c", "d"), KeyValue::new("_MS.c", "d")]);
let props = attrs_to_properties(&attrs, Some(&resource), &[]).unwrap();
let props = attrs_to_properties(attrs.iter(), Some(&resource), &[]).unwrap();
assert_eq!(props.len(), 2);
assert_eq!(props.get(&"a".into()).unwrap().as_ref(), "b");
assert_eq!(props.get(&"c".into()).unwrap().as_ref(), "d");
Expand All @@ -224,7 +224,7 @@ mod tests {
fn attrs_to_properties_encodes_links() {
let attrs: Vec<KeyValue> = Vec::new();
let links = vec![Link::new(SpanContext::empty_context(), Vec::new(), 0)];
let props = attrs_to_properties(&attrs, None, &links).unwrap();
let props = attrs_to_properties(attrs.iter(), None, &links).unwrap();
assert_eq!(props.len(), 1);
assert_eq!(
props.get(&"_MS.links".into()).unwrap().as_ref(),
Expand All @@ -240,7 +240,7 @@ mod tests {
for _ in 0..input_len {
links.push(Link::new(SpanContext::empty_context(), Vec::new(), 0));
}
let props = attrs_to_properties(&attrs, None, &links).unwrap();
let props = attrs_to_properties(attrs.iter(), None, &links).unwrap();
assert_eq!(props.len(), 1);
let encoded_links = props.get(&"_MS.links".into()).unwrap();
let deserialized: serde_json::Value = serde_json::from_str(encoded_links.as_ref()).unwrap();
Expand All @@ -253,7 +253,7 @@ mod tests {
#[test]
fn attrs_map_to_properties_filters_ms() {
let attrs = vec![KeyValue::new("a", "b"), KeyValue::new("_MS.a", "b")];
let attrs_map = attrs_to_map(&attrs);
let attrs_map = attrs_to_map(attrs.iter());
assert_eq!(attrs_map.len(), 2);
let props = attrs_map_to_properties(attrs_map).unwrap();
assert_eq!(props.len(), 1);
Expand All @@ -264,12 +264,12 @@ mod tests {
#[test_case(AnyValue::Double(1.2), "1.2" ; "double")]
#[test_case(AnyValue::String("test".into()), "test" ; "string")]
#[test_case(AnyValue::Boolean(true), "true" ; "boolean")]
#[test_case(AnyValue::Bytes(vec![]), "[]" ; "empty bytes")]
#[test_case(AnyValue::Bytes(vec![1, 2, 3]), "[1,2,3]" ; "bytes")]
#[test_case(AnyValue::ListAny(vec![]), "[]" ; "empty list")]
#[test_case(AnyValue::ListAny(vec![1.into(), "test".into()]), "[1,test]" ; "list")]
#[test_case(AnyValue::Map([].into()), "{}" ; "empty map")]
#[test_case(AnyValue::Map([("k1".into(), "test".into())].into()), "{k1:test}" ; "map")]
#[test_case(AnyValue::Bytes(Box::new(vec![])), "[]" ; "empty bytes")]
#[test_case(AnyValue::Bytes(Box::new(vec![1, 2, 3])), "[1,2,3]" ; "bytes")]
#[test_case(AnyValue::ListAny(Box::new(vec![])), "[]" ; "empty list")]
#[test_case(AnyValue::ListAny(Box::new(vec![1.into(), "test".into()])), "[1,test]" ; "list")]
#[test_case(AnyValue::Map(Box::new([].into())), "{}" ; "empty map")]
#[test_case(AnyValue::Map(Box::new([("k1".into(), "test".into())].into())), "{k1:test}" ; "map")]
fn any_value_as_str(v: AnyValue, expected: &'static str) {
assert_eq!(expected.to_string(), (&v as &dyn AttrValue).as_str());
}
Expand Down
68 changes: 37 additions & 31 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,36 +95,41 @@
//! }
//! ```
//!
//! ## Live Metrics
//!
//! This requires the **live-metrics** feature _and_ the `build_batch`/`install_batch` methods.
//!
//! Enable live metrics collection: <https://learn.microsoft.com/en-us/azure/azure-monitor/app/live-stream>.
//!
//! Metrics are based on traces. See attribute mapping below for how traces are mapped to requests,
//! dependencies and exceptions and how they are deemed "successful" or not.
//!
//! To configure role, instance, and machine name provide `service.name`, `service.instance.id`, and
//! `host.name` resource attributes respectively in the trace config.
//!
//! Sample telemetry is not supported, yet.
//!
//! ```no_run
//! use opentelemetry::trace::Tracer as _;
//!
//! #[tokio::main]
//! async fn main() {
//! let tracer = opentelemetry_application_insights::new_pipeline_from_env()
//! .expect("env var APPLICATIONINSIGHTS_CONNECTION_STRING is valid connection string")
//! .with_client(reqwest::Client::new())
//! .with_live_metrics(true)
//! .install_batch(opentelemetry_sdk::runtime::Tokio);
//!
//! // ... send traces ...
//!
//! opentelemetry::global::shutdown_tracer_provider();
//! }
//! ```
#![cfg_attr(
feature = "live-metrics",
doc = r#"
## Live Metrics

This requires the **live-metrics** feature _and_ the `build_batch`/`install_batch` methods.

Enable live metrics collection: <https://learn.microsoft.com/en-us/azure/azure-monitor/app/live-stream>.

Metrics are based on traces. See attribute mapping below for how traces are mapped to requests,
dependencies and exceptions and how they are deemed "successful" or not.

To configure role, instance, and machine name provide `service.name`, `service.instance.id`, and
`host.name` resource attributes respectively in the trace config.

Sample telemetry is not supported, yet.

```no_run
use opentelemetry::trace::Tracer as _;

#[tokio::main]
async fn main() {
let tracer = opentelemetry_application_insights::new_pipeline_from_env()
.expect("env var APPLICATIONINSIGHTS_CONNECTION_STRING is valid connection string")
.with_client(reqwest::Client::new())
.with_live_metrics(true)
.install_batch(opentelemetry_sdk::runtime::Tokio);

// ... send traces ...

opentelemetry::global::shutdown_tracer_provider();
}
```
"#
)]
//!
//! ## Simple or Batch
//!
Expand Down Expand Up @@ -231,7 +236,7 @@
//!
//! | OpenTelemetry attribute key | Application Insights field |
//! | -------------------------------------------------------------------------- | -------------------------------------------------------- |
//! | `enduser.id` | Context: Authenticated user id (`ai.user.authUserId`) |
//! | `user.id` | Context: Authenticated user id (`ai.user.authUserId`) |
//! | `SpanKind::Server` + `http.request.method` + `http.route` | Context: Operation Name (`ai.operation.name`) |
//! | `ai.*` | Context: AppInsights Tag (`ai.*`) |
//! | `url.full` | Dependency Data |
Expand Down Expand Up @@ -263,6 +268,7 @@
//!
//! | Attribute | Deprecated attribute |
//! | --------------------------- | ------------------------------------------ |
//! | `user.id` | `enduser.id` |
//! | `db.namespace` | `db.name` |
//! | `db.query.text` | `db.statement` |
//! | `http.request.method` | `http.method` |
Expand Down
Loading
Loading