From 0a3320ecdf92090d9e9db4aaaa89af5a8ceec87e Mon Sep 17 00:00:00 2001 From: David Li Date: Thu, 24 Jun 2021 15:05:38 -0400 Subject: [PATCH 01/11] Rename bswap_64 to otel_bswap_64 to avoid clash with macro (#875) (#876) --- .../opentelemetry/exporters/jaeger/recordable.h | 4 ++-- exporters/jaeger/src/recordable.cc | 8 ++++---- exporters/jaeger/test/jaeger_recordable_test.cc | 10 +++++----- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/exporters/jaeger/include/opentelemetry/exporters/jaeger/recordable.h b/exporters/jaeger/include/opentelemetry/exporters/jaeger/recordable.h index c5ce57c3c4..01a4bb0d79 100644 --- a/exporters/jaeger/include/opentelemetry/exporters/jaeger/recordable.h +++ b/exporters/jaeger/include/opentelemetry/exporters/jaeger/recordable.h @@ -29,13 +29,13 @@ namespace jaeger # if defined(__clang__) || \ (defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || __GNUC__ >= 5)) -inline uint64_t bswap_64(uint64_t host_int) +inline uint64_t otel_bswap_64(uint64_t host_int) { return __builtin_bswap64(host_int); } # elif defined(_MSC_VER) -inline uint64_t bswap_64(uint64_t host_int) +inline uint64_t otel_bswap_64(uint64_t host_int) { return _byteswap_uint64(host_int); } diff --git a/exporters/jaeger/src/recordable.cc b/exporters/jaeger/src/recordable.cc index 3e3661623e..c9425b963b 100644 --- a/exporters/jaeger/src/recordable.cc +++ b/exporters/jaeger/src/recordable.cc @@ -46,13 +46,13 @@ void Recordable::SetIdentity(const trace::SpanContext &span_context, // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/sdk_exporters/jaeger.md#ids #if JAEGER_IS_LITTLE_ENDIAN == 1 span_->__set_traceIdHigh( - bswap_64(*(reinterpret_cast(span_context.trace_id().Id().data())))); + otel_bswap_64(*(reinterpret_cast(span_context.trace_id().Id().data())))); span_->__set_traceIdLow( - bswap_64(*(reinterpret_cast(span_context.trace_id().Id().data()) + 1))); + otel_bswap_64(*(reinterpret_cast(span_context.trace_id().Id().data()) + 1))); span_->__set_spanId( - bswap_64(*(reinterpret_cast(span_context.span_id().Id().data())))); + otel_bswap_64(*(reinterpret_cast(span_context.span_id().Id().data())))); span_->__set_parentSpanId( - bswap_64(*(reinterpret_cast(parent_span_id.Id().data())))); + otel_bswap_64(*(reinterpret_cast(parent_span_id.Id().data())))); #else span_->__set_traceIdLow( *(reinterpret_cast(span_context.trace_id().Id().data()))); diff --git a/exporters/jaeger/test/jaeger_recordable_test.cc b/exporters/jaeger/test/jaeger_recordable_test.cc index 2692096213..2289a53ab9 100644 --- a/exporters/jaeger/test/jaeger_recordable_test.cc +++ b/exporters/jaeger/test/jaeger_recordable_test.cc @@ -43,10 +43,10 @@ TEST(JaegerSpanRecordable, SetIdentity) std::unique_ptr span{rec.Span()}; #if JAEGER_IS_LITTLE_ENDIAN == 1 - EXPECT_EQ(span->traceIdLow, opentelemetry::exporter::jaeger::bswap_64(trace_id_val[1])); - EXPECT_EQ(span->traceIdHigh, opentelemetry::exporter::jaeger::bswap_64(trace_id_val[0])); - EXPECT_EQ(span->spanId, opentelemetry::exporter::jaeger::bswap_64(span_id_val)); - EXPECT_EQ(span->parentSpanId, opentelemetry::exporter::jaeger::bswap_64(parent_span_id_val)); + EXPECT_EQ(span->traceIdLow, opentelemetry::exporter::jaeger::otel_bswap_64(trace_id_val[1])); + EXPECT_EQ(span->traceIdHigh, opentelemetry::exporter::jaeger::otel_bswap_64(trace_id_val[0])); + EXPECT_EQ(span->spanId, opentelemetry::exporter::jaeger::otel_bswap_64(span_id_val)); + EXPECT_EQ(span->parentSpanId, opentelemetry::exporter::jaeger::otel_bswap_64(parent_span_id_val)); #else EXPECT_EQ(span->traceIdLow, trace_id_val[0]); EXPECT_EQ(span->traceIdHigh, trace_id_val[1]); @@ -143,4 +143,4 @@ TEST(JaegerSpanRecordable, SetInstrumentationLibrary) EXPECT_EQ(tags[1].key, "otel.library.version"); EXPECT_EQ(tags[1].vType, thrift::TagType::STRING); EXPECT_EQ(tags[1].vStr, library_version); -} \ No newline at end of file +} From b5dd914c9d7a36342a8b9e4d1c014354e983f917 Mon Sep 17 00:00:00 2001 From: Max Golovanov Date: Wed, 30 Jun 2021 09:23:32 -0700 Subject: [PATCH 02/11] Clarify the strategy to avoid conflict between two different versions of Abseil (#883) --- examples/otlp/README.md | 15 +++++++++++++++ examples/otlp/grpc_main.cc | 3 +++ 2 files changed, 18 insertions(+) diff --git a/examples/otlp/README.md b/examples/otlp/README.md index 03325cd681..cd85a392a1 100644 --- a/examples/otlp/README.md +++ b/examples/otlp/README.md @@ -49,3 +49,18 @@ default. This can be changed with first argument from command-line, for example: Once you have the Collector running, see [CONTRIBUTING.md](../../CONTRIBUTING.md) for instructions on building and running the example. + +## Additional notes regarding Abseil library + +gRPC internally uses a different version of Abseil than OpenTelemetry C++ SDK. + +One option to optimize your code is to build the SDK with system-provided +Abseil library. If you are using CMake, then `-DWITH_ABSEIL=ON` may be passed +during the build of SDK to reuse the same Abseil library as gRPC. + +If you do not want to pursue the above option, and in case if you run into +conflict between Abseil library and OpenTelemetry C++ `absl::variant` +implementation, please include either `grpcpp/grpcpp.h` or +`opentelemetry/exporters/otlp/otlp_grpc_exporter.h` BEFORE any other API +headers. This approach efficiently avoids the conflict between the two different +versions of Abseil. diff --git a/examples/otlp/grpc_main.cc b/examples/otlp/grpc_main.cc index 7df891ad0a..7789457909 100644 --- a/examples/otlp/grpc_main.cc +++ b/examples/otlp/grpc_main.cc @@ -1,6 +1,9 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 +// Make sure to include GRPC exporter first because otherwise Abseil may create +// ambiguity with `nostd::variant`. See issue: +// https://github.com/open-telemetry/opentelemetry-cpp/issues/880 #include "opentelemetry/exporters/otlp/otlp_grpc_exporter.h" #include "opentelemetry/sdk/trace/simple_processor.h" #include "opentelemetry/sdk/trace/tracer_provider.h" From 47859cc37e977f70515bbaaf6c4a560899b0ffcd Mon Sep 17 00:00:00 2001 From: Max Golovanov Date: Wed, 30 Jun 2021 19:37:27 -0700 Subject: [PATCH 03/11] ETW example and tests clean-up (#882) --- .../opentelemetry/context/runtime_context.h | 2 +- examples/CMakeLists.txt | 3 + examples/etw_threads/CMakeLists.txt | 6 + examples/etw_threads/README.md | 32 ++++ examples/etw_threads/main.cc | 154 ++++++++++++++++++ exporters/etw/test/etw_tracer_test.cc | 151 +++++++++++++++-- 6 files changed, 337 insertions(+), 11 deletions(-) create mode 100644 examples/etw_threads/CMakeLists.txt create mode 100644 examples/etw_threads/README.md create mode 100644 examples/etw_threads/main.cc diff --git a/api/include/opentelemetry/context/runtime_context.h b/api/include/opentelemetry/context/runtime_context.h index 400b3de544..afefa93e7d 100644 --- a/api/include/opentelemetry/context/runtime_context.h +++ b/api/include/opentelemetry/context/runtime_context.h @@ -169,7 +169,7 @@ inline Token::~Token() } // The ThreadLocalContextStorage class is a derived class from -// RuntimeContextStorage and provides a wrapper for propogating context through +// RuntimeContextStorage and provides a wrapper for propagating context through // cpp thread locally. This file must be included to use the RuntimeContext // class if another implementation has not been registered. class ThreadLocalContextStorage : public RuntimeContextStorage diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 9ea0a544fb..782f20d18e 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -2,6 +2,9 @@ if(WITH_OTLP_GRPC OR WITH_OTLP_HTTP) add_subdirectory(otlp) add_subdirectory(grpc) endif() +if(WITH_ETW) + add_subdirectory(etw_threads) +endif() if(WITH_JAEGER) add_subdirectory(jaeger) endif() diff --git a/examples/etw_threads/CMakeLists.txt b/examples/etw_threads/CMakeLists.txt new file mode 100644 index 0000000000..fd6ac76443 --- /dev/null +++ b/examples/etw_threads/CMakeLists.txt @@ -0,0 +1,6 @@ +project(etw_threadpool) + +add_executable(etw_threadpool main.cc) + +target_link_libraries(etw_threadpool ${CMAKE_THREAD_LIBS_INIT} + opentelemetry_api opentelemetry_exporter_etw) diff --git a/examples/etw_threads/README.md b/examples/etw_threads/README.md new file mode 100644 index 0000000000..a004a9f55b --- /dev/null +++ b/examples/etw_threads/README.md @@ -0,0 +1,32 @@ +# ETW Exporter multithreaded context propagation example + +## Preface + +This example shows how to pass context from main dispatcher thread to worker threads. +While this example is convenient to run in Visual Studio with ETW exporter, the same +logic should apply to any other exporter. Only the initial portion that obtains ETW +Tracer is unique to ETW, the rest can be reused. + +## How to debug events in Visual Studio 2019 or newer + +Specify your component instrumentation name, which should match the destination ETW +Provider Name or GUID. Example uses "OpenTelemetry-ETW-TLD" for the instrument / +instrumentation name. + +In Visual Studio IDE: + +- navigate to `View -> Other Windows -> Diagnostic Events...` +- click `Configure...` gear on top. +- specify `OpenTelemetry-ETW-TLD` in the list of providers to monitor. +- run example. +- `Diagnostic Events` view shows you the event flow in realtime. + +## Explanation of the code flow + +`main` function acts as a dispatcher to manage thread pool called `pool`. `beep_bop` +span is started in the `main`. Then in a loop up to `kMaxThreads` get started +concurrently. Each thread executing `beep` function with a parent scope of `main`. +`beep` subsequently calls into `bop` function, with a parent scope of `beep` span. +Entire execution of all threads is grouped under the main span called `beep_bop`. +At the end of execution, the `main` function joins all pending threads and ends +the main span. diff --git a/examples/etw_threads/main.cc b/examples/etw_threads/main.cc new file mode 100644 index 0000000000..d25883d1d1 --- /dev/null +++ b/examples/etw_threads/main.cc @@ -0,0 +1,154 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +// Include common Trace Provider API and processor +#include "opentelemetry/sdk/trace/simple_processor.h" +#include "opentelemetry/sdk/trace/tracer_provider.h" +#include "opentelemetry/trace/provider.h" + +#include "opentelemetry/exporters/etw/etw_tracer_exporter.h" + +#include +#include + +#include +#ifndef LOG_DEBUG +# include + +/** + * @brief Thread-safe logger routine. + * @param format + * @param args + * @return + */ +static inline int log_vprintf(const char *format, va_list args) +{ + static std::mutex cout_mutex; + std::lock_guard lk(cout_mutex); + return vprintf(format, args); +}; + +/** + * @brief Thread-safe logger routine. + * @param format + * @param + * @return + */ +static inline int log_printf(const char *format, ...) +{ + int result; + va_list ap; + va_start(ap, format); + result = log_vprintf(format, ap); + va_end(ap); + return result; +}; + +// Debug macros +# define LOG_DEBUG(fmt_, ...) log_printf(" " fmt_ "\n", ##__VA_ARGS__) +# define LOG_TRACE(fmt_, ...) log_printf(" " fmt_ "\n", ##__VA_ARGS__) +# define LOG_INFO(fmt_, ...) log_printf(" " fmt_ "\n", ##__VA_ARGS__) +# define LOG_WARN(fmt_, ...) log_printf(" " fmt_ "\n", ##__VA_ARGS__) +# define LOG_ERROR(fmt_, ...) log_printf(" " fmt_ "\n", ##__VA_ARGS__) +#endif + +using namespace OPENTELEMETRY_NAMESPACE; + +using namespace opentelemetry::exporter::etw; + +// Specify destination ETW Provider Name or GUID. +// +// In Visual Studio: +// - View -> Other Windows -> Diagnostic Events... +// - Click Configure (gear on top). +// - Specify "OpenTelemetry-ETW-TLD" in the list of providers. +// +// Event view shows event flow in realtime. +const char *kGlobalProviderName = "OpenTelemetry-ETW-TLD"; + +std::string providerName = kGlobalProviderName; + +// One provider can be used to associate with different destinations. +exporter::etw::TracerProvider provider; + +// Code below is generic and may be reused with any other TracerProvider. +// In ETW provider case - instrumentation name must match destination +// ETW provider name. +nostd::shared_ptr tracer = provider.GetTracer(providerName, "1.0"); + +// Obtain numeric thread id +static inline uint64_t gettid() +{ + std::stringstream ss; + ss << std::this_thread::get_id(); + uint64_t id = std::stoull(ss.str()); + return id; +} + +// bop gets called by beep. +void bop() +{ + LOG_TRACE("bop worker tid=%u", gettid()); + auto span = tracer->StartSpan("bop"); + span->AddEvent("BopEvent", {{"tid", gettid()}}); + span->SetAttribute("attrib", 2); + span->End(); +} + +// beep gets called in its own thread. +// It is running in a thread pool, invoked via lambda by dispatcher. +void beep() +{ + LOG_TRACE("beep worker tid=%u", gettid()); + auto span = tracer->StartSpan("beep"); + span->AddEvent("BeepEvent", {{"tid", gettid()}}); + span->SetAttribute("attrib", 1); + { + auto bopScope = tracer->WithActiveSpan(span); + bop(); + } + span->End(); +} + +// Max number of threads to spawn +constexpr int kMaxThreads = 10; + +int main(int arc, char **argv) +{ + std::thread pool[kMaxThreads]; + + // Main dispatcher span: parent of all child thread spans. + auto mainSpan = tracer->StartSpan("beep_bop"); + mainSpan->SetAttribute("attrib", 0); + + // Start several threads to perform beep-bop actions. + LOG_TRACE("beep-boop dispatcher tid=%u", gettid()); + for (auto i = 0; i < kMaxThreads; i++) + { + pool[i] = std::thread([&]() { + // This code runs in its own worker thread. + auto beepScope = tracer->WithActiveSpan(mainSpan); + // call beep -> bop + beep(); + }); + }; + + // Join all worker threads in the pool + for (auto &th : pool) + { + try + { + if (th.joinable()) + th.join(); + } + catch (...) + { + // thread might have been gracefully terminated already + } + } + + // End span + mainSpan->End(); + + return 0; +} diff --git a/exporters/etw/test/etw_tracer_test.cc b/exporters/etw/test/etw_tracer_test.cc index 45d49356c8..400099bbe7 100644 --- a/exporters/etw/test/etw_tracer_test.cc +++ b/exporters/etw/test/etw_tracer_test.cc @@ -14,6 +14,8 @@ using namespace OPENTELEMETRY_NAMESPACE; using namespace opentelemetry::exporter::etw; +const char *kGlobalProviderName = "OpenTelemetry-ETW-TLD"; + std::string getTemporaryValue() { return std::string("Value from Temporary std::string"); @@ -43,11 +45,10 @@ TEST(ETWTracer, TracerCheck) // Windows Defender Firewall API - GP {0EFF663F-8B6E-4E6D-8182-087A8EAA29CB} // Windows Defender Firewall Driver {D5E09122-D0B2-4235-ADC1-C89FAAAF1069} - std::string providerName = "OpenTelemetry-ETW-TLD"; // supply unique instrumentation name here + std::string providerName = kGlobalProviderName; // supply unique instrumentation name here exporter::etw::TracerProvider tp; - // TODO: this code should fallback to MsgPack if TLD is not available - auto tracer = tp.GetTracer(providerName, "TLD"); + auto tracer = tp.GetTracer(providerName); // Span attributes Properties attribs = @@ -117,7 +118,7 @@ TEST(ETWTracer, TracerCheck) /* { "Timestamp": "2021-03-19T21:04:38.411193-07:00", - "ProviderName": "OpenTelemetry-ETW-Provider", + "ProviderName": "OpenTelemetry-ETW-TLD", "Id": 13, "Message": null, "ProcessId": 15120, @@ -131,7 +132,7 @@ TEST(ETWTracer, TracerCheck) */ TEST(ETWTracer, TracerCheckMinDecoration) { - std::string providerName = "OpenTelemetry-ETW-TLD"; + std::string providerName = kGlobalProviderName; exporter::etw::TracerProvider tp ({ {"enableTraceId", false}, @@ -141,7 +142,7 @@ TEST(ETWTracer, TracerCheckMinDecoration) {"enableRelatedActivityId", false}, {"enableAutoParent", false} }); - auto tracer = tp.GetTracer(providerName, "TLD"); + auto tracer = tp.GetTracer(providerName); { auto aSpan = tracer->StartSpan("A.min"); auto aScope = tracer->WithActiveSpan(aSpan); @@ -166,7 +167,7 @@ TEST(ETWTracer, TracerCheckMinDecoration) /* { "Timestamp": "2021-03-19T21:04:38.4120274-07:00", - "ProviderName": "OpenTelemetry-ETW-Provider", + "ProviderName": "OpenTelemetry-ETW-TLD", "Id": 21, "Message": null, "ProcessId": 15120, @@ -183,7 +184,7 @@ TEST(ETWTracer, TracerCheckMinDecoration) */ TEST(ETWTracer, TracerCheckMaxDecoration) { - std::string providerName = "OpenTelemetry-ETW-TLD"; + std::string providerName = kGlobalProviderName; exporter::etw::TracerProvider tp ({ {"enableTraceId", true}, @@ -192,7 +193,7 @@ TEST(ETWTracer, TracerCheckMaxDecoration) {"enableRelatedActivityId", true}, {"enableAutoParent", true} }); - auto tracer = tp.GetTracer(providerName, "TLD" ); + auto tracer = tp.GetTracer(providerName); { auto aSpan = tracer->StartSpan("A.max"); auto aScope = tracer->WithActiveSpan(aSpan); @@ -222,7 +223,7 @@ TEST(ETWTracer, TracerCheckMsgPack) {"enableRelatedActivityId", true}, {"enableAutoParent", true} }); - auto tracer = tp.GetTracer(providerName, "MsgPack" ); + auto tracer = tp.GetTracer(providerName); { auto aSpan = tracer->StartSpan("A.max"); auto aScope = tracer->WithActiveSpan(aSpan); @@ -249,6 +250,136 @@ TEST(ETWTracer, TracerCheckMsgPack) tracer->CloseWithMicroseconds(0); } +/** + * @brief Global Tracer singleton may be placed in .h header and + * shared across different compilation units. All would get the + * same object. + * + * @return Single global tracer instance. +*/ +static OPENTELEMETRY_NAMESPACE::trace::TracerProvider& GetGlobalTracerProvider() +{ + static exporter::etw::TracerProvider tp + ({ + {"enableTraceId", true}, + {"enableSpanId", true}, + {"enableActivityId", true}, + {"enableRelatedActivityId", true}, + {"enableAutoParent", true} + }); + return tp; +} + +static OPENTELEMETRY_NAMESPACE::trace::Tracer& GetGlobalTracer() +{ + static auto tracer = GetGlobalTracerProvider().GetTracer(kGlobalProviderName); + return (*tracer.get()); +} + +TEST(ETWTracer, GlobalSingletonTracer) +{ + // Obtain a global tracer using C++11 magic static. + auto& globalTracer = GetGlobalTracer(); + auto s1 = globalTracer.StartSpan("Span1"); + auto traceId1 = s1->GetContext().trace_id(); + s1->End(); +/* === Span 1 - "TraceId": "182a64258fb1864ca4e1a542eecbd9bf" +{ + "Timestamp": "2021-05-10T11:45:27.028827-07:00", + "ProviderName": "OpenTelemetry-ETW-TLD", + "Id": 5, + "Message": null, + "ProcessId": 23712, + "Level": "Always", + "Keywords": "0x0000000000000000", + "EventName": "Span", + "ActivityID": "6ed94703-6b0a-4e76-0000-000000000000", + "RelatedActivityID": null, + "Payload": { + "Duration": 0, + "Kind": 1, + "Name": "Span1", + "SpanId": "0347d96e0a6b764e", + "StartTime": "2021-05-10T18:45:27.028000Z", + "StatusCode": 0, + "StatusMessage": "", + "Success": "True", + "TraceId": "182a64258fb1864ca4e1a542eecbd9bf", + "_name": "Span" + } +} +*/ + + // Obtain a different tracer withs its own trace-id. + auto localTracer = GetGlobalTracerProvider().GetTracer(kGlobalProviderName); + auto s2 = localTracer->StartSpan("Span2"); + auto traceId2 = s2->GetContext().trace_id(); + s2->End(); +/* === Span 2 - "TraceId": "334bf9a1eed98d40a873a606295a9368" +{ + "Timestamp": "2021-05-10T11:45:27.0289654-07:00", + "ProviderName": "OpenTelemetry-ETW-TLD", + "Id": 5, + "Message": null, + "ProcessId": 23712, + "Level": "Always", + "Keywords": "0x0000000000000000", + "EventName": "Span", + "ActivityID": "3b7b2ecb-2e84-4903-0000-000000000000", + "RelatedActivityID": null, + "Payload": { + "Duration": 0, + "Kind": 1, + "Name": "Span2", + "SpanId": "cb2e7b3b842e0349", + "StartTime": "2021-05-10T18:45:27.028000Z", + "StatusCode": 0, + "StatusMessage": "", + "Success": "True", + "TraceId": "334bf9a1eed98d40a873a606295a9368", + "_name": "Span" + } +} +*/ + + // Obtain the same global tracer with the same trace-id as before. + auto& globalTracer2 = GetGlobalTracer(); + auto s3 = globalTracer2.StartSpan("Span3"); + auto traceId3 = s3->GetContext().trace_id(); + s3->End(); +/* === Span 3 - "TraceId": "182a64258fb1864ca4e1a542eecbd9bf" +{ + "Timestamp": "2021-05-10T11:45:27.0290936-07:00", + "ProviderName": "OpenTelemetry-ETW-TLD", + "Id": 5, + "Message": null, + "ProcessId": 23712, + "Level": "Always", + "Keywords": "0x0000000000000000", + "EventName": "Span", + "ActivityID": "0a970247-ba0e-4d4b-0000-000000000000", + "RelatedActivityID": null, + "Payload": { + "Duration": 1, + "Kind": 1, + "Name": "Span3", + "SpanId": "4702970a0eba4b4d", + "StartTime": "2021-05-10T18:45:27.028000Z", + "StatusCode": 0, + "StatusMessage": "", + "Success": "True", + "TraceId": "182a64258fb1864ca4e1a542eecbd9bf", + "_name": "Span" + } +} +*/ + EXPECT_NE(traceId1, traceId2); + EXPECT_EQ(traceId1, traceId3); + + localTracer->CloseWithMicroseconds(0); + globalTracer.CloseWithMicroseconds(0); +} + /* clang-format on */ #endif From 85564852048e908e7d579374c52f6214e9dca1a6 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Thu, 1 Jul 2021 08:43:50 +0530 Subject: [PATCH 04/11] Few minor fixes for zipkin exporter (#886) --- .../opentelemetry/exporters/zipkin/zipkin_exporter.h | 6 +++--- exporters/zipkin/src/recordable.cc | 2 +- exporters/zipkin/test/zipkin_recordable_test.cc | 12 +++++------- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h b/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h index a69eaf9caf..cb244867d7 100644 --- a/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h +++ b/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h @@ -17,11 +17,11 @@ namespace exporter namespace zipkin { -const char *kZipkinEndpointDefault = "http://localhost:9411/api/v2/spans"; - -static const std::string GetDefaultZipkinEndpoint() +inline const std::string GetDefaultZipkinEndpoint() { const char *otel_exporter_zipkin_endpoint_env = "OTEL_EXPORTER_ZIPKIN_ENDPOINT"; + const char *kZipkinEndpointDefault = "http://localhost:9411/api/v2/spans"; + #if defined(_MSC_VER) // avoid calling std::getenv which is deprecated in MSVC. size_t required_size = 0; diff --git a/exporters/zipkin/src/recordable.cc b/exporters/zipkin/src/recordable.cc index bbdc85c548..07d9b09c9d 100644 --- a/exporters/zipkin/src/recordable.cc +++ b/exporters/zipkin/src/recordable.cc @@ -225,7 +225,7 @@ void Recordable::SetStartTime(opentelemetry::common::SystemTimestamp start_time) void Recordable::SetDuration(std::chrono::nanoseconds duration) noexcept { - span_["duration"] = duration.count(); + span_["duration"] = std::chrono::duration_cast(duration).count(); } void Recordable::SetSpanKind(opentelemetry::trace::SpanKind span_kind) noexcept diff --git a/exporters/zipkin/test/zipkin_recordable_test.cc b/exporters/zipkin/test/zipkin_recordable_test.cc index 51ba1024b6..7a5feb8bdb 100644 --- a/exporters/zipkin/test/zipkin_recordable_test.cc +++ b/exporters/zipkin/test/zipkin_recordable_test.cc @@ -12,8 +12,6 @@ #include "opentelemetry/common/timestamp.h" #include "opentelemetry/exporters/zipkin/recordable.h" -#include - #include namespace trace = opentelemetry::trace; @@ -69,16 +67,16 @@ TEST(ZipkinSpanRecordable, SetStartTime) TEST(ZipkinSpanRecordable, SetDuration) { - json j_span = {{"duration", 10}, {"timestamp", 0}}; + std::chrono::nanoseconds durationNS(1000000000); // in ns + std::chrono::microseconds durationMS = + std::chrono::duration_cast(durationNS); // in ms + json j_span = {{"duration", durationMS.count()}, {"timestamp", 0}}; opentelemetry::exporter::zipkin::Recordable rec; // Start time is 0 opentelemetry::common::SystemTimestamp start_timestamp; - std::chrono::nanoseconds duration(10); - uint64_t unix_end = duration.count(); - rec.SetStartTime(start_timestamp); - rec.SetDuration(duration); + rec.SetDuration(durationNS); EXPECT_EQ(rec.span(), j_span); } From 2383d99d4d80310999b152cfdff69f3dc1b6f1b7 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Thu, 1 Jul 2021 09:11:50 +0530 Subject: [PATCH 05/11] Associate valid SpanId/SpanContext with Spans irrespective of the Sampling decision. (#879) --- api/include/opentelemetry/trace/noop.h | 11 +++++-- api/test/trace/noop_test.cc | 43 +++++++++++++++++++------- sdk/src/trace/tracer.cc | 22 +++++++------ sdk/test/trace/tracer_test.cc | 8 ++++- 4 files changed, 59 insertions(+), 25 deletions(-) diff --git a/api/include/opentelemetry/trace/noop.h b/api/include/opentelemetry/trace/noop.h index ad7f05273a..76c0fe0749 100644 --- a/api/include/opentelemetry/trace/noop.h +++ b/api/include/opentelemetry/trace/noop.h @@ -29,7 +29,12 @@ class NoopSpan final : public Span { public: explicit NoopSpan(const std::shared_ptr &tracer) noexcept - : tracer_{tracer}, span_context_{SpanContext::GetInvalid()} + : tracer_{tracer}, span_context_{new SpanContext(false, false)} + {} + + explicit NoopSpan(const std::shared_ptr &tracer, + nostd::unique_ptr span_context) noexcept + : tracer_{tracer}, span_context_{std::move(span_context)} {} void SetAttribute(nostd::string_view /*key*/, @@ -55,11 +60,11 @@ class NoopSpan final : public Span bool IsRecording() const noexcept override { return false; } - SpanContext GetContext() const noexcept override { return span_context_; } + SpanContext GetContext() const noexcept override { return *span_context_.get(); } private: std::shared_ptr tracer_; - SpanContext span_context_; + nostd::unique_ptr span_context_; }; /** diff --git a/api/test/trace/noop_test.cc b/api/test/trace/noop_test.cc index 5414a5c726..b17faf64d4 100644 --- a/api/test/trace/noop_test.cc +++ b/api/test/trace/noop_test.cc @@ -10,14 +10,13 @@ #include -using opentelemetry::common::SystemTimestamp; -using opentelemetry::trace::NoopTracer; -using opentelemetry::trace::SpanContext; -using opentelemetry::trace::Tracer; +namespace trace_api = opentelemetry::trace; +namespace nonstd = opentelemetry::nostd; +namespace common = opentelemetry::common; TEST(NoopTest, UseNoopTracers) { - std::shared_ptr tracer{new NoopTracer{}}; + std::shared_ptr tracer{new trace_api::NoopTracer{}}; auto s1 = tracer->StartSpan("abc"); std::map attributes1; @@ -41,7 +40,7 @@ TEST(NoopTest, UseNoopTracers) s1->UpdateName("test_name"); - SystemTimestamp t1; + common::SystemTimestamp t1; s1->AddEvent("test_time_stamp", t1); s1->GetContext(); @@ -49,12 +48,34 @@ TEST(NoopTest, UseNoopTracers) TEST(NoopTest, StartSpan) { - std::shared_ptr tracer{new NoopTracer{}}; + std::shared_ptr tracer{new trace_api::NoopTracer{}}; - std::map attrs = {{"a", "3"}}; - std::vector>> links = { - {SpanContext(false, false), attrs}}; + std::map attrs = {{"a", "3"}}; + std::vector>> links = { + {trace_api::SpanContext(false, false), attrs}}; auto s1 = tracer->StartSpan("abc", attrs, links); - auto s2 = tracer->StartSpan("efg", {{"a", 3}}, {{SpanContext(false, false), {{"b", 4}}}}); + auto s2 = + tracer->StartSpan("efg", {{"a", 3}}, {{trace_api::SpanContext(false, false), {{"b", 4}}}}); +} + +TEST(NoopTest, CreateSpanValidSpanContext) +{ + // Create valid spancontext for NoopSpan + + constexpr uint8_t buf_span[] = {1, 2, 3, 4, 5, 6, 7, 8}; + constexpr uint8_t buf_trace[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; + auto trace_id = trace_api::TraceId{buf_trace}; + auto span_id = trace_api::SpanId{buf_span}; + auto span_context = nonstd::unique_ptr( + new trace_api::SpanContext{trace_id, span_id, trace_api::TraceFlags{true}, false}); + std::shared_ptr tracer{new trace_api::NoopTracer{}}; + auto s1 = + nonstd::shared_ptr(new trace_api::NoopSpan(tracer, std::move(span_context))); + auto stored_span_context = s1->GetContext(); + EXPECT_EQ(stored_span_context.span_id(), span_id); + EXPECT_EQ(stored_span_context.trace_id(), trace_id); + + s1->AddEvent("even1"); // noop + s1->End(); // noop } diff --git a/sdk/src/trace/tracer.cc b/sdk/src/trace/tracer.cc index 149684bc8e..c84d847bd9 100644 --- a/sdk/src/trace/tracer.cc +++ b/sdk/src/trace/tracer.cc @@ -46,25 +46,27 @@ nostd::shared_ptr Tracer::StartSpan( auto sampling_result = context_->GetSampler().ShouldSample(parent_context, trace_id, name, options.kind, attributes, links); + auto trace_flags = sampling_result.decision == Decision::DROP + ? trace_api::TraceFlags{} + : trace_api::TraceFlags{trace_api::TraceFlags::kIsSampled}; + + auto span_context = std::unique_ptr(new trace_api::SpanContext( + trace_id, span_id, trace_flags, false, + sampling_result.trace_state ? sampling_result.trace_state + : is_parent_span_valid ? parent_context.trace_state() + : trace_api::TraceState::GetDefault())); if (sampling_result.decision == Decision::DROP) { - // Don't allocate a no-op span for every DROP decision, but use a static - // singleton for this case. - static nostd::shared_ptr noop_span( - new trace_api::NoopSpan{this->shared_from_this()}); + // create no-op span with valid span-context. + auto noop_span = nostd::shared_ptr{ + new (std::nothrow) trace_api::NoopSpan(this->shared_from_this(), std::move(span_context))}; return noop_span; } else { - auto span_context = std::unique_ptr(new trace_api::SpanContext( - trace_id, span_id, trace_api::TraceFlags{trace_api::TraceFlags::kIsSampled}, false, - sampling_result.trace_state ? sampling_result.trace_state - : is_parent_span_valid ? parent_context.trace_state() - : trace_api::TraceState::GetDefault())); - auto span = nostd::shared_ptr{ new (std::nothrow) Span{this->shared_from_this(), name, attributes, links, options, parent_context, std::move(span_context)}}; diff --git a/sdk/test/trace/tracer_test.cc b/sdk/test/trace/tracer_test.cc index 0c5cc397d8..2e9dd73413 100644 --- a/sdk/test/trace/tracer_test.cc +++ b/sdk/test/trace/tracer_test.cc @@ -165,8 +165,14 @@ TEST(Tracer, StartSpanSampleOff) auto tracer_off = initTracer(std::move(exporter), new AlwaysOffSampler()); // This span will not be recorded. - tracer_off->StartSpan("span 2")->End(); + auto span = tracer_off->StartSpan("span 2"); + // Always generate a valid span-context (span-id) + auto context = span->GetContext(); + EXPECT_TRUE(context.IsValid()); + EXPECT_FALSE(context.IsSampled()); + + span->End(); // The span doesn't write any span data because the sampling decision is alway // DROP. ASSERT_EQ(0, span_data->GetSpans().size()); From 6add2e09b65d4f06ffa75856ae55c1f5620cdbab Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Fri, 2 Jul 2021 02:03:34 +0530 Subject: [PATCH 06/11] update zoom link (#887) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 890021c589..743032d17d 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ contributors' availability. Check the [OpenTelemetry community calendar](https://calendar.google.com/calendar/embed?src=google.com_b79e3e90j7bbsa2n2p5an5lf60%40group.calendar.google.com) for specific dates. -Meetings take place via [Zoom video conference](https://zoom.us/j/8203130519). +Meetings take place via [Zoom video conference](https://zoom.us/j/6729396170). The passcode is _77777_. Meeting notes are available as a public [Google From fdade9a4b43ba880d22065a09a3ef1e37986b60a Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Fri, 2 Jul 2021 10:09:53 +0530 Subject: [PATCH 07/11] Otlp Exporter : Handling InstrumentationLibrary, and Link's trace state (#823) --- exporters/jaeger/test/jaeger_recordable_test.cc | 2 +- .../exporters/otlp/otlp_recordable.h | 4 ++++ exporters/otlp/src/otlp_grpc_exporter.cc | 3 ++- exporters/otlp/src/otlp_recordable.cc | 17 ++++++++++++++--- exporters/otlp/test/otlp_recordable_test.cc | 17 ++++++++++++++++- exporters/zipkin/test/zipkin_recordable_test.cc | 2 +- .../instrumentation_library.h | 2 +- sdk/include/opentelemetry/sdk/trace/tracer.h | 2 +- sdk/src/trace/tracer_provider.cc | 2 +- .../instrumentationlibrary_test.cc | 2 +- 10 files changed, 42 insertions(+), 11 deletions(-) diff --git a/exporters/jaeger/test/jaeger_recordable_test.cc b/exporters/jaeger/test/jaeger_recordable_test.cc index 2289a53ab9..73a089556e 100644 --- a/exporters/jaeger/test/jaeger_recordable_test.cc +++ b/exporters/jaeger/test/jaeger_recordable_test.cc @@ -129,7 +129,7 @@ TEST(JaegerSpanRecordable, SetInstrumentationLibrary) std::string library_name = "opentelemetry-cpp"; std::string library_version = "0.1.0"; - auto instrumentation_library = InstrumentationLibrary::create(library_name, library_version); + auto instrumentation_library = InstrumentationLibrary::Create(library_name, library_version); rec.SetInstrumentationLibrary(*instrumentation_library); diff --git a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_recordable.h b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_recordable.h index b5b73e36d8..a2e9c83ae3 100644 --- a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_recordable.h +++ b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_recordable.h @@ -25,6 +25,8 @@ class OtlpRecordable final : public sdk::trace::Recordable /** Dynamically converts the resource of this span into a proto. */ proto::resource::v1::Resource ProtoResource() const noexcept; + proto::common::v1::InstrumentationLibrary GetProtoInstrumentationLibrary() const noexcept; + void SetIdentity(const opentelemetry::trace::SpanContext &span_context, opentelemetry::trace::SpanId parent_span_id) noexcept override; @@ -57,6 +59,8 @@ class OtlpRecordable final : public sdk::trace::Recordable private: proto::trace::v1::Span span_; const opentelemetry::sdk::resource::Resource *resource_ = nullptr; + const opentelemetry::sdk::instrumentationlibrary::InstrumentationLibrary + *instrumentation_library_ = nullptr; }; } // namespace otlp } // namespace exporter diff --git a/exporters/otlp/src/otlp_grpc_exporter.cc b/exporters/otlp/src/otlp_grpc_exporter.cc index e0aaa0a0ab..42c0b5d300 100644 --- a/exporters/otlp/src/otlp_grpc_exporter.cc +++ b/exporters/otlp/src/otlp_grpc_exporter.cc @@ -31,7 +31,8 @@ void PopulateRequest(const nostd::span> for (auto &recordable : spans) { auto rec = std::unique_ptr(static_cast(recordable.release())); - *instrumentation_lib->add_spans() = std::move(rec->span()); + *instrumentation_lib->add_spans() = std::move(rec->span()); + *instrumentation_lib->mutable_instrumentation_library() = rec->GetProtoInstrumentationLibrary(); if (!has_resource) { diff --git a/exporters/otlp/src/otlp_recordable.cc b/exporters/otlp/src/otlp_recordable.cc index 53e92d8d76..1227850858 100644 --- a/exporters/otlp/src/otlp_recordable.cc +++ b/exporters/otlp/src/otlp_recordable.cc @@ -237,6 +237,18 @@ proto::resource::v1::Resource OtlpRecordable::ProtoResource() const noexcept return proto; } +proto::common::v1::InstrumentationLibrary OtlpRecordable::GetProtoInstrumentationLibrary() + const noexcept +{ + proto::common::v1::InstrumentationLibrary instrumentation_library; + if (instrumentation_library_) + { + instrumentation_library.set_name(instrumentation_library_->GetName()); + instrumentation_library.set_version(instrumentation_library_->GetVersion()); + } + return instrumentation_library; +} + void OtlpRecordable::SetResource(const opentelemetry::sdk::resource::Resource &resource) noexcept { resource_ = &resource; @@ -271,12 +283,11 @@ void OtlpRecordable::AddLink(const opentelemetry::trace::SpanContext &span_conte trace::TraceId::kSize); link->set_span_id(reinterpret_cast(span_context.span_id().Id().data()), trace::SpanId::kSize); + link->set_trace_state(span_context.trace_state()->ToHeader()); attributes.ForEachKeyValue([&](nostd::string_view key, common::AttributeValue value) noexcept { PopulateAttribute(link->add_attributes(), key, value); return true; }); - - // TODO: Populate trace_state when it is supported by SpanContext } void OtlpRecordable::SetStatus(trace::StatusCode code, nostd::string_view description) noexcept @@ -347,7 +358,7 @@ void OtlpRecordable::SetInstrumentationLibrary( const opentelemetry::sdk::instrumentationlibrary::InstrumentationLibrary &instrumentation_library) noexcept { - // TODO: add instrumentation library to OTLP exporter. + instrumentation_library_ = &instrumentation_library; } } // namespace otlp diff --git a/exporters/otlp/test/otlp_recordable_test.cc b/exporters/otlp/test/otlp_recordable_test.cc index f6e0858a8a..9d34cd26a4 100644 --- a/exporters/otlp/test/otlp_recordable_test.cc +++ b/exporters/otlp/test/otlp_recordable_test.cc @@ -53,6 +53,16 @@ TEST(OtlpRecordable, SetSpanKind) opentelemetry::proto::trace::v1::Span_SpanKind::Span_SpanKind_SPAN_KIND_SERVER); } +TEST(OtlpRecordable, SetInstrumentationLibrary) +{ + OtlpRecordable rec; + auto inst_lib = opentelemetry::sdk::trace::InstrumentationLibrary::Create("test", "v1"); + rec.SetInstrumentationLibrary(*inst_lib); + auto proto_instr_libr = rec.GetProtoInstrumentationLibrary(); + EXPECT_EQ(proto_instr_libr.name(), inst_lib->GetName()); + EXPECT_EQ(proto_instr_libr.version(), inst_lib->GetVersion()); +} + TEST(OtlpRecordable, SetStartTime) { OtlpRecordable rec; @@ -141,11 +151,16 @@ TEST(OtlpRecordable, AddLink) auto trace_id = rec.span().trace_id(); auto span_id = rec.span().span_id(); - rec.AddLink(trace::SpanContext(false, false), + trace::TraceFlags flags; + std::string trace_state_header = "k1=v1,k2=v2"; + auto ts = trace::TraceState::FromHeader(trace_state_header); + + rec.AddLink(trace::SpanContext(trace::TraceId(), trace::SpanId(), flags, false, ts), common::KeyValueIterableView>(attributes)); EXPECT_EQ(rec.span().trace_id(), trace_id); EXPECT_EQ(rec.span().span_id(), span_id); + EXPECT_EQ(rec.span().links(0).trace_state(), trace_state_header); for (int i = 0; i < kNumAttributes; i++) { EXPECT_EQ(rec.span().links(0).attributes(i).key(), keys[i]); diff --git a/exporters/zipkin/test/zipkin_recordable_test.cc b/exporters/zipkin/test/zipkin_recordable_test.cc index 7a5feb8bdb..9b51c46c29 100644 --- a/exporters/zipkin/test/zipkin_recordable_test.cc +++ b/exporters/zipkin/test/zipkin_recordable_test.cc @@ -90,7 +90,7 @@ TEST(ZipkinSpanRecordable, SetInstrumentationLibrary) {"tags", {{"otel.library.name", library_name}, {"otel.library.version", library_version}}}}; opentelemetry::exporter::zipkin::Recordable rec; - rec.SetInstrumentationLibrary(*InstrumentationLibrary::create(library_name, library_version)); + rec.SetInstrumentationLibrary(*InstrumentationLibrary::Create(library_name, library_version)); EXPECT_EQ(rec.span(), j_span); } diff --git a/sdk/include/opentelemetry/sdk/instrumentationlibrary/instrumentation_library.h b/sdk/include/opentelemetry/sdk/instrumentationlibrary/instrumentation_library.h index 20d62eba16..e4f7f78ef1 100644 --- a/sdk/include/opentelemetry/sdk/instrumentationlibrary/instrumentation_library.h +++ b/sdk/include/opentelemetry/sdk/instrumentationlibrary/instrumentation_library.h @@ -25,7 +25,7 @@ class InstrumentationLibrary * @param version version of the instrumentation library. * @returns the newly created InstrumentationLibrary. */ - static nostd::unique_ptr create(nostd::string_view name, + static nostd::unique_ptr Create(nostd::string_view name, nostd::string_view version = "") { return nostd::unique_ptr( diff --git a/sdk/include/opentelemetry/sdk/trace/tracer.h b/sdk/include/opentelemetry/sdk/trace/tracer.h index 4b6c1de796..6aeb19fa57 100644 --- a/sdk/include/opentelemetry/sdk/trace/tracer.h +++ b/sdk/include/opentelemetry/sdk/trace/tracer.h @@ -29,7 +29,7 @@ class Tracer final : public trace_api::Tracer, public std::enable_shared_from_th /** Construct a new Tracer with the given context pipeline. */ explicit Tracer(std::shared_ptr context, std::unique_ptr instrumentation_library = - InstrumentationLibrary::create("")) noexcept; + InstrumentationLibrary::Create("")) noexcept; nostd::shared_ptr StartSpan( nostd::string_view name, diff --git a/sdk/src/trace/tracer_provider.cc b/sdk/src/trace/tracer_provider.cc index 13b41d73b6..ed6853be67 100644 --- a/sdk/src/trace/tracer_provider.cc +++ b/sdk/src/trace/tracer_provider.cc @@ -55,7 +55,7 @@ nostd::shared_ptr TracerProvider::GetTracer( } } - auto lib = InstrumentationLibrary::create(library_name, library_version); + auto lib = InstrumentationLibrary::Create(library_name, library_version); tracers_.push_back(std::shared_ptr( new sdk::trace::Tracer(context_, std::move(lib)))); return nostd::shared_ptr{tracers_.back()}; diff --git a/sdk/test/instrumentationlibrary/instrumentationlibrary_test.cc b/sdk/test/instrumentationlibrary/instrumentationlibrary_test.cc index d21f113580..b6ac69df1f 100644 --- a/sdk/test/instrumentationlibrary/instrumentationlibrary_test.cc +++ b/sdk/test/instrumentationlibrary/instrumentationlibrary_test.cc @@ -16,7 +16,7 @@ TEST(InstrumentationLibrary, CreateInstrumentationLibrary) std::string library_name = "opentelemetry-cpp"; std::string library_version = "0.1.0"; - auto instrumentation_library = InstrumentationLibrary::create(library_name, library_version); + auto instrumentation_library = InstrumentationLibrary::Create(library_name, library_version); EXPECT_EQ(instrumentation_library->GetName(), library_name); EXPECT_EQ(instrumentation_library->GetVersion(), library_version); From 98013c2563c4dbd2fa25a00ad3bc63d1db176e0f Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Fri, 2 Jul 2021 10:47:22 +0530 Subject: [PATCH 08/11] Support for TextMapPropagator::Fields method (#799) --- .../baggage/propagation/baggage_propagator.h | 5 +++++ .../context/propagation/composite_propagator.h | 15 +++++++++++++++ .../context/propagation/noop_propagator.h | 5 +++++ .../context/propagation/text_map_propagator.h | 17 +++++++++++++++-- .../trace/propagation/b3_propagator.h | 10 ++++++++++ .../trace/propagation/http_trace_context.h | 5 +++++ .../opentelemetry/trace/propagation/jaeger.h | 11 ++++++++--- .../propagation/baggage_propagator_test.cc | 8 ++++++++ .../propagation/composite_propagator_test.cc | 10 ++++++++++ .../trace/propagation/http_text_format_test.cc | 9 +++++++++ .../propagation/jaeger_propagation_test.cc | 8 ++++++++ 11 files changed, 98 insertions(+), 5 deletions(-) diff --git a/api/include/opentelemetry/baggage/propagation/baggage_propagator.h b/api/include/opentelemetry/baggage/propagation/baggage_propagator.h index 74db10ea59..aa669dd1d9 100644 --- a/api/include/opentelemetry/baggage/propagation/baggage_propagator.h +++ b/api/include/opentelemetry/baggage/propagation/baggage_propagator.h @@ -46,6 +46,11 @@ class BaggagePropagator : public context::propagation::TextMapPropagator auto baggage = Baggage::FromHeader(baggage_str); return SetBaggage(context, baggage); } + + bool Fields(nostd::function_ref callback) const noexcept override + { + return callback(kBaggageHeader); + } }; } // namespace propagation } // namespace baggage diff --git a/api/include/opentelemetry/context/propagation/composite_propagator.h b/api/include/opentelemetry/context/propagation/composite_propagator.h index 52c05ae56f..85ad97b0fc 100644 --- a/api/include/opentelemetry/context/propagation/composite_propagator.h +++ b/api/include/opentelemetry/context/propagation/composite_propagator.h @@ -67,6 +67,21 @@ class CompositePropagator : public TextMapPropagator return propagators_.size() ? tmp_context : context; } + /** + * Invoke callback with fields set to carrier by `inject` method for all the + * configured propagators + * Returns true if all invocation return true + */ + bool Fields(nostd::function_ref callback) const noexcept override + { + bool status = true; + for (auto &p : propagators_) + { + status = status && p->Fields(callback); + } + return status; + } + private: std::vector> propagators_; }; diff --git a/api/include/opentelemetry/context/propagation/noop_propagator.h b/api/include/opentelemetry/context/propagation/noop_propagator.h index ece0229ae8..7c5edc5f8a 100644 --- a/api/include/opentelemetry/context/propagation/noop_propagator.h +++ b/api/include/opentelemetry/context/propagation/noop_propagator.h @@ -27,6 +27,11 @@ class NoOpPropagator : public TextMapPropagator /** Noop inject function does nothing */ void Inject(TextMapCarrier & /*carrier*/, const context::Context &context) noexcept override {} + + bool Fields(nostd::function_ref callback) const noexcept override + { + return true; + } }; } // namespace propagation } // namespace context diff --git a/api/include/opentelemetry/context/propagation/text_map_propagator.h b/api/include/opentelemetry/context/propagation/text_map_propagator.h index efa2686441..7efdc4919d 100644 --- a/api/include/opentelemetry/context/propagation/text_map_propagator.h +++ b/api/include/opentelemetry/context/propagation/text_map_propagator.h @@ -18,11 +18,19 @@ namespace propagation class TextMapCarrier { public: - /*returns the value associated with the passed key.*/ + // returns the value associated with the passed key. virtual nostd::string_view Get(nostd::string_view key) const noexcept = 0; - /*stores the key-value pair.*/ + // stores the key-value pair. virtual void Set(nostd::string_view key, nostd::string_view value) noexcept = 0; + + /* list of all the keys in the carrier. + By default, it returns true without invoking callback */ + virtual bool Keys(nostd::function_ref callback) const noexcept + { + return true; + } + virtual ~TextMapCarrier() = default; }; // The TextMapPropagator class provides an interface that enables extracting and injecting @@ -40,6 +48,11 @@ class TextMapPropagator // Sets the context for carrier with self defined rules. virtual void Inject(TextMapCarrier &carrier, const context::Context &context) noexcept = 0; + + // Gets the fields set in the carrier by the `inject` method + virtual bool Fields(nostd::function_ref callback) const noexcept = 0; + + virtual ~TextMapPropagator() = default; }; } // namespace propagation } // namespace context diff --git a/api/include/opentelemetry/trace/propagation/b3_propagator.h b/api/include/opentelemetry/trace/propagation/b3_propagator.h index 9aac90f03e..f9485bd619 100644 --- a/api/include/opentelemetry/trace/propagation/b3_propagator.h +++ b/api/include/opentelemetry/trace/propagation/b3_propagator.h @@ -150,6 +150,11 @@ class B3Propagator : public B3PropagatorExtractor carrier.Set(kB3CombinedHeader, nostd::string_view(trace_identity, sizeof(trace_identity))); } + + bool Fields(nostd::function_ref callback) const noexcept override + { + return callback(kB3CombinedHeader); + } }; class B3PropagatorMultiHeader : public B3PropagatorExtractor @@ -173,6 +178,11 @@ class B3PropagatorMultiHeader : public B3PropagatorExtractor carrier.Set(kB3SpanIdHeader, nostd::string_view(span_id, sizeof(span_id))); carrier.Set(kB3SampledHeader, nostd::string_view(trace_flags + 1, 1)); } + + bool Fields(nostd::function_ref callback) const noexcept override + { + return callback(kB3TraceIdHeader) && callback(kB3SpanIdHeader) && callback(kB3SampledHeader); + } }; } // namespace propagation diff --git a/api/include/opentelemetry/trace/propagation/http_trace_context.h b/api/include/opentelemetry/trace/propagation/http_trace_context.h index 5bee19c9b7..41c6b1e61d 100644 --- a/api/include/opentelemetry/trace/propagation/http_trace_context.h +++ b/api/include/opentelemetry/trace/propagation/http_trace_context.h @@ -160,6 +160,11 @@ class HttpTraceContext : public opentelemetry::context::propagation::TextMapProp return ExtractContextFromTraceHeaders(trace_parent, trace_state); } + + bool Fields(nostd::function_ref callback) const noexcept override + { + return (callback(kTraceParent) && callback(kTraceState)); + } }; } // namespace propagation } // namespace trace diff --git a/api/include/opentelemetry/trace/propagation/jaeger.h b/api/include/opentelemetry/trace/propagation/jaeger.h index f1a842bdeb..6203752b91 100644 --- a/api/include/opentelemetry/trace/propagation/jaeger.h +++ b/api/include/opentelemetry/trace/propagation/jaeger.h @@ -15,7 +15,7 @@ namespace trace namespace propagation { -static const nostd::string_view kTraceHeader = "uber-trace-id"; +static const nostd::string_view kJaegerTraceHeader = "uber-trace-id"; class JaegerPropagator : public context::propagation::TextMapPropagator { @@ -45,7 +45,7 @@ class JaegerPropagator : public context::propagation::TextMapPropagator trace_identity[trace_id_length + span_id_length + 4] = '0'; trace_identity[trace_id_length + span_id_length + 5] = span_context.IsSampled() ? '1' : '0'; - carrier.Set(kTraceHeader, nostd::string_view(trace_identity, sizeof(trace_identity))); + carrier.Set(kJaegerTraceHeader, nostd::string_view(trace_identity, sizeof(trace_identity))); } context::Context Extract(const context::propagation::TextMapCarrier &carrier, @@ -56,6 +56,11 @@ class JaegerPropagator : public context::propagation::TextMapPropagator return SetSpan(context, sp); } + bool Fields(nostd::function_ref callback) const noexcept override + { + return callback(kJaegerTraceHeader); + } + private: static constexpr uint8_t kIsSampled = 0x01; @@ -67,7 +72,7 @@ class JaegerPropagator : public context::propagation::TextMapPropagator static SpanContext ExtractImpl(const context::propagation::TextMapCarrier &carrier) { - nostd::string_view trace_identity = carrier.Get(kTraceHeader); + nostd::string_view trace_identity = carrier.Get(kJaegerTraceHeader); const size_t trace_field_count = 4; nostd::string_view trace_fields[trace_field_count]; diff --git a/api/test/baggage/propagation/baggage_propagator_test.cc b/api/test/baggage/propagation/baggage_propagator_test.cc index 25f340bd3a..ad54c841ae 100644 --- a/api/test/baggage/propagation/baggage_propagator_test.cc +++ b/api/test/baggage/propagation/baggage_propagator_test.cc @@ -67,5 +67,13 @@ TEST(BaggagePropagatorTest, ExtractAndInjectBaggage) BaggageCarrierTest carrier2; format.Inject(carrier2, ctx2); EXPECT_EQ(carrier2.headers_[kBaggageHeader.data()], baggage.second); + + std::vector fields; + format.Fields([&fields](nostd::string_view field) { + fields.push_back(field.data()); + return true; + }); + EXPECT_EQ(fields.size(), 1); + EXPECT_EQ(fields[0], kBaggageHeader.data()); } } diff --git a/api/test/context/propagation/composite_propagator_test.cc b/api/test/context/propagation/composite_propagator_test.cc index 5168cec989..d516fe17d2 100644 --- a/api/test/context/propagation/composite_propagator_test.cc +++ b/api/test/context/propagation/composite_propagator_test.cc @@ -111,4 +111,14 @@ TEST_F(CompositePropagatorTest, Inject) EXPECT_EQ(carrier.headers_["traceparent"], "00-0102030405060708090a0b0c0d0e0f10-0102030405060708-01"); EXPECT_EQ(carrier.headers_["b3"], "0102030405060708090a0b0c0d0e0f10-0102030405060708-1"); + + std::vector fields; + composite_propagator_->Fields([&fields](nostd::string_view field) { + fields.push_back(field.data()); + return true; + }); + EXPECT_EQ(fields.size(), 3); + EXPECT_EQ(fields[0], opentelemetry::trace::propagation::kTraceParent); + EXPECT_EQ(fields[1], opentelemetry::trace::propagation::kTraceState); + EXPECT_EQ(fields[2], opentelemetry::trace::propagation::kB3CombinedHeader); } diff --git a/api/test/trace/propagation/http_text_format_test.cc b/api/test/trace/propagation/http_text_format_test.cc index a775c3a9ac..497d716bb9 100644 --- a/api/test/trace/propagation/http_text_format_test.cc +++ b/api/test/trace/propagation/http_text_format_test.cc @@ -198,4 +198,13 @@ TEST(GlobalPropagator, SetAndGet) EXPECT_TRUE(carrier.headers_.count("traceparent") > 0); EXPECT_TRUE(carrier.headers_.count("tracestate") > 0); EXPECT_EQ(carrier.headers_["tracestate"], trace_state_value); + + std::vector fields; + propagator->Fields([&fields](nostd::string_view field) { + fields.push_back(field.data()); + return true; + }); + EXPECT_EQ(fields.size(), 2); + EXPECT_EQ(fields[0], opentelemetry::trace::propagation::kTraceParent); + EXPECT_EQ(fields[1], opentelemetry::trace::propagation::kTraceState); } diff --git a/api/test/trace/propagation/jaeger_propagation_test.cc b/api/test/trace/propagation/jaeger_propagation_test.cc index 85a126e663..a0e0ade270 100644 --- a/api/test/trace/propagation/jaeger_propagation_test.cc +++ b/api/test/trace/propagation/jaeger_propagation_test.cc @@ -147,6 +147,14 @@ TEST(JaegerPropagatorTest, InjectsContext) format.Inject(carrier, context::RuntimeContext::GetCurrent()); EXPECT_EQ(carrier.headers_["uber-trace-id"], "0102030405060708090a0b0c0d0e0f10:0102030405060708:0:01"); + + std::vector fields; + format.Fields([&fields](nostd::string_view field) { + fields.push_back(field.data()); + return true; + }); + EXPECT_EQ(fields.size(), 1); + EXPECT_EQ(fields[0], opentelemetry::trace::propagation::kJaegerTraceHeader); } TEST(JaegerPropagatorTest, DoNotInjectInvalidContext) From 8695e8a1f3e64e69aa5d1aa70ea1b131322b6447 Mon Sep 17 00:00:00 2001 From: iocumine Date: Fri, 2 Jul 2021 20:34:35 +0200 Subject: [PATCH 09/11] nlohmann_json::nlohmann_json added (#888) --- exporters/otlp/CMakeLists.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/exporters/otlp/CMakeLists.txt b/exporters/otlp/CMakeLists.txt index 3af587b4a8..1ca788af58 100644 --- a/exporters/otlp/CMakeLists.txt +++ b/exporters/otlp/CMakeLists.txt @@ -33,8 +33,10 @@ if(WITH_OTLP_HTTP) set_target_properties(opentelemetry_exporter_otlp_http PROPERTIES EXPORT_NAME otlp_http_exporter) - target_link_libraries(opentelemetry_exporter_otlp_http - PUBLIC opentelemetry_otlp_recordable http_client_curl) + target_link_libraries( + opentelemetry_exporter_otlp_http + PUBLIC opentelemetry_otlp_recordable http_client_curl + nlohmann_json::nlohmann_json) list(APPEND OPENTELEMETRY_OTLP_TARGETS opentelemetry_exporter_otlp_http) endif() From 016bb8553b2918eb0058a7e87f70717b38846d2b Mon Sep 17 00:00:00 2001 From: Tom Tan Date: Fri, 2 Jul 2021 21:43:09 -0700 Subject: [PATCH 10/11] Remove meeting link in contributing doc (#891) --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9f0aea79af..ee3cca52f2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -141,8 +141,8 @@ on each other), the owner should try to get people aligned by: split it up. If none of the above worked and the PR has been stuck for more than 2 weeks, the -owner should bring it to the [OpenTelemetry C++ SIG -meeting](https://zoom.us/j/8203130519). The meeting passcode is _77777_. +owner should bring it to the OpenTelemetry C++ SIG meeting. See +[README.md](README.md#contributing) for the meeting link. ## Useful Resources From 4292a57fb438283a222d2a4b19d84e7fd6ea15ee Mon Sep 17 00:00:00 2001 From: Tom Tan Date: Sat, 3 Jul 2021 00:12:50 -0700 Subject: [PATCH 11/11] Fix assertion to check the correct attribute value type (#890) --- exporters/otlp/src/otlp_recordable.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/exporters/otlp/src/otlp_recordable.cc b/exporters/otlp/src/otlp_recordable.cc index 1227850858..a17419df7e 100644 --- a/exporters/otlp/src/otlp_recordable.cc +++ b/exporters/otlp/src/otlp_recordable.cc @@ -138,9 +138,9 @@ void PopulateAttribute(opentelemetry::proto::common::v1::KeyValue *attribute, { // Assert size of variant to ensure that this method gets updated if the variant // definition changes - static_assert(nostd::variant_size::value == - kOwnedAttributeValueSize + 1, - "AttributeValue contains unknown type"); + static_assert( + nostd::variant_size::value == kOwnedAttributeValueSize, + "OwnedAttributeValue contains unknown type"); attribute->set_key(key.data(), key.size());