Metrics & Monitoring
1. Overview
FT System Metrics exports metrics in Prometheus format via the Spring Boot Actuator endpoint /actuator/prometheus.
Metrics collection is triggered by PrometheusMetricsFilter on each scrape request from Prometheus. Three specialized collectors aggregate data from the database and register Gauge/Counter metrics in the Micrometer Registry.
1.1. Endpoint
GET /actuator/prometheus
Returns all metrics in Prometheus text format. Available Actuator endpoints:
| Endpoint | Description |
|---|---|
|
Application status (including database connection state) |
|
Application information |
|
All metrics in Prometheus format |
|
List of available metrics (JSON) |
|
Details for a specific metric (JSON) |
2. Metrics Collectors
2.1. Collection Trigger
PrometheusMetricsFilter (extends OncePerRequestFilter) intercepts every HTTP request. If the URI equals /actuator/prometheus, the filter sequentially invokes three collectors:
if (request.getRequestURI().equals("/actuator/prometheus")) {
cpeMetricsCollector.collect();
cpeTaskMetricsCollector.collectTaskMetrics();
cpeEventCollector.collectEventMetrics();
}
2.2. Gauge Registration Pattern
All collectors use a ConcurrentHashMap to store Gauge metric values. On each collection cycle the map is cleared and populated with fresh values:
private final Map<String, Number> gaugeValues = new ConcurrentHashMap<>();
// Registration pattern
String gaugeId = String.format("metric_%s_%s", tenantId, dimension);
gaugeValues.put(gaugeId, value);
Gauge.builder("metric.name", gaugeValues, map -> map.get(gaugeId).doubleValue())
.tags("tenant", tenantName, "dimension", dimensionValue)
.description("Metric description")
.register(registry);
3. Device Metrics (CpeMetricsCollector)
3.1. cpe.devices.total
Total number of registered devices broken down by protocol and tenant.
| Property | Value |
|---|---|
Type |
Gauge |
Tags |
|
Source |
|
Update |
On each Prometheus scrape |
Example output:
cpe_devices_total{application="ft-system-metrics",protocol="TR069",tenant="Default"} 15234.0
cpe_devices_total{application="ft-system-metrics",protocol="LWM2M",tenant="ISP-A"} 892.0
3.2. cpe.devices.online_status
Number of online and offline devices broken down by protocol and tenant.
| Property | Value |
|---|---|
Type |
Gauge |
Tags |
|
Source |
Non-TR069: |
Update |
On each Prometheus scrape |
Online detection logic:
-
TR069 — a device is online if
cpe_next_session_time.check_time >= LocalDateTime.now() + 10s -
All other protocols — a device is online if
cpe.is_online = 1 -
Offline count = total - online
Example output:
cpe_devices_online_status{protocol="TR069",status="online",tenant="Default"} 12100.0
cpe_devices_online_status{protocol="TR069",status="offline",tenant="Default"} 3134.0
4. Task Metrics (CpeTaskMetricsCollector)
4.1. cpe.tasks.status
Task distribution by status for the current and previous day.
| Property | Value |
|---|---|
Type |
Gauge |
Tags |
|
Source |
UNION ALL across |
Time window |
From the start of the previous day ( |
Update |
On each Prometheus scrape |
Task status definitions:
| Status | Source |
|---|---|
Completed |
|
Failed |
|
Rejected |
|
Pending |
|
Sent |
|
Example output:
cpe_tasks_status{day="2026-02-17",status="Completed",tenant="Default"} 4521.0
cpe_tasks_status{day="2026-02-17",status="Failed",tenant="Default"} 23.0
cpe_tasks_status{day="2026-02-18",status="Pending",tenant="Default"} 156.0
4.2. cpe.tasks.type
Task distribution by type for the last 24 hours grouped by hour.
| Property | Value |
|---|---|
Type |
Gauge |
Tags |
|
Source |
UNION ALL across all four task tables |
Time window |
From the start of the previous hour ( |
Update |
On each Prometheus scrape |
Task types (subset):
| ID | Name | ID | Name |
|---|---|---|---|
0 |
GetRPCMethods |
2 |
Reboot |
4 |
SetParameterValues |
5 |
GetParameterNames |
9 |
FactoryReset |
10 |
ScheduleInform |
29 |
Download |
36 |
Upload |
37 |
CustomRPC |
… |
… |
Example output:
cpe_tasks_type{hour="2026-02-18 14:00:00",type="SetParameterValues",tenant="Default"} 89.0
cpe_tasks_type{hour="2026-02-18 14:00:00",type="Reboot",tenant="ISP-A"} 12.0
5. Event Metrics (CpeEventCollector)
|
Event metrics are collected only during the first minute of each hour ( |
5.1. cpe.events.type
CPE event distribution by type for the previous hour.
| Property | Value |
|---|---|
Type |
Gauge |
Tags |
|
Source |
|
Time window |
Previous hour |
Update |
Once per hour (first minute) |
Example output:
cpe_events_type{hour="2026-02-18 14:00:00",type="0 BOOTSTRAP",tenant="Default"} 342.0
cpe_events_type{hour="2026-02-18 14:00:00",type="1 BOOT",tenant="Default"} 1205.0
5.2. cpe.events.total.last_hour
Total number of CPE events for the previous hour by tenant.
| Property | Value |
|---|---|
Type |
Gauge |
Tags |
|
Source |
|
Time window |
Previous hour |
Update |
Once per hour (first minute) |
Example output:
cpe_events_total_last_hour{hour="14",tenant="Default"} 8923.0
6. Metrics Reference
6.1. Complete Metrics Table
| Metric Name | Type | Labels | Description |
|---|---|---|---|
|
Gauge |
|
Total registered devices by protocol and tenant |
|
Gauge |
|
Online/offline device count |
|
Counter |
|
All tenants in the system |
|
Gauge |
|
Task count by status and date |
|
Gauge |
|
Task count by type and hour |
|
Gauge |
|
Event count by type and hour |
|
Gauge |
|
Total event count in the previous hour |
6.2. Standard Micrometer Metrics
In addition to custom metrics, the application automatically exports standard Micrometer metrics:
-
http.server.requests— HTTP requests with histogram and SLA buckets -
jvm.*— JVM metrics (memory, threads, GC) -
process.*— process metrics (CPU, uptime) -
system.*— system metrics (CPU load) -
hikaricp.*— connection pool metrics -
spring.data.repository.*— Spring Data metrics
7. Prometheus Integration
7.1. Scrape Configuration
Prometheus is configured via the prometheus.yml file:
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'spring-boot-app'
metrics_path: '/actuator/prometheus'
static_configs:
- targets: ['ft-system-metrics:8080']
7.2. Useful PromQL Queries
Total devices by tenant:
sum by (tenant) (cpe_devices_total)
Online ratio by protocol:
cpe_devices_online_status{status="online"}
/
cpe_devices_total
Task failure rate by tenant (today):
cpe_tasks_status{status="Failed", day="2026-02-18"}
/
(cpe_tasks_status{status="Completed", day="2026-02-18"} + cpe_tasks_status{status="Failed", day="2026-02-18"})
Events per hour trend:
cpe_events_total_last_hour
8. Grafana Dashboards
8.1. Data Source Setup
-
Open Grafana:
http://localhost:3000 -
Log in:
admin/admin(or theGRAFANA_PASSWORDvalue) -
Configuration → Data Sources → Add data source
-
Select Prometheus
-
URL:
http://prometheus:9090(Docker Compose service name) -
Click Save & Test
8.2. Recommended Dashboard Panels
| Panel | Type | PromQL |
|---|---|---|
Total Devices |
Stat |
|
Devices by Protocol |
Pie Chart |
|
Online vs Offline |
Bar Gauge |
|
Online Ratio |
Gauge (%) |
|
Task Status Distribution |
Stacked Bar |
|
Task Types (Last Hour) |
Table |
|
Events per Hour |
Time Series |
|
Event Type Distribution |
Pie Chart |
|
|
On first launch, Grafana data will appear after the first successful scrape from Prometheus (approximately 15 seconds after the application starts). |