You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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;
}

关键修正说明

  1. 全局MeterProvider设置:在InitMetrics末尾添加metrics_api::Provider::SetMeterProvider(provider);,确保后续获取的Meter使用自定义的导出配置。
  2. Gauge回调修正:直接将传入的ObserverResult转换为ObserverResultT<double>,无需手动创建指针,避免空指针访问问题。
  3. 优雅关闭资源:调用MeterProvider::Shutdown()等待后台导出线程完成当前任务并终止,避免触发警告。

内容的提问来源于stack exchange,提问作者Artem

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 12:24:51