Skip to content

Commit

Permalink
Add user facing Logging API and Benchmarks (#2094)
Browse files Browse the repository at this point in the history
  • Loading branch information
ThomsonTan authored Apr 23, 2023
1 parent 22d0448 commit a39e8b5
Show file tree
Hide file tree
Showing 10 changed files with 626 additions and 26 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ Increment the:

* [BUILD] Build break with old curl, macro CURL_VERSION_BITS unknown
[#2102](https://github.com/open-telemetry/opentelemetry-cpp/pull/2102)
* [API] Add user facing Logging API and Benchmarks
[#2094](https://github.com/open-telemetry/opentelemetry-cpp/pull/2094)

Deprecations:

Expand Down
26 changes: 26 additions & 0 deletions api/include/opentelemetry/common/macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
# define OPENTELEMETRY_LIKELY_IF(...) \
if (__VA_ARGS__) \
[[likely]]

# endif
# endif
#endif
Expand Down Expand Up @@ -176,6 +177,31 @@ point.

#endif

//
// Atomic wrappers based on compiler intrinsics for memory read/write.
// The tailing number is read/write length in bits.
//
// N.B. Compiler instrinsic is used because the usage of C++ standard library is restricted in the
// OpenTelemetry C++ API.
//
#if defined(__GNUC__)

# define OPENTELEMETRY_ATOMIC_READ_8(ptr) __atomic_load_n(ptr, __ATOMIC_SEQ_CST)
# define OPENTELEMETRY_ATOMIC_WRITE_8(ptr, value) __atomic_store_n(ptr, value, __ATOMIC_SEQ_CST)

#elif defined(_MSC_VER)

# include <intrin.h>

# define OPENTELEMETRY_ATOMIC_READ_8(ptr) \
static_cast<uint8_t>(_InterlockedCompareExchange8(reinterpret_cast<char *>(ptr), 0, 0))
# define OPENTELEMETRY_ATOMIC_WRITE_8(ptr, value) \
_InterlockedExchange8(reinterpret_cast<char *>(ptr), static_cast<char>(value))

#else
# error port atomics read/write for the current platform
#endif

/* clang-format on */
//
// The if/elif order matters here. If both OPENTELEMETRY_BUILD_IMPORT_DLL and
Expand Down
36 changes: 36 additions & 0 deletions api/include/opentelemetry/logs/event_id.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

#pragma once

#ifdef ENABLE_LOGS_PREVIEW

# include "opentelemetry/nostd/unique_ptr.h"
# include "opentelemetry/version.h"

OPENTELEMETRY_BEGIN_NAMESPACE
namespace logs
{

/**
* EventId class which acts the Id of the event with an optional name.
*/
class EventId
{
public:
EventId(int64_t id, nostd::string_view name) noexcept
{
id_ = id;
name_ = nostd::unique_ptr<char[]>{new char[name.length() + 1]};
std::copy(name.begin(), name.end(), name_.get());
name_.get()[name.length()] = 0;
}

public:
int64_t id_;
nostd::unique_ptr<char[]> name_;
};

} // namespace logs
OPENTELEMETRY_END_NAMESPACE
#endif
216 changes: 216 additions & 0 deletions api/include/opentelemetry/logs/logger.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#ifdef ENABLE_LOGS_PREVIEW

# include "opentelemetry/common/key_value_iterable.h"
# include "opentelemetry/logs/event_id.h"
# include "opentelemetry/logs/log_record.h"
# include "opentelemetry/logs/logger_type_traits.h"
# include "opentelemetry/logs/severity.h"
Expand Down Expand Up @@ -246,10 +247,225 @@ class Logger
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
{
OPENTELEMETRY_LIKELY_IF(Enabled(severity) == false) { return false; }
return EnabledImplementation(severity, event_id);
}

inline bool Enabled(Severity severity, int64_t event_id) const noexcept
{
OPENTELEMETRY_LIKELY_IF(Enabled(severity) == false) { 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, 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, 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, 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, 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, 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, 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, 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
Expand Down
2 changes: 1 addition & 1 deletion api/include/opentelemetry/logs/logger_provider.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class OPENTELEMETRY_EXPORT LoggerProvider

virtual nostd::shared_ptr<Logger> GetLogger(
nostd::string_view logger_name,
nostd::string_view library_name,
nostd::string_view library_name = "",
nostd::string_view library_version = "",
nostd::string_view schema_url = "",
bool include_trace_context = true,
Expand Down
12 changes: 12 additions & 0 deletions api/include/opentelemetry/logs/logger_type_traits.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
# include "opentelemetry/common/attribute_value.h"
# include "opentelemetry/common/key_value_iterable.h"
# include "opentelemetry/common/timestamp.h"
# include "opentelemetry/logs/event_id.h"
# include "opentelemetry/logs/log_record.h"
# include "opentelemetry/logs/severity.h"
# include "opentelemetry/nostd/shared_ptr.h"
Expand Down Expand Up @@ -43,6 +44,17 @@ struct LogRecordSetterTrait<Severity>
}
};

template <>
struct LogRecordSetterTrait<EventId>
{
template <class ArgumentType>
inline static LogRecord *Set(LogRecord *log_record, ArgumentType && /*arg*/) noexcept
{
// TODO: set log_record
return log_record;
}
};

template <>
struct LogRecordSetterTrait<trace::SpanContext>
{
Expand Down
Loading

0 comments on commit a39e8b5

Please sign in to comment.