Skip to content
Open
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
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ project(YDB-CPP-SDK VERSION ${YDB_SDK_VERSION} LANGUAGES C CXX ASM)
option(YDB_SDK_INSTALL "Install YDB C++ SDK" Off)
option(YDB_SDK_TESTS "Build YDB C++ SDK tests" Off)
option(YDB_SDK_EXAMPLES "Build YDB C++ SDK examples" On)
option(YDB_SDK_ENABLE_OTEL_METRICS "Build OpenTelemetry metrics plugin" Off)
option(YDB_SDK_ENABLE_OTEL_TRACE "Build OpenTelemetry trace plugin" Off)
set(YDB_SDK_GOOGLE_COMMON_PROTOS_TARGET "" CACHE STRING "Name of cmake target preparing google common proto library")
option(YDB_SDK_USE_RAPID_JSON "Search for rapid json library in system" ON)

Expand Down Expand Up @@ -58,6 +60,7 @@ add_subdirectory(library/cpp)
add_subdirectory(include/ydb-cpp-sdk/client)
add_subdirectory(src)
add_subdirectory(util)
add_subdirectory(plugins)

#_ydb_sdk_validate_public_headers()

Expand Down
5 changes: 5 additions & 0 deletions cmake/external_libs.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ find_package(Brotli 1.1.0 REQUIRED)
find_package(jwt-cpp REQUIRED)
find_package(double-conversion REQUIRED)

# OpenTelemetry
if (YDB_SDK_ENABLE_OTEL_METRICS OR YDB_SDK_ENABLE_OTEL_TRACE)
find_package(opentelemetry-cpp REQUIRED)
endif()

# RapidJSON
if (YDB_SDK_USE_RAPID_JSON)
find_package(RapidJSON REQUIRED)
Expand Down
8 changes: 8 additions & 0 deletions include/ydb-cpp-sdk/client/driver/driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#include "fwd.h"

#include <ydb-cpp-sdk/client/common_client/settings.h>
#include <ydb-cpp-sdk/client/metrics/metrics.h>
#include <ydb-cpp-sdk/client/trace/trace.h>
#include <ydb-cpp-sdk/client/types/status_codes.h>
#include <ydb-cpp-sdk/client/types/credentials/credentials.h>
#include <ydb-cpp-sdk/client/types/fatal_error_handlers/handlers.h>
Expand Down Expand Up @@ -153,6 +155,12 @@ class TDriverConfig {
//! If not set, default executor will be used.
TDriverConfig& SetExecutor(std::shared_ptr<IExecutor> executor);

//! Set external metrics registry implementation.
TDriverConfig& SetMetricRegistry(std::shared_ptr<NMetrics::IMetricRegistry> registry);

//! Set external trace provider implementation.
TDriverConfig& SetTraceProvider(std::shared_ptr<NTrace::ITraceProvider> provider);

private:
class TImpl;
std::shared_ptr<TImpl> Impl_;
Expand Down
57 changes: 57 additions & 0 deletions include/ydb-cpp-sdk/client/metrics/metrics.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#pragma once

#include <cstdint>
#include <map>
#include <memory>
#include <string>
#include <vector>

namespace NYdb::inline V3::NMetrics {

using TLabels = std::map<std::string, std::string>;

class ICounter {
public:
virtual ~ICounter() = default;
virtual void Inc() = 0;
};

class IGauge {
public:
virtual ~IGauge() = default;
virtual void Add(double delta) = 0;
virtual void Set(double value) = 0;
};

class IHistogram {
public:
virtual ~IHistogram() = default;
virtual void Record(double value) = 0;
};

class IMetricRegistry {
public:
virtual ~IMetricRegistry() = default;

virtual std::shared_ptr<ICounter> Counter(
const std::string& name,
const TLabels& labels = {},
const std::string& description = {},
const std::string& unit = {}
) = 0;
virtual std::shared_ptr<IGauge> Gauge(
const std::string& name,
const TLabels& labels = {},
const std::string& description = {},
const std::string& unit = {}
) = 0;
virtual std::shared_ptr<IHistogram> Histogram(
const std::string& name,
const std::vector<double>& buckets,
const TLabels& labels = {},
const std::string& description = {},
const std::string& unit = {}
) = 0;
};

} // namespace NYdb::NMetrics
39 changes: 39 additions & 0 deletions include/ydb-cpp-sdk/client/trace/trace.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#pragma once

#include <cstdint>
#include <map>
#include <memory>
#include <string>

namespace NYdb::inline V3::NTrace {

enum class ESpanKind {
INTERNAL,
SERVER,
CLIENT,
PRODUCER,
CONSUMER
};

class ISpan {
public:
virtual ~ISpan() = default;
virtual void End() = 0;
virtual void SetAttribute(const std::string& key, const std::string& value) = 0;
virtual void SetAttribute(const std::string& key, int64_t value) = 0;
virtual void AddEvent(const std::string& name, const std::map<std::string, std::string>& attributes = {}) = 0;
};

class ITracer {
public:
virtual ~ITracer() = default;
virtual std::shared_ptr<ISpan> StartSpan(const std::string& name, ESpanKind kind = ESpanKind::INTERNAL) = 0;
};

class ITraceProvider {
public:
virtual ~ITraceProvider() = default;
virtual std::shared_ptr<ITracer> GetTracer(const std::string& name) = 0;
};

} // namespace NYdb::NTrace
2 changes: 2 additions & 0 deletions plugins/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
add_subdirectory(metrics)
add_subdirectory(trace)
3 changes: 3 additions & 0 deletions plugins/metrics/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
if (YDB_SDK_ENABLE_OTEL_METRICS)
add_subdirectory(otel EXCLUDE_FROM_ALL)
endif()
17 changes: 17 additions & 0 deletions plugins/metrics/otel/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
_ydb_sdk_add_library(open_telemetry_metrics)
target_sources(open_telemetry_metrics PRIVATE
src/metrics.cpp
)
target_include_directories(open_telemetry_metrics PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)
target_link_libraries(open_telemetry_metrics PUBLIC
client-metrics
client-resources
opentelemetry-cpp::api
opentelemetry-cpp::metrics
)
_ydb_sdk_make_client_component(OpenTelemetryMetrics open_telemetry_metrics)

_ydb_sdk_install_headers(${CMAKE_INSTALL_INCLUDEDIR} DIRECTORY include/)
16 changes: 16 additions & 0 deletions plugins/metrics/otel/include/ydb-cpp-sdk/open_telemetry/metrics.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#pragma once

#include <ydb-cpp-sdk/client/metrics/metrics.h>

#include <opentelemetry/nostd/shared_ptr.h>

namespace opentelemetry::metrics {
class MeterProvider;
}

namespace NYdb::inline V3::NMetrics {

std::shared_ptr<IMetricRegistry> CreateOtelMetricRegistry(
opentelemetry::nostd::shared_ptr<opentelemetry::metrics::MeterProvider> meterProvider);

} // namespace NYdb::NMetrics
169 changes: 169 additions & 0 deletions plugins/metrics/otel/src/metrics.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
#include <ydb-cpp-sdk/open_telemetry/metrics.h>
#include <ydb-cpp-sdk/client/resources/ydb_resources.h>

#include <opentelemetry/common/key_value_iterable_view.h>
#include <opentelemetry/context/runtime_context.h>
#include <opentelemetry/metrics/meter.h>
#include <opentelemetry/metrics/meter_provider.h>
#include <opentelemetry/metrics/sync_instruments.h>
#include <opentelemetry/sdk/metrics/meter_context.h>
#include <opentelemetry/sdk/metrics/meter_provider.h>

namespace NYdb::inline V3::NMetrics {

namespace {

using namespace opentelemetry;

common::KeyValueIterableView<TLabels> MakeAttributes(const TLabels& labels) {
return common::KeyValueIterableView<TLabels>(labels);
}

class TOtelCounter : public ICounter {
public:
TOtelCounter(nostd::shared_ptr<metrics::Counter<uint64_t>> counter, const TLabels& labels)
: Counter_(std::move(counter))
, Labels_(labels)
{}

void Inc() override {
Counter_->Add(1, MakeAttributes(Labels_), context::RuntimeContext::GetCurrent());
}

private:
nostd::shared_ptr<metrics::Counter<uint64_t>> Counter_;
TLabels Labels_;
};

class TOtelUpDownCounterGauge : public IGauge {
public:
TOtelUpDownCounterGauge(nostd::shared_ptr<metrics::UpDownCounter<double>> counter, const TLabels& labels)
: Counter_(std::move(counter))
, Labels_(labels)
{}

void Add(double delta) override {
Counter_->Add(delta, MakeAttributes(Labels_), context::RuntimeContext::GetCurrent());
Value_ += delta;
}

void Set(double value) override {
Counter_->Add(value - Value_, MakeAttributes(Labels_), context::RuntimeContext::GetCurrent());
Value_ = value;
}

private:
nostd::shared_ptr<metrics::UpDownCounter<double>> Counter_;
TLabels Labels_;
double Value_ = 0;
};

class TOtelHistogram : public IHistogram {
public:
TOtelHistogram(nostd::shared_ptr<metrics::Histogram<double>> histogram, const TLabels& labels)
: Histogram_(std::move(histogram))
, Labels_(labels)
{}

void Record(double value) override {
Histogram_->Record(value, MakeAttributes(Labels_), context::RuntimeContext::GetCurrent());
}

private:
nostd::shared_ptr<metrics::Histogram<double>> Histogram_;
TLabels Labels_;
};

class TOtelMetricRegistry : public IMetricRegistry {
public:
TOtelMetricRegistry(nostd::shared_ptr<metrics::MeterProvider> meterProvider)
: MeterProvider_(std::move(meterProvider))
, Meter_(MeterProvider_->GetMeter("ydb-cpp-sdk", GetSdkSemver()))
{}

std::shared_ptr<ICounter> Counter(const std::string& name
, const TLabels& labels
, const std::string& description
, const std::string& unit
) override {
auto counter = Meter_->CreateUInt64Counter(name, description, unit);
return std::make_shared<TOtelCounter>(std::move(counter), labels);
}

std::shared_ptr<IGauge> Gauge(const std::string& name
, const TLabels& labels
, const std::string& description
, const std::string& unit
) override {
auto counter = Meter_->CreateDoubleUpDownCounter(name, description, unit);
return std::make_shared<TOtelUpDownCounterGauge>(std::move(counter), labels);
}

std::shared_ptr<IHistogram> Histogram(const std::string& name
, const std::vector<double>& buckets
, const TLabels& labels
, const std::string& description
, const std::string& unit
) override {
ConfigureHistogramBuckets(name, unit, buckets);
auto histogram = Meter_->CreateDoubleHistogram(name, description, unit);
return std::make_shared<TOtelHistogram>(std::move(histogram), labels);
}

private:
void ConfigureHistogramBuckets(const std::string& name, const std::string& unit, const std::vector<double>& buckets) {
if (buckets.empty()) {
return;
}

auto* sdkProvider = dynamic_cast<sdk::metrics::MeterProvider*>(MeterProvider_.get());
if (!sdkProvider) {
return;
}

{
std::lock_guard lock(HistogramViewsLock_);
if (!HistogramViews_.insert(name).second) {
return;
}
}

auto selector = std::make_unique<sdk::metrics::InstrumentSelector>(
sdk::metrics::InstrumentType::kHistogram,
name,
unit
);
auto meterSelector = std::make_unique<sdk::metrics::MeterSelector>(
"ydb-cpp-sdk",
GetSdkSemver(),
{}
);

auto histogramConfig = std::make_shared<sdk::metrics::HistogramAggregationConfig>();
histogramConfig->boundaries_ = buckets;

auto view = std::make_unique<sdk::metrics::View>(
{},
{},
sdk::metrics::AggregationType::kHistogram,
histogramConfig
);

sdkProvider->AddView(std::move(selector), std::move(meterSelector), std::move(view));
}

nostd::shared_ptr<metrics::MeterProvider> MeterProvider_;
nostd::shared_ptr<metrics::Meter> Meter_;
std::mutex HistogramViewsLock_;
std::unordered_set<std::string> HistogramViews_;
};

} // namespace

std::shared_ptr<IMetricRegistry> CreateOtelMetricRegistry(
opentelemetry::nostd::shared_ptr<opentelemetry::metrics::MeterProvider> meterProvider)
{
return std::make_shared<TOtelMetricRegistry>(std::move(meterProvider));
}

} // namespace NYdb::NMetrics
3 changes: 3 additions & 0 deletions plugins/trace/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
if (YDB_SDK_ENABLE_OTEL_TRACE)
add_subdirectory(otel EXCLUDE_FROM_ALL)
endif()
16 changes: 16 additions & 0 deletions plugins/trace/otel/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
_ydb_sdk_add_library(open_telemetry_trace)
target_sources(open_telemetry_trace PRIVATE
src/trace.cpp
)
target_include_directories(open_telemetry_trace PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)
target_link_libraries(open_telemetry_trace PUBLIC
client-trace
opentelemetry-cpp::api
opentelemetry-cpp::trace
)
_ydb_sdk_make_client_component(OpenTelemetryTrace open_telemetry_trace)

_ydb_sdk_install_headers(${CMAKE_INSTALL_INCLUDEDIR} DIRECTORY include/)
16 changes: 16 additions & 0 deletions plugins/trace/otel/include/ydb-cpp-sdk/open_telemetry/trace.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#pragma once

#include <ydb-cpp-sdk/client/trace/trace.h>

#include <opentelemetry/nostd/shared_ptr.h>

namespace opentelemetry::trace {
class TracerProvider;
}

namespace NYdb::inline V3::NTrace {

std::shared_ptr<ITraceProvider> CreateOtelTraceProvider(
opentelemetry::nostd::shared_ptr<opentelemetry::trace::TracerProvider> tracerProvider);

} // namespace NYdb::NTrace
Loading
Loading