skill_web/api/
analytics.rs

1//! Analytics API client
2
3use chrono::{DateTime, Utc};
4use serde::{Deserialize, Serialize};
5
6use super::{ApiClient, ApiResult};
7
8#[derive(Clone)]
9pub struct AnalyticsApi {
10    client: ApiClient,
11}
12
13impl AnalyticsApi {
14    pub fn new(client: ApiClient) -> Self {
15        Self { client }
16    }
17
18    /// Get analytics overview
19    pub async fn get_overview(&self, days: u32) -> ApiResult<AnalyticsOverviewResponse> {
20        self.client
21            .get(&format!("/analytics/overview?days={}", days))
22            .await
23    }
24
25    /// Get top queries
26    pub async fn get_top_queries(&self, limit: usize, days: u32) -> ApiResult<TopQueriesResponse> {
27        self.client
28            .get(&format!(
29                "/analytics/top-queries?limit={}&days={}",
30                limit, days
31            ))
32            .await
33    }
34
35    /// Get feedback statistics
36    pub async fn get_feedback_stats(&self, days: u32) -> ApiResult<FeedbackStatsResponse> {
37        self.client
38            .get(&format!("/analytics/feedback-stats?days={}", days))
39            .await
40    }
41
42    /// Get search timeline
43    pub async fn get_timeline(
44        &self,
45        days: u32,
46        interval_hours: u32,
47    ) -> ApiResult<SearchTimelineResponse> {
48        self.client
49            .get(&format!(
50                "/analytics/timeline?days={}&interval_hours={}",
51                days, interval_hours
52            ))
53            .await
54    }
55}
56
57// Response types
58
59#[derive(Debug, Clone, Deserialize, Serialize)]
60pub struct AnalyticsOverviewResponse {
61    pub total_searches: usize,
62    pub total_feedback: usize,
63    pub positive_feedback: usize,
64    pub negative_feedback: usize,
65    pub avg_latency_ms: f64,
66    pub avg_results: f64,
67    pub recent_searches: Vec<SearchHistorySummary>,
68}
69
70#[derive(Debug, Clone, Deserialize, Serialize)]
71pub struct SearchHistorySummary {
72    pub query: String,
73    pub results_count: usize,
74    pub duration_ms: u64,
75    pub timestamp: DateTime<Utc>,
76}
77
78#[derive(Debug, Clone, Deserialize, Serialize)]
79pub struct TopQueriesResponse {
80    pub queries: Vec<QueryStats>,
81}
82
83#[derive(Debug, Clone, Deserialize, Serialize)]
84pub struct QueryStats {
85    pub query: String,
86    pub count: usize,
87    pub avg_results: f64,
88    pub avg_latency_ms: f64,
89    pub positive_feedback: usize,
90    pub negative_feedback: usize,
91}
92
93#[derive(Debug, Clone, Deserialize, Serialize)]
94pub struct FeedbackStatsResponse {
95    pub by_type: Vec<FeedbackTypeCount>,
96    pub top_positive: Vec<ResultFeedbackSummary>,
97    pub top_negative: Vec<ResultFeedbackSummary>,
98}
99
100#[derive(Debug, Clone, Deserialize, Serialize)]
101pub struct FeedbackTypeCount {
102    pub feedback_type: String,
103    pub count: usize,
104}
105
106#[derive(Debug, Clone, Deserialize, Serialize)]
107pub struct ResultFeedbackSummary {
108    pub result_id: String,
109    pub positive_count: usize,
110    pub negative_count: usize,
111    pub total_count: usize,
112}
113
114#[derive(Debug, Clone, Deserialize, Serialize)]
115pub struct SearchTimelineResponse {
116    pub timeline: Vec<TimelineDataPoint>,
117}
118
119#[derive(Debug, Clone, Deserialize, Serialize)]
120pub struct TimelineDataPoint {
121    pub timestamp: DateTime<Utc>,
122    pub search_count: usize,
123    pub avg_latency_ms: f64,
124}