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

Ubuntu 22下OpenTelemetry C++批处理GRPC日志导出器编译失败,EmitLogRecord()调用报错

Ubuntu 22下OpenTelemetry C++批处理GRPC日志导出器编译失败,EmitLogRecord()调用报错

我帮你分析下问题所在——你遇到的编译错误,核心原因是混淆了OpenTelemetry日志模块的API层和SDK层类型,EmitLogRecord()方法期望的Lambda参数是API层的日志对象,而不是SDK内部的处理对象,这才导致了类型不匹配的编译报错。

具体错误点

你代码里的Lambda参数写的是sdk_logs::Recordable&,但Logger::EmitLogRecord()要求的Lambda参数是api_logs::LogRecord&:

  • API层的LogRecord是我们用户构建日志的入口,是给开发者用的;
  • SDK层的Recordable是OpenTelemetry内部用来处理日志的类型,不需要我们直接操作。

修改后的完整代码

下面是修正后的代码,我已经把关键错误点修复,同时补充了一些细节避免其他潜在问题:

#include <chrono>
#include <iostream>
#include <string>
#include "opentelemetry/sdk/logs/batch_log_record_processor.h"
#include "opentelemetry/sdk/logs/logger_provider_factory.h"
#include "opentelemetry/sdk/logs/logger_provider.h"
#include "opentelemetry/logs/provider.h"
#include "opentelemetry/sdk/version/version.h"
#include "opentelemetry/exporters/otlp/otlp_grpc_log_record_exporter_factory.h"

namespace api_logs = opentelemetry::logs;
namespace common = opentelemetry::common;
namespace otlp = opentelemetry::exporter::otlp;
namespace sdk_logs = opentelemetry::sdk::logs;

int main() {
  // exporter
  otlp::OtlpGrpcLogRecordExporterOptions logger_opts_grpc;
  logger_opts_grpc.endpoint = "localhost:4317"; // set collector endpoint
  logger_opts_grpc.use_ssl_credentials = false; // true if TLS required

  // processor
  opentelemetry::sdk::logs::BatchLogRecordProcessorOptions batch_options;
  batch_options.max_queue_size = 2048; // default: 2048
  batch_options.schedule_delay_millis = std::chrono::milliseconds(500); // delay before forcing a flush
  batch_options.max_export_batch_size = 512; // max logs per export

  // build grpc log exporter, batch processor and provider
  auto exporter = otlp::OtlpGrpcLogRecordExporterFactory::Create(logger_opts_grpc);
  auto processor = std::make_unique<sdk_logs::BatchLogRecordProcessor>(std::move(exporter), batch_options);
  auto sdk_provider = sdk_logs::LoggerProviderFactory::Create(std::move(processor));
  auto shared_provider = std::shared_ptr<sdk_logs::LoggerProvider>(std::move(sdk_provider));

  // upcast shared_ptr<sdk_logs::LoggerProvider> to shared_ptr<api_logs::LoggerProvider>
  std::shared_ptr<api_logs::LoggerProvider> provider = std::static_pointer_cast<api_logs::LoggerProvider>(shared_provider);
  api_logs::Provider::SetLoggerProvider(provider);

  // check
  auto global_provider = api_logs::Provider::GetLoggerProvider();
  std::cout << "LoggerProvider type: " << typeid(*global_provider).name() << std::endl;

  auto logger = provider->GetLogger("first log", "", OPENTELEMETRY_SDK_VERSION);

  // thread_local so lambda can access without specifying a capture mode.
  static thread_local uint32_t tl_j = 1;

  // 修正后的EmitLogRecord调用
  logger->EmitLogRecord([&](api_logs::LogRecord& record) {
    record.SetSeverity(api_logs::Severity::kInfo);
    record.SetBody(common::AttributeValue("User login via gRPC exporter"));
    record.SetAttribute("bool", common::AttributeValue(true));
    record.SetAttribute("u32", common::AttributeValue(tl_j));
  });

  shared_provider->ForceFlush(std::chrono::seconds(5));
  shared_provider->Shutdown();

  return 0;
}

额外注意的细节

  1. SetBody()的参数类型:这个方法需要传入common::AttributeValue类型,直接传字符串会编译失败,所以必须把字符串包装一下;
  2. Lambda捕获:虽然tl_j是static thread_local可以不用捕获,但用[&]显式捕获引用会让代码更清晰,也能避免后续修改变量作用域时出问题;
  3. 编译链接依赖:编译时别忘了链接必要的库,比如需要加上-lotel_sdk -lotel_exporter_otlp_grpc_logs -lgrpc++ -lprotobuf这些库,确保能找到OpenTelemetry的相关实现。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 13:12:58