telemetry.rs

 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/// # let url = "https://example.com";
16/// telemetry::event!("Keymap Changed", version = "1.0.0");
17/// telemetry::event!("Documentation Viewed", url, source = "Extension Upsell");
18/// ```
19///
20/// If you want to debug logging in development, export `RUST_LOG=telemetry=trace`
21#[macro_export]
22macro_rules! event {
23    ($name:expr) => {{
24        let event = $crate::Event {
25            event_type: $name.to_string(),
26            event_properties: std::collections::HashMap::new(),
27        };
28        $crate::send_event(event);
29    }};
30    ($name:expr, $($key:ident $(= $value:expr)?),+ $(,)?) => {{
31        let event = $crate::Event {
32            event_type: $name.to_string(),
33            event_properties: std::collections::HashMap::from([
34                $(
35                    (stringify!($key).to_string(),
36                        $crate::serde_json::value::to_value(&$crate::serialize_property!($key $(= $value)?))
37                            .unwrap_or_else(|_| $crate::serde_json::to_value(&()).unwrap())
38                    ),
39                )+
40            ]),
41        };
42        $crate::send_event(event);
43    }};
44}
45
46#[macro_export]
47macro_rules! serialize_property {
48    ($key:ident) => {
49        $key
50    };
51    ($key:ident = $value:expr) => {
52        $value
53    };
54}
55
56pub fn send_event(event: Event) {
57    if let Some(queue) = TELEMETRY_QUEUE.get() {
58        queue.unbounded_send(event).ok();
59    }
60}
61
62pub fn init(tx: mpsc::UnboundedSender<Event>) {
63    TELEMETRY_QUEUE.set(tx).ok();
64}
65
66static TELEMETRY_QUEUE: OnceLock<mpsc::UnboundedSender<Event>> = OnceLock::new();