diff --git a/Cargo.lock b/Cargo.lock index 958f70d..0371692 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -645,6 +645,51 @@ dependencies = [ "thiserror", ] +[[package]] +name = "axum" +version = "0.6.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8175979259124331c1d7bf6586ee7e0da434155e4b2d48ec2c8386281d8df39" +dependencies = [ + "async-trait", + "axum-core", + "bitflags", + "bytes 1.4.0", + "futures-util", + "http", + "http-body 0.4.5", + "hyper 0.14.26", + "itoa 1.0.6", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite 0.2.9", + "rustversion", + "serde", + "sync_wrapper", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum-core" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" +dependencies = [ + "async-trait", + "bytes 1.4.0", + "futures-util", + "http", + "http-body 0.4.5", + "mime", + "rustversion", + "tower-layer", + "tower-service", +] + [[package]] name = "bae" version = "0.1.7" @@ -1571,6 +1616,19 @@ dependencies = [ "syn 2.0.15", ] +[[package]] +name = "dashmap" +version = "5.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "907076dfda823b0b36d2a1bb5f90c96660a5bbcd7729e10727f07858f22c4edc" +dependencies = [ + "cfg-if 1.0.0", + "hashbrown 0.12.3", + "lock_api", + "once_cell", + "parking_lot_core 0.9.7", +] + [[package]] name = "data-encoding" version = "2.3.3" @@ -2280,6 +2338,16 @@ dependencies = [ "version_check", ] +[[package]] +name = "gethostname" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1ebd34e35c46e00bb73e81363248d627782724609fe1b6396f553f68fe3862e" +dependencies = [ + "libc", + "winapi 0.3.9", +] + [[package]] name = "getrandom" version = "0.1.16" @@ -2662,6 +2730,18 @@ dependencies = [ "want", ] +[[package]] +name = "hyper-timeout" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" +dependencies = [ + "hyper 0.14.26", + "pin-project-lite 0.2.9", + "tokio 1.28.2", + "tokio-io-timeout", +] + [[package]] name = "hyper-tls" version = "0.4.3" @@ -3213,6 +3293,12 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" +[[package]] +name = "matchit" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b87248edafb776e59e6ee64a79086f65890d3510f2c656c000bf2a7e8a0aea40" + [[package]] name = "maybe-async" version = "0.2.7" @@ -3575,8 +3661,50 @@ version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69d6c3d7288a106c0a363e4b0e8d308058d56902adefb16f4936f417ffef086e" dependencies = [ - "opentelemetry_api", - "opentelemetry_sdk", + "opentelemetry_api 0.18.0", + "opentelemetry_sdk 0.18.0", +] + +[[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]] +name = "opentelemetry-otlp" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8af72d59a4484654ea8eb183fea5ae4eb6a41d7ac3e3bae5f4d2a282a3a7d3ca" +dependencies = [ + "async-trait", + "futures 0.3.28", + "futures-util", + "http", + "opentelemetry 0.19.0", + "opentelemetry-proto", + "prost", + "serde", + "thiserror", + "tokio 1.28.2", + "tonic", +] + +[[package]] +name = "opentelemetry-proto" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "045f8eea8c0fa19f7d48e7bc3128a39c2e5c533d5c61298c548dfefc1064474c" +dependencies = [ + "futures 0.3.28", + "futures-util", + "opentelemetry 0.19.0", + "prost", + "tonic", ] [[package]] @@ -3594,6 +3722,22 @@ dependencies = [ "thiserror", ] +[[package]] +name = "opentelemetry_api" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed41783a5bf567688eb38372f2b7a8530f5a607a4b49d38dd7573236c23ca7e2" +dependencies = [ + "fnv", + "futures-channel", + "futures-util", + "indexmap", + "once_cell", + "pin-project-lite 0.2.9", + "thiserror", + "urlencoding", +] + [[package]] name = "opentelemetry_sdk" version = "0.18.0" @@ -3606,7 +3750,27 @@ dependencies = [ "futures-executor", "futures-util", "once_cell", - "opentelemetry_api", + "opentelemetry_api 0.18.0", + "percent-encoding", + "rand 0.8.5", + "thiserror", +] + +[[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", + "dashmap", + "fnv", + "futures-channel", + "futures-executor", + "futures-util", + "once_cell", + "opentelemetry_api 0.19.0", "percent-encoding", "rand 0.8.5", "thiserror", @@ -3957,6 +4121,19 @@ dependencies = [ "tracing", ] +[[package]] +name = "plugin-telemetry" +version = "0.1.0" +dependencies = [ + "opentelemetry 0.19.0", + "opentelemetry-otlp", + "plugin-api", + "serde", + "tokio 1.28.2", + "tracing", + "tracing-bunyan-formatter", +] + [[package]] name = "polling" version = "2.8.0" @@ -4021,6 +4198,29 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "prost" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" +dependencies = [ + "bytes 1.4.0", + "prost-derive", +] + +[[package]] +name = "prost-derive" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" +dependencies = [ + "anyhow", + "itertools 0.10.5", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "psm" version = "0.1.21" @@ -5073,18 +5273,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.163" +version = "1.0.164" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2" +checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.163" +version = "1.0.164" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" +checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68" dependencies = [ "proc-macro2", "quote", @@ -5589,6 +5789,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + [[package]] name = "system-interface" version = "0.23.0" @@ -5632,7 +5838,7 @@ dependencies = [ "fnv", "futures 0.3.28", "humantime", - "opentelemetry", + "opentelemetry 0.18.0", "pin-project", "rand 0.8.5", "serde", @@ -5881,6 +6087,16 @@ dependencies = [ "log", ] +[[package]] +name = "tokio-io-timeout" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" +dependencies = [ + "pin-project-lite 0.2.9", + "tokio 1.28.2", +] + [[package]] name = "tokio-macros" version = "2.1.0" @@ -6022,6 +6238,64 @@ dependencies = [ "winnow", ] +[[package]] +name = "tonic" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f219fad3b929bef19b1f86fbc0358d35daed8f2cac972037ac0dc10bbb8d5fb" +dependencies = [ + "async-stream", + "async-trait", + "axum", + "base64 0.13.1", + "bytes 1.4.0", + "futures-core", + "futures-util", + "h2 0.3.18", + "http", + "http-body 0.4.5", + "hyper 0.14.26", + "hyper-timeout", + "percent-encoding", + "pin-project", + "prost", + "prost-derive", + "tokio 1.28.2", + "tokio-stream", + "tokio-util 0.7.8", + "tower", + "tower-layer", + "tower-service", + "tracing", + "tracing-futures", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "indexmap", + "pin-project", + "pin-project-lite 0.2.9", + "rand 0.8.5", + "slab", + "tokio 1.28.2", + "tokio-util 0.7.8", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + [[package]] name = "tower-service" version = "0.3.2" @@ -6052,6 +6326,24 @@ dependencies = [ "syn 2.0.15", ] +[[package]] +name = "tracing-bunyan-formatter" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25a348912d4e90923cb93343691d3be97e3409607363706c400fc935bb032fb0" +dependencies = [ + "ahash 0.8.3", + "gethostname", + "log", + "serde", + "serde_json", + "time 0.3.20", + "tracing", + "tracing-core", + "tracing-log", + "tracing-subscriber", +] + [[package]] name = "tracing-core" version = "0.1.30" @@ -6090,7 +6382,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21ebb87a95ea13271332df069020513ab70bdb5637ca42d6e492dc3bbbad48de" dependencies = [ "once_cell", - "opentelemetry", + "opentelemetry 0.18.0", "tracing", "tracing-core", "tracing-subscriber", @@ -6269,6 +6561,12 @@ dependencies = [ "serde", ] +[[package]] +name = "urlencoding" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8db7427f936968176eaa7cdf81b7f98b980b18495ec28f1b5791ac3bfe3eea9" + [[package]] name = "uuid" version = "0.8.2" diff --git a/Cargo.toml b/Cargo.toml index 9e71772..6791634 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,6 +28,7 @@ members = [ # "vendor/t_pay", # "vendor/pay_u", # PLUGINS + "crates/plugin-telemetry", "crates/plugin-api", # PAYMENT "crates/payment-adapter", diff --git a/crates/plugin-api/src/lib.rs b/crates/plugin-api/src/lib.rs index a562b37..a6da326 100644 --- a/crates/plugin-api/src/lib.rs +++ b/crates/plugin-api/src/lib.rs @@ -16,6 +16,7 @@ pub enum PluginType { Cache, FileStorage, EventBus, + Other, } #[async_trait] diff --git a/crates/plugin-telemetry/Cargo.toml b/crates/plugin-telemetry/Cargo.toml new file mode 100644 index 0000000..3800caa --- /dev/null +++ b/crates/plugin-telemetry/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "plugin-telemetry" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ['dylib'] + +[dependencies] +opentelemetry-otlp = { version = "0.12.0", features = ['trace', 'serde'] } +opentelemetry = { version = "0.19.0", features = ['default', 'trace'] } +tokio = { version = "1.28.2", features = ['full'] } +plugin-api = { workspace = true } +tracing-bunyan-formatter = { version = "0.3.7" } +tracing = { version = "0.1.37" } +serde = { version = "1.0.164", features = ['derive'] } diff --git a/crates/plugin-telemetry/src/lib.rs b/crates/plugin-telemetry/src/lib.rs new file mode 100644 index 0000000..7ce9857 --- /dev/null +++ b/crates/plugin-telemetry/src/lib.rs @@ -0,0 +1,82 @@ +use opentelemetry::sdk::propagation::TraceContextPropagator; +use opentelemetry::sdk::Resource; +use opentelemetry::{global, trace, KeyValue}; +use opentelemetry_otlp::WithExportConfig; +use plugin_api::{AppConfig, PluginType}; +use serde::Deserialize; +use tracing_bunyan_formatter::{BunyanFormattingLayer, JsonStorageLayer}; + +pub fn init_telemetry(config: &TelemetryConfig) { + let exporter = opentelemetry_otlp::new_exporter() + .tonic() + .with_endpoint(&config.endpoint); + + // Define a tracer + let tracer = opentelemetry_otlp::new_pipeline() + .tracing() + .with_exporter(exporter) + .with_trace_config( + trace::config().with_resource(Resource::new(vec![KeyValue::new( + opentelemetry_semantic_conventions::resource::SERVICE_NAME, + config.service_name.clone(), + )])), + ) + .install_batch(opentelemetry::runtime::Tokio) + .expect("Error: Failed to initialize the tracer."); + + let subscriber = Registry::default(); + let level_filter_layer = EnvFilter::try_from_default_env().unwrap_or(EnvFilter::new( + &config + .log_level + .or_else(|| std::env::var("RUST_LOG").ok()) + .unwrap_or_else(|| "INFO".to_string()), + )); + let tracing_layer = tracing_opentelemetry::layer().with_tracer(tracer); + let formatting_layer = BunyanFormattingLayer::new(config.service_name.clone(), std::io::stdout); + + global::set_text_map_propagator(TraceContextPropagator::new()); + + subscriber + .with(level_filter_layer) + .with(tracing_layer) + .with(JsonStorageLayer) + .with(formatting_layer) + .init() +} + +#[derive(Debug, Deserialize)] +pub struct TelemetryConfig { + endpoint: String, + log_level: Option, + service_name: String, +} + +pub struct TelemetryPlugin {} + +impl plugin_api::Plugin for TelemetryPlugin { + fn plugin_type() -> PluginType + where + Self: Sized, + { + PluginType::Other + } + + fn name(&self) -> &'static str { + "telemetry-plugin" + } + + async fn initialize(app_config: &AppConfig) -> Self + where + Self: Sized, + { + if let Some(config) = app_config.plugin_config("telemetry") { + match config.config::() { + Ok(config) => init_telemetry(&config), + Err(e) => tracing::warn!("Config for telemetry-plugin is malformed: {e}"), + } + } else { + tracing::warn!("Config \"telemetry\" not found for telemetry-plugin"); + } + Self {} + } +} diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..9fde7c8 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,38 @@ +version: '3' +services: + quickwit: + image: quickwit/quickwit:latest + command: run + restart: always + environment: + QW_ENABLE_OTLP_ENDPOINT: true + QW_ENABLE_JAEGER_ENDPOINT: true + ports: + - '7280:7280' + - '7281:7281' + volumes: + - ./qwdata:/quickwit/qwdata + + jaeger: + image: jaegertracing/jaeger-query:latest + restart: always + depends_on: + - quickwit + environment: + SPAN_STORAGE_TYPE: 'grpc-plugin' + GRPC_STORAGE_SERVER: 'quickwit:7281' + ports: + - '16686:16686' + + grafana: + image: grafana/grafana-enterprise:latest + restart: always + user: root + depends_on: + - quickwit + environment: + GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS: 'quickwit-quickwit-datasource' + ports: + - '3000:3000' + volumes: + - ./grafana-storage:/var/lib/grafana