Skip to main content

roder_protocol/
stats.rs

1//! `stats/*` protocol DTOs for local usage analytics (roadmap phase 73).
2//!
3//! Responses re-use the analytics crate's summary records, which exclude
4//! prompt/assistant/tool-output bodies and secrets by construction.
5//! Workspace labels arrive already transformed by the configured label
6//! mode. All listing windows are bounded server-side.
7
8use serde::{Deserialize, Serialize};
9
10pub use roder_usage_analytics::{
11    SessionSummary, StatsFilter, TokenSummaryRow, ToolSummary, UsageSummary,
12};
13
14#[derive(Debug, Clone, Default, Serialize, Deserialize)]
15#[serde(rename_all = "camelCase")]
16pub struct StatsQueryParams {
17    #[serde(default)]
18    pub filter: StatsFilter,
19}
20
21#[derive(Debug, Clone, Serialize, Deserialize)]
22#[serde(rename_all = "camelCase")]
23pub struct StatsSummaryResult {
24    pub summary: UsageSummary,
25}
26
27#[derive(Debug, Clone, Serialize, Deserialize)]
28#[serde(rename_all = "camelCase")]
29pub struct StatsToolsParams {
30    #[serde(default)]
31    pub filter: StatsFilter,
32    /// `calls` (default), `p95`, `errors`, or `underused`.
33    #[serde(default)]
34    pub sort: Option<String>,
35}
36
37#[derive(Debug, Clone, Serialize, Deserialize)]
38#[serde(rename_all = "camelCase")]
39pub struct StatsToolsResult {
40    pub tools: Vec<ToolSummary>,
41}
42
43#[derive(Debug, Clone, Serialize, Deserialize)]
44#[serde(rename_all = "camelCase")]
45pub struct StatsTokensParams {
46    #[serde(default)]
47    pub filter: StatsFilter,
48    /// `day` (default), `session`, `provider`, `model`, or `workspace`.
49    #[serde(default)]
50    pub group: Option<String>,
51}
52
53#[derive(Debug, Clone, Serialize, Deserialize)]
54#[serde(rename_all = "camelCase")]
55pub struct StatsTokensResult {
56    pub rows: Vec<TokenSummaryRow>,
57}
58
59#[derive(Debug, Clone, Serialize, Deserialize)]
60#[serde(rename_all = "camelCase")]
61pub struct StatsSessionsResult {
62    pub sessions: Vec<SessionSummary>,
63}
64
65#[derive(Debug, Clone, Serialize, Deserialize)]
66#[serde(rename_all = "camelCase")]
67pub struct StatsBackfillParams {
68    #[serde(default)]
69    pub rebuild: bool,
70    #[serde(default)]
71    pub best_effort: bool,
72}
73
74#[derive(Debug, Clone, Serialize, Deserialize)]
75#[serde(rename_all = "camelCase")]
76pub struct StatsBackfillResult {
77    pub files_scanned: u64,
78    pub lines_ingested: u64,
79    pub lines_skipped_by_offset: u64,
80    pub sessions_enriched: u64,
81    pub parse_error_count: u64,
82    pub rollup_rows: u64,
83}
84
85#[derive(Debug, Clone, Serialize, Deserialize)]
86#[serde(rename_all = "camelCase")]
87pub struct StatsExportParams {
88    /// Server-side output path; export never streams an unbounded payload
89    /// through the JSON-RPC response.
90    pub output_path: String,
91}
92
93#[derive(Debug, Clone, Serialize, Deserialize)]
94#[serde(rename_all = "camelCase")]
95pub struct StatsExportResult {
96    pub output_path: String,
97    pub records: u64,
98}