diff --git a/.github/workflows/check-all.yml b/.github/workflows/check-all.yml index 3ab742361..5051aa1bf 100644 --- a/.github/workflows/check-all.yml +++ b/.github/workflows/check-all.yml @@ -28,3 +28,4 @@ jobs: - run: git config --global --add safe.directory "$PWD" # actions/runner#2033 - run: just fetch - run: just check --exclude=linkerd-meshtls-boring + - run: just check --exclude=linkerd-meshtls-boring --features=pprof diff --git a/.vscode/settings.json b/.vscode/settings.json index be2b3c246..7e2f86ed0 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,6 @@ { - "rust-analyzer.cargo.features": [], + "rust-analyzer.cargo.features": [ + "pprof" + ], "files.insertFinalNewline": true -} \ No newline at end of file +} diff --git a/Cargo.lock b/Cargo.lock index b4b26c4d1..8900920cf 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" @@ -29,9 +38,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "0.7.20" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" dependencies = [ "memchr", ] @@ -81,7 +90,7 @@ checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" dependencies = [ "proc-macro2", "quote", - "syn 2.0.12", + "syn 2.0.39", ] [[package]] @@ -135,6 +144,21 @@ dependencies = [ "tower-service", ] +[[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 0.7.1", + "object", + "rustc-demangle", +] + [[package]] name = "base64" version = "0.13.1" @@ -164,7 +188,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.12", + "syn 2.0.39", ] [[package]] @@ -179,6 +203,15 @@ version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + [[package]] name = "boring" version = "3.0.4" @@ -266,6 +299,24 @@ dependencies = [ "cc", ] +[[package]] +name = "cpp_demangle" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e8227005286ec39567949b33df9896bcadfa6051bccca2488129f108ca23119" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "cpufeatures" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" +dependencies = [ + "libc", +] + [[package]] name = "crc32fast" version = "1.3.2" @@ -275,12 +326,31 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + [[package]] name = "data-encoding" version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23d8666cb01533c39dde32bcbab8e227b4ed6679b2c925eba05feabea39508fb" +[[package]] +name = "debugid" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" +dependencies = [ + "uuid", +] + [[package]] name = "deflate" version = "1.0.0" @@ -311,6 +381,16 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + [[package]] name = "drain" version = "0.1.1" @@ -369,6 +449,18 @@ dependencies = [ "instant", ] +[[package]] +name = "findshlibs" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40b9e59cd0f7e0806cca4be089683ecb6434e602038df21fe6bf6711b2f07f64" +dependencies = [ + "cc", + "lazy_static", + "libc", + "winapi", +] + [[package]] name = "fixedbitset" version = "0.4.2" @@ -382,7 +474,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" dependencies = [ "crc32fast", - "miniz_oxide", + "miniz_oxide 0.6.2", ] [[package]] @@ -499,7 +591,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.12", + "syn 2.0.39", ] [[package]] @@ -532,6 +624,16 @@ dependencies = [ "slab", ] +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "getrandom" version = "0.2.8" @@ -543,6 +645,12 @@ dependencies = [ "wasi", ] +[[package]] +name = "gimli" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" + [[package]] name = "glob" version = "0.3.1" @@ -846,9 +954,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.140" +version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" [[package]] name = "libfuzzer-sys" @@ -913,12 +1021,14 @@ dependencies = [ name = "linkerd-app-admin" version = "0.1.0" dependencies = [ + "deflate", "futures", "http", "hyper", "linkerd-app-core", "linkerd-app-inbound", "linkerd-tracing", + "pprof", "serde", "serde_json", "thiserror", @@ -1493,7 +1603,7 @@ dependencies = [ "linkerd-tls", "linkerd2-proxy-api", "pin-project", - "prost", + "prost 0.11.8", "tonic", "tower", "tracing", @@ -1535,7 +1645,7 @@ dependencies = [ "linkerd2-proxy-api", "maplit", "once_cell", - "prost-types", + "prost-types 0.11.8", "quickcheck", "thiserror", "tonic", @@ -1642,7 +1752,7 @@ dependencies = [ "linkerd-http-route", "linkerd2-proxy-api", "maplit", - "prost-types", + "prost-types 0.11.8", "quickcheck", "thiserror", ] @@ -1665,7 +1775,7 @@ dependencies = [ "linkerd2-proxy-api", "parking_lot", "pin-project", - "prost-types", + "prost-types 0.11.8", "quickcheck", "rand", "thiserror", @@ -1764,7 +1874,7 @@ dependencies = [ "linkerd-tonic-watch", "linkerd2-proxy-api", "once_cell", - "prost-types", + "prost-types 0.11.8", "quickcheck", "regex", "thiserror", @@ -1916,8 +2026,8 @@ dependencies = [ "linkerd-error", "linkerd-io", "linkerd-stack", - "prost", - "prost-build", + "prost 0.11.8", + "prost-build 0.11.8", "tokio", "tokio-test", "tracing", @@ -1961,8 +2071,8 @@ dependencies = [ "h2", "http", "ipnet", - "prost", - "prost-types", + "prost 0.11.8", + "prost-types 0.11.8", "quickcheck", "thiserror", "tonic", @@ -2026,7 +2136,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" dependencies = [ - "regex-automata", + "regex-automata 0.1.10", ] [[package]] @@ -2047,6 +2157,15 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +[[package]] +name = "memmap2" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a5a03cefb0d953ec0be133036f14e109412fa594edc2f77227249db66cc3ed" +dependencies = [ + "libc", +] + [[package]] name = "mime" version = "0.3.16" @@ -2068,6 +2187,15 @@ dependencies = [ "adler", ] +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", +] + [[package]] name = "mio" version = "0.8.6" @@ -2086,6 +2214,17 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" +[[package]] +name = "nix" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" +dependencies = [ + "bitflags 1.3.2", + "cfg-if", + "libc", +] + [[package]] name = "nom" version = "7.1.0" @@ -2126,6 +2265,15 @@ dependencies = [ "libc", ] +[[package]] +name = "object" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" version = "1.17.1" @@ -2137,8 +2285,8 @@ name = "opencensus-proto" version = "0.1.0" dependencies = [ "bytes", - "prost", - "prost-types", + "prost 0.11.8", + "prost-types 0.11.8", "tonic", "tonic-build", ] @@ -2242,6 +2390,30 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" +[[package]] +name = "pprof" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef5c97c51bd34c7e742402e216abdeb44d415fbe6ae41d56b114723e953711cb" +dependencies = [ + "backtrace", + "cfg-if", + "findshlibs", + "libc", + "log", + "nix", + "once_cell", + "parking_lot", + "prost 0.12.1", + "prost-build 0.12.1", + "prost-derive 0.12.1", + "sha2", + "smallvec", + "symbolic-demangle", + "tempfile", + "thiserror", +] + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -2258,6 +2430,16 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "prettyplease" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d" +dependencies = [ + "proc-macro2", + "syn 2.0.39", +] + [[package]] name = "proc-macro2" version = "1.0.69" @@ -2287,7 +2469,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e48e50df39172a3e7eb17e14642445da64996989bc212b583015435d39a58537" dependencies = [ "bytes", - "prost-derive", + "prost-derive 0.11.8", +] + +[[package]] +name = "prost" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4fdd22f3b9c31b53c060df4a0613a1c7f062d4115a2b984dd15b1858f7e340d" +dependencies = [ + "bytes", + "prost-derive 0.12.1", ] [[package]] @@ -2303,15 +2495,37 @@ dependencies = [ "log", "multimap", "petgraph", - "prettyplease", - "prost", - "prost-types", + "prettyplease 0.1.25", + "prost 0.11.8", + "prost-types 0.11.8", "regex", "syn 1.0.109", "tempfile", "which", ] +[[package]] +name = "prost-build" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bdf592881d821b83d471f8af290226c8d51402259e9bb5be7f9f8bdebbb11ac" +dependencies = [ + "bytes", + "heck", + "itertools", + "log", + "multimap", + "once_cell", + "petgraph", + "prettyplease 0.2.15", + "prost 0.12.1", + "prost-types 0.12.1", + "regex", + "syn 2.0.39", + "tempfile", + "which", +] + [[package]] name = "prost-derive" version = "0.11.8" @@ -2325,13 +2539,35 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "prost-derive" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "265baba7fabd416cf5078179f7d2cbeca4ce7a9041111900675ea7c4cb8a4c32" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn 2.0.39", +] + [[package]] name = "prost-types" version = "0.11.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "379119666929a1afd7a043aa6cf96fa67a6dce9af60c88095a4686dbce4c9c88" dependencies = [ - "prost", + "prost 0.11.8", +] + +[[package]] +name = "prost-types" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e081b29f63d83a4bc75cfc9f3fe424f9156cf92d8a4f0c9407cce9a1b67327cf" +dependencies = [ + "prost 0.12.1", ] [[package]] @@ -2351,9 +2587,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.26" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] @@ -2426,13 +2662,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.7.3" +version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d" +checksum = "12de2eff854e5fa4b1295edd650e227e9d8fb0c9e90b12e7f36d6a6811791a29" dependencies = [ "aho-corasick", "memchr", - "regex-syntax", + "regex-automata 0.3.7", + "regex-syntax 0.7.5", ] [[package]] @@ -2441,7 +2678,18 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" dependencies = [ - "regex-syntax", + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49530408a136e16e5b486e883fbb6ba058e8e4e8ae6621a77b048b314336e629" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.7.5", ] [[package]] @@ -2450,6 +2698,12 @@ version = "0.6.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" +[[package]] +name = "regex-syntax" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" + [[package]] name = "resolv-conf" version = "0.7.0" @@ -2475,6 +2729,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 = "rustc-hash" version = "1.1.0" @@ -2591,6 +2851,17 @@ dependencies = [ "serde", ] +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "sharded-slab" version = "0.1.4" @@ -2646,6 +2917,35 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "symbolic-common" +version = "12.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "405af7bd5edd866cef462e22ef73f11cf9bf506c9d62824fef8364eb69d4d4ad" +dependencies = [ + "debugid", + "memmap2", + "stable_deref_trait", + "uuid", +] + +[[package]] +name = "symbolic-demangle" +version = "12.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bcd041ccfb77d9c70639efcd5b804b508ac7a273e9224d227379e225625daf9" +dependencies = [ + "cpp_demangle", + "rustc-demangle", + "symbolic-common", +] + [[package]] name = "syn" version = "1.0.109" @@ -2659,9 +2959,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.12" +version = "2.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79d9531f94112cfc3e4c8f5f02cb2b58f72c97b7efd85f70203cc6d8efda5927" +checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" dependencies = [ "proc-macro2", "quote", @@ -2881,8 +3181,8 @@ dependencies = [ "hyper-timeout", "percent-encoding", "pin-project", - "prost", - "prost-derive", + "prost 0.11.8", + "prost-derive 0.11.8", "tokio", "tokio-stream", "tokio-util", @@ -2899,9 +3199,9 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5bf5e9b9c0f7e0a7c027dcfaba7b2c60816c7049171f679d99ee2ff65d0de8c4" dependencies = [ - "prettyplease", + "prettyplease 0.1.25", "proc-macro2", - "prost-build", + "prost-build 0.11.8", "quote", "syn 1.0.109", ] @@ -3005,12 +3305,12 @@ dependencies = [ [[package]] name = "tracing-log" -version = "0.1.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" dependencies = [ - "lazy_static", "log", + "once_cell", "tracing-core", ] @@ -3026,9 +3326,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.16" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ "matchers", "nu-ansi-term", @@ -3097,6 +3397,12 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + [[package]] name = "unicode-bidi" version = "0.3.11" @@ -3135,6 +3441,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "uuid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ad59a7560b41a70d191093a945f0b87bc1deeda46fb237479708a1d6b6cdfc" + [[package]] name = "valuable" version = "0.1.0" @@ -3448,5 +3760,5 @@ checksum = "9731702e2f0617ad526794ae28fbc6f6ca8849b5ba729666c2a5bc4b6ddee2cd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.12", + "syn 2.0.39", ] diff --git a/Dockerfile b/Dockerfile index e5f7d2a03..ee515af5c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,11 +7,11 @@ ARG RUST_IMAGE=ghcr.io/linkerd/dev:v42-rust # Use an arbitrary ~recent edge release image to get the proxy # identity-initializing and linkerd-await wrappers. -# Currently pinned to a build off of edge-23.11.1 + dev:v42 -ARG LINKERD2_IMAGE=ghcr.io/olix0r/l2-proxy:git-04283611 +ARG LINKERD2_IMAGE=ghcr.io/linkerd/proxy:edge-23.11.2 -# Build the proxy. -FROM --platform=$BUILDPLATFORM $RUST_IMAGE as build +FROM $LINKERD2_IMAGE as linkerd2 + +FROM --platform=$BUILDPLATFORM $RUST_IMAGE as fetch ARG PROXY_FEATURES="" RUN apt-get update && \ @@ -28,24 +28,27 @@ WORKDIR /src COPY . . RUN --mount=type=cache,id=cargo,target=/usr/local/cargo/registry \ just fetch + +# Build the proxy. +FROM fetch as build ENV CARGO_INCREMENTAL=0 ENV RUSTFLAGS="-D warnings -A deprecated" ARG TARGETARCH="amd64" ARG PROFILE="release" ARG LINKERD2_PROXY_VERSION="" ARG LINKERD2_PROXY_VENDOR="" +SHELL ["/bin/bash", "-c"] RUN --mount=type=cache,id=cargo,target=/usr/local/cargo/registry \ - /usr/bin/time -v just arch="$TARGETARCH" features="$PROXY_FEATURES" profile="$PROFILE" build && \ - bin=$(just --evaluate profile="$PROFILE" _target_bin) ; \ - du -sh "$bin" "$bin".dbg && \ - mkdir -p /out && mv "$bin" /out/linkerd2-proxy + if [[ "$PROXY_FEATURES" =~ .*pprof.* ]] ; then cmd=build-debug ; else cmd=build ; fi ; \ + /usr/bin/time -v just arch="$TARGETARCH" features="$PROXY_FEATURES" profile="$PROFILE" "$cmd" && \ + ( mkdir -p /out ; \ + mv $(just --evaluate profile="$PROFILE" _target_bin) /out/ ; \ + du -sh /out/* ) -FROM $LINKERD2_IMAGE as linkerd2 - -# Install the proxy binary into a base image that we can at least get a shell to -# debug on. +# Install the proxy binary into a base image that we can at least get a shell +# for debugging. FROM docker.io/library/debian:bookworm-slim as runtime WORKDIR /linkerd COPY --from=linkerd2 /usr/lib/linkerd/* /usr/lib/linkerd/ -COPY --from=build /out/linkerd2-proxy /usr/lib/linkerd/linkerd2-proxy +COPY --from=build /out/* /usr/lib/linkerd/ ENTRYPOINT ["/usr/lib/linkerd/linkerd2-proxy-identity"] diff --git a/deny.toml b/deny.toml index 441e22fbf..f059ea1a6 100644 --- a/deny.toml +++ b/deny.toml @@ -76,6 +76,15 @@ skip = [ # `linkerd-trace-context`, `rustls-pemfile` and `tonic` depend on `base64` # v0.13.1 while `rcgen` depends on v0.21.5 { name = "base64" }, + # https://github.com/hawkw/matchers/pull/4 + { name = "regex-automata", version = "0.1" }, + { name = "regex-syntax", version = "0.6" }, + # linkerd2-proxy-api needs to upgrade tonic to upgrade prost... + { name = "prost", version = "0.11" }, + { name = "prost-build", version = "0.11" }, + { name = "prost-derive", version = "0.11" }, + { name = "prost-types", version = "0.11" }, + { name = "prettyplease", version = "0.1" }, ] skip-tree = [ # right now we have a mix of versions of this crate in the ecosystem diff --git a/justfile b/justfile index f8c985d3a..592bb5a53 100644 --- a/justfile +++ b/justfile @@ -116,7 +116,12 @@ test-dir dir *flags: cd {{ dir }} && {{ _cargo }} test --frozen {{ _features }} {{ flags }} # Build the proxy -build: && checksec _strip +build: _build checksec _strip + +# Build the proxy without stripping debug symbols +build-debug: _build + +_build: @rm -f {{ _target_bin }} {{ _target_bin }}.dbg @{{ _cargo }} build --frozen --package=linkerd2-proxy {{ _features }} diff --git a/linkerd/app/Cargo.toml b/linkerd/app/Cargo.toml index eb19e1d92..2221e5a1c 100644 --- a/linkerd/app/Cargo.toml +++ b/linkerd/app/Cargo.toml @@ -14,6 +14,7 @@ This is used by tests and the executable. [features] allow-loopback = ["linkerd-app-outbound/allow-loopback"] log-streaming = ["linkerd-app-admin/log-streaming"] +pprof = ["linkerd-app-admin/pprof"] [dependencies] futures = { version = "0.3", default-features = false } diff --git a/linkerd/app/admin/Cargo.toml b/linkerd/app/admin/Cargo.toml index 7f2208329..ce61556ea 100644 --- a/linkerd/app/admin/Cargo.toml +++ b/linkerd/app/admin/Cargo.toml @@ -10,15 +10,19 @@ The linkerd proxy's admin server. """ [features] +default = [] +pprof = ["deflate", "dep:pprof"] log-streaming = ["linkerd-tracing/stream"] [dependencies] +deflate = { version = "1", optional = true, features = ["gzip"] } http = "0.2" hyper = { version = "0.14", features = ["http1", "http2"] } futures = { version = "0.3", default-features = false } linkerd-app-core = { path = "../core" } linkerd-app-inbound = { path = "../inbound" } linkerd-tracing = { path = "../../tracing" } +pprof = { version = "0.13", optional = true, features = ["prost-codec"] } serde = "1" serde_json = "1" thiserror = "1" diff --git a/linkerd/app/admin/src/lib.rs b/linkerd/app/admin/src/lib.rs index 97c66dc51..e1e1264b1 100644 --- a/linkerd/app/admin/src/lib.rs +++ b/linkerd/app/admin/src/lib.rs @@ -1,6 +1,8 @@ #![deny(rust_2018_idioms, clippy::disallowed_methods, clippy::disallowed_types)] #![forbid(unsafe_code)] +#[cfg(feature = "pprof")] +mod pprof; mod server; mod stack; diff --git a/linkerd/app/admin/src/pprof.rs b/linkerd/app/admin/src/pprof.rs new file mode 100644 index 000000000..ad8c6aac0 --- /dev/null +++ b/linkerd/app/admin/src/pprof.rs @@ -0,0 +1,62 @@ +use linkerd_app_core::Result; + +#[derive(Copy, Clone, Debug)] +pub(crate) struct Pprof; + +impl Pprof { + pub async fn profile(self, req: http::Request) -> Result> { + use pprof::protos::Message; + + fn query_param<'r, B>(req: &'r http::Request, name: &'static str) -> Option<&'r str> { + let params = req.uri().path_and_query()?.query()?.split('&'); + params + .filter_map(|p| p.strip_prefix(name)?.strip_prefix('=')) + .next() + } + + // TODO(ver) Pretty-up error handling if we ever expose this outside of + // development. + let duration = std::time::Duration::from_secs_f64( + query_param(&req, "seconds") + .map(|s| s.parse::()) + .transpose()? + .unwrap_or(30.0), + ); + let frequency = query_param(&req, "frequency") + .map(|s| s.parse::()) + .transpose()? + // Go's default. + .unwrap_or(100); + tracing::info!(?duration, frequency, "Collecting"); + + let report = { + let guard = pprof::ProfilerGuard::new(frequency)?; + tokio::time::sleep(duration).await; + guard.report().build()? + }; + tracing::info!( + ?duration, + frequency, + frames = report.data.len(), + "Collected" + ); + + let pb_gz = { + let mut gz = deflate::write::GzEncoder::new( + Vec::::new(), + deflate::CompressionOptions::fast(), + ); + std::io::Write::write_all(&mut gz, &{ + let mut buf = Vec::new(); + report.pprof()?.encode(&mut buf)?; + buf + })?; + gz.finish()? + }; + + Ok(http::Response::builder() + .header(http::header::CONTENT_TYPE, "application/octet-stream") + .body(hyper::Body::from(pb_gz)) + .expect("response must be valid")) + } +} diff --git a/linkerd/app/admin/src/server.rs b/linkerd/app/admin/src/server.rs index d70b53c5a..eb1c0cfdd 100644 --- a/linkerd/app/admin/src/server.rs +++ b/linkerd/app/admin/src/server.rs @@ -19,7 +19,7 @@ use hyper::{ use linkerd_app_core::{ metrics::{self as metrics, FmtMetrics}, proxy::http::ClientHandle, - trace, Error, + trace, Error, Result, }; use std::{ future::Future, @@ -40,10 +40,11 @@ pub struct Admin { tracing: trace::Handle, ready: Readiness, shutdown_tx: mpsc::UnboundedSender<()>, + #[cfg(feature = "pprof")] + pprof: Option, } -pub type ResponseFuture = - Pin, Error>> + Send + 'static>>; +pub type ResponseFuture = Pin>> + Send + 'static>>; impl Admin { pub fn new( @@ -57,9 +58,18 @@ impl Admin { ready, shutdown_tx, tracing, + + #[cfg(feature = "pprof")] + pprof: None, } } + #[cfg(feature = "pprof")] + pub fn with_profiling(mut self, enabled: bool) -> Self { + self.pprof = enabled.then_some(crate::pprof::Pprof); + self + } + fn ready_rsp(&self) -> Response { if self.ready.is_ready() { Response::builder() @@ -254,6 +264,26 @@ where } } + #[cfg(feature = "pprof")] + "/debug/pprof/profile.pb.gz" if self.pprof.is_some() => { + let pprof = self.pprof.expect("unreachable"); + + if !Self::client_is_localhost(&req) { + return Box::pin(future::ok(Self::forbidden_not_localhost())); + } + + if req.method() != http::Method::GET { + return Box::pin(future::ok(Self::method_not_allowed())); + } + + Box::pin(async move { + Ok(pprof + .profile(req) + .await + .unwrap_or_else(Self::internal_error_rsp)) + }) + } + _ => Box::pin(future::ok(Self::not_found())), } } diff --git a/linkerd/app/admin/src/stack.rs b/linkerd/app/admin/src/stack.rs index 016c46711..97514ae40 100644 --- a/linkerd/app/admin/src/stack.rs +++ b/linkerd/app/admin/src/stack.rs @@ -22,6 +22,8 @@ use tracing::debug; pub struct Config { pub server: ServerConfig, pub metrics_retain_idle: Duration, + #[cfg(feature = "pprof")] + pub enable_profiling: bool, } pub struct Task { @@ -96,7 +98,13 @@ impl Config { let policy = policy.get_policy(OrigDstAddr(listen_addr.into())); let (ready, latch) = crate::server::Readiness::new(); + + #[cfg_attr(not(feature = "pprof"), allow(unused_mut))] let admin = crate::server::Admin::new(report, ready, shutdown, trace); + + #[cfg(feature = "pprof")] + let admin = admin.with_profiling(self.enable_profiling); + let http = svc::stack(move |_| admin.clone()) .push( metrics diff --git a/linkerd/app/src/env.rs b/linkerd/app/src/env.rs index 2892e10f0..a1673b5d4 100644 --- a/linkerd/app/src/env.rs +++ b/linkerd/app/src/env.rs @@ -717,6 +717,12 @@ pub fn parse_config(strings: &S) -> Result keepalive: inbound.proxy.server.keepalive, h2_settings, }, + + // TODO(ver) Currently we always enable profiling when the pprof feature + // is enabled. In the future, this should be driven by runtime + // configuration. + #[cfg(feature = "pprof")] + enable_profiling: true, }; let dns = dns::Config { diff --git a/linkerd/tracing/Cargo.toml b/linkerd/tracing/Cargo.toml index 7bd44147a..c00beec26 100644 --- a/linkerd/tracing/Cargo.toml +++ b/linkerd/tracing/Cargo.toml @@ -17,9 +17,17 @@ slab = { version = "0.4", optional = true } thingbuf = { version = "0.1.2", features = ["std"], optional = true } tokio = { version = "1", features = ["time"] } tracing = "0.1" -tracing-log = "0.1" +tracing-log = "0.2" [dependencies.tracing-subscriber] version = "0.3.16" default-features = false -features = ["env-filter", "fmt", "smallvec", "tracing-log", "json", "parking_lot", "registry"] +features = [ + "env-filter", + "fmt", + "smallvec", + "tracing-log", + "json", + "parking_lot", + "registry", +] diff --git a/linkerd2-proxy/Cargo.toml b/linkerd2-proxy/Cargo.toml index 3197f20ae..8b3af75ab 100644 --- a/linkerd2-proxy/Cargo.toml +++ b/linkerd2-proxy/Cargo.toml @@ -14,6 +14,7 @@ meshtls-boring = ["linkerd-meshtls/boring"] meshtls-boring-fips = ["linkerd-meshtls/boring-fips"] meshtls-rustls = ["linkerd-meshtls/rustls"] log-streaming = ["linkerd-app/log-streaming"] +pprof = ["linkerd-app/pprof"] [dependencies] futures = { version = "0.3", default-features = false }