Skip to content

In file client, allow mitigate between kJson and kBinary. #3224

@dev-ninja-ops

Description

@dev-ninja-ops

Why?:

As of right now it is only possible to dump the message directly to a jsonl file, add ability to mitigate between json to raw binary proto.

Benefits of This Change:

Improved Performance: Writing raw Protobuf is faster than converting to JSON, especially for large messages.
Protobuf Compatibility: The output is directly compatible with other systems or tools expecting Protobuf binary data.
Reduced Overhead: Avoid the extra JSON conversion step and associated dependencies.

Is your feature request related to a problem?
No.

Describe the solution you'd like
In otlp_file_exporter_options.h add OtlpFileFormat definition and modify OtlpFileClientOptions to include the format(Default to JSON):

// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

#pragma once

#include "opentelemetry/version.h"
#include "opentelemetry/exporters/otlp/otlp_file_client_options.h"

OPENTELEMETRY_BEGIN_NAMESPACE
namespace exporter
{
namespace otlp
{

/**
 * Enum to specify the output format for OTLP File traces exporter.
 */
enum class OtlpFileFormat
{
  kJson,    ///< Output as JSON (default)
  kBinary   ///< Output as raw Protobuf binary
};

/**
 * Struct to hold OTLP File traces exporter options.
 *
 * See
 * https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/file-exporter.md
 */
struct OPENTELEMETRY_EXPORT OtlpFileExporterOptions : public OtlpFileClientOptions
{
  OtlpFileFormat file_format = OtlpFileFormat::kJson; ///< Output format for the exporter

  OtlpFileExporterOptions();
  ~OtlpFileExporterOptions();
};

}  // namespace otlp
}  // namespace exporter
OPENTELEMETRY_END_NAMESPACE

in otlp_file_client.cc modify OtlpFileClient::Export so that the Export method respect the chosen format:

opentelemetry::sdk::common::ExportResult OtlpFileClient::Export(
    const google::protobuf::Message &message,
    std::size_t record_count) noexcept
{
    if (is_shutdown_)
    {
        return ::opentelemetry::sdk::common::ExportResult::kFailure;
    }

    if (backend_)
    {
        std::string output_data;

        if (options_.file_format == OtlpFileFormat::kJson)
        {
            // Convert to JSON
            nlohmann::json json_request;
            ConvertGenericMessageToJson(json_request, message);
            output_data = json_request.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace);
            output_data += '\n'; // Ensure a newline for JSONL format
        }
        else if (options_.file_format == OtlpFileFormat::kBinary)
        {
            // Serialize to binary
            if (!message.SerializeToString(&output_data))
            {
                OTEL_INTERNAL_LOG_ERROR("[OTLP FILE Client] Failed to serialize message to binary.");
                return ::opentelemetry::sdk::common::ExportResult::kFailure;
            }
        }

        if (options_.console_debug)
        {
            if (options_.file_format == OtlpFileFormat::kJson)
            {
                OTEL_INTERNAL_LOG_DEBUG("[OTLP FILE Client] Write body(Json): " << output_data);
            }
            else
            {
                OTEL_INTERNAL_LOG_DEBUG("[OTLP FILE Client] Write body(Binary), size: " << output_data.size());
            }
        }

        backend_->Export(output_data, record_count);
        return ::opentelemetry::sdk::common::ExportResult::kSuccess;
    }

    return ::opentelemetry::sdk::common::ExportResult::kFailure;
}

Usage:

When creating the OtlpFileExporterOptions, specify the desired format:

opentelemetry::exporter::otlp::OtlpFileExporterOptions exporter_options;
exporter_options.file_format = opentelemetry::exporter::otlp::OtlpFileFormat::kBinary;

or for JSON:

exporter_options.file_format = opentelemetry::exporter::otlp::OtlpFileFormat::kJson;

Describe alternatives you've considered
Patch otel's cpp source code, I don't really want to do that for obvious reasons...

Additional context
None..

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions