From 6af1d3ded6bb120503f2fb265b9a0d08a8480619 Mon Sep 17 00:00:00 2001 From: Josh W Lewis Date: Thu, 21 Sep 2023 16:43:38 -0500 Subject: [PATCH 1/5] Add otel tracing via file exports to nodejs-corepack --- Cargo.lock | 307 ++++++++++++++++++++++++- Cargo.toml | 1 + buildpacks/nodejs-corepack/Cargo.toml | 1 + buildpacks/nodejs-corepack/src/main.rs | 111 +++++---- common/nodejs-utils/Cargo.toml | 3 + common/nodejs-utils/src/lib.rs | 1 + common/nodejs-utils/src/telemetry.rs | 83 +++++++ 7 files changed, 455 insertions(+), 52 deletions(-) create mode 100644 common/nodejs-utils/src/telemetry.rs diff --git a/Cargo.lock b/Cargo.lock index 321c94c9..1543c173 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,15 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + [[package]] name = "adler" version = "1.0.2" @@ -38,12 +47,38 @@ version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +[[package]] +name = "async-trait" +version = "0.1.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "backtrace" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + [[package]] name = "base64" version = "0.21.2" @@ -185,6 +220,16 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crossbeam-channel" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.16" @@ -313,6 +358,70 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" +[[package]] +name = "futures-channel" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" + +[[package]] +name = "futures-executor" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-macro" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" + +[[package]] +name = "futures-task" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" + +[[package]] +name = "futures-util" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +dependencies = [ + "futures-core", + "futures-macro", + "futures-sink", + "futures-task", + "pin-project-lite", + "pin-utils", + "slab", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -323,6 +432,23 @@ dependencies = [ "version_check", ] +[[package]] +name = "getrandom" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "gimli" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" + [[package]] name = "hashbrown" version = "0.12.3" @@ -344,6 +470,7 @@ dependencies = [ "libcnb", "libcnb-test", "libherokubuildpack", + "opentelemetry", "serde", "test_support", "thiserror", @@ -403,6 +530,9 @@ dependencies = [ "anyhow", "chrono", "node-semver", + "opentelemetry", + "opentelemetry-stdout", + "opentelemetry_sdk", "regex", "serde", "serde-xml-rs", @@ -699,12 +829,91 @@ dependencies = [ "autocfg", ] +[[package]] +name = "object" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ac5bbd07aea88c60a577a1ce218075ffd59208b2d7ca97adf9bfc5aeb21ebe" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +[[package]] +name = "opentelemetry" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9591d937bc0e6d2feb6f71a559540ab300ea49955229c347a517a28d27784c54" +dependencies = [ + "opentelemetry_api", + "opentelemetry_sdk", +] + +[[package]] +name = "opentelemetry-stdout" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bd550321bc0f9d3f6dcbfe5c75262789de5b3e2776da2cbcfd2392aa05db0c6" +dependencies = [ + "futures-util", + "opentelemetry_api", + "opentelemetry_sdk", + "ordered-float", + "serde", + "serde_json", +] + +[[package]] +name = "opentelemetry_api" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a81f725323db1b1206ca3da8bb19874bbd3f57c3bcd59471bfb04525b265b9b" +dependencies = [ + "futures-channel", + "futures-util", + "indexmap 1.9.3", + "js-sys", + "once_cell", + "pin-project-lite", + "thiserror", + "urlencoding", +] + +[[package]] +name = "opentelemetry_sdk" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa8e705a0612d48139799fcbaba0d4a90f06277153e43dd2bdc16c6f0edd8026" +dependencies = [ + "async-trait", + "crossbeam-channel", + "futures-channel", + "futures-executor", + "futures-util", + "once_cell", + "opentelemetry_api", + "ordered-float", + "percent-encoding", + "rand", + "thiserror", + "tokio", + "tokio-stream", +] + +[[package]] +name = "ordered-float" +version = "3.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a54938017eacd63036332b4ae5c8a49fc8c0c1d6d629893057e4f13609edd06" +dependencies = [ + "num-traits", +] + [[package]] name = "pathdiff" version = "0.2.1" @@ -727,12 +936,30 @@ dependencies = [ "indexmap 1.9.3", ] +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + [[package]] name = "pkg-config" version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +[[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.66" @@ -751,6 +978,36 @@ 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 = "redox_syscall" version = "0.3.5" @@ -804,6 +1061,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + [[package]] name = "rustix" version = "0.38.8" @@ -937,6 +1200,15 @@ dependencies = [ "digest", ] +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + [[package]] name = "spin" version = "0.5.2" @@ -1022,7 +1294,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" dependencies = [ "libc", - "wasi", + "wasi 0.10.0+wasi-snapshot-preview1", "winapi", ] @@ -1041,6 +1313,27 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" +[[package]] +name = "tokio" +version = "1.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9" +dependencies = [ + "backtrace", + "pin-project-lite", +] + +[[package]] +name = "tokio-stream" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + [[package]] name = "toml" version = "0.7.6" @@ -1153,6 +1446,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" @@ -1171,6 +1470,12 @@ version = "0.10.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + [[package]] name = "wasm-bindgen" version = "0.2.87" diff --git a/Cargo.toml b/Cargo.toml index 687e93f2..518e3afc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,6 +23,7 @@ indoc = "2" libcnb-test = "=0.14.0" libcnb = "=0.14.0" libherokubuildpack = "=0.14.0" +opentelemetry = "0.20.0" serde = "1" serde_json = "1" test_support = { path = "./test_support" } diff --git a/buildpacks/nodejs-corepack/Cargo.toml b/buildpacks/nodejs-corepack/Cargo.toml index 51e81401..6815a331 100644 --- a/buildpacks/nodejs-corepack/Cargo.toml +++ b/buildpacks/nodejs-corepack/Cargo.toml @@ -10,6 +10,7 @@ publish.workspace = true heroku-nodejs-utils.workspace = true libcnb.workspace = true libherokubuildpack.workspace = true +opentelemetry.workspace = true serde.workspace = true thiserror.workspace = true indoc.workspace = true diff --git a/buildpacks/nodejs-corepack/src/main.rs b/buildpacks/nodejs-corepack/src/main.rs index d5dc0b38..974aea55 100644 --- a/buildpacks/nodejs-corepack/src/main.rs +++ b/buildpacks/nodejs-corepack/src/main.rs @@ -4,6 +4,7 @@ #![allow(clippy::module_name_repetitions)] use heroku_nodejs_utils::package_json::{PackageJson, PackageJsonError}; +use heroku_nodejs_utils::telemetry::init_tracer; use layers::{ManagerLayer, ShimLayer}; use libcnb::build::{BuildContext, BuildResult, BuildResultBuilder}; use libcnb::data::build_plan::BuildPlanBuilder; @@ -14,6 +15,8 @@ use libcnb::generic::GenericPlatform; use libcnb::layer_env::Scope; use libcnb::{buildpack_main, Buildpack, Env}; use libherokubuildpack::log::log_header; +use opentelemetry::global; +use opentelemetry::trace::Tracer; #[cfg(test)] use libcnb_test as _; @@ -37,60 +40,66 @@ impl Buildpack for CorepackBuildpack { fn detect(&self, context: DetectContext) -> libcnb::Result { // Corepack requires the `packageManager` key from `package.json`. // This buildpack won't be detected without it. - let pkg_json_path = context.app_dir.join("package.json"); - if pkg_json_path.exists() { - let pkg_json = - PackageJson::read(pkg_json_path).map_err(CorepackBuildpackError::PackageJson)?; - cfg::get_supported_package_manager(&pkg_json).map_or_else( - || DetectResultBuilder::fail().build(), - |pkg_mgr| { - DetectResultBuilder::pass() - .build_plan( - BuildPlanBuilder::new() - .requires("node") - .requires(&pkg_mgr) - .provides(pkg_mgr) - .build(), - ) - .build() - }, - ) - } else { - DetectResultBuilder::fail().build() - } + let tracer = init_tracer(format!("{}", context.buildpack_descriptor.buildpack.id)); + tracer.in_span("nodejs-corepack-detect", |_cx| { + let pkg_json_path = context.app_dir.join("package.json"); + if pkg_json_path.exists() { + let pkg_json = PackageJson::read(pkg_json_path) + .map_err(CorepackBuildpackError::PackageJson)?; + cfg::get_supported_package_manager(&pkg_json).map_or_else( + || DetectResultBuilder::fail().build(), + |pkg_mgr| { + DetectResultBuilder::pass() + .build_plan( + BuildPlanBuilder::new() + .requires("node") + .requires(&pkg_mgr) + .provides(pkg_mgr) + .build(), + ) + .build() + }, + ) + } else { + DetectResultBuilder::fail().build() + } + }) } fn build(&self, context: BuildContext) -> libcnb::Result { - let pkg_mgr = PackageJson::read(context.app_dir.join("package.json")) - .map_err(CorepackBuildpackError::PackageJson)? - .package_manager - .ok_or(CorepackBuildpackError::PackageManagerMissing)?; - - let env = &Env::from_current(); - - let corepack_version = - cmd::corepack_version(env).map_err(CorepackBuildpackError::CorepackVersion)?; - - log_header(format!( - "Installing {} {} via corepack {corepack_version}", - pkg_mgr.name, pkg_mgr.version - )); - - let shims_layer = - context.handle_layer(layer_name!("shim"), ShimLayer { corepack_version })?; - cmd::corepack_enable(&pkg_mgr.name, &shims_layer.path.join("bin"), env) - .map_err(CorepackBuildpackError::CorepackEnable)?; - - let mgr_layer = context.handle_layer( - layer_name!("mgr"), - ManagerLayer { - package_manager: pkg_mgr, - }, - )?; - let mgr_env = mgr_layer.env.apply(Scope::Build, env); - cmd::corepack_prepare(&mgr_env).map_err(CorepackBuildpackError::CorepackPrepare)?; - - BuildResultBuilder::new().build() + let tracer = init_tracer(format!("{}", context.buildpack_descriptor.buildpack.id)); + tracer.in_span("nodejs-corepack-build", |_cx| { + let pkg_mgr = PackageJson::read(context.app_dir.join("package.json")) + .map_err(CorepackBuildpackError::PackageJson)? + .package_manager + .ok_or(CorepackBuildpackError::PackageManagerMissing)?; + + let env = &Env::from_current(); + + let corepack_version = + cmd::corepack_version(env).map_err(CorepackBuildpackError::CorepackVersion)?; + + log_header(format!( + "Installing {} {} via corepack {corepack_version}", + pkg_mgr.name, pkg_mgr.version + )); + + let shims_layer = + context.handle_layer(layer_name!("shim"), ShimLayer { corepack_version })?; + cmd::corepack_enable(&pkg_mgr.name, &shims_layer.path.join("bin"), env) + .map_err(CorepackBuildpackError::CorepackEnable)?; + + let mgr_layer = context.handle_layer( + layer_name!("mgr"), + ManagerLayer { + package_manager: pkg_mgr, + }, + )?; + let mgr_env = mgr_layer.env.apply(Scope::Build, env); + cmd::corepack_prepare(&mgr_env).map_err(CorepackBuildpackError::CorepackPrepare)?; + + BuildResultBuilder::new().build() + }) } fn on_error(&self, err: libcnb::Error) { diff --git a/common/nodejs-utils/Cargo.toml b/common/nodejs-utils/Cargo.toml index 1709908f..a9a0cf4f 100644 --- a/common/nodejs-utils/Cargo.toml +++ b/common/nodejs-utils/Cargo.toml @@ -18,6 +18,9 @@ thiserror.workspace = true toml.workspace = true ureq = { workspace = true, features = ["json"] } url = "2" +opentelemetry.workspace = true +opentelemetry-stdout = { version = "0.1.0", features = ["trace"] } +opentelemetry_sdk = { version = "0.20.0", features = ["trace", "rt-tokio"] } [dev-dependencies] tempfile.workspace = true diff --git a/common/nodejs-utils/src/lib.rs b/common/nodejs-utils/src/lib.rs index b543fc84..73f1b0fb 100644 --- a/common/nodejs-utils/src/lib.rs +++ b/common/nodejs-utils/src/lib.rs @@ -9,4 +9,5 @@ mod nodejs_org; mod npmjs_org; pub mod package_json; mod s3; +pub mod telemetry; pub mod vrs; diff --git a/common/nodejs-utils/src/telemetry.rs b/common/nodejs-utils/src/telemetry.rs new file mode 100644 index 00000000..841f5615 --- /dev/null +++ b/common/nodejs-utils/src/telemetry.rs @@ -0,0 +1,83 @@ +use std::{ + fs::{create_dir_all, File}, + path::Path, +}; + +use opentelemetry::{ + global::{self, BoxedTracer}, + KeyValue, +}; +use opentelemetry_sdk::{ + trace::{Config, TracerProvider}, + Resource, +}; + +pub fn init_tracer(buildpack_name: String) -> BoxedTracer { + let buildpack_file_name = buildpack_name.replace('/', "_"); + let telemetry_file_path = Path::new("/tmp") + .join("cnb-telemetry") + .join(format!("{buildpack_file_name}.jsonl")); + if let Some(pd) = telemetry_file_path.parent() { + let _ = create_dir_all(pd); + } + let telemetry_writer = File::create(telemetry_file_path); + let exporter = match telemetry_writer { + Ok(f) => opentelemetry_stdout::SpanExporter::builder() + .with_writer(f) + .build(), + Err(_) => opentelemetry_stdout::SpanExporter::default(), + }; + let provider = TracerProvider::builder() + .with_config( + Config::default().with_resource(Resource::new(vec![KeyValue::new( + "service.name", + buildpack_name.clone(), + )])), + ) + .with_simple_exporter(exporter) + .build(); + global::set_tracer_provider(provider); + global::tracer(buildpack_name) +} + +#[cfg(test)] +mod tests { + use std::fs::{self}; + + use super::init_tracer; + use opentelemetry::{global, trace::TraceContextExt, trace::Tracer}; + + #[test] + fn test_tracer_writes_span_file() -> Result<(), String> { + let buildpack_name = "heroku_test_buildpack"; + let test_span_name = "test_span_1"; + let test_event_name = "test_event_1"; + let telemetry_file_path = format!("/tmp/cnb-telemetry/{buildpack_name}.jsonl"); + + let _ = fs::remove_file(&telemetry_file_path); + + init_tracer(buildpack_name.to_string()); + let tracer = global::tracer(""); + tracer.in_span(test_span_name, |cx| { + cx.span().add_event(test_event_name, Vec::new()); + }); + global::shutdown_tracer_provider(); + let contents = fs::read_to_string(telemetry_file_path) + .expect("expected to read existing telemetry file"); + println!("{contents}"); + + if !contents.contains(buildpack_name) { + Err("File export did not include buildpack name")?; + } + + if !contents.contains(test_span_name) { + Err("File export did not include test span")?; + } + + if !contents.contains(test_event_name) { + Err("File export did not include test event")?; + } + + Ok(()) + } +} From d36460ff46d1a332e206c178cee1831e3f54cffc Mon Sep 17 00:00:00 2001 From: Josh W Lewis Date: Thu, 21 Sep 2023 16:51:04 -0500 Subject: [PATCH 2/5] Drop tokio features --- Cargo.lock | 68 -------------------------- buildpacks/nodejs-corepack/src/main.rs | 1 - common/nodejs-utils/Cargo.toml | 2 +- 3 files changed, 1 insertion(+), 70 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1543c173..461dc61b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,15 +2,6 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -dependencies = [ - "gimli", -] - [[package]] name = "adler" version = "1.0.2" @@ -64,21 +55,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" -[[package]] -name = "backtrace" -version = "0.3.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - [[package]] name = "base64" version = "0.21.2" @@ -443,12 +419,6 @@ dependencies = [ "wasi 0.11.0+wasi-snapshot-preview1", ] -[[package]] -name = "gimli" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" - [[package]] name = "hashbrown" version = "0.12.3" @@ -829,15 +799,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "object" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ac5bbd07aea88c60a577a1ce218075ffd59208b2d7ca97adf9bfc5aeb21ebe" -dependencies = [ - "memchr", -] - [[package]] name = "once_cell" version = "1.18.0" @@ -901,8 +862,6 @@ dependencies = [ "percent-encoding", "rand", "thiserror", - "tokio", - "tokio-stream", ] [[package]] @@ -1061,12 +1020,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "rustc-demangle" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" - [[package]] name = "rustix" version = "0.38.8" @@ -1313,27 +1266,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" -[[package]] -name = "tokio" -version = "1.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9" -dependencies = [ - "backtrace", - "pin-project-lite", -] - -[[package]] -name = "tokio-stream" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" -dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", -] - [[package]] name = "toml" version = "0.7.6" diff --git a/buildpacks/nodejs-corepack/src/main.rs b/buildpacks/nodejs-corepack/src/main.rs index 974aea55..343efeef 100644 --- a/buildpacks/nodejs-corepack/src/main.rs +++ b/buildpacks/nodejs-corepack/src/main.rs @@ -15,7 +15,6 @@ use libcnb::generic::GenericPlatform; use libcnb::layer_env::Scope; use libcnb::{buildpack_main, Buildpack, Env}; use libherokubuildpack::log::log_header; -use opentelemetry::global; use opentelemetry::trace::Tracer; #[cfg(test)] diff --git a/common/nodejs-utils/Cargo.toml b/common/nodejs-utils/Cargo.toml index a9a0cf4f..1d959c12 100644 --- a/common/nodejs-utils/Cargo.toml +++ b/common/nodejs-utils/Cargo.toml @@ -20,7 +20,7 @@ ureq = { workspace = true, features = ["json"] } url = "2" opentelemetry.workspace = true opentelemetry-stdout = { version = "0.1.0", features = ["trace"] } -opentelemetry_sdk = { version = "0.20.0", features = ["trace", "rt-tokio"] } +opentelemetry_sdk = { version = "0.20.0", features = ["trace"] } [dev-dependencies] tempfile.workspace = true From 41f3b3ae95f83f4ef3b1ee94207b0be44f0dc3a1 Mon Sep 17 00:00:00 2001 From: Josh W Lewis Date: Thu, 21 Sep 2023 17:21:34 -0500 Subject: [PATCH 3/5] Add attributes to nodejs-corepack-build span --- buildpacks/nodejs-corepack/src/main.rs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/buildpacks/nodejs-corepack/src/main.rs b/buildpacks/nodejs-corepack/src/main.rs index 343efeef..a933b469 100644 --- a/buildpacks/nodejs-corepack/src/main.rs +++ b/buildpacks/nodejs-corepack/src/main.rs @@ -15,7 +15,8 @@ use libcnb::generic::GenericPlatform; use libcnb::layer_env::Scope; use libcnb::{buildpack_main, Buildpack, Env}; use libherokubuildpack::log::log_header; -use opentelemetry::trace::Tracer; +use opentelemetry::trace::{TraceContextExt, Tracer}; +use opentelemetry::KeyValue; #[cfg(test)] use libcnb_test as _; @@ -67,17 +68,27 @@ impl Buildpack for CorepackBuildpack { fn build(&self, context: BuildContext) -> libcnb::Result { let tracer = init_tracer(format!("{}", context.buildpack_descriptor.buildpack.id)); - tracer.in_span("nodejs-corepack-build", |_cx| { + tracer.in_span("nodejs-corepack-build", |cx| { let pkg_mgr = PackageJson::read(context.app_dir.join("package.json")) .map_err(CorepackBuildpackError::PackageJson)? .package_manager .ok_or(CorepackBuildpackError::PackageManagerMissing)?; + cx.span().set_attributes([ + KeyValue::new("package_manager.name", pkg_mgr.name.clone()), + KeyValue::new("package_manager.version", pkg_mgr.version.to_string()), + ]); + let env = &Env::from_current(); let corepack_version = cmd::corepack_version(env).map_err(CorepackBuildpackError::CorepackVersion)?; + cx.span().set_attribute(KeyValue::new( + "corepack.version", + corepack_version.to_string(), + )); + log_header(format!( "Installing {} {} via corepack {corepack_version}", pkg_mgr.name, pkg_mgr.version From 070bc2d432003a8e025264c3db1f7170b8a6d972 Mon Sep 17 00:00:00 2001 From: Josh W Lewis Date: Fri, 22 Sep 2023 14:22:32 -0500 Subject: [PATCH 4/5] Add changelog entry for telemetry --- buildpacks/nodejs-corepack/CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/buildpacks/nodejs-corepack/CHANGELOG.md b/buildpacks/nodejs-corepack/CHANGELOG.md index 0e0d76db..19e2145c 100644 --- a/buildpacks/nodejs-corepack/CHANGELOG.md +++ b/buildpacks/nodejs-corepack/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +- Add basic OpenTelemetry tracing. ([#652](https://github.com/heroku/buildpacks-nodejs/pull/652)) + ## [1.1.5] - 2023-09-19 - No changes. From a65206fe0abf1108fdf62b527e97b16664628e29 Mon Sep 17 00:00:00 2001 From: Josh W Lewis Date: Fri, 22 Sep 2023 14:22:51 -0500 Subject: [PATCH 5/5] init_tracer accepts an Into now --- buildpacks/nodejs-corepack/src/main.rs | 8 ++++---- common/nodejs-utils/src/telemetry.rs | 19 +++++++++---------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/buildpacks/nodejs-corepack/src/main.rs b/buildpacks/nodejs-corepack/src/main.rs index a933b469..1fc8afc6 100644 --- a/buildpacks/nodejs-corepack/src/main.rs +++ b/buildpacks/nodejs-corepack/src/main.rs @@ -38,10 +38,10 @@ impl Buildpack for CorepackBuildpack { type Error = CorepackBuildpackError; fn detect(&self, context: DetectContext) -> libcnb::Result { - // Corepack requires the `packageManager` key from `package.json`. - // This buildpack won't be detected without it. - let tracer = init_tracer(format!("{}", context.buildpack_descriptor.buildpack.id)); + let tracer = init_tracer(context.buildpack_descriptor.buildpack.id.to_string()); tracer.in_span("nodejs-corepack-detect", |_cx| { + // Corepack requires the `packageManager` key from `package.json`. + // This buildpack won't be detected without it. let pkg_json_path = context.app_dir.join("package.json"); if pkg_json_path.exists() { let pkg_json = PackageJson::read(pkg_json_path) @@ -67,7 +67,7 @@ impl Buildpack for CorepackBuildpack { } fn build(&self, context: BuildContext) -> libcnb::Result { - let tracer = init_tracer(format!("{}", context.buildpack_descriptor.buildpack.id)); + let tracer = init_tracer(context.buildpack_descriptor.buildpack.id.to_string()); tracer.in_span("nodejs-corepack-build", |cx| { let pkg_mgr = PackageJson::read(context.app_dir.join("package.json")) .map_err(CorepackBuildpackError::PackageJson)? diff --git a/common/nodejs-utils/src/telemetry.rs b/common/nodejs-utils/src/telemetry.rs index 841f5615..e8bb0bf5 100644 --- a/common/nodejs-utils/src/telemetry.rs +++ b/common/nodejs-utils/src/telemetry.rs @@ -12,16 +12,15 @@ use opentelemetry_sdk::{ Resource, }; -pub fn init_tracer(buildpack_name: String) -> BoxedTracer { - let buildpack_file_name = buildpack_name.replace('/', "_"); - let telemetry_file_path = Path::new("/tmp") +pub fn init_tracer(buildpack_name: impl Into) -> BoxedTracer { + let bp_name = buildpack_name.into(); + let telem_file_path = Path::new("/tmp") .join("cnb-telemetry") - .join(format!("{buildpack_file_name}.jsonl")); - if let Some(pd) = telemetry_file_path.parent() { - let _ = create_dir_all(pd); + .join(format!("{}.jsonl", bp_name.replace('/', "_"))); + if let Some(parent_dir) = telem_file_path.parent() { + let _ = create_dir_all(parent_dir); } - let telemetry_writer = File::create(telemetry_file_path); - let exporter = match telemetry_writer { + let exporter = match File::create(telem_file_path) { Ok(f) => opentelemetry_stdout::SpanExporter::builder() .with_writer(f) .build(), @@ -31,13 +30,13 @@ pub fn init_tracer(buildpack_name: String) -> BoxedTracer { .with_config( Config::default().with_resource(Resource::new(vec![KeyValue::new( "service.name", - buildpack_name.clone(), + bp_name.clone(), )])), ) .with_simple_exporter(exporter) .build(); global::set_tracer_provider(provider); - global::tracer(buildpack_name) + global::tracer(bp_name) } #[cfg(test)]