Skip to main content

systemprompt_cli/commands/analytics/costs/
mod.rs

1mod breakdown;
2mod summary;
3mod trends;
4
5use anyhow::Result;
6use clap::Subcommand;
7use schemars::JsonSchema;
8use serde::{Deserialize, Serialize};
9use systemprompt_runtime::DatabaseContext;
10
11use crate::CliConfig;
12
13#[derive(Debug, Subcommand)]
14pub enum CostsCommands {
15    #[command(about = "Cost summary")]
16    Summary(summary::SummaryArgs),
17
18    #[command(about = "Cost trends over time")]
19    Trends(trends::TrendsArgs),
20
21    #[command(about = "Cost breakdown by model/agent")]
22    Breakdown(breakdown::BreakdownArgs),
23}
24
25#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
26pub struct CostSummaryOutput {
27    pub period: String,
28    pub total_cost_cents: i64,
29    pub total_requests: i64,
30    pub total_tokens: i64,
31    pub avg_cost_per_request_cents: f64,
32    pub change_percent: Option<f64>,
33}
34
35#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
36pub struct CostTrendPoint {
37    pub timestamp: String,
38    pub cost_cents: i64,
39    pub request_count: i64,
40    pub tokens: i64,
41}
42
43#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
44pub struct CostTrendsOutput {
45    pub period: String,
46    pub group_by: String,
47    pub points: Vec<CostTrendPoint>,
48    pub total_cost_cents: i64,
49}
50
51#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
52pub struct CostBreakdownItem {
53    pub name: String,
54    pub cost_cents: i64,
55    pub request_count: i64,
56    pub tokens: i64,
57    pub percentage: f64,
58}
59
60#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
61pub struct CostBreakdownOutput {
62    pub period: String,
63    pub breakdown_by: String,
64    pub items: Vec<CostBreakdownItem>,
65    pub total_cost_cents: i64,
66}
67
68pub async fn execute(command: CostsCommands, config: &CliConfig) -> Result<()> {
69    match command {
70        CostsCommands::Summary(args) => summary::execute(args, config).await,
71        CostsCommands::Trends(args) => trends::execute(args, config).await,
72        CostsCommands::Breakdown(args) => breakdown::execute(args, config).await,
73    }
74}
75
76pub async fn execute_with_pool(
77    command: CostsCommands,
78    db_ctx: &DatabaseContext,
79    config: &CliConfig,
80) -> Result<()> {
81    match command {
82        CostsCommands::Summary(args) => summary::execute_with_pool(args, db_ctx, config).await,
83        CostsCommands::Trends(args) => trends::execute_with_pool(args, db_ctx, config).await,
84        CostsCommands::Breakdown(args) => breakdown::execute_with_pool(args, db_ctx, config).await,
85    }
86}