493 lines
18 KiB
C++
493 lines
18 KiB
C++
// Copyright The OpenTelemetry Authors
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
#pragma once
|
|
|
|
#include "opentelemetry/logs/logger_type_traits.h"
|
|
#include "opentelemetry/logs/severity.h"
|
|
#include "opentelemetry/nostd/string_view.h"
|
|
#include "opentelemetry/nostd/unique_ptr.h"
|
|
#include "opentelemetry/version.h"
|
|
|
|
OPENTELEMETRY_BEGIN_NAMESPACE
|
|
namespace common
|
|
{
|
|
class KeyValueIterable;
|
|
} // namespace common
|
|
|
|
namespace logs
|
|
{
|
|
|
|
class EventId;
|
|
class LogRecord;
|
|
|
|
/**
|
|
* Handles log record creation.
|
|
**/
|
|
class Logger
|
|
{
|
|
public:
|
|
virtual ~Logger() = default;
|
|
|
|
/* Returns the name of the logger */
|
|
virtual const nostd::string_view GetName() noexcept = 0;
|
|
|
|
/**
|
|
* Create a Log Record object
|
|
*
|
|
* @return nostd::unique_ptr<LogRecord>
|
|
*/
|
|
virtual nostd::unique_ptr<LogRecord> CreateLogRecord() noexcept = 0;
|
|
|
|
/**
|
|
* Emit a Log Record object
|
|
*
|
|
* @param log_record Log record
|
|
*/
|
|
virtual void EmitLogRecord(nostd::unique_ptr<LogRecord> &&log_record) noexcept = 0;
|
|
|
|
/**
|
|
* Emit a Log Record object with arguments
|
|
*
|
|
* @param log_record Log record
|
|
* @param args Arguments which can be used to set data of log record by type.
|
|
* Severity -> severity, severity_text
|
|
* string_view -> body
|
|
* AttributeValue -> body
|
|
* SpanContext -> span_id,trace_id and trace_flags
|
|
* SpanId -> span_id
|
|
* TraceId -> trace_id
|
|
* TraceFlags -> trace_flags
|
|
* SystemTimestamp -> timestamp
|
|
* system_clock::time_point -> timestamp
|
|
* KeyValueIterable -> attributes
|
|
* Key value iterable container -> attributes
|
|
* span<pair<string_view, AttributeValue>> -> attributes(return type of MakeAttributes)
|
|
*/
|
|
template <class... ArgumentType>
|
|
void EmitLogRecord(nostd::unique_ptr<LogRecord> &&log_record, ArgumentType &&...args)
|
|
{
|
|
if (!log_record)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Keep the parameter pack unpacking order from left to right because left
|
|
// ones are usually more important like severity and event_id than the
|
|
// attributes. The left to right unpack order could pass the more important
|
|
// data to processors to avoid caching and memory allocating.
|
|
//
|
|
#if __cplusplus <= 201402L
|
|
// C++14 does not support fold expressions for parameter pack expansion.
|
|
int dummy[] = {(detail::LogRecordSetterTrait<typename std::decay<ArgumentType>::type>::Set(
|
|
log_record.get(), std::forward<ArgumentType>(args)),
|
|
0)...};
|
|
IgnoreTraitResult(dummy);
|
|
#else
|
|
IgnoreTraitResult((detail::LogRecordSetterTrait<typename std::decay<ArgumentType>::type>::Set(
|
|
log_record.get(), std::forward<ArgumentType>(args)),
|
|
...));
|
|
#endif
|
|
|
|
EmitLogRecord(std::move(log_record));
|
|
}
|
|
|
|
/**
|
|
* Emit a Log Record object with arguments
|
|
*
|
|
* @param args Arguments which can be used to set data of log record by type.
|
|
* Severity -> severity, severity_text
|
|
* string_view -> body
|
|
* AttributeValue -> body
|
|
* SpanContext -> span_id,trace_id and trace_flags
|
|
* SpanId -> span_id
|
|
* TraceId -> trace_id
|
|
* TraceFlags -> trace_flags
|
|
* SystemTimestamp -> timestamp
|
|
* system_clock::time_point -> timestamp
|
|
* KeyValueIterable -> attributes
|
|
* Key value iterable container -> attributes
|
|
* span<pair<string_view, AttributeValue>> -> attributes(return type of MakeAttributes)
|
|
*/
|
|
template <class... ArgumentType>
|
|
void EmitLogRecord(ArgumentType &&...args)
|
|
{
|
|
nostd::unique_ptr<LogRecord> log_record = CreateLogRecord();
|
|
|
|
EmitLogRecord(std::move(log_record), std::forward<ArgumentType>(args)...);
|
|
}
|
|
|
|
/**
|
|
* Writes a log with a severity of trace.
|
|
* @param args Arguments which can be used to set data of log record by type.
|
|
* string_view -> body
|
|
* AttributeValue -> body
|
|
* SpanContext -> span_id,trace_id and trace_flags
|
|
* SpanId -> span_id
|
|
* TraceId -> trace_id
|
|
* TraceFlags -> trace_flags
|
|
* SystemTimestamp -> timestamp
|
|
* system_clock::time_point -> timestamp
|
|
* KeyValueIterable -> attributes
|
|
* Key value iterable container -> attributes
|
|
* span<pair<string_view, AttributeValue>> -> attributes(return type of MakeAttributes)
|
|
*/
|
|
template <class... ArgumentType>
|
|
void Trace(ArgumentType &&...args) noexcept
|
|
{
|
|
static_assert(
|
|
!detail::LogRecordHasType<Severity, typename std::decay<ArgumentType>::type...>::value,
|
|
"Severity is already set.");
|
|
this->EmitLogRecord(Severity::kTrace, std::forward<ArgumentType>(args)...);
|
|
}
|
|
|
|
/**
|
|
* Writes a log with a severity of debug.
|
|
* @param args Arguments which can be used to set data of log record by type.
|
|
* string_view -> body
|
|
* AttributeValue -> body
|
|
* SpanContext -> span_id,trace_id and trace_flags
|
|
* SpanId -> span_id
|
|
* TraceId -> trace_id
|
|
* TraceFlags -> trace_flags
|
|
* SystemTimestamp -> timestamp
|
|
* system_clock::time_point -> timestamp
|
|
* KeyValueIterable -> attributes
|
|
* Key value iterable container -> attributes
|
|
* span<pair<string_view, AttributeValue>> -> attributes(return type of MakeAttributes)
|
|
*/
|
|
template <class... ArgumentType>
|
|
void Debug(ArgumentType &&...args) noexcept
|
|
{
|
|
static_assert(
|
|
!detail::LogRecordHasType<Severity, typename std::decay<ArgumentType>::type...>::value,
|
|
"Severity is already set.");
|
|
this->EmitLogRecord(Severity::kDebug, std::forward<ArgumentType>(args)...);
|
|
}
|
|
|
|
/**
|
|
* Writes a log with a severity of info.
|
|
* @param args Arguments which can be used to set data of log record by type.
|
|
* string_view -> body
|
|
* AttributeValue -> body
|
|
* SpanContext -> span_id,trace_id and trace_flags
|
|
* SpanId -> span_id
|
|
* TraceId -> trace_id
|
|
* TraceFlags -> trace_flags
|
|
* SystemTimestamp -> timestamp
|
|
* system_clock::time_point -> timestamp
|
|
* KeyValueIterable -> attributes
|
|
* Key value iterable container -> attributes
|
|
* span<pair<string_view, AttributeValue>> -> attributes(return type of MakeAttributes)
|
|
*/
|
|
template <class... ArgumentType>
|
|
void Info(ArgumentType &&...args) noexcept
|
|
{
|
|
static_assert(
|
|
!detail::LogRecordHasType<Severity, typename std::decay<ArgumentType>::type...>::value,
|
|
"Severity is already set.");
|
|
this->EmitLogRecord(Severity::kInfo, std::forward<ArgumentType>(args)...);
|
|
}
|
|
|
|
/**
|
|
* Writes a log with a severity of warn.
|
|
* @param args Arguments which can be used to set data of log record by type.
|
|
* string_view -> body
|
|
* AttributeValue -> body
|
|
* SpanContext -> span_id,trace_id and trace_flags
|
|
* SpanId -> span_id
|
|
* TraceId -> trace_id
|
|
* TraceFlags -> trace_flags
|
|
* SystemTimestamp -> timestamp
|
|
* system_clock::time_point -> timestamp
|
|
* KeyValueIterable -> attributes
|
|
* Key value iterable container -> attributes
|
|
* span<pair<string_view, AttributeValue>> -> attributes(return type of MakeAttributes)
|
|
*/
|
|
template <class... ArgumentType>
|
|
void Warn(ArgumentType &&...args) noexcept
|
|
{
|
|
static_assert(
|
|
!detail::LogRecordHasType<Severity, typename std::decay<ArgumentType>::type...>::value,
|
|
"Severity is already set.");
|
|
this->EmitLogRecord(Severity::kWarn, std::forward<ArgumentType>(args)...);
|
|
}
|
|
|
|
/**
|
|
* Writes a log with a severity of error.
|
|
* @param args Arguments which can be used to set data of log record by type.
|
|
* string_view -> body
|
|
* AttributeValue -> body
|
|
* SpanContext -> span_id,trace_id and trace_flags
|
|
* SpanId -> span_id
|
|
* TraceId -> trace_id
|
|
* TraceFlags -> trace_flags
|
|
* SystemTimestamp -> timestamp
|
|
* system_clock::time_point -> timestamp
|
|
* KeyValueIterable -> attributes
|
|
* Key value iterable container -> attributes
|
|
* span<pair<string_view, AttributeValue>> -> attributes(return type of MakeAttributes)
|
|
*/
|
|
template <class... ArgumentType>
|
|
void Error(ArgumentType &&...args) noexcept
|
|
{
|
|
static_assert(
|
|
!detail::LogRecordHasType<Severity, typename std::decay<ArgumentType>::type...>::value,
|
|
"Severity is already set.");
|
|
this->EmitLogRecord(Severity::kError, std::forward<ArgumentType>(args)...);
|
|
}
|
|
|
|
/**
|
|
* Writes a log with a severity of fatal.
|
|
* @param args Arguments which can be used to set data of log record by type.
|
|
* string_view -> body
|
|
* AttributeValue -> body
|
|
* SpanContext -> span_id,trace_id and trace_flags
|
|
* SpanId -> span_id
|
|
* TraceId -> trace_id
|
|
* TraceFlags -> trace_flags
|
|
* SystemTimestamp -> timestamp
|
|
* system_clock::time_point -> timestamp
|
|
* KeyValueIterable -> attributes
|
|
* Key value iterable container -> attributes
|
|
* span<pair<string_view, AttributeValue>> -> attributes(return type of MakeAttributes)
|
|
*/
|
|
template <class... ArgumentType>
|
|
void Fatal(ArgumentType &&...args) noexcept
|
|
{
|
|
static_assert(
|
|
!detail::LogRecordHasType<Severity, typename std::decay<ArgumentType>::type...>::value,
|
|
"Severity is already set.");
|
|
this->EmitLogRecord(Severity::kFatal, std::forward<ArgumentType>(args)...);
|
|
}
|
|
|
|
//
|
|
// OpenTelemetry C++ user-facing Logs API
|
|
//
|
|
|
|
inline bool Enabled(Severity severity, const EventId &event_id) const noexcept
|
|
{
|
|
if OPENTELEMETRY_LIKELY_CONDITION (!Enabled(severity))
|
|
{
|
|
return false;
|
|
}
|
|
return EnabledImplementation(severity, event_id);
|
|
}
|
|
|
|
inline bool Enabled(Severity severity, int64_t event_id) const noexcept
|
|
{
|
|
if OPENTELEMETRY_LIKELY_CONDITION (!Enabled(severity))
|
|
{
|
|
return false;
|
|
}
|
|
return EnabledImplementation(severity, event_id);
|
|
}
|
|
|
|
inline bool Enabled(Severity severity) const noexcept
|
|
{
|
|
return static_cast<uint8_t>(severity) >= OPENTELEMETRY_ATOMIC_READ_8(&minimum_severity_);
|
|
}
|
|
|
|
/**
|
|
* Log an event
|
|
*
|
|
* @severity severity of the log
|
|
* @event_id event identifier of the log
|
|
* @format an utf-8 string following https://messagetemplates.org/
|
|
* @attributes key value pairs of the log
|
|
*/
|
|
virtual void Log(Severity severity,
|
|
const EventId &event_id,
|
|
nostd::string_view format,
|
|
const common::KeyValueIterable &attributes) noexcept
|
|
{
|
|
this->EmitLogRecord(severity, event_id, format, attributes);
|
|
}
|
|
|
|
virtual void Log(Severity severity,
|
|
int64_t event_id,
|
|
nostd::string_view format,
|
|
const common::KeyValueIterable &attributes) noexcept
|
|
{
|
|
this->EmitLogRecord(severity, EventId{event_id}, format, attributes);
|
|
}
|
|
|
|
virtual void Log(Severity severity,
|
|
nostd::string_view format,
|
|
const common::KeyValueIterable &attributes) noexcept
|
|
{
|
|
this->EmitLogRecord(severity, format, attributes);
|
|
}
|
|
|
|
virtual void Log(Severity severity, nostd::string_view message) noexcept
|
|
{
|
|
this->EmitLogRecord(severity, message);
|
|
}
|
|
|
|
// Convenient wrappers based on virtual methods Log().
|
|
// https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/data-model.md#field-severitynumber
|
|
|
|
inline void Trace(const EventId &event_id,
|
|
nostd::string_view format,
|
|
const common::KeyValueIterable &attributes) noexcept
|
|
{
|
|
this->Log(Severity::kTrace, event_id, format, attributes);
|
|
}
|
|
|
|
inline void Trace(int64_t event_id,
|
|
nostd::string_view format,
|
|
const common::KeyValueIterable &attributes) noexcept
|
|
{
|
|
this->Log(Severity::kTrace, EventId{event_id}, format, attributes);
|
|
}
|
|
|
|
inline void Trace(nostd::string_view format, const common::KeyValueIterable &attributes) noexcept
|
|
{
|
|
this->Log(Severity::kTrace, format, attributes);
|
|
}
|
|
|
|
inline void Trace(nostd::string_view message) noexcept { this->Log(Severity::kTrace, message); }
|
|
|
|
inline void Debug(const EventId &event_id,
|
|
nostd::string_view format,
|
|
const common::KeyValueIterable &attributes) noexcept
|
|
{
|
|
this->Log(Severity::kDebug, event_id, format, attributes);
|
|
}
|
|
|
|
inline void Debug(int64_t event_id,
|
|
nostd::string_view format,
|
|
const common::KeyValueIterable &attributes) noexcept
|
|
{
|
|
this->Log(Severity::kDebug, EventId{event_id}, format, attributes);
|
|
}
|
|
|
|
inline void Debug(nostd::string_view format, const common::KeyValueIterable &attributes) noexcept
|
|
{
|
|
this->Log(Severity::kDebug, format, attributes);
|
|
}
|
|
|
|
inline void Debug(nostd::string_view message) noexcept { this->Log(Severity::kDebug, message); }
|
|
|
|
inline void Info(const EventId &event_id,
|
|
nostd::string_view format,
|
|
const common::KeyValueIterable &attributes) noexcept
|
|
{
|
|
this->Log(Severity::kInfo, event_id, format, attributes);
|
|
}
|
|
|
|
inline void Info(int64_t event_id,
|
|
nostd::string_view format,
|
|
const common::KeyValueIterable &attributes) noexcept
|
|
{
|
|
this->Log(Severity::kInfo, EventId{event_id}, format, attributes);
|
|
}
|
|
|
|
inline void Info(nostd::string_view format, const common::KeyValueIterable &attributes) noexcept
|
|
{
|
|
this->Log(Severity::kInfo, format, attributes);
|
|
}
|
|
|
|
inline void Info(nostd::string_view message) noexcept { this->Log(Severity::kInfo, message); }
|
|
|
|
inline void Warn(const EventId &event_id,
|
|
nostd::string_view format,
|
|
const common::KeyValueIterable &attributes) noexcept
|
|
{
|
|
this->Log(Severity::kWarn, event_id, format, attributes);
|
|
}
|
|
|
|
inline void Warn(int64_t event_id,
|
|
nostd::string_view format,
|
|
const common::KeyValueIterable &attributes) noexcept
|
|
{
|
|
this->Log(Severity::kWarn, EventId{event_id}, format, attributes);
|
|
}
|
|
|
|
inline void Warn(nostd::string_view format, const common::KeyValueIterable &attributes) noexcept
|
|
{
|
|
this->Log(Severity::kWarn, format, attributes);
|
|
}
|
|
|
|
inline void Warn(nostd::string_view message) noexcept { this->Log(Severity::kWarn, message); }
|
|
|
|
inline void Error(const EventId &event_id,
|
|
nostd::string_view format,
|
|
const common::KeyValueIterable &attributes) noexcept
|
|
{
|
|
this->Log(Severity::kError, event_id, format, attributes);
|
|
}
|
|
|
|
inline void Error(int64_t event_id,
|
|
nostd::string_view format,
|
|
const common::KeyValueIterable &attributes) noexcept
|
|
{
|
|
this->Log(Severity::kError, EventId{event_id}, format, attributes);
|
|
}
|
|
|
|
inline void Error(nostd::string_view format, const common::KeyValueIterable &attributes) noexcept
|
|
{
|
|
this->Log(Severity::kError, format, attributes);
|
|
}
|
|
|
|
inline void Error(nostd::string_view message) noexcept { this->Log(Severity::kError, message); }
|
|
|
|
inline void Fatal(const EventId &event_id,
|
|
nostd::string_view format,
|
|
const common::KeyValueIterable &attributes) noexcept
|
|
{
|
|
this->Log(Severity::kFatal, event_id, format, attributes);
|
|
}
|
|
|
|
inline void Fatal(int64_t event_id,
|
|
nostd::string_view format,
|
|
const common::KeyValueIterable &attributes) noexcept
|
|
{
|
|
this->Log(Severity::kFatal, EventId{event_id}, format, attributes);
|
|
}
|
|
|
|
inline void Fatal(nostd::string_view format, const common::KeyValueIterable &attributes) noexcept
|
|
{
|
|
this->Log(Severity::kFatal, format, attributes);
|
|
}
|
|
|
|
inline void Fatal(nostd::string_view message) noexcept { this->Log(Severity::kFatal, message); }
|
|
|
|
//
|
|
// End of OpenTelemetry C++ user-facing Log API.
|
|
//
|
|
|
|
protected:
|
|
// TODO: discuss with community about naming for internal methods.
|
|
virtual bool EnabledImplementation(Severity /*severity*/,
|
|
const EventId & /*event_id*/) const noexcept
|
|
{
|
|
return false;
|
|
}
|
|
|
|
virtual bool EnabledImplementation(Severity /*severity*/, int64_t /*event_id*/) const noexcept
|
|
{
|
|
return false;
|
|
}
|
|
|
|
void SetMinimumSeverity(uint8_t severity_or_max) noexcept
|
|
{
|
|
OPENTELEMETRY_ATOMIC_WRITE_8(&minimum_severity_, severity_or_max);
|
|
}
|
|
|
|
private:
|
|
template <class... ValueType>
|
|
void IgnoreTraitResult(ValueType &&...)
|
|
{}
|
|
|
|
//
|
|
// minimum_severity_ can be updated concurrently by multiple threads/cores, so race condition on
|
|
// read/write should be handled. And std::atomic can not be used here because it is not ABI
|
|
// compatible for OpenTelemetry C++ API.
|
|
//
|
|
mutable uint8_t minimum_severity_{kMaxSeverity};
|
|
};
|
|
} // namespace logs
|
|
OPENTELEMETRY_END_NAMESPACE
|