Skip to content

deps: Add unified metric collection interface (IMetricCollector) #234

Description

@kcenon

Summary

Extend common_system monitoring interfaces with a unified IMetricCollector to enable clean metric reporting across the ecosystem without requiring direct monitoring_system dependencies.

5W1H Specification

  • Who: common_system maintainers
  • What: Add IMetricCollector interface for cross-module metric reporting
  • Where: include/kcenon/common/interfaces/monitoring/
  • When: Before v0.4.0.0 (blocks network_system monitoring decoupling)
  • Why:
    • network_system currently has optional monitoring_system dependency for metrics
    • thread_system defines its own monitoring_interface
    • A unified interface enables modules to report metrics without compile-time dependencies
  • How: Extend existing IMonitor interface family with metric collection capability

Priority

CRITICAL - This is a blocking dependency for:

  • network_system monitoring decoupling
  • thread_system monitoring consolidation
  • logger_system monitoring integration

Proposed Interface Design

File: include/kcenon/common/interfaces/monitoring/metric_collector_interface.h

#pragma once

#include <chrono>
#include <functional>
#include <map>
#include <string>
#include <string_view>

namespace kcenon::common::interfaces {

/// Metric label set for dimensional data
using metric_labels = std::map<std::string, std::string>;

/// Interface for collecting metrics across modules
class IMetricCollector {
public:
    virtual ~IMetricCollector() = default;

    /// Increment a counter metric
    virtual auto increment(std::string_view name, 
                          double value = 1.0,
                          const metric_labels& labels = {}) -> void = 0;

    /// Set a gauge metric to absolute value
    virtual auto gauge(std::string_view name, 
                      double value,
                      const metric_labels& labels = {}) -> void = 0;

    /// Record a histogram observation
    virtual auto histogram(std::string_view name, 
                          double value,
                          const metric_labels& labels = {}) -> void = 0;

    /// Record a timing measurement
    virtual auto timing(std::string_view name,
                       std::chrono::nanoseconds duration,
                       const metric_labels& labels = {}) -> void = 0;
};

/// RAII timer for automatic timing measurements
class scoped_timer {
public:
    scoped_timer(IMetricCollector& collector, 
                 std::string_view name,
                 metric_labels labels = {})
        : collector_(collector)
        , name_(name)
        , labels_(std::move(labels))
        , start_(std::chrono::steady_clock::now()) {}

    ~scoped_timer() {
        auto elapsed = std::chrono::steady_clock::now() - start_;
        collector_.timing(name_, 
            std::chrono::duration_cast<std::chrono::nanoseconds>(elapsed),
            labels_);
    }

private:
    IMetricCollector& collector_;
    std::string name_;
    metric_labels labels_;
    std::chrono::steady_clock::time_point start_;
};

/// Null implementation for when metrics are disabled
class null_metric_collector : public IMetricCollector {
public:
    void increment(std::string_view, double, const metric_labels&) override {}
    void gauge(std::string_view, double, const metric_labels&) override {}
    void histogram(std::string_view, double, const metric_labels&) override {}
    void timing(std::string_view, std::chrono::nanoseconds, const metric_labels&) override {}
};

} // namespace kcenon::common::interfaces

Relationship with Existing IMonitor

The existing IMonitor interface focuses on:

  • Health checks (health_check_result)
  • Metrics snapshots (metrics_snapshot)
  • Component status reporting

IMetricCollector complements this by providing:

  • Real-time metric emission (counter, gauge, histogram)
  • Label/tag support for dimensional metrics
  • RAII timing helpers
IMonitor (read status)     IMetricCollector (emit metrics)
       ↓                            ↓
   [Component]  ─────────────>  [Metrics Backend]

Tasks

  • Create include/kcenon/common/interfaces/monitoring/metric_collector_interface.h
  • Implement IMetricCollector interface with counter/gauge/histogram/timing
  • Implement scoped_timer RAII helper
  • Implement null_metric_collector for disabled metrics
  • Update umbrella header to include new interface
  • Add unit tests for interface concepts
  • Document relationship with existing IMonitor

Acceptance Criteria

  • IMetricCollector interface compiles with C++20
  • scoped_timer correctly measures and reports timing
  • null_metric_collector provides no-op implementation
  • Interface is header-only (no runtime dependencies)
  • Compatible with existing IMonitor interface family

Downstream Impact

Repository Change Required
monitoring_system Implement IMetricCollector adapter
network_system Use IMetricCollector instead of direct monitoring_system
thread_system Migrate to IMetricCollector from local monitoring_interface
database_system Use IMetricCollector for query metrics

Parent Epic

Related Issues

  • Extends existing IMonitor interface (no issue reference)

Metadata

Metadata

Assignees

Labels

architectureArchitectural changes and designdependenciesExternal dependencies managementpriority:highHigh priority issue

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions