1
0
mirror of https://github.com/actix/examples synced 2024-11-23 14:31:07 +01:00

feat: add mainmatter telemetry workshop example

This commit is contained in:
Rob Ede 2024-06-05 04:52:05 +01:00
parent 0614b2c506
commit 8e0b57e658
No known key found for this signature in database
GPG Key ID: 97C636207D3EF933
16 changed files with 793 additions and 87 deletions

View File

@ -9,9 +9,11 @@
"dotenv",
"dotenvy",
"graphiql",
"mainmatter",
"minijinja",
"nocapture",
"oneshot",
"opentelemetry",
"pemfile",
"prost",
"protobuf",

497
Cargo.lock generated
View File

@ -162,7 +162,7 @@ dependencies = [
"actix-service",
"actix-tls",
"actix-utils",
"ahash 0.8.7",
"ahash 0.8.11",
"base64 0.22.1",
"bitflags 2.4.1",
"brotli",
@ -436,7 +436,7 @@ dependencies = [
"actix-tls",
"actix-utils",
"actix-web-codegen",
"ahash 0.8.7",
"ahash 0.8.11",
"bytes 1.6.0",
"bytestring",
"cfg-if 1.0.0",
@ -504,7 +504,7 @@ dependencies = [
"actix-utils",
"actix-web",
"actix-web-lab-derive",
"ahash 0.8.7",
"ahash 0.8.11",
"arc-swap",
"async-trait",
"bytes 1.6.0",
@ -643,9 +643,9 @@ dependencies = [
[[package]]
name = "ahash"
version = "0.8.7"
version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01"
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
dependencies = [
"cfg-if 1.0.0",
"const-random",
@ -1110,6 +1110,12 @@ dependencies = [
"num-traits",
]
[[package]]
name = "atomic"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba"
[[package]]
name = "autocfg"
version = "1.1.0"
@ -1571,6 +1577,51 @@ dependencies = [
"tracing",
]
[[package]]
name = "axum"
version = "0.6.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf"
dependencies = [
"async-trait",
"axum-core",
"bitflags 1.3.2",
"bytes 1.6.0",
"futures-util",
"http 0.2.9",
"http-body 0.4.5",
"hyper 0.14.27",
"itoa 1.0.9",
"matchit",
"memchr",
"mime",
"percent-encoding",
"pin-project-lite 0.2.13",
"rustversion",
"serde",
"sync_wrapper",
"tower",
"tower-layer",
"tower-service",
]
[[package]]
name = "axum-core"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c"
dependencies = [
"async-trait",
"bytes 1.6.0",
"futures-util",
"http 0.2.9",
"http-body 0.4.5",
"mime",
"rustversion",
"tower-layer",
"tower-service",
]
[[package]]
name = "background-jobs"
version = "1.0.0"
@ -1846,7 +1897,7 @@ version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce21468c1c9c154a85696bb25c20582511438edb6ad67f846ba1378ffdd80222"
dependencies = [
"ahash 0.8.7",
"ahash 0.8.11",
"base64 0.13.1",
"bitvec",
"hex",
@ -3508,6 +3559,16 @@ dependencies = [
"zeroize",
]
[[package]]
name = "gethostname"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1ebd34e35c46e00bb73e81363248d627782724609fe1b6396f553f68fe3862e"
dependencies = [
"libc",
"winapi 0.3.9",
]
[[package]]
name = "getrandom"
version = "0.1.16"
@ -3589,7 +3650,7 @@ dependencies = [
"no-std-compat",
"nonzero_ext",
"parking_lot 0.12.3",
"quanta",
"quanta 0.11.1",
"rand 0.8.5",
"smallvec",
]
@ -3736,7 +3797,7 @@ version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e"
dependencies = [
"ahash 0.8.7",
"ahash 0.8.11",
]
[[package]]
@ -3745,7 +3806,7 @@ version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156"
dependencies = [
"ahash 0.8.7",
"ahash 0.8.11",
"allocator-api2",
]
@ -4031,7 +4092,7 @@ dependencies = [
"hyper 0.14.27",
"log",
"rustls 0.21.12",
"rustls-native-certs",
"rustls-native-certs 0.6.3",
"tokio 1.37.0",
"tokio-rustls 0.24.1",
]
@ -4053,6 +4114,18 @@ dependencies = [
"tower-service",
]
[[package]]
name = "hyper-timeout"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1"
dependencies = [
"hyper 0.14.27",
"pin-project-lite 0.2.13",
"tokio 1.37.0",
"tokio-io-timeout",
]
[[package]]
name = "hyper-tls"
version = "0.4.3"
@ -4763,12 +4836,27 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4"
[[package]]
name = "matchers"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
dependencies = [
"regex-automata 0.1.10",
]
[[package]]
name = "matches"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5"
[[package]]
name = "matchit"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94"
[[package]]
name = "md-5"
version = "0.10.6"
@ -4806,6 +4894,45 @@ dependencies = [
"autocfg",
]
[[package]]
name = "metrics"
version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "884adb57038347dfbaf2d5065887b6cf4312330dc8e94bc30a1a839bd79d3261"
dependencies = [
"ahash 0.8.11",
"portable-atomic",
]
[[package]]
name = "metrics-exporter-prometheus"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26eb45aff37b45cff885538e1dcbd6c2b462c04fe84ce0155ea469f325672c98"
dependencies = [
"base64 0.22.1",
"indexmap 2.1.0",
"metrics",
"metrics-util",
"quanta 0.12.3",
"thiserror",
]
[[package]]
name = "metrics-util"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4259040465c955f9f2f1a4a8a16dc46726169bca0f88e8fb2dbeced487c3e828"
dependencies = [
"crossbeam-epoch",
"crossbeam-utils",
"hashbrown 0.14.2",
"metrics",
"num_cpus",
"quanta 0.12.3",
"sketches-ddsketch",
]
[[package]]
name = "middleware-encrypted-payloads"
version = "1.0.0"
@ -5074,6 +5201,12 @@ dependencies = [
"tokio-util 0.7.11",
]
[[package]]
name = "mutually_exclusive_features"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d02c0b00610773bb7fc61d85e13d86c7858cbdf00e1a120bfc41bc055dbaa0e"
[[package]]
name = "mysql"
version = "1.0.0"
@ -5281,6 +5414,16 @@ dependencies = [
"windows-sys 0.48.0",
]
[[package]]
name = "nu-ansi-term"
version = "0.46.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
dependencies = [
"overload",
"winapi 0.3.9",
]
[[package]]
name = "num-bigint"
version = "0.4.4"
@ -5421,6 +5564,89 @@ 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 0.2.13",
"thiserror",
"urlencoding",
]
[[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.9",
"opentelemetry",
"opentelemetry-proto",
"opentelemetry-semantic-conventions",
"opentelemetry_sdk",
"prost",
"thiserror",
"tokio 1.37.0",
"tonic",
]
[[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_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 0.8.5",
"thiserror",
"tokio 1.37.0",
"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 = "ordered-multimap"
version = "0.4.3"
@ -5437,6 +5663,12 @@ version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4030760ffd992bef45b0ae3f10ce1aba99e33464c90d14dd7c039884963ddc7a"
[[package]]
name = "overload"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
[[package]]
name = "owo-colors"
version = "3.5.0"
@ -5789,6 +6021,12 @@ dependencies = [
"universal-hash",
]
[[package]]
name = "portable-atomic"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0"
[[package]]
name = "postgres-protocol"
version = "0.6.6"
@ -5996,7 +6234,22 @@ dependencies = [
"libc",
"mach2",
"once_cell",
"raw-cpuid",
"raw-cpuid 10.7.0",
"wasi 0.11.0+wasi-snapshot-preview1",
"web-sys",
"winapi 0.3.9",
]
[[package]]
name = "quanta"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e5167a477619228a0b284fac2674e3c388cba90631d7b7de620e6f1fcd08da5"
dependencies = [
"crossbeam-utils",
"libc",
"once_cell",
"raw-cpuid 11.0.2",
"wasi 0.11.0+wasi-snapshot-preview1",
"web-sys",
"winapi 0.3.9",
@ -6124,6 +6377,15 @@ dependencies = [
"bitflags 1.3.2",
]
[[package]]
name = "raw-cpuid"
version = "11.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e29830cbb1290e404f24c73af91c5d8d631ce7e128691e9477556b540cd01ecd"
dependencies = [
"bitflags 2.4.1",
]
[[package]]
name = "redis"
version = "0.24.0"
@ -6196,8 +6458,17 @@ checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
"regex-automata 0.4.3",
"regex-syntax 0.8.2",
]
[[package]]
name = "regex-automata"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
dependencies = [
"regex-syntax 0.6.29",
]
[[package]]
@ -6208,7 +6479,7 @@ checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
"regex-syntax 0.8.2",
]
[[package]]
@ -6217,6 +6488,12 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30b661b2f27137bdbc16f00eda72866a92bb28af1753ffbd56744fb6e2e9cd8e"
[[package]]
name = "regex-syntax"
version = "0.6.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
[[package]]
name = "regex-syntax"
version = "0.8.2"
@ -6388,7 +6665,7 @@ version = "1.16.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3625f343d89990133d013e39c46e350915178cf94f1bec9f49b0cbef98a3e3c"
dependencies = [
"ahash 0.8.7",
"ahash 0.8.11",
"bitflags 2.4.1",
"instant",
"num-traits",
@ -6669,6 +6946,19 @@ dependencies = [
"security-framework",
]
[[package]]
name = "rustls-native-certs"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f1fb85efa936c42c6d5fc28d2629bb51e4b2f4b8a5211e297d599cc5a093792"
dependencies = [
"openssl-probe",
"rustls-pemfile 2.1.2",
"rustls-pki-types",
"schannel",
"security-framework",
]
[[package]]
name = "rustls-pemfile"
version = "1.0.4"
@ -7167,6 +7457,12 @@ version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
[[package]]
name = "sketches-ddsketch"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85636c14b73d81f541e525f585c0a2109e6744e1565b5c1668e31c70c10ed65c"
[[package]]
name = "slab"
version = "0.4.9"
@ -7338,7 +7634,7 @@ version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24ba59a9342a3d9bab6c56c118be528b27c9b60e490080e9711a04dccac83ef6"
dependencies = [
"ahash 0.8.7",
"ahash 0.8.11",
"atoi",
"byteorder",
"bytes 1.6.0",
@ -8044,6 +8340,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 0.2.13",
"tokio 1.37.0",
]
[[package]]
name = "tokio-macros"
version = "2.2.0"
@ -8270,6 +8576,37 @@ dependencies = [
"winnow",
]
[[package]]
name = "tonic"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76c4eb7a4e9ef9d4763600161f12f5070b92a578e1b634db88a6887844c91a13"
dependencies = [
"async-stream",
"async-trait",
"axum",
"base64 0.21.7",
"bytes 1.6.0",
"h2 0.3.26",
"http 0.2.9",
"http-body 0.4.5",
"hyper 0.14.27",
"hyper-timeout",
"percent-encoding",
"pin-project",
"prost",
"rustls-native-certs 0.7.0",
"rustls-pemfile 2.1.2",
"rustls-pki-types",
"tokio 1.37.0",
"tokio-rustls 0.25.0",
"tokio-stream",
"tower",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
name = "tower"
version = "0.4.13"
@ -8278,9 +8615,13 @@ checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
dependencies = [
"futures-core",
"futures-util",
"indexmap 1.9.3",
"pin-project",
"pin-project-lite 0.2.13",
"rand 0.8.5",
"slab",
"tokio 1.37.0",
"tokio-util 0.7.11",
"tower-layer",
"tower-service",
"tracing",
@ -8310,6 +8651,21 @@ dependencies = [
"tracing-core",
]
[[package]]
name = "tracing-actix-web"
version = "0.7.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa069bd1503dd526ee793bb3fce408895136c95fc86d2edb2acf1c646d7f0684"
dependencies = [
"actix-web",
"mutually_exclusive_features",
"opentelemetry",
"pin-project",
"tracing",
"tracing-opentelemetry",
"uuid 1.7.0",
]
[[package]]
name = "tracing-attributes"
version = "0.1.27"
@ -8321,6 +8677,24 @@ dependencies = [
"syn 2.0.48",
]
[[package]]
name = "tracing-bunyan-formatter"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5c266b9ac83dedf0e0385ad78514949e6d89491269e7065bee51d2bb8ec7373"
dependencies = [
"ahash 0.8.11",
"gethostname",
"log",
"serde",
"serde_json",
"time",
"tracing",
"tracing-core",
"tracing-log 0.1.4",
"tracing-subscriber",
]
[[package]]
name = "tracing-core"
version = "0.1.32"
@ -8351,15 +8725,95 @@ dependencies = [
"tracing",
]
[[package]]
name = "tracing-log"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f751112709b4e791d8ce53e32c4ed2d353565a795ce84da2285393f41557bdf2"
dependencies = [
"log",
"once_cell",
"tracing-core",
]
[[package]]
name = "tracing-log"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
dependencies = [
"log",
"once_cell",
"tracing-core",
]
[[package]]
name = "tracing-mainmatter-workshop"
version = "1.0.0"
dependencies = [
"actix-web",
"actix-web-lab",
"dotenvy",
"metrics",
"metrics-exporter-prometheus",
"opentelemetry",
"opentelemetry-otlp",
"opentelemetry_sdk",
"tonic",
"tracing",
"tracing-actix-web",
"tracing-bunyan-formatter",
"tracing-opentelemetry",
"tracing-subscriber",
]
[[package]]
name = "tracing-opentelemetry"
version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9be14ba1bbe4ab79e9229f7f89fab8d120b865859f10527f31c033e599d2284"
dependencies = [
"js-sys",
"once_cell",
"opentelemetry",
"opentelemetry_sdk",
"smallvec",
"tracing",
"tracing-core",
"tracing-log 0.2.0",
"tracing-subscriber",
"web-time",
]
[[package]]
name = "tracing-serde"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc6b213177105856957181934e4920de57730fc69bf42c37ee5bb664d406d9e1"
dependencies = [
"serde",
"tracing-core",
]
[[package]]
name = "tracing-subscriber"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77"
dependencies = [
"matchers",
"nu-ansi-term",
"once_cell",
"regex",
"serde",
"serde_json",
"sharded-slab",
"smallvec",
"thread_local",
"tracing",
"tracing-core",
"tracing-log 0.1.4",
"tracing-serde",
]
[[package]]
@ -8687,6 +9141,7 @@ version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a"
dependencies = [
"atomic",
"getrandom 0.2.12",
"serde",
]
@ -8910,6 +9365,16 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "web-time"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "webpki-roots"
version = "0.25.4"

View File

@ -1,72 +1,73 @@
[workspace]
resolver = "2"
members = [
"auth/casbin",
"auth/cookie-auth",
"auth/cookie-session",
"auth/redis-session",
"auth/simple-auth-server",
"background-jobs",
"basics/basics",
"basics/error-handling",
"basics/hello-world",
"basics/nested-routing",
"basics/state",
"basics/static-files",
"basics/todo",
"cors/backend",
"data-factory",
"databases/diesel",
"databases/mongodb",
"databases/mysql",
"databases/postgres",
"databases/redis",
# "databases/sqlite",
"docker",
"forms/form",
"forms/multipart-s3",
"forms/multipart",
"graphql/async-graphql",
"graphql/juniper-advanced",
"graphql/juniper",
"guards",
"http-proxy",
"https-tls/acme-letsencrypt",
"https-tls/awc-https",
"https-tls/cert-watch",
"https-tls/openssl",
"https-tls/rustls-client-cert",
"https-tls/rustls",
"json/json-decode-error",
"json/json-error",
"json/json-validation",
"json/json",
"json/jsonrpc",
"middleware/encrypted-payloads",
"middleware/http-to-https",
"middleware/rate-limit",
"middleware/request-extensions",
"middleware/various",
"protobuf",
"run-in-thread",
"server-sent-events",
"shutdown-server",
"templating/askama",
"templating/fluent",
"templating/handlebars",
"templating/minijinja",
"templating/sailfish",
"templating/tera",
"templating/tinytemplate",
"templating/yarte",
"unix-socket",
"websockets/autobahn",
"websockets/chat-actorless",
"websockets/chat-broker",
"websockets/chat-tcp",
"websockets/chat",
"websockets/echo-actorless",
"websockets/echo",
"auth/casbin",
"auth/cookie-auth",
"auth/cookie-session",
"auth/redis-session",
"auth/simple-auth-server",
"background-jobs",
"basics/basics",
"basics/error-handling",
"basics/hello-world",
"basics/nested-routing",
"basics/state",
"basics/static-files",
"basics/todo",
"cors/backend",
"data-factory",
"databases/diesel",
"databases/mongodb",
"databases/mysql",
"databases/postgres",
"databases/redis",
# "databases/sqlite",
"docker",
"forms/form",
"forms/multipart-s3",
"forms/multipart",
"graphql/async-graphql",
"graphql/juniper-advanced",
"graphql/juniper",
"guards",
"http-proxy",
"https-tls/acme-letsencrypt",
"https-tls/awc-https",
"https-tls/cert-watch",
"https-tls/openssl",
"https-tls/rustls-client-cert",
"https-tls/rustls",
"json/json-decode-error",
"json/json-error",
"json/json-validation",
"json/json",
"json/jsonrpc",
"middleware/encrypted-payloads",
"middleware/http-to-https",
"middleware/rate-limit",
"middleware/request-extensions",
"middleware/various",
"protobuf",
"run-in-thread",
"server-sent-events",
"shutdown-server",
"templating/askama",
"templating/fluent",
"templating/handlebars",
"templating/minijinja",
"templating/sailfish",
"templating/tera",
"templating/tinytemplate",
"templating/yarte",
"tracing/mainmatter-workshop",
"unix-socket",
"websockets/autobahn",
"websockets/chat-actorless",
"websockets/chat-broker",
"websockets/chat-tcp",
"websockets/chat",
"websockets/echo-actorless",
"websockets/echo",
]
[workspace.package]
@ -99,9 +100,14 @@ chrono = { version = "0.4.30", features = ["serde"] }
derive_more = "0.99.7"
dotenvy = "0.15"
env_logger = "0.11"
eyre = { version = "0.6", default-features = false, features = ["auto-install", "track-caller"] }
eyre = { version = "0.6", default-features = false, features = [
"auto-install",
"track-caller",
] }
color-eyre = "0.6"
futures-util = { version = "0.3.17", default-features = false, features = ["std"] }
futures-util = { version = "0.3.17", default-features = false, features = [
"std",
] }
log = "0.4"
openssl = { version = "0.10.60", features = ["v110"] }
rand = "0.8"
@ -112,3 +118,5 @@ serde_json = "1"
tokio = { version = "1.24.2", features = ["sync", "io-util"] }
tokio-util = "0.7.4"
tokio-stream = "0.1.1"
tracing = "0.1.30"
tracing-subscriber = { version = "0.3", features = ["env-filter", "json"] }

View File

@ -8,5 +8,8 @@ actix-web.workspace = true
env_logger.workspace = true
log.workspace = true
redis = { version = "0.24", default-features = false, features = ["tokio-comp", "connection-manager"] }
redis = { version = "0.24", default-features = false, features = [
"tokio-comp",
"connection-manager",
] }
serde.workspace = true

View File

@ -6,7 +6,7 @@ edition = "2021"
[package.metadata.cargo-machete]
ignored = [
"yarte_helpers", # only build dep
"yarte_helpers", # only build dep
]
[dependencies]

View File

@ -0,0 +1,2 @@
RUST_LOG="info,mainmatter_workshop=trace"
HONEYCOMB_API_KEY="..."

View File

@ -0,0 +1 @@
/target

View File

@ -0,0 +1,22 @@
[package]
name = "tracing-mainmatter-workshop"
version = "1.0.0"
publish.workspace = true
edition.workspace = true
rust-version.workspace = true
[dependencies]
actix-web.workspace = true
actix-web-lab.workspace = true
dotenvy.workspace = true
metrics = "0.23"
metrics-exporter-prometheus = { version = "0.15", default-features = false }
opentelemetry = "0.22"
opentelemetry_sdk = { version = "0.22", features = ["rt-tokio-current-thread"] }
opentelemetry-otlp = { version = "0.15", features = ["tls-roots"] }
tonic = "0.11"
tracing-actix-web = { version = "0.7", features = ["opentelemetry_0_22", "uuid_v7"] }
tracing-opentelemetry = "0.23"
tracing-subscriber.workspace = true
tracing-bunyan-formatter = "0.3"
tracing.workspace = true

View File

@ -0,0 +1,23 @@
# Telemetry Workshop Solution
## Overview
A solution to the capstone project at the end of [Mainmatter's telemetry workshop](https://github.com/mainmatter/rust-telemetry-workshop).
As stated in the exercise brief, this example will:
- Configure a `tracing` subscriber that exports data to both Honeycomb and stdout, in JSON format;
- Configure a suitable panic hook;
- Configure a `metric` recorder that exposes metric data at `/metrics`~~, using a different port than your API endpoints~~ (this example shows how to use the existing HTTP server);
- Add one or more middleware that:
- Create a top-level INFO span for each incoming request;
- Track the number of concurrent requests using a gauge;
- Track request duration using a histogram;
- Track the number of handled requests All metrics should include success/failure as a label.
## Usage
```console
$ cd tracing/mainmatter-workshop
$ cargo run
```

View File

@ -0,0 +1,57 @@
use std::{io, time::Duration};
use opentelemetry::KeyValue;
use opentelemetry_otlp::WithExportConfig as _;
use opentelemetry_sdk::{runtime, trace::Tracer, Resource};
use tonic::metadata::MetadataMap;
use tracing::level_filters::LevelFilter;
use tracing_bunyan_formatter::{BunyanFormattingLayer, JsonStorageLayer};
use tracing_subscriber::{layer::SubscriberExt as _, util::SubscriberInitExt as _, EnvFilter};
pub(crate) fn init() {
let app_name = "actix-web-mainmatter-telemetry-workshop-capstone";
let tracer = opentelemetry_tracer(app_name);
let telemetry = tracing_opentelemetry::layer().with_tracer(tracer);
// we prefer the bunyan formatting layer in this example because it captures
// span enters and exits by default, making a good way to observe request
// info like duration when
let stdout_log = BunyanFormattingLayer::new(app_name.to_owned(), io::stdout);
tracing_subscriber::registry()
.with(
EnvFilter::builder()
.with_default_directive(LevelFilter::INFO.into())
.from_env_lossy(),
)
.with(telemetry)
.with(JsonStorageLayer)
.with(stdout_log)
.init();
}
fn opentelemetry_tracer(app_name: &str) -> Tracer {
let honeycomb_key =
std::env::var("HONEYCOMB_API_KEY").expect("`HONEYCOMB_API_KEY` should be set in your .env");
let mut metadata = MetadataMap::with_capacity(1);
metadata.insert("x-honeycomb-team", honeycomb_key.try_into().unwrap());
let trace_config =
opentelemetry_sdk::trace::Config::default().with_resource(Resource::new(vec![
KeyValue::new("service.name", app_name.to_owned()),
]));
let exporter = opentelemetry_otlp::new_exporter()
.tonic()
.with_endpoint("https://api.honeycomb.io/api/traces")
.with_timeout(Duration::from_secs(5))
.with_metadata(metadata);
opentelemetry_otlp::new_pipeline()
.tracing()
.with_trace_config(trace_config)
.with_exporter(exporter)
.install_batch(runtime::TokioCurrentThread)
.unwrap()
}

View File

@ -0,0 +1,32 @@
use std::io;
use actix_web::{App, HttpServer};
use actix_web_lab::{extract::ThinData, middleware::from_fn};
use tracing_actix_web::TracingLogger;
mod logging;
mod metric_names;
mod middleware;
mod prometheus;
mod routes;
#[actix_web::main]
async fn main() -> io::Result<()> {
dotenvy::dotenv().ok();
logging::init();
let handle = prometheus::init();
HttpServer::new(move || {
App::new()
.app_data(ThinData(handle.clone()))
.service(routes::hello)
.service(routes::sleep)
.service(routes::metrics)
.wrap(from_fn(middleware::request_telemetry))
.wrap(TracingLogger::default())
})
.workers(2)
.bind(("127.0.0.1", 8080))?
.run()
.await
}

View File

@ -0,0 +1,2 @@
pub(crate) const HISTOGRAM_HTTP_REQUEST_DURATION: &str = "http_request_duration";
pub(crate) const GAUGE_HTTP_CONCURRENT_REQUESTS: &str = "http_concurrent_requests";

View File

@ -0,0 +1,40 @@
use std::time::Instant;
use actix_web::HttpMessage as _;
use actix_web::{
body::MessageBody,
dev::{ServiceRequest, ServiceResponse},
http::header::{HeaderName, HeaderValue},
};
use actix_web_lab::middleware::Next;
use tracing_actix_web::RequestId;
use crate::metric_names::*;
pub(crate) async fn request_telemetry(
req: ServiceRequest,
next: Next<impl MessageBody>,
) -> actix_web::Result<ServiceResponse<impl MessageBody>> {
let now = Instant::now();
metrics::gauge!(GAUGE_HTTP_CONCURRENT_REQUESTS).increment(1);
let mut res = next.call(req).await?;
let req_id = res.request().extensions().get::<RequestId>().copied();
if let Some(req_id) = req_id {
res.headers_mut().insert(
HeaderName::from_static("request-id"),
// this unwrap never fails, since UUIDs are valid ASCII strings
HeaderValue::from_str(&req_id.to_string()).unwrap(),
);
};
let diff = now.elapsed();
metrics::histogram!(HISTOGRAM_HTTP_REQUEST_DURATION).record(diff);
metrics::gauge!(GAUGE_HTTP_CONCURRENT_REQUESTS).decrement(1);
Ok(res)
}

View File

@ -0,0 +1,28 @@
use std::array;
use metrics::Unit;
use metrics_exporter_prometheus::{PrometheusBuilder, PrometheusHandle};
use crate::metric_names::*;
pub(crate) fn init() -> PrometheusHandle {
metrics::describe_histogram!(
HISTOGRAM_HTTP_REQUEST_DURATION,
Unit::Seconds,
"Duration (in seconds) a request took to be processed"
);
PrometheusBuilder::new()
.set_buckets_for_metric(
metrics_exporter_prometheus::Matcher::Full(HISTOGRAM_HTTP_REQUEST_DURATION.to_owned()),
&exp_buckets::<28>(0.001), // values from ~0.3ms -> ~33s
)
.unwrap()
.install_recorder()
.unwrap()
}
fn exp_buckets<const N: usize>(base: f64) -> [f64; N] {
const RATIO: f64 = 1.5;
array::from_fn(|i| base * RATIO.powi(i as i32 - 3)).map(|val| (val * 1_e7).round() / 1_e7)
}

View File

@ -0,0 +1,21 @@
use std::time::Duration;
use actix_web::{get, HttpResponse, Responder};
use actix_web_lab::extract::ThinData;
use metrics_exporter_prometheus::PrometheusHandle;
#[get("/hello")]
pub(crate) async fn hello() -> impl Responder {
"Hello, World!"
}
#[get("/sleep")]
pub(crate) async fn sleep() -> impl Responder {
actix_web::rt::time::sleep(Duration::from_millis(500)).await;
HttpResponse::Ok()
}
#[get("/metrics")]
pub(crate) async fn metrics(metrics_handle: ThinData<PrometheusHandle>) -> impl Responder {
metrics_handle.render()
}

View File

@ -24,7 +24,7 @@ async fn main() {
return;
}
if cmd == "/exit" {
if cmd.trim() == "/exit" {
println!("exiting input loop");
return;
}