You've already forked authentication-service
mirror of
https://github.com/matrix-org/matrix-authentication-service.git
synced 2025-07-07 22:41:18 +03:00
OpenTelemetry upgrade
This commit is contained in:
142
Cargo.lock
generated
142
Cargo.lock
generated
@ -3039,12 +3039,13 @@ dependencies = [
|
|||||||
"mas-templates",
|
"mas-templates",
|
||||||
"mas-tower",
|
"mas-tower",
|
||||||
"oauth2-types",
|
"oauth2-types",
|
||||||
"opentelemetry 0.20.0",
|
"opentelemetry",
|
||||||
"opentelemetry-http 0.9.0",
|
"opentelemetry-http",
|
||||||
"opentelemetry-jaeger",
|
"opentelemetry-jaeger",
|
||||||
"opentelemetry-otlp",
|
"opentelemetry-otlp",
|
||||||
"opentelemetry-prometheus",
|
"opentelemetry-prometheus",
|
||||||
"opentelemetry-semantic-conventions 0.12.0",
|
"opentelemetry-semantic-conventions",
|
||||||
|
"opentelemetry-stdout",
|
||||||
"opentelemetry-zipkin",
|
"opentelemetry-zipkin",
|
||||||
"prometheus",
|
"prometheus",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
@ -3192,7 +3193,8 @@ dependencies = [
|
|||||||
"mas-templates",
|
"mas-templates",
|
||||||
"mime",
|
"mime",
|
||||||
"oauth2-types",
|
"oauth2-types",
|
||||||
"opentelemetry 0.20.0",
|
"opentelemetry",
|
||||||
|
"opentelemetry-semantic-conventions",
|
||||||
"pbkdf2",
|
"pbkdf2",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"rand_chacha 0.3.1",
|
"rand_chacha 0.3.1",
|
||||||
@ -3231,7 +3233,7 @@ dependencies = [
|
|||||||
"hyper-rustls",
|
"hyper-rustls",
|
||||||
"mas-tower",
|
"mas-tower",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"opentelemetry 0.20.0",
|
"opentelemetry",
|
||||||
"rustls",
|
"rustls",
|
||||||
"rustls-native-certs",
|
"rustls-native-certs",
|
||||||
"serde",
|
"serde",
|
||||||
@ -3472,7 +3474,7 @@ dependencies = [
|
|||||||
"mas-iana",
|
"mas-iana",
|
||||||
"mas-jose",
|
"mas-jose",
|
||||||
"oauth2-types",
|
"oauth2-types",
|
||||||
"opentelemetry 0.20.0",
|
"opentelemetry",
|
||||||
"rand_core 0.6.4",
|
"rand_core 0.6.4",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
@ -3527,7 +3529,7 @@ dependencies = [
|
|||||||
"mas-storage",
|
"mas-storage",
|
||||||
"mas-storage-pg",
|
"mas-storage-pg",
|
||||||
"mas-tower",
|
"mas-tower",
|
||||||
"opentelemetry 0.20.0",
|
"opentelemetry",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"rand_chacha 0.3.1",
|
"rand_chacha 0.3.1",
|
||||||
"serde",
|
"serde",
|
||||||
@ -3572,8 +3574,9 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"aws-smithy-http",
|
"aws-smithy-http",
|
||||||
"http",
|
"http",
|
||||||
"opentelemetry 0.20.0",
|
"opentelemetry",
|
||||||
"opentelemetry-http 0.9.0",
|
"opentelemetry-http",
|
||||||
|
"opentelemetry-semantic-conventions",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tower",
|
"tower",
|
||||||
@ -3876,36 +3879,14 @@ version = "0.1.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
|
checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "opentelemetry"
|
|
||||||
version = "0.19.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5f4b8347cc26099d3aeee044065ecc3ae11469796b4d65d065a23a584ed92a6f"
|
|
||||||
dependencies = [
|
|
||||||
"opentelemetry_api 0.19.0",
|
|
||||||
"opentelemetry_sdk 0.19.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "opentelemetry"
|
name = "opentelemetry"
|
||||||
version = "0.20.0"
|
version = "0.20.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9591d937bc0e6d2feb6f71a559540ab300ea49955229c347a517a28d27784c54"
|
checksum = "9591d937bc0e6d2feb6f71a559540ab300ea49955229c347a517a28d27784c54"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"opentelemetry_api 0.20.0",
|
"opentelemetry_api",
|
||||||
"opentelemetry_sdk 0.20.0",
|
"opentelemetry_sdk",
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "opentelemetry-http"
|
|
||||||
version = "0.8.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a819b71d6530c4297b49b3cae2939ab3a8cc1b9f382826a1bc29dd0ca3864906"
|
|
||||||
dependencies = [
|
|
||||||
"async-trait",
|
|
||||||
"bytes 1.4.0",
|
|
||||||
"http",
|
|
||||||
"opentelemetry_api 0.19.0",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -3918,7 +3899,7 @@ dependencies = [
|
|||||||
"bytes 1.4.0",
|
"bytes 1.4.0",
|
||||||
"http",
|
"http",
|
||||||
"hyper",
|
"hyper",
|
||||||
"opentelemetry_api 0.20.0",
|
"opentelemetry_api",
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -3932,9 +3913,9 @@ dependencies = [
|
|||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"http",
|
"http",
|
||||||
"opentelemetry 0.20.0",
|
"opentelemetry",
|
||||||
"opentelemetry-http 0.9.0",
|
"opentelemetry-http",
|
||||||
"opentelemetry-semantic-conventions 0.12.0",
|
"opentelemetry-semantic-conventions",
|
||||||
"thrift",
|
"thrift",
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
@ -3949,9 +3930,9 @@ dependencies = [
|
|||||||
"futures-core",
|
"futures-core",
|
||||||
"http",
|
"http",
|
||||||
"opentelemetry-proto",
|
"opentelemetry-proto",
|
||||||
"opentelemetry-semantic-conventions 0.12.0",
|
"opentelemetry-semantic-conventions",
|
||||||
"opentelemetry_api 0.20.0",
|
"opentelemetry_api",
|
||||||
"opentelemetry_sdk 0.20.0",
|
"opentelemetry_sdk",
|
||||||
"prost",
|
"prost",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
@ -3965,8 +3946,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "c7d81bc254e2d572120363a2b16cdb0d715d301b5789be0cfc26ad87e4e10e53"
|
checksum = "c7d81bc254e2d572120363a2b16cdb0d715d301b5789be0cfc26ad87e4e10e53"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"opentelemetry_api 0.20.0",
|
"opentelemetry_api",
|
||||||
"opentelemetry_sdk 0.20.0",
|
"opentelemetry_sdk",
|
||||||
"prometheus",
|
"prometheus",
|
||||||
"protobuf",
|
"protobuf",
|
||||||
]
|
]
|
||||||
@ -3977,64 +3958,55 @@ version = "0.3.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b1e3f814aa9f8c905d0ee4bde026afd3b2577a97c10e1699912e3e44f0c4cbeb"
|
checksum = "b1e3f814aa9f8c905d0ee4bde026afd3b2577a97c10e1699912e3e44f0c4cbeb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"opentelemetry_api 0.20.0",
|
"opentelemetry_api",
|
||||||
"opentelemetry_sdk 0.20.0",
|
"opentelemetry_sdk",
|
||||||
"prost",
|
"prost",
|
||||||
"tonic",
|
"tonic",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "opentelemetry-semantic-conventions"
|
|
||||||
version = "0.11.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "24e33428e6bf08c6f7fcea4ddb8e358fab0fe48ab877a87c70c6ebe20f673ce5"
|
|
||||||
dependencies = [
|
|
||||||
"opentelemetry 0.19.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "opentelemetry-semantic-conventions"
|
name = "opentelemetry-semantic-conventions"
|
||||||
version = "0.12.0"
|
version = "0.12.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "73c9f9340ad135068800e7f1b24e9e09ed9e7143f5bf8518ded3d3ec69789269"
|
checksum = "73c9f9340ad135068800e7f1b24e9e09ed9e7143f5bf8518ded3d3ec69789269"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"opentelemetry 0.20.0",
|
"opentelemetry",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "opentelemetry-stdout"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8bd550321bc0f9d3f6dcbfe5c75262789de5b3e2776da2cbcfd2392aa05db0c6"
|
||||||
|
dependencies = [
|
||||||
|
"async-trait",
|
||||||
|
"futures-util",
|
||||||
|
"opentelemetry_api",
|
||||||
|
"opentelemetry_sdk",
|
||||||
|
"ordered-float 3.7.0",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "opentelemetry-zipkin"
|
name = "opentelemetry-zipkin"
|
||||||
version = "0.17.0"
|
version = "0.18.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e1fd48caee5e1db71454c95be32d1daeb6fae265321ff8f51b1efc8a50b0be80"
|
checksum = "eb966f01235207a6933c0aec98374fe9782df1c1d2b3d1db35c458451d138143"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"http",
|
"http",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"opentelemetry 0.19.0",
|
"opentelemetry",
|
||||||
"opentelemetry-http 0.8.0",
|
"opentelemetry-http",
|
||||||
"opentelemetry-semantic-conventions 0.11.0",
|
"opentelemetry-semantic-conventions",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"typed-builder",
|
"typed-builder",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "opentelemetry_api"
|
|
||||||
version = "0.19.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ed41783a5bf567688eb38372f2b7a8530f5a607a4b49d38dd7573236c23ca7e2"
|
|
||||||
dependencies = [
|
|
||||||
"futures-channel",
|
|
||||||
"futures-util",
|
|
||||||
"indexmap 1.9.3",
|
|
||||||
"once_cell",
|
|
||||||
"pin-project-lite",
|
|
||||||
"thiserror",
|
|
||||||
"urlencoding",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "opentelemetry_api"
|
name = "opentelemetry_api"
|
||||||
version = "0.20.0"
|
version = "0.20.0"
|
||||||
@ -4051,24 +4023,6 @@ dependencies = [
|
|||||||
"urlencoding",
|
"urlencoding",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "opentelemetry_sdk"
|
|
||||||
version = "0.19.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8b3a2a91fdbfdd4d212c0dcc2ab540de2c2bcbbd90be17de7a7daf8822d010c1"
|
|
||||||
dependencies = [
|
|
||||||
"async-trait",
|
|
||||||
"crossbeam-channel",
|
|
||||||
"futures-channel",
|
|
||||||
"futures-executor",
|
|
||||||
"futures-util",
|
|
||||||
"once_cell",
|
|
||||||
"opentelemetry_api 0.19.0",
|
|
||||||
"percent-encoding",
|
|
||||||
"rand 0.8.5",
|
|
||||||
"thiserror",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "opentelemetry_sdk"
|
name = "opentelemetry_sdk"
|
||||||
version = "0.20.0"
|
version = "0.20.0"
|
||||||
@ -4081,7 +4035,7 @@ dependencies = [
|
|||||||
"futures-executor",
|
"futures-executor",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"opentelemetry_api 0.20.0",
|
"opentelemetry_api",
|
||||||
"ordered-float 3.7.0",
|
"ordered-float 3.7.0",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
@ -6353,7 +6307,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "fc09e402904a5261e42cf27aea09ccb7d5318c6717a9eec3d8e2e65c56b18f19"
|
checksum = "fc09e402904a5261e42cf27aea09ccb7d5318c6717a9eec3d8e2e65c56b18f19"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"opentelemetry 0.20.0",
|
"opentelemetry",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-core",
|
"tracing-core",
|
||||||
"tracing-log",
|
"tracing-log",
|
||||||
|
@ -34,12 +34,13 @@ tracing-appender = "0.2.2"
|
|||||||
tracing-subscriber = { version = "0.3.17", features = ["env-filter"] }
|
tracing-subscriber = { version = "0.3.17", features = ["env-filter"] }
|
||||||
tracing-opentelemetry = "0.20.0"
|
tracing-opentelemetry = "0.20.0"
|
||||||
opentelemetry = { version = "0.20.0", features = ["trace", "metrics", "rt-tokio"] }
|
opentelemetry = { version = "0.20.0", features = ["trace", "metrics", "rt-tokio"] }
|
||||||
opentelemetry-semantic-conventions = "0.12.0"
|
opentelemetry-http = { version = "0.9.0", features = ["tokio", "hyper"] }
|
||||||
opentelemetry-jaeger = { version = "0.19.0", features = ["rt-tokio", "collector_client"] }
|
opentelemetry-jaeger = { version = "0.19.0", features = ["rt-tokio", "collector_client"] }
|
||||||
opentelemetry-otlp = { version = "0.13.0", features = ["trace", "metrics"] }
|
opentelemetry-otlp = { version = "0.13.0", features = ["trace", "metrics"] }
|
||||||
opentelemetry-zipkin = { version = "0.17.0", features = ["opentelemetry-http"], default-features = false }
|
opentelemetry-prometheus = "0.13.0"
|
||||||
opentelemetry-http = { version = "0.9.0", features = ["tokio", "hyper"] }
|
opentelemetry-semantic-conventions = "0.12.0"
|
||||||
opentelemetry-prometheus = { version = "0.13.0" }
|
opentelemetry-stdout = { version = "0.1.0", features = ["trace", "metrics"] }
|
||||||
|
opentelemetry-zipkin = { version = "0.18.0", default-features = false }
|
||||||
prometheus = "0.13.3"
|
prometheus = "0.13.3"
|
||||||
sentry = { version = "0.31.5", default-features = false, features = ["backtrace", "contexts", "panic", "tower"] }
|
sentry = { version = "0.31.5", default-features = false, features = ["backtrace", "contexts", "panic", "tower"] }
|
||||||
sentry-tracing = "0.31.5"
|
sentry-tracing = "0.31.5"
|
||||||
|
@ -100,7 +100,7 @@ async fn try_main() -> anyhow::Result<()> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Setup OpenTelemetry tracing and metrics
|
// Setup OpenTelemetry tracing and metrics
|
||||||
let (tracer, _meter) = telemetry::setup(&telemetry_config)
|
let tracer = telemetry::setup(&telemetry_config)
|
||||||
.await
|
.await
|
||||||
.context("failed to setup OpenTelemetry")?;
|
.context("failed to setup OpenTelemetry")?;
|
||||||
|
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
borrow::Cow,
|
|
||||||
future::ready,
|
future::ready,
|
||||||
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, TcpListener, ToSocketAddrs},
|
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, TcpListener, ToSocketAddrs},
|
||||||
os::unix::net::UnixListener,
|
os::unix::net::UnixListener,
|
||||||
@ -27,7 +26,7 @@ use axum::{
|
|||||||
Extension, Router,
|
Extension, Router,
|
||||||
};
|
};
|
||||||
use hyper::{
|
use hyper::{
|
||||||
header::{HeaderValue, CACHE_CONTROL},
|
header::{HeaderValue, CACHE_CONTROL, USER_AGENT},
|
||||||
Method, Request, Response, StatusCode, Version,
|
Method, Request, Response, StatusCode, Version,
|
||||||
};
|
};
|
||||||
use listenfd::ListenFd;
|
use listenfd::ListenFd;
|
||||||
@ -40,10 +39,11 @@ use mas_tower::{
|
|||||||
make_span_fn, metrics_attributes_fn, DurationRecorderLayer, InFlightCounterLayer, TraceLayer,
|
make_span_fn, metrics_attributes_fn, DurationRecorderLayer, InFlightCounterLayer, TraceLayer,
|
||||||
KV,
|
KV,
|
||||||
};
|
};
|
||||||
use opentelemetry::{Key, KeyValue};
|
use opentelemetry::{trace::TraceContextExt, Key, KeyValue};
|
||||||
use opentelemetry_http::HeaderExtractor;
|
use opentelemetry_http::HeaderExtractor;
|
||||||
use opentelemetry_semantic_conventions::trace::{
|
use opentelemetry_semantic_conventions::trace::{
|
||||||
HTTP_METHOD, HTTP_ROUTE, HTTP_SCHEME, HTTP_STATUS_CODE,
|
HTTP_REQUEST_METHOD, HTTP_RESPONSE_STATUS_CODE, HTTP_ROUTE, NETWORK_PROTOCOL_NAME,
|
||||||
|
NETWORK_PROTOCOL_VERSION, URL_SCHEME,
|
||||||
};
|
};
|
||||||
use rustls::ServerConfig;
|
use rustls::ServerConfig;
|
||||||
use sentry_tower::{NewSentryLayer, SentryHttpLayer};
|
use sentry_tower::{NewSentryLayer, SentryHttpLayer};
|
||||||
@ -52,35 +52,33 @@ use tower_http::{services::ServeDir, set_header::SetResponseHeaderLayer};
|
|||||||
use tracing::{warn, Span};
|
use tracing::{warn, Span};
|
||||||
use tracing_opentelemetry::OpenTelemetrySpanExt;
|
use tracing_opentelemetry::OpenTelemetrySpanExt;
|
||||||
|
|
||||||
const NET_PROTOCOL_NAME: Key = Key::from_static_str("net.protocol.name");
|
|
||||||
const NET_PROTOCOL_VERSION: Key = Key::from_static_str("net.protocol.version");
|
|
||||||
const MAS_LISTENER_NAME: Key = Key::from_static_str("mas.listener.name");
|
const MAS_LISTENER_NAME: Key = Key::from_static_str("mas.listener.name");
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn otel_http_method<B>(request: &Request<B>) -> Cow<'static, str> {
|
fn otel_http_method<B>(request: &Request<B>) -> &'static str {
|
||||||
match request.method() {
|
match request.method() {
|
||||||
&Method::OPTIONS => "OPTIONS".into(),
|
&Method::OPTIONS => "OPTIONS",
|
||||||
&Method::GET => "GET".into(),
|
&Method::GET => "GET",
|
||||||
&Method::POST => "POST".into(),
|
&Method::POST => "POST",
|
||||||
&Method::PUT => "PUT".into(),
|
&Method::PUT => "PUT",
|
||||||
&Method::DELETE => "DELETE".into(),
|
&Method::DELETE => "DELETE",
|
||||||
&Method::HEAD => "HEAD".into(),
|
&Method::HEAD => "HEAD",
|
||||||
&Method::TRACE => "TRACE".into(),
|
&Method::TRACE => "TRACE",
|
||||||
&Method::CONNECT => "CONNECT".into(),
|
&Method::CONNECT => "CONNECT",
|
||||||
&Method::PATCH => "PATCH".into(),
|
&Method::PATCH => "PATCH",
|
||||||
other => other.to_string().into(),
|
_other => "_OTHER",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn otel_net_protocol_version<B>(request: &Request<B>) -> Cow<'static, str> {
|
fn otel_net_protocol_version<B>(request: &Request<B>) -> &'static str {
|
||||||
match request.version() {
|
match request.version() {
|
||||||
Version::HTTP_09 => "0.9".into(),
|
Version::HTTP_09 => "0.9",
|
||||||
Version::HTTP_10 => "1.0".into(),
|
Version::HTTP_10 => "1.0",
|
||||||
Version::HTTP_11 => "1.1".into(),
|
Version::HTTP_11 => "1.1",
|
||||||
Version::HTTP_2 => "2.0".into(),
|
Version::HTTP_2 => "2.0",
|
||||||
Version::HTTP_3 => "3.0".into(),
|
Version::HTTP_3 => "3.0",
|
||||||
other => format!("{other:?}").into(),
|
_other => "_OTHER",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,11 +89,7 @@ fn otel_http_route<B>(request: &Request<B>) -> Option<&str> {
|
|||||||
.map(MatchedPath::as_str)
|
.map(MatchedPath::as_str)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn otel_http_target<B>(request: &Request<B>) -> &str {
|
fn otel_url_scheme<B>(request: &Request<B>) -> &'static str {
|
||||||
request.uri().path_and_query().map_or("", |p| p.as_str())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn otel_http_scheme<B>(request: &Request<B>) -> &'static str {
|
|
||||||
// XXX: maybe we should panic if the connection info was not injected in the
|
// XXX: maybe we should panic if the connection info was not injected in the
|
||||||
// request extensions
|
// request extensions
|
||||||
request
|
request
|
||||||
@ -117,7 +111,7 @@ fn make_http_span<B>(req: &Request<B>) -> Span {
|
|||||||
let span_name = if let Some(route) = route.as_ref() {
|
let span_name = if let Some(route) = route.as_ref() {
|
||||||
format!("{method} {route}")
|
format!("{method} {route}")
|
||||||
} else {
|
} else {
|
||||||
format!("{method}")
|
method.to_owned()
|
||||||
};
|
};
|
||||||
|
|
||||||
let span = tracing::info_span!(
|
let span = tracing::info_span!(
|
||||||
@ -125,42 +119,60 @@ fn make_http_span<B>(req: &Request<B>) -> Span {
|
|||||||
"otel.kind" = "server",
|
"otel.kind" = "server",
|
||||||
"otel.name" = span_name,
|
"otel.name" = span_name,
|
||||||
"otel.status_code" = tracing::field::Empty,
|
"otel.status_code" = tracing::field::Empty,
|
||||||
"net.protocol.name" = "http",
|
"network.protocol.name" = "http",
|
||||||
"net.protocol.version" = otel_net_protocol_version(req).as_ref(),
|
"network.protocol.version" = otel_net_protocol_version(req),
|
||||||
"http.scheme" = otel_http_scheme(req),
|
"http.method" = method,
|
||||||
"http.method" = method.as_ref(),
|
|
||||||
"http.route" = tracing::field::Empty,
|
"http.route" = tracing::field::Empty,
|
||||||
"http.target" = otel_http_target(req),
|
"http.response.status_code" = tracing::field::Empty,
|
||||||
"http.status_code" = tracing::field::Empty,
|
"url.path" = req.uri().path(),
|
||||||
|
"url.query" = tracing::field::Empty,
|
||||||
|
"url.scheme" = otel_url_scheme(req),
|
||||||
|
"user_agent.original" = tracing::field::Empty,
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(route) = route.as_ref() {
|
if let Some(route) = route.as_ref() {
|
||||||
span.record("http.route", route);
|
span.record("http.route", route);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(query) = req.uri().query() {
|
||||||
|
span.record("url.query", query);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(user_agent) = req.headers().get(USER_AGENT) {
|
||||||
|
span.record(
|
||||||
|
"user_agent.original",
|
||||||
|
user_agent.to_str().unwrap_or("INVALID"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Extract the parent span context from the request headers
|
// Extract the parent span context from the request headers
|
||||||
let parent_context = opentelemetry::global::get_text_map_propagator(|propagator| {
|
let parent_context = opentelemetry::global::get_text_map_propagator(|propagator| {
|
||||||
let extractor = HeaderExtractor(req.headers());
|
let extractor = HeaderExtractor(req.headers());
|
||||||
let context = opentelemetry::Context::new();
|
let context = opentelemetry::Context::new();
|
||||||
propagator.extract_with_context(&context, &extractor)
|
propagator.extract_with_context(&context, &extractor)
|
||||||
});
|
});
|
||||||
span.set_parent(parent_context);
|
|
||||||
|
if parent_context.span().span_context().is_remote() {
|
||||||
|
// For now, set_parent is broken, so in the meantime we're using add_link
|
||||||
|
// instead
|
||||||
|
span.add_link(parent_context.span().span_context().clone());
|
||||||
|
}
|
||||||
|
|
||||||
span
|
span
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_http_request_labels<B>(request: &Request<B>) -> Vec<KeyValue> {
|
fn on_http_request_labels<B>(request: &Request<B>) -> Vec<KeyValue> {
|
||||||
vec![
|
vec![
|
||||||
NET_PROTOCOL_NAME.string("http"),
|
NETWORK_PROTOCOL_NAME.string("http"),
|
||||||
NET_PROTOCOL_VERSION.string(otel_net_protocol_version(request)),
|
NETWORK_PROTOCOL_VERSION.string(otel_net_protocol_version(request)),
|
||||||
HTTP_METHOD.string(otel_http_method(request)),
|
HTTP_REQUEST_METHOD.string(otel_http_method(request)),
|
||||||
HTTP_SCHEME.string(otel_http_scheme(request).as_ref()),
|
|
||||||
HTTP_ROUTE.string(otel_http_route(request).unwrap_or("FALLBACK").to_owned()),
|
HTTP_ROUTE.string(otel_http_route(request).unwrap_or("FALLBACK").to_owned()),
|
||||||
|
URL_SCHEME.string(otel_url_scheme(request).as_ref()),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_http_response_labels<B>(res: &Response<B>) -> Vec<KeyValue> {
|
fn on_http_response_labels<B>(res: &Response<B>) -> Vec<KeyValue> {
|
||||||
vec![HTTP_STATUS_CODE.i64(res.status().as_u16().into())]
|
vec![HTTP_RESPONSE_STATUS_CODE.i64(res.status().as_u16().into())]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_router<B>(
|
pub fn build_router<B>(
|
||||||
@ -259,7 +271,7 @@ where
|
|||||||
))
|
))
|
||||||
.on_response_fn(|span: &Span, response: &Response<_>| {
|
.on_response_fn(|span: &Span, response: &Response<_>| {
|
||||||
let status_code = response.status().as_u16();
|
let status_code = response.status().as_u16();
|
||||||
span.record("http.status_code", status_code);
|
span.record("http.response.status_code", status_code);
|
||||||
span.record("otel.status_code", "OK");
|
span.record("otel.status_code", "OK");
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
@ -25,26 +25,29 @@ use opentelemetry::{
|
|||||||
propagation::TextMapPropagator,
|
propagation::TextMapPropagator,
|
||||||
sdk::{
|
sdk::{
|
||||||
self,
|
self,
|
||||||
metrics::controllers::BasicController,
|
metrics::{
|
||||||
|
reader::{DefaultAggregationSelector, DefaultTemporalitySelector},
|
||||||
|
MeterProvider, PeriodicReader,
|
||||||
|
},
|
||||||
propagation::{BaggagePropagator, TextMapCompositePropagator, TraceContextPropagator},
|
propagation::{BaggagePropagator, TextMapCompositePropagator, TraceContextPropagator},
|
||||||
trace::{Sampler, Tracer},
|
trace::{Sampler, Tracer, TracerProvider},
|
||||||
Resource,
|
Resource,
|
||||||
},
|
},
|
||||||
Context,
|
trace::TracerProvider as _,
|
||||||
};
|
};
|
||||||
use opentelemetry_jaeger::Propagator as JaegerPropagator;
|
use opentelemetry_jaeger::Propagator as JaegerPropagator;
|
||||||
|
use opentelemetry_otlp::MetricsExporterBuilder;
|
||||||
use opentelemetry_prometheus::PrometheusExporter;
|
use opentelemetry_prometheus::PrometheusExporter;
|
||||||
use opentelemetry_semantic_conventions as semcov;
|
use opentelemetry_semantic_conventions as semcov;
|
||||||
use opentelemetry_zipkin::{B3Encoding, Propagator as ZipkinPropagator};
|
use opentelemetry_zipkin::{B3Encoding, Propagator as ZipkinPropagator};
|
||||||
|
use prometheus::Registry;
|
||||||
use tokio::sync::OnceCell;
|
use tokio::sync::OnceCell;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
static METRICS_BASIC_CONTROLLER: OnceCell<BasicController> = OnceCell::const_new();
|
static METER_PROVIDER: OnceCell<MeterProvider> = OnceCell::const_new();
|
||||||
static PROMETHEUS_EXPORTER: OnceCell<PrometheusExporter> = OnceCell::const_new();
|
static PROMETHEUS_REGISTRY: OnceCell<Registry> = OnceCell::const_new();
|
||||||
|
|
||||||
pub async fn setup(
|
pub async fn setup(config: &TelemetryConfig) -> anyhow::Result<Option<Tracer>> {
|
||||||
config: &TelemetryConfig,
|
|
||||||
) -> anyhow::Result<(Option<Tracer>, Option<BasicController>)> {
|
|
||||||
global::set_error_handler(|e| tracing::error!("{}", e))?;
|
global::set_error_handler(|e| tracing::error!("{}", e))?;
|
||||||
let propagator = propagator(&config.tracing.propagators);
|
let propagator = propagator(&config.tracing.propagators);
|
||||||
|
|
||||||
@ -57,20 +60,16 @@ pub async fn setup(
|
|||||||
.await
|
.await
|
||||||
.context("Failed to configure traces exporter")?;
|
.context("Failed to configure traces exporter")?;
|
||||||
|
|
||||||
let meter = meter(&config.metrics.exporter).context("Failed to configure metrics exporter")?;
|
init_meter(&config.metrics.exporter).context("Failed to configure metrics exporter")?;
|
||||||
if let Some(meter) = meter.as_ref() {
|
|
||||||
METRICS_BASIC_CONTROLLER.set(meter.clone())?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok((tracer, meter))
|
Ok(tracer)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn shutdown() {
|
pub fn shutdown() {
|
||||||
global::shutdown_tracer_provider();
|
global::shutdown_tracer_provider();
|
||||||
|
|
||||||
if let Some(controller) = METRICS_BASIC_CONTROLLER.get() {
|
if let Some(meter_provider) = METER_PROVIDER.get() {
|
||||||
let cx = Context::new();
|
meter_provider.shutdown().unwrap();
|
||||||
controller.stop(&cx).unwrap();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,11 +99,11 @@ async fn http_client() -> anyhow::Result<impl opentelemetry_http::HttpClient + '
|
|||||||
Ok(client)
|
Ok(client)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stdout_tracer() -> Tracer {
|
fn stdout_tracer_provider() -> TracerProvider {
|
||||||
sdk::export::trace::stdout::new_pipeline()
|
let exporter = opentelemetry_stdout::SpanExporter::default();
|
||||||
.with_pretty_print(true)
|
TracerProvider::builder()
|
||||||
.with_trace_config(trace_config())
|
.with_simple_exporter(exporter)
|
||||||
.install_simple()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn otlp_tracer(endpoint: Option<&Url>) -> anyhow::Result<Tracer> {
|
fn otlp_tracer(endpoint: Option<&Url>) -> anyhow::Result<Tracer> {
|
||||||
@ -125,24 +124,24 @@ fn otlp_tracer(endpoint: Option<&Url>) -> anyhow::Result<Tracer> {
|
|||||||
Ok(tracer)
|
Ok(tracer)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn jaeger_agent_tracer(host: &str, port: u16) -> anyhow::Result<Tracer> {
|
fn jaeger_agent_tracer_provider(host: &str, port: u16) -> anyhow::Result<TracerProvider> {
|
||||||
let pipeline = opentelemetry_jaeger::new_agent_pipeline()
|
let pipeline = opentelemetry_jaeger::new_agent_pipeline()
|
||||||
.with_service_name(env!("CARGO_PKG_NAME"))
|
.with_service_name(env!("CARGO_PKG_NAME"))
|
||||||
.with_trace_config(trace_config())
|
.with_trace_config(trace_config())
|
||||||
.with_endpoint((host, port));
|
.with_endpoint((host, port));
|
||||||
|
|
||||||
let tracer = pipeline
|
let tracer_provider = pipeline
|
||||||
.install_batch(opentelemetry::runtime::Tokio)
|
.build_batch(opentelemetry::runtime::Tokio)
|
||||||
.context("Failed to configure Jaeger agent exporter")?;
|
.context("Failed to configure Jaeger agent exporter")?;
|
||||||
|
|
||||||
Ok(tracer)
|
Ok(tracer_provider)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn jaeger_collector_tracer(
|
async fn jaeger_collector_tracer_provider(
|
||||||
endpoint: &str,
|
endpoint: &str,
|
||||||
username: Option<&str>,
|
username: Option<&str>,
|
||||||
password: Option<&str>,
|
password: Option<&str>,
|
||||||
) -> anyhow::Result<Tracer> {
|
) -> anyhow::Result<TracerProvider> {
|
||||||
let http_client = http_client().await?;
|
let http_client = http_client().await?;
|
||||||
let mut pipeline = opentelemetry_jaeger::new_collector_pipeline()
|
let mut pipeline = opentelemetry_jaeger::new_collector_pipeline()
|
||||||
.with_service_name(env!("CARGO_PKG_NAME"))
|
.with_service_name(env!("CARGO_PKG_NAME"))
|
||||||
@ -158,11 +157,11 @@ async fn jaeger_collector_tracer(
|
|||||||
pipeline = pipeline.with_password(password);
|
pipeline = pipeline.with_password(password);
|
||||||
}
|
}
|
||||||
|
|
||||||
let tracer = pipeline
|
let tracer_provider = pipeline
|
||||||
.install_batch(opentelemetry::runtime::Tokio)
|
.build_batch(opentelemetry::runtime::Tokio)
|
||||||
.context("Failed to configure Jaeger collector exporter")?;
|
.context("Failed to configure Jaeger collector exporter")?;
|
||||||
|
|
||||||
Ok(tracer)
|
Ok(tracer_provider)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn zipkin_tracer(collector_endpoint: &Option<Url>) -> anyhow::Result<Tracer> {
|
async fn zipkin_tracer(collector_endpoint: &Option<Url>) -> anyhow::Result<Tracer> {
|
||||||
@ -185,28 +184,43 @@ async fn zipkin_tracer(collector_endpoint: &Option<Url>) -> anyhow::Result<Trace
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn tracer(config: &TracingExporterConfig) -> anyhow::Result<Option<Tracer>> {
|
async fn tracer(config: &TracingExporterConfig) -> anyhow::Result<Option<Tracer>> {
|
||||||
let tracer = match config {
|
let tracer_provider = match config {
|
||||||
TracingExporterConfig::None => return Ok(None),
|
TracingExporterConfig::None => return Ok(None),
|
||||||
TracingExporterConfig::Stdout => stdout_tracer(),
|
TracingExporterConfig::Stdout => stdout_tracer_provider(),
|
||||||
TracingExporterConfig::Otlp { endpoint } => otlp_tracer(endpoint.as_ref())?,
|
TracingExporterConfig::Otlp { endpoint } => {
|
||||||
|
// The OTLP exporter already creates a tracer and installs it
|
||||||
|
return Ok(Some(otlp_tracer(endpoint.as_ref())?));
|
||||||
|
}
|
||||||
TracingExporterConfig::Jaeger(JaegerExporterProtocolConfig::UdpThriftCompact {
|
TracingExporterConfig::Jaeger(JaegerExporterProtocolConfig::UdpThriftCompact {
|
||||||
agent_host,
|
agent_host,
|
||||||
agent_port,
|
agent_port,
|
||||||
}) => jaeger_agent_tracer(agent_host, *agent_port)?,
|
}) => jaeger_agent_tracer_provider(agent_host, *agent_port)?,
|
||||||
TracingExporterConfig::Jaeger(JaegerExporterProtocolConfig::HttpThriftBinary {
|
TracingExporterConfig::Jaeger(JaegerExporterProtocolConfig::HttpThriftBinary {
|
||||||
endpoint,
|
endpoint,
|
||||||
username,
|
username,
|
||||||
password,
|
password,
|
||||||
}) => jaeger_collector_tracer(endpoint, username.as_deref(), password.as_deref()).await?,
|
}) => {
|
||||||
|
jaeger_collector_tracer_provider(endpoint, username.as_deref(), password.as_deref())
|
||||||
|
.await?
|
||||||
|
}
|
||||||
TracingExporterConfig::Zipkin { collector_endpoint } => {
|
TracingExporterConfig::Zipkin { collector_endpoint } => {
|
||||||
zipkin_tracer(collector_endpoint).await?
|
// The Zipkin exporter already creates a tracer and installs it
|
||||||
|
return Ok(Some(zipkin_tracer(collector_endpoint).await?));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let tracer = tracer_provider.versioned_tracer(
|
||||||
|
env!("CARGO_PKG_NAME"),
|
||||||
|
Some(env!("CARGO_PKG_VERSION")),
|
||||||
|
Some(semcov::SCHEMA_URL),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
global::set_tracer_provider(tracer_provider);
|
||||||
|
|
||||||
Ok(Some(tracer))
|
Ok(Some(tracer))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn otlp_meter(endpoint: Option<&url::Url>) -> anyhow::Result<BasicController> {
|
fn otlp_metric_reader(endpoint: Option<&url::Url>) -> anyhow::Result<PeriodicReader> {
|
||||||
use opentelemetry_otlp::WithExportConfig;
|
use opentelemetry_otlp::WithExportConfig;
|
||||||
|
|
||||||
let mut exporter = opentelemetry_otlp::new_exporter().tonic();
|
let mut exporter = opentelemetry_otlp::new_exporter().tonic();
|
||||||
@ -214,35 +228,17 @@ fn otlp_meter(endpoint: Option<&url::Url>) -> anyhow::Result<BasicController> {
|
|||||||
exporter = exporter.with_endpoint(endpoint.to_string());
|
exporter = exporter.with_endpoint(endpoint.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
let controller = opentelemetry_otlp::new_pipeline()
|
let exporter = MetricsExporterBuilder::from(exporter).build_metrics_exporter(
|
||||||
.metrics(
|
Box::new(DefaultTemporalitySelector::new()),
|
||||||
sdk::metrics::selectors::simple::inexpensive(),
|
Box::new(DefaultAggregationSelector::new()),
|
||||||
sdk::export::metrics::aggregation::cumulative_temporality_selector(),
|
)?;
|
||||||
opentelemetry::runtime::Tokio,
|
|
||||||
)
|
|
||||||
.with_resource(resource())
|
|
||||||
.with_exporter(exporter)
|
|
||||||
.build()
|
|
||||||
.context("Failed to configure OTLP metrics exporter")?;
|
|
||||||
|
|
||||||
Ok(controller)
|
Ok(PeriodicReader::builder(exporter, opentelemetry::runtime::Tokio).build())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stdout_meter() -> anyhow::Result<BasicController> {
|
fn stdout_metric_reader() -> PeriodicReader {
|
||||||
let exporter = sdk::export::metrics::stdout().build()?;
|
let exporter = opentelemetry_stdout::MetricsExporter::default();
|
||||||
let controller = sdk::metrics::controllers::basic(sdk::metrics::processors::factory(
|
PeriodicReader::builder(exporter, opentelemetry::runtime::Tokio).build()
|
||||||
sdk::metrics::selectors::simple::inexpensive(),
|
|
||||||
exporter.temporality_selector(),
|
|
||||||
))
|
|
||||||
.with_resource(resource())
|
|
||||||
.with_exporter(exporter)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
let cx = Context::new();
|
|
||||||
controller.start(&cx, opentelemetry::runtime::Tokio)?;
|
|
||||||
|
|
||||||
global::set_meter_provider(controller.clone());
|
|
||||||
Ok(controller)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn prometheus_service<T>() -> tower::util::ServiceFn<
|
pub fn prometheus_service<T>() -> tower::util::ServiceFn<
|
||||||
@ -250,15 +246,15 @@ pub fn prometheus_service<T>() -> tower::util::ServiceFn<
|
|||||||
> {
|
> {
|
||||||
use prometheus::{Encoder, TextEncoder};
|
use prometheus::{Encoder, TextEncoder};
|
||||||
|
|
||||||
if !PROMETHEUS_EXPORTER.initialized() {
|
if !PROMETHEUS_REGISTRY.initialized() {
|
||||||
tracing::warn!("A Prometheus resource was mounted on a listener, but the Prometheus exporter was not setup in the config");
|
tracing::warn!("A Prometheus resource was mounted on a listener, but the Prometheus exporter was not setup in the config");
|
||||||
}
|
}
|
||||||
|
|
||||||
tower::service_fn(move |_req| {
|
tower::service_fn(move |_req| {
|
||||||
let response = if let Some(exporter) = PROMETHEUS_EXPORTER.get() {
|
let response = if let Some(registry) = PROMETHEUS_REGISTRY.get() {
|
||||||
let mut buffer = vec![];
|
let mut buffer = vec![];
|
||||||
let encoder = TextEncoder::new();
|
let encoder = TextEncoder::new();
|
||||||
let metric_families = exporter.registry().gather();
|
let metric_families = registry.gather();
|
||||||
|
|
||||||
// That shouldn't panic, unless we're constructing invalid labels
|
// That shouldn't panic, unless we're constructing invalid labels
|
||||||
encoder.encode(&metric_families, &mut buffer).unwrap();
|
encoder.encode(&metric_families, &mut buffer).unwrap();
|
||||||
@ -280,32 +276,41 @@ pub fn prometheus_service<T>() -> tower::util::ServiceFn<
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prometheus_meter() -> anyhow::Result<BasicController> {
|
fn prometheus_metric_reader() -> anyhow::Result<PrometheusExporter> {
|
||||||
let controller = sdk::metrics::controllers::basic(sdk::metrics::processors::factory(
|
let registry = Registry::new();
|
||||||
// All histogram metrics are in milliseconds. Each bucket is ~2x the previous one.
|
PROMETHEUS_REGISTRY.set(registry.clone())?;
|
||||||
sdk::metrics::selectors::simple::histogram([
|
|
||||||
1.0, 3.0, 5.0, 10.0, 30.0, 50.0, 100.0, 300.0, 1000.0,
|
|
||||||
]),
|
|
||||||
sdk::export::metrics::aggregation::cumulative_temporality_selector(),
|
|
||||||
))
|
|
||||||
.with_resource(resource())
|
|
||||||
.build();
|
|
||||||
|
|
||||||
let exporter = opentelemetry_prometheus::exporter(controller.clone()).try_init()?;
|
let exporter = opentelemetry_prometheus::exporter()
|
||||||
PROMETHEUS_EXPORTER.set(exporter)?;
|
.with_registry(registry)
|
||||||
|
.without_scope_info()
|
||||||
|
.build()?;
|
||||||
|
|
||||||
Ok(controller)
|
Ok(exporter)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn meter(config: &MetricsExporterConfig) -> anyhow::Result<Option<BasicController>> {
|
fn init_meter(config: &MetricsExporterConfig) -> anyhow::Result<()> {
|
||||||
let controller = match config {
|
let mut meter_provider_builder = MeterProvider::builder();
|
||||||
MetricsExporterConfig::None => None,
|
match config {
|
||||||
MetricsExporterConfig::Stdout => Some(stdout_meter()?),
|
MetricsExporterConfig::None => {}
|
||||||
MetricsExporterConfig::Otlp { endpoint } => Some(otlp_meter(endpoint.as_ref())?),
|
MetricsExporterConfig::Stdout => {
|
||||||
MetricsExporterConfig::Prometheus => Some(prometheus_meter()?),
|
meter_provider_builder = meter_provider_builder.with_reader(stdout_metric_reader());
|
||||||
|
}
|
||||||
|
MetricsExporterConfig::Otlp { endpoint } => {
|
||||||
|
meter_provider_builder =
|
||||||
|
meter_provider_builder.with_reader(otlp_metric_reader(endpoint.as_ref())?);
|
||||||
|
}
|
||||||
|
MetricsExporterConfig::Prometheus => {
|
||||||
|
meter_provider_builder =
|
||||||
|
meter_provider_builder.with_reader(prometheus_metric_reader()?);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(controller)
|
let meter_provider = meter_provider_builder.with_resource(resource()).build();
|
||||||
|
|
||||||
|
METER_PROVIDER.set(meter_provider.clone())?;
|
||||||
|
global::set_meter_provider(meter_provider.clone());
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trace_config() -> sdk::trace::Config {
|
fn trace_config() -> sdk::trace::Config {
|
||||||
@ -326,6 +331,7 @@ fn resource() -> Resource {
|
|||||||
Box::new(sdk::resource::EnvResourceDetector::new()),
|
Box::new(sdk::resource::EnvResourceDetector::new()),
|
||||||
Box::new(sdk::resource::OsResourceDetector),
|
Box::new(sdk::resource::OsResourceDetector),
|
||||||
Box::new(sdk::resource::ProcessResourceDetector),
|
Box::new(sdk::resource::ProcessResourceDetector),
|
||||||
|
Box::new(sdk::resource::TelemetryResourceDetector),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ futures-util = "0.3.28"
|
|||||||
# Logging and tracing
|
# Logging and tracing
|
||||||
tracing = "0.1.37"
|
tracing = "0.1.37"
|
||||||
opentelemetry = "0.20.0"
|
opentelemetry = "0.20.0"
|
||||||
|
opentelemetry-semantic-conventions = "0.12.0"
|
||||||
|
|
||||||
# Error management
|
# Error management
|
||||||
thiserror = "1.0.44"
|
thiserror = "1.0.44"
|
||||||
|
@ -29,7 +29,7 @@ use mas_storage_pg::PgRepository;
|
|||||||
use mas_templates::Templates;
|
use mas_templates::Templates;
|
||||||
use opentelemetry::{
|
use opentelemetry::{
|
||||||
metrics::{Histogram, MetricsError, Unit},
|
metrics::{Histogram, MetricsError, Unit},
|
||||||
Context, KeyValue,
|
KeyValue,
|
||||||
};
|
};
|
||||||
use rand::SeedableRng;
|
use rand::SeedableRng;
|
||||||
use sqlx::PgPool;
|
use sqlx::PgPool;
|
||||||
@ -60,7 +60,12 @@ impl AppState {
|
|||||||
/// Returns an error if the metrics could not be initialized.
|
/// Returns an error if the metrics could not be initialized.
|
||||||
pub fn init_metrics(&mut self) -> Result<(), MetricsError> {
|
pub fn init_metrics(&mut self) -> Result<(), MetricsError> {
|
||||||
// XXX: do we want to put that somewhere else?
|
// XXX: do we want to put that somewhere else?
|
||||||
let meter = opentelemetry::global::meter("mas-handlers");
|
let meter = opentelemetry::global::meter_with_version(
|
||||||
|
env!("CARGO_PKG_NAME"),
|
||||||
|
Some(env!("CARGO_PKG_VERSION")),
|
||||||
|
Some(opentelemetry_semantic_conventions::SCHEMA_URL),
|
||||||
|
None,
|
||||||
|
);
|
||||||
let pool = self.pool.clone();
|
let pool = self.pool.clone();
|
||||||
let usage = meter
|
let usage = meter
|
||||||
.i64_observable_up_down_counter("db.connections.usage")
|
.i64_observable_up_down_counter("db.connections.usage")
|
||||||
@ -75,13 +80,13 @@ impl AppState {
|
|||||||
.init();
|
.init();
|
||||||
|
|
||||||
// Observe the number of active and idle connections in the pool
|
// Observe the number of active and idle connections in the pool
|
||||||
meter.register_callback(move |cx| {
|
meter.register_callback(&[usage.as_any(), max.as_any()], move |observer| {
|
||||||
let idle = u32::try_from(pool.num_idle()).unwrap_or(u32::MAX);
|
let idle = u32::try_from(pool.num_idle()).unwrap_or(u32::MAX);
|
||||||
let used = pool.size() - idle;
|
let used = pool.size() - idle;
|
||||||
let max_conn = pool.options().get_max_connections();
|
let max_conn = pool.options().get_max_connections();
|
||||||
usage.observe(cx, i64::from(idle), &[KeyValue::new("state", "idle")]);
|
observer.observe_i64(&usage, i64::from(idle), &[KeyValue::new("state", "idle")]);
|
||||||
usage.observe(cx, i64::from(used), &[KeyValue::new("state", "used")]);
|
observer.observe_i64(&usage, i64::from(used), &[KeyValue::new("state", "used")]);
|
||||||
max.observe(cx, i64::from(max_conn), &[]);
|
observer.observe_i64(&max, i64::from(max_conn), &[]);
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
// Track the connection acquisition time
|
// Track the connection acquisition time
|
||||||
@ -212,7 +217,7 @@ impl FromRequestParts<AppState> for BoxRepository {
|
|||||||
let duration_ms = duration.as_millis().try_into().unwrap_or(u64::MAX);
|
let duration_ms = duration.as_millis().try_into().unwrap_or(u64::MAX);
|
||||||
|
|
||||||
if let Some(histogram) = &state.conn_acquisition_histogram {
|
if let Some(histogram) = &state.conn_acquisition_histogram {
|
||||||
histogram.record(&Context::new(), duration_ms, &[]);
|
histogram.record(duration_ms, &[]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(repo
|
Ok(repo
|
||||||
|
@ -42,5 +42,7 @@ pub async fn get(
|
|||||||
|
|
||||||
let content = templates.render_index(&ctx).await?;
|
let content = templates.render_index(&ctx).await?;
|
||||||
|
|
||||||
|
tracing::info!("rendered index page");
|
||||||
|
|
||||||
Ok((cookie_jar, Html(content)))
|
Ok((cookie_jar, Html(content)))
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ tower = "0.4.13"
|
|||||||
tokio = { version = "1.30.0", features = ["time"] }
|
tokio = { version = "1.30.0", features = ["time"] }
|
||||||
opentelemetry = { version = "0.20.0", features = ["metrics"] }
|
opentelemetry = { version = "0.20.0", features = ["metrics"] }
|
||||||
opentelemetry-http = "0.9.0"
|
opentelemetry-http = "0.9.0"
|
||||||
|
opentelemetry-semantic-conventions = "0.12.0"
|
||||||
pin-project-lite = "0.2.12"
|
pin-project-lite = "0.2.12"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
@ -27,6 +27,7 @@ fn meter() -> opentelemetry::metrics::Meter {
|
|||||||
opentelemetry::global::meter_with_version(
|
opentelemetry::global::meter_with_version(
|
||||||
env!("CARGO_PKG_NAME"),
|
env!("CARGO_PKG_NAME"),
|
||||||
Some(env!("CARGO_PKG_VERSION")),
|
Some(env!("CARGO_PKG_VERSION")),
|
||||||
|
Some(opentelemetry_semantic_conventions::SCHEMA_URL),
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
|
|
||||||
use opentelemetry::{metrics::Histogram, Context, KeyValue};
|
use opentelemetry::{metrics::Histogram, KeyValue};
|
||||||
use pin_project_lite::pin_project;
|
use pin_project_lite::pin_project;
|
||||||
use tokio::time::Instant;
|
use tokio::time::Instant;
|
||||||
use tower::{Layer, Service};
|
use tower::{Layer, Service};
|
||||||
@ -195,8 +195,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.histogram
|
this.histogram.record(duration_ms, &attributes);
|
||||||
.record(&Context::new(), duration_ms, &attributes);
|
|
||||||
std::task::Poll::Ready(result)
|
std::task::Poll::Ready(result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ use std::future::Future;
|
|||||||
|
|
||||||
use opentelemetry::{
|
use opentelemetry::{
|
||||||
metrics::{Unit, UpDownCounter},
|
metrics::{Unit, UpDownCounter},
|
||||||
Context, KeyValue,
|
KeyValue,
|
||||||
};
|
};
|
||||||
use pin_project_lite::pin_project;
|
use pin_project_lite::pin_project;
|
||||||
use tower::{Layer, Service};
|
use tower::{Layer, Service};
|
||||||
@ -98,7 +98,7 @@ struct InFlightGuard {
|
|||||||
|
|
||||||
impl InFlightGuard {
|
impl InFlightGuard {
|
||||||
fn new(counter: UpDownCounter<i64>, attributes: Vec<KeyValue>) -> Self {
|
fn new(counter: UpDownCounter<i64>, attributes: Vec<KeyValue>) -> Self {
|
||||||
counter.add(&Context::new(), 1, &attributes);
|
counter.add(1, &attributes);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
counter,
|
counter,
|
||||||
@ -109,7 +109,7 @@ impl InFlightGuard {
|
|||||||
|
|
||||||
impl Drop for InFlightGuard {
|
impl Drop for InFlightGuard {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
self.counter.add(&Context::new(), -1, &self.attributes);
|
self.counter.add(-1, &self.attributes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +54,8 @@ where
|
|||||||
|
|
||||||
// Poll the inner future, with the span entered. This is effectively what
|
// Poll the inner future, with the span entered. This is effectively what
|
||||||
// [`tracing::Instrumented`] does.
|
// [`tracing::Instrumented`] does.
|
||||||
let result = ready!(this.span.in_scope(|| this.inner.poll(cx)));
|
let _guard = this.span.enter();
|
||||||
|
let result = ready!(this.inner.poll(cx));
|
||||||
|
|
||||||
match &result {
|
match &result {
|
||||||
Ok(response) => {
|
Ok(response) => {
|
||||||
|
Reference in New Issue
Block a user