Program Listing for File logger.h

Return to documentation for file (/tmp/B.puc0r6hi/BUILD/opentelemetry-cpp-1.27.0-build/opentelemetry-cpp-1.27.0/api/include/opentelemetry/logs/logger.h)

// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

#pragma once

#include <stdint.h>
#include <type_traits>
#include <utility>

#include "opentelemetry/context/context.h"
#include "opentelemetry/logs/event_id.h"
#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;

class Logger
{
public:
  Logger()                              = default;
  Logger(const Logger &)                = default;
  Logger(Logger &&) noexcept            = default;
  Logger &operator=(const Logger &)     = default;
  Logger &operator=(Logger &&) noexcept = default;
  virtual ~Logger()                     = default;

  /* Returns the name of the logger */
  virtual const nostd::string_view GetName() noexcept = 0;

  virtual nostd::unique_ptr<LogRecord> CreateLogRecord() noexcept = 0;

  virtual void EmitLogRecord(nostd::unique_ptr<LogRecord> &&log_record) noexcept = 0;

  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));
  }

  template <class... ArgumentType>
  void EmitLogRecord(ArgumentType &&...args)
  {
    nostd::unique_ptr<LogRecord> log_record = CreateLogRecord();

    EmitLogRecord(std::move(log_record), std::forward<ArgumentType>(args)...);
  }

  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)...);
  }

  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)...);
  }

  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)...);
  }

  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)...);
  }

  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)...);
  }

  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
  //

#if OPENTELEMETRY_ABI_VERSION_NO >= 2
  inline bool Enabled(const opentelemetry::context::Context &context,
                      Severity severity = Severity::kInvalid) const noexcept
  {
    if OPENTELEMETRY_LIKELY_CONDITION (!Enabled(severity))
    {
      return false;
    }
    return EnabledImplementation(context, severity);
  }

  inline bool Enabled(const opentelemetry::context::Context &context,
                      Severity severity,
                      const EventId &event_id) const noexcept
  {
    if OPENTELEMETRY_LIKELY_CONDITION (!Enabled(severity))
    {
      return false;
    }
    return EnabledImplementation(context, severity, event_id);
  }
#endif  // OPENTELEMETRY_ABI_VERSION_NO >= 2

  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_);
  }

  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:
  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;
  }

#if OPENTELEMETRY_ABI_VERSION_NO >= 2
  virtual bool EnabledImplementation(const opentelemetry::context::Context & /*context*/,
                                     Severity /*severity*/) const noexcept
  {
    return false;
  }

  virtual bool EnabledImplementation(const opentelemetry::context::Context & /*context*/,
                                     Severity /*severity*/,
                                     const EventId & /*event_id*/) const noexcept
  {
    return false;
  }
#endif  // OPENTELEMETRY_ABI_VERSION_NO >= 2

  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