11// Copyright The OpenTelemetry Authors
22// SPDX-License-Identifier: Apache-2.0
33
4+ #include < chrono>
5+ #include < ctime>
6+ #include < nlohmann/json.hpp>
7+ #include < string>
8+
49#include " opentelemetry/exporters/elasticsearch/es_log_recordable.h"
510#include " opentelemetry/logs/severity.h"
11+ #include " opentelemetry/nostd/variant.h"
612#include " opentelemetry/sdk/instrumentationscope/instrumentation_scope.h"
713#include " opentelemetry/sdk/resource/resource.h"
814#include " opentelemetry/trace/span_id.h"
915#include " opentelemetry/trace/trace_flags.h"
1016#include " opentelemetry/trace/trace_id.h"
1117
18+ namespace nlohmann
19+ {
20+ template <>
21+ struct adl_serializer <opentelemetry::sdk::common::OwnedAttributeValue>
22+ {
23+ static void to_json (json &j, const opentelemetry::sdk::common::OwnedAttributeValue &v)
24+ {
25+ opentelemetry::nostd::visit ([&j](const auto &value) { j = value; }, v);
26+ }
27+ };
28+
29+ template <>
30+ struct adl_serializer <opentelemetry::common::AttributeValue>
31+ {
32+ static void to_json (json &j, const opentelemetry::common::AttributeValue &v)
33+ {
34+ opentelemetry::nostd::visit ([&j](const auto &value) { j = value; }, v);
35+ }
36+ };
37+ } // namespace nlohmann
38+
1239OPENTELEMETRY_BEGIN_NAMESPACE
1340namespace exporter
1441{
@@ -18,146 +45,13 @@ void ElasticSearchRecordable::WriteValue(
1845 const opentelemetry::sdk::common::OwnedAttributeValue &value,
1946 const std::string &name)
2047{
21- namespace common = opentelemetry::sdk::common;
22- switch (value.index ())
23- {
24- case common::kTypeBool :
25- json_[name] = opentelemetry::nostd::get<bool >(value) ? true : false ;
26- return ;
27- case common::kTypeInt :
28- json_[name] = opentelemetry::nostd::get<int >(value);
29- return ;
30- case common::kTypeInt64 :
31- json_[name] = opentelemetry::nostd::get<int64_t >(value);
32- return ;
33- case common::kTypeUInt :
34- json_[name] = opentelemetry::nostd::get<unsigned int >(value);
35- return ;
36- case common::kTypeUInt64 :
37- json_[name] = opentelemetry::nostd::get<uint64_t >(value);
38- return ;
39- case common::kTypeDouble :
40- json_[name] = opentelemetry::nostd::get<double >(value);
41- return ;
42- case common::kTypeString :
43- json_[name] = opentelemetry::nostd::get<std::string>(value).data ();
44- return ;
45- default :
46- return ;
47- }
48+ json_[name] = value;
4849}
4950
5051void ElasticSearchRecordable::WriteValue (const opentelemetry::common::AttributeValue &value,
5152 const std::string &name)
5253{
53-
54- // Assert size of variant to ensure that this method gets updated if the variant
55- // definition changes
56-
57- if (nostd::holds_alternative<bool >(value))
58- {
59- json_[name] = opentelemetry::nostd::get<bool >(value) ? true : false ;
60- }
61- else if (nostd::holds_alternative<int >(value))
62- {
63- json_[name] = opentelemetry::nostd::get<int >(value);
64- }
65- else if (nostd::holds_alternative<int64_t >(value))
66- {
67- json_[name] = opentelemetry::nostd::get<int64_t >(value);
68- }
69- else if (nostd::holds_alternative<unsigned int >(value))
70- {
71- json_[name] = opentelemetry::nostd::get<unsigned int >(value);
72- }
73- else if (nostd::holds_alternative<uint64_t >(value))
74- {
75- json_[name] = opentelemetry::nostd::get<uint64_t >(value);
76- }
77- else if (nostd::holds_alternative<double >(value))
78- {
79- json_[name] = opentelemetry::nostd::get<double >(value);
80- }
81- else if (nostd::holds_alternative<const char *>(value))
82- {
83- json_[name] = std::string (nostd::get<const char *>(value));
84- }
85- else if (nostd::holds_alternative<nostd::string_view>(value))
86- {
87- json_[name] = static_cast <std::string>(opentelemetry::nostd::get<nostd::string_view>(value));
88- }
89- else if (nostd::holds_alternative<nostd::span<const uint8_t >>(value))
90- {
91- nlohmann::json array_value = nlohmann::json::array ();
92- for (const auto &val : nostd::get<nostd::span<const uint8_t >>(value))
93- {
94- array_value.push_back (val);
95- }
96- json_[name] = array_value;
97- }
98- else if (nostd::holds_alternative<nostd::span<const bool >>(value))
99- {
100- nlohmann::json array_value = nlohmann::json::array ();
101- for (const auto &val : nostd::get<nostd::span<const bool >>(value))
102- {
103- array_value.push_back (val);
104- }
105- json_[name] = array_value;
106- }
107- else if (nostd::holds_alternative<nostd::span<const int >>(value))
108- {
109- nlohmann::json array_value = nlohmann::json::array ();
110- for (const auto &val : nostd::get<nostd::span<const int >>(value))
111- {
112- array_value.push_back (val);
113- }
114- json_[name] = array_value;
115- }
116- else if (nostd::holds_alternative<nostd::span<const int64_t >>(value))
117- {
118- nlohmann::json array_value = nlohmann::json::array ();
119- for (const auto &val : nostd::get<nostd::span<const int64_t >>(value))
120- {
121- array_value.push_back (val);
122- }
123- json_[name] = array_value;
124- }
125- else if (nostd::holds_alternative<nostd::span<const unsigned int >>(value))
126- {
127- nlohmann::json array_value = nlohmann::json::array ();
128- for (const auto &val : nostd::get<nostd::span<const unsigned int >>(value))
129- {
130- array_value.push_back (val);
131- }
132- json_[name] = array_value;
133- }
134- else if (nostd::holds_alternative<nostd::span<const uint64_t >>(value))
135- {
136- nlohmann::json array_value = nlohmann::json::array ();
137- for (const auto &val : nostd::get<nostd::span<const uint64_t >>(value))
138- {
139- array_value.push_back (val);
140- }
141- json_[name] = array_value;
142- }
143- else if (nostd::holds_alternative<nostd::span<const double >>(value))
144- {
145- nlohmann::json array_value = nlohmann::json::array ();
146- for (const auto &val : nostd::get<nostd::span<const double >>(value))
147- {
148- array_value.push_back (val);
149- }
150- json_[name] = array_value;
151- }
152- else if (nostd::holds_alternative<nostd::span<const nostd::string_view>>(value))
153- {
154- nlohmann::json array_value = nlohmann::json::array ();
155- for (const auto &val : nostd::get<nostd::span<const nostd::string_view>>(value))
156- {
157- array_value.push_back (static_cast <std::string>(val));
158- }
159- json_[name] = array_value;
160- }
54+ json_[name] = value;
16155}
16256
16357ElasticSearchRecordable::ElasticSearchRecordable () noexcept : sdk::logs::Recordable()
@@ -180,27 +74,19 @@ void ElasticSearchRecordable::SetTimestamp(
18074#if __cplusplus >= 202002L
18175 const std::string dateStr = std::format (" {:%FT%T%Ez}" , timePoint);
18276#else
183- const static int dateToSecondsSize = 19 ;
184- const static int millisecondsSize = 8 ;
185- const static int timeZoneSize = 1 ;
186- const static int dateSize = dateToSecondsSize + millisecondsSize + timeZoneSize;
187-
18877 std::time_t time = std::chrono::system_clock::to_time_t (timePoint);
18978 std::tm tm = *std::gmtime (&time);
190-
191- char bufferDate[dateSize]; // example: 2024-10-18T07:26:00.123456Z
192- std::strftime (bufferDate, sizeof (bufferDate), " %Y-%m-%dT%H:%M:%S" , &tm);
19379 auto microseconds =
19480 std::chrono::duration_cast<std::chrono::microseconds>(timePoint.time_since_epoch ()) %
19581 std::chrono::seconds (1 );
19682
197- char bufferMilliseconds[millisecondsSize];
198- std::snprintf (bufferMilliseconds, sizeof (bufferMilliseconds), " .%06ld" ,
83+ // `sizeof()` includes the null terminator
84+ constexpr auto dateSize = sizeof (" YYYY-MM-DDTHH:MM:SS.uuuuuuZ" );
85+ char bufferDate[dateSize];
86+ auto offset = std::strftime (bufferDate, sizeof (bufferDate), " %Y-%m-%dT%H:%M:%S" , &tm);
87+ std::snprintf (bufferDate + offset, sizeof (bufferDate) - offset, " .%06ldZ" ,
19988 static_cast <long >(microseconds.count ()));
20089
201- std::strcat (bufferDate, bufferMilliseconds);
202- std::strcat (bufferDate, " Z" );
203-
20490 const std::string dateStr (bufferDate);
20591#endif
20692
@@ -221,9 +107,8 @@ void ElasticSearchRecordable::SetSeverity(opentelemetry::logs::Severity severity
221107 std::uint32_t severity_index = static_cast <std::uint32_t >(severity);
222108 if (severity_index >= std::extent<decltype (opentelemetry::logs::SeverityNumToText)>::value)
223109 {
224- std::stringstream sout;
225- sout << " Invalid severity(" << severity_index << " )" ;
226- severityField = sout.str ();
110+ severityField =
111+ std::string (" Invalid severity(" ).append (std::to_string (severity_index)).append (" )" );
227112 }
228113 else
229114 {
@@ -240,7 +125,7 @@ void ElasticSearchRecordable::SetTraceId(const opentelemetry::trace::TraceId &tr
240125{
241126 if (trace_id.IsValid ())
242127 {
243- char trace_buf[32 ];
128+ char trace_buf[opentelemetry::trace::TraceId:: kSize * 2 ];
244129 trace_id.ToLowerBase16 (trace_buf);
245130 json_[" traceid" ] = std::string (trace_buf, sizeof (trace_buf));
246131 }
@@ -254,7 +139,7 @@ void ElasticSearchRecordable::SetSpanId(const opentelemetry::trace::SpanId &span
254139{
255140 if (span_id.IsValid ())
256141 {
257- char span_buf[16 ];
142+ char span_buf[opentelemetry::trace::SpanId:: kSize * 2 ];
258143 span_id.ToLowerBase16 (span_buf);
259144 json_[" spanid" ] = std::string (span_buf, sizeof (span_buf));
260145 }
@@ -282,7 +167,7 @@ void ElasticSearchRecordable::SetAttribute(
282167void ElasticSearchRecordable::SetResource (
283168 const opentelemetry::sdk::resource::Resource &resource) noexcept
284169{
285- for (auto &attribute : resource.GetAttributes ())
170+ for (const auto &attribute : resource.GetAttributes ())
286171 {
287172 WriteValue (attribute.second , attribute.first );
288173 }
0 commit comments