diff --git a/CHANGELOG.md b/CHANGELOG.md index 38c8121..a3c4b49 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +# 0.4.0 + +- Switched to native OpenTelemetry for wide compatibility. +- `service.name` is now set in the `OTEL_SERVICE_NAME`. +- String, Boolean and Number attributes are supported. + # 0.3.0 - `service.name` must be sent vs `service_name` now for consistency diff --git a/Cargo.lock b/Cargo.lock index 71599f4..f596fab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -38,6 +38,28 @@ version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +[[package]] +name = "async-stream" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" +dependencies = [ + "async-stream-impl", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + [[package]] name = "async-trait" version = "0.1.80" @@ -46,7 +68,7 @@ checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.68", ] [[package]] @@ -55,6 +77,34 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +[[package]] +name = "axum" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" +dependencies = [ + "async-trait", + "axum-core 0.3.4", + "bitflags 1.3.2", + "bytes", + "futures-util", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.29", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "sync_wrapper 0.1.2", + "tower", + "tower-layer", + "tower-service", +] + [[package]] name = "axum" version = "0.7.5" @@ -62,7 +112,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" dependencies = [ "async-trait", - "axum-core", + "axum-core 0.4.3", "bytes", "futures-util", "http 1.1.0", @@ -89,6 +139,23 @@ dependencies = [ "tracing", ] +[[package]] +name = "axum-core" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http 0.2.12", + "http-body 0.4.6", + "mime", + "rustversion", + "tower-layer", + "tower-service", +] + [[package]] name = "axum-core" version = "0.4.3" @@ -177,24 +244,10 @@ dependencies = [ "iana-time-zone", "js-sys", "num-traits", - "serde", "wasm-bindgen", "windows-targets 0.52.5", ] -[[package]] -name = "console" -version = "0.15.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" -dependencies = [ - "encode_unicode", - "lazy_static", - "libc", - "unicode-width", - "windows-sys 0.52.0", -] - [[package]] name = "core-foundation" version = "0.9.4" @@ -233,19 +286,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" [[package]] -name = "encode_unicode" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" - -[[package]] -name = "encoding_rs" -version = "0.8.34" +name = "either" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" -dependencies = [ - "cfg-if", -] +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "equivalent" @@ -253,43 +297,12 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" -[[package]] -name = "errno" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "fastrand" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" - [[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "form_urlencoded" version = "1.2.1" @@ -355,7 +368,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.68", ] [[package]] @@ -417,13 +430,19 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap", + "indexmap 2.2.6", "slab", "tokio", "tokio-util", "tracing", ] +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "hashbrown" version = "0.14.5" @@ -436,22 +455,6 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" -[[package]] -name = "honeycomb-client" -version = "0.2.2" -source = "git+https://github.com/jerbly/honeycomb-client?tag=0.2.2#def7ae2ac0ce0fd5667e798b2bfea1e26bcbe65e" -dependencies = [ - "anyhow", - "chrono", - "futures", - "indicatif", - "openssl", - "reqwest", - "serde", - "serde_json", - "tokio", -] - [[package]] name = "http" version = "0.2.12" @@ -564,16 +567,15 @@ dependencies = [ ] [[package]] -name = "hyper-tls" -version = "0.5.0" +name = "hyper-timeout" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" dependencies = [ - "bytes", "hyper 0.14.29", - "native-tls", + "pin-project-lite", "tokio", - "tokio-native-tls", + "tokio-io-timeout", ] [[package]] @@ -615,13 +617,13 @@ dependencies = [ ] [[package]] -name = "idna" -version = "0.5.0" +name = "indexmap" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "autocfg", + "hashbrown 0.12.3", ] [[package]] @@ -631,37 +633,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.14.5", ] [[package]] -name = "indicatif" -version = "0.17.8" +name = "itertools" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "763a5a8f45087d6bcea4222e7b72c291a054edf80e4ef6efd2a4979878c7bea3" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" dependencies = [ - "console", - "instant", - "number_prefix", - "portable-atomic", - "unicode-width", -] - -[[package]] -name = "instant" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" -dependencies = [ - "cfg-if", + "either", ] -[[package]] -name = "ipnet" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" - [[package]] name = "itoa" version = "1.0.11" @@ -677,24 +660,12 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - [[package]] name = "libc" version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" -[[package]] -name = "linux-raw-sys" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" - [[package]] name = "lock_api" version = "0.4.12" @@ -749,23 +720,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "native-tls" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" -dependencies = [ - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - [[package]] name = "num-traits" version = "0.2.19" @@ -785,12 +739,6 @@ dependencies = [ "libc", ] -[[package]] -name = "number_prefix" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" - [[package]] name = "object" version = "0.36.1" @@ -806,32 +754,6 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" -[[package]] -name = "openssl" -version = "0.10.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" -dependencies = [ - "bitflags 2.6.0", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "openssl-probe" version = "0.1.5" @@ -839,62 +761,72 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] -name = "openssl-src" -version = "300.3.1+3.3.1" +name = "opentelemetry" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7259953d42a81bf137fbbd73bd30a8e1914d6dce43c2b90ed575783a22608b91" +checksum = "1e32339a5dc40459130b3bd269e9892439f55b33e772d2a9d402a789baaf4e8a" dependencies = [ - "cc", + "futures-core", + "futures-sink", + "indexmap 2.2.6", + "js-sys", + "once_cell", + "pin-project-lite", + "thiserror", + "urlencoding", ] [[package]] -name = "openssl-sys" -version = "0.9.102" +name = "opentelemetry-otlp" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" +checksum = "f24cda83b20ed2433c68241f918d0f6fdec8b1d43b7a9590ab4420c5095ca930" dependencies = [ - "cc", - "libc", - "openssl-src", - "pkg-config", - "vcpkg", + "async-trait", + "futures-core", + "http 0.2.12", + "opentelemetry", + "opentelemetry-proto", + "opentelemetry-semantic-conventions 0.13.0", + "opentelemetry_sdk", + "prost", + "thiserror", + "tokio", + "tonic", ] [[package]] -name = "opentelemetry" -version = "0.22.0" +name = "opentelemetry-proto" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900d57987be3f2aeb70d385fff9b27fb74c5723cc9a52d904d4f9c807a0667bf" +checksum = "a2e155ce5cc812ea3d1dffbd1539aed653de4bf4882d60e6e04dcf0901d674e1" dependencies = [ - "futures-core", - "futures-sink", - "js-sys", - "once_cell", - "pin-project-lite", - "thiserror", - "urlencoding", + "opentelemetry", + "opentelemetry_sdk", + "prost", + "tonic", ] [[package]] -name = "opentelemetry-stdout" -version = "0.3.0" +name = "opentelemetry-semantic-conventions" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bdf28b381f23afcd150afc0b38a4183dd321fc96320c1554752b6b761648f78" +checksum = "f5774f1ef1f982ef2a447f6ee04ec383981a3ab99c8e77a1a7b30182e65bbc84" dependencies = [ - "chrono", - "futures-util", "opentelemetry", - "opentelemetry_sdk", - "ordered-float", - "serde", - "serde_json", ] +[[package]] +name = "opentelemetry-semantic-conventions" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9ab5bd6c42fb9349dcf28af2ba9a0667f697f9bdcca045d39f2cec5543e2910" + [[package]] name = "opentelemetry_sdk" -version = "0.22.1" +version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e90c7113be649e31e9a0f8b5ee24ed7a16923b322c3c5ab6367469c049d6b7e" +checksum = "2f16aec8a98a457a52664d69e0091bac3a0abd18ead9b641cb00202ba4e0efe4" dependencies = [ "async-trait", "crossbeam-channel", @@ -907,6 +839,8 @@ dependencies = [ "percent-encoding", "rand", "thiserror", + "tokio", + "tokio-stream", ] [[package]] @@ -964,7 +898,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.68", ] [[package]] @@ -979,18 +913,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" -[[package]] -name = "pkg-config" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" - -[[package]] -name = "portable-atomic" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" - [[package]] name = "ppv-lite86" version = "0.2.17" @@ -1006,6 +928,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", + "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", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "quote" version = "1.0.36" @@ -1055,43 +1000,18 @@ dependencies = [ ] [[package]] -name = "reqwest" -version = "0.11.27" +name = "ring" +version = "0.17.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ - "base64", - "bytes", - "encoding_rs", - "futures-core", - "futures-util", - "h2", - "http 0.2.12", - "http-body 0.4.6", - "hyper 0.14.29", - "hyper-tls", - "ipnet", - "js-sys", - "log", - "mime", - "native-tls", - "once_cell", - "percent-encoding", - "pin-project-lite", - "rustls-pemfile", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper 0.1.2", - "system-configuration", - "tokio", - "tokio-native-tls", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "winreg", + "cc", + "cfg-if", + "getrandom", + "libc", + "spin", + "untrusted", + "windows-sys 0.52.0", ] [[package]] @@ -1101,16 +1021,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] -name = "rustix" -version = "0.38.34" +name = "rustls" +version = "0.21.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ - "bitflags 2.6.0", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.52.0", + "log", + "ring", + "rustls-webpki", + "sct", +] + +[[package]] +name = "rustls-native-certs" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" +dependencies = [ + "openssl-probe", + "rustls-pemfile", + "schannel", + "security-framework", ] [[package]] @@ -1122,6 +1053,16 @@ dependencies = [ "base64", ] +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "rustversion" version = "1.0.17" @@ -1149,6 +1090,16 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "sct" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "security-framework" version = "2.11.0" @@ -1189,7 +1140,7 @@ checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.68", ] [[package]] @@ -1259,6 +1210,23 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "syn" version = "2.0.68" @@ -1282,55 +1250,23 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" -[[package]] -name = "system-configuration" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "system-configuration-sys", -] - -[[package]] -name = "system-configuration-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "tempfile" -version = "3.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" -dependencies = [ - "cfg-if", - "fastrand", - "rustix", - "windows-sys 0.52.0", -] - [[package]] name = "testevents" -version = "0.3.0" +version = "0.4.0" dependencies = [ "anyhow", - "axum", + "axum 0.7.5", "chrono", "dotenv", "futures", - "honeycomb-client", "opentelemetry", - "opentelemetry-stdout", + "opentelemetry-otlp", + "opentelemetry-semantic-conventions 0.14.0", "opentelemetry_sdk", "serde", "serde_json", "tokio", + "tonic", ] [[package]] @@ -1350,24 +1286,9 @@ checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.68", ] -[[package]] -name = "tinyvec" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c55115c6fbe2d2bef26eb09ad74bde02d8255476fc0c7b515ef09fbb35742d82" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - [[package]] name = "tokio" version = "1.38.0" @@ -1387,6 +1308,16 @@ dependencies = [ "windows-sys 0.48.0", ] +[[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", + "tokio", +] + [[package]] name = "tokio-macros" version = "2.3.0" @@ -1395,16 +1326,27 @@ checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.68", ] [[package]] -name = "tokio-native-tls" -version = "0.3.1" +name = "tokio-rustls" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "native-tls", + "rustls", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" +dependencies = [ + "futures-core", + "pin-project-lite", "tokio", ] @@ -1421,6 +1363,38 @@ dependencies = [ "tokio", ] +[[package]] +name = "tonic" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3082666a3a6433f7f511c7192923fa1fe07c69332d3c6a2e6bb040b569199d5a" +dependencies = [ + "async-stream", + "async-trait", + "axum 0.6.20", + "base64", + "bytes", + "futures-core", + "futures-util", + "h2", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.29", + "hyper-timeout", + "percent-encoding", + "pin-project", + "prost", + "rustls-native-certs", + "rustls-pemfile", + "tokio", + "tokio-rustls", + "tokio-stream", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + [[package]] name = "tower" version = "0.4.13" @@ -1429,9 +1403,13 @@ checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" dependencies = [ "futures-core", "futures-util", + "indexmap 1.9.3", "pin-project", "pin-project-lite", + "rand", + "slab", "tokio", + "tokio-util", "tower-layer", "tower-service", "tracing", @@ -1457,9 +1435,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.68", +] + [[package]] name = "tracing-core" version = "0.1.32" @@ -1475,12 +1465,6 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" -[[package]] -name = "unicode-bidi" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" - [[package]] name = "unicode-ident" version = "1.0.12" @@ -1488,30 +1472,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] -name = "unicode-normalization" -version = "0.1.23" +name = "untrusted" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "unicode-width" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" - -[[package]] -name = "url" -version = "2.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", -] +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "urlencoding" @@ -1519,12 +1483,6 @@ version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - [[package]] name = "want" version = "0.3.1" @@ -1561,22 +1519,10 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn", + "syn 2.0.68", "wasm-bindgen-shared", ] -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - [[package]] name = "wasm-bindgen-macro" version = "0.2.92" @@ -1595,7 +1541,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.68", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -1606,16 +1552,6 @@ version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" -[[package]] -name = "web-sys" -version = "0.3.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - [[package]] name = "windows-core" version = "0.52.0" @@ -1763,13 +1699,3 @@ name = "windows_x86_64_msvc" version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" - -[[package]] -name = "winreg" -version = "0.50.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] diff --git a/Cargo.toml b/Cargo.toml index 9672655..13a5869 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "testevents" -version = "0.3.0" +version = "0.4.0" edition = "2021" authors = ["Jeremy Blythe "] repository = "https://github.com/jerbly/testevents" @@ -10,11 +10,11 @@ anyhow = "1.0.86" axum = "0.7.5" chrono = "0.4.38" futures = "0.3.30" -honeycomb-client = { git = "https://github.com/jerbly/honeycomb-client", tag = "0.2.2" } -# honeycomb-client = { path = "../honeycomb-client" } -opentelemetry = "0.22" -opentelemetry_sdk = "0.22" -opentelemetry-stdout = { version = "0.3", features = ["trace"] } +opentelemetry = "0.21.0" +opentelemetry_sdk = { version = "0.21.2", features = ["rt-tokio"] } +opentelemetry-semantic-conventions = "0.14" +opentelemetry-otlp = { version = "0.14", features = ["tls", "tls-roots"] } +tonic = { version = "0.9.2" } serde = { version = "1.0.203", features = ["derive"] } serde_json = "1.0.120" tokio = { version = "1.38.0", features = ["full"] } diff --git a/README.md b/README.md index 196e408..eaf0f9e 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ # testevents -A service to make it easier to create Honeycomb spans in some restricted environments. Similar to [buildevents](https://github.com/honeycombio/buildevents/tree/main) but a simple RESTful server. This is useful when you can't execute a binary but need a way to open and close OpenTelemetry compatible spans. Low-code testing tools are a good use case. +A service to make it easier to create OpenTelemetry spans in some restricted environments. Similar to [buildevents](https://github.com/honeycombio/buildevents/tree/main) but a simple RESTful server. This is useful when you can't execute a binary but need a way to open and close OpenTelemetry spans. Low-code testing tools are a good use case. -**testevents** wraps the Honeycomb [Create Events API](https://docs.honeycomb.io/api/tag/Events#operation/createEvents) with an in-memory store, keyed on `trace_id` and `span_id`. When you open a span you provide a TTL. If you don't close it in time, say your script crashed, it will "close" the span with an error stating that the TTL ran out. +**testevents** has an in-memory store keyed on `trace_id` and `span_id`. When you open a span you provide a TTL. If you don't close it in time, say your script crashed, it will "close" the span with an error stating that the TTL ran out. **testevents** uses the OpenTelemetry library to create the `trace_id` and `span_id` ensuring downstream compatibility. A [`traceparent`](https://www.w3.org/TR/trace-context/#traceparent-header-field-values) is returned from `POST` operations that can be used in subsequent http calls for distributed tracing. -Spans are "closed" with a `DELETE` to `/{trace_id}/{span_id}/` - this creates the Honeycomb event with a calculated `duration_ms` from the "open" call. +Spans are "closed" with a `DELETE` to `/{trace_id}/{span_id}/` - this creates the span with a calculated `duration_ms` from the "open" call. `PATCH` to `/{trace_id}/{span_id}/` can be used to merge a set of key-values into the "open" span. Existing keys will have their values overwritten. You can change the `ttl` to extend or shorten the time to expiry. e.g. patching 10000 to a span that has been running for 34125ms will set the ttl to 44125. @@ -29,10 +29,20 @@ cargo build --release ### Environment variables / `.env` file entries -You must provide `HONEYCOMB_API_KEY`. This api key must have access to create datasets. An ingest key is ideal. +_(See [`example_env.txt`](example_env.txt) for an example `.env` file)_ + +You must provide `OTEL_EXPORTER_OTLP_ENDPOINT`. For example `http://localhost:4317`. + +For Honeycomb `OTEL_EXPORTER_OTLP_ENDPOINT="https://api.honeycomb.io"`. You must also provide `HONEYCOMB_API_KEY`. An ingest key is ideal. + +Provide `OTEL_SERVICE_NAME` to set the `service.name` for every span produced by **testevents** e.g. `my-test-automation`. Defaults to: `testevents`. Provide `TESTEVENTS_PORT` to bind to an alternative from the default `3003`. +Run `test.sh` to check your setup. This will create an output like this in [otel-desktop-viewer](https://github.com/CtrlSpice/otel-desktop-viewer/tree/v0.1.4): + +![otel-desktop-viewer test trace](otel-trace.png) + ### Example Make a root span: @@ -41,8 +51,7 @@ Make a root span: curl -i -X POST \ 'http://127.0.0.1:3003/' \ -H 'Content-Type: application/json' \ - -d '{"service.name":"jerbly-test", - "name":"test", + -d '{"name":"test", "hello":"world", "ttl":600000}' @@ -60,8 +69,7 @@ Make a child span: curl -i -X POST \ 'http://127.0.0.1:3003/4c278c122e123f87036b44772861b9f4/5370f70191c4b03c/' \ -H 'Content-Type: application/json' \ - -d '{"service.name":"jerbly-test", - "name":"test_child", + -d '{"name":"test_child", "hello":"child span", "ttl":600000}' @@ -101,6 +109,6 @@ date: Thu, 11 Jul 2024 11:07:38 GMT {"message":"OK"} ``` -Gives this trace: +Gives this trace in [Honeycomb](https://honeycomb.io): ![a screenshot showing the trace](trace.png "Trace screenshot") diff --git a/example_env.txt b/example_env.txt new file mode 100644 index 0000000..8a9ca56 --- /dev/null +++ b/example_env.txt @@ -0,0 +1,11 @@ +# This is an example env file. Copy the contents into your own .env file or export each variable. + +OTEL_SERVICE_NAME="my-test-automation" + +OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4317" + +# Honeycomb +#OTEL_EXPORTER_OTLP_ENDPOINT="https://api.honeycomb.io" +#HONEYCOMB_API_KEY=ingest_api_key + +TESTEVENTS_PORT=3003 \ No newline at end of file diff --git a/otel-trace.png b/otel-trace.png new file mode 100644 index 0000000..fdfb4ea Binary files /dev/null and b/otel-trace.png differ diff --git a/src/main.rs b/src/main.rs index c956fb6..35ebd1d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,9 +2,11 @@ mod span_store; use std::{ collections::HashMap, + env, sync::{Arc, RwLock}, }; +use anyhow::Context; use axum::{ extract::{Path, State}, http::StatusCode, @@ -12,19 +14,70 @@ use axum::{ routing::{delete, patch, post}, Json, Router, }; -use honeycomb_client::honeycomb::HoneyComb; use serde_json::{json, Value}; -use opentelemetry_sdk::trace::TracerProvider; - -use span_store::{HoneycombEvent, QueryAttributes, SpanAttributes, SpanStore}; +use span_store::{QueryAttributes, SpanAttributes, SpanStore}; use tokio::sync::mpsc; +use opentelemetry::{ + global::{self}, + trace::{Span, SpanContext, SpanKind, TraceContextExt, TraceFlags, TraceState}, +}; +use opentelemetry::{trace::Tracer, KeyValue}; +use opentelemetry_otlp::TonicExporterBuilder; +use opentelemetry_sdk::trace::{Config, IdGenerator, RandomIdGenerator}; +use opentelemetry_sdk::{trace as sdktrace, Resource}; + type SharedState = Arc>; +const HONEYCOMB_API_KEY: &str = "HONEYCOMB_API_KEY"; + +fn init_hc_exporter() -> anyhow::Result { + use tonic::{metadata::MetadataMap, transport::ClientTlsConfig}; + const HONEYCOMB_ENDPOINT_HOST: &str = "api.honeycomb.io"; + + let api_key = env::var(HONEYCOMB_API_KEY).context(format!( + "Environment variable {} not found", + HONEYCOMB_API_KEY + ))?; + + let mut metadata = MetadataMap::with_capacity(1); + metadata.insert("x-honeycomb-team", api_key.parse()?); + + let tls_config = ClientTlsConfig::new().domain_name(HONEYCOMB_ENDPOINT_HOST); + Ok(opentelemetry_otlp::new_exporter() + .tonic() + .with_metadata(metadata) + .with_tls_config(tls_config)) +} + +fn init_tracer_provider() -> anyhow::Result { + let service_name = env::var("OTEL_SERVICE_NAME").unwrap_or_else(|_| "testevents".to_string()); + + let config = Config::default().with_resource(Resource::new(vec![KeyValue::new( + opentelemetry_semantic_conventions::resource::SERVICE_NAME, + service_name, + )])); + + // Is "honeycomb" in the OTEL_EXPORTER_OTLP_ENDPOINT env var? + let otel_exporter = if env::var("OTEL_EXPORTER_OTLP_ENDPOINT") + .unwrap_or_else(|_| "".to_string()) + .contains("honeycomb") + { + init_hc_exporter()? + } else { + opentelemetry_otlp::new_exporter().tonic() + }; + + Ok(opentelemetry_otlp::new_pipeline() + .tracing() + .with_exporter(otel_exporter) + .with_trace_config(config) + .install_batch(opentelemetry_sdk::runtime::Tokio)?) +} + struct AppState { - honeycomb_tx: mpsc::UnboundedSender, - provider: TracerProvider, + otel_tx: mpsc::UnboundedSender, spans: SpanStore, } @@ -33,19 +86,12 @@ async fn main() -> anyhow::Result<()> { // load configuration dotenv::dotenv().ok(); - let provider = TracerProvider::builder() - .with_simple_exporter(opentelemetry_stdout::SpanExporter::default()) - .build(); - let hc = honeycomb_client::get_honeycomb(&["createDatasets"]) - .await - .expect("Honeycomb connection must be established") - .expect("Honeycomb API key must be valid"); + let _tracer = init_tracer_provider()?; - let (honeycomb_tx, honeycomb_rx) = mpsc::unbounded_channel(); + let (otel_tx, otel_rx) = mpsc::unbounded_channel(); let state = AppState { - honeycomb_tx, - provider, + otel_tx, spans: SpanStore::new(), }; let shared_state = Arc::new(RwLock::new(state)); @@ -60,7 +106,7 @@ async fn main() -> anyhow::Result<()> { // Start the span ttl handler let task1 = handle_span_ttl(&shared_state); - let task2 = handle_honeycomb(hc, honeycomb_rx); + let task2 = handle_otel(otel_rx); // run it let bind_port = std::env::var("TESTEVENTS_PORT").unwrap_or("3003".to_string()); @@ -81,9 +127,9 @@ async fn root_handler( Json(attributes): Json, ) -> impl IntoResponse { let state = &mut state.write().expect("RwLock should not be poisoned"); - let provider = &state.provider; - let trace_id = provider.config().id_generator.new_trace_id(); - let span_id = provider.config().id_generator.new_span_id(); + let id_generator = RandomIdGenerator::default(); + let trace_id = id_generator.new_trace_id(); + let span_id = id_generator.new_span_id(); let traceparent = format!("00-{}-{}-01", trace_id, span_id); // Store the span state @@ -102,7 +148,8 @@ async fn child_handler( let state = &mut state.write().expect("RwLock should not be poisoned"); // Set the parent_id to the span_id let parent_id = span_id; - let span_id = &state.provider.config().id_generator.new_span_id(); + let id_generator = RandomIdGenerator::default(); + let span_id = id_generator.new_span_id(); let traceparent = format!("00-{}-{}-01", trace_id, span_id); // Store the span state.spans.insert( @@ -125,7 +172,7 @@ async fn close_handler( let span = state.spans.remove(trace_id, span_id); match span { Some(span) => { - state.honeycomb_tx.send(span).expect("Must send span"); + state.otel_tx.send(span).expect("Must send span"); Ok(Json(json!({ "message": "OK" }))) } None => Err(AppError::SpanNotFound), @@ -175,39 +222,92 @@ fn handle_span_ttl(shared_state: &SharedState) -> tokio::task::JoinHandle<()> { let s = state.spans.remove(trace_id, span_id); if let Some(mut span) = s { span.error_timeout(); - state.honeycomb_tx.send(span).expect("Must send span"); + state.otel_tx.send(span).expect("Must send span"); } } } }) } -fn handle_honeycomb( - hc: HoneyComb, +fn handle_otel( mut action_rx: mpsc::UnboundedReceiver, ) -> tokio::task::JoinHandle<()> { tokio::spawn(async move { loop { - let span = action_rx.recv().await; - if let Some(span) = span { - let he: HoneycombEvent = span.into(); - let he_list = vec![&he]; - match hc - .create_events( - he.dataset_slug(), - serde_json::to_value(he_list).expect("Must serialize"), + let span_attributes = action_rx.recv().await; + if let Some(span_attributes) = span_attributes { + // Get the otel trace, span and parent ids + let Some(trace_id) = span_attributes.otel_trace_id() else { + eprintln!("Invalid trace_id {}", span_attributes.trace_trace_id); + continue; + }; + let Some(span_id) = span_attributes.otel_span_id() else { + eprintln!("Invalid span_id {}", span_attributes.trace_span_id); + continue; + }; + let parent_id = span_attributes.otel_parent_id(); + + let tracer = global::tracer("testevents"); + + let span_context: Option = parent_id.map(|parent| { + SpanContext::new( + trace_id, + parent, + TraceFlags::SAMPLED, + false, + TraceState::NONE, ) - .await - { - Err(e) => eprintln!("Error sending to Honeycomb: {:?}", e), - Ok(statuses) => { - for status in statuses { - if status.status != 202 { - eprintln!("Error sending to Honeycomb: {:?}", status); + }); + + // convert the extra hashmap to a vec of KeyValue + fn serde_to_otel(v: Value) -> opentelemetry::Value { + match v { + Value::String(s) => opentelemetry::Value::String(s.into()), + Value::Number(n) => { + if n.is_i64() { + // Unwrap is safe because we know it's an i64 + opentelemetry::Value::I64(n.as_i64().unwrap()) + } else if n.is_f64() { + // Unwrap is safe because we know it's an f64 + opentelemetry::Value::F64(n.as_f64().unwrap()) + } else { + opentelemetry::Value::String("unsupported".into()) } } + Value::Bool(b) => opentelemetry::Value::Bool(b), + _ => opentelemetry::Value::String("unsupported".into()), } } + + let attrs = span_attributes + .extra + .into_iter() + .map(|(k, v)| KeyValue::new(k, serde_to_otel(v))); + + let span_builder = tracer + .span_builder(span_attributes.name) + .with_kind(SpanKind::Client) + .with_trace_id(trace_id) + .with_span_id(span_id) + .with_start_time(span_attributes.timestamp) + .with_attributes(attrs); + + let mut span = if let Some(sc) = span_context { + span_builder.start_with_context( + &tracer, + &opentelemetry::Context::new().with_remote_span_context(sc), + ) + } else { + span_builder.start(&tracer) + }; + + if span_attributes.status_code == 2 { + span.set_status(opentelemetry::trace::Status::Error { + description: span_attributes.status_message.into(), + }); + } + + drop(span); } } }) diff --git a/src/span_store.rs b/src/span_store.rs index 4e1fcfb..9dc214a 100644 --- a/src/span_store.rs +++ b/src/span_store.rs @@ -1,6 +1,7 @@ use std::collections::HashMap; use chrono::{DateTime, Utc}; +use opentelemetry::trace::{SpanId, TraceId}; use serde::{Deserialize, Serialize}; use serde_json::Value; @@ -27,8 +28,8 @@ impl SpanStore { timestamp: Utc::now(), duration_ms: 0, name: query_attributes.name, - service_name: query_attributes.service_name, status_code: 0, + status_message: "".to_string(), trace_span_id: span_id.clone(), trace_trace_id: trace_id.clone(), trace_parent_id: parent_id, @@ -81,21 +82,20 @@ impl SpanStore { #[derive(Debug, Serialize, Clone)] pub struct SpanAttributes { #[serde(skip_serializing)] - timestamp: DateTime, + pub timestamp: DateTime, duration_ms: i64, - name: String, - status_code: i64, - #[serde(rename = "service.name")] - service_name: String, + pub name: String, + pub status_code: i64, + pub status_message: String, #[serde(rename = "trace.span_id")] - trace_span_id: String, + pub trace_span_id: String, #[serde(rename = "trace.trace_id")] - trace_trace_id: String, + pub trace_trace_id: String, #[serde(skip_serializing_if = "Option::is_none")] #[serde(rename = "trace.parent_id")] - trace_parent_id: Option, + pub trace_parent_id: Option, #[serde(flatten)] - extra: HashMap, + pub extra: HashMap, #[serde(skip_serializing)] ttl: i64, } @@ -108,11 +108,11 @@ impl SpanAttributes { .as_str() .unwrap_or_default() .clone_into(&mut self.name), - "service.name" => value + "status_code" => self.status_code = value.as_i64().unwrap_or_default(), + "status_message" => value .as_str() .unwrap_or_default() - .clone_into(&mut self.service_name), - "status_code" => self.status_code = value.as_i64().unwrap_or_default(), + .clone_into(&mut self.status_message), "ttl" => self.set_ttl(value.as_i64().unwrap_or_default()), _ => { self.extra.insert(key, value); @@ -127,26 +127,19 @@ impl SpanAttributes { let current_used_millis = now - self.timestamp.timestamp_millis(); self.ttl = current_used_millis + ttl; } -} -#[derive(Debug, Serialize, Clone)] -pub struct HoneycombEvent { - time: DateTime, - data: SpanAttributes, -} + pub fn otel_trace_id(&self) -> Option { + TraceId::from_hex(&self.trace_trace_id).ok() + } -impl From for HoneycombEvent { - fn from(span: SpanAttributes) -> Self { - HoneycombEvent { - time: span.timestamp, - data: span, - } + pub fn otel_span_id(&self) -> Option { + SpanId::from_hex(&self.trace_span_id).ok() } -} -impl HoneycombEvent { - pub fn dataset_slug(&self) -> &str { - self.data.service_name.as_str() + pub fn otel_parent_id(&self) -> Option { + self.trace_parent_id + .as_ref() + .and_then(|parent_id| SpanId::from_hex(parent_id).ok()) } } @@ -156,18 +149,12 @@ impl SpanAttributes { } pub fn error_timeout(&mut self) { self.status_code = 2; - self.extra.insert("error".to_owned(), true.into()); - self.extra.insert( - "status_message".to_owned(), - format!("testevents timeout: TTL was {}", self.ttl).into(), - ); + self.status_message = format!("testevents timeout: TTL was {}", self.ttl); } } #[derive(Deserialize, Debug)] pub struct QueryAttributes { - #[serde(rename = "service.name")] - service_name: String, name: String, ttl: Option, #[serde(flatten)] diff --git a/test.sh b/test.sh index 17aef66..3028660 100755 --- a/test.sh +++ b/test.sh @@ -2,13 +2,13 @@ url="http://localhost:3003" echo "Make a root span" -response=$(curl -s -X POST $url/ -H 'Content-Type: application/json' -d '{"service.name":"jerbly-test","name":"test","hello":"world","ttl":3600000}') +response=$(curl -s -X POST $url/ -H 'Content-Type: application/json' -d '{"name":"test","hello":"world","amount":15,"fraction":17.67,"ttl":3600000}') root_span_id=$(echo $response | jq -r '.span_id') root_trace_id=$(echo $response | jq -r '.trace_id') sleep 1 echo "Make a child span" -response=$(curl -s -X POST $url/$root_trace_id/$root_span_id/ -H 'Content-Type: application/json' -d '{"service.name":"jerbly-test","name":"child","ttl":3600000}') +response=$(curl -s -X POST $url/$root_trace_id/$root_span_id/ -H 'Content-Type: application/json' -d '{"name":"child","ttl":3600000}') span_id=$(echo $response | jq -r '.span_id') sleep 1