Skip to main content

systemprompt_analytics/
extension.rs

1//! Registers analytics-owned reporting, engagement, reputation, funnel and
2//! feedback schemas, seeds and migrations.
3//!
4//! Copyright (c) systemprompt.io — Business Source License 1.1.
5//! See <https://systemprompt.io> for licensing details.
6
7use systemprompt_extension::prelude::*;
8
9#[derive(Debug, Clone, Copy, Default)]
10pub struct AnalyticsExtension;
11
12impl Extension for AnalyticsExtension {
13    fn metadata(&self) -> ExtensionMetadata {
14        ExtensionMetadata {
15            id: "analytics",
16            name: "Analytics",
17            version: env!("CARGO_PKG_VERSION"),
18        }
19    }
20
21    fn schemas(&self) -> Vec<SchemaDefinition> {
22        let mut schemas = capture_schemas();
23        schemas.extend(fact_schemas());
24        schemas.extend(snapshot_schemas());
25        schemas.extend(projection_schemas());
26        schemas.extend(behavioral_schemas());
27        schemas
28    }
29
30    fn dependencies(&self) -> Vec<&'static str> {
31        vec!["users"]
32    }
33
34    fn migrations(&self) -> Vec<Migration> {
35        extension_migrations!()
36    }
37
38    fn seeds(&self) -> Vec<Seed> {
39        vec![Seed::new(
40            "analytics_projection_state",
41            crate::projection::REPORTING_STATE_SEED,
42        )]
43    }
44}
45
46register_extension!(AnalyticsExtension);
47
48fn capture_schemas() -> Vec<SchemaDefinition> {
49    vec![SchemaDefinition::sql_only(include_str!(
50        "../schema/reporting_privacy.sql"
51    ))]
52}
53
54fn fact_schemas() -> Vec<SchemaDefinition> {
55    vec![
56        SchemaDefinition::new(
57            "analytics_ingestion_producers",
58            include_str!("../schema/ingestion_producers.sql"),
59        ),
60        SchemaDefinition::new(
61            "analytics_fact_changes",
62            include_str!("../schema/analytics_fact_changes.sql"),
63        ),
64        SchemaDefinition::new(
65            "analytics_normalized_facts",
66            include_str!("../schema/analytics_normalized_facts.sql"),
67        ),
68        SchemaDefinition::new(
69            "analytics_fact_checkpoints",
70            include_str!("../schema/analytics_fact_checkpoints.sql"),
71        ),
72        SchemaDefinition::new(
73            "analytics_fact_deltas",
74            include_str!("../schema/analytics_fact_deltas.sql"),
75        ),
76        SchemaDefinition::new(
77            "analytics_fact_backfills",
78            include_str!("../schema/analytics_fact_backfills.sql"),
79        ),
80        SchemaDefinition::new(
81            "analytics_fact_backfill_pages",
82            include_str!("../schema/analytics_fact_backfill_pages.sql"),
83        ),
84        SchemaDefinition::new(
85            "analytics_fact_consumers",
86            include_str!("../schema/analytics_fact_consumers.sql"),
87        ),
88    ]
89}
90
91fn snapshot_schemas() -> Vec<SchemaDefinition> {
92    vec![
93        SchemaDefinition::new(
94            "analytics_snapshot_dirty",
95            include_str!("../schema/analytics_snapshot_dirty.sql"),
96        ),
97        SchemaDefinition::new(
98            "analytics_snapshot_shadow",
99            include_str!("../schema/analytics_snapshot_shadow.sql"),
100        ),
101        SchemaDefinition::new(
102            "analytics_snapshot_daily",
103            include_str!("../schema/analytics_snapshot_daily.sql"),
104        ),
105        SchemaDefinition::new(
106            "analytics_snapshot_identities",
107            include_str!("../schema/analytics_snapshot_identities.sql"),
108        ),
109        SchemaDefinition::new(
110            "analytics_snapshot_state",
111            include_str!("../schema/analytics_snapshot_state.sql"),
112        ),
113        SchemaDefinition::new(
114            "analytics_snapshot_jobs",
115            include_str!("../schema/analytics_snapshot_jobs.sql"),
116        ),
117    ]
118}
119
120fn projection_schemas() -> Vec<SchemaDefinition> {
121    vec![
122        SchemaDefinition::new(
123            "analytics_projection_state",
124            include_str!("../schema/analytics_projection_state.sql"),
125        )
126        .with_required_columns(vec!["generation".into(), "cutoff_revision".into()]),
127        SchemaDefinition::new(
128            "analytics_projection_revisions",
129            include_str!("../schema/analytics_projection_revisions.sql"),
130        ),
131        SchemaDefinition::new(
132            "analytics_report_users",
133            include_str!("../schema/analytics_report_users.sql"),
134        ),
135        SchemaDefinition::new(
136            "analytics_report_user_sessions",
137            include_str!("../schema/analytics_report_user_sessions.sql"),
138        ),
139        SchemaDefinition::new(
140            "analytics_report_agent_tasks",
141            include_str!("../schema/analytics_report_agent_tasks.sql"),
142        ),
143        SchemaDefinition::new(
144            "analytics_report_task_messages",
145            include_str!("../schema/analytics_report_task_messages.sql"),
146        ),
147        SchemaDefinition::new(
148            "analytics_report_user_contexts",
149            include_str!("../schema/analytics_report_user_contexts.sql"),
150        ),
151        SchemaDefinition::new(
152            "analytics_report_ai_requests",
153            include_str!("../schema/analytics_report_ai_requests.sql"),
154        ),
155        SchemaDefinition::new(
156            "analytics_report_ai_request_messages",
157            include_str!("../schema/analytics_report_ai_request_messages.sql"),
158        ),
159        SchemaDefinition::new(
160            "analytics_report_mcp_tool_executions",
161            include_str!("../schema/analytics_report_mcp_tool_executions.sql"),
162        ),
163        SchemaDefinition::new(
164            "analytics_report_markdown_content",
165            include_str!("../schema/analytics_report_markdown_content.sql"),
166        ),
167        SchemaDefinition::new(
168            "analytics_report_logs",
169            include_str!("../schema/analytics_report_logs.sql"),
170        ),
171        SchemaDefinition::new(
172            "analytics_report_analytics_events",
173            include_str!("../schema/analytics_report_analytics_events.sql"),
174        ),
175    ]
176}
177
178fn behavioral_schemas() -> Vec<SchemaDefinition> {
179    vec![
180        SchemaDefinition::new(
181            "analytics_feedback_snapshots",
182            include_str!("../schema/analytics_feedback_snapshots.sql"),
183        ),
184        SchemaDefinition::new(
185            "engagement_events",
186            include_str!("../schema/engagement_events.sql"),
187        )
188        .with_required_columns(vec!["id".into(), "session_id".into(), "created_at".into()]),
189        SchemaDefinition::new(
190            "anomaly_thresholds",
191            include_str!("../schema/anomaly_thresholds.sql"),
192        )
193        .with_required_columns(vec!["metric_name".into()]),
194        SchemaDefinition::new(
195            "fingerprint_reputation",
196            include_str!("../schema/fingerprint_reputation.sql"),
197        )
198        .with_required_columns(vec!["fingerprint_hash".into()]),
199        SchemaDefinition::new("funnels", include_str!("../schema/funnels.sql"))
200            .with_required_columns(vec!["id".into(), "name".into()]),
201        SchemaDefinition::new("funnel_steps", include_str!("../schema/funnel_steps.sql"))
202            .with_required_columns(vec!["funnel_id".into(), "step_order".into()]),
203        SchemaDefinition::new(
204            "funnel_progress",
205            include_str!("../schema/funnel_progress.sql"),
206        )
207        .with_required_columns(vec!["id".into(), "funnel_id".into(), "session_id".into()]),
208    ]
209}