如何在C++ OpenTelemetry中使用Gauge指标与OTLP导出器
OpenTelemetry C++ v1.14.2 Double Observable Gauge 正确使用示例
核心问题分析
- 全局MeterProvider未配置:你的
InitMetrics函数中创建了自定义MeterProvider,但没有将其设置为全局实例,后续获取的Meter属于默认空实现,无法关联到导出器。 - Gauge回调实现错误:回调中错误地创建了未初始化的
ObserverResultT<double>指针,正确做法是将传入的ObserverResult转换为对应类型后直接调用Observe。 - 资源关闭逻辑错误:直接设置空MeterProvider会导致后台导出线程未正常终止,触发
Collect invoked while Shutdown in progress警告。
修正后的完整代码
#include <opentelemetry/metrics/provider.h> #include <opentelemetry/sdk/metrics/meter_provider.h> #include <opentelemetry/sdk/metrics/export/periodic_exporting_metric_reader.h> #include <opentelemetry/exporter/otlp/otlp_http_metric_exporter.h> #include <opentelemetry/metrics/observer_result.h> #include <chrono> #include <thread> #include <string> namespace metrics_api = opentelemetry::metrics; namespace metric_sdk = opentelemetry::sdk::metrics; namespace otlpexportmetrics = opentelemetry::exporter::otlp; void InitMetrics(const std::string& service_name) { // 配置OTLP HTTP指标导出器 opentelemetry::exporter::otlp::OtlpHttpMetricExporterOptions opts; opts.url = "http://ip:port/v1/metrics"; // 替换为你的Collector地址 auto exporter = std::make_unique<otlpexportmetrics::OtlpHttpMetricExporter>(opts); // 配置周期性导出器参数 metric_sdk::PeriodicExportingMetricReaderOptions reader_options; reader_options.export_interval_millis = std::chrono::milliseconds(1000); reader_options.export_timeout_millis = std::chrono::milliseconds(500); // 创建指标读取器 auto reader = std::make_shared<metric_sdk::PeriodicExportingMetricReader>( std::move(exporter), reader_options); // 创建并配置全局MeterProvider auto provider = std::make_shared<metric_sdk::MeterProvider>(); provider->AddMetricReader(reader); // 关键:将自定义Provider设置为全局实例 metrics_api::Provider::SetMeterProvider(provider); } void SetupGauge(const std::string& service_name) { std::string gauge_name = service_name + "_pressure_gauge"; // 获取全局MeterProvider创建Meter auto meter = metrics_api::Provider::GetMeterProvider()->GetMeter( service_name + "_meter", "1.0.0", "https://opentelemetry.io/schemas/1.21.0"); // 创建Double Observable Gauge auto gauge = meter->CreateDoubleObservableGauge( gauge_name, "pressure", "MPa", "System pressure gauge"); // 添加回调函数:每次导出前会调用此函数获取指标值 gauge->AddCallback( [](metrics_api::ObserverResult result, void* state) { // 将通用ObserverResult转换为double类型的观察者 auto double_result = nostd::get<metrics_api::ObserverResultT<double>>(result); // 上报指标值,附带标签 double_result->Observe(5.6, {{"service.name", "example"}, {"component", "pressure-sensor"}}); }, nullptr); } int main() { InitMetrics("example"); SetupGauge("example"); // 运行一段时间,让指标有足够时间导出 std::this_thread::sleep_for(std::chrono::seconds(20)); // 正确关闭:先获取全局Provider,调用Shutdown等待后台线程终止 if (auto provider = std::static_pointer_cast<metric_sdk::MeterProvider>( metrics_api::Provider::GetMeterProvider())) { provider->Shutdown(); } // 清空全局Provider metrics_api::Provider::SetMeterProvider(nullptr); return 0; }
关键修正说明
- 全局MeterProvider设置:在
InitMetrics末尾添加metrics_api::Provider::SetMeterProvider(provider);,确保后续获取的Meter使用自定义的导出配置。 - Gauge回调修正:直接将传入的
ObserverResult转换为ObserverResultT<double>,无需手动创建指针,避免空指针访问问题。 - 优雅关闭资源:调用
MeterProvider::Shutdown()等待后台导出线程完成当前任务并终止,避免触发警告。
内容的提问来源于stack exchange,提问作者Artem
相关产品推荐
相关产品推荐

