Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ set(THERMAL_SIMD_DISPATCHER_CPU_FLAGS "-msse4.1" CACHE STRING "CPU-specific comp

include(CTest)

find_package(OpenSSL REQUIRED)

file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include/thermal/simd)
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/include/thermal/simd/version.h.in
Expand All @@ -32,6 +34,8 @@ set(THERMAL_SIMD_CORE_SOURCES
src/telemetry/fusion.cpp
src/telemetry/fusion_bridge.cpp
src/observability/metrics.cpp
src/observability/statsd_exporter.cpp
src/observability/telemetry_state.cpp
src/thermal_config.c
src/thermal_cpu.c
src/patcher/trampoline.cpp
Expand All @@ -57,6 +61,8 @@ target_compile_definitions(thermal_simd_core
TSD_DEFAULT_COEFF_PATH="${CMAKE_CURRENT_SOURCE_DIR}/config/controller_coeffs.json"
)

target_link_libraries(thermal_simd_core PRIVATE pthread OpenSSL::SSL OpenSSL::Crypto)

add_executable(thermal_simd src/main.cpp src/thermal_simd.c)
target_compile_options(thermal_simd PRIVATE -O2 -pthread -fPIC -mno-avx ${THERMAL_SIMD_DISPATCHER_CPU_FLAGS})
target_link_libraries(thermal_simd PRIVATE thermal_simd_core pthread)
Expand Down Expand Up @@ -89,6 +95,7 @@ if(BUILD_TESTING)
PRIVATE
TSD_DEFAULT_COEFF_PATH="${CMAKE_CURRENT_SOURCE_DIR}/config/controller_coeffs.json"
)
target_link_libraries(thermal_simd_core_tests PUBLIC OpenSSL::SSL OpenSSL::Crypto)

add_executable(test_config_parser tests/test_config_parser.c)
target_link_libraries(test_config_parser PRIVATE thermal_simd_core_tests)
Expand Down Expand Up @@ -158,6 +165,11 @@ if(BUILD_TESTING)
target_compile_options(test_integration_metrics_tuner PRIVATE -Wall -Wextra)
add_test(NAME integration_metrics_tuner COMMAND test_integration_metrics_tuner)

add_executable(test_observability_metrics tests/observability/test_metrics_exporter.cpp)
target_link_libraries(test_observability_metrics PRIVATE thermal_simd_core_tests pthread OpenSSL::SSL OpenSSL::Crypto)
target_compile_options(test_observability_metrics PRIVATE -Wall -Wextra -pthread)
add_test(NAME observability_metrics COMMAND test_observability_metrics)

add_library(tsd_stress_common STATIC
tests/stress/stress_common.c
src/thermal_simd.c)
Expand Down
5 changes: 5 additions & 0 deletions config/certs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Metrics Certificates

Place production certificates and private keys here when configuring the dispatcher metrics server. The test suite
ships self-signed certificates under `tests/observability/certs/` that can be copied into this directory for local
smoke testing, but **do not** deploy them to production environments.
12 changes: 12 additions & 0 deletions config/observability/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Observability Configuration

The `metrics.example.json` file documents how to configure the dispatcher metrics server.

* `bind_address`/`port` configure where the HTTPS listener binds. A port of `0` selects an ephemeral port.
* `tls` enables TLS when `certificate` and `private_key` reference PEM-encoded files. Supplying a `client_ca`
enables optional client authentication; set `require_client_auth` to `true` to enforce mutual TLS.
* `basic_auth` secures the endpoints using HTTP basic authentication. Populate the `username` and `password` fields
with values deployed alongside the dispatcher.
* `statsd` enables the StatsD exporter and points it at an upstream aggregator.

Copy the example to your deployment configuration management system and replace the placeholder credential paths.
20 changes: 20 additions & 0 deletions config/observability/metrics.example.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"metrics": {
"bind_address": "0.0.0.0",
"port": 9443,
"tls": {
"certificate": "config/certs/dispatcher.crt",
"private_key": "config/certs/dispatcher.key",
"client_ca": "config/certs/ca.crt",
"require_client_auth": false
},
"basic_auth": {
"username": "metrics",
"password": "change-me"
},
"statsd": {
"host": "127.0.0.1",
"port": 8125
}
}
}
22 changes: 22 additions & 0 deletions include/observability/metrics_exporter.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,28 @@
extern "C" {
#endif

typedef struct tsd_metrics_tls_config_s {
const char *certificate_path;
const char *private_key_path;
const char *ca_certificate_path;
int require_client_auth;
} tsd_metrics_tls_config_t;

typedef struct tsd_metrics_basic_auth_s {
const char *username;
const char *password;
} tsd_metrics_basic_auth_t;

typedef struct tsd_metrics_exporter_config_s {
const char *bind_address;
uint16_t port;
const tsd_metrics_tls_config_t *tls;
const tsd_metrics_basic_auth_t *basic_auth;
const char *statsd_host;
uint16_t statsd_port;
} tsd_metrics_exporter_config_t;

int tsd_metrics_exporter_start_with_config(const tsd_metrics_exporter_config_t *config);
int tsd_metrics_exporter_start(const char *bind_address, uint16_t port);
void tsd_metrics_exporter_stop(void);
uint16_t tsd_metrics_exporter_listen_port(void);
Expand Down
38 changes: 38 additions & 0 deletions include/observability/statsd_exporter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#pragma once

#include <cstdint>
#include <string>

#include <mutex>

#include <sys/socket.h>

namespace observability {

class StatsdExporter {
public:
static StatsdExporter &instance();

void configure(const std::string &host, uint16_t port);
void shutdown();

void send_counter(const std::string &name, uint64_t value);
void send_gauge(const std::string &name, double value);

private:
StatsdExporter();
~StatsdExporter();
StatsdExporter(const StatsdExporter &) = delete;
StatsdExporter &operator=(const StatsdExporter &) = delete;

void send(const std::string &payload);

int socket_;
bool configured_;
struct sockaddr_storage destination_;
socklen_t destination_len_;
std::mutex mutex_;
};

} // namespace observability

87 changes: 87 additions & 0 deletions include/observability/telemetry_state.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#pragma once

#include <thermal/simd/simd_width.h>

#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

typedef struct tsd_controller_telemetry_s {
int fallback_active;
simd_width_t current_width;
simd_width_t recommended_width;
int issued_change;
} tsd_controller_telemetry_t;

typedef struct tsd_fusion_telemetry_s {
int running;
int degraded;
int temp_available;
double package_temp_c;
int freq_available;
double freq_ratio;
int cpi_available;
double thermal_cpi;
int power_available;
double power_budget_w;
} tsd_fusion_telemetry_t;

void tsd_observability_update_controller(const tsd_controller_telemetry_t *telemetry);
void tsd_observability_update_fusion(const tsd_fusion_telemetry_t *telemetry);

#ifdef __cplusplus
}
#endif

#ifdef __cplusplus
#include <chrono>
#include <mutex>
#include <optional>

namespace observability {

struct ControllerTelemetrySnapshot {
bool fallback_active{false};
simd_width_t current_width{SIMD_SSE41};
simd_width_t recommended_width{SIMD_SSE41};
bool issued_change{false};
std::chrono::system_clock::time_point updated_at{std::chrono::system_clock::time_point{}};
};

struct FusionTelemetrySnapshot {
bool running{false};
bool degraded{false};
bool temp_available{false};
double package_temp_c{0.0};
bool freq_available{false};
double freq_ratio{0.0};
bool cpi_available{false};
double thermal_cpi{0.0};
bool power_available{false};
double power_budget_w{0.0};
std::chrono::system_clock::time_point updated_at{std::chrono::system_clock::time_point{}};
};

class TelemetryState {
public:
static TelemetryState &instance();

void update_controller(const tsd_controller_telemetry_t *telemetry);
void update_fusion(const tsd_fusion_telemetry_t *telemetry);

ControllerTelemetrySnapshot controller_snapshot() const;
FusionTelemetrySnapshot fusion_snapshot() const;

private:
TelemetryState() = default;

mutable std::mutex mutex_;
ControllerTelemetrySnapshot controller_{};
FusionTelemetrySnapshot fusion_{};
};

} // namespace observability
#endif

Loading