Skip to main content

progit_plugin_sdk/traits/
analytics.rs

1// SPDX-License-Identifier: LSL-1.0
2// Copyright (c) 2025 Markus Maiwald
3
4//! Analytics plugin traits
5//!
6//! Traits for plugins that compute metrics, generate reports, or export data.
7
8use serde::{Deserialize, Serialize};
9use std::collections::HashMap;
10
11use super::core::{Issue, Plugin, PluginResult};
12
13/// Query parameters for filtering issues in analytics
14#[derive(Debug, Clone, Serialize, Deserialize, Default)]
15pub struct AnalyticsQuery {
16    /// Date range for the query
17    pub date_range: Option<DateRange>,
18    /// Filter by statuses
19    pub statuses: Vec<String>,
20    /// Filter by tags
21    pub tags: Vec<String>,
22    /// Filter by assignees
23    pub assignees: Vec<String>,
24    /// Filter by sprints
25    pub sprints: Vec<u32>,
26    /// Include deleted issues
27    pub include_deleted: bool,
28    /// Maximum number of results
29    pub limit: Option<usize>,
30    /// Offset for pagination
31    pub offset: Option<usize>,
32}
33
34/// Date range for queries
35#[derive(Debug, Clone, Serialize, Deserialize)]
36pub struct DateRange {
37    /// Start date (ISO 8601)
38    pub start: String,
39    /// End date (ISO 8601)
40    pub end: String,
41}
42
43/// Types of metrics that can be computed
44#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
45pub enum MetricType {
46    /// Issues completed per sprint/week
47    Velocity,
48    /// Time from created to done
49    LeadTime,
50    /// Time from in-progress to done
51    CycleTime,
52    /// Total issues completed in period
53    Throughput,
54    /// Work in progress count
55    WIP,
56    /// Percentage of issues that are blocked
57    BlockedRatio,
58    /// Estimated vs actual effort accuracy
59    EffortAccuracy,
60    /// Number of issues by status
61    StatusDistribution,
62    /// Number of issues by tag
63    TagDistribution,
64    /// Number of issues by assignee
65    AssigneeWorkload,
66    /// Custom metric with name
67    Custom(String),
68}
69
70/// Result of a metric computation
71#[derive(Debug, Clone, Serialize, Deserialize)]
72pub struct MetricValue {
73    /// The metric that was computed
74    pub metric: MetricType,
75    /// The computed value
76    pub value: f64,
77    /// Unit of measurement (e.g., "issues", "days", "percent")
78    pub unit: String,
79    /// Breakdown by category (per-tag, per-assignee, etc.)
80    pub breakdown: Option<HashMap<String, f64>>,
81    /// Trend compared to previous period
82    pub trend: Option<Trend>,
83}
84
85/// Trend indicator for metrics
86#[derive(Debug, Clone, Serialize, Deserialize)]
87pub struct Trend {
88    /// Change from previous period
89    pub change: f64,
90    /// Percentage change
91    pub change_percent: f64,
92    /// Direction of change
93    pub direction: TrendDirection,
94}
95
96/// Direction of trend change
97#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
98pub enum TrendDirection {
99    Up,
100    Down,
101    Stable,
102}
103
104/// Types of reports that can be generated
105#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
106pub enum ReportType {
107    /// Burndown chart data
108    Burndown,
109    /// Burn-up chart data
110    BurnUp,
111    /// Velocity trend over time
112    VelocityTrend,
113    /// Cumulative flow diagram data
114    CumulativeFlow,
115    /// Lead time trend over time
116    LeadTimeTrend,
117    /// Tag distribution pie chart
118    TagDistribution,
119    /// Assignee workload bar chart
120    AssigneeWorkload,
121    /// Sprint summary
122    SprintSummary,
123    /// Custom report with name
124    Custom(String),
125}
126
127/// A generated report
128#[derive(Debug, Clone, Serialize, Deserialize)]
129pub struct Report {
130    /// Type of report
131    pub report_type: ReportType,
132    /// Report title
133    pub title: String,
134    /// When the report was generated (ISO 8601)
135    pub generated_at: String,
136    /// Data points for charting
137    pub data_points: Vec<DataPoint>,
138    /// Summary statistics
139    pub summary: HashMap<String, serde_json::Value>,
140    /// Report-specific metadata
141    pub metadata: HashMap<String, serde_json::Value>,
142}
143
144/// A single data point in a report
145#[derive(Debug, Clone, Serialize, Deserialize)]
146pub struct DataPoint {
147    /// X-axis label (date, sprint number, etc.)
148    pub label: String,
149    /// Y-axis values (can have multiple series)
150    pub values: HashMap<String, f64>,
151}
152
153/// Export formats for data
154#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
155pub enum ExportFormat {
156    /// JSON format
157    Json,
158    /// CSV format
159    Csv,
160    /// Markdown format
161    Markdown,
162    /// HTML format
163    Html,
164    /// Custom format with name
165    Custom(String),
166}
167
168/// Historical issue snapshot for analytics
169#[derive(Debug, Clone, Serialize, Deserialize)]
170pub struct IssueSnapshot {
171    /// The issue at this point in time
172    pub issue: Issue,
173    /// When this snapshot was taken (ISO 8601)
174    pub snapshot_time: String,
175    /// Status at snapshot time
176    pub status_at_time: String,
177    /// Sprint at snapshot time
178    pub sprint_at_time: Option<u32>,
179}
180
181/// Sprint definition
182#[derive(Debug, Clone, Serialize, Deserialize)]
183pub struct Sprint {
184    /// Sprint number
185    pub number: u32,
186    /// Sprint name (optional)
187    pub name: Option<String>,
188    /// Start date (ISO 8601)
189    pub start_date: String,
190    /// End date (ISO 8601)
191    pub end_date: String,
192    /// Sprint goal
193    pub goal: Option<String>,
194    /// Total effort committed
195    pub committed_effort: u32,
196    /// Total effort completed
197    pub completed_effort: u32,
198}
199
200/// Status transition record
201#[derive(Debug, Clone, Serialize, Deserialize)]
202pub struct StatusTransition {
203    /// Issue ID
204    pub issue_id: String,
205    /// Previous status
206    pub from_status: String,
207    /// New status
208    pub to_status: String,
209    /// When the transition occurred (ISO 8601)
210    pub timestamp: String,
211    /// Who made the change
212    pub by_user: Option<String>,
213}
214
215/// Trait for plugins that compute metrics, generate reports, or export data
216pub trait AnalyticsPlugin: Plugin {
217    /// Query issues with filters
218    ///
219    /// Returns issues matching the query parameters.
220    fn query_issues(&mut self, query: &AnalyticsQuery) -> PluginResult<Vec<Issue>>;
221
222    /// Compute a specific metric
223    ///
224    /// Calculates the requested metric for the given date range.
225    fn compute_metric(
226        &mut self,
227        metric: MetricType,
228        range: &DateRange,
229    ) -> PluginResult<MetricValue>;
230
231    /// Generate a report
232    ///
233    /// Creates a full report of the requested type for the given date range.
234    fn generate_report(
235        &mut self,
236        report_type: ReportType,
237        range: &DateRange,
238    ) -> PluginResult<Report>;
239
240    /// Export data in specified format
241    ///
242    /// Exports filtered data in the requested format. Returns raw bytes.
243    fn export(
244        &mut self,
245        format: ExportFormat,
246        query: &AnalyticsQuery,
247    ) -> PluginResult<Vec<u8>>;
248
249    /// Get available metrics
250    ///
251    /// Returns list of metrics this plugin can compute.
252    fn available_metrics(&self) -> Vec<MetricType> {
253        vec![
254            MetricType::Velocity,
255            MetricType::LeadTime,
256            MetricType::CycleTime,
257            MetricType::Throughput,
258            MetricType::WIP,
259        ]
260    }
261
262    /// Get available report types
263    ///
264    /// Returns list of reports this plugin can generate.
265    fn available_reports(&self) -> Vec<ReportType> {
266        vec![
267            ReportType::Burndown,
268            ReportType::VelocityTrend,
269        ]
270    }
271
272    /// Get available export formats
273    ///
274    /// Returns list of export formats this plugin supports.
275    fn available_formats(&self) -> Vec<ExportFormat> {
276        vec![
277            ExportFormat::Json,
278            ExportFormat::Csv,
279        ]
280    }
281
282    /// Get historical snapshots
283    ///
284    /// Returns historical issue snapshots for trend analysis.
285    fn get_snapshots(
286        &mut self,
287        _range: &DateRange,
288    ) -> PluginResult<Vec<IssueSnapshot>> {
289        // Default: no historical data
290        Ok(vec![])
291    }
292
293    /// Get status transitions
294    ///
295    /// Returns status transition history for cycle time analysis.
296    fn get_transitions(
297        &mut self,
298        _range: &DateRange,
299    ) -> PluginResult<Vec<StatusTransition>> {
300        // Default: no transition data
301        Ok(vec![])
302    }
303
304    /// Get sprint definitions
305    ///
306    /// Returns sprint information for sprint-based reports.
307    fn get_sprints(&mut self) -> PluginResult<Vec<Sprint>> {
308        // Default: no sprint data
309        Ok(vec![])
310    }
311}