|
| 1 | +# PostHog Integration Design Document |
| 2 | + |
| 3 | +## 1. Overview |
| 4 | + |
| 5 | +This document outlines the design for integrating PostHog analytics into the Syncable CLI application. The integration will track usage of key commands (analyze, security, vulnerabilities) using the user's unique identifier generated during first use. |
| 6 | + |
| 7 | +## 2. Current Implementation Analysis |
| 8 | + |
| 9 | +The current telemetry implementation already includes: |
| 10 | +- PostHog client initialization with API key |
| 11 | +- User ID generation and persistence |
| 12 | +- Event tracking for command start/complete and specific events |
| 13 | +- Asynchronous event sending using tokio::spawn |
| 14 | + |
| 15 | +However, there are some issues with the current implementation: |
| 16 | +1. The API host is set to EU endpoint but should use US endpoint for the provided API key |
| 17 | +2. The event tracking methods are using a non-standard API pattern rather than the recommended PostHog Rust SDK approach |
| 18 | +3. Events are being sent with a `track` method that doesn't match the PostHog Rust SDK documentation |
| 19 | + |
| 20 | +## 3. Architecture |
| 21 | + |
| 22 | +### 3.1 Component Structure |
| 23 | + |
| 24 | +``` |
| 25 | +src/telemetry/ |
| 26 | +├── client.rs # Telemetry client implementation with PostHog integration |
| 27 | +├── config.rs # Telemetry configuration |
| 28 | +├── mod.rs # Module exports and initialization |
| 29 | +├── user.rs # User ID generation and management |
| 30 | +└── test.rs # Telemetry tests |
| 31 | +``` |
| 32 | + |
| 33 | +### 3.2 Data Flow |
| 34 | + |
| 35 | +```mermaid |
| 36 | +graph TD |
| 37 | + A[CLI Command Execution] --> B[Telemetry Initialization] |
| 38 | + B --> C[User ID Generation/Loading] |
| 39 | + C --> D[PostHog Client Creation] |
| 40 | + D --> E[Event Tracking] |
| 41 | + E --> F[Asynchronous Event Sending] |
| 42 | + F --> G[PostHog API] |
| 43 | +``` |
| 44 | + |
| 45 | +## 4. Implementation Details |
| 46 | + |
| 47 | +### 4.1 PostHog Client Configuration |
| 48 | + |
| 49 | +The PostHog client will be configured with: |
| 50 | +- API Key: `phc_t5zrCHU3yiU52lcUfOP3SiCSxdhJcmB2I3m06dGTk2D` |
| 51 | +- API Host: `https://us.i.posthog.com` (US endpoint as required for this key) |
| 52 | +- Asynchronous event sending using tokio |
| 53 | + |
| 54 | +### 4.2 Event Structure |
| 55 | + |
| 56 | +All events will include the following properties: |
| 57 | +- `distinct_id`: User's unique identifier |
| 58 | +- `personal_id`: Random number for privacy-preserving tracking |
| 59 | +- `version`: CLI version from `CARGO_PKG_VERSION` |
| 60 | +- `os`: Operating system from `std::env::consts::OS` |
| 61 | + |
| 62 | +### 4.3 Tracked Events |
| 63 | + |
| 64 | +1. **Command Start Event** |
| 65 | + - Event Name: `command_start` |
| 66 | + - Properties: `command` (command name) |
| 67 | + |
| 68 | +2. **Command Complete Event** |
| 69 | + - Event Name: `command_complete` |
| 70 | + - Properties: `command`, `duration_ms`, `success` |
| 71 | + |
| 72 | +3. **Specific Feature Events** |
| 73 | + - Event Name: `Security Scan` |
| 74 | + - Event Name: `Analyze Folder` |
| 75 | + - Event Name: `Vulnerability Scan` |
| 76 | + |
| 77 | +### 4.4 User Identification |
| 78 | + |
| 79 | +Users will be identified by a UUID generated on first use and stored in: |
| 80 | +- Path: `~/.config/syncable-cli/user_id` |
| 81 | +- Format: JSON with `id` and `first_seen` fields |
| 82 | + |
| 83 | +## 5. API Design |
| 84 | + |
| 85 | +### 5.1 TelemetryClient Methods |
| 86 | + |
| 87 | +```rust |
| 88 | +impl TelemetryClient { |
| 89 | + pub fn new(config: &Config) -> Result<Self, Box<dyn std::error::Error>> |
| 90 | + pub fn track_command_start(&self, command: &str) |
| 91 | + pub fn track_command_complete(&self, command: &str, duration: Duration, success: bool) |
| 92 | + pub fn track_event(&self, name: &str, properties: HashMap<String, Value>) |
| 93 | + pub fn track_security_scan(&self) |
| 94 | + pub fn track_analyze_folder(&self) |
| 95 | + pub fn track_vulnerability_scan(&self) |
| 96 | +} |
| 97 | +``` |
| 98 | + |
| 99 | +### 5.2 Event Creation Pattern |
| 100 | + |
| 101 | +```rust |
| 102 | +let mut event = Event::new("event_name", "distinct_id"); |
| 103 | +event.insert_prop("property_key", "property_value")?; |
| 104 | +client.capture(event)?; |
| 105 | +``` |
| 106 | + |
| 107 | +## 5. PostHog Rust SDK Usage |
| 108 | + |
| 109 | +### 5.1 Client Initialization |
| 110 | + |
| 111 | +Following the PostHog Rust SDK documentation, the client will be initialized as: |
| 112 | + |
| 113 | +```rust |
| 114 | +let client = posthog_rs::client("API_KEY") |
| 115 | + .host("https://us.i.posthog.com") |
| 116 | + .build()?; |
| 117 | +``` |
| 118 | + |
| 119 | +### 5.2 Event Creation |
| 120 | + |
| 121 | +Events will be created and sent using the SDK's recommended approach: |
| 122 | + |
| 123 | +```rust |
| 124 | +let mut event = posthog_rs::Event::new("event_name", "distinct_id"); |
| 125 | +event.insert_prop("key", "value")?; |
| 126 | +client.capture(event)?; |
| 127 | +``` |
| 128 | + |
| 129 | +### 5.3 Required Implementation Changes |
| 130 | + |
| 131 | +The current implementation needs to be updated to match the PostHog Rust SDK: |
| 132 | + |
| 133 | +1. Change the API endpoint from `https://eu.i.posthog.com` to `https://us.i.posthog.com` |
| 134 | +2. Replace the non-standard `track` method with the proper `capture` method |
| 135 | +3. Create `Event` objects properly using the SDK's API |
| 136 | +4. Ensure all event properties are added using `insert_prop` method |
| 137 | + |
| 138 | +### 5.4 Implementation Plan |
| 139 | + |
| 140 | +The implementation will involve the following steps: |
| 141 | + |
| 142 | +1. Update the `POSTHOG_API_HOST` constant to use the US endpoint |
| 143 | +2. Modify all event tracking methods to use the proper PostHog Rust SDK API |
| 144 | +3. Replace HashMap-based properties with direct `insert_prop` calls on Event objects |
| 145 | +4. Change from `client.track()` to `client.capture()` |
| 146 | +5. Ensure all event sending is properly asynchronous |
| 147 | + |
| 148 | +### 5.5 Code Implementation Details |
| 149 | + |
| 150 | +For each event tracking method, the implementation should follow this pattern: |
| 151 | + |
| 152 | +```rust |
| 153 | +let client = Arc::clone(&self.client); |
| 154 | +let mut event = Event::new(event_name, &self.user_id.id); |
| 155 | +// Add properties using insert_prop |
| 156 | +// event.insert_prop("key", value)?; |
| 157 | + |
| 158 | +// Send the event asynchronously |
| 159 | +tokio::spawn(async move { |
| 160 | + match client.capture(event) { |
| 161 | + Ok(_) => log::debug!("Successfully sent telemetry event: {}", event_name), |
| 162 | + Err(e) => log::warn!("Failed to send telemetry event '{}': {}", event_name, e), |
| 163 | + } |
| 164 | +}); |
| 165 | +``` |
| 166 | + |
| 167 | +### 5.6 Asynchronous Operations |
| 168 | + |
| 169 | +All event sending will be performed asynchronously using `tokio::spawn` to avoid blocking the main application flow. |
| 170 | + |
| 171 | +## 6. Integration Points |
| 172 | + |
| 173 | +### 6.1 Main Application Integration |
| 174 | + |
| 175 | +The telemetry client is initialized in `main.rs` during application startup: |
| 176 | +- Called in the `run()` function before command execution |
| 177 | +- Events tracked at command start and completion |
| 178 | +- Specific events tracked in command handlers |
| 179 | + |
| 180 | +### 6.2 Command-Specific Tracking |
| 181 | + |
| 182 | +1. **Analyze Command** |
| 183 | + - Tracks `Analyze Folder` event in `handle_analyze` |
| 184 | + |
| 185 | +2. **Security Command** |
| 186 | + - Tracks `Security Scan` event in `handle_security` |
| 187 | + |
| 188 | +3. **Vulnerabilities Command** |
| 189 | + - Tracks `Vulnerability Scan` event in `handle_vulnerabilities` |
| 190 | + |
| 191 | +## 7. Privacy and Compliance |
| 192 | + |
| 193 | +### 7.1 Data Collection |
| 194 | +- Only anonymous usage data is collected |
| 195 | +- No personally identifiable information (PII) is sent |
| 196 | +- User identification is through randomly generated UUIDs |
| 197 | + |
| 198 | +### 7.2 Opt-Out Mechanism |
| 199 | +- Users can disable telemetry through: |
| 200 | + - `--disable-telemetry` CLI flag |
| 201 | + - `SYNCABLE_CLI_TELEMETRY=false` environment variable |
| 202 | + - Configuration file setting |
| 203 | + |
| 204 | +## 8. Testing Strategy |
| 205 | + |
| 206 | +### 8.1 Unit Tests |
| 207 | +- Test user ID generation and persistence |
| 208 | +- Test PostHog client creation |
| 209 | +- Test event property generation |
| 210 | + |
| 211 | +### 8.2 Integration Tests |
| 212 | +- Verify events are sent to PostHog API |
| 213 | +- Test opt-out mechanisms |
| 214 | +- Validate event structure and content |
| 215 | + |
| 216 | +### 8.3 Implementation Verification |
| 217 | +- Verify that all three required events (`Security Scan`, `Analyze Folder`, `Vulnerability Scan`) are properly sent |
| 218 | +- Confirm that `distinct_id` is correctly set to the user's unique identifier |
| 219 | +- Ensure `personal_id` is included in all events for privacy-preserving tracking |
| 220 | +- Validate that events are sent asynchronously without blocking the main application |
| 221 | + |
| 222 | +## 9. Error Handling |
| 223 | + |
| 224 | +### 9.1 Client Initialization Failures |
| 225 | +- Log warning and continue without telemetry |
| 226 | +- Don't crash the application |
| 227 | + |
| 228 | +### 9.2 Event Sending Failures |
| 229 | +- Log warning for failed event sends |
| 230 | +- Continue with command execution |
| 231 | +- No retries or persistence of failed events |
| 232 | + |
| 233 | +### 9.3 Event Creation Failures |
| 234 | +- Handle `insert_prop` errors gracefully |
| 235 | +- Log warnings for property insertion failures |
| 236 | +- Continue with event sending even if some properties fail to insert |
| 237 | + |
| 238 | +## 10. Performance Considerations |
| 239 | + |
| 240 | +### 10.1 Asynchronous Operations |
| 241 | +- All event sending happens asynchronously |
| 242 | +- No blocking of main command execution |
| 243 | +- Uses tokio::spawn for background tasks |
| 244 | + |
| 245 | +### 10.2 Resource Management |
| 246 | +- Single PostHog client instance per application run |
| 247 | +- Shared through static OnceLock |
| 248 | +- Automatic cleanup when application exits |
0 commit comments