diff --git a/Cargo.lock b/Cargo.lock index 3813fb1..e7e7f90 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,12 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "anyhow" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" + [[package]] name = "ascii" version = "0.9.3" @@ -55,6 +61,12 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + [[package]] name = "base64" version = "0.22.1" @@ -143,6 +155,21 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +[[package]] +name = "crossbeam-channel" +version = "0.5.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" + [[package]] name = "either" version = "1.11.0" @@ -225,6 +252,17 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +[[package]] +name = "futures-executor" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + [[package]] name = "futures-io" version = "0.3.30" @@ -271,12 +309,31 @@ dependencies = [ "slab", ] +[[package]] +name = "getrandom" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + [[package]] name = "gimli" version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + [[package]] name = "graphql-introspection-query" version = "0.2.0" @@ -346,7 +403,7 @@ dependencies = [ "futures-core", "futures-sink", "futures-util", - "http", + "http 1.1.0", "indexmap", "slab", "tokio", @@ -366,6 +423,17 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + [[package]] name = "http" version = "1.1.0" @@ -377,6 +445,17 @@ dependencies = [ "itoa", ] +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes", + "http 0.2.12", + "pin-project-lite", +] + [[package]] name = "http-body" version = "1.0.0" @@ -384,7 +463,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" dependencies = [ "bytes", - "http", + "http 1.1.0", ] [[package]] @@ -395,8 +474,8 @@ checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" dependencies = [ "bytes", "futures-core", - "http", - "http-body", + "http 1.1.0", + "http-body 1.0.0", "pin-project-lite", ] @@ -416,8 +495,8 @@ dependencies = [ "futures-channel", "futures-util", "h2", - "http", - "http-body", + "http 1.1.0", + "http-body 1.0.0", "httparse", "itoa", "pin-project-lite", @@ -451,8 +530,8 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "http", - "http-body", + "http 1.1.0", + "http-body 1.0.0", "hyper", "pin-project-lite", "socket2", @@ -488,6 +567,15 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.11" @@ -651,6 +739,116 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "opentelemetry" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900d57987be3f2aeb70d385fff9b27fb74c5723cc9a52d904d4f9c807a0667bf" +dependencies = [ + "futures-core", + "futures-sink", + "js-sys", + "once_cell", + "pin-project-lite", + "thiserror", + "urlencoding", +] + +[[package]] +name = "opentelemetry-http" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7690dc77bf776713848c4faa6501157469017eaf332baccd4eb1cea928743d94" +dependencies = [ + "async-trait", + "bytes", + "http 0.2.12", + "opentelemetry", +] + +[[package]] +name = "opentelemetry-otlp" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a016b8d9495c639af2145ac22387dcb88e44118e45320d9238fbf4e7889abcb" +dependencies = [ + "async-trait", + "futures-core", + "http 0.2.12", + "opentelemetry", + "opentelemetry-http", + "opentelemetry-proto", + "opentelemetry-semantic-conventions", + "opentelemetry_sdk", + "prost", + "thiserror", +] + +[[package]] +name = "opentelemetry-proto" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a8fddc9b68f5b80dae9d6f510b88e02396f006ad48cac349411fbecc80caae4" +dependencies = [ + "opentelemetry", + "opentelemetry_sdk", + "prost", + "tonic", +] + +[[package]] +name = "opentelemetry-semantic-conventions" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9ab5bd6c42fb9349dcf28af2ba9a0667f697f9bdcca045d39f2cec5543e2910" + +[[package]] +name = "opentelemetry-stdout" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bdf28b381f23afcd150afc0b38a4183dd321fc96320c1554752b6b761648f78" +dependencies = [ + "async-trait", + "chrono", + "futures-util", + "opentelemetry", + "opentelemetry_sdk", + "ordered-float", + "serde", + "serde_json", +] + +[[package]] +name = "opentelemetry_sdk" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e90c7113be649e31e9a0f8b5ee24ed7a16923b322c3c5ab6367469c049d6b7e" +dependencies = [ + "async-trait", + "crossbeam-channel", + "futures-channel", + "futures-executor", + "futures-util", + "glob", + "once_cell", + "opentelemetry", + "ordered-float", + "percent-encoding", + "rand", + "thiserror", + "tokio", + "tokio-stream", +] + +[[package]] +name = "ordered-float" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a76df7075c7d4d01fdcb46c912dd17fba5b60c78ea480b475f2b6ab6f666584e" +dependencies = [ + "num-traits", +] + [[package]] name = "percent-encoding" version = "2.3.1" @@ -695,6 +893,12 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + [[package]] name = "proc-macro2" version = "1.0.81" @@ -704,6 +908,29 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "prost" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0f5d036824e4761737860779c906171497f6d55681139d8312388f8fe398922" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-derive" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19de2de2a00075bf566bee3bd4db014b11587e84184d3f7a791bc17f1a8e9e48" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn 2.0.60", +] + [[package]] name = "quote" version = "1.0.36" @@ -713,20 +940,50 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + [[package]] name = "reqwest" version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10" dependencies = [ - "base64", + "base64 0.22.1", "bytes", "encoding_rs", "futures-core", "futures-util", "h2", - "http", - "http-body", + "http 1.1.0", + "http-body 1.0.0", "http-body-util", "hyper", "hyper-tls", @@ -780,7 +1037,7 @@ version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" dependencies = [ - "base64", + "base64 0.22.1", "rustls-pki-types", ] @@ -1039,6 +1296,17 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-stream" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + [[package]] name = "tokio-util" version = "0.7.10" @@ -1053,6 +1321,27 @@ dependencies = [ "tracing", ] +[[package]] +name = "tonic" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76c4eb7a4e9ef9d4763600161f12f5070b92a578e1b634db88a6887844c91a13" +dependencies = [ + "async-trait", + "base64 0.21.7", + "bytes", + "http 0.2.12", + "http-body 0.4.6", + "percent-encoding", + "pin-project", + "prost", + "tokio", + "tokio-stream", + "tower-layer", + "tower-service", + "tracing", +] + [[package]] name = "tower" version = "0.4.13" @@ -1089,9 +1378,21 @@ checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ "log", "pin-project-lite", + "tracing-attributes", "tracing-core", ] +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", +] + [[package]] name = "tracing-core" version = "0.1.32" @@ -1148,6 +1449,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "urlencoding" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" + [[package]] name = "vcpkg" version = "0.2.15" @@ -1424,8 +1731,8 @@ dependencies = [ "chrono", "futures-channel", "futures-util", - "http", - "http-body", + "http 1.1.0", + "http-body 1.0.0", "js-sys", "matchit", "pin-project", @@ -1479,9 +1786,16 @@ dependencies = [ name = "worker-rust" version = "0.1.0" dependencies = [ + "getrandom", "graphql_client", + "opentelemetry", + "opentelemetry-http", + "opentelemetry-otlp", + "opentelemetry-stdout", + "opentelemetry_sdk", "reqwest", "serde", + "serde_json", "worker", ] diff --git a/Cargo.toml b/Cargo.toml index efb5d6f..a0a6df8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,13 @@ graphql_client = "0.14.0" serde = "1.0.200" worker = "0.2.0" reqwest = { version = "0.12.4", features = ["json"] } +opentelemetry = { version = "=0.22.0", features = ["otel_unstable"] } +opentelemetry_sdk = { version="=0.22.1", default-features = false, features = ["trace", "metrics", "rt-tokio-current-thread"] } +opentelemetry-stdout = { version="0.3.0", default-features = false, features=["trace", "metrics"] } +getrandom = { version = "0.2.14", features = ["js"] } +serde_json = "1.0.116" +opentelemetry-http = { version="0.11.1" } +opentelemetry-otlp = { version="0.15.0", features = ["metrics", "http-proto"], default-features = false } [profile.release] opt-level = "s" # optimize for size in release builds diff --git a/package-lock.json b/package-lock.json index cfd884b..e95841d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "devDependencies": { "env-cmd": "^10.1.0", "get-graphql-schema": "^2.1.2", - "wrangler": "^3.53.0" + "wrangler": "^3.53.1" } }, "node_modules/@cloudflare/kv-asset-handler": { @@ -318,24 +318,6 @@ "node": ">= 0.6" } }, - "node_modules/cross-env": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", - "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.1" - }, - "bin": { - "cross-env": "src/bin/cross-env.js", - "cross-env-shell": "src/bin/cross-env-shell.js" - }, - "engines": { - "node": ">=10.14", - "npm": ">=6", - "yarn": ">=1" - } - }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -1055,9 +1037,9 @@ } }, "node_modules/wrangler": { - "version": "3.53.0", - "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-3.53.0.tgz", - "integrity": "sha512-JxkvCQekL9j8Mu4CEKM/HEVyDnymWzKQuMUuJH0yum1AilutD5HAP9kVVYmvu7BvwlRyRUAj8TI5OUxXnLCEpQ==", + "version": "3.53.1", + "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-3.53.1.tgz", + "integrity": "sha512-bdMRQdHYdvowIwOhEMFkARIZUh56aDw7HLUZ/2JreBjj760osXE4Fc4L1TCkfRRBWgB6/LKF5LA4OcvORMYmHg==", "dev": true, "dependencies": { "@cloudflare/kv-asset-handler": "0.3.2", diff --git a/package.json b/package.json index ed64a4d..91ecb38 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,6 @@ "devDependencies": { "env-cmd": "^10.1.0", "get-graphql-schema": "^2.1.2", - "wrangler": "^3.53.0" + "wrangler": "^3.53.1" } } diff --git a/src/gql.rs b/src/gql.rs index 30dfab9..85c69a9 100644 --- a/src/gql.rs +++ b/src/gql.rs @@ -1,5 +1,7 @@ use std::error::Error; use graphql_client::GraphQLQuery; +use opentelemetry::{global, KeyValue}; +use opentelemetry::metrics::Unit; // The paths are relative to the directory where your `Cargo.toml` is located. // Both json and the GraphQL schema language are supported as sources for the schema @@ -29,7 +31,20 @@ pub async fn perform_my_query(variables: get_workers_analytics_query::Variables) let res = client.post("/graphql").json(&request_body).send().await?; let response: get_workers_analytics_query::ResponseData = res.json().await?; let _ = response.viewer.unwrap().accounts.iter().map(|account| account.workers_invocations_adaptive.iter().map(|worker| { - return worker.sum.as_ref().unwrap().subrequests; + let subrequests = worker.sum.as_ref().unwrap().subrequests; + let meter = global::meter("mylibraryname"); + let gauge = meter + .u64_gauge("my_gauge") + .with_description("A gauge set to 1.0") + .with_unit(Unit::new("myunit")) + .init(); + gauge.record( + subrequests, + &[ + KeyValue::new("mykey1", "myvalue1"), + KeyValue::new("mykey2", "myvalue2"), + ], + ); })); Ok(()) } diff --git a/src/lib.rs b/src/lib.rs index 24da698..7393767 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,9 +1,45 @@ +use opentelemetry::{global, KeyValue}; +use opentelemetry::metrics::{MetricsError, Unit}; +use opentelemetry_otlp::WithExportConfig; +use opentelemetry_sdk::metrics::SdkMeterProvider; +use worker::*; + mod gql; -use worker::*; +fn init_metrics() -> + core::result::Result { + let export_config = opentelemetry_otlp::ExportConfig { + endpoint: "http://localhost:4318/v1/metrics".to_string(), + ..opentelemetry_otlp::ExportConfig::default() + }; + let provider = opentelemetry_otlp::new_pipeline() + .metrics(opentelemetry_sdk::runtime::TokioCurrentThread) + .with_exporter( + opentelemetry_otlp::new_exporter() + .http() + .with_export_config(export_config), + ) + .build(); + provider +} + +fn flush_and_shutdown(provider: SdkMeterProvider) -> core::result::Result<(), MetricsError> { + provider.force_flush()?; + provider.shutdown()?; + Ok(()) +} #[event(fetch)] async fn main(_req: Request, _env: Env, _ctx: Context) -> Result { + let maybe_provider = init_metrics(); + let provider = match maybe_provider { + Ok(provider) => provider, + Err(err) => { + console_log!("{}", err.to_string()); + return Response::error("failed to init metrics", 500); + } + }; + let variables = gql::get_workers_analytics_query::Variables { account_tag: Some("".to_string()), datetime_start: Some("".to_string()), @@ -11,5 +47,43 @@ async fn main(_req: Request, _env: Env, _ctx: Context) -> Result { script_name: Some("".to_string()), }; let _ = gql::perform_my_query(variables); - Response::ok("Hello, World!") + + // Create a meter from the above MeterProvider. + let meter = global::meter("mylibraryname"); + let counter = meter.u64_counter("my_counter").init(); + counter.add( + 10, + &[ + KeyValue::new("mykey1", "myvalue1"), + KeyValue::new("mykey2", "myvalue2"), + ], + ); + + // Create a Gauge Instrument. + { + let gauge = meter + .f64_gauge("my_gauge") + .with_description("A gauge set to 1.0") + .with_unit(Unit::new("myunit")) + .init(); + + gauge.record( + 1.0, + &[ + KeyValue::new("mykey1", "myvalue1"), + KeyValue::new("mykey2", "myvalue2"), + ], + ); + } + + let res = flush_and_shutdown(provider); + match res { + Ok(_) => { + Response::ok("metrics flushed") + } + Err(err) => { + console_log!("{}", err.to_string()); + Response::error("failed to flushed", 500) + } + } }