Architecture Overview

1. System Context

FT System Metrics is a satellite service for the FTACS platform. It connects to the FTACS database in read-only mode and exports aggregated metrics for Prometheus.

1.1. System Context Diagram

Diagram

1.2. Core Operations

  • Device Metrics — device count by protocol and tenant, online/offline status

  • Task Metrics — task distribution by status and type over time windows

  • Event Metrics — CPE event distribution by type for the previous hour

  • Multi-tenant Tagging — all metrics are tagged with the ISP/tenant name

2. Component Architecture

2.1. Layered Architecture

Diagram

2.2. Key Components

Component Description

PrometheusMetricsFilter

A OncePerRequestFilter that intercepts requests to /actuator/prometheus and triggers all metrics collectors before the response is generated.

CpeMetricsCollector

Collects device metrics: total count by protocol, online/offline status. TR069 devices determine online status via the cpe_next_session_time table (check_time >= now + 10s); all other protocols use the is_online field.

CpeTaskMetricsCollector

Collects task distribution by status (Pending, Completed, Failed, Rejected, Sent) for the current and previous day, as well as distribution by task type for the last 24 hours.

CpeEventCollector

Collects CPE event distribution by type for the previous hour. Only executes during the first minute of each hour (TimeUtil.isFirstMinuteOfHour()).

IspService

Maps ISP/tenant IDs to names for metric tagging. Handles the super domain (ID=0) separately.

TimeUtil

Utility for computing time windows: start/end of the previous hour, previous day, and first-minute-of-hour check.

Micrometer Registry

The Micrometer metrics registry. Gauges store current values in a ConcurrentHashMap and are re-registered on each collection cycle.

3. Request Flow

3.1. Prometheus Scrape Flow

Diagram

3.2. Flow Description

  1. Prometheus sends a GET request to /actuator/prometheus every 15 seconds

  2. PrometheusMetricsFilter intercepts the request and sequentially invokes three collectors

  3. Each collector executes SQL queries against the database via JPA repositories

  4. Query results are mapped onto Projection interfaces

  5. Collectors register Gauge metrics in the Micrometer Registry with tags (tenant, protocol, status, etc.)

  6. The Actuator Prometheus endpoint formats the response in Prometheus text format

4. Multi-Database Strategy

The application supports MySQL and Oracle through the Strategy pattern with Spring Profiles:

CpeTaskQueryRepository (interface)
+-- MysqlCpeTaskQueryRepository  (@Profile("mysql"))
+-- OracleCpeTaskQueryRepository (@Profile("oracle"))

CpeLogQueryRepository (interface)
+-- MysqlCpeLogQueryRepository   (@Profile("mysql"))
+-- OracleCpeLogQueryRepository  (@Profile("oracle"))

4.1. Key Differences Between Implementations

Feature MySQL Oracle

Date formatting

DATE_FORMAT(date, '%Y-%m-%d')

TO_CHAR(date, 'YYYY-MM-DD')

Hour formatting

DATE_FORMAT(date, '%Y-%m-%d %H:00:00')

TO_CHAR(date, 'YYYY-MM-DD HH24:00:00')

GROUP BY

Allows aliases in GROUP BY

Requires full expressions in GROUP BY

Profile activation

spring.profiles.active=mysql

spring.profiles.active=oracle

4.2. Profile Selection

The database profile is determined by the DB_VENDOR variable in the Dockerfile:

ENV DB_VENDOR=mysql
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -Dspring.profiles.active=${DB_VENDOR:-mysql} -jar app.jar"]

In application.yml, profiles are grouped as follows:

spring:
  profiles:
    group:
      mysql:  [ common, mysql ]
      oracle: [ common, oracle ]

The common profile contains shared JPA and HikariCP settings, while the mysql/oracle profiles hold database-specific parameters (driver, URL, dialect).