opentelemetry-cpp/api/include/opentelemetry/logs/logger.h

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