feat(analytics): add core analytics infrastructure with PostHog integration

- Implement comprehensive analytics type system with 100+ event types
- Create event builders for consistent event tracking
- Add main analytics service with PostHog integration
- Include performance tracking utilities with percentile monitoring
- Support anonymous user tracking with session management
- Implement sanitization helpers to remove PII from events
- Add event queueing with automatic flush intervals
- Support for screen tracking and app context

BREAKING CHANGE: Analytics tracking is now integrated throughout the app
and requires PostHog API key configuration via environment variables.
This commit is contained in:
Vivek R
2025-07-31 14:21:14 +05:30
parent f7e932ed79
commit ed695e50e6
3 changed files with 1003 additions and 9 deletions

View File

@@ -7,7 +7,42 @@ import type {
AgentProperties,
MCPProperties,
SlashCommandProperties,
PerformanceMetrics
PerformanceMetrics,
PromptSubmittedProperties,
SessionStoppedProperties,
EnhancedSessionStoppedProperties,
CheckpointCreatedProperties,
CheckpointRestoredProperties,
ToolExecutedProperties,
AgentStartedProperties,
AgentProgressProperties,
AgentErrorProperties,
MCPServerAddedProperties,
MCPServerRemovedProperties,
MCPToolInvokedProperties,
MCPConnectionErrorProperties,
SlashCommandSelectedProperties,
SlashCommandExecutedProperties,
SlashCommandCreatedProperties,
APIErrorProperties,
UIErrorProperties,
PerformanceBottleneckProperties,
MemoryWarningProperties,
UserJourneyProperties,
EnhancedPromptSubmittedProperties,
EnhancedToolExecutedProperties,
EnhancedErrorProperties,
SessionEngagementProperties,
FeatureDiscoveryProperties,
OutputQualityProperties,
ResourceUsageProperties,
FeatureAdoptionProperties,
FeatureCombinationProperties,
AIInteractionProperties,
PromptPatternProperties,
WorkflowProperties,
NetworkPerformanceProperties,
SuggestionProperties
} from './types';
export const ANALYTICS_EVENTS = {
@@ -15,6 +50,11 @@ export const ANALYTICS_EVENTS = {
SESSION_CREATED: 'session_created' as EventName,
SESSION_COMPLETED: 'session_completed' as EventName,
SESSION_RESUMED: 'session_resumed' as EventName,
PROMPT_SUBMITTED: 'prompt_submitted' as EventName,
SESSION_STOPPED: 'session_stopped' as EventName,
CHECKPOINT_CREATED: 'checkpoint_created' as EventName,
CHECKPOINT_RESTORED: 'checkpoint_restored' as EventName,
TOOL_EXECUTED: 'tool_executed' as EventName,
// Feature usage events
FEATURE_USED: 'feature_used' as EventName,
@@ -24,18 +64,73 @@ export const ANALYTICS_EVENTS = {
FILE_OPENED: 'file_opened' as EventName,
FILE_EDITED: 'file_edited' as EventName,
FILE_SAVED: 'file_saved' as EventName,
// Agent events
AGENT_EXECUTED: 'agent_executed' as EventName,
AGENT_STARTED: 'agent_started' as EventName,
AGENT_PROGRESS: 'agent_progress' as EventName,
AGENT_ERROR: 'agent_error' as EventName,
// MCP events
MCP_SERVER_CONNECTED: 'mcp_server_connected' as EventName,
MCP_SERVER_DISCONNECTED: 'mcp_server_disconnected' as EventName,
MCP_SERVER_ADDED: 'mcp_server_added' as EventName,
MCP_SERVER_REMOVED: 'mcp_server_removed' as EventName,
MCP_TOOL_INVOKED: 'mcp_tool_invoked' as EventName,
MCP_CONNECTION_ERROR: 'mcp_connection_error' as EventName,
// Slash command events
SLASH_COMMAND_USED: 'slash_command_used' as EventName,
SLASH_COMMAND_SELECTED: 'slash_command_selected' as EventName,
SLASH_COMMAND_EXECUTED: 'slash_command_executed' as EventName,
SLASH_COMMAND_CREATED: 'slash_command_created' as EventName,
// Settings and system events
SETTINGS_CHANGED: 'settings_changed' as EventName,
APP_STARTED: 'app_started' as EventName,
APP_CLOSED: 'app_closed' as EventName,
// Error events
// Error and performance events
ERROR_OCCURRED: 'error_occurred' as EventName,
API_ERROR: 'api_error' as EventName,
UI_ERROR: 'ui_error' as EventName,
PERFORMANCE_BOTTLENECK: 'performance_bottleneck' as EventName,
MEMORY_WARNING: 'memory_warning' as EventName,
// User journey events
JOURNEY_MILESTONE: 'journey_milestone' as EventName,
USER_RETENTION: 'user_retention' as EventName,
// AI interaction events
AI_INTERACTION: 'ai_interaction' as EventName,
PROMPT_PATTERN: 'prompt_pattern' as EventName,
// Quality events
OUTPUT_REGENERATED: 'output_regenerated' as EventName,
CONVERSATION_ABANDONED: 'conversation_abandoned' as EventName,
SUGGESTION_ACCEPTED: 'suggestion_accepted' as EventName,
SUGGESTION_REJECTED: 'suggestion_rejected' as EventName,
// Workflow events
WORKFLOW_STARTED: 'workflow_started' as EventName,
WORKFLOW_COMPLETED: 'workflow_completed' as EventName,
WORKFLOW_ABANDONED: 'workflow_abandoned' as EventName,
// Feature adoption events
FEATURE_DISCOVERED: 'feature_discovered' as EventName,
FEATURE_ADOPTED: 'feature_adopted' as EventName,
FEATURE_COMBINATION: 'feature_combination' as EventName,
// Resource usage events
RESOURCE_USAGE_HIGH: 'resource_usage_high' as EventName,
RESOURCE_USAGE_SAMPLED: 'resource_usage_sampled' as EventName,
// Network performance events
NETWORK_PERFORMANCE: 'network_performance' as EventName,
NETWORK_FAILURE: 'network_failure' as EventName,
// Engagement events
SESSION_ENGAGEMENT: 'session_engagement' as EventName,
} as const;
// Event property builders - help ensure consistent event structure
@@ -116,6 +211,437 @@ export const eventBuilders = {
...metrics,
},
}),
// Claude Code Session event builders
promptSubmitted: (props: PromptSubmittedProperties) => ({
event: ANALYTICS_EVENTS.PROMPT_SUBMITTED,
properties: {
category: 'session',
...props,
},
}),
sessionStopped: (props: SessionStoppedProperties) => ({
event: ANALYTICS_EVENTS.SESSION_STOPPED,
properties: {
category: 'session',
...props,
},
}),
// Enhanced session stopped with detailed metrics
enhancedSessionStopped: (props: EnhancedSessionStoppedProperties) => ({
event: ANALYTICS_EVENTS.SESSION_STOPPED,
properties: {
category: 'session',
duration_ms: props.duration_ms,
messages_count: props.messages_count,
reason: props.reason,
// Timing metrics
time_to_first_message_ms: props.time_to_first_message_ms,
average_response_time_ms: props.average_response_time_ms,
idle_time_ms: props.idle_time_ms,
// Interaction metrics
prompts_sent: props.prompts_sent,
tools_executed: props.tools_executed,
tools_failed: props.tools_failed,
files_created: props.files_created,
files_modified: props.files_modified,
files_deleted: props.files_deleted,
// Content metrics
total_tokens_used: props.total_tokens_used,
code_blocks_generated: props.code_blocks_generated,
errors_encountered: props.errors_encountered,
// Session context
model: props.model,
has_checkpoints: props.has_checkpoints,
checkpoint_count: props.checkpoint_count,
was_resumed: props.was_resumed,
// Agent context
agent_type: props.agent_type,
agent_name: props.agent_name ? sanitizers.sanitizeAgentName(props.agent_name) : undefined,
agent_success: props.agent_success,
// Stop context
stop_source: props.stop_source,
final_state: props.final_state,
has_pending_prompts: props.has_pending_prompts,
pending_prompts_count: props.pending_prompts_count,
},
}),
checkpointCreated: (props: CheckpointCreatedProperties) => ({
event: ANALYTICS_EVENTS.CHECKPOINT_CREATED,
properties: {
category: 'session',
...props,
},
}),
checkpointRestored: (props: CheckpointRestoredProperties) => ({
event: ANALYTICS_EVENTS.CHECKPOINT_RESTORED,
properties: {
category: 'session',
...props,
},
}),
toolExecuted: (props: ToolExecutedProperties) => ({
event: ANALYTICS_EVENTS.TOOL_EXECUTED,
properties: {
category: 'session',
tool_name: sanitizers.sanitizeToolName(props.tool_name),
execution_time_ms: props.execution_time_ms,
success: props.success,
error_message: props.error_message ? sanitizers.sanitizeErrorMessage(props.error_message) : undefined,
},
}),
// Enhanced Agent event builders
agentStarted: (props: AgentStartedProperties) => ({
event: ANALYTICS_EVENTS.AGENT_STARTED,
properties: {
category: 'agent',
agent_type: props.agent_type,
agent_name: props.agent_name ? sanitizers.sanitizeAgentName(props.agent_name) : undefined,
has_custom_prompt: props.has_custom_prompt,
},
}),
agentProgress: (props: AgentProgressProperties) => ({
event: ANALYTICS_EVENTS.AGENT_PROGRESS,
properties: {
category: 'agent',
...props,
},
}),
agentError: (props: AgentErrorProperties) => ({
event: ANALYTICS_EVENTS.AGENT_ERROR,
properties: {
category: 'agent',
...props,
},
}),
// MCP event builders
mcpServerAdded: (props: MCPServerAddedProperties) => ({
event: ANALYTICS_EVENTS.MCP_SERVER_ADDED,
properties: {
category: 'mcp',
...props,
},
}),
mcpServerRemoved: (props: MCPServerRemovedProperties) => ({
event: ANALYTICS_EVENTS.MCP_SERVER_REMOVED,
properties: {
category: 'mcp',
server_name: sanitizers.sanitizeServerName(props.server_name),
was_connected: props.was_connected,
},
}),
mcpToolInvoked: (props: MCPToolInvokedProperties) => ({
event: ANALYTICS_EVENTS.MCP_TOOL_INVOKED,
properties: {
category: 'mcp',
server_name: sanitizers.sanitizeServerName(props.server_name),
tool_name: sanitizers.sanitizeToolName(props.tool_name),
invocation_source: props.invocation_source,
},
}),
mcpConnectionError: (props: MCPConnectionErrorProperties) => ({
event: ANALYTICS_EVENTS.MCP_CONNECTION_ERROR,
properties: {
category: 'mcp',
server_name: sanitizers.sanitizeServerName(props.server_name),
error_type: props.error_type,
retry_attempt: props.retry_attempt,
},
}),
// Slash Command event builders
slashCommandSelected: (props: SlashCommandSelectedProperties) => ({
event: ANALYTICS_EVENTS.SLASH_COMMAND_SELECTED,
properties: {
category: 'slash_command',
command_name: sanitizers.sanitizeCommandName(props.command_name),
selection_method: props.selection_method,
},
}),
slashCommandExecuted: (props: SlashCommandExecutedProperties) => ({
event: ANALYTICS_EVENTS.SLASH_COMMAND_EXECUTED,
properties: {
category: 'slash_command',
command_name: sanitizers.sanitizeCommandName(props.command_name),
parameters_count: props.parameters_count,
execution_time_ms: props.execution_time_ms,
},
}),
slashCommandCreated: (props: SlashCommandCreatedProperties) => ({
event: ANALYTICS_EVENTS.SLASH_COMMAND_CREATED,
properties: {
category: 'slash_command',
...props,
},
}),
// Error and Performance event builders
apiError: (props: APIErrorProperties) => ({
event: ANALYTICS_EVENTS.API_ERROR,
properties: {
category: 'error',
endpoint: sanitizers.sanitizeEndpoint(props.endpoint),
error_code: props.error_code,
retry_count: props.retry_count,
response_time_ms: props.response_time_ms,
},
}),
uiError: (props: UIErrorProperties) => ({
event: ANALYTICS_EVENTS.UI_ERROR,
properties: {
category: 'error',
...props,
},
}),
performanceBottleneck: (props: PerformanceBottleneckProperties) => ({
event: ANALYTICS_EVENTS.PERFORMANCE_BOTTLENECK,
properties: {
category: 'performance',
...props,
},
}),
memoryWarning: (props: MemoryWarningProperties) => ({
event: ANALYTICS_EVENTS.MEMORY_WARNING,
properties: {
category: 'performance',
...props,
},
}),
// User journey event builders
journeyMilestone: (props: UserJourneyProperties) => ({
event: ANALYTICS_EVENTS.JOURNEY_MILESTONE,
properties: {
category: 'user_journey',
...props,
},
}),
// Enhanced prompt submission with more context
enhancedPromptSubmitted: (props: EnhancedPromptSubmittedProperties) => ({
event: ANALYTICS_EVENTS.PROMPT_SUBMITTED,
properties: {
category: 'session',
prompt_length: props.prompt_length,
model: props.model,
has_attachments: props.has_attachments,
source: props.source,
word_count: props.word_count,
conversation_depth: props.conversation_depth,
prompt_complexity: props.prompt_complexity,
contains_code: props.contains_code,
language_detected: props.language_detected,
session_age_ms: props.session_age_ms,
},
}),
// Enhanced tool execution with more context
enhancedToolExecuted: (props: EnhancedToolExecutedProperties) => ({
event: ANALYTICS_EVENTS.TOOL_EXECUTED,
properties: {
category: 'session',
tool_name: sanitizers.sanitizeToolName(props.tool_name),
execution_time_ms: props.execution_time_ms,
success: props.success,
error_message: props.error_message ? sanitizers.sanitizeErrorMessage(props.error_message) : undefined,
tool_category: props.tool_category,
consecutive_failures: props.consecutive_failures,
retry_attempted: props.retry_attempted,
input_size_bytes: props.input_size_bytes,
output_size_bytes: props.output_size_bytes,
},
}),
// Enhanced error tracking
enhancedError: (props: EnhancedErrorProperties) => ({
event: ANALYTICS_EVENTS.ERROR_OCCURRED,
properties: {
category: 'error',
error_type: props.error_type,
error_code: props.error_code,
error_message: props.error_message ? sanitizers.sanitizeErrorMessage(props.error_message) : undefined,
context: props.context,
user_action_before_error: props.user_action_before_error,
recovery_attempted: props.recovery_attempted,
recovery_successful: props.recovery_successful,
error_frequency: props.error_frequency,
stack_trace_hash: props.stack_trace_hash,
},
}),
// Session engagement
sessionEngagement: (props: SessionEngagementProperties) => ({
event: ANALYTICS_EVENTS.SESSION_ENGAGEMENT,
properties: {
category: 'engagement',
...props,
},
}),
// Feature discovery
featureDiscovered: (props: FeatureDiscoveryProperties) => ({
event: ANALYTICS_EVENTS.FEATURE_DISCOVERED,
properties: {
category: 'feature_adoption',
...props,
},
}),
// Output quality
outputRegenerated: (props: OutputQualityProperties) => ({
event: ANALYTICS_EVENTS.OUTPUT_REGENERATED,
properties: {
category: 'quality',
...props,
},
}),
// Conversation abandoned
conversationAbandoned: (reason: string, messagesCount: number) => ({
event: ANALYTICS_EVENTS.CONVERSATION_ABANDONED,
properties: {
category: 'quality',
reason,
messages_count: messagesCount,
},
}),
// Suggestion tracking
suggestionAccepted: (props: SuggestionProperties) => ({
event: ANALYTICS_EVENTS.SUGGESTION_ACCEPTED,
properties: {
category: 'quality',
...props,
},
}),
suggestionRejected: (props: SuggestionProperties) => ({
event: ANALYTICS_EVENTS.SUGGESTION_REJECTED,
properties: {
category: 'quality',
...props,
},
}),
// Resource usage
resourceUsageHigh: (props: ResourceUsageProperties) => ({
event: ANALYTICS_EVENTS.RESOURCE_USAGE_HIGH,
properties: {
category: 'performance',
...props,
},
}),
resourceUsageSampled: (props: ResourceUsageProperties) => ({
event: ANALYTICS_EVENTS.RESOURCE_USAGE_SAMPLED,
properties: {
category: 'performance',
...props,
},
}),
// Feature adoption
featureAdopted: (props: FeatureAdoptionProperties) => ({
event: ANALYTICS_EVENTS.FEATURE_ADOPTED,
properties: {
category: 'feature_adoption',
...props,
},
}),
featureCombination: (props: FeatureCombinationProperties) => ({
event: ANALYTICS_EVENTS.FEATURE_COMBINATION,
properties: {
category: 'feature_adoption',
...props,
},
}),
// AI interactions
aiInteraction: (props: AIInteractionProperties) => ({
event: ANALYTICS_EVENTS.AI_INTERACTION,
properties: {
category: 'ai',
...props,
},
}),
promptPattern: (props: PromptPatternProperties) => ({
event: ANALYTICS_EVENTS.PROMPT_PATTERN,
properties: {
category: 'ai',
...props,
},
}),
// Workflow tracking
workflowStarted: (props: WorkflowProperties) => ({
event: ANALYTICS_EVENTS.WORKFLOW_STARTED,
properties: {
category: 'workflow',
...props,
},
}),
workflowCompleted: (props: WorkflowProperties) => ({
event: ANALYTICS_EVENTS.WORKFLOW_COMPLETED,
properties: {
category: 'workflow',
...props,
},
}),
workflowAbandoned: (props: WorkflowProperties) => ({
event: ANALYTICS_EVENTS.WORKFLOW_ABANDONED,
properties: {
category: 'workflow',
...props,
},
}),
// Network performance
networkPerformance: (props: NetworkPerformanceProperties) => ({
event: ANALYTICS_EVENTS.NETWORK_PERFORMANCE,
properties: {
category: 'network',
endpoint_type: props.endpoint_type,
latency_ms: props.latency_ms,
payload_size_bytes: props.payload_size_bytes,
connection_quality: props.connection_quality,
retry_count: props.retry_count,
circuit_breaker_triggered: props.circuit_breaker_triggered,
},
}),
networkFailure: (props: NetworkPerformanceProperties) => ({
event: ANALYTICS_EVENTS.NETWORK_FAILURE,
properties: {
category: 'network',
endpoint_type: props.endpoint_type,
latency_ms: props.latency_ms,
payload_size_bytes: props.payload_size_bytes,
connection_quality: props.connection_quality,
retry_count: props.retry_count,
circuit_breaker_triggered: props.circuit_breaker_triggered,
},
}),
};
// Sanitization helpers to remove PII
@@ -147,4 +673,28 @@ export const sanitizers = {
// Only keep the type, remove custom names
return name.split('-')[0] || 'custom';
},
};
// Sanitize tool names to remove any user-specific info
sanitizeToolName: (name: string): string => {
// Remove any path-like structures
return name.replace(/\/[\w\-\/\.]+/g, '').toLowerCase();
},
// Sanitize server names to remove any user-specific info
sanitizeServerName: (name: string): string => {
// Keep only the type or first part
return name.split(/[\-_]/)[0] || 'custom';
},
// Sanitize command names
sanitizeCommandName: (name: string): string => {
// Remove any custom prefixes or user-specific parts
return name.replace(/^custom-/, '').split('-')[0] || 'custom';
},
// Sanitize API endpoints
sanitizeEndpoint: (endpoint: string): string => {
// Remove any dynamic IDs or user-specific parts
return endpoint.replace(/\/\d+/g, '/:id').replace(/\/[\w\-]{20,}/g, '/:id');
},
};

View File

@@ -11,6 +11,7 @@ import type {
export * from './types';
export * from './events';
export { ConsentManager } from './consent';
export { ResourceMonitor, resourceMonitor } from './resourceMonitor';
class AnalyticsService {
private static instance: AnalyticsService;
@@ -19,6 +20,7 @@ class AnalyticsService {
private config: AnalyticsConfig;
private eventQueue: AnalyticsEvent[] = [];
private flushInterval: NodeJS.Timeout | null = null;
private currentScreen: string = 'app_start';
private constructor() {
this.consentManager = ConsentManager.getInstance();
@@ -66,9 +68,11 @@ class AnalyticsService {
try {
posthog.init(this.config.apiKey, {
api_host: this.config.apiHost,
defaults: '2025-05-24',
capture_exceptions: true,
debug: import.meta.env.MODE === 'development',
capture_pageview: false, // Disable automatic pageview capture
capture_pageleave: false, // Disable automatic pageleave
bootstrap: {
distinctID: settings.userId,
},
persistence: this.config.persistence,
autocapture: this.config.autocapture,
disable_session_recording: this.config.disable_session_recording,
@@ -78,6 +82,13 @@ class AnalyticsService {
ph.identify(settings.userId, {
anonymous: true,
consent_date: settings.consentDate,
app_type: 'desktop',
app_name: 'claudia',
});
// Set initial screen
ph.capture('$screen', {
$screen_name: 'app_start',
});
// Opt in since user has consented
@@ -115,6 +126,17 @@ class AnalyticsService {
}
}
setScreen(screenName: string): void {
this.currentScreen = screenName;
// Track screen view in PostHog
if (typeof posthog !== 'undefined' && typeof posthog.capture === 'function') {
posthog.capture('$screen', {
$screen_name: screenName,
});
}
}
track(eventName: EventName | string, properties?: Record<string, any>): void {
// Check if analytics is enabled
if (!this.consentManager.isEnabled()) {
@@ -124,10 +146,17 @@ class AnalyticsService {
// Sanitize properties to remove PII
const sanitizedProperties = this.sanitizeProperties(properties || {});
// Add screen context to all events
const enhancedProperties = {
...sanitizedProperties,
screen_name: this.currentScreen,
app_context: 'claudia_desktop',
};
// Create event
const event: AnalyticsEvent = {
event: eventName,
properties: sanitizedProperties,
properties: enhancedProperties,
timestamp: Date.now(),
sessionId: this.consentManager.getSessionId(),
userId: this.consentManager.getUserId(),
@@ -205,6 +234,7 @@ class AnalyticsService {
...event.properties,
$session_id: event.sessionId,
timestamp: event.timestamp,
$current_url: `claudia://${event.properties?.screen_name || 'unknown'}`,
});
}
});
@@ -248,3 +278,74 @@ export const analytics = AnalyticsService.getInstance();
// Export for direct usage
export default analytics;
/**
* Performance tracking utility for better insights
*/
export class PerformanceTracker {
private static performanceData: Map<string, number[]> = new Map();
/**
* Record a performance metric
* Automatically tracks percentiles when enough data is collected
*/
static recordMetric(operation: string, duration: number): void {
if (!this.performanceData.has(operation)) {
this.performanceData.set(operation, []);
}
const data = this.performanceData.get(operation)!;
data.push(duration);
// Keep last 100 measurements for memory efficiency
if (data.length > 100) {
data.shift();
}
// Track percentiles every 10 measurements
if (data.length >= 10 && data.length % 10 === 0) {
const sorted = [...data].sort((a, b) => a - b);
const p50 = sorted[Math.floor(sorted.length * 0.5)];
const p95 = sorted[Math.floor(sorted.length * 0.95)];
const p99 = sorted[Math.floor(sorted.length * 0.99)];
analytics.track('performance_percentiles', {
operation,
p50,
p95,
p99,
sample_size: data.length,
min: sorted[0],
max: sorted[sorted.length - 1],
avg: data.reduce((a, b) => a + b, 0) / data.length,
});
}
}
/**
* Get current statistics for an operation
*/
static getStats(operation: string): { p50: number; p95: number; p99: number; count: number } | null {
const data = this.performanceData.get(operation);
if (!data || data.length === 0) return null;
const sorted = [...data].sort((a, b) => a - b);
return {
p50: sorted[Math.floor(sorted.length * 0.5)],
p95: sorted[Math.floor(sorted.length * 0.95)],
p99: sorted[Math.floor(sorted.length * 0.99)],
count: data.length,
};
}
/**
* Clear data for an operation or all operations
*/
static clear(operation?: string): void {
if (operation) {
this.performanceData.delete(operation);
} else {
this.performanceData.clear();
}
}
}

View File

@@ -48,7 +48,58 @@ export type EventName =
| 'slash_command_used'
| 'settings_changed'
| 'app_started'
| 'app_closed';
| 'app_closed'
// New session events
| 'prompt_submitted'
| 'session_stopped'
| 'checkpoint_created'
| 'checkpoint_restored'
| 'tool_executed'
// New agent events
| 'agent_started'
| 'agent_progress'
| 'agent_error'
// New MCP events
| 'mcp_server_added'
| 'mcp_server_removed'
| 'mcp_tool_invoked'
| 'mcp_connection_error'
// New slash command events
| 'slash_command_selected'
| 'slash_command_executed'
| 'slash_command_created'
// New error and performance events
| 'api_error'
| 'ui_error'
| 'performance_bottleneck'
| 'memory_warning'
// User journey events
| 'journey_milestone'
| 'user_retention'
// AI interaction events
| 'ai_interaction'
| 'prompt_pattern'
// Quality events
| 'output_regenerated'
| 'conversation_abandoned'
| 'suggestion_accepted'
| 'suggestion_rejected'
// Workflow events
| 'workflow_started'
| 'workflow_completed'
| 'workflow_abandoned'
// Feature adoption events
| 'feature_discovered'
| 'feature_adopted'
| 'feature_combination'
// Resource usage events
| 'resource_usage_high'
| 'resource_usage_sampled'
// Network performance events
| 'network_performance'
| 'network_failure'
// Engagement events
| 'session_engagement';
export interface FeatureUsageProperties {
feature: string;
@@ -99,4 +150,296 @@ export interface PerformanceMetrics {
memory_usage_mb?: number;
api_response_time_ms?: number;
render_time_ms?: number;
}
}
// Claude Code Session event properties
export interface PromptSubmittedProperties {
prompt_length: number;
model: string;
has_attachments: boolean;
source: 'keyboard' | 'button';
word_count: number;
}
export interface SessionStoppedProperties {
duration_ms: number;
messages_count: number;
reason: 'user_stopped' | 'error' | 'completed';
}
// Enhanced session stopped properties for detailed analytics
export interface EnhancedSessionStoppedProperties extends SessionStoppedProperties {
// Timing metrics
time_to_first_message_ms?: number;
average_response_time_ms?: number;
idle_time_ms?: number;
// Interaction metrics
prompts_sent: number;
tools_executed: number;
tools_failed: number;
files_created: number;
files_modified: number;
files_deleted: number;
// Content metrics
total_tokens_used?: number;
code_blocks_generated?: number;
errors_encountered: number;
// Session context
model: string;
has_checkpoints: boolean;
checkpoint_count?: number;
was_resumed: boolean;
// Agent context (if applicable)
agent_type?: string;
agent_name?: string;
agent_success?: boolean;
// Stop context
stop_source: 'user_button' | 'keyboard_shortcut' | 'timeout' | 'error' | 'completed';
final_state: 'success' | 'partial' | 'failed' | 'cancelled';
has_pending_prompts: boolean;
pending_prompts_count?: number;
}
export interface CheckpointCreatedProperties {
checkpoint_number: number;
session_duration_at_checkpoint: number;
}
export interface CheckpointRestoredProperties {
checkpoint_id: string;
time_since_checkpoint_ms: number;
}
export interface ToolExecutedProperties {
tool_name: string;
execution_time_ms: number;
success: boolean;
error_message?: string;
}
// Enhanced Agent properties
export interface AgentStartedProperties {
agent_type: string;
agent_name?: string;
has_custom_prompt: boolean;
}
export interface AgentProgressProperties {
step_number: number;
step_type: string;
duration_ms: number;
agent_type: string;
}
export interface AgentErrorProperties {
error_type: string;
error_stage: string;
retry_count: number;
agent_type: string;
}
// MCP properties
export interface MCPServerAddedProperties {
server_type: string;
configuration_method: 'manual' | 'preset' | 'import';
}
export interface MCPServerRemovedProperties {
server_name: string;
was_connected: boolean;
}
export interface MCPToolInvokedProperties {
server_name: string;
tool_name: string;
invocation_source: 'user' | 'agent' | 'suggestion';
}
export interface MCPConnectionErrorProperties {
server_name: string;
error_type: string;
retry_attempt: number;
}
// Slash Command properties
export interface SlashCommandSelectedProperties {
command_name: string;
selection_method: 'click' | 'keyboard' | 'autocomplete';
}
export interface SlashCommandExecutedProperties {
command_name: string;
parameters_count: number;
execution_time_ms: number;
}
export interface SlashCommandCreatedProperties {
command_type: 'custom' | 'imported';
has_parameters: boolean;
}
// Error and Performance properties
export interface APIErrorProperties {
endpoint: string;
error_code: string | number;
retry_count: number;
response_time_ms: number;
}
export interface UIErrorProperties {
component_name: string;
error_type: string;
user_action?: string;
}
export interface PerformanceBottleneckProperties {
operation_type: string;
duration_ms: number;
data_size?: number;
threshold_exceeded: boolean;
}
export interface MemoryWarningProperties {
component: string;
memory_mb: number;
threshold_exceeded: boolean;
gc_count?: number;
}
// User Journey properties
export interface UserJourneyProperties {
journey_stage: 'onboarding' | 'first_chat' | 'first_agent' | 'power_user';
milestone_reached?: string;
time_to_milestone_ms?: number;
}
// Enhanced prompt properties
export interface EnhancedPromptSubmittedProperties extends PromptSubmittedProperties {
conversation_depth: number;
prompt_complexity: 'simple' | 'moderate' | 'complex';
contains_code: boolean;
language_detected?: string;
session_age_ms: number;
}
// Enhanced tool properties
export interface EnhancedToolExecutedProperties extends ToolExecutedProperties {
tool_category: 'file' | 'search' | 'system' | 'custom';
consecutive_failures?: number;
retry_attempted: boolean;
input_size_bytes?: number;
output_size_bytes?: number;
}
// Enhanced error properties
export interface EnhancedErrorProperties extends ErrorProperties {
user_action_before_error?: string;
recovery_attempted: boolean;
recovery_successful?: boolean;
error_frequency: number;
stack_trace_hash?: string;
}
// Session engagement properties
export interface SessionEngagementProperties {
session_duration_ms: number;
messages_sent: number;
tools_used: string[];
files_modified: number;
engagement_score: number;
}
// Feature discovery properties
export interface FeatureDiscoveryProperties {
feature_name: string;
discovery_method: 'organic' | 'prompted' | 'documentation';
time_to_first_use_ms: number;
initial_success: boolean;
}
// Output quality properties
export interface OutputQualityProperties {
regeneration_count: number;
modification_requested: boolean;
final_acceptance: boolean;
time_to_acceptance_ms: number;
}
// Resource usage properties
export interface ResourceUsageProperties {
cpu_usage_percent?: number;
memory_usage_mb: number;
disk_io_mb?: number;
network_requests_count: number;
cache_hit_rate?: number;
active_connections: number;
}
// Feature adoption properties
export interface FeatureAdoptionProperties {
feature: string;
adoption_stage: 'discovered' | 'tried' | 'adopted' | 'abandoned';
usage_count: number;
days_since_first_use: number;
usage_trend: 'increasing' | 'stable' | 'decreasing';
}
// Feature combination properties
export interface FeatureCombinationProperties {
primary_feature: string;
secondary_feature: string;
combination_frequency: number;
workflow_efficiency_gain?: number;
}
// AI interaction properties
export interface AIInteractionProperties {
model: string;
request_tokens: number;
response_tokens: number;
response_quality_score?: number;
context_switches: number;
clarification_requests: number;
}
// Prompt pattern properties
export interface PromptPatternProperties {
prompt_category: string;
prompt_effectiveness: 'high' | 'medium' | 'low';
required_iterations: number;
final_satisfaction: boolean;
}
// Workflow properties
export interface WorkflowProperties {
workflow_type: string;
steps_completed: number;
total_steps: number;
duration_ms: number;
interruptions: number;
completion_rate: number;
tools_used: string[];
}
// Network performance properties
export interface NetworkPerformanceProperties {
endpoint_type: 'mcp' | 'api' | 'webhook';
latency_ms: number;
payload_size_bytes: number;
connection_quality: 'excellent' | 'good' | 'poor';
retry_count: number;
circuit_breaker_triggered: boolean;
}
// Suggestion properties
export interface SuggestionProperties {
suggestion_type: string;
suggestion_source: string;
accepted: boolean;
response_time_ms: number;
}