Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add trace context injection and Logger limit to Logging SDK #15

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion sdk/include/opentelemetry/sdk/logs/exporter.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class LogExporter
* @returns an ExportResult code (whether export was success or failure)
*/
virtual ExportResult Export(
const nostd::span<std::unique_ptr<opentelemetry::logs::LogRecord>> &records) noexcept = 0;
const nostd::span<std::shared_ptr<opentelemetry::logs::LogRecord>> &records) noexcept = 0;

/**
* Marks the exporter as ShutDown and cleans up any resources as required.
Expand Down
7 changes: 5 additions & 2 deletions sdk/include/opentelemetry/sdk/logs/logger_provider.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@
#include "opentelemetry/sdk/logs/processor.h"

// Define the maximum number of loggers that are allowed to be registered to the loggerprovider.
// TODO: Add link to logging spec once this is added to it
#define MAX_LOGGER_COUNT 100
// References spec issue https://github.com/open-telemetry/opentelemetry-specification/issues/1259
#define OTEL_MAX_LOGGER_COUNT 1000

OPENTELEMETRY_BEGIN_NAMESPACE
namespace sdk
Expand Down Expand Up @@ -95,6 +95,9 @@ class LoggerProvider final : public opentelemetry::logs::LoggerProvider,

// A mutex that ensures only one thread is using the map of loggers
std::mutex mu_;

// A noop logger that is returned by GetLogger() when OTEL_MAX_LOGGER_COUNT reached
opentelemetry::nostd::shared_ptr<opentelemetry::logs::Logger> noop_logger_;
};
} // namespace logs
} // namespace sdk
Expand Down
2 changes: 1 addition & 1 deletion sdk/include/opentelemetry/sdk/logs/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class LogProcessor
* OnReceive is called by the SDK once a log record has been successfully created.
* @param record the log record
*/
virtual void OnReceive(std::unique_ptr<opentelemetry::logs::LogRecord> &&record) noexcept = 0;
virtual void OnReceive(std::shared_ptr<opentelemetry::logs::LogRecord> record) noexcept = 0;

/**
* Exports all log records that have not yet been exported to the configured Exporter.
Expand Down
2 changes: 1 addition & 1 deletion sdk/include/opentelemetry/sdk/logs/simple_log_processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class SimpleLogProcessor : public LogProcessor
explicit SimpleLogProcessor(std::unique_ptr<LogExporter> &&exporter);
virtual ~SimpleLogProcessor() = default;

void OnReceive(std::unique_ptr<opentelemetry::logs::LogRecord> &&record) noexcept override;
void OnReceive(std::shared_ptr<opentelemetry::logs::LogRecord> record) noexcept override;

bool ForceFlush(
std::chrono::microseconds timeout = std::chrono::microseconds::max()) noexcept override;
Expand Down
1 change: 1 addition & 0 deletions sdk/src/logs/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,6 @@ cc_library(
deps = [
"//api",
"//sdk:headers",
"//sdk/src/trace",
],
)
3 changes: 2 additions & 1 deletion sdk/src/logs/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
add_library(opentelemetry_logs logger_provider.cc logger.cc
simple_log_processor.cc)

target_link_libraries(opentelemetry_logs opentelemetry_common)
target_link_libraries(opentelemetry_logs opentelemetry_common
opentelemetry_trace)
46 changes: 34 additions & 12 deletions sdk/src/logs/logger.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
*/

#include "opentelemetry/sdk/logs/logger.h"
#include "opentelemetry/sdk/trace/span_data.h"
#include "opentelemetry/trace/provider.h"

OPENTELEMETRY_BEGIN_NAMESPACE
namespace sdk
Expand All @@ -36,23 +38,43 @@ void Logger::log(const opentelemetry::logs::LogRecord &record) noexcept

// TODO: Sampler logic (should include check for minSeverity)

/**
* Convert the LogRecord to the heap first before sending to processor.
* TODO: Change the API log(LogRecord) function to log(*LogRecord) so the following line
* converting record a heap variable can be removed
*/
// Create a shared pointer to the LogRecord to be passed to the processor(s)
auto record_pointer =
std::unique_ptr<opentelemetry::logs::LogRecord>(new opentelemetry::logs::LogRecord(record));
std::shared_ptr<opentelemetry::logs::LogRecord>(new opentelemetry::logs::LogRecord(record));

// TODO: Do not want to overwrite user-set timestamp if there already is one -
// add a flag in the API to check if timestamp is set by user already before setting timestamp
// Inject values into record if not user specified
// Timestamp
if (record_pointer->timestamp == opentelemetry::core::SystemTimestamp(std::chrono::seconds(0)))
{
record_pointer->timestamp = core::SystemTimestamp(std::chrono::system_clock::now());
}

auto provider = opentelemetry::trace::Provider::GetTracerProvider();
auto tracer = provider->GetTracer("foo_library");
auto span_context = tracer->GetCurrentSpan()->GetContext();

// Traceid
if (!record_pointer->trace_id.IsValid())
{
record_pointer->trace_id = span_context.trace_id();
}

// Spanid
if (!record_pointer->span_id.IsValid())
{
record_pointer->span_id = span_context.span_id();
}

// Traceflag
if (!record_pointer->trace_flag.IsSampled())
{
record_pointer->trace_flag = span_context.trace_flags();
}

// Inject timestamp if none is set
record_pointer->timestamp = core::SystemTimestamp(std::chrono::system_clock::now());
// TODO: inject traceid/spanid later
// TODO: Inject logger name into record

// Send the log record to the processor
processor->OnReceive(std::move(record_pointer));
processor->OnReceive(record_pointer);
}

} // namespace logs
Expand Down
19 changes: 8 additions & 11 deletions sdk/src/logs/logger_provider.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ namespace sdk
namespace logs
{

LoggerProvider::LoggerProvider() noexcept : processor_{nullptr} {}
LoggerProvider::LoggerProvider() noexcept
: processor_{nullptr},
noop_logger_{
nostd::shared_ptr<opentelemetry::logs::NoopLogger>(new opentelemetry::logs::NoopLogger)}
{}

opentelemetry::nostd::shared_ptr<opentelemetry::logs::Logger> LoggerProvider::GetLogger(
opentelemetry::nostd::string_view name,
Expand All @@ -39,20 +43,13 @@ opentelemetry::nostd::shared_ptr<opentelemetry::logs::Logger> LoggerProvider::Ge
}

// Check if creating a new logger would exceed the max number of loggers
// TODO: Remove the noexcept from the API's and SDK's GetLogger(~)
/*
if (loggers_.size() > MAX_LOGGER_COUNT)
if (loggers_.size() >= OTEL_MAX_LOGGER_COUNT)
{
#if __EXCEPTIONS
throw std::length_error("Number of loggers exceeds max count");
#else
std::terminate();
#endif
// Return a noop logger
return noop_logger_;
}
*/

// If no logger with that name exists yet, create it and add it to the map of loggers

opentelemetry::nostd::shared_ptr<opentelemetry::logs::Logger> logger(
new Logger(this->shared_from_this()));
loggers_[name.data()] = logger;
Expand Down
9 changes: 5 additions & 4 deletions sdk/src/logs/simple_log_processor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,15 @@ SimpleLogProcessor::SimpleLogProcessor(std::unique_ptr<LogExporter> &&exporter)
* Batches the log record it receives in a batch of 1 and immediately sends it
* to the configured exporter
*/
void SimpleLogProcessor::OnReceive(
std::unique_ptr<opentelemetry::logs::LogRecord> &&record) noexcept
void SimpleLogProcessor::OnReceive(std::shared_ptr<opentelemetry::logs::LogRecord> record) noexcept
{
nostd::span<std::unique_ptr<opentelemetry::logs::LogRecord>> batch(&record, 1);
std::vector<std::shared_ptr<opentelemetry::logs::LogRecord>> batch;
batch.emplace_back(record);
// Get lock to ensure Export() is never called concurrently
const std::lock_guard<opentelemetry::common::SpinLockMutex> locked(lock_);

if (exporter_->Export(batch) != ExportResult::kSuccess)
if (exporter_->Export(opentelemetry::nostd::span<std::shared_ptr<opentelemetry::logs::LogRecord>>(
batch.data(), batch.size())) != ExportResult::kSuccess)
{
/* Alert user of the failed export */
}
Expand Down
8 changes: 4 additions & 4 deletions sdk/test/logs/simple_log_processor_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class TestExporter final : public LogExporter

// Stores the names of the log records this exporter receives to an internal list
ExportResult Export(
const opentelemetry::nostd::span<std::unique_ptr<LogRecord>> &records) noexcept override
const opentelemetry::nostd::span<std::shared_ptr<LogRecord>> &records) noexcept override
{
*batch_size_received = records.size();
for (auto &record : records)
Expand Down Expand Up @@ -66,12 +66,12 @@ TEST(SimpleLogProcessorTest, SendReceivedLogsToExporter)
const int num_logs = 5;
for (int i = 0; i < num_logs; i++)
{
auto record = std::unique_ptr<LogRecord>(new LogRecord());
auto record = std::shared_ptr<LogRecord>(new LogRecord());
std::string s("Log name");
s += std::to_string(i);
record->name = s;

processor.OnReceive(std::move(record));
processor.OnReceive(record);

// Verify that the batch of 1 log record sent by processor matches what exporter received
EXPECT_EQ(1, batch_size_received);
Expand Down Expand Up @@ -116,7 +116,7 @@ class FailShutDownExporter final : public LogExporter
FailShutDownExporter() {}

ExportResult Export(
const opentelemetry::nostd::span<std::unique_ptr<LogRecord>> &records) noexcept override
const opentelemetry::nostd::span<std::shared_ptr<LogRecord>> &records) noexcept override
{
return ExportResult::kSuccess;
}
Expand Down