diff --git a/Cargo.lock b/Cargo.lock
index 0ab6eca6..77b1edbe 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2349,7 +2349,7 @@ dependencies = [
"atty",
"clap",
"dotenv",
- "futures 0.3.24",
+ "futures-util",
"hyper",
"indoc",
"mas-config",
@@ -2366,8 +2366,10 @@ dependencies = [
"opentelemetry-http",
"opentelemetry-jaeger",
"opentelemetry-otlp",
+ "opentelemetry-prometheus",
"opentelemetry-semantic-conventions",
"opentelemetry-zipkin",
+ "prometheus",
"schemars",
"serde_json",
"serde_yaml",
@@ -2375,6 +2377,7 @@ dependencies = [
"tower",
"tracing",
"tracing-appender",
+ "tracing-opentelemetry",
"tracing-subscriber",
"url",
"watchman_client",
@@ -2994,8 +2997,10 @@ dependencies = [
"async-trait",
"futures 0.3.24",
"futures-executor",
+ "http",
"once_cell",
"opentelemetry",
+ "opentelemetry-http",
"opentelemetry-semantic-conventions",
"thiserror",
"thrift",
@@ -3021,6 +3026,17 @@ dependencies = [
"tonic",
]
+[[package]]
+name = "opentelemetry-prometheus"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06c3d833835a53cf91331d2cfb27e9121f5a95261f31f08a1f79ab31688b8da8"
+dependencies = [
+ "opentelemetry",
+ "prometheus",
+ "protobuf",
+]
+
[[package]]
name = "opentelemetry-proto"
version = "0.1.0"
@@ -3540,6 +3556,21 @@ dependencies = [
"yansi",
]
+[[package]]
+name = "prometheus"
+version = "0.13.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "45c8babc29389186697fe5a2a4859d697825496b83db5d0b65271cdc0488e88c"
+dependencies = [
+ "cfg-if",
+ "fnv",
+ "lazy_static",
+ "memchr",
+ "parking_lot 0.12.1",
+ "protobuf",
+ "thiserror",
+]
+
[[package]]
name = "prost"
version = "0.11.0"
@@ -3593,6 +3624,12 @@ dependencies = [
"prost",
]
+[[package]]
+name = "protobuf"
+version = "2.28.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94"
+
[[package]]
name = "psm"
version = "0.1.21"
diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml
index d8152343..e1720f84 100644
--- a/crates/cli/Cargo.toml
+++ b/crates/cli/Cargo.toml
@@ -7,7 +7,7 @@ license = "Apache-2.0"
[dependencies]
tokio = { version = "1.21.1", features = ["full"] }
-futures = "0.3.24"
+futures-util = "0.3.24"
anyhow = "1.0.65"
clap = { version = "3.2.22", features = ["derive"] }
dotenv = "0.15.0"
@@ -24,13 +24,15 @@ atty = "0.2.14"
tracing = "0.1.36"
tracing-appender = "0.2.2"
tracing-subscriber = { version = "0.3.15", features = ["env-filter"] }
-#tracing-opentelemetry = "0.17.4"
+tracing-opentelemetry = "0.18.0"
opentelemetry = { version = "0.18.0", features = ["trace", "metrics", "rt-tokio"] }
opentelemetry-semantic-conventions = "0.10.0"
-opentelemetry-jaeger = { version = "0.17.0", features = ["rt-tokio"], optional = true }
+opentelemetry-jaeger = { version = "0.17.0", features = ["rt-tokio", "collector_client"], optional = true }
opentelemetry-otlp = { version = "0.11.0", features = ["trace", "metrics", "http-proto"], optional = true }
opentelemetry-zipkin = { version = "0.16.0", features = ["opentelemetry-http"], default-features = false, optional = true }
opentelemetry-http = { version = "0.7.0", features = ["tokio", "hyper"], optional = true }
+opentelemetry-prometheus = "0.11.0"
+prometheus = "0.13.2"
mas-config = { path = "../config" }
mas-email = { path = "../email" }
diff --git a/crates/cli/src/main.rs b/crates/cli/src/main.rs
index eb6d1424..c83a8b8f 100644
--- a/crates/cli/src/main.rs
+++ b/crates/cli/src/main.rs
@@ -58,16 +58,14 @@ async fn try_main() -> anyhow::Result<()> {
.or_else(|_| EnvFilter::try_new("info"))
.context("could not setup logging filter")?;
- /*
// Don't fill the telemetry layer for now, we want to configure it based on the
// app config, so we need to delay that a bit
let (telemetry_layer, handle) = reload::Layer::new(None);
// We only want "INFO" level spans to go through OpenTelemetry
let telemetry_layer = telemetry_layer.with_filter(LevelFilter::INFO);
- */
let subscriber = Registry::default()
- //.with(telemetry_layer)
+ .with(telemetry_layer)
.with(filter_layer)
.with(fmt_layer);
subscriber
@@ -91,10 +89,9 @@ async fn try_main() -> anyhow::Result<()> {
let telemetry_config: TelemetryConfig = opts.load_config().unwrap_or_default();
// Setup OpenTelemtry tracing and metrics
- let tracer = telemetry::setup(&telemetry_config)
+ let (tracer, _meter) = telemetry::setup(&telemetry_config)
.await
.context("failed to setup opentelemetry")?;
- /*
if let Some(tracer) = tracer {
// Now we can swap out the actual opentelemetry tracing layer
handle.reload(
@@ -103,7 +100,6 @@ async fn try_main() -> anyhow::Result<()> {
.with_tracked_inactivity(false),
)?;
}
- */
// And run the command
tracing::trace!(?opts, "Running command");
diff --git a/crates/cli/src/telemetry.rs b/crates/cli/src/telemetry.rs
index 8b208b3c..aef14793 100644
--- a/crates/cli/src/telemetry.rs
+++ b/crates/cli/src/telemetry.rs
@@ -12,28 +12,46 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-use std::{net::SocketAddr, time::Duration};
+use std::{
+ convert::Infallible,
+ net::{SocketAddr, TcpListener},
+ time::Duration,
+};
-use anyhow::bail;
-use mas_config::{MetricsExporterConfig, Propagator, TelemetryConfig, TracingExporterConfig};
+use anyhow::{bail, Context as _};
+use hyper::{header::CONTENT_TYPE, service::make_service_fn, Body, Method, Request, Response};
+use mas_config::{
+ JaegerExporterProtocolConfig, MetricsExporterConfig, Propagator, TelemetryConfig,
+ TracingExporterConfig,
+};
use opentelemetry::{
global,
propagation::TextMapPropagator,
sdk::{
self,
+ metrics::controllers::BasicController,
propagation::{BaggagePropagator, TextMapCompositePropagator, TraceContextPropagator},
trace::{Sampler, Tracer},
Resource,
},
+ Context,
};
#[cfg(feature = "jaeger")]
use opentelemetry_jaeger::Propagator as JaegerPropagator;
use opentelemetry_semantic_conventions as semcov;
#[cfg(feature = "zipkin")]
use opentelemetry_zipkin::{B3Encoding, Propagator as ZipkinPropagator};
+use prometheus::{Encoder, TextEncoder};
+use tokio::sync::OnceCell;
+use tower::service_fn;
+use tracing::info;
use url::Url;
-pub async fn setup(config: &TelemetryConfig) -> anyhow::Result