Skip to content

Commit 2ca0fa9

Browse files
committed
feat: [#238] add PrometheusContext for template rendering
- Create PrometheusContext struct with scrape_interval, api_token, api_port fields - Add complete module structure following existing patterns - Implement comprehensive unit tests (5 tests covering creation, defaults, serialization) - Update Tera template to use api_port variable (renamed from metrics_port for clarity) - Context extracts data from tracker HTTP API configuration for Prometheus scraping
1 parent 5ae2a69 commit 2ca0fa9

7 files changed

Lines changed: 185 additions & 2 deletions

File tree

src/infrastructure/templating/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
//! - `template` - Template renderers for `OpenTofu` configuration files
2323
//! - `tracker` - Torrust Tracker configuration management
2424
//! - `template` - Template renderers for Tracker configuration files
25+
//! - `prometheus` - Prometheus metrics collection configuration
26+
//! - `template` - Template renderers for Prometheus configuration files
2527
//!
2628
//! ## Template Rendering
2729
//!
@@ -32,5 +34,6 @@
3234
3335
pub mod ansible;
3436
pub mod docker_compose;
37+
pub mod prometheus;
3538
pub mod tofu;
3639
pub mod tracker;
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//! Prometheus integration for metrics collection
2+
//!
3+
//! This module provides Prometheus-specific functionality for the deployment system,
4+
//! including template rendering for Prometheus configuration files.
5+
//!
6+
//! ## Components
7+
//!
8+
//! - `template` - Template rendering functionality for Prometheus configuration
9+
10+
pub mod template;
11+
12+
pub use template::PrometheusContext;
13+
14+
/// Subdirectory name for Prometheus-related files within the build directory.
15+
///
16+
/// Prometheus configuration files will be rendered to `build_dir/storage/prometheus/etc/`.
17+
pub const PROMETHEUS_SUBFOLDER: &str = "storage/prometheus/etc";
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
//! Prometheus template functionality
2+
//!
3+
//! This module provides template-related functionality for Prometheus configuration,
4+
//! including wrappers for dynamic templates.
5+
6+
pub mod wrapper;
7+
8+
pub use wrapper::PrometheusContext;
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
//! Template wrappers for prometheus.yml.tera
2+
//!
3+
//! This module provides context and template wrappers for Prometheus configuration.
4+
5+
pub mod prometheus_config;
6+
7+
pub use prometheus_config::PrometheusContext;
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
//! Prometheus template context
2+
//!
3+
//! Defines the variables needed for prometheus.yml.tera template rendering.
4+
5+
use serde::Serialize;
6+
7+
/// Context for rendering prometheus.yml.tera template
8+
///
9+
/// Contains all variables needed for Prometheus scrape configuration.
10+
/// The context extracts metrics endpoint details from the tracker configuration.
11+
///
12+
/// # Example
13+
///
14+
/// ```rust
15+
/// use torrust_tracker_deployer_lib::infrastructure::templating::prometheus::PrometheusContext;
16+
///
17+
/// let context = PrometheusContext {
18+
/// scrape_interval: 15,
19+
/// api_token: "MyAccessToken".to_string(),
20+
/// api_port: 1212,
21+
/// };
22+
/// ```
23+
///
24+
/// # Data Flow
25+
///
26+
/// Environment Config (`tracker.http_api`) → Application Layer → `PrometheusContext`
27+
///
28+
/// - `scrape_interval`: From `prometheus.scrape_interval` (default: 15 seconds)
29+
/// - `api_token`: From `tracker.http_api.admin_token`
30+
/// - `api_port`: Parsed from `tracker.http_api.bind_address` (e.g., 1212 from "0.0.0.0:1212")
31+
#[derive(Debug, Clone, Serialize, PartialEq)]
32+
pub struct PrometheusContext {
33+
/// How often to scrape metrics from tracker (in seconds)
34+
///
35+
/// Default: 15 seconds
36+
/// Minimum: 5 seconds (to avoid overwhelming the tracker)
37+
/// Maximum: 300 seconds (5 minutes)
38+
pub scrape_interval: u32,
39+
40+
/// Tracker HTTP API admin token for authentication
41+
///
42+
/// This token is required to access the tracker's metrics endpoints:
43+
/// - `/api/v1/stats` - Aggregate statistics
44+
/// - `/api/v1/metrics` - Detailed operational metrics
45+
pub api_token: String,
46+
47+
/// Tracker HTTP API port
48+
///
49+
/// The port where the tracker's HTTP API is listening.
50+
/// Prometheus scrapes metrics from this API.
51+
/// Extracted from the tracker's HTTP API bind address.
52+
/// Example: 1212 from "0.0.0.0:1212"
53+
pub api_port: u16,
54+
}
55+
56+
impl PrometheusContext {
57+
/// Creates a new `PrometheusContext`
58+
///
59+
/// # Arguments
60+
///
61+
/// * `scrape_interval` - How often to scrape metrics (in seconds)
62+
/// * `api_token` - Tracker HTTP API admin token
63+
/// * `api_port` - Tracker HTTP API port
64+
///
65+
/// # Example
66+
///
67+
/// ```rust
68+
/// use torrust_tracker_deployer_lib::infrastructure::templating::prometheus::PrometheusContext;
69+
///
70+
/// let context = PrometheusContext::new(15, "MyToken".to_string(), 1212);
71+
/// ```
72+
#[must_use]
73+
pub fn new(scrape_interval: u32, api_token: String, api_port: u16) -> Self {
74+
Self {
75+
scrape_interval,
76+
api_token,
77+
api_port,
78+
}
79+
}
80+
}
81+
82+
impl Default for PrometheusContext {
83+
fn default() -> Self {
84+
Self {
85+
scrape_interval: 15,
86+
api_token: String::new(),
87+
api_port: 1212,
88+
}
89+
}
90+
}
91+
92+
#[cfg(test)]
93+
mod tests {
94+
use super::*;
95+
96+
#[test]
97+
fn it_should_create_prometheus_context() {
98+
let context = PrometheusContext::new(15, "test_token".to_string(), 1212);
99+
100+
assert_eq!(context.scrape_interval, 15);
101+
assert_eq!(context.api_token, "test_token");
102+
assert_eq!(context.api_port, 1212);
103+
}
104+
105+
#[test]
106+
fn it_should_create_default_context() {
107+
let context = PrometheusContext::default();
108+
109+
assert_eq!(context.scrape_interval, 15);
110+
assert_eq!(context.api_token, "");
111+
assert_eq!(context.api_port, 1212);
112+
}
113+
114+
#[test]
115+
fn it_should_serialize_to_json() {
116+
let context = PrometheusContext::new(30, "admin_token".to_string(), 8080);
117+
118+
let json = serde_json::to_value(&context).unwrap();
119+
assert_eq!(json["scrape_interval"], 30);
120+
assert_eq!(json["api_token"], "admin_token");
121+
assert_eq!(json["api_port"], 8080);
122+
}
123+
124+
#[test]
125+
fn it_should_support_different_scrape_intervals() {
126+
let fast_scrape = PrometheusContext::new(5, "token".to_string(), 1212);
127+
let slow_scrape = PrometheusContext::new(300, "token".to_string(), 1212);
128+
129+
assert_eq!(fast_scrape.scrape_interval, 5);
130+
assert_eq!(slow_scrape.scrape_interval, 300);
131+
}
132+
133+
#[test]
134+
fn it_should_support_different_ports() {
135+
let default_port = PrometheusContext::new(15, "token".to_string(), 1212);
136+
let custom_port = PrometheusContext::new(15, "token".to_string(), 8080);
137+
138+
assert_eq!(default_port.api_port, 1212);
139+
assert_eq!(custom_port.api_port, 8080);
140+
}
141+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
//! Prometheus configuration template wrapper
2+
//!
3+
//! This module provides the context for rendering the prometheus.yml.tera template.
4+
5+
pub mod context;
6+
7+
pub use context::PrometheusContext;

templates/prometheus/prometheus.yml.tera

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ scrape_configs:
1414
token: ["{{ api_token }}"]
1515
format: ["prometheus"]
1616
static_configs:
17-
- targets: ["tracker:{{ metrics_port }}"]
17+
- targets: ["tracker:{{ api_port }}"]
1818

1919
# Tracker Metrics - Detailed operational metrics
2020
- job_name: "tracker_metrics"
@@ -23,4 +23,4 @@ scrape_configs:
2323
token: ["{{ api_token }}"]
2424
format: ["prometheus"]
2525
static_configs:
26-
- targets: ["tracker:{{ metrics_port }}"]
26+
- targets: ["tracker:{{ api_port }}"]

0 commit comments

Comments
 (0)