@@ -197,6 +197,11 @@ void ElasticSearchRecordable::WriteValue(const opentelemetry::common::AttributeV
197197 }
198198}
199199
200+ ElasticSearchRecordable::ElasticSearchRecordable () noexcept : sdk::logs::Recordable()
201+ {
202+ json_[" ecs" ][" version" ] = " 8.11.0" ;
203+ }
204+
200205nlohmann::json ElasticSearchRecordable::GetJSON () noexcept
201206{
202207 return json_;
@@ -205,7 +210,38 @@ nlohmann::json ElasticSearchRecordable::GetJSON() noexcept
205210void ElasticSearchRecordable::SetTimestamp (
206211 opentelemetry::common::SystemTimestamp timestamp) noexcept
207212{
208- json_[" timestamp" ] = timestamp.time_since_epoch ().count ();
213+ const std::chrono::system_clock::time_point timePoint{timestamp};
214+
215+ // If built with with at least cpp 20 then use std::format
216+ // Otherwise use the old style to format the timestamp in UTC
217+ #if __cplusplus >= 202002L
218+ const std::string dateStr = std::format (" {:%FT%T%Ez}" , timePoint);
219+ #else
220+ const static int dateToSecondsSize = 19 ;
221+ const static int millisecondsSize = 8 ;
222+ const static int timeZoneSize = 1 ;
223+ const static int dateSize = dateToSecondsSize + millisecondsSize + timeZoneSize;
224+
225+ std::time_t time = std::chrono::system_clock::to_time_t (timePoint);
226+ std::tm tm = *std::gmtime (&time);
227+
228+ char bufferDate[dateSize]; // example: 2024-10-18T07:26:00.123456Z
229+ std::strftime (bufferDate, sizeof (bufferDate), " %Y-%m-%dT%H:%M:%S" , &tm);
230+ auto microseconds =
231+ std::chrono::duration_cast<std::chrono::microseconds>(timePoint.time_since_epoch ()) %
232+ std::chrono::seconds (1 );
233+
234+ char bufferMilliseconds[millisecondsSize];
235+ std::snprintf (bufferMilliseconds, sizeof (bufferMilliseconds), " .%06ld" ,
236+ static_cast <long >(microseconds.count ()));
237+
238+ std::strcat (bufferDate, bufferMilliseconds);
239+ std::strcat (bufferDate, " Z" );
240+
241+ const std::string dateStr (bufferDate);
242+ #endif
243+
244+ json_[" @timestamp" ] = dateStr;
209245}
210246
211247void ElasticSearchRecordable::SetObservedTimestamp (
@@ -216,23 +252,25 @@ void ElasticSearchRecordable::SetObservedTimestamp(
216252
217253void ElasticSearchRecordable::SetSeverity (opentelemetry::logs::Severity severity) noexcept
218254{
255+ auto &severityField = json_[" log" ][" level" ];
256+
219257 // Convert the severity enum to a string
220258 std::uint32_t severity_index = static_cast <std::uint32_t >(severity);
221259 if (severity_index >= std::extent<decltype (opentelemetry::logs::SeverityNumToText)>::value)
222260 {
223261 std::stringstream sout;
224262 sout << " Invalid severity(" << severity_index << " )" ;
225- json_[ " severity " ] = sout.str ();
263+ severityField = sout.str ();
226264 }
227265 else
228266 {
229- json_[ " severity " ] = opentelemetry::logs::SeverityNumToText[severity_index];
267+ severityField = opentelemetry::logs::SeverityNumToText[severity_index];
230268 }
231269}
232270
233271void ElasticSearchRecordable::SetBody (const opentelemetry::common::AttributeValue &message) noexcept
234272{
235- WriteValue (message, " body " );
273+ WriteValue (message, " message " );
236274}
237275
238276void ElasticSearchRecordable::SetTraceId (const opentelemetry::trace::TraceId &trace_id) noexcept
@@ -275,7 +313,7 @@ void ElasticSearchRecordable::SetAttribute(
275313 nostd::string_view key,
276314 const opentelemetry::common::AttributeValue &value) noexcept
277315{
278- WriteKeyValue (key, value, " attributes " );
316+ WriteValue ( value, key. data () );
279317}
280318
281319void ElasticSearchRecordable::SetResource (
@@ -291,7 +329,7 @@ void ElasticSearchRecordable::SetInstrumentationScope(
291329 const opentelemetry::sdk::instrumentationscope::InstrumentationScope
292330 &instrumentation_scope) noexcept
293331{
294- json_[" name " ] = instrumentation_scope.GetName ();
332+ json_[" log " ][ " logger " ] = instrumentation_scope.GetName ();
295333}
296334
297335} // namespace logs
0 commit comments