Skip to content

Commit b27ef03

Browse files
Merge pull request #38 from SaridakisStamatisChristos/codex/add-metrics-registry-and-statsd-exporter
Add TLS-enabled metrics registry with StatsD and health probes
2 parents cbf4847 + 736ab72 commit b27ef03

File tree

16 files changed

+1276
-142
lines changed

16 files changed

+1276
-142
lines changed

CMakeLists.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ set(THERMAL_SIMD_DISPATCHER_CPU_FLAGS "-msse4.1" CACHE STRING "CPU-specific comp
88

99
include(CTest)
1010

11+
find_package(OpenSSL REQUIRED)
12+
1113
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include/thermal/simd)
1214
configure_file(
1315
${CMAKE_CURRENT_SOURCE_DIR}/include/thermal/simd/version.h.in
@@ -32,6 +34,8 @@ set(THERMAL_SIMD_CORE_SOURCES
3234
src/telemetry/fusion.cpp
3335
src/telemetry/fusion_bridge.cpp
3436
src/observability/metrics.cpp
37+
src/observability/statsd_exporter.cpp
38+
src/observability/telemetry_state.cpp
3539
src/thermal_config.c
3640
src/thermal_cpu.c
3741
src/patcher/trampoline.cpp
@@ -57,6 +61,8 @@ target_compile_definitions(thermal_simd_core
5761
TSD_DEFAULT_COEFF_PATH="${CMAKE_CURRENT_SOURCE_DIR}/config/controller_coeffs.json"
5862
)
5963

64+
target_link_libraries(thermal_simd_core PRIVATE pthread OpenSSL::SSL OpenSSL::Crypto)
65+
6066
add_executable(thermal_simd src/main.cpp src/thermal_simd.c)
6167
target_compile_options(thermal_simd PRIVATE -O2 -pthread -fPIC -mno-avx ${THERMAL_SIMD_DISPATCHER_CPU_FLAGS})
6268
target_link_libraries(thermal_simd PRIVATE thermal_simd_core pthread)
@@ -89,6 +95,7 @@ if(BUILD_TESTING)
8995
PRIVATE
9096
TSD_DEFAULT_COEFF_PATH="${CMAKE_CURRENT_SOURCE_DIR}/config/controller_coeffs.json"
9197
)
98+
target_link_libraries(thermal_simd_core_tests PUBLIC OpenSSL::SSL OpenSSL::Crypto)
9299

93100
add_executable(test_config_parser tests/test_config_parser.c)
94101
target_link_libraries(test_config_parser PRIVATE thermal_simd_core_tests)
@@ -158,6 +165,11 @@ if(BUILD_TESTING)
158165
target_compile_options(test_integration_metrics_tuner PRIVATE -Wall -Wextra)
159166
add_test(NAME integration_metrics_tuner COMMAND test_integration_metrics_tuner)
160167

168+
add_executable(test_observability_metrics tests/observability/test_metrics_exporter.cpp)
169+
target_link_libraries(test_observability_metrics PRIVATE thermal_simd_core_tests pthread OpenSSL::SSL OpenSSL::Crypto)
170+
target_compile_options(test_observability_metrics PRIVATE -Wall -Wextra -pthread)
171+
add_test(NAME observability_metrics COMMAND test_observability_metrics)
172+
161173
add_library(tsd_stress_common STATIC
162174
tests/stress/stress_common.c
163175
src/thermal_simd.c)

config/certs/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Metrics Certificates
2+
3+
Place production certificates and private keys here when configuring the dispatcher metrics server. The test suite
4+
ships self-signed certificates under `tests/observability/certs/` that can be copied into this directory for local
5+
smoke testing, but **do not** deploy them to production environments.

config/observability/README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Observability Configuration
2+
3+
The `metrics.example.json` file documents how to configure the dispatcher metrics server.
4+
5+
* `bind_address`/`port` configure where the HTTPS listener binds. A port of `0` selects an ephemeral port.
6+
* `tls` enables TLS when `certificate` and `private_key` reference PEM-encoded files. Supplying a `client_ca`
7+
enables optional client authentication; set `require_client_auth` to `true` to enforce mutual TLS.
8+
* `basic_auth` secures the endpoints using HTTP basic authentication. Populate the `username` and `password` fields
9+
with values deployed alongside the dispatcher.
10+
* `statsd` enables the StatsD exporter and points it at an upstream aggregator.
11+
12+
Copy the example to your deployment configuration management system and replace the placeholder credential paths.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"metrics": {
3+
"bind_address": "0.0.0.0",
4+
"port": 9443,
5+
"tls": {
6+
"certificate": "config/certs/dispatcher.crt",
7+
"private_key": "config/certs/dispatcher.key",
8+
"client_ca": "config/certs/ca.crt",
9+
"require_client_auth": false
10+
},
11+
"basic_auth": {
12+
"username": "metrics",
13+
"password": "change-me"
14+
},
15+
"statsd": {
16+
"host": "127.0.0.1",
17+
"port": 8125
18+
}
19+
}
20+
}

include/observability/metrics_exporter.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,28 @@
99
extern "C" {
1010
#endif
1111

12+
typedef struct tsd_metrics_tls_config_s {
13+
const char *certificate_path;
14+
const char *private_key_path;
15+
const char *ca_certificate_path;
16+
int require_client_auth;
17+
} tsd_metrics_tls_config_t;
18+
19+
typedef struct tsd_metrics_basic_auth_s {
20+
const char *username;
21+
const char *password;
22+
} tsd_metrics_basic_auth_t;
23+
24+
typedef struct tsd_metrics_exporter_config_s {
25+
const char *bind_address;
26+
uint16_t port;
27+
const tsd_metrics_tls_config_t *tls;
28+
const tsd_metrics_basic_auth_t *basic_auth;
29+
const char *statsd_host;
30+
uint16_t statsd_port;
31+
} tsd_metrics_exporter_config_t;
32+
33+
int tsd_metrics_exporter_start_with_config(const tsd_metrics_exporter_config_t *config);
1234
int tsd_metrics_exporter_start(const char *bind_address, uint16_t port);
1335
void tsd_metrics_exporter_stop(void);
1436
uint16_t tsd_metrics_exporter_listen_port(void);
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#pragma once
2+
3+
#include <cstdint>
4+
#include <string>
5+
6+
#include <mutex>
7+
8+
#include <sys/socket.h>
9+
10+
namespace observability {
11+
12+
class StatsdExporter {
13+
public:
14+
static StatsdExporter &instance();
15+
16+
void configure(const std::string &host, uint16_t port);
17+
void shutdown();
18+
19+
void send_counter(const std::string &name, uint64_t value);
20+
void send_gauge(const std::string &name, double value);
21+
22+
private:
23+
StatsdExporter();
24+
~StatsdExporter();
25+
StatsdExporter(const StatsdExporter &) = delete;
26+
StatsdExporter &operator=(const StatsdExporter &) = delete;
27+
28+
void send(const std::string &payload);
29+
30+
int socket_;
31+
bool configured_;
32+
struct sockaddr_storage destination_;
33+
socklen_t destination_len_;
34+
std::mutex mutex_;
35+
};
36+
37+
} // namespace observability
38+
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
#pragma once
2+
3+
#include <thermal/simd/simd_width.h>
4+
5+
#include <stdint.h>
6+
7+
#ifdef __cplusplus
8+
extern "C" {
9+
#endif
10+
11+
typedef struct tsd_controller_telemetry_s {
12+
int fallback_active;
13+
simd_width_t current_width;
14+
simd_width_t recommended_width;
15+
int issued_change;
16+
} tsd_controller_telemetry_t;
17+
18+
typedef struct tsd_fusion_telemetry_s {
19+
int running;
20+
int degraded;
21+
int temp_available;
22+
double package_temp_c;
23+
int freq_available;
24+
double freq_ratio;
25+
int cpi_available;
26+
double thermal_cpi;
27+
int power_available;
28+
double power_budget_w;
29+
} tsd_fusion_telemetry_t;
30+
31+
void tsd_observability_update_controller(const tsd_controller_telemetry_t *telemetry);
32+
void tsd_observability_update_fusion(const tsd_fusion_telemetry_t *telemetry);
33+
34+
#ifdef __cplusplus
35+
}
36+
#endif
37+
38+
#ifdef __cplusplus
39+
#include <chrono>
40+
#include <mutex>
41+
#include <optional>
42+
43+
namespace observability {
44+
45+
struct ControllerTelemetrySnapshot {
46+
bool fallback_active{false};
47+
simd_width_t current_width{SIMD_SSE41};
48+
simd_width_t recommended_width{SIMD_SSE41};
49+
bool issued_change{false};
50+
std::chrono::system_clock::time_point updated_at{std::chrono::system_clock::time_point{}};
51+
};
52+
53+
struct FusionTelemetrySnapshot {
54+
bool running{false};
55+
bool degraded{false};
56+
bool temp_available{false};
57+
double package_temp_c{0.0};
58+
bool freq_available{false};
59+
double freq_ratio{0.0};
60+
bool cpi_available{false};
61+
double thermal_cpi{0.0};
62+
bool power_available{false};
63+
double power_budget_w{0.0};
64+
std::chrono::system_clock::time_point updated_at{std::chrono::system_clock::time_point{}};
65+
};
66+
67+
class TelemetryState {
68+
public:
69+
static TelemetryState &instance();
70+
71+
void update_controller(const tsd_controller_telemetry_t *telemetry);
72+
void update_fusion(const tsd_fusion_telemetry_t *telemetry);
73+
74+
ControllerTelemetrySnapshot controller_snapshot() const;
75+
FusionTelemetrySnapshot fusion_snapshot() const;
76+
77+
private:
78+
TelemetryState() = default;
79+
80+
mutable std::mutex mutex_;
81+
ControllerTelemetrySnapshot controller_{};
82+
FusionTelemetrySnapshot fusion_{};
83+
};
84+
85+
} // namespace observability
86+
#endif
87+

0 commit comments

Comments
 (0)