Skip to content

Commit aa4471d

Browse files
committed
Fix lifetime for sdk::ReadWriteLogRecord
1 parent 149d29c commit aa4471d

File tree

8 files changed

+403
-9
lines changed

8 files changed

+403
-9
lines changed

exporters/otlp/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,9 @@ if(BUILD_TESTING)
332332
else()
333333
find_library(GMOCK_LIB gmock PATH_SUFFIXES lib)
334334
endif()
335+
if(NOT GMOCK_LIB)
336+
unset(GMOCK_LIB CACHE)
337+
endif()
335338
endif()
336339

337340
if(WITH_OTLP_GRPC)

exporters/zipkin/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ if(BUILD_TESTING)
5959
else()
6060
find_library(GMOCK_LIB gmock PATH_SUFFIXES lib)
6161
endif()
62+
if(NOT GMOCK_LIB)
63+
unset(GMOCK_LIB CACHE)
64+
endif()
6265

6366
add_executable(zipkin_exporter_test test/zipkin_exporter_test.cc)
6467

sdk/include/opentelemetry/sdk/common/attribute_utils.h

Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <cstdint>
77
#include <initializer_list>
88
#include <map>
9+
#include <memory>
910
#include <string>
1011
#include <unordered_map>
1112
#include <utility>
@@ -49,6 +50,8 @@ using OwnedAttributeValue = nostd::variant<bool,
4950
std::vector<uint64_t>,
5051
std::vector<uint8_t>>;
5152

53+
using OwnedAttributeView = nostd::variant<std::vector<nostd::string_view>, std::unique_ptr<bool[]>>;
54+
5255
enum OwnedAttributeType
5356
{
5457
kTypeBool,
@@ -215,6 +218,248 @@ class OrderedAttributeMap : public std::map<std::string, OwnedAttributeValue>
215218
AttributeConverter converter_;
216219
};
217220

221+
/**
222+
* Class for storing attributes.
223+
*/
224+
struct MixedAttributeMapStorage
225+
{
226+
std::unordered_map<std::string, opentelemetry::common::AttributeValue> attributes;
227+
AttributeMap owened_attributes;
228+
std::unordered_map<std::string, OwnedAttributeView> owened_attributes_view;
229+
};
230+
231+
/**
232+
* Set an owned copy (OwnedAttributeValue) and attribute view of a non-owning AttributeValue.
233+
*/
234+
class MixedAttributeViewSetter
235+
{
236+
public:
237+
inline MixedAttributeViewSetter(const nostd::string_view &key,
238+
MixedAttributeMapStorage &storage,
239+
AttributeConverter &converter) noexcept
240+
: key_(&key), storage_(&storage), converter_(&converter)
241+
{}
242+
243+
void operator()(bool v)
244+
{
245+
storage_->owened_attributes[std::string(*key_)] = (*converter_)(v);
246+
storage_->attributes[std::string(*key_)] = v;
247+
}
248+
249+
void operator()(int32_t v)
250+
{
251+
storage_->owened_attributes[std::string(*key_)] = (*converter_)(v);
252+
storage_->attributes[std::string(*key_)] = v;
253+
}
254+
255+
void operator()(uint32_t v)
256+
{
257+
storage_->owened_attributes[std::string(*key_)] = (*converter_)(v);
258+
storage_->attributes[std::string(*key_)] = v;
259+
}
260+
261+
void operator()(int64_t v)
262+
{
263+
storage_->owened_attributes[std::string(*key_)] = (*converter_)(v);
264+
storage_->attributes[std::string(*key_)] = v;
265+
}
266+
267+
void operator()(uint64_t v)
268+
{
269+
storage_->owened_attributes[std::string(*key_)] = (*converter_)(v);
270+
storage_->attributes[std::string(*key_)] = v;
271+
}
272+
273+
void operator()(double v)
274+
{
275+
storage_->owened_attributes[std::string(*key_)] = (*converter_)(v);
276+
storage_->attributes[std::string(*key_)] = v;
277+
}
278+
279+
void operator()(nostd::string_view v)
280+
{
281+
auto &owned_value = storage_->owened_attributes[std::string(*key_)];
282+
owned_value = (*converter_)(v);
283+
storage_->attributes[std::string(*key_)] = nostd::get<std::string>(owned_value);
284+
}
285+
286+
void operator()(const char *v)
287+
{
288+
auto &owned_value = storage_->owened_attributes[std::string(*key_)];
289+
owned_value = (*converter_)(v);
290+
storage_->attributes[std::string(*key_)] = nostd::get<std::string>(owned_value).c_str();
291+
}
292+
293+
void operator()(nostd::span<const uint8_t> v)
294+
{
295+
auto &owned_value = storage_->owened_attributes[std::string(*key_)];
296+
owned_value = (*converter_)(v);
297+
storage_->attributes[std::string(*key_)] = nostd::get<std::vector<uint8_t>>(owned_value);
298+
}
299+
300+
void operator()(nostd::span<const bool> v)
301+
{
302+
storage_->owened_attributes[std::string(*key_)] = (*converter_)(v);
303+
if (v.empty())
304+
{
305+
storage_->attributes[std::string(*key_)] = nostd::span<const bool>{};
306+
}
307+
else
308+
{
309+
std::unique_ptr<bool[]> owned_view{new bool[v.size()]};
310+
for (size_t i = 0; i < v.size(); i++)
311+
{
312+
owned_view[i] = v[i];
313+
}
314+
315+
storage_->attributes[std::string(*key_)] =
316+
nostd::span<const bool>{owned_view.get(), v.size()};
317+
storage_->owened_attributes_view[std::string(*key_)] = std::move(owned_view);
318+
}
319+
}
320+
321+
void operator()(nostd::span<const int32_t> v)
322+
{
323+
auto &owned_value = storage_->owened_attributes[std::string(*key_)];
324+
owned_value = (*converter_)(v);
325+
storage_->attributes[std::string(*key_)] = nostd::get<std::vector<int32_t>>(owned_value);
326+
}
327+
328+
void operator()(nostd::span<const uint32_t> v)
329+
{
330+
auto &owned_value = storage_->owened_attributes[std::string(*key_)];
331+
owned_value = (*converter_)(v);
332+
storage_->attributes[std::string(*key_)] = nostd::get<std::vector<uint32_t>>(owned_value);
333+
}
334+
335+
void operator()(nostd::span<const int64_t> v)
336+
{
337+
auto &owned_value = storage_->owened_attributes[std::string(*key_)];
338+
owned_value = (*converter_)(v);
339+
storage_->attributes[std::string(*key_)] = nostd::get<std::vector<int64_t>>(owned_value);
340+
}
341+
342+
void operator()(nostd::span<const uint64_t> v)
343+
{
344+
auto &owned_value = storage_->owened_attributes[std::string(*key_)];
345+
owned_value = (*converter_)(v);
346+
storage_->attributes[std::string(*key_)] = nostd::get<std::vector<uint64_t>>(owned_value);
347+
}
348+
349+
void operator()(nostd::span<const double> v)
350+
{
351+
auto &owned_value = storage_->owened_attributes[std::string(*key_)];
352+
owned_value = (*converter_)(v);
353+
storage_->attributes[std::string(*key_)] = nostd::get<std::vector<double>>(owned_value);
354+
}
355+
356+
void operator()(nostd::span<const nostd::string_view> v)
357+
{
358+
auto &owned_value = storage_->owened_attributes[std::string(*key_)];
359+
owned_value = (*converter_)(v);
360+
361+
if (v.empty())
362+
{
363+
storage_->attributes[std::string(*key_)] = nostd::span<const nostd::string_view>{};
364+
}
365+
else
366+
{
367+
auto &owned_view = storage_->owened_attributes_view[std::string(*key_)];
368+
owned_view = std::vector<nostd::string_view>{};
369+
auto &owned_vector = nostd::get<std::vector<nostd::string_view>>(owned_view);
370+
371+
owned_vector.reserve(v.size());
372+
for (auto &data : nostd::get<std::vector<std::string>>(owned_value))
373+
{
374+
owned_vector.push_back(data);
375+
}
376+
377+
storage_->attributes[std::string(*key_)] =
378+
nostd::span<const nostd::string_view>{owned_vector.data(), owned_vector.size()};
379+
}
380+
}
381+
382+
private:
383+
const nostd::string_view *key_;
384+
MixedAttributeMapStorage *storage_;
385+
AttributeConverter *converter_;
386+
};
387+
388+
/**
389+
* Class for storing attributes and attribute view.
390+
*/
391+
class MixedAttributeMap
392+
{
393+
public:
394+
// Construct empty attribute map
395+
MixedAttributeMap() {}
396+
397+
// Construct attribute map and populate with attributes
398+
MixedAttributeMap(const opentelemetry::common::KeyValueIterable &attributes) : MixedAttributeMap()
399+
{
400+
attributes.ForEachKeyValue(
401+
[&](nostd::string_view key, opentelemetry::common::AttributeValue value) noexcept {
402+
nostd::visit(MixedAttributeViewSetter(key, storage_, converter_), value);
403+
return true;
404+
});
405+
}
406+
407+
// Construct attribute map and populate with optional attributes
408+
MixedAttributeMap(const opentelemetry::common::KeyValueIterable *attributes) : MixedAttributeMap()
409+
{
410+
if (attributes != nullptr)
411+
{
412+
attributes->ForEachKeyValue(
413+
[&](nostd::string_view key, opentelemetry::common::AttributeValue value) noexcept {
414+
nostd::visit(MixedAttributeViewSetter(key, storage_, converter_), value);
415+
return true;
416+
});
417+
}
418+
}
419+
420+
// Construct map from initializer list by applying `SetAttribute` transform for every attribute
421+
MixedAttributeMap(
422+
std::initializer_list<std::pair<nostd::string_view, opentelemetry::common::AttributeValue>>
423+
attributes)
424+
: MixedAttributeMap()
425+
{
426+
for (auto &kv : attributes)
427+
{
428+
nostd::visit(MixedAttributeViewSetter(kv.first, storage_, converter_), kv.second);
429+
}
430+
}
431+
432+
// Returns a reference to this map
433+
const std::unordered_map<std::string, opentelemetry::common::AttributeValue> &GetAttributes()
434+
const noexcept
435+
{
436+
return storage_.attributes;
437+
}
438+
439+
const AttributeMap &GetOwnedAttributes() const noexcept { return storage_.owened_attributes; }
440+
441+
// Convert non-owning key-value to owning std::string(key) and OwnedAttributeValue(value)
442+
void SetAttribute(nostd::string_view key,
443+
const opentelemetry::common::AttributeValue &value) noexcept
444+
{
445+
nostd::visit(MixedAttributeViewSetter(key, storage_, converter_), value);
446+
}
447+
448+
void Reserve(AttributeMap::size_type size)
449+
{
450+
storage_.attributes.reserve(size);
451+
storage_.owened_attributes.reserve(size);
452+
}
453+
454+
AttributeMap::size_type Size() const noexcept { return storage_.attributes.size(); }
455+
456+
bool Empty() const noexcept { return storage_.attributes.empty(); }
457+
458+
private:
459+
MixedAttributeMapStorage storage_;
460+
AttributeConverter converter_;
461+
};
462+
218463
} // namespace common
219464
} // namespace sdk
220465
OPENTELEMETRY_END_NAMESPACE

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,8 +187,9 @@ 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+
common::MixedAttributeMap attributes_map_;
191+
// We resue the same utility functions of MixedAttributeMap with key="" for the body field
192+
common::MixedAttributeMap body_;
192193
opentelemetry::common::SystemTimestamp timestamp_;
193194
opentelemetry::common::SystemTimestamp observed_timestamp_;
194195

sdk/src/logs/read_write_log_record.cc

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,12 @@ ReadWriteLogRecord::ReadWriteLogRecord()
2929
: severity_(opentelemetry::logs::Severity::kInvalid),
3030
resource_(nullptr),
3131
instrumentation_scope_(nullptr),
32-
body_(nostd::string_view()),
3332
observed_timestamp_(std::chrono::system_clock::now()),
3433
event_id_(0),
3534
event_name_("")
36-
{}
35+
{
36+
body_.SetAttribute("", nostd::string_view());
37+
}
3738

3839
ReadWriteLogRecord::~ReadWriteLogRecord() {}
3940

@@ -70,12 +71,12 @@ opentelemetry::logs::Severity ReadWriteLogRecord::GetSeverity() const noexcept
7071

7172
void ReadWriteLogRecord::SetBody(const opentelemetry::common::AttributeValue &message) noexcept
7273
{
73-
body_ = message;
74+
body_.SetAttribute("", message);
7475
}
7576

7677
const opentelemetry::common::AttributeValue &ReadWriteLogRecord::GetBody() const noexcept
7778
{
78-
return body_;
79+
return body_.GetAttributes().begin()->second;
7980
}
8081

8182
void ReadWriteLogRecord::SetEventId(int64_t id, nostd::string_view name) noexcept
@@ -160,13 +161,13 @@ const opentelemetry::trace::TraceFlags &ReadWriteLogRecord::GetTraceFlags() cons
160161
void ReadWriteLogRecord::SetAttribute(nostd::string_view key,
161162
const opentelemetry::common::AttributeValue &value) noexcept
162163
{
163-
attributes_map_[static_cast<std::string>(key)] = value;
164+
attributes_map_.SetAttribute(key, value);
164165
}
165166

166167
const std::unordered_map<std::string, opentelemetry::common::AttributeValue> &
167168
ReadWriteLogRecord::GetAttributes() const noexcept
168169
{
169-
return attributes_map_;
170+
return attributes_map_.GetAttributes();
170171
}
171172

172173
const opentelemetry::sdk::resource::Resource &ReadWriteLogRecord::GetResource() const noexcept

0 commit comments

Comments
 (0)