1
0
mirror of https://github.com/matrix-org/matrix-authentication-service.git synced 2025-07-29 22:01:14 +03:00

cli: always include all OTEL exporters

This commit is contained in:
Quentin Gliech
2023-08-03 16:43:59 +02:00
parent f5dae9f8e2
commit 033479bc57
3 changed files with 22 additions and 119 deletions

View File

@ -35,12 +35,12 @@ tracing-subscriber = { version = "0.3.17", features = ["env-filter"] }
tracing-opentelemetry = "0.19.0" tracing-opentelemetry = "0.19.0"
opentelemetry = { version = "0.19.0", features = ["trace", "metrics", "rt-tokio"] } opentelemetry = { version = "0.19.0", features = ["trace", "metrics", "rt-tokio"] }
opentelemetry-semantic-conventions = "0.11.0" opentelemetry-semantic-conventions = "0.11.0"
opentelemetry-jaeger = { version = "0.18.0", features = ["rt-tokio", "collector_client"], optional = true } opentelemetry-jaeger = { version = "0.18.0", features = ["rt-tokio", "collector_client"] }
opentelemetry-otlp = { version = "0.12.0", features = ["trace", "metrics"], optional = true } opentelemetry-otlp = { version = "0.12.0", features = ["trace", "metrics"] }
opentelemetry-zipkin = { version = "0.17.0", features = ["opentelemetry-http"], default-features = false, optional = true } opentelemetry-zipkin = { version = "0.17.0", features = ["opentelemetry-http"], default-features = false }
opentelemetry-http = { version = "0.8.0", features = ["tokio", "hyper"], optional = true } opentelemetry-http = { version = "0.8.0", features = ["tokio", "hyper"] }
opentelemetry-prometheus = { version = "0.12.0", optional = true } opentelemetry-prometheus = { version = "0.12.0" }
prometheus = { version = "0.13.3", optional = true } 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"
sentry-tower = { version = "0.31.5", features = ["http"] } sentry-tower = { version = "0.31.5", features = ["http"] }
@ -68,13 +68,13 @@ oauth2-types = { path = "../oauth2-types" }
indoc = "2.0.3" indoc = "2.0.3"
[features] [features]
default = ["jaeger", "zipkin", "webpki-roots", "policy-cache"] default = ["webpki-roots", "policy-cache"]
# Features used for the prebuilt binaries # Features used for the prebuilt binaries
dist = ["otlp", "jaeger", "zipkin", "prometheus", "policy-cache", "native-roots", "mas-config/dist"] dist = ["policy-cache", "native-roots", "mas-config/dist"]
# Features used in the Docker image # Features used in the Docker image
docker = ["otlp", "jaeger", "zipkin", "prometheus", "native-roots", "mas-config/docker"] docker = ["native-roots", "mas-config/docker"]
# Enable wasmtime compilation cache # Enable wasmtime compilation cache
policy-cache = ["mas-policy/cache"] policy-cache = ["mas-policy/cache"]
@ -83,12 +83,3 @@ policy-cache = ["mas-policy/cache"]
native-roots = ["mas-http/native-roots", "mas-handlers/native-roots"] native-roots = ["mas-http/native-roots", "mas-handlers/native-roots"]
# Use the webpki root certificates # Use the webpki root certificates
webpki-roots = ["mas-http/webpki-roots", "mas-handlers/webpki-roots"] webpki-roots = ["mas-http/webpki-roots", "mas-handlers/webpki-roots"]
# Enable OpenTelemetry OTLP exporter. Requires protoc.
otlp = ["dep:opentelemetry-otlp"]
# Enable OpenTelemetry Jaeger exporter and propagator.
jaeger = ["dep:opentelemetry-jaeger", "dep:opentelemetry-http"]
# Enable OpenTelemetry Zipkin exporter and B3 propagator.
zipkin = ["dep:opentelemetry-zipkin", "dep:opentelemetry-http"]
# Enable OpenTelemetry Prometheus exporter. Requires "protoc"
prometheus = ["dep:opentelemetry-prometheus", "dep:prometheus"]

View File

@ -14,7 +14,7 @@
use std::time::Duration; use std::time::Duration;
use anyhow::{bail, Context as _}; use anyhow::Context as _;
use hyper::{header::CONTENT_TYPE, Body, Response}; use hyper::{header::CONTENT_TYPE, Body, Response};
use mas_config::{ use mas_config::{
JaegerExporterProtocolConfig, MetricsExporterConfig, Propagator, TelemetryConfig, JaegerExporterProtocolConfig, MetricsExporterConfig, Propagator, TelemetryConfig,
@ -32,26 +32,21 @@ use opentelemetry::{
}, },
Context, Context,
}; };
#[cfg(feature = "jaeger")]
use opentelemetry_jaeger::Propagator as JaegerPropagator; use opentelemetry_jaeger::Propagator as JaegerPropagator;
#[cfg(feature = "prometheus")]
use opentelemetry_prometheus::PrometheusExporter; use opentelemetry_prometheus::PrometheusExporter;
use opentelemetry_semantic_conventions as semcov; use opentelemetry_semantic_conventions as semcov;
#[cfg(feature = "zipkin")]
use opentelemetry_zipkin::{B3Encoding, Propagator as ZipkinPropagator}; use opentelemetry_zipkin::{B3Encoding, Propagator as ZipkinPropagator};
use tokio::sync::OnceCell; use tokio::sync::OnceCell;
use url::Url; use url::Url;
static METRICS_BASIC_CONTROLLER: OnceCell<BasicController> = OnceCell::const_new(); static METRICS_BASIC_CONTROLLER: OnceCell<BasicController> = OnceCell::const_new();
#[cfg(feature = "prometheus")]
static PROMETHEUS_EXPORTER: OnceCell<PrometheusExporter> = OnceCell::const_new(); static PROMETHEUS_EXPORTER: OnceCell<PrometheusExporter> = OnceCell::const_new();
pub async fn setup( pub async fn setup(
config: &TelemetryConfig, config: &TelemetryConfig,
) -> anyhow::Result<(Option<Tracer>, Option<BasicController>)> { ) -> 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);
// The CORS filter needs to know what headers it should whitelist for // The CORS filter needs to know what headers it should whitelist for
// CORS-protected requests. // CORS-protected requests.
@ -79,40 +74,23 @@ pub fn shutdown() {
} }
} }
fn match_propagator( fn match_propagator(propagator: Propagator) -> Box<dyn TextMapPropagator + Send + Sync> {
propagator: Propagator, use Propagator as P;
) -> anyhow::Result<Box<dyn TextMapPropagator + Send + Sync>> {
match propagator { match propagator {
Propagator::TraceContext => Ok(Box::new(TraceContextPropagator::new())), P::TraceContext => Box::new(TraceContextPropagator::new()),
Propagator::Baggage => Ok(Box::new(BaggagePropagator::new())), P::Baggage => Box::new(BaggagePropagator::new()),
P::Jaeger => Box::new(JaegerPropagator::new()),
#[cfg(feature = "jaeger")] P::B3 => Box::new(ZipkinPropagator::with_encoding(B3Encoding::SingleHeader)),
Propagator::Jaeger => Ok(Box::new(JaegerPropagator::new())), P::B3Multi => Box::new(ZipkinPropagator::with_encoding(B3Encoding::MultipleHeader)),
#[cfg(feature = "zipkin")]
Propagator::B3 => Ok(Box::new(ZipkinPropagator::with_encoding(
B3Encoding::SingleHeader,
))),
#[cfg(feature = "zipkin")]
Propagator::B3Multi => Ok(Box::new(ZipkinPropagator::with_encoding(
B3Encoding::MultipleHeader,
))),
p => bail!(
"The service was compiled without support for the {p:?} propagator, but config uses it.",
),
} }
} }
fn propagator(propagators: &[Propagator]) -> anyhow::Result<impl TextMapPropagator> { fn propagator(propagators: &[Propagator]) -> impl TextMapPropagator {
let propagators: Result<Vec<_>, _> = let propagators = propagators.iter().copied().map(match_propagator).collect();
propagators.iter().cloned().map(match_propagator).collect();
Ok(TextMapCompositePropagator::new(propagators?)) TextMapCompositePropagator::new(propagators)
} }
#[cfg(any(feature = "zipkin", feature = "jaeger"))]
async fn http_client() -> anyhow::Result<impl opentelemetry_http::HttpClient + 'static> { async fn http_client() -> anyhow::Result<impl opentelemetry_http::HttpClient + 'static> {
let client = mas_http::make_untraced_client() let client = mas_http::make_untraced_client()
.await .await
@ -129,7 +107,6 @@ fn stdout_tracer() -> Tracer {
.install_simple() .install_simple()
} }
#[cfg(feature = "otlp")]
fn otlp_tracer(endpoint: Option<&Url>) -> anyhow::Result<Tracer> { fn otlp_tracer(endpoint: Option<&Url>) -> anyhow::Result<Tracer> {
use opentelemetry_otlp::WithExportConfig; use opentelemetry_otlp::WithExportConfig;
@ -148,19 +125,6 @@ fn otlp_tracer(endpoint: Option<&Url>) -> anyhow::Result<Tracer> {
Ok(tracer) Ok(tracer)
} }
#[cfg(not(feature = "otlp"))]
#[allow(unused_variables)]
fn otlp_tracer(endpoint: Option<&Url>) -> anyhow::Result<Tracer> {
anyhow::bail!("The service was compiled without OTLP exporter support, but config exports traces via OTLP.")
}
#[cfg(not(feature = "jaeger"))]
#[allow(unused_variables)]
fn jaeger_agent_tracer(host: &str, port: u16) -> anyhow::Result<Tracer> {
anyhow::bail!("The service was compiled without Jaeger exporter support, but config exports traces via Jaeger.")
}
#[cfg(feature = "jaeger")]
fn jaeger_agent_tracer(host: &str, port: u16) -> anyhow::Result<Tracer> { fn jaeger_agent_tracer(host: &str, port: u16) -> anyhow::Result<Tracer> {
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"))
@ -174,17 +138,6 @@ fn jaeger_agent_tracer(host: &str, port: u16) -> anyhow::Result<Tracer> {
Ok(tracer) Ok(tracer)
} }
#[cfg(not(feature = "jaeger"))]
#[allow(unused_variables, clippy::unused_async)]
async fn jaeger_collector_tracer(
endpoint: &str,
username: Option<&str>,
password: Option<&str>,
) -> anyhow::Result<Tracer> {
anyhow::bail!("The service was compiled without Jaeger exporter support, but config exports traces via Jaeger.")
}
#[cfg(feature = "jaeger")]
async fn jaeger_collector_tracer( async fn jaeger_collector_tracer(
endpoint: &str, endpoint: &str,
username: Option<&str>, username: Option<&str>,
@ -212,13 +165,6 @@ async fn jaeger_collector_tracer(
Ok(tracer) Ok(tracer)
} }
#[cfg(not(feature = "zipkin"))]
#[allow(unused_variables, clippy::unused_async)]
async fn zipkin_tracer(collector_endpoint: &Option<Url>) -> anyhow::Result<Tracer> {
anyhow::bail!("The service was compiled without Jaeger exporter support, but config exports traces via Jaeger.")
}
#[cfg(feature = "zipkin")]
async fn zipkin_tracer(collector_endpoint: &Option<Url>) -> anyhow::Result<Tracer> { async fn zipkin_tracer(collector_endpoint: &Option<Url>) -> anyhow::Result<Tracer> {
let http_client = http_client().await?; let http_client = http_client().await?;
@ -260,7 +206,6 @@ async fn tracer(config: &TracingExporterConfig) -> anyhow::Result<Option<Tracer>
Ok(Some(tracer)) Ok(Some(tracer))
} }
#[cfg(feature = "otlp")]
fn otlp_meter(endpoint: Option<&url::Url>) -> anyhow::Result<BasicController> { fn otlp_meter(endpoint: Option<&url::Url>) -> anyhow::Result<BasicController> {
use opentelemetry_otlp::WithExportConfig; use opentelemetry_otlp::WithExportConfig;
@ -283,12 +228,6 @@ fn otlp_meter(endpoint: Option<&url::Url>) -> anyhow::Result<BasicController> {
Ok(controller) Ok(controller)
} }
#[cfg(not(feature = "otlp"))]
#[allow(unused_variables)]
fn otlp_meter(endpoint: Option<&url::Url>) -> anyhow::Result<BasicController> {
anyhow::bail!("The service was compiled without OTLP exporter support, but config exports metrics via OTLP.")
}
fn stdout_meter() -> anyhow::Result<BasicController> { fn stdout_meter() -> anyhow::Result<BasicController> {
let exporter = sdk::export::metrics::stdout().build()?; let exporter = sdk::export::metrics::stdout().build()?;
let controller = sdk::metrics::controllers::basic(sdk::metrics::processors::factory( let controller = sdk::metrics::controllers::basic(sdk::metrics::processors::factory(
@ -306,26 +245,6 @@ fn stdout_meter() -> anyhow::Result<BasicController> {
Ok(controller) Ok(controller)
} }
#[cfg(not(feature = "prometheus"))]
pub fn prometheus_service<T>() -> tower::util::ServiceFn<
impl FnMut(T) -> std::future::Ready<Result<Response<Body>, std::convert::Infallible>> + Clone,
> {
tracing::warn!("Prometheus exporter was not enabled at compilation time, but the Prometheus resource was mounted on a listener");
tower::service_fn(move |_req| {
let response = Response::builder()
.status(500)
.header(CONTENT_TYPE, "text/plain")
.body(Body::from(
"Prometheus exporter was not enabled at compilation time",
))
.unwrap();
std::future::ready(Ok(response))
})
}
#[cfg(feature = "prometheus")]
pub fn prometheus_service<T>() -> tower::util::ServiceFn< pub fn prometheus_service<T>() -> tower::util::ServiceFn<
impl FnMut(T) -> std::future::Ready<Result<Response<Body>, std::convert::Infallible>> + Clone, impl FnMut(T) -> std::future::Ready<Result<Response<Body>, std::convert::Infallible>> + Clone,
> { > {
@ -361,12 +280,6 @@ pub fn prometheus_service<T>() -> tower::util::ServiceFn<
}) })
} }
#[cfg(not(feature = "prometheus"))]
fn prometheus_meter() -> anyhow::Result<BasicController> {
anyhow::bail!("The service was compiled without Prometheus exporter support, but config exports metrics via Prometheus.")
}
#[cfg(feature = "prometheus")]
fn prometheus_meter() -> anyhow::Result<BasicController> { fn prometheus_meter() -> anyhow::Result<BasicController> {
let controller = sdk::metrics::controllers::basic(sdk::metrics::processors::factory( let controller = sdk::metrics::controllers::basic(sdk::metrics::processors::factory(
// All histogram metrics are in milliseconds. Each bucket is ~2x the previous one. // All histogram metrics are in milliseconds. Each bucket is ~2x the previous one.

View File

@ -25,9 +25,8 @@ use url::Url;
use super::ConfigurationSection; use super::ConfigurationSection;
/// Propagation format for incoming and outgoing requests /// Propagation format for incoming and outgoing requests
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] #[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
#[serde(rename_all = "lowercase")] #[serde(rename_all = "lowercase")]
#[non_exhaustive]
pub enum Propagator { pub enum Propagator {
/// Propagate according to the W3C Trace Context specification /// Propagate according to the W3C Trace Context specification
TraceContext, TraceContext,