Skip to main content

systemprompt_analytics/
extension.rs

1use systemprompt_extension::prelude::*;
2
3const MIGRATION_001_EVENT_TYPE: &str = r"
4ALTER TABLE engagement_events ADD COLUMN IF NOT EXISTS event_type VARCHAR(50) NOT NULL DEFAULT 'page_exit';
5CREATE INDEX IF NOT EXISTS idx_engagement_events_event_type ON engagement_events(event_type);
6";
7
8const MIGRATION_002_EVENT_DATA: &str = r"
9ALTER TABLE engagement_events ADD COLUMN IF NOT EXISTS event_data JSONB;
10";
11
12#[derive(Debug, Clone, Copy, Default)]
13pub struct AnalyticsExtension;
14
15impl Extension for AnalyticsExtension {
16    fn metadata(&self) -> ExtensionMetadata {
17        ExtensionMetadata {
18            id: "analytics",
19            name: "Analytics",
20            version: env!("CARGO_PKG_VERSION"),
21        }
22    }
23
24    fn migration_weight(&self) -> u32 {
25        20
26    }
27
28    fn schemas(&self) -> Vec<SchemaDefinition> {
29        vec![
30            SchemaDefinition::inline(
31                "engagement_events",
32                include_str!("../schema/engagement_events.sql"),
33            )
34            .with_required_columns(vec![
35                "id".into(),
36                "session_id".into(),
37                "created_at".into(),
38            ]),
39            SchemaDefinition::inline(
40                "anomaly_thresholds",
41                include_str!("../schema/anomaly_thresholds.sql"),
42            )
43            .with_required_columns(vec!["metric_name".into()]),
44            SchemaDefinition::inline(
45                "fingerprint_reputation",
46                include_str!("../schema/fingerprint_reputation.sql"),
47            )
48            .with_required_columns(vec!["fingerprint_hash".into()]),
49            SchemaDefinition::inline("funnels", include_str!("../schema/funnels.sql"))
50                .with_required_columns(vec!["id".into(), "name".into()]),
51            SchemaDefinition::inline(
52                "funnel_progress",
53                include_str!("../schema/funnel_progress.sql"),
54            )
55            .with_required_columns(vec![
56                "id".into(),
57                "funnel_id".into(),
58                "session_id".into(),
59            ]),
60        ]
61    }
62
63    fn dependencies(&self) -> Vec<&'static str> {
64        vec!["users"]
65    }
66
67    fn migrations(&self) -> Vec<Migration> {
68        vec![
69            Migration::new(1, "add_engagement_event_type", MIGRATION_001_EVENT_TYPE),
70            Migration::new(2, "add_engagement_event_data", MIGRATION_002_EVENT_DATA),
71        ]
72    }
73}
74
75register_extension!(AnalyticsExtension);