// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include #include #include #include #include #if ZEN_WITH_OTEL namespace zen::logging { /** * OTLP/HTTP sink for spdlog * * Sends log messages and traces to an OpenTelemetry collector via OTLP over HTTP */ class OtelHttpProtobufSink : public spdlog::sinks::sink { public: // Note that this URI should be the base URI of the OTLP HTTP endpoint, e.g. // "http://otel-collector:4318" OtelHttpProtobufSink(const std::string_view& Uri); ~OtelHttpProtobufSink(); OtelHttpProtobufSink(const OtelHttpProtobufSink&) = delete; OtelHttpProtobufSink& operator=(const OtelHttpProtobufSink&) = delete; private: virtual void log(const spdlog::details::log_msg& Msg) override; virtual void flush() override; virtual void set_pattern(const std::string& pattern) override { ZEN_UNUSED(pattern); } virtual void set_formatter(std::unique_ptr sink_formatter) override { ZEN_UNUSED(sink_formatter); } void RecordSpans(zen::otel::TraceId Trace, std::span Spans); // This is just a thin wrapper to call back into the sink while participating in // reference counting from the OTEL trace back-end class TraceRecorder : public zen::otel::TraceRecorder { public: TraceRecorder(OtelHttpProtobufSink* InSink) : m_Sink(InSink) {} private: TraceRecorder(const TraceRecorder&) = delete; TraceRecorder& operator=(const TraceRecorder&) = delete; virtual void RecordSpans(zen::otel::TraceId Trace, std::span Spans) override; OtelHttpProtobufSink* m_Sink; }; HttpClient m_OtelHttp; OtlpEncoder m_Encoder; Ref m_TraceRecorder; }; } // namespace zen::logging #endif