Ok, I realised that because of the std::move
when declaring the processor, we were giving away the ownership thus we were trying to access a stream that was nullptr...
Here is what I ended up doing:
main.cpp
auto trace_provider = new TraceProvider(vm["trace-provider"].as<std::string>(), vm["trace-output-log-file"].as<std::string>());
trace_provider->InitTracer();
TraceProvider.hpp
class TraceProvider {
public:
TraceProvider(std::string exporter_backend_str, std::string log_trace_output_file = std::string());
~TraceProvider();
void InitTracer();
private:
std::string exporter_backend_str_;
std::string log_trace_output_file_;
std::shared_ptr<std::ofstream> log_trace_output_file_handle_ = nullptr;
void initSimpleTracer();
};
TraceProvider.cpp
TraceProvider::TraceProvider(std::string exporter_backend_str, std::string log_trace_output_file) {
exporter_backend_str_ = exporter_backend_str;
exporter_backend_ = string_to_trace_exporter(exporter_backend_str);
log_trace_output_file_ = log_trace_output_file;
if (exporter_backend_ == Exporter::SIMPLE) {
try {
if (log_trace_output_file_.compare("") != 0) {
log_trace_output_file_handle_ = std::make_shared<std::ofstream>(std::ofstream(log_trace_output_file.c_str()));
} else {
throw std::runtime_error("You chose the Simple trace exporter but you specified an empty log file.");
}
} catch(std::exception const& e) {
std::cout << "Exception: " << e.what() << "\n";
}
}
}
TraceProvider::~TraceProvider() {
// If it exists, close the file stream and delete the ptr
if (log_trace_output_file_handle_ != nullptr) {
std::cout << "Closing tracing log file at: " << log_trace_output_file_ << std::endl;
log_trace_output_file_handle_.get()->close();
log_trace_output_file_handle_.reset();
log_trace_output_file_handle_ = nullptr;
}
}
void TraceProvider::InitTracer() {
switch (exporter_backend_) {
case Exporter::SIMPLE:
initSimpleTracer();
break;
case Exporter::JAEGER:
initJaegerTracer();
break;
default:
std::stringstream err_msg_stream;
err_msg_stream << "Invalid tracing backend: " << exporter_backend_str_
<< "\n";
throw po::validation_error(po::validation_error::invalid_option_value,
err_msg_stream.str());
}
}
void TraceProvider::initSimpleTracer() {
std::unique_ptr<trace_sdk::SpanExporter> exporter;
if (log_trace_output_file_.compare("") != 0)
exporter = std::unique_ptr<trace_sdk::SpanExporter>(new opentelemetry::exporter::trace::OStreamSpanExporter(*log_trace_output_file_handle_.get()));
} else {
exporter = std::unique_ptr<trace_sdk::SpanExporter>(new opentelemetry::exporter::trace::OStreamSpanExporter);
}
auto processor = std::unique_ptr<trace_sdk::SpanProcessor>(
new trace_sdk::SimpleSpanProcessor(std::move(exporter)));
auto provider = nostd::shared_ptr<opentelemetry::trace::TracerProvider>(
new trace_sdk::TracerProvider(std::move(processor), resources));
// Set the global trace provider
opentelemetry::trace::Provider::SetTracerProvider(provider);
// Set global propagator
context::propagation::GlobalTextMapPropagator::SetGlobalPropagator(
nostd::shared_ptr<context::propagation::TextMapPropagator>(
new opentelemetry::trace::propagation::HttpTraceContext()));
std::cout << "Simple (log stream) exporter successfully initialized!"
<< std::endl;
}