Skip to content

Commit b4254a4

Browse files
authored
[EXPORTER] ostream log exporter, fix memory ownership issues (#3417)
1 parent f7babf1 commit b4254a4

File tree

5 files changed

+70
-57
lines changed

5 files changed

+70
-57
lines changed

CHANGELOG.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,28 @@ Increment the:
6161
* [SEMANTIC CONVENTIONS] Upgrade to semantic conventions 1.34.0
6262
[#3428](https://github.com/open-telemetry/opentelemetry-cpp/pull/3428)
6363

64+
* [EXPORTER] ostream log exporter, fixed memory ownership issues
65+
[#3417](https://github.com/open-telemetry/opentelemetry-cpp/pull/3417)
66+
67+
Important changes:
68+
69+
* [EXPORTER] ostream log exporter, fixed memory ownership issues
70+
[#3417](https://github.com/open-telemetry/opentelemetry-cpp/pull/3417)
71+
72+
* In the SDK, the following classes implementation has changed:
73+
74+
* opentelemetry::sdk::logs::ReadableLogRecord
75+
* opentelemetry::sdk::logs::ReadWriteLogRecord
76+
77+
* An application implementing a custom log record exporter,
78+
that reuses these classes from the opentelemetry-cpp SDK,
79+
will need code adjustments, in particular for methods:
80+
81+
* GetBody()
82+
* GetAttributes()
83+
84+
* Applications not using these SDK classes directly are not affected.
85+
6486
## [1.20 2025-04-01]
6587

6688
* [BUILD] Update opentelemetry-proto version

sdk/include/opentelemetry/sdk/logs/read_write_log_record.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ class ReadWriteLogRecord final : public ReadableLogRecord
8282
* Get body field of this log.
8383
* @return the body field for this log.
8484
*/
85-
const opentelemetry::common::AttributeValue &GetBody() const noexcept override;
85+
const opentelemetry::sdk::common::OwnedAttributeValue &GetBody() const noexcept override;
8686

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

157157
/**
158158
* Get resource of this log
@@ -187,8 +187,8 @@ class ReadWriteLogRecord final : public ReadableLogRecord
187187
const opentelemetry::sdk::resource::Resource *resource_;
188188
const opentelemetry::sdk::instrumentationscope::InstrumentationScope *instrumentation_scope_;
189189

190-
std::unordered_map<std::string, opentelemetry::common::AttributeValue> attributes_map_;
191-
opentelemetry::common::AttributeValue body_;
190+
std::unordered_map<std::string, opentelemetry::sdk::common::OwnedAttributeValue> attributes_map_;
191+
opentelemetry::sdk::common::OwnedAttributeValue body_;
192192
opentelemetry::common::SystemTimestamp timestamp_;
193193
opentelemetry::common::SystemTimestamp observed_timestamp_;
194194

sdk/include/opentelemetry/sdk/logs/readable_log_record.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ class ReadableLogRecord : public Recordable
7575
* Get body field of this log.
7676
* @return the body field for this log.
7777
*/
78-
virtual const opentelemetry::common::AttributeValue &GetBody() const noexcept = 0;
78+
virtual const opentelemetry::sdk::common::OwnedAttributeValue &GetBody() const noexcept = 0;
7979

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

117117
/**

sdk/src/logs/read_write_log_record.cc

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "opentelemetry/logs/severity.h"
1313
#include "opentelemetry/nostd/string_view.h"
1414
#include "opentelemetry/nostd/variant.h"
15+
#include "opentelemetry/sdk/common/attribute_utils.h"
1516
#include "opentelemetry/sdk/instrumentationscope/instrumentation_scope.h"
1617
#include "opentelemetry/sdk/logs/read_write_log_record.h"
1718
#include "opentelemetry/sdk/resource/resource.h"
@@ -30,7 +31,7 @@ ReadWriteLogRecord::ReadWriteLogRecord()
3031
: severity_(opentelemetry::logs::Severity::kInvalid),
3132
resource_(nullptr),
3233
instrumentation_scope_(nullptr),
33-
body_(nostd::string_view()),
34+
body_(std::string()),
3435
observed_timestamp_(std::chrono::system_clock::now()),
3536
event_id_(0),
3637
event_name_("")
@@ -71,10 +72,11 @@ opentelemetry::logs::Severity ReadWriteLogRecord::GetSeverity() const noexcept
7172

7273
void ReadWriteLogRecord::SetBody(const opentelemetry::common::AttributeValue &message) noexcept
7374
{
74-
body_ = message;
75+
opentelemetry::sdk::common::AttributeConverter converter;
76+
body_ = nostd::visit(converter, message);
7577
}
7678

77-
const opentelemetry::common::AttributeValue &ReadWriteLogRecord::GetBody() const noexcept
79+
const opentelemetry::sdk::common::OwnedAttributeValue &ReadWriteLogRecord::GetBody() const noexcept
7880
{
7981
return body_;
8082
}
@@ -161,10 +163,12 @@ const opentelemetry::trace::TraceFlags &ReadWriteLogRecord::GetTraceFlags() cons
161163
void ReadWriteLogRecord::SetAttribute(nostd::string_view key,
162164
const opentelemetry::common::AttributeValue &value) noexcept
163165
{
164-
attributes_map_[static_cast<std::string>(key)] = value;
166+
std::string safe_key(key);
167+
opentelemetry::sdk::common::AttributeConverter converter;
168+
attributes_map_[safe_key] = nostd::visit(converter, value);
165169
}
166170

167-
const std::unordered_map<std::string, opentelemetry::common::AttributeValue> &
171+
const std::unordered_map<std::string, opentelemetry::sdk::common::OwnedAttributeValue> &
168172
ReadWriteLogRecord::GetAttributes() const noexcept
169173
{
170174
return attributes_map_;

sdk/test/logs/log_record_test.cc

Lines changed: 32 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
#include <string>
1010
#include <unordered_map>
1111
#include <utility>
12+
#include <vector>
1213

13-
#include "opentelemetry/common/attribute_value.h"
1414
#include "opentelemetry/common/key_value_iterable.h"
1515
#include "opentelemetry/common/timestamp.h"
1616
#include "opentelemetry/logs/log_record.h"
@@ -22,6 +22,7 @@
2222
#include "opentelemetry/nostd/string_view.h"
2323
#include "opentelemetry/nostd/unique_ptr.h"
2424
#include "opentelemetry/nostd/variant.h"
25+
#include "opentelemetry/sdk/common/attribute_utils.h"
2526
#include "opentelemetry/sdk/logs/read_write_log_record.h"
2627
#include "opentelemetry/sdk/resource/resource.h"
2728
#include "opentelemetry/trace/span_id.h"
@@ -72,13 +73,9 @@ TEST(ReadWriteLogRecord, SetAndGet)
7273

7374
// Test that all fields match what was set
7475
ASSERT_EQ(record.GetSeverity(), logs_api::Severity::kInvalid);
75-
if (nostd::holds_alternative<const char *>(record.GetBody()))
76+
if (nostd::holds_alternative<std::string>(record.GetBody()))
7677
{
77-
ASSERT_EQ(std::string(nostd::get<const char *>(record.GetBody())), "Message");
78-
}
79-
else if (nostd::holds_alternative<nostd::string_view>(record.GetBody()))
80-
{
81-
ASSERT_TRUE(nostd::get<nostd::string_view>(record.GetBody()) == "Message");
78+
ASSERT_EQ(std::string(nostd::get<std::string>(record.GetBody())), "Message");
8279
}
8380
ASSERT_TRUE(nostd::get<bool>(record.GetResource().GetAttributes().at("res1")));
8481
ASSERT_EQ(nostd::get<int64_t>(record.GetAttributes().at("attr1")), 314159);
@@ -109,13 +106,13 @@ class TestBodyLogger : public opentelemetry::logs::Logger
109106
}
110107
}
111108

112-
const opentelemetry::common::AttributeValue &GetLastLogRecord() const noexcept
109+
const opentelemetry::sdk::common::OwnedAttributeValue &GetLastLogRecord() const noexcept
113110
{
114111
return last_body_;
115112
}
116113

117114
private:
118-
opentelemetry::common::AttributeValue last_body_;
115+
opentelemetry::sdk::common::OwnedAttributeValue last_body_;
119116
};
120117

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

174171
real_logger->EmitLogRecord(opentelemetry::logs::Severity::kInfo, "128");
175172
ASSERT_TRUE(
176-
opentelemetry::nostd::holds_alternative<const char *>(real_logger->GetLastLogRecord()) ||
177-
opentelemetry::nostd::holds_alternative<nostd::string_view>(real_logger->GetLastLogRecord()));
178-
if (opentelemetry::nostd::holds_alternative<const char *>(real_logger->GetLastLogRecord()))
179-
{
180-
ASSERT_EQ(nostd::string_view{"128"},
181-
opentelemetry::nostd::get<const char *>(real_logger->GetLastLogRecord()));
182-
}
183-
else
184-
{
185-
ASSERT_EQ(nostd::string_view{"128"},
186-
opentelemetry::nostd::get<nostd::string_view>(real_logger->GetLastLogRecord()));
187-
}
173+
opentelemetry::nostd::holds_alternative<std::string>(real_logger->GetLastLogRecord()));
174+
ASSERT_EQ(nostd::string_view{"128"},
175+
opentelemetry::nostd::get<std::string>(real_logger->GetLastLogRecord()));
188176

189177
{
190178
bool data[] = {true, false, true};
191179
nostd::span<const bool> data_span = data;
192180
real_logger->EmitLogRecord(opentelemetry::logs::Severity::kInfo, data_span);
193-
ASSERT_TRUE(opentelemetry::nostd::holds_alternative<nostd::span<const bool>>(
181+
ASSERT_TRUE(opentelemetry::nostd::holds_alternative<std::vector<bool>>(
194182
real_logger->GetLastLogRecord()));
195183

196-
nostd::span<const bool> output =
197-
opentelemetry::nostd::get<nostd::span<const bool>>(real_logger->GetLastLogRecord());
184+
std::vector<bool> output =
185+
opentelemetry::nostd::get<std::vector<bool>>(real_logger->GetLastLogRecord());
198186

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

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

214202
nostd::span<const int32_t> output =
215-
opentelemetry::nostd::get<nostd::span<const int32_t>>(real_logger->GetLastLogRecord());
203+
opentelemetry::nostd::get<std::vector<int32_t>>(real_logger->GetLastLogRecord());
216204

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

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

232-
nostd::span<const uint32_t> output =
233-
opentelemetry::nostd::get<nostd::span<const uint32_t>>(real_logger->GetLastLogRecord());
220+
std::vector<uint32_t> output =
221+
opentelemetry::nostd::get<std::vector<uint32_t>>(real_logger->GetLastLogRecord());
234222

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

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

250-
nostd::span<const int64_t> output =
251-
opentelemetry::nostd::get<nostd::span<const int64_t>>(real_logger->GetLastLogRecord());
238+
std::vector<int64_t> output =
239+
opentelemetry::nostd::get<std::vector<int64_t>>(real_logger->GetLastLogRecord());
252240

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

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

268-
nostd::span<const uint64_t> output =
269-
opentelemetry::nostd::get<nostd::span<const uint64_t>>(real_logger->GetLastLogRecord());
256+
std::vector<uint64_t> output =
257+
opentelemetry::nostd::get<std::vector<uint64_t>>(real_logger->GetLastLogRecord());
270258

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

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

286-
nostd::span<const uint8_t> output =
287-
opentelemetry::nostd::get<nostd::span<const uint8_t>>(real_logger->GetLastLogRecord());
274+
std::vector<uint8_t> output =
275+
opentelemetry::nostd::get<std::vector<uint8_t>>(real_logger->GetLastLogRecord());
288276

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

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

304-
nostd::span<const double> output =
305-
opentelemetry::nostd::get<nostd::span<const double>>(real_logger->GetLastLogRecord());
292+
std::vector<double> output =
293+
opentelemetry::nostd::get<std::vector<double>>(real_logger->GetLastLogRecord());
306294

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

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

323-
nostd::span<const nostd::string_view> output =
324-
opentelemetry::nostd::get<nostd::span<const nostd::string_view>>(
325-
real_logger->GetLastLogRecord());
311+
std::vector<std::string> output =
312+
opentelemetry::nostd::get<std::vector<std::string>>(real_logger->GetLastLogRecord());
326313

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

0 commit comments

Comments
 (0)