From b14ad9af59fa2369fb45f39a80ad8a709bb1d887 Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Tue, 16 Jun 2026 17:34:45 +0200 Subject: [PATCH 1/3] mas-handlers: expose the GraphQL operation on the response extensions Define a `GraphQlOperation` type holding the operation type and name, and attach it to the GraphQL response via the response extensions, so the HTTP logging middleware can pick it up. The operation type is resolved from the parsed query document, which is cached on the request and reused by the executor. --- crates/handlers/src/graphql/mod.rs | 109 +++++++++++++++++++++++++---- crates/handlers/src/lib.rs | 3 +- 2 files changed, 99 insertions(+), 13 deletions(-) diff --git a/crates/handlers/src/graphql/mod.rs b/crates/handlers/src/graphql/mod.rs index ef7169d4f..c22a1010d 100644 --- a/crates/handlers/src/graphql/mod.rs +++ b/crates/handlers/src/graphql/mod.rs @@ -1,3 +1,4 @@ +// Copyright 2026 Element Creations Ltd. // Copyright 2024, 2025 New Vector Ltd. // Copyright 2022-2024 The Matrix.org Foundation C.I.C. // @@ -12,6 +13,7 @@ use async_graphql::{ EmptySubscription, InputObject, extensions::Tracing, http::{GraphQLPlaygroundConfig, MultipartOptions, playground_source}, + parser::types::{DocumentOperations, OperationType}, }; use axum::{ Extension, Json, @@ -35,7 +37,9 @@ use mas_matrix::HomeserverConnection; use mas_policy::{InstantiateError, Policy, PolicyFactory}; use mas_router::UrlBuilder; use mas_storage::{BoxRepository, BoxRepositoryFactory, RepositoryError}; -use opentelemetry_semantic_conventions::trace::{GRAPHQL_DOCUMENT, GRAPHQL_OPERATION_NAME}; +use opentelemetry_semantic_conventions::trace::{ + GRAPHQL_DOCUMENT, GRAPHQL_OPERATION_NAME, GRAPHQL_OPERATION_TYPE, +}; use rand::{SeedableRng, thread_rng}; use rand_chacha::ChaChaRng; use state::has_session_ended; @@ -146,21 +150,90 @@ pub fn schema( schema_builder().extension(Tracing).data(state).finish() } -fn span_for_graphql_request(request: &async_graphql::Request) -> tracing::Span { +fn span_and_operation_for_graphql_request( + request: &mut async_graphql::Request, +) -> (tracing::Span, GraphQLOperation) { let span = info_span!( "GraphQL operation", "otel.name" = tracing::field::Empty, "otel.kind" = "server", { GRAPHQL_DOCUMENT } = request.query, { GRAPHQL_OPERATION_NAME } = tracing::field::Empty, + { GRAPHQL_OPERATION_TYPE } = tracing::field::Empty, ); - if let Some(name) = &request.operation_name { - span.record("otel.name", name); - span.record(GRAPHQL_OPERATION_NAME, name); + let mut graphql_operation = GraphQLOperation { + operation_type: None, + operation_name: None, + }; + + // We need to clone the operation_name before parsing the query, else we're + // going to have a borrow conflict between request.parsed_query() and + // request.operation_name + let operation_name = request.operation_name.clone(); + if let Ok(document) = request.parsed_query() { + match (&document.operations, operation_name) { + // A single anonymous operation, with no name requested: the + // document defines no name for it, so we only record the type. + (DocumentOperations::Single(operation), None) => { + span.record("otel.name", format!("GraphQL {}", operation.node.ty)); + span.record( + GRAPHQL_OPERATION_TYPE, + tracing::field::display(operation.node.ty), + ); + graphql_operation.operation_type = Some(operation.node.ty); + } + + (DocumentOperations::Multiple(operations), Some(name)) => { + if let Some((name, operation)) = operations.get_key_value(name.as_str()) { + span.record( + "otel.name", + format!("GraphQL {} {}", operation.node.ty, name), + ); + span.record( + GRAPHQL_OPERATION_TYPE, + tracing::field::display(operation.node.ty), + ); + span.record(GRAPHQL_OPERATION_NAME, tracing::field::display(name)); + graphql_operation.operation_type = Some(operation.node.ty); + graphql_operation.operation_name = Some(name.to_string()); + } + } + + (DocumentOperations::Multiple(operations), None) if operations.len() == 1 => { + let mut iter = operations.iter(); + let (name, operation) = iter.next().unwrap(); + span.record( + "otel.name", + format!("GraphQL {} {}", operation.node.ty, name), + ); + span.record( + GRAPHQL_OPERATION_TYPE, + tracing::field::display(operation.node.ty), + ); + span.record(GRAPHQL_OPERATION_NAME, name.as_ref()); + graphql_operation.operation_type = Some(operation.node.ty); + graphql_operation.operation_name = Some(name.to_string()); + } + + // Cases the executor rejects, so we don't record a misleading + // operation: a single anonymous operation with a name requested, or + // several named operations with no requested name (ambiguous). + (DocumentOperations::Single(_), Some(_)) | (DocumentOperations::Multiple(_), None) => {} + } } - span + (span, graphql_operation) +} + +/// The GraphQL operation being executed, attached to the response extensions so +/// the HTTP logging middleware can record it on the request log line. +#[derive(Clone, Debug)] +pub struct GraphQLOperation { + /// The type of the operation: query, mutation or subscription. + pub operation_type: Option, + /// The name of the operation, as defined in the query document. + pub operation_name: Option, } #[derive(thiserror::Error, Debug)] @@ -339,7 +412,7 @@ pub async fn post( let content_type = content_type.map(|TypedHeader(h)| h.to_string()); - let request = async_graphql::http::receive_body( + let mut request = async_graphql::http::receive_body( content_type, body.map_err(std::io::Error::other).into_async_read(), MultipartOptions::default(), @@ -347,7 +420,7 @@ pub async fn post( .await? .data(requester); // XXX: this should probably return another error response? - let span = span_for_graphql_request(&request); + let (span, operation) = span_and_operation_for_graphql_request(&mut request); let mut response = schema.execute(request).instrument(span).await; if has_session_ended(&mut response) { @@ -363,7 +436,13 @@ pub async fn post( let headers = response.http_headers.clone(); - Ok((headers, cache_control, cookie_jar, Json(response))) + Ok(( + headers, + cache_control, + cookie_jar, + Extension(operation), + Json(response), + )) } pub async fn get( @@ -395,10 +474,10 @@ pub async fn get( ) .await?; - let request = + let mut request = async_graphql::http::parse_query_string(&query.unwrap_or_default())?.data(requester); - let span = span_for_graphql_request(&request); + let (span, operation) = span_and_operation_for_graphql_request(&mut request); let mut response = schema.execute(request).instrument(span).await; if has_session_ended(&mut response) { @@ -414,7 +493,13 @@ pub async fn get( let headers = response.http_headers.clone(); - Ok((headers, cache_control, cookie_jar, Json(response))) + Ok(( + headers, + cache_control, + cookie_jar, + Extension(operation), + Json(response), + )) } pub async fn playground() -> impl IntoResponse { diff --git a/crates/handlers/src/lib.rs b/crates/handlers/src/lib.rs index 5063c7697..357d0bd4b 100644 --- a/crates/handlers/src/lib.rs +++ b/crates/handlers/src/lib.rs @@ -107,7 +107,8 @@ pub use self::{ activity_tracker::{ActivityTracker, Bound as BoundActivityTracker}, admin::router as admin_api_router, graphql::{ - Schema as GraphQLSchema, schema as graphql_schema, schema_builder as graphql_schema_builder, + GraphQLOperation, Schema as GraphQLSchema, schema as graphql_schema, + schema_builder as graphql_schema_builder, }, preferred_language::PreferredLanguage, rate_limit::{Limiter, RequesterFingerprint}, From 98106df25a37517cb093c4d54ee0e0985096872b Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Tue, 16 Jun 2026 17:36:21 +0200 Subject: [PATCH 2/3] mas-cli: log the GraphQL operation on the request log line Read the `GraphQlOperation` set by the GraphQL handler from the response extensions in the logging middleware, and record the operation type and name on the `http.server.response` log line when present. --- crates/cli/src/server.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/crates/cli/src/server.rs b/crates/cli/src/server.rs index 15114a5d9..62aed7ce5 100644 --- a/crates/cli/src/server.rs +++ b/crates/cli/src/server.rs @@ -21,6 +21,7 @@ use hyper::{Method, Request, Response, StatusCode, Version, header::USER_AGENT}; use listenfd::ListenFd; use mas_config::{HttpBindConfig, HttpResource, HttpTlsConfig, UnixOrTcp}; use mas_context::LogContext; +use mas_handlers::GraphQLOperation; use mas_listener::{ConnectionInfo, unix_or_tcp::UnixOrTcpListener}; use mas_router::Route; use mas_templates::Templates; @@ -191,6 +192,16 @@ async fn log_response_middleware( let response = next.run(request).await; + // If the request went through the GraphQL handler, it will have recorded the + // operation type and name in the response extensions. + let graphql = response.extensions().get::(); + let graphql_operation_type = graphql + .and_then(|operation| operation.operation_type) + .map(tracing::field::display); + let graphql_operation_name = graphql + .and_then(|operation| operation.operation_name.as_deref()) + .map(tracing::field::display); + let Some(stats) = LogContext::maybe_with(LogContext::stats) else { tracing::error!("Missing log context for request, this is a bug!"); return response; @@ -200,14 +211,26 @@ async fn log_response_middleware( match status_code.as_u16() { 100..=399 => tracing::info!( name: "http.server.response", + { + graphql.operation.type = graphql_operation_type, + graphql.operation.name = graphql_operation_name, + }, "\"{method} {path} HTTP/{version}\" {status_code} {user_agent:?} [{stats}]", ), 400..=499 => tracing::warn!( name: "http.server.response", + { + graphql.operation.type = graphql_operation_type, + graphql.operation.name = graphql_operation_name, + }, "\"{method} {path} HTTP/{version}\" {status_code} {user_agent:?} [{stats}]", ), 500..=599 => tracing::error!( name: "http.server.response", + { + graphql.operation.type = graphql_operation_type, + graphql.operation.name = graphql_operation_name, + }, "\"{method} {path} HTTP/{version}\" {status_code} {user_agent:?} [{stats}]", ), _ => { /* This shouldn't happen */ } From e0c03b06e841cc4599c1513213305f0383b4a949 Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Wed, 17 Jun 2026 18:50:22 +0200 Subject: [PATCH 3/3] deps: upgrade reqwest 0.13, sentry 0.48, opentelemetry 0.32 We need to group the sentry and opentelemetry bumps together because they both upgraded reqwest to 0.13. - reqwest 0.12 -> 0.13: rename the rustls feature to rustls-no-provider, add the now-opt-in 'form' feature. - sentry 0.46 -> 0.48: add rustls-no-provider so Sentry's reqwest 0.13 transport reuses our process-wide aws-lc-rs provider. - opentelemetry 0.31 -> 0.32 / tracing-opentelemetry 0.33: update the get_otel_context call in mas-context for the new signature. opentelemetry-jaeger-propagator 0.32 is deprecated upstream but still published; we keep it for now (with an expect(deprecated)) and will vendor it in-tree once it's actually removed. --- Cargo.lock | 141 +++++++++++++++++++++--------------- Cargo.toml | 37 +++++----- crates/cli/src/telemetry.rs | 6 ++ crates/context/src/fmt.rs | 2 +- 4 files changed, 109 insertions(+), 77 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4305a870f..13ba9ea05 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4098,9 +4098,9 @@ checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "opentelemetry" -version = "0.31.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b84bcd6ae87133e903af7ef497404dda70c60d0ea14895fc8a5e6722754fc2a0" +checksum = "b0142c63252a9e054e68a4c61a5778f7b14f576274d593f8ce883d191a099682" dependencies = [ "futures-core", "futures-sink", @@ -4112,9 +4112,9 @@ dependencies = [ [[package]] name = "opentelemetry-http" -version = "0.31.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7a6d09a73194e6b66df7c8f1b680f156d916a1a942abf2de06823dd02b7855d" +checksum = "5683015d09e2df236ef005b17f6f196f0d5f6313c4fa43a7b6a53b52776e4331" dependencies = [ "async-trait", "bytes", @@ -4125,9 +4125,9 @@ dependencies = [ [[package]] name = "opentelemetry-instrumentation-process" -version = "0.1.2" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a81f1738bbdcf58eae20bd85ab0973f9c1f700ba37789e3253dc4e7ba61855c" +checksum = "065d9891eac9d4089f2c61872a43236029496c3642f62706ddbe71e96f6e00be" dependencies = [ "opentelemetry", "opentelemetry-semantic-conventions", @@ -4136,9 +4136,9 @@ dependencies = [ [[package]] name = "opentelemetry-instrumentation-tokio" -version = "0.1.2" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fbe5cbcb32e33e68fd7a3a60d47c3b0a00cd40a4d012cec2f862f463dc0c296" +checksum = "aac2efa77dc2389d53fc00e53074a8117f53b1bd5ab92b0cd8bf7625156dc49f" dependencies = [ "opentelemetry", "tokio", @@ -4146,18 +4146,18 @@ dependencies = [ [[package]] name = "opentelemetry-jaeger-propagator" -version = "0.31.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3bbd907f151104a112f749f3b8387ef669b7264e0bb80546ea0700a3b307b7" +checksum = "92c2cebef9a57a493394ba0901b692a6915cc4a1314e93f905db1344392b4aa4" dependencies = [ "opentelemetry", ] [[package]] name = "opentelemetry-otlp" -version = "0.31.1" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f69cd6acbb9af919df949cd1ec9e5e7fdc2ef15d234b6b795aaa525cc02f71f" +checksum = "9966929966d17620d7c316c643ba62631826e10021409357772d5eea84f62c35" dependencies = [ "http", "opentelemetry", @@ -4171,9 +4171,9 @@ dependencies = [ [[package]] name = "opentelemetry-prometheus-text-exporter" -version = "0.2.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897906366b17a89bec845f6051e0c3474049402a09a0711eea180941293bd013" +checksum = "b4fe57ea90b12f643a366aa7c4fa5cfb54bd1cf252f55368337e40534b278a68" dependencies = [ "opentelemetry", "opentelemetry_sdk", @@ -4182,22 +4182,20 @@ dependencies = [ [[package]] name = "opentelemetry-proto" -version = "0.31.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7175df06de5eaee9909d4805a3d07e28bb752c34cab57fa9cff549da596b30f" +checksum = "56d658ba1faf63f7b9c492cfbe6e0ec365440a16132d3270c1065f7b33f1b638" dependencies = [ "opentelemetry", "opentelemetry_sdk", "prost", - "tonic", - "tonic-prost", ] [[package]] name = "opentelemetry-resource-detectors" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e82845106cf72d47c141cee7f0d95e0650d8f28c6222a1f1ae727a8883899c19" +checksum = "96c8b28af3391a756b248f470f59b35041dd3ac9b9633d2df40757df709314f1" dependencies = [ "opentelemetry", "opentelemetry-semantic-conventions", @@ -4206,15 +4204,15 @@ dependencies = [ [[package]] name = "opentelemetry-semantic-conventions" -version = "0.31.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e62e29dfe041afb8ed2a6c9737ab57db4907285d999ef8ad3a59092a36bdc846" +checksum = "6ca2f98a0437b427b4b08f19f1caa3c44db885a202bc12cfea13d6c702243d68" [[package]] name = "opentelemetry-stdout" -version = "0.31.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc8887887e169414f637b18751487cce4e095be787d23fad13c454e2fb1b3811" +checksum = "a1b1c6a247d79091f0062a5f4bd058589525cf987a8d4c169440d9c1be72f0ad" dependencies = [ "chrono", "opentelemetry", @@ -4223,15 +4221,16 @@ dependencies = [ [[package]] name = "opentelemetry_sdk" -version = "0.31.0" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14ae4f5991976fd48df6d843de219ca6d31b01daaab2dad5af2badeded372bd" +checksum = "9b59f80e1ac4d5ff7a2db8fb6c80badb7f0f3f858211fba08dd9aaec750894f9" dependencies = [ "futures-channel", "futures-executor", "futures-util", "opentelemetry", "percent-encoding", + "portable-atomic", "rand 0.9.4", "thiserror 2.0.17", "tokio", @@ -4940,9 +4939,9 @@ checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" [[package]] name = "reqwest" -version = "0.12.28" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" +checksum = "219c5811de6525e5416c7d5d53bb656d3afdbc6c5af816e0802bcfa42dbdc1c3" dependencies = [ "base64", "bytes", @@ -4964,6 +4963,7 @@ dependencies = [ "pin-project-lite", "rustls", "rustls-pki-types", + "rustls-platform-verifier", "serde", "serde_json", "serde_urlencoded", @@ -5130,6 +5130,7 @@ dependencies = [ "aws-lc-rs", "log", "once_cell", + "ring", "rustls-pki-types", "rustls-webpki", "subtle", @@ -5390,13 +5391,14 @@ checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" [[package]] name = "sentry" -version = "0.46.2" +version = "0.48.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d92d893ba7469d361a6958522fa440e4e2bc8bf4c5803cd1bf40b9af63f8f9a8" +checksum = "931a20b0da02350676e3d6d3c9028d58eaa448cf42a866712eec5845a505421e" dependencies = [ "cfg_aliases", "httpdate", "reqwest", + "rustls", "sentry-backtrace", "sentry-contexts", "sentry-core", @@ -5404,13 +5406,14 @@ dependencies = [ "sentry-tower", "sentry-tracing", "tokio", + "ureq", ] [[package]] name = "sentry-backtrace" -version = "0.46.2" +version = "0.48.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f8784d0a27b5cd4b5f75769ffc84f0b7580e3c35e1af9cd83cb90b612d769cc" +checksum = "911ee36abf5b7fa335fccd5f54361ba9c16baea5f0c3bb361a687b6c195c21cf" dependencies = [ "backtrace", "regex", @@ -5419,9 +5422,9 @@ dependencies = [ [[package]] name = "sentry-contexts" -version = "0.46.2" +version = "0.48.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e5eb42f4cd4f9fdfec9e3b07b25a4c9769df83d218a7e846658984d5948ad3e" +checksum = "9b9d7d469e9e22741c17ca23fb8b42d79861590eb7cf330f3da34fc1e4bc1bc6" dependencies = [ "hostname", "libc", @@ -5433,9 +5436,9 @@ dependencies = [ [[package]] name = "sentry-core" -version = "0.46.2" +version = "0.48.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0b1e7ca40f965db239da279bf278d87b7407469b98835f27f0c8e59ed189b06" +checksum = "545dc562b6758d646ac19e1407f4ebc26d452111386743e03323464bc48bb2e0" dependencies = [ "rand 0.9.4", "sentry-types", @@ -5446,9 +5449,9 @@ dependencies = [ [[package]] name = "sentry-panic" -version = "0.46.2" +version = "0.48.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8906f8be87aea5ac7ef937323fb655d66607427f61007b99b7cb3504dc5a156c" +checksum = "772d9de150c8ca910c835353c85f434457348fdd21208f9b3da3574202b1dc5d" dependencies = [ "sentry-backtrace", "sentry-core", @@ -5456,9 +5459,9 @@ dependencies = [ [[package]] name = "sentry-tower" -version = "0.46.2" +version = "0.48.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56aebe376310840b49dad4cca55c7b32d9abdc14946cd071d4158ecb149b63a4" +checksum = "2abea154597936d5df2d39fbe8aac16d584de6b3572c70c39558764d9d2efe15" dependencies = [ "axum", "http", @@ -5471,9 +5474,9 @@ dependencies = [ [[package]] name = "sentry-tracing" -version = "0.46.2" +version = "0.48.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b07eefe04486316c57aba08ab53dd44753c25102d1d3fe05775cc93a13262d9" +checksum = "c51ec9620a4d398dcdf7ee90effbf8d8691cfa24e91978bfa8565cac039d4980" dependencies = [ "bitflags", "sentry-backtrace", @@ -5484,9 +5487,9 @@ dependencies = [ [[package]] name = "sentry-types" -version = "0.46.2" +version = "0.48.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567711f01f86a842057e1fc17779eba33a336004227e1a1e7e6cc2599e22e259" +checksum = "041359745a44dd2e14fe21b7510fe7ca8b5beffce6636a0b52e5bc7d5f736887" dependencies = [ "debugid", "hex", @@ -6451,7 +6454,6 @@ version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb7613188ce9f7df5bfe185db26c5814347d110db17920415cf2fbcad85e7203" dependencies = [ - "async-trait", "base64", "bytes", "http", @@ -6468,17 +6470,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "tonic-prost" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66bd50ad6ce1252d87ef024b3d64fe4c3cf54a86fb9ef4c631fdd0ded7aeaa67" -dependencies = [ - "bytes", - "prost", - "tonic", -] - [[package]] name = "tower" version = "0.5.2" @@ -6606,9 +6597,9 @@ dependencies = [ [[package]] name = "tracing-opentelemetry" -version = "0.32.1" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ac28f2d093c6c477eaa76b23525478f38de514fa9aeb1285738d4b97a9552fc" +checksum = "adbc64cba7137545b8044cb1fe9814f7aacf3c6b5f9b45be8bb5db538befdb26" dependencies = [ "js-sys", "opentelemetry", @@ -6763,6 +6754,34 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" +[[package]] +name = "ureq" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dea7109cdcd5864d4eeb1b58a1648dc9bf520360d7af16ec26d0a9354bafcfc0" +dependencies = [ + "base64", + "log", + "percent-encoding", + "rustls", + "rustls-pki-types", + "ureq-proto", + "utf8-zero", + "webpki-roots 1.0.2", +] + +[[package]] +name = "ureq-proto" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e994ba84b0bd1b1b0cf92878b7ef898a5c1760108fe7b6010327e274917a808c" +dependencies = [ + "base64", + "http", + "httparse", + "log", +] + [[package]] name = "url" version = "2.5.7" @@ -6787,6 +6806,12 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" +[[package]] +name = "utf8-zero" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8c0a043c9540bae7c578c88f91dda8bd82e59ae27c21baca69c8b191aaf5a6e" + [[package]] name = "utf8_iter" version = "1.0.4" diff --git a/Cargo.toml b/Cargo.toml index a6077739c..f7605a70b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -404,40 +404,40 @@ version = "0.2.0" # OpenTelemetry [workspace.dependencies.opentelemetry] -version = "0.31.0" +version = "0.32.0" features = ["trace", "metrics"] [workspace.dependencies.opentelemetry-http] -version = "0.31.0" +version = "0.32.0" features = ["reqwest"] [workspace.dependencies.opentelemetry-instrumentation-process] -version = "0.1.2" +version = "0.2.0" [workspace.dependencies.opentelemetry-instrumentation-tokio] -version = "0.1.2" +version = "0.2.0" [workspace.dependencies.opentelemetry-jaeger-propagator] -version = "0.31.0" +version = "0.32.0" [workspace.dependencies.opentelemetry-otlp] -version = "0.31.1" +version = "0.32.0" default-features = false features = ["trace", "metrics", "http-proto", "tls-provider-agnostic"] [workspace.dependencies.opentelemetry-prometheus-text-exporter] -version = "0.2.1" +version = "0.3.0" [workspace.dependencies.opentelemetry-resource-detectors] -version = "0.10.0" +version = "0.11.0" [workspace.dependencies.opentelemetry-semantic-conventions] -version = "0.31.0" +version = "0.32.0" features = ["semconv_experimental"] [workspace.dependencies.opentelemetry-stdout] -version = "0.31.0" +version = "0.32.0" features = ["trace", "metrics"] [workspace.dependencies.opentelemetry_sdk] -version = "0.31.0" +version = "0.32.1" features = [ "experimental_trace_batch_span_processor_with_async_runtime", "experimental_metrics_periodicreader_with_async_runtime", "rt-tokio", ] [workspace.dependencies.tracing-opentelemetry] -version = "0.32.1" +version = "0.33.0" default-features = false # P256 elliptic curve @@ -508,13 +508,14 @@ version = "1.12.2" # High-level HTTP client [workspace.dependencies.reqwest] -version = "0.12.24" +version = "0.13.4" default-features = false features = [ "http2", - "rustls-tls-manual-roots-no-provider", + "rustls-no-provider", "charset", "json", + "form", "socks", "system-proxy", ] @@ -576,18 +577,18 @@ features = [ # Sentry error tracking [workspace.dependencies.sentry] -version = "0.46.2" +version = "0.48.2" default-features = false -features = ["backtrace", "contexts", "panic", "tower", "reqwest"] +features = ["backtrace", "contexts", "panic", "tower", "reqwest", "rustls-no-provider"] # Sentry tower layer [workspace.dependencies.sentry-tower] -version = "0.46.0" +version = "0.48.2" features = ["http", "axum-matched-path"] # Sentry tracing integration [workspace.dependencies.sentry-tracing] -version = "0.46.0" +version = "0.48.2" # Serialization and deserialization [workspace.dependencies.serde] diff --git a/crates/cli/src/telemetry.rs b/crates/cli/src/telemetry.rs index 283b9018d..12add6ec4 100644 --- a/crates/cli/src/telemetry.rs +++ b/crates/cli/src/telemetry.rs @@ -83,6 +83,12 @@ fn match_propagator(propagator: Propagator) -> Box Box::new(TraceContextPropagator::new()), P::Baggage => Box::new(BaggagePropagator::new()), + // opentelemetry-jaeger-propagator is deprecated upstream but still + // published; we keep supporting the Jaeger format until it's removed. + #[expect( + deprecated, + reason = "the Jaeger propagator is deprecated upstream but we still expose it as an option" + )] P::Jaeger => Box::new(opentelemetry_jaeger_propagator::Propagator::new()), } } diff --git a/crates/context/src/fmt.rs b/crates/context/src/fmt.rs index 5d52625fc..0b6edb130 100644 --- a/crates/context/src/fmt.rs +++ b/crates/context/src/fmt.rs @@ -129,7 +129,7 @@ where // If we have a OTEL span, we can add the trace ID to the end of the log line if let Some(span) = ctx.lookup_current() && let Some(trace_id) = tracing::dispatcher::get_default(|dispatch| { - let otel_cx = get_otel_context(&mut span.extensions_mut(), dispatch)?; + let otel_cx = get_otel_context(&span.id(), dispatch)?; let trace_id = otel_cx.span().span_context().trace_id(); Some(trace_id) })