systemprompt_cli/commands/analytics/costs/
mod.rs1mod 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::shared::render_result;
12use crate::CliConfig;
13
14#[derive(Debug, Subcommand)]
15pub enum CostsCommands {
16 #[command(about = "Cost summary")]
17 Summary(summary::SummaryArgs),
18
19 #[command(about = "Cost trends over time")]
20 Trends(trends::TrendsArgs),
21
22 #[command(about = "Cost breakdown by model/agent")]
23 Breakdown(breakdown::BreakdownArgs),
24}
25
26#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
27pub struct CostSummaryOutput {
28 pub period: String,
29 pub total_cost_microdollars: i64,
30 pub total_requests: i64,
31 pub total_tokens: i64,
32 pub avg_cost_per_request_microdollars: f64,
33 pub change_percent: Option<f64>,
34}
35
36#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
37pub struct CostTrendPoint {
38 pub timestamp: String,
39 pub cost_microdollars: i64,
40 pub request_count: i64,
41 pub tokens: i64,
42}
43
44#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
45pub struct CostTrendsOutput {
46 pub period: String,
47 pub group_by: String,
48 pub points: Vec<CostTrendPoint>,
49 pub total_cost_microdollars: i64,
50}
51
52#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
53pub struct CostBreakdownItem {
54 pub name: String,
55 pub cost_microdollars: i64,
56 pub request_count: i64,
57 pub tokens: i64,
58 pub percentage: f64,
59}
60
61#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
62pub struct CostBreakdownOutput {
63 pub period: String,
64 pub breakdown_by: String,
65 pub items: Vec<CostBreakdownItem>,
66 pub total_cost_microdollars: i64,
67}
68
69pub async fn execute(command: CostsCommands, config: &CliConfig) -> Result<()> {
70 match command {
71 CostsCommands::Summary(args) => {
72 let result = summary::execute(args, config).await?;
73 render_result(&result);
74 Ok(())
75 },
76 CostsCommands::Trends(args) => {
77 let result = trends::execute(args, config).await?;
78 render_result(&result);
79 Ok(())
80 },
81 CostsCommands::Breakdown(args) => {
82 let result = breakdown::execute(args, config).await?;
83 render_result(&result);
84 Ok(())
85 },
86 }
87}
88
89pub async fn execute_with_pool(
90 command: CostsCommands,
91 db_ctx: &DatabaseContext,
92 config: &CliConfig,
93) -> Result<()> {
94 match command {
95 CostsCommands::Summary(args) => {
96 let result = summary::execute_with_pool(args, db_ctx, config).await?;
97 render_result(&result);
98 Ok(())
99 },
100 CostsCommands::Trends(args) => {
101 let result = trends::execute_with_pool(args, db_ctx, config).await?;
102 render_result(&result);
103 Ok(())
104 },
105 CostsCommands::Breakdown(args) => {
106 let result = breakdown::execute_with_pool(args, db_ctx, config).await?;
107 render_result(&result);
108 Ok(())
109 },
110 }
111}