1//! See [Telemetry in Zed](https://zed.dev/docs/telemetry) for additional information.
2use futures::channel::mpsc;
3pub use serde_json;
4use std::sync::OnceLock;
5pub use telemetry_events::FlexibleEvent as Event;
6
7/// Macro to create telemetry events and send them to the telemetry queue.
8///
9/// By convention, the name should be "Noun Verbed", e.g. "Keymap Changed"
10/// or "Project Diagnostics Opened".
11///
12/// The properties can be any value that implements serde::Serialize.
13///
14/// ```
15/// telemetry::event!("Keymap Changed", version = "1.0.0");
16/// telemetry::event!("Documentation Viewed", url, source = "Extension Upsell");
17/// ```
18///
19/// If you want to debug logging in development, export `RUST_LOG=telemetry=trace`
20#[macro_export]
21macro_rules! event {
22 ($name:expr) => {{
23 let event = $crate::Event {
24 event_type: $name.to_string(),
25 event_properties: std::collections::HashMap::new(),
26 };
27 $crate::send_event(event);
28 }};
29 ($name:expr, $($key:ident $(= $value:expr)?),+ $(,)?) => {{
30 let event = $crate::Event {
31 event_type: $name.to_string(),
32 event_properties: std::collections::HashMap::from([
33 $(
34 (stringify!($key).to_string(),
35 $crate::serde_json::value::to_value(&$crate::serialize_property!($key $(= $value)?))
36 .unwrap_or_else(|_| $crate::serde_json::to_value(&()).unwrap())
37 ),
38 )+
39 ]),
40 };
41 $crate::send_event(event);
42 }};
43}
44
45#[macro_export]
46macro_rules! serialize_property {
47 ($key:ident) => {
48 $key
49 };
50 ($key:ident = $value:expr) => {
51 $value
52 };
53}
54
55pub fn send_event(event: Event) {
56 if let Some(queue) = TELEMETRY_QUEUE.get() {
57 queue.unbounded_send(event).ok();
58 }
59}
60
61pub fn init(tx: mpsc::UnboundedSender<Event>) {
62 TELEMETRY_QUEUE.set(tx).ok();
63}
64
65static TELEMETRY_QUEUE: OnceLock<mpsc::UnboundedSender<Event>> = OnceLock::new();