posthog_cli/
invocation_context.rs1use anyhow::Result;
2use posthog_rs::Event;
3use reqwest::blocking::Client;
4use std::{
5 sync::{Mutex, OnceLock},
6 thread::JoinHandle,
7};
8use tracing::{debug, info, warn};
9
10use crate::utils::auth::{get_token, Token};
11
12pub static INVOCATION_CONTEXT: OnceLock<InvocationContext> = OnceLock::new();
14
15pub struct InvocationContext {
16 pub token: Token,
17 pub client: Client,
18
19 handles: Mutex<Vec<JoinHandle<()>>>,
20}
21
22pub fn context() -> &'static InvocationContext {
23 INVOCATION_CONTEXT.get().expect("Context has been set up")
24}
25
26pub fn init_context(host: Option<String>, skip_ssl: bool) -> Result<()> {
27 let mut token = get_token()?;
28 if let Some(host) = host {
29 token.host = Some(host);
31 }
32
33 let client = reqwest::blocking::Client::builder()
34 .danger_accept_invalid_certs(skip_ssl)
35 .build()?;
36
37 INVOCATION_CONTEXT.get_or_init(|| InvocationContext::new(token, client));
38
39 if let Some(token) = option_env!("POSTHOG_API_TOKEN") {
41 let ph_config = posthog_rs::ClientOptionsBuilder::default()
42 .api_key(token.to_string())
43 .request_timeout_seconds(5) .build()
45 .expect("Building PH config succeeds");
46 posthog_rs::init_global(ph_config).expect("Initializing PostHog client");
47 } else {
48 warn!("Posthog api token not set at build time - is this a debug build?");
49 };
50
51 Ok(())
52}
53
54impl InvocationContext {
55 pub fn new(token: Token, client: Client) -> Self {
56 Self {
57 token,
58 client,
59 handles: Default::default(),
60 }
61 }
62
63 pub fn capture_command_invoked(&self, command: &str) {
64 let env_id = &self.token.env_id;
65 let event_name = "posthog cli command run".to_string();
66 let mut event = Event::new_anon(event_name);
67
68 event
69 .insert_prop("command_name", command)
70 .expect("Inserting command prop succeeds");
71
72 event
73 .insert_prop("env_id", env_id)
74 .expect("Inserting env_id prop succeeds");
75
76 let handle = std::thread::spawn(move || {
77 debug!("Capturing event");
78 let res = posthog_rs::capture(event); if let Err(err) = res {
80 debug!("Failed to capture event: {:?}", err);
81 } else {
82 debug!("Event captured successfully");
83 }
84 });
85
86 self.handles.lock().unwrap().push(handle);
87 }
88
89 pub fn finish(&self) {
90 info!("Finishing up....");
91
92 self.handles
93 .lock()
94 .unwrap()
95 .drain(..)
96 .for_each(|handle| handle.join().unwrap());
97
98 info!("Finished!")
99 }
100}