Zebra Codes

OpenTelemetry Null Span Exporter

24th of August, 2023

The OpenTelemetry C++ implementation ships with several exporters for outputting your recorded traces: ostream, HTTP, gRPC, and more. It does not, however, provide a null implementation.

A null exporter is useful in test environments, where you just want to discard instrumentation data. The simple class below provides an implementation of a null span exporter.

#ifndef INCLUDED_NULLSPANEXPORTER_510E043774634B3883865AE2BD56BDBD
#define INCLUDED_NULLSPANEXPORTER_510E043774634B3883865AE2BD56BDBD

#include "opentelemetry/sdk/trace/exporter.h"
#include "opentelemetry/sdk/trace/span_data.h"
#include <chrono>
#include <memory>

/**
 * @brief A null exporter to discard telemetry traces during unit tests.
 */
class NullSpanExporter : public opentelemetry::sdk::trace::SpanExporter
{
    /**
     * Create a span recordable.
     *
     * @return Returns a newly initialized Recordable object.
     */
    virtual std::unique_ptr<opentelemetry::sdk::trace::Recordable> MakeRecordable() noexcept override
    {
        return std::make_unique<opentelemetry::sdk::trace::SpanData>();
    }

    /**
     * Exports a batch of span recordables.
     *
     * @param spans Returns a span of unique pointers to span recordables.
     */
    virtual opentelemetry::sdk::common::ExportResult Export(const opentelemetry::nostd::span<std::unique_ptr<opentelemetry::sdk::trace::Recordable>>& spans) noexcept override
    {
        (void)spans;
        return opentelemetry::sdk::common::ExportResult::kSuccess;
    }

    /**
     * Shut down the exporter.
     *
     * @param timeout An optional timeout.
     *
     * @return Returns the status of the operation.
     */
    virtual bool Shutdown(std::chrono::microseconds timeout = std::chrono::microseconds::max()) noexcept override
    {
        (void)timeout;
        return true;
    }
};

#endif

To use this exporter, simply create a NullSpanExporter instead of whatever exporter you are currently using:

#include "NullSpanExporter.h"

#include "opentelemetry/context/runtime_context.h"
#include "opentelemetry/sdk/trace/exporter.h"
#include "opentelemetry/sdk/trace/processor.h"
#include "opentelemetry/sdk/trace/simple_processor_factory.h"
#include "opentelemetry/sdk/trace/tracer_provider_factory.h"
#include "opentelemetry/trace/provider.h"

using opentelemetry::context::RuntimeContext;
using opentelemetry::context::Token;
using opentelemetry::sdk::trace::SimpleSpanProcessorFactory;
using opentelemetry::sdk::trace::TracerProviderFactory;
using opentelemetry::trace::Provider;
using opentelemetry::trace::TracerProvider;

#include <memory>

void initializeTracing()
{
    // Create a null exporter that discards traces.
    auto exporter = std::make_unique<NullSpanExporter>();

    // Processing done on the span prior to exporting.
    auto processor = SimpleSpanProcessorFactory::Create(std::move(exporter));

    // Create the TracerProvider, which is is a factory to create the Tracer.
    std::shared_ptr<TracerProvider> provider = TracerProviderFactory::Create(std::move(processor));

    // Set the global trace provider.
    Provider::SetTracerProvider(provider);

    // Create the tracer.
    tracer = provider->GetTracer("price-worker");
}