From e29cb410024b8a0507ce1a728e4a64f8816b188f Mon Sep 17 00:00:00 2001 From: Zarina Tlupova <96023685+zarinatlupova@users.noreply.github.com> Date: Sat, 31 May 2025 08:47:46 +0300 Subject: [PATCH 01/12] Create tracing_example.cpp --- examples/tracing/tracing_example.cpp | 29 ++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 examples/tracing/tracing_example.cpp diff --git a/examples/tracing/tracing_example.cpp b/examples/tracing/tracing_example.cpp new file mode 100644 index 0000000000..c28729f49a --- /dev/null +++ b/examples/tracing/tracing_example.cpp @@ -0,0 +1,29 @@ +#include +#include +#include +#include + +int main() { + // 1. Настройка OpenTelemetry с экспортером в Jaeger + auto exporter = opentelemetry::exporter::jaeger::JaegerExporterFactory::Create(); + auto provider = opentelemetry::sdk::trace::TracerProviderFactory::Create(std::move(exporter)); + auto otel_tracer = provider->GetTracer("ydb-cpp-sdk"); + + // 2. Создание адаптера для YDB SDK + auto ydb_tracer = std::make_shared(otel_tracer); + + // 3. Инициализация драйвера YDB с трейсером + auto driver = NYdb::TDriver( + NYdb::TDriverConfig() + .SetEndpoint("grpc://localhost:2136") + .SetDatabase("/local") + .SetTracer(ydb_tracer) + ); + + // 4. Тестовый запрос (спан создастся автоматически внутри SDK) + auto client = NYdb::NTable::TTableClient(driver); + auto session = client.CreateSession().GetValueSync(); + session.ExecuteDataQuery("SELECT 1", NYdb::NTable::TTxControl::BeginTx().CommitTx()).GetValueSync(); + + return 0; +} From 607fd1cdcd82ca3f312231be3b720b00304fe869 Mon Sep 17 00:00:00 2001 From: Zarina Tlupova <96023685+zarinatlupova@users.noreply.github.com> Date: Sat, 31 May 2025 08:49:23 +0300 Subject: [PATCH 02/12] Update CMakeLists.txt --- examples/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 97119cff5e..f98ec530f4 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -4,5 +4,6 @@ add_subdirectory(pagination) add_subdirectory(secondary_index) add_subdirectory(secondary_index_builtin) add_subdirectory(topic_reader) +add_subdirectory(tracing) add_subdirectory(ttl) add_subdirectory(vector_index) From e5af77fee3f1fefa520e6299a2e4ccbf19ac2a3f Mon Sep 17 00:00:00 2001 From: Zarina Tlupova <96023685+zarinatlupova@users.noreply.github.com> Date: Sat, 31 May 2025 08:52:01 +0300 Subject: [PATCH 03/12] Create tracer.h --- include/ydb-cpp-sdk/client/tracing/tracer.h | 25 +++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 include/ydb-cpp-sdk/client/tracing/tracer.h diff --git a/include/ydb-cpp-sdk/client/tracing/tracer.h b/include/ydb-cpp-sdk/client/tracing/tracer.h new file mode 100644 index 0000000000..61508210ec --- /dev/null +++ b/include/ydb-cpp-sdk/client/tracing/tracer.h @@ -0,0 +1,25 @@ +#pragma once + +#include +#include + +namespace NYdb::inline V3 { +namespace NTracing { + +class ISpan { +public: + virtual ~ISpan() = default; + + virtual void AddAttribute(const std::string& key, const std::string& value) = 0; + virtual void End() = 0; +}; + +class ITracer { +public: + virtual ~ITracer() = default; + + virtual std::unique_ptr StartSpan(const std::string& name) = 0; +}; + +} // namespace NTracing +} // namespace NYdb From fad89b4488a58b032a49f55407cd2f92c4a8ca63 Mon Sep 17 00:00:00 2001 From: Zarina Tlupova <96023685+zarinatlupova@users.noreply.github.com> Date: Sat, 31 May 2025 08:54:03 +0300 Subject: [PATCH 04/12] Create otel_tracer.h --- .../ydb-cpp-sdk/client/tracing/otel_tracer.h | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 include/ydb-cpp-sdk/client/tracing/otel_tracer.h diff --git a/include/ydb-cpp-sdk/client/tracing/otel_tracer.h b/include/ydb-cpp-sdk/client/tracing/otel_tracer.h new file mode 100644 index 0000000000..1b9ef7eaa7 --- /dev/null +++ b/include/ydb-cpp-sdk/client/tracing/otel_tracer.h @@ -0,0 +1,50 @@ +#pragma once + +#include +#include +#include +#include + +namespace NYdb::inline V3 { +namespace NTracing { + + class TOpenTelemetrySpan : public ISpan { + public: + explicit TOpenTelemetrySpan(opentelemetry::nostd::shared_ptr span) + : Span_(std::move(span)) {} + + void AddAttribute(const std::string& key, const std::string& value) override { + if (Span_) { + Span_->SetAttribute(key, value); + } + } + + void End() override { + if (Span_) { + Span_->End(); + } + } + + private: + opentelemetry::nostd::shared_ptr Span_; + }; + + class TOpenTelemetryTracer : public ITracer { + public: + explicit TOpenTelemetryTracer(opentelemetry::nostd::shared_ptr tracer) + : Tracer_(std::move(tracer)) {} + + std::unique_ptr StartSpan(const std::string& name) override { + if (!Tracer_) { + return nullptr; + } + auto span = Tracer_->StartSpan(name); + return std::make_unique(std::move(span)); + } + + private: + opentelemetry::nostd::shared_ptr Tracer_; + }; + +} // namespace NTracing +} // namespace NYdb From cbaf74e63db4232f0311e95f9fb0f7f75ede400a Mon Sep 17 00:00:00 2001 From: Zarina Tlupova <96023685+zarinatlupova@users.noreply.github.com> Date: Sat, 31 May 2025 08:54:58 +0300 Subject: [PATCH 05/12] Create noop_tracer.h --- .../ydb-cpp-sdk/client/tracing/noop_tracer.h | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 include/ydb-cpp-sdk/client/tracing/noop_tracer.h diff --git a/include/ydb-cpp-sdk/client/tracing/noop_tracer.h b/include/ydb-cpp-sdk/client/tracing/noop_tracer.h new file mode 100644 index 0000000000..4d4999b34a --- /dev/null +++ b/include/ydb-cpp-sdk/client/tracing/noop_tracer.h @@ -0,0 +1,22 @@ +#pragma once + +#include + +namespace NYdb::inline V3 { +namespace NTracing { + +class TNoopSpan : public ISpan { +public: + void AddAttribute(const std::string&, const std::string&) override {} + void End() override {} +}; + +class TNoopTracer : public ITracer { +public: + std::unique_ptr StartSpan(const std::string&) override { + return std::make_unique(); + } +}; + +} // namespace NTracing +} // namespace NYdb From 2d2ae1a91af5f2049107aeb807d869ea2984e463 Mon Sep 17 00:00:00 2001 From: Zarina Tlupova <96023685+zarinatlupova@users.noreply.github.com> Date: Sat, 31 May 2025 08:56:52 +0300 Subject: [PATCH 06/12] Update driver.h --- include/ydb-cpp-sdk/client/driver/driver.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/ydb-cpp-sdk/client/driver/driver.h b/include/ydb-cpp-sdk/client/driver/driver.h index c934c422cb..98e13dd440 100644 --- a/include/ydb-cpp-sdk/client/driver/driver.h +++ b/include/ydb-cpp-sdk/client/driver/driver.h @@ -118,6 +118,8 @@ class TDriverConfig { //! Log backend. TDriverConfig& SetLog(std::unique_ptr&& log); + + TDriverConfig& SetTracer(std::shared_ptr tracer); private: class TImpl; std::shared_ptr Impl_; From 4bcac3b3a1c6076977f9f03df0d73da4c715d729 Mon Sep 17 00:00:00 2001 From: Zarina Tlupova <96023685+zarinatlupova@users.noreply.github.com> Date: Sat, 31 May 2025 08:58:36 +0300 Subject: [PATCH 07/12] Update request_settings.h --- include/ydb-cpp-sdk/client/types/request_settings.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/ydb-cpp-sdk/client/types/request_settings.h b/include/ydb-cpp-sdk/client/types/request_settings.h index 2f2d4dca8a..8d481726e3 100644 --- a/include/ydb-cpp-sdk/client/types/request_settings.h +++ b/include/ydb-cpp-sdk/client/types/request_settings.h @@ -8,6 +8,7 @@ #include #include +#include namespace NYdb::inline V3 { @@ -20,6 +21,7 @@ struct TRequestSettings { FLUENT_SETTING(std::string, RequestType); FLUENT_SETTING(THeader, Header); FLUENT_SETTING(TDuration, ClientTimeout); + FLUENT_SETTING(std::string, TraceParent); TRequestSettings() = default; @@ -29,6 +31,7 @@ struct TRequestSettings { , RequestType_(other.RequestType_) , Header_(other.Header_) , ClientTimeout_(other.ClientTimeout_) + , TraceParent_(other.TraceParent_) {} }; From 4bba95b7ac278dc6ae7d890f14eb44e43b67d64a Mon Sep 17 00:00:00 2001 From: Zarina Tlupova <96023685+zarinatlupova@users.noreply.github.com> Date: Sat, 31 May 2025 09:01:37 +0300 Subject: [PATCH 08/12] Update grpc_connections.h --- .../grpc_connections/grpc_connections.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/client/impl/ydb_internal/grpc_connections/grpc_connections.h b/src/client/impl/ydb_internal/grpc_connections/grpc_connections.h index db777210ca..9171a2776d 100644 --- a/src/client/impl/ydb_internal/grpc_connections/grpc_connections.h +++ b/src/client/impl/ydb_internal/grpc_connections/grpc_connections.h @@ -181,6 +181,11 @@ class TGRpcConnectionsImpl TCallMeta meta; meta.Timeout = requestSettings.ClientTimeout; + + if (!requestSettings.TraceParent.empty()) { + meta.Aux.emplace_back({"traceparent", requestSettings.TraceParent}); + } + #ifndef YDB_GRPC_UNSECURE_AUTH meta.CallCredentials = dbState->CallCredentials; #else @@ -415,6 +420,11 @@ class TGRpcConnectionsImpl TCallMeta meta; meta.Timeout = requestSettings.ClientTimeout; + + if (!requestSettings.TraceParent.empty()) { + meta.Aux.emplace_back({"traceparent", requestSettings.TraceParent}); + } + #ifndef YDB_GRPC_UNSECURE_AUTH meta.CallCredentials = dbState->CallCredentials; #else @@ -509,6 +519,11 @@ class TGRpcConnectionsImpl } TCallMeta meta; + + if (!requestSettings.TraceParent.empty()) { + meta.Aux.emplace_back({"traceparent", requestSettings.TraceParent}); + } + #ifndef YDB_GRPC_UNSECURE_AUTH meta.CallCredentials = dbState->CallCredentials; #else From 84046f1f3835e561670972b001ae567165d5790f Mon Sep 17 00:00:00 2001 From: Zarina Tlupova <96023685+zarinatlupova@users.noreply.github.com> Date: Sat, 31 May 2025 09:04:30 +0300 Subject: [PATCH 09/12] Update compose.yml --- .devcontainer/compose.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.devcontainer/compose.yml b/.devcontainer/compose.yml index f896916862..9a1ccec4fa 100644 --- a/.devcontainer/compose.yml +++ b/.devcontainer/compose.yml @@ -8,6 +8,15 @@ volumes: ydb-certs: services: + jaeger: + image: jaegertracing/all-in-one:1.51.0 + ports: + - "16686:16686" # Jaeger UI frontend + - "4317:4317" # gRPC port for accepts traces in OpenTelemetry OTLP format + - "4318:4318" # HTTP port for accepts traces in OpenTelemetry OTLP format + environment: + - COLLECTOR_OTLP_ENABLED=true + sdk: platform: linux/amd64 From b2f90e179163ee6d2ec8e1d14ded2270a57b1c6d Mon Sep 17 00:00:00 2001 From: Zarina Tlupova <96023685+zarinatlupova@users.noreply.github.com> Date: Sat, 31 May 2025 12:15:28 +0300 Subject: [PATCH 10/12] Update tracer.h --- include/ydb-cpp-sdk/client/tracing/tracer.h | 58 +++++++++++++++++++-- 1 file changed, 55 insertions(+), 3 deletions(-) diff --git a/include/ydb-cpp-sdk/client/tracing/tracer.h b/include/ydb-cpp-sdk/client/tracing/tracer.h index 61508210ec..393c71668f 100644 --- a/include/ydb-cpp-sdk/client/tracing/tracer.h +++ b/include/ydb-cpp-sdk/client/tracing/tracer.h @@ -1,24 +1,76 @@ #pragma once -#include #include +#include +#include -namespace NYdb::inline V3 { +namespace NYdb { namespace NTracing { +using TAttributeMap = std::unordered_map; + +// Контекст с идентификаторами трассировки +class TTraceContext { +public: + TTraceContext(std::string traceId, std::string spanId, std::string parentSpanId = "") + : TraceId_(std::move(traceId)) + , SpanId_(std::move(spanId)) + , ParentSpanId_(std::move(parentSpanId)) + {} + + const std::string& GetTraceId() const { return TraceId_; } + const std::string& GetSpanId() const { return SpanId_; } + const std::string& GetParentSpanId() const { return ParentSpanId_; } + + // Генерация нового контекста (создает новые уникальные traceId и spanId) + static std::shared_ptr GenerateNew(); + + // Создание дочернего контекста (новый spanId, тот же traceId) + std::shared_ptr CreateChild() const; + + // Формирование W3C traceparent ("00-traceId-spanId-01") + std::string ToTraceParent() const; + +private: + std::string TraceId_; + std::string SpanId_; + std::string ParentSpanId_; +}; + + class ISpan { public: virtual ~ISpan() = default; virtual void AddAttribute(const std::string& key, const std::string& value) = 0; + virtual void AddEvent(const std::string& name, const TAttributeMap& attributes = {}) = 0; + virtual void SetStatus(bool isError, const std::string& description = "") = 0; virtual void End() = 0; + + virtual const TTraceContext& GetContext() const = 0; }; + class ITracer { public: virtual ~ITracer() = default; - virtual std::unique_ptr StartSpan(const std::string& name) = 0; + // Создать новый спан с именем, атрибутами и опциональным родительским контекстом + virtual std::unique_ptr StartSpan( + const std::string& name, + const TAttributeMap& attributes = {}, + std::shared_ptr parentContext = nullptr) = 0; + + // Получить текущий контекст + virtual std::shared_ptr GetCurrentContext() const = 0; + + // Получить W3C traceparent текущего контекста (если есть) + virtual std::string GetCurrentTraceParent() const { + if (auto ctx = GetCurrentContext()) { + return ctx->ToTraceParent(); + } + return ""; + } }; } // namespace NTracing From 88690b0427336584ac1900d167ba5439705794f9 Mon Sep 17 00:00:00 2001 From: Zarina Tlupova <96023685+zarinatlupova@users.noreply.github.com> Date: Sat, 31 May 2025 12:17:06 +0300 Subject: [PATCH 11/12] Update otel_tracer.h --- .../ydb-cpp-sdk/client/tracing/otel_tracer.h | 122 +++++++++++++----- 1 file changed, 89 insertions(+), 33 deletions(-) diff --git a/include/ydb-cpp-sdk/client/tracing/otel_tracer.h b/include/ydb-cpp-sdk/client/tracing/otel_tracer.h index 1b9ef7eaa7..07eb9d277e 100644 --- a/include/ydb-cpp-sdk/client/tracing/otel_tracer.h +++ b/include/ydb-cpp-sdk/client/tracing/otel_tracer.h @@ -1,50 +1,106 @@ #pragma once -#include +#include "tracer.h" + #include #include -#include +#include +#include +#include -namespace NYdb::inline V3 { +namespace NYdb { namespace NTracing { - class TOpenTelemetrySpan : public ISpan { - public: - explicit TOpenTelemetrySpan(opentelemetry::nostd::shared_ptr span) - : Span_(std::move(span)) {} +class OpenTelemetrySpan : public ISpan { +public: + OpenTelemetrySpan(opentelemetry::trace::Span span, std::shared_ptr context) + : span_(std::move(span)), context_(std::move(context)) {} + + void AddAttribute(const std::string& key, const std::string& value) override { + span_.SetAttribute(key, value); + } - void AddAttribute(const std::string& key, const std::string& value) override { - if (Span_) { - Span_->SetAttribute(key, value); - } + void AddEvent(const std::string& name, const TAttributeMap& attributes = {}) override { + // Преобразуем std::unordered_map в вектор KeyValue для OpenTelemetry + std::vector otelAttributes; + otelAttributes.reserve(attributes.size()); + for (const auto& [k, v] : attributes) { + otelAttributes.emplace_back(k, v); } + span_.AddEvent(name, otelAttributes); + } + + void SetStatus(bool isError, const std::string& description = "") override { + span_.SetStatus(isError ? opentelemetry::trace::StatusCode::kError + : opentelemetry::trace::StatusCode::kOk, + description); + } + + void End() override { + span_.End(); + } + + const TTraceContext& GetContext() const override { + return *context_; + } + +private: + opentelemetry::trace::Span span_; + std::shared_ptr context_; +}; + + +class OpenTelemetryTracer : public ITracer { +public: + explicit OpenTelemetryTracer(std::shared_ptr tracer) + : tracer_(std::move(tracer)) {} - void End() override { - if (Span_) { - Span_->End(); - } + std::unique_ptr StartSpan( + const std::string& name, + const TAttributeMap& attributes = {}, + std::shared_ptr parentContext = nullptr + ) override { + opentelemetry::context::Context otelContext; + + if (parentContext) { + auto traceId = opentelemetry::trace::TraceId::FromHex(parentContext->GetTraceId()); + auto spanId = opentelemetry::trace::SpanId::FromHex(parentContext->GetSpanId()); + + auto spanContext = opentelemetry::trace::SpanContext::Create( + traceId, + spanId, + opentelemetry::trace::TraceFlags::kIsSampled, + false // remote + ); + + otelContext = opentelemetry::context::Context{}.SetValue( + opentelemetry::trace::kSpanKey, + opentelemetry::trace::Span{spanContext}); } - private: - opentelemetry::nostd::shared_ptr Span_; - }; - - class TOpenTelemetryTracer : public ITracer { - public: - explicit TOpenTelemetryTracer(opentelemetry::nostd::shared_ptr tracer) - : Tracer_(std::move(tracer)) {} - - std::unique_ptr StartSpan(const std::string& name) override { - if (!Tracer_) { - return nullptr; - } - auto span = Tracer_->StartSpan(name); - return std::make_unique(std::move(span)); + auto span = tracer_->StartSpan(name, attributes, otelContext); + + auto context = parentContext ? parentContext->CreateChild() : TTraceContext::GenerateNew(); + + return std::make_unique(std::move(span), std::move(context)); + } + + std::shared_ptr GetCurrentContext() const override { + auto currentSpan = opentelemetry::trace::GetCurrentSpan(); + if (!currentSpan.IsValid()) { + return nullptr; } + auto spanContext = currentSpan.GetContext(); + + return std::make_shared( + spanContext.trace_id().ToHex(), + spanContext.span_id().ToHex(), + spanContext.IsValid() ? spanContext.trace_id().ToHex() : ""); + } - private: - opentelemetry::nostd::shared_ptr Tracer_; - }; +private: + std::shared_ptr tracer_; +}; } // namespace NTracing } // namespace NYdb From b49fd2dc3c500feb9e6b7cafc28d8e7d3821cb4b Mon Sep 17 00:00:00 2001 From: user2 Date: Thu, 5 Jun 2025 14:42:51 +0300 Subject: [PATCH 12/12] Support tracing in SDK --- CMakeLists.txt | 2 + cmake/external_libs.cmake | 7 +- examples/tracing/CMakeLists.txt | 11 ++ examples/tracing/tracing_example.cpp | 12 +- include/ydb-cpp-sdk/client/driver/driver.h | 1 + .../ydb-cpp-sdk/client/tracing/noop_tracer.h | 22 ---- .../ydb-cpp-sdk/client/tracing/otel_tracer.h | 106 --------------- include/ydb-cpp-sdk/client/tracing/tracer.h | 9 -- src/client/driver/driver.cpp | 6 + src/client/tracing/noop_tracer.h | 37 ++++++ src/client/tracing/otel_tracer.h | 123 ++++++++++++++++++ src/client/tracing/tracer.cpp | 44 +++++++ 12 files changed, 234 insertions(+), 146 deletions(-) create mode 100644 examples/tracing/CMakeLists.txt delete mode 100644 include/ydb-cpp-sdk/client/tracing/noop_tracer.h delete mode 100644 include/ydb-cpp-sdk/client/tracing/otel_tracer.h create mode 100644 src/client/tracing/noop_tracer.h create mode 100644 src/client/tracing/otel_tracer.h create mode 100644 src/client/tracing/tracer.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index a1e8a38f64..7fb60db6fc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,6 +7,8 @@ option(YDB_SDK_EXAMPLES "Build YDB C++ SDK examples" On) 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) +option(YDB_SDK_TRACING "Enable tracing support" ON) + set(BUILD_SHARED_LIBS Off) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED On) diff --git a/cmake/external_libs.cmake b/cmake/external_libs.cmake index c258dea642..b788604971 100644 --- a/cmake/external_libs.cmake +++ b/cmake/external_libs.cmake @@ -15,6 +15,11 @@ find_package(jwt-cpp REQUIRED) find_package(GTest REQUIRED) find_package(double-conversion REQUIRED) +# OpenTelemetry +if(YDB_SDK_TRACING) + find_package(opentelemetry-cpp REQUIRED) +endif() + # RapidJSON if (YDB_SDK_USE_RAPID_JSON) find_package(RapidJSON REQUIRED) @@ -85,4 +90,4 @@ target_include_directories(nayuki_md5 PUBLIC $ ) -_ydb_sdk_install_targets(TARGETS nayuki_md5) +_ydb_sdk_install_targets(TARGETS nayuki_md5) \ No newline at end of file diff --git a/examples/tracing/CMakeLists.txt b/examples/tracing/CMakeLists.txt new file mode 100644 index 0000000000..7473f4ecb9 --- /dev/null +++ b/examples/tracing/CMakeLists.txt @@ -0,0 +1,11 @@ +add_executable(tracing_example tracing_example.cpp) + +if(YDB_SDK_TRACING) + target_link_libraries(tracing_example PRIVATE + ydb-cpp-sdk + ${OPENTELEMETRY_LIBRARIES} + ) +else() + target_link_libraries(tracing_example PRIVATE ydb-cpp-sdk) + target_compile_definitions(tracing_example PRIVATE -DYDB_SDK_TRACING_DISABLED) +endif() \ No newline at end of file diff --git a/examples/tracing/tracing_example.cpp b/examples/tracing/tracing_example.cpp index c28729f49a..4f36220b8b 100644 --- a/examples/tracing/tracing_example.cpp +++ b/examples/tracing/tracing_example.cpp @@ -4,23 +4,19 @@ #include int main() { - // 1. Настройка OpenTelemetry с экспортером в Jaeger auto exporter = opentelemetry::exporter::jaeger::JaegerExporterFactory::Create(); auto provider = opentelemetry::sdk::trace::TracerProviderFactory::Create(std::move(exporter)); - auto otel_tracer = provider->GetTracer("ydb-cpp-sdk"); + auto otelTracer = provider->GetTracer("ydb-cpp-sdk"); - // 2. Создание адаптера для YDB SDK - auto ydb_tracer = std::make_shared(otel_tracer); + auto ydbTracer = std::make_shared(otelTracer); - // 3. Инициализация драйвера YDB с трейсером auto driver = NYdb::TDriver( NYdb::TDriverConfig() - .SetEndpoint("grpc://localhost:2136") + .SetEndpoint("localhost:2136") .SetDatabase("/local") - .SetTracer(ydb_tracer) + .SetTracer(ydbTracer) ); - // 4. Тестовый запрос (спан создастся автоматически внутри SDK) auto client = NYdb::NTable::TTableClient(driver); auto session = client.CreateSession().GetValueSync(); session.ExecuteDataQuery("SELECT 1", NYdb::NTable::TTxControl::BeginTx().CommitTx()).GetValueSync(); diff --git a/include/ydb-cpp-sdk/client/driver/driver.h b/include/ydb-cpp-sdk/client/driver/driver.h index 98e13dd440..9fa14c06ae 100644 --- a/include/ydb-cpp-sdk/client/driver/driver.h +++ b/include/ydb-cpp-sdk/client/driver/driver.h @@ -8,6 +8,7 @@ #include #include #include +#include #include diff --git a/include/ydb-cpp-sdk/client/tracing/noop_tracer.h b/include/ydb-cpp-sdk/client/tracing/noop_tracer.h deleted file mode 100644 index 4d4999b34a..0000000000 --- a/include/ydb-cpp-sdk/client/tracing/noop_tracer.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include - -namespace NYdb::inline V3 { -namespace NTracing { - -class TNoopSpan : public ISpan { -public: - void AddAttribute(const std::string&, const std::string&) override {} - void End() override {} -}; - -class TNoopTracer : public ITracer { -public: - std::unique_ptr StartSpan(const std::string&) override { - return std::make_unique(); - } -}; - -} // namespace NTracing -} // namespace NYdb diff --git a/include/ydb-cpp-sdk/client/tracing/otel_tracer.h b/include/ydb-cpp-sdk/client/tracing/otel_tracer.h deleted file mode 100644 index 07eb9d277e..0000000000 --- a/include/ydb-cpp-sdk/client/tracing/otel_tracer.h +++ /dev/null @@ -1,106 +0,0 @@ -#pragma once - -#include "tracer.h" - -#include -#include -#include -#include -#include - -namespace NYdb { -namespace NTracing { - -class OpenTelemetrySpan : public ISpan { -public: - OpenTelemetrySpan(opentelemetry::trace::Span span, std::shared_ptr context) - : span_(std::move(span)), context_(std::move(context)) {} - - void AddAttribute(const std::string& key, const std::string& value) override { - span_.SetAttribute(key, value); - } - - void AddEvent(const std::string& name, const TAttributeMap& attributes = {}) override { - // Преобразуем std::unordered_map в вектор KeyValue для OpenTelemetry - std::vector otelAttributes; - otelAttributes.reserve(attributes.size()); - for (const auto& [k, v] : attributes) { - otelAttributes.emplace_back(k, v); - } - span_.AddEvent(name, otelAttributes); - } - - void SetStatus(bool isError, const std::string& description = "") override { - span_.SetStatus(isError ? opentelemetry::trace::StatusCode::kError - : opentelemetry::trace::StatusCode::kOk, - description); - } - - void End() override { - span_.End(); - } - - const TTraceContext& GetContext() const override { - return *context_; - } - -private: - opentelemetry::trace::Span span_; - std::shared_ptr context_; -}; - - -class OpenTelemetryTracer : public ITracer { -public: - explicit OpenTelemetryTracer(std::shared_ptr tracer) - : tracer_(std::move(tracer)) {} - - std::unique_ptr StartSpan( - const std::string& name, - const TAttributeMap& attributes = {}, - std::shared_ptr parentContext = nullptr - ) override { - opentelemetry::context::Context otelContext; - - if (parentContext) { - auto traceId = opentelemetry::trace::TraceId::FromHex(parentContext->GetTraceId()); - auto spanId = opentelemetry::trace::SpanId::FromHex(parentContext->GetSpanId()); - - auto spanContext = opentelemetry::trace::SpanContext::Create( - traceId, - spanId, - opentelemetry::trace::TraceFlags::kIsSampled, - false // remote - ); - - otelContext = opentelemetry::context::Context{}.SetValue( - opentelemetry::trace::kSpanKey, - opentelemetry::trace::Span{spanContext}); - } - - auto span = tracer_->StartSpan(name, attributes, otelContext); - - auto context = parentContext ? parentContext->CreateChild() : TTraceContext::GenerateNew(); - - return std::make_unique(std::move(span), std::move(context)); - } - - std::shared_ptr GetCurrentContext() const override { - auto currentSpan = opentelemetry::trace::GetCurrentSpan(); - if (!currentSpan.IsValid()) { - return nullptr; - } - auto spanContext = currentSpan.GetContext(); - - return std::make_shared( - spanContext.trace_id().ToHex(), - spanContext.span_id().ToHex(), - spanContext.IsValid() ? spanContext.trace_id().ToHex() : ""); - } - -private: - std::shared_ptr tracer_; -}; - -} // namespace NTracing -} // namespace NYdb diff --git a/include/ydb-cpp-sdk/client/tracing/tracer.h b/include/ydb-cpp-sdk/client/tracing/tracer.h index 393c71668f..3896c9685d 100644 --- a/include/ydb-cpp-sdk/client/tracing/tracer.h +++ b/include/ydb-cpp-sdk/client/tracing/tracer.h @@ -9,7 +9,6 @@ namespace NTracing { using TAttributeMap = std::unordered_map; -// Контекст с идентификаторами трассировки class TTraceContext { public: TTraceContext(std::string traceId, std::string spanId, std::string parentSpanId = "") @@ -22,13 +21,8 @@ class TTraceContext { const std::string& GetSpanId() const { return SpanId_; } const std::string& GetParentSpanId() const { return ParentSpanId_; } - // Генерация нового контекста (создает новые уникальные traceId и spanId) static std::shared_ptr GenerateNew(); - - // Создание дочернего контекста (новый spanId, тот же traceId) std::shared_ptr CreateChild() const; - - // Формирование W3C traceparent ("00-traceId-spanId-01") std::string ToTraceParent() const; private: @@ -55,16 +49,13 @@ class ITracer { public: virtual ~ITracer() = default; - // Создать новый спан с именем, атрибутами и опциональным родительским контекстом virtual std::unique_ptr StartSpan( const std::string& name, const TAttributeMap& attributes = {}, std::shared_ptr parentContext = nullptr) = 0; - // Получить текущий контекст virtual std::shared_ptr GetCurrentContext() const = 0; - // Получить W3C traceparent текущего контекста (если есть) virtual std::string GetCurrentTraceParent() const { if (auto ctx = GetCurrentContext()) { return ctx->ToTraceParent(); diff --git a/src/client/driver/driver.cpp b/src/client/driver/driver.cpp index 7596a1840a..f158561919 100644 --- a/src/client/driver/driver.cpp +++ b/src/client/driver/driver.cpp @@ -1,4 +1,5 @@ #include +#include #define INCLUDE_YDB_INTERNAL_H #include @@ -203,6 +204,11 @@ TDriverConfig& TDriverConfig::SetLog(std::unique_ptr&& log) { return *this; } +TDriverConfig& TDriverConfig::SetTracer(std::shared_ptr tracer) { + Impl_->Tracer_ = tracer ? tracer : std::make_shared(); + return *this; +} + //////////////////////////////////////////////////////////////////////////////// std::shared_ptr CreateInternalInterface(const TDriver connection) { diff --git a/src/client/tracing/noop_tracer.h b/src/client/tracing/noop_tracer.h new file mode 100644 index 0000000000..8169c81d94 --- /dev/null +++ b/src/client/tracing/noop_tracer.h @@ -0,0 +1,37 @@ +#pragma once + +#include + +namespace NYdb::inline V3 { +namespace NTracing { + + class TNoopSpan : public ISpan { + public: + void AddAttribute(const std::string&, const std::string&) override {} + void AddEvent(const std::string&, const TAttributeMap& = {}) override {} + void SetStatus(bool, const std::string& = "") override {} + void End() override {} + + const TTraceContext& GetContext() const override { + static TTraceContext emptyContext("", ""); + return emptyContext; + } + }; + + class TNoopTracer : public ITracer { + public: + std::unique_ptr StartSpan( + const std::string&, + const TAttributeMap& = {}, + std::shared_ptr = nullptr) override + { + return std::make_unique(); + } + + std::shared_ptr GetCurrentContext() const override { + return nullptr; + } + }; + +} // namespace NTracing +} // namespace NYdb diff --git a/src/client/tracing/otel_tracer.h b/src/client/tracing/otel_tracer.h new file mode 100644 index 0000000000..e40364973f --- /dev/null +++ b/src/client/tracing/otel_tracer.h @@ -0,0 +1,123 @@ +#pragma once + +#include "tracer.h" + +#include +#include +#include +#include +#include + +namespace NYdb { +namespace NTracing { + +class TOpenTelemetrySpan : public ISpan { +public: + OpenTelemetrySpan( + opentelemetry::nostd::shared_ptr span, + std::shared_ptr context + ) : span_(std::move(span)), context_(std::move(context)) {} + + void AddAttribute(const std::string& key, const std::string& value) override { + span_->SetAttribute(key, value); + } + + void AddEvent(const std::string& name, const TAttributeMap& attributes = {}) override { + // Преобразование атрибутов в формат OpenTelemetry + std::vector> kvPairs; + kvPairs.reserve(attributes.size()); + for (const auto& [k, v] : attributes) { + kvPairs.emplace_back(k, v); + } + + // Создание ивента + span_->AddEvent(name, opentelemetry::common::MakeKeyValueIterableView(kvPairs)); + } + + void SetStatus(bool isError, const std::string& description = "") override { + span_->SetStatus(isError ? opentelemetry::trace::StatusCode::kError + : opentelemetry::trace::StatusCode::kOk, + description); + } + + void End() override { + span_->End(); + } + + const TTraceContext& GetContext() const override { + return *context_; + } + +private: + opentelemetry::nostd::shared_ptr span_; + std::shared_ptr context_; +}; + +class TOpenTelemetryTracer : public ITracer { +public: + explicit OpenTelemetryTracer( + opentelemetry::nostd::shared_ptr tracer + ) : tracer_(std::move(tracer)) {} + + std::unique_ptr StartSpan( + const std::string& name, + const TAttributeMap& attributes = {}, + std::shared_ptr parentContext = nullptr + ) override { + opentelemetry::trace::StartSpanOptions options; + + // Установка родительского контекста + if (parentContext) { + auto traceId = opentelemetry::trace::TraceId::FromHex(parentContext->GetTraceId()); + auto spanId = opentelemetry::trace::SpanId::FromHex(parentContext->GetSpanId()); + + auto parentContext = opentelemetry::trace::SpanContext( + traceId, + spanId, + opentelemetry::trace::TraceFlags::kSampled, + true + ); + options.parent = parentContext; + } + + // Создание спана + auto span = tracer_->StartSpan(name, options); + + // Установка атрибутов + for (const auto& [key, value] : attributes) { + span->SetAttribute(key, value); + } + + // Создание контекста + std::shared_ptr context; + if (parentContext) { + context = parentContext->CreateChild(); + } else { + context = TTraceContext::GenerateNew(); + } + + return std::make_unique(span, context); + } + + std::shared_ptr GetCurrentContext() const override { + auto currentSpan = opentelemetry::trace::GetSpan( + opentelemetry::context::RuntimeContext::GetCurrent() + ); + + if (!currentSpan->IsValid()) { + return nullptr; + } + + auto context = currentSpan->GetContext(); + return std::make_shared( + context.trace_id().ToHex(), + context.span_id().ToHex() + ); + } + +private: + opentelemetry::nostd::shared_ptr tracer_; +}; + +} // namespace NTracing +} // namespace NYdb diff --git a/src/client/tracing/tracer.cpp b/src/client/tracing/tracer.cpp new file mode 100644 index 0000000000..a27d2f306c --- /dev/null +++ b/src/client/tracing/tracer.cpp @@ -0,0 +1,44 @@ +#include +#include +#include +#include + +namespace NYdb { +namespace NTracing { + +namespace { + std::string GenerateRandomHex(size_t length) { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(0, 15); + + std::ostringstream oss; + for (size_t i = 0; i < length; ++i) { + oss << std::hex << dis(gen); + } + return oss.str(); + } +} + +std::shared_ptr TTraceContext::GenerateNew() { + return std::make_shared( + GenerateRandomHex(32), + GenerateRandomHex(16) + ); +} + +std::shared_ptr TTraceContext::CreateChild() const { + return std::make_shared( + TraceId_, + GenerateRandomHex(16), + SpanId_ + ); +} + +std::string TTraceContext::ToTraceParent() const { + // Format: 00---01 + return "00-" + TraceId_ + "-" + SpanId_ + "-01"; +} + +} // namespace NTracing +} // namespace NYdb