Skip to main content

systemprompt_analytics/models/reporting/
request.rs

1//! CLI-facing request analytics rows.
2//!
3//! Copyright (c) systemprompt.io — Business Source License 1.1.
4//! See <https://systemprompt.io> for licensing details.
5
6use chrono::{DateTime, Utc};
7use serde::{Deserialize, Serialize};
8use sqlx::FromRow;
9use systemprompt_identifiers::{AiRequestId, ContextId, UserId};
10
11#[derive(Debug, Clone, Copy, Serialize, Deserialize, FromRow)]
12pub struct RequestStatsRow {
13    pub total: i64,
14    pub total_tokens: Option<i64>,
15    pub input_tokens: Option<i64>,
16    pub output_tokens: Option<i64>,
17    pub reasoning_tokens: Option<i64>,
18    pub cache_read_tokens: Option<i64>,
19    pub cache_creation_tokens: Option<i64>,
20    pub cost: Option<i64>,
21    pub avg_latency: Option<f64>,
22    pub cache_hits: i64,
23}
24
25#[derive(Debug, Clone, Serialize, Deserialize, FromRow)]
26pub struct ModelUsageRow {
27    pub provider: String,
28    pub model: String,
29    pub request_count: i64,
30    pub total_tokens: Option<i64>,
31    pub total_cost: Option<i64>,
32    pub avg_latency: Option<f64>,
33}
34
35#[derive(Debug, Clone, Copy, Serialize, Deserialize, FromRow)]
36pub struct RequestTrendRow {
37    pub created_at: DateTime<Utc>,
38    pub tokens_used: Option<i32>,
39    pub cost_microdollars: Option<i64>,
40    pub latency_ms: Option<i32>,
41}
42
43#[derive(Debug, Clone, Default)]
44pub struct RequestListFilter {
45    pub limit: i64,
46    pub offset: i64,
47    pub model: Option<String>,
48    pub user: Option<UserId>,
49}
50
51impl RequestListFilter {
52    #[must_use]
53    pub const fn new(limit: i64) -> Self {
54        Self {
55            limit,
56            offset: 0,
57            model: None,
58            user: None,
59        }
60    }
61
62    #[must_use]
63    pub const fn with_offset(mut self, offset: i64) -> Self {
64        self.offset = offset;
65        self
66    }
67
68    #[must_use]
69    pub fn with_model(mut self, model: impl Into<String>) -> Self {
70        self.model = Some(model.into());
71        self
72    }
73
74    #[must_use]
75    pub fn with_user(mut self, user: UserId) -> Self {
76        self.user = Some(user);
77        self
78    }
79}
80
81#[derive(Debug, Clone, Serialize, Deserialize, FromRow)]
82pub struct RequestListRow {
83    pub id: AiRequestId,
84    pub provider: Option<String>,
85    pub model: Option<String>,
86    pub input_tokens: Option<i32>,
87    pub output_tokens: Option<i32>,
88    pub cost_microdollars: Option<i64>,
89    pub latency_ms: Option<i32>,
90    pub cache_hit: Option<bool>,
91    pub created_at: DateTime<Utc>,
92    pub status: String,
93    pub error_message: Option<String>,
94    pub user_id: UserId,
95}
96
97#[derive(Debug, Clone, Copy, Serialize, Deserialize, FromRow)]
98pub struct CostSummaryRow {
99    pub requests: i64,
100    pub cost: Option<i64>,
101    pub tokens: Option<i64>,
102    pub reasoning_tokens: Option<i64>,
103    pub cache_read_tokens: Option<i64>,
104    pub cache_creation_tokens: Option<i64>,
105}
106
107#[derive(Debug, Clone, Copy, Serialize, Deserialize, FromRow)]
108pub struct PreviousCostRow {
109    pub cost: Option<i64>,
110}
111
112#[derive(Debug, Clone, Serialize, Deserialize, FromRow)]
113pub struct CostBreakdownRow {
114    pub name: String,
115    pub cost: i64,
116    pub requests: i64,
117    pub tokens: i64,
118}
119
120/// Spend grouped by requesting user.
121///
122/// `name` comes from the reporting projection, which carries no email —
123/// the address never leaves the source table.
124#[derive(Debug, Clone, Serialize, Deserialize, FromRow)]
125pub struct CostUserBreakdownRow {
126    pub user_id: UserId,
127    pub name: Option<String>,
128    pub cost: i64,
129    pub requests: i64,
130    pub tokens: i64,
131    pub conversations: i64,
132}
133
134#[derive(Debug, Clone, Copy, Serialize, Deserialize, FromRow)]
135pub struct ContextSummaryRow {
136    pub conversations: i64,
137    pub ai_requests: i64,
138}
139
140#[derive(Debug, Clone, Serialize, Deserialize, FromRow)]
141pub struct ContextGroupRow {
142    pub name: String,
143    pub conversations: i64,
144    pub ai_requests: i64,
145}
146
147#[derive(Debug, Clone, Serialize, Deserialize, FromRow)]
148pub struct RecentContextRow {
149    pub context_id: ContextId,
150    pub last_activity: DateTime<Utc>,
151    pub ai_requests: i64,
152    pub model: Option<String>,
153    pub agent_name: Option<String>,
154    pub context_name: Option<String>,
155}
156
157#[derive(Debug, Clone, Copy, Serialize, Deserialize, FromRow)]
158pub struct CostTrendRow {
159    pub created_at: DateTime<Utc>,
160    pub cost_microdollars: Option<i64>,
161    pub tokens_used: Option<i32>,
162}