Skip to content

[EXPORTER] ostream log exporter, fix memory ownership issues #3417

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ Increment the:
* [CMAKE] Add generated protobuf headers to the opentelemetry_proto target
[#3400](https://github.com/open-telemetry/opentelemetry-cpp/pull/3400)

* [EXPORTER] ostream log exporter, fixed memory ownership issues
[#3417](https://github.com/open-telemetry/opentelemetry-cpp/pull/3417)

## [1.20 2025-04-01]

* [BUILD] Update opentelemetry-proto version
Expand Down
10 changes: 5 additions & 5 deletions sdk/include/opentelemetry/sdk/logs/read_write_log_record.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ class ReadWriteLogRecord final : public ReadableLogRecord
* Get body field of this log.
* @return the body field for this log.
*/
const opentelemetry::common::AttributeValue &GetBody() const noexcept override;
const opentelemetry::sdk::common::OwnedAttributeValue &GetBody() const noexcept override;

/**
* Set the Event Id object
Expand Down Expand Up @@ -151,8 +151,8 @@ class ReadWriteLogRecord final : public ReadableLogRecord
* Get attributes of this log.
* @return the body field of this log
*/
const std::unordered_map<std::string, opentelemetry::common::AttributeValue> &GetAttributes()
const noexcept override;
const std::unordered_map<std::string, opentelemetry::sdk::common::OwnedAttributeValue> &
GetAttributes() const noexcept override;

/**
* Get resource of this log
Expand Down Expand Up @@ -187,8 +187,8 @@ class ReadWriteLogRecord final : public ReadableLogRecord
const opentelemetry::sdk::resource::Resource *resource_;
const opentelemetry::sdk::instrumentationscope::InstrumentationScope *instrumentation_scope_;

std::unordered_map<std::string, opentelemetry::common::AttributeValue> attributes_map_;
opentelemetry::common::AttributeValue body_;
std::unordered_map<std::string, opentelemetry::sdk::common::OwnedAttributeValue> attributes_map_;
opentelemetry::sdk::common::OwnedAttributeValue body_;
opentelemetry::common::SystemTimestamp timestamp_;
opentelemetry::common::SystemTimestamp observed_timestamp_;

Expand Down
4 changes: 2 additions & 2 deletions sdk/include/opentelemetry/sdk/logs/readable_log_record.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ class ReadableLogRecord : public Recordable
* Get body field of this log.
* @return the body field for this log.
*/
virtual const opentelemetry::common::AttributeValue &GetBody() const noexcept = 0;
virtual const opentelemetry::sdk::common::OwnedAttributeValue &GetBody() const noexcept = 0;

/**
* Get the Event id.
Expand Down Expand Up @@ -111,7 +111,7 @@ class ReadableLogRecord : public Recordable
* Get attributes of this log.
* @return the body field of this log
*/
virtual const std::unordered_map<std::string, opentelemetry::common::AttributeValue> &
virtual const std::unordered_map<std::string, opentelemetry::sdk::common::OwnedAttributeValue> &
GetAttributes() const noexcept = 0;

/**
Expand Down
14 changes: 9 additions & 5 deletions sdk/src/logs/read_write_log_record.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "opentelemetry/logs/severity.h"
#include "opentelemetry/nostd/string_view.h"
#include "opentelemetry/nostd/variant.h"
#include "opentelemetry/sdk/common/attribute_utils.h"
#include "opentelemetry/sdk/instrumentationscope/instrumentation_scope.h"
#include "opentelemetry/sdk/logs/read_write_log_record.h"
#include "opentelemetry/sdk/resource/resource.h"
Expand All @@ -30,7 +31,7 @@ ReadWriteLogRecord::ReadWriteLogRecord()
: severity_(opentelemetry::logs::Severity::kInvalid),
resource_(nullptr),
instrumentation_scope_(nullptr),
body_(nostd::string_view()),
body_(std::string()),
observed_timestamp_(std::chrono::system_clock::now()),
event_id_(0),
event_name_("")
Expand Down Expand Up @@ -71,10 +72,11 @@ opentelemetry::logs::Severity ReadWriteLogRecord::GetSeverity() const noexcept

void ReadWriteLogRecord::SetBody(const opentelemetry::common::AttributeValue &message) noexcept
{
body_ = message;
opentelemetry::sdk::common::AttributeConverter converter;
body_ = nostd::visit(converter, message);
}

const opentelemetry::common::AttributeValue &ReadWriteLogRecord::GetBody() const noexcept
const opentelemetry::sdk::common::OwnedAttributeValue &ReadWriteLogRecord::GetBody() const noexcept
{
return body_;
}
Expand Down Expand Up @@ -161,10 +163,12 @@ const opentelemetry::trace::TraceFlags &ReadWriteLogRecord::GetTraceFlags() cons
void ReadWriteLogRecord::SetAttribute(nostd::string_view key,
const opentelemetry::common::AttributeValue &value) noexcept
{
attributes_map_[static_cast<std::string>(key)] = value;
std::string safe_key(key);
opentelemetry::sdk::common::AttributeConverter converter;
attributes_map_[safe_key] = nostd::visit(converter, value);
}

const std::unordered_map<std::string, opentelemetry::common::AttributeValue> &
const std::unordered_map<std::string, opentelemetry::sdk::common::OwnedAttributeValue> &
ReadWriteLogRecord::GetAttributes() const noexcept
{
return attributes_map_;
Expand Down
77 changes: 32 additions & 45 deletions sdk/test/logs/log_record_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>

#include "opentelemetry/common/attribute_value.h"
#include "opentelemetry/common/key_value_iterable.h"
#include "opentelemetry/common/timestamp.h"
#include "opentelemetry/logs/log_record.h"
Expand All @@ -22,6 +22,7 @@
#include "opentelemetry/nostd/string_view.h"
#include "opentelemetry/nostd/unique_ptr.h"
#include "opentelemetry/nostd/variant.h"
#include "opentelemetry/sdk/common/attribute_utils.h"
#include "opentelemetry/sdk/logs/read_write_log_record.h"
#include "opentelemetry/sdk/resource/resource.h"
#include "opentelemetry/trace/span_id.h"
Expand Down Expand Up @@ -72,13 +73,9 @@ TEST(ReadWriteLogRecord, SetAndGet)

// Test that all fields match what was set
ASSERT_EQ(record.GetSeverity(), logs_api::Severity::kInvalid);
if (nostd::holds_alternative<const char *>(record.GetBody()))
if (nostd::holds_alternative<std::string>(record.GetBody()))
{
ASSERT_EQ(std::string(nostd::get<const char *>(record.GetBody())), "Message");
}
else if (nostd::holds_alternative<nostd::string_view>(record.GetBody()))
{
ASSERT_TRUE(nostd::get<nostd::string_view>(record.GetBody()) == "Message");
ASSERT_EQ(std::string(nostd::get<std::string>(record.GetBody())), "Message");
}
ASSERT_TRUE(nostd::get<bool>(record.GetResource().GetAttributes().at("res1")));
ASSERT_EQ(nostd::get<int64_t>(record.GetAttributes().at("attr1")), 314159);
Expand Down Expand Up @@ -109,13 +106,13 @@ class TestBodyLogger : public opentelemetry::logs::Logger
}
}

const opentelemetry::common::AttributeValue &GetLastLogRecord() const noexcept
const opentelemetry::sdk::common::OwnedAttributeValue &GetLastLogRecord() const noexcept
{
return last_body_;
}

private:
opentelemetry::common::AttributeValue last_body_;
opentelemetry::sdk::common::OwnedAttributeValue last_body_;
};

// Define a basic LoggerProvider class that returns an instance of the logger class defined above
Expand Down Expand Up @@ -173,28 +170,19 @@ TEST(LogBody, BodyConversation)

real_logger->EmitLogRecord(opentelemetry::logs::Severity::kInfo, "128");
ASSERT_TRUE(
opentelemetry::nostd::holds_alternative<const char *>(real_logger->GetLastLogRecord()) ||
opentelemetry::nostd::holds_alternative<nostd::string_view>(real_logger->GetLastLogRecord()));
if (opentelemetry::nostd::holds_alternative<const char *>(real_logger->GetLastLogRecord()))
{
ASSERT_EQ(nostd::string_view{"128"},
opentelemetry::nostd::get<const char *>(real_logger->GetLastLogRecord()));
}
else
{
ASSERT_EQ(nostd::string_view{"128"},
opentelemetry::nostd::get<nostd::string_view>(real_logger->GetLastLogRecord()));
}
opentelemetry::nostd::holds_alternative<std::string>(real_logger->GetLastLogRecord()));
ASSERT_EQ(nostd::string_view{"128"},
opentelemetry::nostd::get<std::string>(real_logger->GetLastLogRecord()));

{
bool data[] = {true, false, true};
nostd::span<const bool> data_span = data;
real_logger->EmitLogRecord(opentelemetry::logs::Severity::kInfo, data_span);
ASSERT_TRUE(opentelemetry::nostd::holds_alternative<nostd::span<const bool>>(
ASSERT_TRUE(opentelemetry::nostd::holds_alternative<std::vector<bool>>(
real_logger->GetLastLogRecord()));

nostd::span<const bool> output =
opentelemetry::nostd::get<nostd::span<const bool>>(real_logger->GetLastLogRecord());
std::vector<bool> output =
opentelemetry::nostd::get<std::vector<bool>>(real_logger->GetLastLogRecord());

ASSERT_EQ(data_span.size(), output.size());

Expand All @@ -208,11 +196,11 @@ TEST(LogBody, BodyConversation)
int32_t data[] = {221, 222, 223};
nostd::span<const int32_t> data_span = data;
real_logger->EmitLogRecord(opentelemetry::logs::Severity::kInfo, data_span);
ASSERT_TRUE(opentelemetry::nostd::holds_alternative<nostd::span<const int32_t>>(
ASSERT_TRUE(opentelemetry::nostd::holds_alternative<std::vector<int32_t>>(
real_logger->GetLastLogRecord()));

nostd::span<const int32_t> output =
opentelemetry::nostd::get<nostd::span<const int32_t>>(real_logger->GetLastLogRecord());
opentelemetry::nostd::get<std::vector<int32_t>>(real_logger->GetLastLogRecord());

ASSERT_EQ(data_span.size(), output.size());

Expand All @@ -226,11 +214,11 @@ TEST(LogBody, BodyConversation)
uint32_t data[] = {231, 232, 233};
nostd::span<const uint32_t> data_span = data;
real_logger->EmitLogRecord(opentelemetry::logs::Severity::kInfo, data_span);
ASSERT_TRUE(opentelemetry::nostd::holds_alternative<nostd::span<const uint32_t>>(
ASSERT_TRUE(opentelemetry::nostd::holds_alternative<std::vector<uint32_t>>(
real_logger->GetLastLogRecord()));

nostd::span<const uint32_t> output =
opentelemetry::nostd::get<nostd::span<const uint32_t>>(real_logger->GetLastLogRecord());
std::vector<uint32_t> output =
opentelemetry::nostd::get<std::vector<uint32_t>>(real_logger->GetLastLogRecord());

ASSERT_EQ(data_span.size(), output.size());

Expand All @@ -244,11 +232,11 @@ TEST(LogBody, BodyConversation)
int64_t data[] = {241, 242, 243};
nostd::span<const int64_t> data_span = data;
real_logger->EmitLogRecord(opentelemetry::logs::Severity::kInfo, data_span);
ASSERT_TRUE(opentelemetry::nostd::holds_alternative<nostd::span<const int64_t>>(
ASSERT_TRUE(opentelemetry::nostd::holds_alternative<std::vector<int64_t>>(
real_logger->GetLastLogRecord()));

nostd::span<const int64_t> output =
opentelemetry::nostd::get<nostd::span<const int64_t>>(real_logger->GetLastLogRecord());
std::vector<int64_t> output =
opentelemetry::nostd::get<std::vector<int64_t>>(real_logger->GetLastLogRecord());

ASSERT_EQ(data_span.size(), output.size());

Expand All @@ -262,11 +250,11 @@ TEST(LogBody, BodyConversation)
uint64_t data[] = {251, 252, 253};
nostd::span<const uint64_t> data_span = data;
real_logger->EmitLogRecord(opentelemetry::logs::Severity::kInfo, data_span);
ASSERT_TRUE(opentelemetry::nostd::holds_alternative<nostd::span<const uint64_t>>(
ASSERT_TRUE(opentelemetry::nostd::holds_alternative<std::vector<uint64_t>>(
real_logger->GetLastLogRecord()));

nostd::span<const uint64_t> output =
opentelemetry::nostd::get<nostd::span<const uint64_t>>(real_logger->GetLastLogRecord());
std::vector<uint64_t> output =
opentelemetry::nostd::get<std::vector<uint64_t>>(real_logger->GetLastLogRecord());

ASSERT_EQ(data_span.size(), output.size());

Expand All @@ -280,11 +268,11 @@ TEST(LogBody, BodyConversation)
uint8_t data[] = {161, 162, 163};
nostd::span<const uint8_t> data_span = data;
real_logger->EmitLogRecord(opentelemetry::logs::Severity::kInfo, data_span);
ASSERT_TRUE(opentelemetry::nostd::holds_alternative<nostd::span<const uint8_t>>(
ASSERT_TRUE(opentelemetry::nostd::holds_alternative<std::vector<uint8_t>>(
real_logger->GetLastLogRecord()));

nostd::span<const uint8_t> output =
opentelemetry::nostd::get<nostd::span<const uint8_t>>(real_logger->GetLastLogRecord());
std::vector<uint8_t> output =
opentelemetry::nostd::get<std::vector<uint8_t>>(real_logger->GetLastLogRecord());

ASSERT_EQ(data_span.size(), output.size());

Expand All @@ -298,11 +286,11 @@ TEST(LogBody, BodyConversation)
double data[] = {271.0, 272.0, 273.0};
nostd::span<const double> data_span = data;
real_logger->EmitLogRecord(opentelemetry::logs::Severity::kInfo, data_span);
ASSERT_TRUE(opentelemetry::nostd::holds_alternative<nostd::span<const double>>(
ASSERT_TRUE(opentelemetry::nostd::holds_alternative<std::vector<double>>(
real_logger->GetLastLogRecord()));

nostd::span<const double> output =
opentelemetry::nostd::get<nostd::span<const double>>(real_logger->GetLastLogRecord());
std::vector<double> output =
opentelemetry::nostd::get<std::vector<double>>(real_logger->GetLastLogRecord());

ASSERT_EQ(data_span.size(), output.size());

Expand All @@ -317,12 +305,11 @@ TEST(LogBody, BodyConversation)
nostd::string_view data[] = {data_origin[0], data_origin[1], data_origin[2]};
nostd::span<const nostd::string_view> data_span = data;
real_logger->EmitLogRecord(opentelemetry::logs::Severity::kInfo, data_span);
ASSERT_TRUE(opentelemetry::nostd::holds_alternative<nostd::span<const nostd::string_view>>(
ASSERT_TRUE(opentelemetry::nostd::holds_alternative<std::vector<std::string>>(
real_logger->GetLastLogRecord()));

nostd::span<const nostd::string_view> output =
opentelemetry::nostd::get<nostd::span<const nostd::string_view>>(
real_logger->GetLastLogRecord());
std::vector<std::string> output =
opentelemetry::nostd::get<std::vector<std::string>>(real_logger->GetLastLogRecord());

ASSERT_EQ(data_span.size(), output.size());

Expand Down
Loading