Skip to main content

systemprompt_analytics/snapshots/
types.rs

1//! Snapshot values explicitly distinguish unavailable identity and suppressed
2//! coverage.
3//!
4//! Copyright (c) systemprompt.io — Business Source License 1.1.
5//! See <https://systemprompt.io> for licensing details.
6
7use chrono::{DateTime, NaiveDate, Utc};
8use serde::{Deserialize, Serialize};
9use std::collections::BTreeMap;
10use systemprompt_identifiers::{AnalyticsSnapshotJobId, AnalyticsWorkerId, ManagedResourceId};
11
12#[derive(
13    Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq, schemars::JsonSchema,
14)]
15#[serde(default)]
16/// Additive counts and measured denominators for the selected contribution
17/// range.
18pub struct SnapshotMetrics {
19    pub invocations: i64,
20    pub verified_invocations: i64,
21    pub requests: i64,
22    pub failed_requests: i64,
23    pub priced_requests: i64,
24    pub latency_measured_requests: i64,
25    pub token_measured_requests: i64,
26    pub input_tokens: i128,
27    pub output_tokens: i128,
28    pub assessed_conversations: i64,
29    pub assessment_conversations: i64,
30    pub failed_assessments: i64,
31}
32#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
33/// A retained aggregate result with explicit identity and suppression
34/// availability.
35pub struct FeedbackSnapshot {
36    pub resource_id: Option<ManagedResourceId>,
37    pub generation: i64,
38    pub fact_generation: i64,
39    pub from_day: NaiveDate,
40    pub to_day: NaiveDate,
41    pub generated_at: DateTime<Utc>,
42    pub metrics: SnapshotMetrics,
43    pub spend_by_currency: BTreeMap<String, i128>,
44    pub distinct_users: Option<i64>,
45    pub distinct_sessions: Option<i64>,
46    pub histogram: super::LatencyHistogram,
47    pub related_spend_non_additive: bool,
48    pub suppressed_days: i64,
49    pub historical_identity_available: bool,
50}
51#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
52/// Durable generation watermarks and outstanding producer, fact, and range
53/// work.
54pub struct SnapshotHealth {
55    pub generation: i64,
56    pub fact_generation: i64,
57    pub generated_at: Option<DateTime<Utc>>,
58    pub last_error: Option<String>,
59    pub pending_changes: i64,
60    pub pending_producer_changes: i64,
61    pub facts_generation: i64,
62    pub pending_jobs: i64,
63}
64#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
65#[serde(deny_unknown_fields)]
66/// An idempotent bounded request for a UTC-day aggregate range.
67pub struct SnapshotRangeRequest {
68    pub operation_id: AnalyticsSnapshotJobId,
69    pub resource_id: Option<ManagedResourceId>,
70    pub from_day: NaiveDate,
71    pub to_day: NaiveDate,
72}
73#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
74/// A durable custom-range operation and its current result or diagnostic.
75pub struct SnapshotRangeJob {
76    pub operation_id: AnalyticsSnapshotJobId,
77    pub state: SnapshotJobState,
78    pub result: Option<FeedbackSnapshot>,
79    pub diagnostic: Option<String>,
80}
81#[derive(Debug, Clone)]
82/// Worker identity and fencing epoch for a leased custom-range operation.
83pub struct SnapshotJobLease {
84    pub operation_id: AnalyticsSnapshotJobId,
85    pub worker_id: AnalyticsWorkerId,
86    pub epoch: i64,
87}
88#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
89#[serde(rename_all = "snake_case")]
90/// Lifecycle of a custom-range operation; `failed` is terminal and carries the
91/// assembly diagnostic.
92pub enum SnapshotJobState {
93    Pending,
94    Leased,
95    Ready,
96    Failed,
97}
98impl SnapshotJobState {
99    #[must_use]
100    pub const fn as_str(self) -> &'static str {
101        match self {
102            Self::Pending => "pending",
103            Self::Leased => "leased",
104            Self::Ready => "ready",
105            Self::Failed => "failed",
106        }
107    }
108    pub fn parse(state: &str) -> crate::Result<Self> {
109        Ok(match state {
110            "pending" => Self::Pending,
111            "leased" => Self::Leased,
112            "ready" => Self::Ready,
113            "failed" => Self::Failed,
114            _ => return Err(super::invalid("Unknown range job state")),
115        })
116    }
117}
118#[derive(Debug, Clone, Copy, Serialize, Deserialize, schemars::JsonSchema)]
119/// One organizational scope compacted behind drained evidence barriers.
120pub struct RetentionOutcome {
121    pub compacted_before: NaiveDate,
122    pub removed_facts: u64,
123    pub removed_daily: u64,
124}
125
126/// Aggregate results after every initialized organizational scope is compacted
127/// atomically.
128#[derive(Debug, Clone, Copy, Serialize, Deserialize, schemars::JsonSchema)]
129pub struct RetentionSummary {
130    pub organizations: u64,
131    pub removed_facts: u64,
132    pub removed_daily: u64,
133}