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; }
额外注意的细节
SetBody()的参数类型:这个方法需要传入common::AttributeValue类型,直接传字符串会编译失败,所以必须把字符串包装一下;- Lambda捕获:虽然
tl_j是static thread_local可以不用捕获,但用[&]显式捕获引用会让代码更清晰,也能避免后续修改变量作用域时出问题; - 编译链接依赖:编译时别忘了链接必要的库,比如需要加上
-lotel_sdk -lotel_exporter_otlp_grpc_logs -lgrpc++ -lprotobuf这些库,确保能找到OpenTelemetry的相关实现。
内容来源于stack exchange
相关产品推荐
相关产品推荐

