Goal
Collect system and custom metrics using monitoring_system's collector and factory pattern, then store them for later analysis.
Prerequisites
- monitoring_system installed and linked (
kcenon::monitoring_system)
- Familiarity with
Result<T> from common_system
Step 1: Use a built-in system collector
System collectors ship with the library and require no custom code. Register one and it starts emitting metrics on its own schedule.
auto collector = std::make_shared<system_resource_collector>();
collector->set_interval(std::chrono::seconds(5));
collector->start();
auto snapshot = collector->latest();
std::cout << "CPU: " << snapshot.cpu_percent
<< "% | RSS: " << snapshot.memory_rss_mb << " MB\n";
System resource collector for CPU, memory, and disk metrics.
Step 2: Define a custom metric
For domain-specific measurements, derive from metric_base and populate values on a tick callback or push path.
class queue_depth_metric : public metric_base {
public:
explicit queue_depth_metric(const job_queue& q) : q_(q) {}
metric_sample collect() override {
return metric_sample{
.name = "queue.depth",
.value = static_cast<double>(q_.size()),
.timestamp = std::chrono::system_clock::now()
};
}
private:
const job_queue& q_;
};
Step 3: Register via the factory
The factory pattern centralizes creation and lets the app pick which collectors run based on configuration, not code.
auto& factory = metric_factory::instance();
factory.register_type<queue_depth_metric>("queue.depth");
auto collector = factory.create("queue.depth", queue_context);
registry.add(collector);
Step 4: Time-series storage
Collected samples can be written to an in-memory ring buffer, a local file, or exported via OTLP. See Tutorial: Distributed Tracing for the OTLP path.
Common Mistakes
- Collecting too frequently. Sub-second intervals on cheap metrics are fine; on expensive ones you'll dominate CPU with measurement overhead.
- Unbounded tag cardinality. Tagging metrics with user IDs or request paths creates an explosion of time series. Keep tag values to a bounded set.
- Forgetting to start the collector. Registration alone does nothing — you must call
start().
Next Steps