Merge pull request #940 from zed-industries/telemetry

Antonio Scandurra created

Instrument the collab server with OpenTelemetry collecting into Honeycomb.io

Change summary

Cargo.lock                                   | 507 +++++++++++++++++----
Cargo.toml                                   |  10 
crates/collab/Cargo.toml                     |   9 
crates/collab/k8s/environments/production.sh |   2 
crates/collab/k8s/environments/staging.sh    |   2 
crates/collab/k8s/manifest.template.yml      |  13 
crates/collab/src/db.rs                      |   6 
crates/collab/src/main.rs                    |  60 ++
crates/collab/src/rpc.rs                     | 119 +++-
crates/collab/src/rpc/store.rs               |  28 +
crates/gpui/Cargo.toml                       |   4 
crates/rpc/build.rs                          |   1 
crates/rpc/src/proto.rs                      |   3 
crates/util/src/lib.rs                       |   1 
14 files changed, 612 insertions(+), 153 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -52,6 +52,15 @@ dependencies = [
  "winapi 0.3.9",
 ]
 
+[[package]]
+name = "ansi_term"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
+dependencies = [
+ "winapi 0.3.9",
+]
+
 [[package]]
 name = "anyhow"
 version = "1.0.42"
@@ -115,15 +124,15 @@ dependencies = [
 
 [[package]]
 name = "async-compression"
-version = "0.3.8"
+version = "0.3.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5443ccbb270374a2b1055fc72da40e1f237809cd6bb0e97e66d264cd138473a6"
+checksum = "f2bf394cfbbe876f0ac67b13b6ca819f9c9f2fb9ec67223cceb1555fbab1c31a"
 dependencies = [
  "flate2",
  "futures-core",
  "futures-io",
  "memchr",
- "pin-project-lite 0.2.8",
+ "pin-project-lite 0.2.9",
 ]
 
 [[package]]
@@ -228,6 +237,27 @@ dependencies = [
  "syn",
 ]
 
+[[package]]
+name = "async-stream"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dad5c83079eae9969be7fadefe640a1c566901f05ff91ab221de4b6f68d9507e"
+dependencies = [
+ "async-stream-impl",
+ "futures-core",
+]
+
+[[package]]
+name = "async-stream-impl"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
 [[package]]
 name = "async-task"
 version = "4.0.3"
@@ -267,7 +297,7 @@ dependencies = [
  "futures-io",
  "futures-util",
  "log",
- "pin-project-lite 0.2.8",
+ "pin-project-lite 0.2.9",
  "tungstenite 0.16.0",
 ]
 
@@ -339,9 +369,9 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
 
 [[package]]
 name = "axum"
-version = "0.5.3"
+version = "0.5.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f523b4e98ba6897ae90994bc18423d9877c54f9047b06a00ddc8122a957b1c70"
+checksum = "f4af7447fc1214c1f3a1ace861d0216a6c8bb13965b64bbad9650f375b67689a"
 dependencies = [
  "async-trait",
  "axum-core",
@@ -358,7 +388,7 @@ dependencies = [
  "memchr",
  "mime",
  "percent-encoding",
- "pin-project-lite 0.2.8",
+ "pin-project-lite 0.2.9",
  "serde",
  "serde_json",
  "serde_urlencoded",
@@ -374,9 +404,9 @@ dependencies = [
 
 [[package]]
 name = "axum-core"
-version = "0.2.2"
+version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d3ddbd16eabff8b45f21b98671fddcc93daaa7ac4c84f8473693437226040de5"
+checksum = "3bdc19781b16e32f8a7200368a336fa4509d4b72ef15dd4e41df5290855ee1e6"
 dependencies = [
  "async-trait",
  "bytes",
@@ -444,7 +474,7 @@ dependencies = [
  "cexpr",
  "clang-sys",
  "clap 2.33.3",
- "env_logger 0.8.3",
+ "env_logger",
  "lazy_static",
  "lazycell",
  "log",
@@ -669,7 +699,7 @@ version = "2.33.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
 dependencies = [
- "ansi_term",
+ "ansi_term 0.11.0",
  "atty",
  "bitflags",
  "strsim 0.8.0",
@@ -680,16 +710,16 @@ dependencies = [
 
 [[package]]
 name = "clap"
-version = "3.1.8"
+version = "3.1.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "71c47df61d9e16dc010b55dba1952a57d8c215dbb533fd13cdd13369aac73b1c"
+checksum = "7c167e37342afc5f33fd87bbc870cedd020d2a6dffa05d45ccd9241fbdd146db"
 dependencies = [
  "atty",
  "bitflags",
  "clap_derive",
+ "clap_lex",
  "indexmap",
  "lazy_static",
- "os_str_bytes",
  "strsim 0.10.0",
  "termcolor",
  "textwrap 0.15.0",
@@ -708,12 +738,21 @@ dependencies = [
  "syn",
 ]
 
+[[package]]
+name = "clap_lex"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "189ddd3b5d32a70b35e7686054371742a937b0d99128e76dde6340210e966669"
+dependencies = [
+ "os_str_bytes",
+]
+
 [[package]]
 name = "cli"
 version = "0.1.0"
 dependencies = [
  "anyhow",
- "clap 3.1.8",
+ "clap 3.1.12",
  "core-foundation",
  "core-services",
  "dirs 3.0.1",
@@ -767,7 +806,7 @@ dependencies = [
 [[package]]
 name = "cocoa"
 version = "0.24.0"
-source = "git+https://github.com/servo/core-foundation-rs?rev=025dcb3c0d1ef01530f57ef65f3b1deb948f5737#025dcb3c0d1ef01530f57ef65f3b1deb948f5737"
+source = "git+https://github.com/servo/core-foundation-rs?rev=079665882507dd5e2ff77db3de5070c1f6c0fb85#079665882507dd5e2ff77db3de5070c1f6c0fb85"
 dependencies = [
  "bitflags",
  "block",
@@ -781,8 +820,8 @@ dependencies = [
 
 [[package]]
 name = "cocoa-foundation"
-version = "0.1.0"
-source = "git+https://github.com/servo/core-foundation-rs?rev=025dcb3c0d1ef01530f57ef65f3b1deb948f5737#025dcb3c0d1ef01530f57ef65f3b1deb948f5737"
+version = "0.1.1"
+source = "git+https://github.com/servo/core-foundation-rs?rev=079665882507dd5e2ff77db3de5070c1f6c0fb85#079665882507dd5e2ff77db3de5070c1f6c0fb85"
 dependencies = [
  "bitflags",
  "block",
@@ -806,16 +845,17 @@ dependencies = [
  "collections",
  "ctor",
  "editor",
- "env_logger 0.8.3",
+ "env_logger",
  "envy",
  "futures",
  "gpui",
- "json_env_logger",
  "language",
  "lazy_static",
  "lipsum",
  "log",
  "lsp",
+ "opentelemetry",
+ "opentelemetry-otlp",
  "parking_lot",
  "project",
  "rand 0.8.3",
@@ -831,7 +871,11 @@ dependencies = [
  "tokio",
  "tokio-tungstenite",
  "toml",
+ "tonic",
  "tower",
+ "tracing",
+ "tracing-opentelemetry",
+ "tracing-subscriber",
  "util",
  "workspace",
 ]
@@ -855,7 +899,7 @@ version = "0.1.0"
 dependencies = [
  "ctor",
  "editor",
- "env_logger 0.8.3",
+ "env_logger",
  "fuzzy",
  "gpui",
  "picker",
@@ -895,8 +939,8 @@ dependencies = [
 
 [[package]]
 name = "core-foundation"
-version = "0.9.1"
-source = "git+https://github.com/servo/core-foundation-rs?rev=025dcb3c0d1ef01530f57ef65f3b1deb948f5737#025dcb3c0d1ef01530f57ef65f3b1deb948f5737"
+version = "0.9.3"
+source = "git+https://github.com/servo/core-foundation-rs?rev=079665882507dd5e2ff77db3de5070c1f6c0fb85#079665882507dd5e2ff77db3de5070c1f6c0fb85"
 dependencies = [
  "core-foundation-sys",
  "libc",
@@ -904,13 +948,13 @@ dependencies = [
 
 [[package]]
 name = "core-foundation-sys"
-version = "0.8.2"
-source = "git+https://github.com/servo/core-foundation-rs?rev=025dcb3c0d1ef01530f57ef65f3b1deb948f5737#025dcb3c0d1ef01530f57ef65f3b1deb948f5737"
+version = "0.8.3"
+source = "git+https://github.com/servo/core-foundation-rs?rev=079665882507dd5e2ff77db3de5070c1f6c0fb85#079665882507dd5e2ff77db3de5070c1f6c0fb85"
 
 [[package]]
 name = "core-graphics"
-version = "0.22.2"
-source = "git+https://github.com/servo/core-foundation-rs?rev=025dcb3c0d1ef01530f57ef65f3b1deb948f5737#025dcb3c0d1ef01530f57ef65f3b1deb948f5737"
+version = "0.22.3"
+source = "git+https://github.com/servo/core-foundation-rs?rev=079665882507dd5e2ff77db3de5070c1f6c0fb85#079665882507dd5e2ff77db3de5070c1f6c0fb85"
 dependencies = [
  "bitflags",
  "core-foundation",
@@ -922,7 +966,7 @@ dependencies = [
 [[package]]
 name = "core-graphics-types"
 version = "0.1.1"
-source = "git+https://github.com/servo/core-foundation-rs?rev=025dcb3c0d1ef01530f57ef65f3b1deb948f5737#025dcb3c0d1ef01530f57ef65f3b1deb948f5737"
+source = "git+https://github.com/servo/core-foundation-rs?rev=079665882507dd5e2ff77db3de5070c1f6c0fb85#079665882507dd5e2ff77db3de5070c1f6c0fb85"
 dependencies = [
  "bitflags",
  "core-foundation",
@@ -1304,7 +1348,7 @@ dependencies = [
  "clock",
  "collections",
  "ctor",
- "env_logger 0.8.3",
+ "env_logger",
  "futures",
  "fuzzy",
  "gpui",
@@ -1350,15 +1394,6 @@ dependencies = [
  "cfg-if 1.0.0",
 ]
 
-[[package]]
-name = "env_logger"
-version = "0.7.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
-dependencies = [
- "log",
-]
-
 [[package]]
 name = "env_logger"
 version = "0.8.3"
@@ -1440,7 +1475,7 @@ version = "0.1.0"
 dependencies = [
  "ctor",
  "editor",
- "env_logger 0.8.3",
+ "env_logger",
  "fuzzy",
  "gpui",
  "picker",
@@ -1459,6 +1494,12 @@ version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d"
 
+[[package]]
+name = "fixedbitset"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "279fb028e20b3c4c320317955b77c5e0c9701f05a1d309905d6fc702cdc5053e"
+
 [[package]]
 name = "flate2"
 version = "1.0.20"
@@ -1676,7 +1717,7 @@ dependencies = [
  "futures-io",
  "memchr",
  "parking",
- "pin-project-lite 0.2.8",
+ "pin-project-lite 0.2.9",
  "waker-fn",
 ]
 
@@ -1716,7 +1757,7 @@ dependencies = [
  "futures-sink",
  "futures-task",
  "memchr",
- "pin-project-lite 0.2.8",
+ "pin-project-lite 0.2.9",
  "pin-utils",
  "slab",
 ]
@@ -1838,7 +1879,7 @@ dependencies = [
  "core-text",
  "ctor",
  "dhat",
- "env_logger 0.8.3",
+ "env_logger",
  "etagere",
  "font-kit",
  "foreign-types",
@@ -1883,6 +1924,25 @@ dependencies = [
  "syn",
 ]
 
+[[package]]
+name = "h2"
+version = "0.3.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37a82c6d637fc9515a4694bbf1cb2457b79d81ce52b3108bdeea58b07dd34a57"
+dependencies = [
+ "bytes",
+ "fnv",
+ "futures-core",
+ "futures-sink",
+ "futures-util",
+ "http",
+ "indexmap",
+ "slab",
+ "tokio",
+ "tokio-util 0.7.1",
+ "tracing",
+]
+
 [[package]]
 name = "hashbrown"
 version = "0.9.1"
@@ -2010,7 +2070,7 @@ checksum = "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6"
 dependencies = [
  "bytes",
  "http",
- "pin-project-lite 0.2.8",
+ "pin-project-lite 0.2.9",
 ]
 
 [[package]]
@@ -2047,12 +2107,13 @@ dependencies = [
  "futures-channel",
  "futures-core",
  "futures-util",
+ "h2",
  "http",
  "http-body",
  "httparse",
  "httpdate",
  "itoa 1.0.1",
- "pin-project-lite 0.2.8",
+ "pin-project-lite 0.2.9",
  "socket2 0.4.0",
  "tokio",
  "tower-service",
@@ -2060,6 +2121,18 @@ dependencies = [
  "want",
 ]
 
+[[package]]
+name = "hyper-timeout"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1"
+dependencies = [
+ "hyper",
+ "pin-project-lite 0.2.9",
+ "tokio",
+ "tokio-io-timeout",
+]
+
 [[package]]
 name = "idna"
 version = "0.2.3"
@@ -2258,18 +2331,6 @@ version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "41ee439ee368ba4a77ac70d04f14015415af8600d6c894dc1f11bd79758c57d5"
 
-[[package]]
-name = "json_env_logger"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4e2ec540ea0448b187d3a8b4a9f13e75527d06ef76b3a2baa1cd982aecb62ce2"
-dependencies = [
- "env_logger 0.7.1",
- "kv-log-macro",
- "log",
- "serde_json",
-]
-
 [[package]]
 name = "kernel32-sys"
 version = "0.2.2"
@@ -2289,15 +2350,6 @@ dependencies = [
  "arrayvec 0.5.2",
 ]
 
-[[package]]
-name = "kv-log-macro"
-version = "1.0.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f"
-dependencies = [
- "log",
-]
-
 [[package]]
 name = "language"
 version = "0.1.0"
@@ -2309,7 +2361,7 @@ dependencies = [
  "clock",
  "collections",
  "ctor",
- "env_logger 0.8.3",
+ "env_logger",
  "futures",
  "fuzzy",
  "gpui",
@@ -2476,7 +2528,7 @@ dependencies = [
  "async-pipe",
  "collections",
  "ctor",
- "env_logger 0.8.3",
+ "env_logger",
  "futures",
  "gpui",
  "log",
@@ -2880,6 +2932,45 @@ dependencies = [
  "vcpkg",
 ]
 
+[[package]]
+name = "opentelemetry"
+version = "0.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6105e89802af13fdf48c49d7646d3b533a70e536d818aae7e78ba0433d01acb8"
+dependencies = [
+ "async-trait",
+ "crossbeam-channel 0.5.0",
+ "futures-channel",
+ "futures-executor",
+ "futures-util",
+ "js-sys",
+ "lazy_static",
+ "percent-encoding",
+ "pin-project",
+ "rand 0.8.3",
+ "thiserror",
+ "tokio",
+ "tokio-stream",
+]
+
+[[package]]
+name = "opentelemetry-otlp"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9d1a6ca9de4c8b00aa7f1a153bd76cb263287155cec642680d79d98706f3d28a"
+dependencies = [
+ "async-trait",
+ "futures",
+ "futures-util",
+ "http",
+ "opentelemetry",
+ "prost 0.9.0",
+ "thiserror",
+ "tokio",
+ "tonic",
+ "tonic-build",
+]
+
 [[package]]
 name = "ordered-float"
 version = "2.1.1"
@@ -2894,9 +2985,6 @@ name = "os_str_bytes"
 version = "6.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64"
-dependencies = [
- "memchr",
-]
 
 [[package]]
 name = "outline"
@@ -3023,7 +3111,17 @@ version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7"
 dependencies = [
- "fixedbitset",
+ "fixedbitset 0.2.0",
+ "indexmap",
+]
+
+[[package]]
+name = "petgraph"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4a13a2fa9d0b63e5f22328828741e523766fff0ee9e779316902290dff3f824f"
+dependencies = [
+ "fixedbitset 0.4.1",
  "indexmap",
 ]
 
@@ -3033,7 +3131,7 @@ version = "0.1.0"
 dependencies = [
  "ctor",
  "editor",
- "env_logger 0.8.3",
+ "env_logger",
  "gpui",
  "serde_json",
  "settings",
@@ -3076,9 +3174,9 @@ checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777"
 
 [[package]]
 name = "pin-project-lite"
-version = "0.2.8"
+version = "0.2.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c"
+checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
 
 [[package]]
 name = "pin-utils"
@@ -3280,7 +3378,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "de5e2533f59d08fcf364fd374ebda0692a70bd6d7e66ef97f306f45c6c5d8020"
 dependencies = [
  "bytes",
- "prost-derive",
+ "prost-derive 0.8.0",
+]
+
+[[package]]
+name = "prost"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "444879275cb4fd84958b1a1d5420d15e6fcf7c235fe47f053c9c2a80aceb6001"
+dependencies = [
+ "bytes",
+ "prost-derive 0.9.0",
 ]
 
 [[package]]
@@ -3294,9 +3402,29 @@ dependencies = [
  "itertools",
  "log",
  "multimap",
- "petgraph",
- "prost",
- "prost-types",
+ "petgraph 0.5.1",
+ "prost 0.8.0",
+ "prost-types 0.8.0",
+ "tempfile",
+ "which 4.1.0",
+]
+
+[[package]]
+name = "prost-build"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62941722fb675d463659e49c4f3fe1fe792ff24fe5bbaa9c08cd3b98a1c354f5"
+dependencies = [
+ "bytes",
+ "heck 0.3.3",
+ "itertools",
+ "lazy_static",
+ "log",
+ "multimap",
+ "petgraph 0.6.0",
+ "prost 0.9.0",
+ "prost-types 0.9.0",
+ "regex",
  "tempfile",
  "which 4.1.0",
 ]
@@ -3314,6 +3442,19 @@ dependencies = [
  "syn",
 ]
 
+[[package]]
+name = "prost-derive"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f9cc1a3263e07e0bf68e96268f37665207b49560d98739662cdfaae215c720fe"
+dependencies = [
+ "anyhow",
+ "itertools",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
 [[package]]
 name = "prost-types"
 version = "0.8.0"
@@ -3321,7 +3462,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "603bbd6394701d13f3f25aada59c7de9d35a6a5887cfc156181234a44002771b"
 dependencies = [
  "bytes",
- "prost",
+ "prost 0.8.0",
+]
+
+[[package]]
+name = "prost-types"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "534b7a0e836e3c482d2693070f982e39e7611da9695d4d1f5a4b186b51faef0a"
+dependencies = [
+ "bytes",
+ "prost 0.9.0",
 ]
 
 [[package]]
@@ -3596,8 +3747,8 @@ dependencies = [
  "gpui",
  "log",
  "parking_lot",
- "prost",
- "prost-build",
+ "prost 0.8.0",
+ "prost-build 0.8.0",
  "rand 0.8.3",
  "rsa",
  "serde",
@@ -3697,6 +3848,18 @@ dependencies = [
  "webpki",
 ]
 
+[[package]]
+name = "rustls-native-certs"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a07b7c1885bd8ed3831c289b7870b13ef46fe0e856d288c30d9cc17d75a2092"
+dependencies = [
+ "openssl-probe",
+ "rustls",
+ "schannel",
+ "security-framework",
+]
+
 [[package]]
 name = "rustybuzz"
 version = "0.3.0"
@@ -3855,6 +4018,29 @@ dependencies = [
  "workspace",
 ]
 
+[[package]]
+name = "security-framework"
+version = "2.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "525bc1abfda2e1998d152c45cf13e696f76d0a4972310b22fac1658b05df7c87"
+dependencies = [
+ "bitflags",
+ "core-foundation",
+ "core-foundation-sys",
+ "libc",
+ "security-framework-sys",
+]
+
+[[package]]
+name = "security-framework-sys"
+version = "2.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+]
+
 [[package]]
 name = "semver"
 version = "0.9.0"
@@ -4047,6 +4233,15 @@ dependencies = [
  "digest 0.10.3",
 ]
 
+[[package]]
+name = "sharded-slab"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31"
+dependencies = [
+ "lazy_static",
+]
+
 [[package]]
 name = "shlex"
 version = "1.0.0"
@@ -4406,7 +4601,7 @@ version = "0.1.0"
 dependencies = [
  "arrayvec 0.7.1",
  "ctor",
- "env_logger 0.8.3",
+ "env_logger",
  "log",
  "rand 0.8.3",
 ]
@@ -4523,7 +4718,7 @@ dependencies = [
  "clock",
  "collections",
  "ctor",
- "env_logger 0.8.3",
+ "env_logger",
  "gpui",
  "lazy_static",
  "log",
@@ -4609,9 +4804,9 @@ checksum = "3bf63baf9f5039dadc247375c29eb13706706cfde997d0330d05aa63a77d8820"
 
 [[package]]
 name = "thread_local"
-version = "1.1.3"
+version = "1.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd"
+checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180"
 dependencies = [
  "once_cell",
 ]
@@ -4742,12 +4937,22 @@ dependencies = [
  "num_cpus",
  "once_cell",
  "parking_lot",
- "pin-project-lite 0.2.8",
+ "pin-project-lite 0.2.9",
  "signal-hook-registry",
  "tokio-macros",
  "winapi 0.3.9",
 ]
 
+[[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.9",
+ "tokio",
+]
+
 [[package]]
 name = "tokio-macros"
 version = "1.7.0"
@@ -4777,7 +4982,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "50145484efff8818b5ccd256697f36863f587da82cf8b409c53adf1e840798e3"
 dependencies = [
  "futures-core",
- "pin-project-lite 0.2.8",
+ "pin-project-lite 0.2.9",
  "tokio",
 ]
 
@@ -4793,6 +4998,20 @@ dependencies = [
  "tungstenite 0.17.2",
 ]
 
+[[package]]
+name = "tokio-util"
+version = "0.6.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9e99e1983e5d376cd8eb4b66604d2e99e79f5bd988c3055891dcd8c9e2604cc0"
+dependencies = [
+ "bytes",
+ "futures-core",
+ "futures-sink",
+ "log",
+ "pin-project-lite 0.2.9",
+ "tokio",
+]
+
 [[package]]
 name = "tokio-util"
 version = "0.7.1"
@@ -4802,8 +5021,9 @@ dependencies = [
  "bytes",
  "futures-core",
  "futures-sink",
- "pin-project-lite 0.2.8",
+ "pin-project-lite 0.2.9",
  "tokio",
+ "tracing",
 ]
 
 [[package]]
@@ -4815,6 +5035,51 @@ dependencies = [
  "serde",
 ]
 
+[[package]]
+name = "tonic"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ff08f4649d10a70ffa3522ca559031285d8e421d727ac85c60825761818f5d0a"
+dependencies = [
+ "async-stream",
+ "async-trait",
+ "base64 0.13.0",
+ "bytes",
+ "futures-core",
+ "futures-util",
+ "h2",
+ "http",
+ "http-body",
+ "hyper",
+ "hyper-timeout",
+ "percent-encoding",
+ "pin-project",
+ "prost 0.9.0",
+ "prost-derive 0.9.0",
+ "rustls-native-certs",
+ "tokio",
+ "tokio-rustls",
+ "tokio-stream",
+ "tokio-util 0.6.9",
+ "tower",
+ "tower-layer",
+ "tower-service",
+ "tracing",
+ "tracing-futures",
+]
+
+[[package]]
+name = "tonic-build"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9403f1bafde247186684b230dc6f38b5cd514584e8bec1dd32514be4745fa757"
+dependencies = [
+ "proc-macro2",
+ "prost-build 0.9.0",
+ "quote",
+ "syn",
+]
+
 [[package]]
 name = "tower"
 version = "0.4.12"
@@ -4823,10 +5088,13 @@ checksum = "9a89fd63ad6adf737582df5db40d286574513c69a11dac5214dc3b5603d6713e"
 dependencies = [
  "futures-core",
  "futures-util",
+ "indexmap",
  "pin-project",
- "pin-project-lite 0.2.8",
+ "pin-project-lite 0.2.9",
+ "rand 0.8.3",
+ "slab",
  "tokio",
- "tokio-util",
+ "tokio-util 0.7.1",
  "tower-layer",
  "tower-service",
  "tracing",
@@ -4834,9 +5102,9 @@ dependencies = [
 
 [[package]]
 name = "tower-http"
-version = "0.2.5"
+version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aba3f3efabf7fb41fae8534fc20a817013dd1c12cb45441efb6c82e6556b4cd8"
+checksum = "79dd37121c38240c4b4fe6520332406218bbf876f2f690fe9e406020189366fd"
 dependencies = [
  "bitflags",
  "bytes",
@@ -4845,7 +5113,7 @@ dependencies = [
  "http",
  "http-body",
  "http-range-header",
- "pin-project-lite 0.2.8",
+ "pin-project-lite 0.2.9",
  "tower",
  "tower-layer",
  "tower-service",
@@ -4871,7 +5139,7 @@ checksum = "09adeb8c97449311ccd28a427f96fb563e7fd31aabf994189879d9da2394b89d"
 dependencies = [
  "cfg-if 1.0.0",
  "log",
- "pin-project-lite 0.2.8",
+ "pin-project-lite 0.2.9",
  "tracing-attributes",
  "tracing-core",
 ]
@@ -4889,11 +5157,12 @@ dependencies = [
 
 [[package]]
 name = "tracing-core"
-version = "0.1.18"
+version = "0.1.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a9ff14f98b1a4b289c6248a023c1c2fa1491062964e9fed67ab29c4e4da4a052"
+checksum = "f54c8ca710e81886d498c2fd3331b56c93aa248d49de2222ad2742247c60072f"
 dependencies = [
  "lazy_static",
+ "valuable",
 ]
 
 [[package]]
@@ -4906,6 +5175,44 @@ dependencies = [
  "tracing",
 ]
 
+[[package]]
+name = "tracing-log"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922"
+dependencies = [
+ "lazy_static",
+ "log",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-opentelemetry"
+version = "0.17.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f9378e96a9361190ae297e7f3a8ff644aacd2897f244b1ff81f381669196fa6"
+dependencies = [
+ "opentelemetry",
+ "tracing",
+ "tracing-core",
+ "tracing-log",
+ "tracing-subscriber",
+]
+
+[[package]]
+name = "tracing-subscriber"
+version = "0.3.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4bc28f93baff38037f64e6f43d34cfa1605f27a49c34e8a04c5e78b0babf2596"
+dependencies = [
+ "ansi_term 0.12.1",
+ "sharded-slab",
+ "smallvec",
+ "thread_local",
+ "tracing-core",
+ "tracing-log",
+]
+
 [[package]]
 name = "tree-sitter"
 version = "0.20.4"
@@ -5205,6 +5512,12 @@ dependencies = [
  "getrandom 0.2.2",
 ]
 
+[[package]]
+name = "valuable"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
+
 [[package]]
 name = "value-bag"
 version = "1.0.0-alpha.8"
@@ -5559,7 +5872,7 @@ dependencies = [
  "dirs 3.0.1",
  "easy-parallel",
  "editor",
- "env_logger 0.8.3",
+ "env_logger",
  "file_finder",
  "fsevent",
  "futures",

Cargo.toml 🔗

@@ -6,11 +6,11 @@ resolver = "2"
 [patch.crates-io]
 async-task = { git = "https://github.com/zed-industries/async-task", rev = "341b57d6de98cdfd7b418567b8de2022ca993a6e" }
 # TODO - Remove when a version is released with this PR: https://github.com/servo/core-foundation-rs/pull/457
-cocoa = { git = "https://github.com/servo/core-foundation-rs", rev = "025dcb3c0d1ef01530f57ef65f3b1deb948f5737" }
-cocoa-foundation = { git = "https://github.com/servo/core-foundation-rs", rev = "025dcb3c0d1ef01530f57ef65f3b1deb948f5737" }
-core-foundation = { git = "https://github.com/servo/core-foundation-rs", rev = "025dcb3c0d1ef01530f57ef65f3b1deb948f5737" }
-core-foundation-sys = { git = "https://github.com/servo/core-foundation-rs", rev = "025dcb3c0d1ef01530f57ef65f3b1deb948f5737" }
-core-graphics = { git = "https://github.com/servo/core-foundation-rs", rev = "025dcb3c0d1ef01530f57ef65f3b1deb948f5737" }
+cocoa = { git = "https://github.com/servo/core-foundation-rs", rev = "079665882507dd5e2ff77db3de5070c1f6c0fb85" }
+cocoa-foundation = { git = "https://github.com/servo/core-foundation-rs", rev = "079665882507dd5e2ff77db3de5070c1f6c0fb85" }
+core-foundation = { git = "https://github.com/servo/core-foundation-rs", rev = "079665882507dd5e2ff77db3de5070c1f6c0fb85" }
+core-foundation-sys = { git = "https://github.com/servo/core-foundation-rs", rev = "079665882507dd5e2ff77db3de5070c1f6c0fb85" }
+core-graphics = { git = "https://github.com/servo/core-foundation-rs", rev = "079665882507dd5e2ff77db3de5070c1f6c0fb85" }
 
 [profile.dev]
 split-debuginfo = "unpacked"

crates/collab/Cargo.toml 🔗

@@ -25,21 +25,26 @@ base64 = "0.13"
 envy = "0.4.2"
 env_logger = "0.8"
 futures = "0.3"
-json_env_logger = "0.1"
 lazy_static = "1.4"
 lipsum = { version = "0.8", optional = true }
 log = { version = "0.4.16", features = ["kv_unstable_serde"] }
+opentelemetry = { version = "0.17", features = ["rt-tokio"] }
+opentelemetry-otlp = { version = "0.10", features = ["tls-roots"] }
 parking_lot = "0.11.1"
 rand = "0.8"
 scrypt = "0.7"
 serde = { version = "1.0", features = ["derive"] }
 serde_json = "1.0"
 sha-1 = "0.9"
+time = "0.2"
 tokio = { version = "1", features = ["full"] }
 tokio-tungstenite = "0.17"
+tonic = "0.6"
 tower = "0.4"
-time = "0.2"
 toml = "0.5.8"
+tracing = "0.1"
+tracing-opentelemetry = "0.17"
+tracing-subscriber = "0.3"
 
 [dependencies.sqlx]
 version = "0.5.2"

crates/collab/k8s/manifest.template.yml 🔗

@@ -81,10 +81,17 @@ spec:
                 secretKeyRef:
                   name: api
                   key: token
-            - name: LOG_JSON
-              value: "1"
             - name: RUST_LOG
-              value: "trace"
+              value: ${RUST_LOG}
+            - name: TRACE_LEVEL
+              value: ${TRACE_LEVEL}
+            - name: HONEYCOMB_DATASET
+              value: "collab"
+            - name: HONEYCOMB_API_KEY
+              valueFrom:
+                secretKeyRef:
+                  name: honeycomb
+                  key: apiKey
           securityContext:
             capabilities:
               # FIXME - Switch to the more restrictive `PERFMON` capability.

crates/collab/src/db.rs 🔗

@@ -431,6 +431,12 @@ macro_rules! id_type {
                 self.0 as u64
             }
         }
+
+        impl std::fmt::Display for $name {
+            fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+                self.0.fmt(f)
+            }
+        }
     };
 }
 

crates/collab/src/main.rs 🔗

@@ -6,18 +6,21 @@ mod rpc;
 
 use axum::{body::Body, http::StatusCode, response::IntoResponse, Router};
 use db::{Db, PostgresDb};
-
 use serde::Deserialize;
 use std::{
     net::{SocketAddr, TcpListener},
     sync::Arc,
 };
+use tracing::metadata::LevelFilter;
 
 #[derive(Default, Deserialize)]
 pub struct Config {
     pub http_port: u16,
     pub database_url: String,
     pub api_token: String,
+    pub honeycomb_api_key: Option<String>,
+    pub honeycomb_dataset: Option<String>,
+    pub trace_level: Option<String>,
 }
 
 pub struct AppState {
@@ -38,11 +41,7 @@ impl AppState {
 
 #[tokio::main]
 async fn main() -> Result<()> {
-    if std::env::var("LOG_JSON").is_ok() {
-        json_env_logger::init();
-    } else {
-        env_logger::init();
-    }
+    env_logger::init();
 
     if let Err(error) = env::load_dotenv() {
         log::error!(
@@ -52,6 +51,7 @@ async fn main() -> Result<()> {
     }
 
     let config = envy::from_env::<Config>().expect("error loading config");
+    init_tracing(&config);
     let state = AppState::new(&config).await?;
 
     let listener = TcpListener::bind(&format!("0.0.0.0:{}", config.http_port))
@@ -112,3 +112,51 @@ impl std::fmt::Display for Error {
         }
     }
 }
+
+pub fn init_tracing(config: &Config) -> Option<()> {
+    use opentelemetry::KeyValue;
+    use opentelemetry_otlp::WithExportConfig;
+    use std::str::FromStr;
+    use tracing_opentelemetry::OpenTelemetryLayer;
+    use tracing_subscriber::layer::SubscriberExt;
+
+    let (honeycomb_api_key, honeycomb_dataset) = config
+        .honeycomb_api_key
+        .clone()
+        .zip(config.honeycomb_dataset.clone())?;
+
+    let mut metadata = tonic::metadata::MetadataMap::new();
+    metadata.insert("x-honeycomb-team", honeycomb_api_key.parse().unwrap());
+    let tracer = opentelemetry_otlp::new_pipeline()
+        .tracing()
+        .with_exporter(
+            opentelemetry_otlp::new_exporter()
+                .tonic()
+                .with_endpoint("https://api.honeycomb.io")
+                .with_metadata(metadata),
+        )
+        .with_trace_config(opentelemetry::sdk::trace::config().with_resource(
+            opentelemetry::sdk::Resource::new(vec![KeyValue::new(
+                "service.name",
+                honeycomb_dataset,
+            )]),
+        ))
+        .install_batch(opentelemetry::runtime::Tokio)
+        .expect("failed to initialize tracing");
+
+    let subscriber = tracing_subscriber::Registry::default()
+        .with(OpenTelemetryLayer::new(tracer))
+        .with(tracing_subscriber::fmt::layer())
+        .with(
+            config
+                .trace_level
+                .as_ref()
+                .map_or(LevelFilter::INFO, |level| {
+                    LevelFilter::from_str(level).unwrap()
+                }),
+        );
+
+    tracing::subscriber::set_global_default(subscriber).unwrap();
+
+    None
+}

crates/collab/src/rpc.rs 🔗

@@ -25,7 +25,6 @@ use axum::{
 use collections::{HashMap, HashSet};
 use futures::{channel::mpsc, future::BoxFuture, FutureExt, SinkExt, StreamExt, TryStreamExt};
 use lazy_static::lazy_static;
-use log::{as_debug, as_display};
 use rpc::{
     proto::{self, AnyTypedEnvelope, EntityMessage, EnvelopedMessage, RequestMessage},
     Connection, ConnectionId, Peer, TypedEnvelope,
@@ -38,7 +37,7 @@ use std::{
     ops::{Deref, DerefMut},
     rc::Rc,
     sync::Arc,
-    time::{Duration, Instant},
+    time::Duration,
 };
 use store::{Store, Worktree};
 use time::OffsetDateTime;
@@ -47,11 +46,10 @@ use tokio::{
     time::Sleep,
 };
 use tower::ServiceBuilder;
-use util::ResultExt;
+use tracing::{info_span, instrument, Instrument};
 
-type MessageHandler = Box<
-    dyn Send + Sync + Fn(Arc<Server>, Box<dyn AnyTypedEnvelope>) -> BoxFuture<'static, Result<()>>,
->;
+type MessageHandler =
+    Box<dyn Send + Sync + Fn(Arc<Server>, Box<dyn AnyTypedEnvelope>) -> BoxFuture<'static, ()>>;
 
 pub struct Server {
     peer: Arc<Peer>,
@@ -156,7 +154,21 @@ impl Server {
             TypeId::of::<M>(),
             Box::new(move |server, envelope| {
                 let envelope = envelope.into_any().downcast::<TypedEnvelope<M>>().unwrap();
-                (handler)(server, *envelope).boxed()
+                let span = info_span!(
+                    "handle message",
+                    payload_type = envelope.payload_type_name(),
+                    payload = serde_json::to_string_pretty(&envelope.payload)
+                        .unwrap()
+                        .as_str(),
+                );
+                let future = (handler)(server, *envelope);
+                async move {
+                    if let Err(error) = future.await {
+                        tracing::error!(%error, "error handling message");
+                    }
+                }
+                .instrument(span)
+                .boxed()
             }),
         );
         if prev_handler.is_some() {
@@ -209,7 +221,7 @@ impl Server {
             let receipt = envelope.receipt();
             let handler = handler.clone();
             async move {
-                let mut store = server.store.write().await;
+                let mut store = server.state_mut().await;
                 let response = (handler)(server.clone(), &mut *store, envelope);
                 match response {
                     Ok(response) => {
@@ -233,12 +245,13 @@ impl Server {
     pub fn handle_connection<E: Executor>(
         self: &Arc<Self>,
         connection: Connection,
-        addr: String,
+        address: String,
         user_id: UserId,
         mut send_connection_id: Option<mpsc::Sender<ConnectionId>>,
         executor: E,
     ) -> impl Future<Output = ()> {
         let mut this = self.clone();
+        let span = info_span!("handle connection", %user_id, %address);
         async move {
             let (connection_id, handle_io, mut incoming_rx) = this
                 .peer
@@ -253,6 +266,8 @@ impl Server {
                 })
                 .await;
 
+            tracing::info!(%user_id, %connection_id, %address, "connection opened");
+
             if let Some(send_connection_id) = send_connection_id.as_mut() {
                 let _ = send_connection_id.send(connection_id).await;
             }
@@ -270,50 +285,47 @@ impl Server {
                 futures::pin_mut!(next_message);
                 futures::select_biased! {
                     result = handle_io => {
-                        if let Err(err) = result {
-                            log::error!("error handling rpc connection {:?} - {:?}", addr, err);
+                        if let Err(error) = result {
+                            tracing::error!(%error, "error handling I/O");
                         }
                         break;
                     }
                     message = next_message => {
                         if let Some(message) = message {
-                            let start_time = Instant::now();
                             let type_name = message.payload_type_name();
-                            log::info!(connection_id = connection_id.0, type_name = type_name; "rpc message received");
-                            if let Some(handler) = this.handlers.get(&message.payload_type_id()) {
-                                let notifications = this.notifications.clone();
-                                let is_background = message.is_background();
-                                let handle_message = (handler)(this.clone(), message);
-                                let handle_message = async move {
-                                    if let Err(err) = handle_message.await {
-                                        log::error!(connection_id = connection_id.0, type = type_name, error = as_display!(err); "rpc message error");
+                            let span = tracing::info_span!("receive message", %user_id, %connection_id, %address, type_name);
+                            async {
+                                if let Some(handler) = this.handlers.get(&message.payload_type_id()) {
+                                    let notifications = this.notifications.clone();
+                                    let is_background = message.is_background();
+                                    let handle_message = (handler)(this.clone(), message);
+                                    let handle_message = async move {
+                                        handle_message.await;
+                                        if let Some(mut notifications) = notifications {
+                                            let _ = notifications.send(()).await;
+                                        }
+                                    };
+                                    if is_background {
+                                        executor.spawn_detached(handle_message);
                                     } else {
-                                        log::info!(connection_id = connection_id.0, type = type_name, duration = as_debug!(start_time.elapsed()); "rpc message handled");
+                                        handle_message.await;
                                     }
-                                    if let Some(mut notifications) = notifications {
-                                        let _ = notifications.send(()).await;
-                                    }
-                                };
-                                if is_background {
-                                    executor.spawn_detached(handle_message);
                                 } else {
-                                    handle_message.await;
+                                    tracing::error!("no message handler");
                                 }
-                            } else {
-                                log::warn!("unhandled message: {}", type_name);
-                            }
+                            }.instrument(span).await;
                         } else {
-                            log::info!(address = as_debug!(addr); "rpc connection closed");
+                            tracing::info!(%user_id, %connection_id, %address, "connection closed");
                             break;
                         }
                     }
                 }
             }
 
-            if let Err(err) = this.sign_out(connection_id).await {
-                log::error!("error signing out connection {:?} - {:?}", addr, err);
+            if let Err(error) = this.sign_out(connection_id).await {
+                tracing::error!(%error, "error signing out");
             }
-        }
+        }.instrument(span)
     }
 
     async fn sign_out(self: &mut Arc<Self>, connection_id: ConnectionId) -> Result<()> {
@@ -849,6 +861,7 @@ impl Server {
         Ok(proto::GetUsersResponse { users })
     }
 
+    #[instrument(skip(self, state, user_ids))]
     fn update_contacts_for_users<'a>(
         self: &Arc<Self>,
         state: &Store,
@@ -864,7 +877,7 @@ impl Server {
                             contacts: contacts.clone(),
                         },
                     )
-                    .log_err();
+                    .trace_err();
             }
         }
     }
@@ -1084,6 +1097,14 @@ impl<'a> Drop for StoreWriteGuard<'a> {
     fn drop(&mut self) {
         #[cfg(test)]
         self.check_invariants();
+
+        let metrics = self.metrics();
+        tracing::info!(
+            connections = metrics.connections,
+            registered_projects = metrics.registered_projects,
+            shared_projects = metrics.shared_projects,
+            "metrics"
+        );
     }
 }
 
@@ -1099,13 +1120,14 @@ impl Executor for RealExecutor {
     }
 }
 
+#[instrument(skip(f))]
 fn broadcast<F>(sender_id: ConnectionId, receiver_ids: Vec<ConnectionId>, mut f: F)
 where
     F: FnMut(ConnectionId) -> anyhow::Result<()>,
 {
     for receiver_id in receiver_ids {
         if receiver_id != sender_id {
-            f(receiver_id).log_err();
+            f(receiver_id).trace_err();
         }
     }
 }
@@ -1206,6 +1228,29 @@ fn to_tungstenite_message(message: AxumMessage) -> TungsteniteMessage {
     }
 }
 
+pub trait ResultExt {
+    type Ok;
+
+    fn trace_err(self) -> Option<Self::Ok>;
+}
+
+impl<T, E> ResultExt for Result<T, E>
+where
+    E: std::fmt::Debug,
+{
+    type Ok = T;
+
+    fn trace_err(self) -> Option<T> {
+        match self {
+            Ok(value) => Some(value),
+            Err(error) => {
+                tracing::error!("{:?}", error);
+                None
+            }
+        }
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use super::*;

crates/collab/src/rpc/store.rs 🔗

@@ -3,6 +3,7 @@ use anyhow::{anyhow, Result};
 use collections::{BTreeMap, HashMap, HashSet};
 use rpc::{proto, ConnectionId};
 use std::{collections::hash_map, path::PathBuf};
+use tracing::instrument;
 
 #[derive(Default)]
 pub struct Store {
@@ -80,7 +81,33 @@ pub struct LeftProject {
     pub authorized_user_ids: Vec<UserId>,
 }
 
+#[derive(Copy, Clone)]
+pub struct Metrics {
+    pub connections: usize,
+    pub registered_projects: usize,
+    pub shared_projects: usize,
+}
+
 impl Store {
+    pub fn metrics(&self) -> Metrics {
+        let connections = self.connections.len();
+        let mut registered_projects = 0;
+        let mut shared_projects = 0;
+        for project in self.projects.values() {
+            registered_projects += 1;
+            if project.share.is_some() {
+                shared_projects += 1;
+            }
+        }
+
+        Metrics {
+            connections,
+            registered_projects,
+            shared_projects,
+        }
+    }
+
+    #[instrument(skip(self))]
     pub fn add_connection(&mut self, connection_id: ConnectionId, user_id: UserId) {
         self.connections.insert(
             connection_id,
@@ -96,6 +123,7 @@ impl Store {
             .insert(connection_id);
     }
 
+    #[instrument(skip(self))]
     pub fn remove_connection(
         &mut self,
         connection_id: ConnectionId,

crates/gpui/Cargo.toml 🔗

@@ -62,8 +62,8 @@ simplelog = "0.9"
 anyhow = "1"
 block = "0.1"
 cocoa = "0.24"
-core-foundation = "0.9"
-core-graphics = "0.22.2"
+core-foundation = "0.9.3"
+core-graphics = "0.22.3"
 core-text = "19.2"
 font-kit = { git = "https://github.com/zed-industries/font-kit", rev = "8eaf7a918eafa28b0a37dc759e2e0e7683fa24f1" }
 foreign-types = "0.3"

crates/rpc/build.rs 🔗

@@ -2,6 +2,7 @@ fn main() {
     let mut build = prost_build::Config::new();
     // build.protoc_arg("--experimental_allow_proto3_optional");
     build
+        .type_attribute(".", "#[derive(serde::Serialize)]")
         .compile_protos(&["proto/zed.proto"], &["proto"])
         .unwrap();
 }

crates/rpc/src/proto.rs 🔗

@@ -3,6 +3,7 @@ use anyhow::{anyhow, Result};
 use async_tungstenite::tungstenite::Message as WebSocketMessage;
 use futures::{SinkExt as _, StreamExt as _};
 use prost::Message as _;
+use serde::Serialize;
 use std::any::{Any, TypeId};
 use std::{
     io,
@@ -11,7 +12,7 @@ use std::{
 
 include!(concat!(env!("OUT_DIR"), "/zed.messages.rs"));
 
-pub trait EnvelopedMessage: Clone + Sized + Send + Sync + 'static {
+pub trait EnvelopedMessage: Clone + Serialize + Sized + Send + Sync + 'static {
     const NAME: &'static str;
     const PRIORITY: MessagePriority;
     fn into_envelope(