From 045be9c02b555545e64eff91a792cc3869a0892c Mon Sep 17 00:00:00 2001 From: Harish Shan <140232061+perhapsmaple@users.noreply.github.com> Date: Tue, 24 Oct 2023 03:12:28 +0530 Subject: [PATCH 01/31] [BUILD] DLL export interface for Metrics (#2344) --- ci/do_ci.ps1 | 12 +++++- .../common/metrics_foo_library/CMakeLists.txt | 8 +++- examples/metrics_simple/CMakeLists.txt | 19 ++++++++-- examples/otlp/CMakeLists.txt | 28 ++++++++++---- .../otlp/otlp_grpc_metric_exporter_factory.h | 2 +- .../otlp/otlp_http_metric_exporter_factory.h | 2 +- ext/src/dll/CMakeLists.txt | 14 +++++++ ext/src/dll/opentelemetry_cpp.src | 37 +++++++++++++++++++ ...periodic_exporting_metric_reader_factory.h | 2 +- .../sdk/metrics/meter_context_factory.h | 2 +- .../sdk/metrics/meter_provider.h | 2 +- .../sdk/metrics/meter_provider_factory.h | 2 +- .../view/instrument_selector_factory.h | 2 +- .../sdk/metrics/view/meter_selector_factory.h | 2 +- 14 files changed, 112 insertions(+), 22 deletions(-) diff --git a/ci/do_ci.ps1 b/ci/do_ci.ps1 index e55cf8e536..b97617e96f 100644 --- a/ci/do_ci.ps1 +++ b/ci/do_ci.ps1 @@ -58,7 +58,7 @@ switch ($action) { cmake $SRC_DIR ` -DVCPKG_TARGET_TRIPLET=x64-windows ` -DOPENTELEMETRY_BUILD_DLL=1 ` - "-DCMAKE_TOOLCHAIN_FILE=$VCPKG_DIR/scripts/buildsystems/vcpkg.cmake" + "-DCMAKE_TOOLCHAIN_FILE=$VCPKG_DIR/scripts/buildsystems/vcpkg.cmake" $exit = $LASTEXITCODE if ($exit -ne 0) { exit $exit @@ -79,6 +79,16 @@ switch ($action) { if ($exit -ne 0) { exit $exit } + examples\metrics_simple\Debug\metrics_ostream_example.exe + $exit = $LASTEXITCODE + if ($exit -ne 0) { + exit $exit + } + examples\logs_simple\Debug\example_logs_simple.exe + $exit = $LASTEXITCODE + if ($exit -ne 0) { + exit $exit + } } "cmake.maintainer.test" { cd "$BUILD_DIR" diff --git a/examples/common/metrics_foo_library/CMakeLists.txt b/examples/common/metrics_foo_library/CMakeLists.txt index a91b2595b8..abda93c3e6 100644 --- a/examples/common/metrics_foo_library/CMakeLists.txt +++ b/examples/common/metrics_foo_library/CMakeLists.txt @@ -1,6 +1,12 @@ # Copyright The OpenTelemetry Authors # SPDX-License-Identifier: Apache-2.0 +if(DEFINED OPENTELEMETRY_BUILD_DLL) + add_definitions(-DOPENTELEMETRY_BUILD_IMPORT_DLL) +endif() + add_library(common_metrics_foo_library foo_library.h foo_library.cc) set_target_version(common_metrics_foo_library) -target_link_libraries(common_metrics_foo_library PUBLIC opentelemetry_api) + +target_link_libraries(common_metrics_foo_library + PUBLIC ${CMAKE_THREAD_LIBS_INIT} opentelemetry_api) diff --git a/examples/metrics_simple/CMakeLists.txt b/examples/metrics_simple/CMakeLists.txt index 2018ed808c..0fc8c24621 100644 --- a/examples/metrics_simple/CMakeLists.txt +++ b/examples/metrics_simple/CMakeLists.txt @@ -1,9 +1,20 @@ # Copyright The OpenTelemetry Authors # SPDX-License-Identifier: Apache-2.0 +if(DEFINED OPENTELEMETRY_BUILD_DLL) + add_definitions(-DOPENTELEMETRY_BUILD_IMPORT_DLL) +endif() + include_directories(${CMAKE_SOURCE_DIR}/exporters/ostream/include) + add_executable(metrics_ostream_example metrics_ostream.cc) -target_link_libraries( - metrics_ostream_example ${CMAKE_THREAD_LIBS_INIT} opentelemetry_metrics - opentelemetry_exporter_ostream_metrics opentelemetry_resources - common_metrics_foo_library) +target_link_libraries(metrics_ostream_example ${CMAKE_THREAD_LIBS_INIT} + common_metrics_foo_library) + +if(DEFINED OPENTELEMETRY_BUILD_DLL) + target_link_libraries(metrics_ostream_example opentelemetry_cpp) +else() + target_link_libraries( + metrics_ostream_example opentelemetry_metrics + opentelemetry_exporter_ostream_metrics opentelemetry_resources) +endif() diff --git a/examples/otlp/CMakeLists.txt b/examples/otlp/CMakeLists.txt index 398300ab36..5d051a52cc 100644 --- a/examples/otlp/CMakeLists.txt +++ b/examples/otlp/CMakeLists.txt @@ -28,10 +28,15 @@ if(WITH_OTLP_GRPC) add_executable(example_otlp_grpc_metric grpc_metric_main.cc) - target_link_libraries( - example_otlp_grpc_metric ${CMAKE_THREAD_LIBS_INIT} - common_metrics_foo_library opentelemetry_metrics - opentelemetry_exporter_otlp_grpc_metrics) + target_link_libraries(example_otlp_grpc_metric ${CMAKE_THREAD_LIBS_INIT} + common_metrics_foo_library) + + if(DEFINED OPENTELEMETRY_BUILD_DLL) + target_link_libraries(example_otlp_grpc_metric opentelemetry_cpp) + else() + target_link_libraries(example_otlp_grpc_metric opentelemetry_metrics + opentelemetry_exporter_otlp_grpc_metrics) + endif() # LOG @@ -66,10 +71,17 @@ if(WITH_OTLP_HTTP) # METRIC add_executable(example_otlp_http_metric http_metric_main.cc) - target_link_libraries( - example_otlp_http_metric ${CMAKE_THREAD_LIBS_INIT} - common_metrics_foo_library opentelemetry_metrics - opentelemetry_exporter_otlp_http_metric) + target_link_libraries(example_otlp_http_metric ${CMAKE_THREAD_LIBS_INIT} + common_metrics_foo_library) + + if(DEFINED OPENTELEMETRY_BUILD_DLL) + target_link_libraries(example_otlp_http_metric opentelemetry_cpp + opentelemetry_common) + else() + target_link_libraries( + example_otlp_http_metric common_metrics_foo_library opentelemetry_metrics + opentelemetry_exporter_otlp_http_metric) + endif() # LOG diff --git a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_metric_exporter_factory.h b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_metric_exporter_factory.h index d605100ae6..f8b3ee1fc3 100644 --- a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_metric_exporter_factory.h +++ b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_metric_exporter_factory.h @@ -15,7 +15,7 @@ namespace otlp /** * Factory class for OtlpGrpcMetricExporter. */ -class OtlpGrpcMetricExporterFactory +class OPENTELEMETRY_EXPORT OtlpGrpcMetricExporterFactory { public: /** diff --git a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_http_metric_exporter_factory.h b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_http_metric_exporter_factory.h index 2fe0476575..7fa7980470 100644 --- a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_http_metric_exporter_factory.h +++ b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_http_metric_exporter_factory.h @@ -17,7 +17,7 @@ namespace otlp /** * Factory class for OtlpHttpMetricExporter. */ -class OtlpHttpMetricExporterFactory +class OPENTELEMETRY_EXPORT OtlpHttpMetricExporterFactory { public: /** diff --git a/ext/src/dll/CMakeLists.txt b/ext/src/dll/CMakeLists.txt index c0b6b91745..687d55e01f 100644 --- a/ext/src/dll/CMakeLists.txt +++ b/ext/src/dll/CMakeLists.txt @@ -22,6 +22,20 @@ if(WITH_OTLP_HTTP) PRIVATE opentelemetry_exporter_otlp_http) endif() +target_link_libraries( + opentelemetry_cpp PRIVATE opentelemetry_metrics + opentelemetry_exporter_ostream_metrics) + +if(WITH_OTLP_GRPC) + target_link_libraries(opentelemetry_cpp + PRIVATE opentelemetry_exporter_otlp_grpc_metrics) +endif() + +if(WITH_OTLP_HTTP) + target_link_libraries(opentelemetry_cpp + PRIVATE opentelemetry_exporter_otlp_http_metric) +endif() + target_link_libraries( opentelemetry_cpp PRIVATE opentelemetry_logs opentelemetry_exporter_ostream_logs) diff --git a/ext/src/dll/opentelemetry_cpp.src b/ext/src/dll/opentelemetry_cpp.src index 5d6d5e0092..49226ec543 100644 --- a/ext/src/dll/opentelemetry_cpp.src +++ b/ext/src/dll/opentelemetry_cpp.src @@ -57,15 +57,48 @@ EXPORTS ?ForceFlush@TracerProvider@trace@sdk@v1@opentelemetry@@QEAA_NV?$duration@_JU?$ratio@$00$0PECEA@@std@@@chrono@std@@@Z ?ForceFlush@LoggerProvider@logs@sdk@v1@opentelemetry@@QEAA_NV?$duration@_JU?$ratio@$00$0PECEA@@std@@@chrono@std@@@Z ??0OStreamLogRecordExporter@logs@exporter@v1@opentelemetry@@QEAA@AEAV?$basic_ostream@DU?$char_traits@D@std@@@std@@@Z + + // public: static class std::unique_ptr > __cdecl opentelemetry::v1::exporter::metrics::OStreamMetricExporterFactory::Create(void) + ?Create@OStreamMetricExporterFactory@metrics@exporter@v1@opentelemetry@@SA?AV?$unique_ptr@VPushMetricExporter@metrics@sdk@v1@opentelemetry@@U?$default_delete@VPushMetricExporter@metrics@sdk@v1@opentelemetry@@@std@@@std@@XZ + // public: static class std::unique_ptr > __cdecl opentelemetry::v1::sdk::metrics::PeriodicExportingMetricReaderFactory::Create(class std::unique_ptr >,struct opentelemetry::v1::sdk::metrics::PeriodicExportingMetricReaderOptions const & __ptr64) + ?Create@PeriodicExportingMetricReaderFactory@metrics@sdk@v1@opentelemetry@@SA?AV?$unique_ptr@VMetricReader@metrics@sdk@v1@opentelemetry@@U?$default_delete@VMetricReader@metrics@sdk@v1@opentelemetry@@@std@@@std@@V?$unique_ptr@VPushMetricExporter@metrics@sdk@v1@opentelemetry@@U?$default_delete@VPushMetricExporter@metrics@sdk@v1@opentelemetry@@@std@@@7@AEBUPeriodicExportingMetricReaderOptions@2345@@Z + // public: static class std::unique_ptr > __cdecl opentelemetry::v1::sdk::metrics::MeterProviderFactory::Create(void) + ?Create@MeterProviderFactory@metrics@sdk@v1@opentelemetry@@SA?AV?$unique_ptr@VMeterProvider@metrics@v1@opentelemetry@@U?$default_delete@VMeterProvider@metrics@v1@opentelemetry@@@std@@@std@@XZ + // public: static class std::unique_ptr > __cdecl opentelemetry::v1::sdk::metrics::MeterContextFactory::Create(void) + ?Create@MeterContextFactory@metrics@sdk@v1@opentelemetry@@SA?AV?$unique_ptr@VMeterContext@metrics@sdk@v1@opentelemetry@@U?$default_delete@VMeterContext@metrics@sdk@v1@opentelemetry@@@std@@@std@@XZ + // public: static class std::unique_ptr > __cdecl opentelemetry::v1::sdk::metrics::MeterProviderFactory::Create(class std::unique_ptr >) + ?Create@MeterProviderFactory@metrics@sdk@v1@opentelemetry@@SA?AV?$unique_ptr@VMeterProvider@metrics@v1@opentelemetry@@U?$default_delete@VMeterProvider@metrics@v1@opentelemetry@@@std@@@std@@V?$unique_ptr@VMeterContext@metrics@sdk@v1@opentelemetry@@U?$default_delete@VMeterContext@metrics@sdk@v1@opentelemetry@@@std@@@7@@Z + // public: static class std::unique_ptr > __cdecl opentelemetry::v1::sdk::metrics::ViewFactory::Create(class std::basic_string,class std::allocator > const &,class std::basic_string,class std::allocator > const &,class std::basic_string,class std::allocator > const &,enum opentelemetry::v1::sdk::metrics::AggregationType,class std::shared_ptr) + ?Create@ViewFactory@metrics@sdk@v1@opentelemetry@@SA?AV?$unique_ptr@VView@metrics@sdk@v1@opentelemetry@@U?$default_delete@VView@metrics@sdk@v1@opentelemetry@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@7@00W4AggregationType@2345@V?$shared_ptr@VAggregationConfig@metrics@sdk@v1@opentelemetry@@@7@@Z + // public: static class std::unique_ptr > __cdecl opentelemetry::v1::sdk::metrics::ViewFactory::Create(class std::basic_string,class std::allocator > const &,class std::basic_string,class std::allocator > const &,class std::basic_string,class std::allocator > const &,enum opentelemetry::v1::sdk::metrics::AggregationType) + ?Create@ViewFactory@metrics@sdk@v1@opentelemetry@@SA?AV?$unique_ptr@VView@metrics@sdk@v1@opentelemetry@@U?$default_delete@VView@metrics@sdk@v1@opentelemetry@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@7@00W4AggregationType@2345@@Z + // public: static class std::unique_ptr > __cdecl opentelemetry::v1::sdk::metrics::MeterSelectorFactory::Create(class opentelemetry::v1::nostd::string_view,class opentelemetry::v1::nostd::string_view,class opentelemetry::v1::nostd::string_view) + ?Create@MeterSelectorFactory@metrics@sdk@v1@opentelemetry@@SA?AV?$unique_ptr@VMeterSelector@metrics@sdk@v1@opentelemetry@@U?$default_delete@VMeterSelector@metrics@sdk@v1@opentelemetry@@@std@@@std@@Vstring_view@nostd@45@00@Z + // public: static class std::unique_ptr > __cdecl opentelemetry::v1::sdk::metrics::InstrumentSelectorFactory::Create(enum opentelemetry::v1::sdk::metrics::InstrumentType,class opentelemetry::v1::nostd::string_view,class opentelemetry::v1::nostd::string_view) + ?Create@InstrumentSelectorFactory@metrics@sdk@v1@opentelemetry@@SA?AV?$unique_ptr@VInstrumentSelector@metrics@sdk@v1@opentelemetry@@U?$default_delete@VInstrumentSelector@metrics@sdk@v1@opentelemetry@@@std@@@std@@W4InstrumentType@2345@Vstring_view@nostd@45@1@Z + + // public: void __cdecl opentelemetry::v1::sdk::metrics::MeterContext::AddMetricReader(class std::shared_ptr) + ?AddMetricReader@MeterContext@metrics@sdk@v1@opentelemetry@@QEAAXV?$shared_ptr@VMetricReader@metrics@sdk@v1@opentelemetry@@@std@@@Z + // public: void __cdecl opentelemetry::v1::sdk::metrics::MeterProvider::AddMetricReader(class std::shared_ptr) + ?AddMetricReader@MeterProvider@metrics@sdk@v1@opentelemetry@@QEAAXV?$shared_ptr@VMetricReader@metrics@sdk@v1@opentelemetry@@@std@@@Z + // public: void __cdecl opentelemetry::v1::sdk::metrics::MeterProvider::AddView(class std::unique_ptr >,class std::unique_ptr >,class std::unique_ptr >) + ?AddView@MeterProvider@metrics@sdk@v1@opentelemetry@@QEAAXV?$unique_ptr@VInstrumentSelector@metrics@sdk@v1@opentelemetry@@U?$default_delete@VInstrumentSelector@metrics@sdk@v1@opentelemetry@@@std@@@std@@V?$unique_ptr@VMeterSelector@metrics@sdk@v1@opentelemetry@@U?$default_delete@VMeterSelector@metrics@sdk@v1@opentelemetry@@@std@@@7@V?$unique_ptr@VView@metrics@sdk@v1@opentelemetry@@U?$default_delete@VView@metrics@sdk@v1@opentelemetry@@@std@@@7@@Z + + #if defined(WITH_OTLP_GRPC) || defined(WITH_OTLP_HTTP) ?GetOtlpDefaultTracesTimeout@otlp@exporter@v1@opentelemetry@@YA?AV?$duration@_JU?$ratio@$00$0JIJGIA@@std@@@chrono@std@@XZ ?GetOtlpDefaultTracesHeaders@otlp@exporter@v1@opentelemetry@@YA?AV?$multimap@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V12@Ucmp_ic@otlp@exporter@v1@opentelemetry@@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V12@@std@@@2@@std@@XZ ?GetOtlpDefaultLogsTimeout@otlp@exporter@v1@opentelemetry@@YA?AV?$duration@_JU?$ratio@$00$0JIJGIA@@std@@@chrono@std@@XZ ?GetOtlpDefaultLogsHeaders@otlp@exporter@v1@opentelemetry@@YA?AV?$multimap@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V12@Ucmp_ic@otlp@exporter@v1@opentelemetry@@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V12@@std@@@2@@std@@XZ + ?GetOtlpDefaultMetricsTimeout@otlp@exporter@v1@opentelemetry@@YA?AV?$duration@_JU?$ratio@$00$0JIJGIA@@std@@@chrono@std@@XZ + ?GetOtlpDefaultMetricsHeaders@otlp@exporter@v1@opentelemetry@@YA?AV?$multimap@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V12@Ucmp_ic@otlp@exporter@v1@opentelemetry@@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V12@@std@@@2@@std@@XZ #endif // defined(WITH_OTLP_GRPC) || defined(WITH_OTLP_HTTP) #if defined(WITH_OTLP_GRPC) // public: static class std::unique_ptr > __cdecl opentelemetry::v1::exporter::otlp::OtlpGrpcLogRecordExporterFactory::Create(struct opentelemetry::v1::exporter::otlp::OtlpGrpcExporterOptions const & __ptr64) ?Create@OtlpGrpcLogRecordExporterFactory@otlp@exporter@v1@opentelemetry@@SA?AV?$unique_ptr@VLogRecordExporter@logs@sdk@v1@opentelemetry@@U?$default_delete@VLogRecordExporter@logs@sdk@v1@opentelemetry@@@std@@@std@@AEBUOtlpGrpcExporterOptions@2345@@Z + // public: static class std::unique_ptr > __cdecl opentelemetry::v1::exporter::otlp::OtlpGrpcMetricExporterFactory::Create(struct opentelemetry::v1::exporter::otlp::OtlpGrpcMetricExporterOptions const & __ptr64) + ?Create@OtlpGrpcMetricExporterFactory@otlp@exporter@v1@opentelemetry@@SA?AV?$unique_ptr@VPushMetricExporter@metrics@sdk@v1@opentelemetry@@U?$default_delete@VPushMetricExporter@metrics@sdk@v1@opentelemetry@@@std@@@std@@AEBUOtlpGrpcMetricExporterOptions@2345@@Z + ?GetOtlpDefaultGrpcTracesEndpoint@otlp@exporter@v1@opentelemetry@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ ?GetOtlpDefaultGrpcTracesIsInsecure@otlp@exporter@v1@opentelemetry@@YA_NXZ ?GetOtlpDefaultTracesSslCertificatePath@otlp@exporter@v1@opentelemetry@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ @@ -76,5 +109,9 @@ EXPORTS ?Create@OtlpHttpLogRecordExporterFactory@otlp@exporter@v1@opentelemetry@@SA?AV?$unique_ptr@VLogRecordExporter@logs@sdk@v1@opentelemetry@@U?$default_delete@VLogRecordExporter@logs@sdk@v1@opentelemetry@@@std@@@std@@AEBUOtlpHttpLogRecordExporterOptions@2345@@Z ?GetOtlpDefaultHttpTracesEndpoint@otlp@exporter@v1@opentelemetry@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ ?GetOtlpDefaultHttpLogsEndpoint@otlp@exporter@v1@opentelemetry@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ + + // public: static class std::unique_ptr > __cdecl opentelemetry::v1::exporter::otlp::OtlpHttpMetricExporterFactory::Create(struct opentelemetry::v1::exporter::otlp::OtlpHttpMetricExporterOptions const &) + ?Create@OtlpHttpMetricExporterFactory@otlp@exporter@v1@opentelemetry@@SA?AV?$unique_ptr@VPushMetricExporter@metrics@sdk@v1@opentelemetry@@U?$default_delete@VPushMetricExporter@metrics@sdk@v1@opentelemetry@@@std@@@std@@AEBUOtlpHttpMetricExporterOptions@2345@@Z + ?GetOtlpDefaultHttpMetricsEndpoint@otlp@exporter@v1@opentelemetry@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ #endif // defined(WITH_OTLP_HTTP) // clang-format on diff --git a/sdk/include/opentelemetry/sdk/metrics/export/periodic_exporting_metric_reader_factory.h b/sdk/include/opentelemetry/sdk/metrics/export/periodic_exporting_metric_reader_factory.h index c4254793f3..1c5c1a0d7b 100644 --- a/sdk/include/opentelemetry/sdk/metrics/export/periodic_exporting_metric_reader_factory.h +++ b/sdk/include/opentelemetry/sdk/metrics/export/periodic_exporting_metric_reader_factory.h @@ -16,7 +16,7 @@ namespace metrics class MetricReader; class PushMetricExporter; -class PeriodicExportingMetricReaderFactory +class OPENTELEMETRY_EXPORT PeriodicExportingMetricReaderFactory { public: static std::unique_ptr Create(std::unique_ptr exporter, diff --git a/sdk/include/opentelemetry/sdk/metrics/meter_context_factory.h b/sdk/include/opentelemetry/sdk/metrics/meter_context_factory.h index d5ca16cc27..13e3a9f290 100644 --- a/sdk/include/opentelemetry/sdk/metrics/meter_context_factory.h +++ b/sdk/include/opentelemetry/sdk/metrics/meter_context_factory.h @@ -21,7 +21,7 @@ class ViewRegistry; /** * Factory class for MeterContext. */ -class MeterContextFactory +class OPENTELEMETRY_EXPORT MeterContextFactory { public: /** diff --git a/sdk/include/opentelemetry/sdk/metrics/meter_provider.h b/sdk/include/opentelemetry/sdk/metrics/meter_provider.h index c7089844a5..8a8c04c636 100644 --- a/sdk/include/opentelemetry/sdk/metrics/meter_provider.h +++ b/sdk/include/opentelemetry/sdk/metrics/meter_provider.h @@ -30,7 +30,7 @@ class MeterContext; class MetricCollector; class MetricReader; -class MeterProvider final : public opentelemetry::metrics::MeterProvider +class OPENTELEMETRY_EXPORT MeterProvider final : public opentelemetry::metrics::MeterProvider { public: /** diff --git a/sdk/include/opentelemetry/sdk/metrics/meter_provider_factory.h b/sdk/include/opentelemetry/sdk/metrics/meter_provider_factory.h index 6c0375ad9d..69e77ebf5e 100644 --- a/sdk/include/opentelemetry/sdk/metrics/meter_provider_factory.h +++ b/sdk/include/opentelemetry/sdk/metrics/meter_provider_factory.h @@ -56,7 +56,7 @@ namespace metrics even if this forces, temporarily, existing applications to use a downcast. */ -class MeterProviderFactory +class OPENTELEMETRY_EXPORT MeterProviderFactory { public: static std::unique_ptr Create(); diff --git a/sdk/include/opentelemetry/sdk/metrics/view/instrument_selector_factory.h b/sdk/include/opentelemetry/sdk/metrics/view/instrument_selector_factory.h index f30b1e27c1..0af1efe04b 100644 --- a/sdk/include/opentelemetry/sdk/metrics/view/instrument_selector_factory.h +++ b/sdk/include/opentelemetry/sdk/metrics/view/instrument_selector_factory.h @@ -14,7 +14,7 @@ namespace metrics class InstrumentSelector; -class InstrumentSelectorFactory +class OPENTELEMETRY_EXPORT InstrumentSelectorFactory { public: static std::unique_ptr Create( diff --git a/sdk/include/opentelemetry/sdk/metrics/view/meter_selector_factory.h b/sdk/include/opentelemetry/sdk/metrics/view/meter_selector_factory.h index f335f725f7..bd599d9c4b 100644 --- a/sdk/include/opentelemetry/sdk/metrics/view/meter_selector_factory.h +++ b/sdk/include/opentelemetry/sdk/metrics/view/meter_selector_factory.h @@ -16,7 +16,7 @@ namespace metrics class MeterSelector; -class MeterSelectorFactory +class OPENTELEMETRY_EXPORT MeterSelectorFactory { public: static std::unique_ptr Create(opentelemetry::nostd::string_view name, From 0baf5015ea3b4efc1e86db6fa179ec2e3918eb80 Mon Sep 17 00:00:00 2001 From: Marc Alff Date: Tue, 24 Oct 2023 10:11:32 +0200 Subject: [PATCH 02/31] [BUILD] enum CanonicalCode names too generic... conflict with old C defines (#2385) --- CHANGELOG.md | 9 ++ .../opentelemetry/trace/canonical_code.h | 141 ------------------ api/include/opentelemetry/trace/span.h | 1 - .../exporters/ostream/span_exporter.h | 2 +- .../ext/zpages/threadsafe_span_data.h | 1 - .../opentelemetry/ext/zpages/tracez_data.h | 2 - .../ext/zpages/tracez_data_aggregator.h | 3 - 7 files changed, 10 insertions(+), 149 deletions(-) delete mode 100644 api/include/opentelemetry/trace/canonical_code.h diff --git a/CHANGELOG.md b/CHANGELOG.md index 01f54cf339..536a90487a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,8 @@ Increment the: [#2378](https://github.com/open-telemetry/opentelemetry-cpp/pull/2378) * [API] Add InstrumentationScope attributes in TracerProvider::GetTracer() [#2371](https://github.com/open-telemetry/opentelemetry-cpp/pull/2371) +* [BUILD] enum CanonicalCode names too generic... conflict with old C defines + [#2385](https://github.com/open-telemetry/opentelemetry-cpp/pull/2385) Important changes: @@ -48,6 +50,13 @@ Breaking changes: * The experimental `CMake` option `WITH_REMOVE_METER_PREVIEW` is removed, use option `WITH_ABI_VERSION_2` instead. +* [BUILD] enum CanonicalCode names too generic... conflict with old C defines + [#2385](https://github.com/open-telemetry/opentelemetry-cpp/pull/2385) + * Header file `opentelemetry/trace/canonical_code.h` is unused, + and is now removed. + * This header should not be included directly in an application. + If this is the case, please remove any remaining include directives. + ## [1.12.0] 2023-10-16 * [BUILD] Support `pkg-config` diff --git a/api/include/opentelemetry/trace/canonical_code.h b/api/include/opentelemetry/trace/canonical_code.h deleted file mode 100644 index fd722891d6..0000000000 --- a/api/include/opentelemetry/trace/canonical_code.h +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include - -#include "opentelemetry/version.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace trace -{ -enum class CanonicalCode : uint8_t -{ - /** - * The operation completed successfully. - */ - OK = 0, - - /** - * The operation was cancelled (typically by the caller). - */ - CANCELLED = 1, - - /** - * Unknown error. An example of where this error may be returned is if a Status value received - * from another address space belongs to an error-space that is not known in this address space. - * Also errors raised by APIs that do not return enough error information may be converted to - * this error. - */ - UNKNOWN = 2, - - /** - * Client specified an invalid argument. Note that this differs from FAILED_PRECONDITION. - * INVALID_ARGUMENT indicates arguments that are problematic regardless of the state of the - * system (e.g., a malformed file name). - */ - INVALID_ARGUMENT = 3, - - /** - * Deadline expired before operation could complete. For operations that change the state of the - * system, this error may be returned even if the operation has completed successfully. For - * example, a successful response from a server could have been delayed long enough for the - * deadline to expire. - */ - DEADLINE_EXCEEDED = 4, - - /** - * Some requested entity (e.g., file or directory) was not found. - */ - NOT_FOUND = 5, - - /** - * Some entity that we attempted to create (e.g., file or directory) already exists. - */ - ALREADY_EXISTS = 6, - - /** - * The caller does not have permission to execute the specified operation. PERMISSION_DENIED - * must not be used for rejections caused by exhausting some resource (use RESOURCE_EXHAUSTED - * instead for those errors). PERMISSION_DENIED must not be used if the caller cannot be - * identified (use UNAUTHENTICATED instead for those errors). - */ - PERMISSION_DENIED = 7, - - /** - * Some resource has been exhausted, perhaps a per-user quota, or perhaps the entire file system - * is out of space. - */ - RESOURCE_EXHAUSTED = 8, - - /** - * Operation was rejected because the system is not in a state required for the operation's - * execution. For example, directory to be deleted may be non-empty, an rmdir operation is - * applied to a non-directory, etc. - * - * A litmus test that may help a service implementor in deciding between FAILED_PRECONDITION, - * ABORTED, and UNAVAILABLE: (a) Use UNAVAILABLE if the client can retry just the failing call. - * (b) Use ABORTED if the client should retry at a higher-level (e.g., restarting a - * read-modify-write sequence). (c) Use FAILED_PRECONDITION if the client should not retry until - * the system state has been explicitly fixed. E.g., if an "rmdir" fails because the directory - * is non-empty, FAILED_PRECONDITION should be returned since the client should not retry unless - * they have first fixed up the directory by deleting files from it. - */ - FAILED_PRECONDITION = 9, - - /** - * The operation was aborted, typically due to a concurrency issue like sequencer check - * failures, transaction aborts, etc. - * - * See litmus test above for deciding between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE. - */ - ABORTED = 10, - - /** - * Operation was attempted past the valid range. E.g., seeking or reading past end of file. - * - * Unlike INVALID_ARGUMENT, this error indicates a problem that may be fixed if the system - * state changes. For example, a 32-bit file system will generate INVALID_ARGUMENT if asked to - * read at an offset that is not in the range [0,2^32-1], but it will generate OUT_OF_RANGE if - * asked to read from an offset past the current file size. - * - * There is a fair bit of overlap between FAILED_PRECONDITION and OUT_OF_RANGE. We recommend - * using OUT_OF_RANGE (the more specific error) when it applies so that callers who are - * iterating through a space can easily look for an OUT_OF_RANGE error to detect when they are - * done. - */ - OUT_OF_RANGE = 11, - - /** - * Operation is not implemented or not supported/enabled in this service. - */ - UNIMPLEMENTED = 12, - - /** - * Internal errors. Means some invariants expected by underlying system has been broken. If you - * see one of these errors, something is very broken. - */ - INTERNAL = 13, - - /** - * The service is currently unavailable. This is a most likely a transient condition and may be - * corrected by retrying with a backoff. - * - * See litmus test above for deciding between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE. - */ - UNAVAILABLE = 14, - - /** - * Unrecoverable data loss or corruption. - */ - DATA_LOSS = 15, - - /** - * The request does not have valid authentication credentials for the operation. - */ - UNAUTHENTICATED = 16, -}; - -} // namespace trace -OPENTELEMETRY_END_NAMESPACE diff --git a/api/include/opentelemetry/trace/span.h b/api/include/opentelemetry/trace/span.h index ffd145a30d..8fb371d48c 100644 --- a/api/include/opentelemetry/trace/span.h +++ b/api/include/opentelemetry/trace/span.h @@ -10,7 +10,6 @@ #include "opentelemetry/nostd/span.h" #include "opentelemetry/nostd/string_view.h" #include "opentelemetry/nostd/type_traits.h" -#include "opentelemetry/trace/canonical_code.h" #include "opentelemetry/trace/span_context.h" #include "opentelemetry/trace/span_metadata.h" diff --git a/exporters/ostream/include/opentelemetry/exporters/ostream/span_exporter.h b/exporters/ostream/include/opentelemetry/exporters/ostream/span_exporter.h index baa4e860b1..05c8a89982 100644 --- a/exporters/ostream/include/opentelemetry/exporters/ostream/span_exporter.h +++ b/exporters/ostream/include/opentelemetry/exporters/ostream/span_exporter.h @@ -55,7 +55,7 @@ class OStreamSpanExporter final : public opentelemetry::sdk::trace::SpanExporter mutable opentelemetry::common::SpinLockMutex lock_; bool isShutdown() const noexcept; - // Mapping status number to the string from api/include/opentelemetry/trace/canonical_code.h + // Mapping status number to the string from api/include/opentelemetry/trace/span_metadata.h std::map statusMap{{0, "Unset"}, {1, "Ok"}, {2, "Error"}}; // various print helpers diff --git a/ext/include/opentelemetry/ext/zpages/threadsafe_span_data.h b/ext/include/opentelemetry/ext/zpages/threadsafe_span_data.h index fdc244255b..bd1f716ad8 100644 --- a/ext/include/opentelemetry/ext/zpages/threadsafe_span_data.h +++ b/ext/include/opentelemetry/ext/zpages/threadsafe_span_data.h @@ -12,7 +12,6 @@ #include "opentelemetry/nostd/string_view.h" #include "opentelemetry/sdk/trace/recordable.h" #include "opentelemetry/sdk/trace/span_data.h" -#include "opentelemetry/trace/canonical_code.h" #include "opentelemetry/trace/span.h" #include "opentelemetry/trace/span_id.h" #include "opentelemetry/trace/trace_id.h" diff --git a/ext/include/opentelemetry/ext/zpages/tracez_data.h b/ext/include/opentelemetry/ext/zpages/tracez_data.h index 4594fbe057..5f36a6b047 100644 --- a/ext/include/opentelemetry/ext/zpages/tracez_data.h +++ b/ext/include/opentelemetry/ext/zpages/tracez_data.h @@ -12,13 +12,11 @@ #include "opentelemetry/nostd/span.h" #include "opentelemetry/nostd/string_view.h" #include "opentelemetry/sdk/trace/span_data.h" -#include "opentelemetry/trace/canonical_code.h" #include "opentelemetry/trace/span_id.h" #include "opentelemetry/trace/trace_id.h" #include "opentelemetry/version.h" using opentelemetry::ext::zpages::ThreadsafeSpanData; -using opentelemetry::trace::CanonicalCode; using opentelemetry::trace::SpanId; using opentelemetry::trace::TraceId; diff --git a/ext/include/opentelemetry/ext/zpages/tracez_data_aggregator.h b/ext/include/opentelemetry/ext/zpages/tracez_data_aggregator.h index 62c944b704..5bc7e847db 100644 --- a/ext/include/opentelemetry/ext/zpages/tracez_data_aggregator.h +++ b/ext/include/opentelemetry/ext/zpages/tracez_data_aggregator.h @@ -19,9 +19,6 @@ #include "opentelemetry/nostd/span.h" #include "opentelemetry/nostd/string_view.h" #include "opentelemetry/sdk/trace/span_data.h" -#include "opentelemetry/trace/canonical_code.h" - -using opentelemetry::trace::CanonicalCode; OPENTELEMETRY_BEGIN_NAMESPACE namespace ext From d3a873a673809875595aaf98615b8a1a1fc501db Mon Sep 17 00:00:00 2001 From: jafonso Date: Wed, 25 Oct 2023 20:33:21 +0200 Subject: [PATCH 03/31] [BUILD] Fix cpack broken package version (#2386) --- cmake/package.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/package.cmake b/cmake/package.cmake index ef0a879e0f..c14b38fde0 100644 --- a/cmake/package.cmake +++ b/cmake/package.cmake @@ -1,6 +1,7 @@ # Copyright The OpenTelemetry Authors # SPDX-License-Identifier: Apache-2.0 +set(CPACK_PACKAGE_VERSION "${OPENTELEMETRY_VERSION}") set(CPACK_PACKAGE_DESCRIPTION "OpenTelemetry C++ for Linux") set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "OpenTelemetry C++ for Linux - C++ Implementation of OpenTelemetry Specification") set(CPACK_PACKAGE_VENDOR "OpenTelemetry") From 17da6d87c1fbd5e63260b3eb414e426e255dfebd Mon Sep 17 00:00:00 2001 From: Marc Alff Date: Fri, 27 Oct 2023 18:27:57 +0200 Subject: [PATCH 04/31] [API] Add a new AddLink() operation to Span (#2380) --- CHANGELOG.md | 11 + api/include/opentelemetry/plugin/tracer.h | 14 + .../opentelemetry/trace/default_span.h | 8 + api/include/opentelemetry/trace/noop.h | 9 + api/include/opentelemetry/trace/span.h | 138 ++++++- .../trace/span_context_kv_iterable.h | 1 + api/test/trace/noop_test.cc | 15 + examples/plugin/plugin/tracer.cc | 8 + sdk/src/trace/span.cc | 29 ++ sdk/src/trace/span.h | 7 + sdk/test/trace/tracer_test.cc | 386 ++++++++++++++++++ 11 files changed, 623 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 536a90487a..a76b91692b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,8 @@ Increment the: [#2371](https://github.com/open-telemetry/opentelemetry-cpp/pull/2371) * [BUILD] enum CanonicalCode names too generic... conflict with old C defines [#2385](https://github.com/open-telemetry/opentelemetry-cpp/pull/2385) +* [API] Add a new AddLink() operation to Span + [#2380](https://github.com/open-telemetry/opentelemetry-cpp/pull/2380) Important changes: @@ -34,6 +36,15 @@ Important changes: * When building with `CMake` option `WITH_ABI_VERSION_1=ON` (by default) the `ABI` is unchanged, and the fix is not available. +* [API] Add a new AddLink() operation to Span + [#2380](https://github.com/open-telemetry/opentelemetry-cpp/pull/2380) + * New `API` Span::AddLink() adds a single link to a span. + * New `API` Span::AddLinks() adds multiple links to a span. + * Because this is an `ABI` breaking change, the fix is only available + with the `CMake` option `WITH_ABI_VERSION_2=ON`. + * When building with `CMake` option `WITH_ABI_VERSION_1=ON` (by default) + the `ABI` is unchanged, and the fix is not available. + * [BUILD] Make WITH_OTLP_HTTP_SSL_PREVIEW mainstream [#2378](https://github.com/open-telemetry/opentelemetry-cpp/pull/2378) * The experimental `CMake` option `WITH_OTLP_HTTP_SSL_PREVIEW` diff --git a/api/include/opentelemetry/plugin/tracer.h b/api/include/opentelemetry/plugin/tracer.h index b87f9e889f..068b08071d 100644 --- a/api/include/opentelemetry/plugin/tracer.h +++ b/api/include/opentelemetry/plugin/tracer.h @@ -7,6 +7,7 @@ #include "opentelemetry/common/key_value_iterable.h" #include "opentelemetry/plugin/detail/tracer_handle.h" +#include "opentelemetry/trace/span_context_kv_iterable.h" #include "opentelemetry/trace/tracer.h" #include "opentelemetry/version.h" @@ -49,6 +50,19 @@ class Span final : public trace::Span span_->AddEvent(name, timestamp, attributes); } +#if OPENTELEMETRY_ABI_VERSION_NO >= 2 + void AddLink(const trace::SpanContext &target, + const common::KeyValueIterable &attrs) noexcept override + { + span_->AddLink(target, attrs); + } + + void AddLinks(const trace::SpanContextKeyValueIterable &links) noexcept override + { + span_->AddLinks(links); + } +#endif + void SetStatus(trace::StatusCode code, nostd::string_view description) noexcept override { span_->SetStatus(code, description); diff --git a/api/include/opentelemetry/trace/default_span.h b/api/include/opentelemetry/trace/default_span.h index cccc7951ad..7e3979501e 100644 --- a/api/include/opentelemetry/trace/default_span.h +++ b/api/include/opentelemetry/trace/default_span.h @@ -47,6 +47,14 @@ class DefaultSpan : public Span const common::KeyValueIterable & /* attributes */) noexcept override {} +#if OPENTELEMETRY_ABI_VERSION_NO >= 2 + void AddLink(const SpanContext & /* target */, + const common::KeyValueIterable & /* attrs */) noexcept override + {} + + void AddLinks(const SpanContextKeyValueIterable & /* links */) noexcept override {} +#endif + void SetStatus(StatusCode /* status */, nostd::string_view /* description */) noexcept override {} void UpdateName(nostd::string_view /* name */) noexcept override {} diff --git a/api/include/opentelemetry/trace/noop.h b/api/include/opentelemetry/trace/noop.h index c6a5838867..407f3c1ac9 100644 --- a/api/include/opentelemetry/trace/noop.h +++ b/api/include/opentelemetry/trace/noop.h @@ -15,6 +15,7 @@ #include "opentelemetry/nostd/unique_ptr.h" #include "opentelemetry/trace/span.h" #include "opentelemetry/trace/span_context.h" +#include "opentelemetry/trace/span_context_kv_iterable.h" #include "opentelemetry/trace/tracer.h" #include "opentelemetry/trace/tracer_provider.h" #include "opentelemetry/version.h" @@ -58,6 +59,14 @@ class OPENTELEMETRY_EXPORT NoopSpan final : public Span const common::KeyValueIterable & /*attributes*/) noexcept override {} +#if OPENTELEMETRY_ABI_VERSION_NO >= 2 + void AddLink(const SpanContext & /* target */, + const common::KeyValueIterable & /* attrs */) noexcept override + {} + + void AddLinks(const SpanContextKeyValueIterable & /* links */) noexcept override {} +#endif + void SetStatus(StatusCode /*code*/, nostd::string_view /*description*/) noexcept override {} void UpdateName(nostd::string_view /*name*/) noexcept override {} diff --git a/api/include/opentelemetry/trace/span.h b/api/include/opentelemetry/trace/span.h index 8fb371d48c..27e91ceec4 100644 --- a/api/include/opentelemetry/trace/span.h +++ b/api/include/opentelemetry/trace/span.h @@ -11,6 +11,8 @@ #include "opentelemetry/nostd/string_view.h" #include "opentelemetry/nostd/type_traits.h" #include "opentelemetry/trace/span_context.h" +#include "opentelemetry/trace/span_context_kv_iterable.h" +#include "opentelemetry/trace/span_context_kv_iterable_view.h" #include "opentelemetry/trace/span_metadata.h" #include "opentelemetry/version.h" @@ -23,6 +25,31 @@ class Tracer; /** * A Span represents a single operation within a Trace. + * + * Span attributes can be provided: + * - at span creation time, using Tracer::StartSpan(), + * - during the span lifetime, using Span::SetAttribute() + * + * Please note that head samplers, + * in the SDK (@ref opentelemetry::sdk::trace::Sampler), + * can only make sampling decisions based on data known + * at span creation time. + * + * When attributes are known early, adding attributes + * with @ref opentelemetry::trace::Tracer::StartSpan() is preferable. + * + * Attributes added or changed with Span::SetAttribute() + * can not change a sampler decision. + * + * Likewise, links can be provided: + * - at span creation time, using Tracer::StartSpan(), + * - during the span lifetime, using Span::AddLink() or Span::AddLinks(). + * + * When links are known early, adding links + * with @ref opentelemetry::trace::Tracer::StartSpan() is preferable. + * + * Links added with Span::AddLink() or Span::AddLinks() + * can not change a sampler decision. */ class Span { @@ -40,9 +67,14 @@ class Span Span &operator=(const Span &) = delete; Span &operator=(Span &&) = delete; - // Sets an attribute on the Span. If the Span previously contained a mapping - // for - // the key, the old value is replaced. + /** + * Sets an attribute on the Span (ABI). + * + * If the Span previously contained a mapping for the key, + * the old value is replaced. + * + * See comments about sampling in @ref opentelemetry::trace::Span + */ virtual void SetAttribute(nostd::string_view key, const common::AttributeValue &value) noexcept = 0; @@ -98,6 +130,106 @@ class Span attributes.begin(), attributes.end()}); } +#if OPENTELEMETRY_ABI_VERSION_NO >= 2 + + /** + * Add link (ABI). + * + * See comments about sampling in @ref opentelemetry::trace::Span + * + * @since ABI_VERSION 2 + */ + virtual void AddLink(const SpanContext &target, + const common::KeyValueIterable &attrs) noexcept = 0; + + /** + * Add links (ABI). + * + * See comments about sampling in @ref opentelemetry::trace::Span + * + * @since ABI_VERSION 2 + */ + virtual void AddLinks(const SpanContextKeyValueIterable &links) noexcept = 0; + + /** + * Add link (API helper). + * + * See comments about sampling in @ref opentelemetry::trace::Span + * + * @since ABI_VERSION 2 + */ + template ::value> * = nullptr> + void AddLink(const SpanContext &target, const U &attrs) + { + common::KeyValueIterableView view(attrs); + this->AddLink(target, view); + } + + /** + * Add link (API helper). + * + * See comments about sampling in @ref opentelemetry::trace::Span + * + * @since ABI_VERSION 2 + */ + void AddLink(const SpanContext &target, + std::initializer_list> attrs) + { + /* Build a container from std::initializer_list. */ + nostd::span> container{ + attrs.begin(), attrs.end()}; + + /* Build a view on the container. */ + common::KeyValueIterableView< + nostd::span>> + view(container); + + return this->AddLink(target, view); + } + + /** + * Add links (API helper). + * + * See comments about sampling in @ref opentelemetry::trace::Span + * + * @since ABI_VERSION 2 + */ + template ::value> * = nullptr> + void AddLinks(const U &links) + { + SpanContextKeyValueIterableView view(links); + this->AddLinks(view); + } + + /** + * Add links (API helper). + * + * See comments about sampling in @ref opentelemetry::trace::Span + * + * @since ABI_VERSION 2 + */ + void AddLinks( + std::initializer_list< + std::pair>>> + links) + { + /* Build a container from std::initializer_list. */ + nostd::span>>> + container{links.begin(), links.end()}; + + /* Build a view on the container. */ + SpanContextKeyValueIterableView>>>> + view(container); + + return this->AddLinks(view); + } + +#endif /* OPENTELEMETRY_ABI_VERSION_NO */ + // Sets the status of the span. The default status is Unset. Only the value of // the last call will be // recorded, and implementations are free to ignore previous calls. diff --git a/api/include/opentelemetry/trace/span_context_kv_iterable.h b/api/include/opentelemetry/trace/span_context_kv_iterable.h index 8f3010ce9d..aed3474272 100644 --- a/api/include/opentelemetry/trace/span_context_kv_iterable.h +++ b/api/include/opentelemetry/trace/span_context_kv_iterable.h @@ -6,6 +6,7 @@ #include "opentelemetry/common/attribute_value.h" #include "opentelemetry/common/key_value_iterable_view.h" #include "opentelemetry/nostd/function_ref.h" +#include "opentelemetry/trace/span_context.h" #include "opentelemetry/version.h" OPENTELEMETRY_BEGIN_NAMESPACE diff --git a/api/test/trace/noop_test.cc b/api/test/trace/noop_test.cc index 130496faf0..b47700d442 100644 --- a/api/test/trace/noop_test.cc +++ b/api/test/trace/noop_test.cc @@ -46,6 +46,21 @@ TEST(NoopTest, UseNoopTracers) s1->GetContext(); } +#if OPENTELEMETRY_ABI_VERSION_NO >= 2 +TEST(NoopTest, UseNoopTracersAbiv2) +{ + std::shared_ptr tracer{new trace_api::NoopTracer{}}; + auto s1 = tracer->StartSpan("abc"); + + EXPECT_EQ(s1->IsRecording(), false); + + trace_api::SpanContext target(false, false); + s1->AddLink(target, {{"noop1", 1}}); + + s1->AddLinks({{trace_api::SpanContext(false, false), {{"noop2", 2}}}}); +} +#endif /* OPENTELEMETRY_ABI_VERSION_NO >= 2 */ + TEST(NoopTest, StartSpan) { std::shared_ptr tracer{new trace_api::NoopTracer{}}; diff --git a/examples/plugin/plugin/tracer.cc b/examples/plugin/plugin/tracer.cc index 55de64438d..14d1a746df 100644 --- a/examples/plugin/plugin/tracer.cc +++ b/examples/plugin/plugin/tracer.cc @@ -49,6 +49,14 @@ class Span final : public trace::Span const common::KeyValueIterable & /*attributes*/) noexcept override {} +#if OPENTELEMETRY_ABI_VERSION_NO >= 2 + void AddLink(const trace::SpanContext & /* target */, + const common::KeyValueIterable & /* attrs */) noexcept override + {} + + void AddLinks(const trace::SpanContextKeyValueIterable & /* links */) noexcept override {} +#endif + void SetStatus(trace::StatusCode /*code*/, nostd::string_view /*description*/) noexcept override {} diff --git a/sdk/src/trace/span.cc b/sdk/src/trace/span.cc index c7524d43aa..25708cddd9 100644 --- a/sdk/src/trace/span.cc +++ b/sdk/src/trace/span.cc @@ -146,6 +146,35 @@ void Span::AddEvent(nostd::string_view name, recordable_->AddEvent(name, timestamp, attributes); } +#if OPENTELEMETRY_ABI_VERSION_NO >= 2 +void Span::AddLink(const opentelemetry::trace::SpanContext &target, + const opentelemetry::common::KeyValueIterable &attrs) noexcept +{ + std::lock_guard lock_guard{mu_}; + if (recordable_ == nullptr) + { + return; + } + + recordable_->AddLink(target, attrs); +} + +void Span::AddLinks(const opentelemetry::trace::SpanContextKeyValueIterable &links) noexcept +{ + std::lock_guard lock_guard{mu_}; + if (recordable_ == nullptr) + { + return; + } + + links.ForEachKeyValue([&](opentelemetry::trace::SpanContext span_context, + const common::KeyValueIterable &attributes) { + recordable_->AddLink(span_context, attributes); + return true; + }); +} +#endif + void Span::SetStatus(opentelemetry::trace::StatusCode code, nostd::string_view description) noexcept { std::lock_guard lock_guard{mu_}; diff --git a/sdk/src/trace/span.h b/sdk/src/trace/span.h index 75e31e9500..eb603b9025 100644 --- a/sdk/src/trace/span.h +++ b/sdk/src/trace/span.h @@ -42,6 +42,13 @@ class Span final : public opentelemetry::trace::Span opentelemetry::common::SystemTimestamp timestamp, const opentelemetry::common::KeyValueIterable &attributes) noexcept override; +#if OPENTELEMETRY_ABI_VERSION_NO >= 2 + void AddLink(const opentelemetry::trace::SpanContext &target, + const opentelemetry::common::KeyValueIterable &attrs) noexcept override; + + void AddLinks(const opentelemetry::trace::SpanContextKeyValueIterable &links) noexcept override; +#endif + void SetStatus(opentelemetry::trace::StatusCode code, nostd::string_view description) noexcept override; diff --git a/sdk/test/trace/tracer_test.cc b/sdk/test/trace/tracer_test.cc index 45b5fc010f..36cc135a1d 100644 --- a/sdk/test/trace/tracer_test.cc +++ b/sdk/test/trace/tracer_test.cc @@ -519,6 +519,392 @@ TEST(Tracer, SpanSetLinks) } } +#if OPENTELEMETRY_ABI_VERSION_NO >= 2 +TEST(Tracer, SpanAddLinkAbiv2) +{ + InMemorySpanExporter *exporter = new InMemorySpanExporter(); + std::shared_ptr span_data = exporter->GetData(); + auto tracer = initTracer(std::unique_ptr{exporter}); + + { + auto span = tracer->StartSpan("span"); + SpanContext target(false, false); + // Single link attribute passed through Initialization list + span->AddLink(target, {{"attr2", 2}}); + span->End(); + + auto spans = span_data->GetSpans(); + ASSERT_EQ(1, spans.size()); + + auto &span_data_links = spans.at(0)->GetLinks(); + ASSERT_EQ(1, span_data_links.size()); + auto link = span_data_links.at(0); + auto attrs = link.GetAttributes(); + ASSERT_EQ(nostd::get(attrs.at("attr2")), 2); + } + + { + auto span = tracer->StartSpan("span"); + SpanContext target(false, false); + // Multiple link attributes passed through Initialization list + span->AddLink(target, {{"attr2", 2}, {"attr3", 3}}); + span->End(); + + auto spans = span_data->GetSpans(); + ASSERT_EQ(1, spans.size()); + + auto &span_data_links = spans.at(0)->GetLinks(); + ASSERT_EQ(1, span_data_links.size()); + auto link = span_data_links.at(0); + auto attrs = link.GetAttributes(); + ASSERT_EQ(nostd::get(attrs.at("attr2")), 2); + ASSERT_EQ(nostd::get(attrs.at("attr3")), 3); + } + + { + std::map attrs_map = {{"attr1", "1"}, {"attr2", "2"}}; + + auto span = tracer->StartSpan("span"); + SpanContext target(false, false); + span->AddLink(target, attrs_map); + span->End(); + + auto spans = span_data->GetSpans(); + + auto &span_data_links = spans.at(0)->GetLinks(); + ASSERT_EQ(1, span_data_links.size()); + auto link = span_data_links.at(0); + auto attrs = link.GetAttributes(); + ASSERT_EQ(nostd::get(attrs.at("attr1")), "1"); + ASSERT_EQ(nostd::get(attrs.at("attr2")), "2"); + } + + { + auto span = tracer->StartSpan("span"); + SpanContext target(false, false); + + // Single link attribute passed through Initialization list + span->AddLink(target, {{"attr1", 1}}); + + // Multiple link attributes passed through Initialization list + span->AddLink(target, {{"attr2", 2}, {"attr3", 3}}); + + std::map attrs_map = {{"attr4", "4"}, {"attr5", "5"}}; + span->AddLink(target, attrs_map); + + span->End(); + + auto spans = span_data->GetSpans(); + ASSERT_EQ(1, spans.size()); + + auto &span_data_links = spans.at(0)->GetLinks(); + ASSERT_EQ(3, span_data_links.size()); + + { + auto link = span_data_links.at(0); + auto attrs = link.GetAttributes(); + ASSERT_EQ(attrs.size(), 1); + ASSERT_EQ(nostd::get(attrs.at("attr1")), 1); + } + + { + auto link = span_data_links.at(1); + auto attrs = link.GetAttributes(); + ASSERT_EQ(attrs.size(), 2); + ASSERT_EQ(nostd::get(attrs.at("attr2")), 2); + ASSERT_EQ(nostd::get(attrs.at("attr3")), 3); + } + + { + auto link = span_data_links.at(2); + auto attrs = link.GetAttributes(); + ASSERT_EQ(attrs.size(), 2); + ASSERT_EQ(nostd::get(attrs.at("attr4")), "4"); + ASSERT_EQ(nostd::get(attrs.at("attr5")), "5"); + } + } +} + +TEST(Tracer, SpanAddLinksAbiv2) +{ + InMemorySpanExporter *exporter = new InMemorySpanExporter(); + std::shared_ptr span_data = exporter->GetData(); + auto tracer = initTracer(std::unique_ptr{exporter}); + + { + auto span = tracer->StartSpan("span"); + // Single span link passed through Initialization list + span->AddLinks({{SpanContext(false, false), {{"attr2", 2}}}}); + span->End(); + + auto spans = span_data->GetSpans(); + ASSERT_EQ(1, spans.size()); + + auto &span_data_links = spans.at(0)->GetLinks(); + ASSERT_EQ(1, span_data_links.size()); + auto link = span_data_links.at(0); + ASSERT_EQ(nostd::get(link.GetAttributes().at("attr2")), 2); + } + + { + auto span = tracer->StartSpan("span"); + // Multiple span links passed through Initialization list + span->AddLinks( + {{SpanContext(false, false), {{"attr2", 2}}}, {SpanContext(false, false), {{"attr3", 3}}}}); + span->End(); + + auto spans = span_data->GetSpans(); + ASSERT_EQ(1, spans.size()); + + auto &span_data_links = spans.at(0)->GetLinks(); + ASSERT_EQ(2, span_data_links.size()); + auto link1 = span_data_links.at(0); + ASSERT_EQ(nostd::get(link1.GetAttributes().at("attr2")), 2); + auto link2 = span_data_links.at(1); + ASSERT_EQ(nostd::get(link2.GetAttributes().at("attr3")), 3); + } + + { + auto span = tracer->StartSpan("span"); + // Multiple links, each with multiple attributes passed through Initialization list + span->AddLinks({{SpanContext(false, false), {{"attr2", 2}, {"attr3", 3}}}, + {SpanContext(false, false), {{"attr4", 4}}}}); + span->End(); + + auto spans = span_data->GetSpans(); + ASSERT_EQ(1, spans.size()); + + auto &span_data_links = spans.at(0)->GetLinks(); + ASSERT_EQ(2, span_data_links.size()); + auto link1 = span_data_links.at(0); + ASSERT_EQ(nostd::get(link1.GetAttributes().at("attr2")), 2); + ASSERT_EQ(nostd::get(link1.GetAttributes().at("attr3")), 3); + auto link2 = span_data_links.at(1); + ASSERT_EQ(nostd::get(link2.GetAttributes().at("attr4")), 4); + } + + { + std::map attrs1 = {{"attr1", "1"}, {"attr2", "2"}}; + std::map attrs2 = {{"attr3", "3"}, {"attr4", "4"}}; + + std::vector>> links = { + {SpanContext(false, false), attrs1}, {SpanContext(false, false), attrs2}}; + + auto span = tracer->StartSpan("span"); + span->AddLinks(links); + span->End(); + + auto spans = span_data->GetSpans(); + + auto &span_data_links = spans.at(0)->GetLinks(); + ASSERT_EQ(2, span_data_links.size()); + auto link1 = span_data_links.at(0); + ASSERT_EQ(nostd::get(link1.GetAttributes().at("attr1")), "1"); + ASSERT_EQ(nostd::get(link1.GetAttributes().at("attr2")), "2"); + auto link2 = span_data_links.at(1); + ASSERT_EQ(nostd::get(link2.GetAttributes().at("attr3")), "3"); + ASSERT_EQ(nostd::get(link2.GetAttributes().at("attr4")), "4"); + } + + { + auto span = tracer->StartSpan("span"); + + // Single span link passed through Initialization list + span->AddLinks({{SpanContext(false, false), {{"attr10", 10}}}}); + span->AddLinks({{SpanContext(false, false), {{"attr11", 11}}}}); + + // Multiple span links passed through Initialization list + span->AddLinks({{SpanContext(false, false), {{"attr12", 12}}}, + {SpanContext(false, false), {{"attr13", 13}}}}); + span->AddLinks({{SpanContext(false, false), {{"attr14", 14}}}, + {SpanContext(false, false), {{"attr15", 15}}}}); + + // Multiple links, each with multiple attributes passed through Initialization list + span->AddLinks({{SpanContext(false, false), {{"attr16", 16}, {"attr17", 17}}}, + {SpanContext(false, false), {{"attr18", 18}}}}); + span->AddLinks({{SpanContext(false, false), {{"attr19", 19}, {"attr20", 20}}}, + {SpanContext(false, false), {{"attr21", 21}}}}); + + std::map attrsa1 = {{"attra1", "1"}, {"attra2", "2"}}; + std::map attrsa2 = {{"attra3", "3"}, {"attra4", "4"}}; + + std::vector>> linksa = { + {SpanContext(false, false), attrsa1}, {SpanContext(false, false), attrsa2}}; + + span->AddLinks(linksa); + + std::map attrsb1 = {{"attrb1", "1"}, {"attrb2", "2"}}; + std::map attrsb2 = {{"attrb3", "3"}, {"attrb4", "4"}}; + + std::vector>> linksb = { + {SpanContext(false, false), attrsb1}, {SpanContext(false, false), attrsb2}}; + + span->AddLinks(linksb); + + span->End(); + + auto spans = span_data->GetSpans(); + ASSERT_EQ(1, spans.size()); + + auto &span_data_links = spans.at(0)->GetLinks(); + ASSERT_EQ(14, span_data_links.size()); + + { + auto link = span_data_links.at(0); + auto attrs = link.GetAttributes(); + ASSERT_EQ(attrs.size(), 1); + ASSERT_EQ(nostd::get(attrs.at("attr10")), 10); + } + + { + auto link = span_data_links.at(1); + auto attrs = link.GetAttributes(); + ASSERT_EQ(attrs.size(), 1); + ASSERT_EQ(nostd::get(attrs.at("attr11")), 11); + } + + { + auto link = span_data_links.at(2); + auto attrs = link.GetAttributes(); + ASSERT_EQ(attrs.size(), 1); + ASSERT_EQ(nostd::get(attrs.at("attr12")), 12); + } + + { + auto link = span_data_links.at(3); + auto attrs = link.GetAttributes(); + ASSERT_EQ(attrs.size(), 1); + ASSERT_EQ(nostd::get(attrs.at("attr13")), 13); + } + + { + auto link = span_data_links.at(4); + auto attrs = link.GetAttributes(); + ASSERT_EQ(attrs.size(), 1); + ASSERT_EQ(nostd::get(attrs.at("attr14")), 14); + } + + { + auto link = span_data_links.at(5); + auto attrs = link.GetAttributes(); + ASSERT_EQ(attrs.size(), 1); + ASSERT_EQ(nostd::get(attrs.at("attr15")), 15); + } + + { + auto link = span_data_links.at(6); + auto attrs = link.GetAttributes(); + ASSERT_EQ(attrs.size(), 2); + ASSERT_EQ(nostd::get(attrs.at("attr16")), 16); + ASSERT_EQ(nostd::get(attrs.at("attr17")), 17); + } + + { + auto link = span_data_links.at(7); + auto attrs = link.GetAttributes(); + ASSERT_EQ(attrs.size(), 1); + ASSERT_EQ(nostd::get(attrs.at("attr18")), 18); + } + + { + auto link = span_data_links.at(8); + auto attrs = link.GetAttributes(); + ASSERT_EQ(attrs.size(), 2); + ASSERT_EQ(nostd::get(attrs.at("attr19")), 19); + ASSERT_EQ(nostd::get(attrs.at("attr20")), 20); + } + + { + auto link = span_data_links.at(9); + auto attrs = link.GetAttributes(); + ASSERT_EQ(attrs.size(), 1); + ASSERT_EQ(nostd::get(attrs.at("attr21")), 21); + } + + { + auto link = span_data_links.at(10); + auto attrs = link.GetAttributes(); + ASSERT_EQ(attrs.size(), 2); + ASSERT_EQ(nostd::get(attrs.at("attra1")), "1"); + ASSERT_EQ(nostd::get(attrs.at("attra2")), "2"); + } + + { + auto link = span_data_links.at(11); + auto attrs = link.GetAttributes(); + ASSERT_EQ(attrs.size(), 2); + ASSERT_EQ(nostd::get(attrs.at("attra3")), "3"); + ASSERT_EQ(nostd::get(attrs.at("attra4")), "4"); + } + + { + auto link = span_data_links.at(12); + auto attrs = link.GetAttributes(); + ASSERT_EQ(attrs.size(), 2); + ASSERT_EQ(nostd::get(attrs.at("attrb1")), "1"); + ASSERT_EQ(nostd::get(attrs.at("attrb2")), "2"); + } + + { + auto link = span_data_links.at(13); + auto attrs = link.GetAttributes(); + ASSERT_EQ(attrs.size(), 2); + ASSERT_EQ(nostd::get(attrs.at("attrb3")), "3"); + ASSERT_EQ(nostd::get(attrs.at("attrb4")), "4"); + } + } +} + +TEST(Tracer, SpanMixLinksAbiv2) +{ + InMemorySpanExporter *exporter = new InMemorySpanExporter(); + std::shared_ptr span_data = exporter->GetData(); + auto tracer = initTracer(std::unique_ptr{exporter}); + + { + // Link 1 added at StartSpan + auto span = + tracer->StartSpan("span", {{"attr1", 1}}, {{SpanContext(false, false), {{"attr2", 2}}}}); + + SpanContext target(false, false); + // Link 2 added with AddLink + span->AddLink(target, {{"attr3", 3}}); + + // Link 3 added with AddLinks + span->AddLinks({{SpanContext(false, false), {{"attr4", 4}}}}); + + span->End(); + + auto spans = span_data->GetSpans(); + ASSERT_EQ(1, spans.size()); + + auto &span_data_links = spans.at(0)->GetLinks(); + ASSERT_EQ(3, span_data_links.size()); + + { + auto link = span_data_links.at(0); + auto attrs = link.GetAttributes(); + ASSERT_EQ(attrs.size(), 1); + ASSERT_EQ(nostd::get(attrs.at("attr2")), 2); + } + + { + auto link = span_data_links.at(1); + auto attrs = link.GetAttributes(); + ASSERT_EQ(attrs.size(), 1); + ASSERT_EQ(nostd::get(attrs.at("attr3")), 3); + } + + { + auto link = span_data_links.at(2); + auto attrs = link.GetAttributes(); + ASSERT_EQ(attrs.size(), 1); + ASSERT_EQ(nostd::get(attrs.at("attr4")), 4); + } + } +} +#endif /* OPENTELEMETRY_ABI_VERSION_NO >= 2 */ + TEST(Tracer, TestAlwaysOnSampler) { InMemorySpanExporter *exporter = new InMemorySpanExporter(); From 758687cde41c5a4a854818585520b47305011267 Mon Sep 17 00:00:00 2001 From: Alex E <36134278+chusitoo@users.noreply.github.com> Date: Mon, 30 Oct 2023 12:55:32 -0400 Subject: [PATCH 05/31] [opentracing-shim] Add check for sampled context (#2390) --- opentracing-shim/src/tracer_shim.cc | 21 ++++++++++++++------- opentracing-shim/test/tracer_shim_test.cc | 1 + 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/opentracing-shim/src/tracer_shim.cc b/opentracing-shim/src/tracer_shim.cc index c8805d15ef..41c6404624 100644 --- a/opentracing-shim/src/tracer_shim.cc +++ b/opentracing-shim/src/tracer_shim.cc @@ -148,13 +148,20 @@ opentracing::expected> TracerShim::ext auto span_context = opentelemetry::trace::GetSpan(context)->GetContext(); auto baggage = opentelemetry::baggage::GetBaggage(context); - // If the extracted SpanContext is invalid AND the extracted Baggage is empty, - // this operation MUST return a null value, and otherwise it MUST return a - // SpanContext Shim instance with the extracted values. - SpanContextShim *context_shim = (!span_context.IsValid() && utils::isBaggageEmpty(baggage)) - ? nullptr - : new (std::nothrow) SpanContextShim(span_context, baggage); - + // The operation MUST return a `SpanContext` Shim instance with the extracted values if any of + // these conditions are met: + // * `SpanContext` is valid. + // * `SpanContext` is sampled. + // * `SpanContext` contains non-empty extracted `Baggage`. + // Otherwise, the operation MUST return null or empty value. + SpanContextShim *context_shim = + (!span_context.IsValid() && !span_context.IsSampled() && utils::isBaggageEmpty(baggage)) + ? nullptr + : new (std::nothrow) SpanContextShim(span_context, baggage); + + // Note: Invalid but sampled `SpanContext` instances are returned as a way to support + // jaeger-debug-id headers (https://github.com/jaegertracing/jaeger-client-java#via-http-headers) + // which are used to force propagation of debug information. return opentracing::make_expected(std::unique_ptr(context_shim)); } diff --git a/opentracing-shim/test/tracer_shim_test.cc b/opentracing-shim/test/tracer_shim_test.cc index 7a06175323..9d57bbcae4 100644 --- a/opentracing-shim/test/tracer_shim_test.cc +++ b/opentracing-shim/test/tracer_shim_test.cc @@ -211,6 +211,7 @@ TEST_F(TracerShimTest, ExtractOnlyBaggage) auto span_context_shim = static_cast(span_context.value().get()); ASSERT_TRUE(span_context_shim != nullptr); ASSERT_FALSE(span_context_shim->context().IsValid()); + ASSERT_FALSE(span_context_shim->context().IsSampled()); ASSERT_FALSE(shim::utils::isBaggageEmpty(span_context_shim->baggage())); std::string value; From ca08c5a34ad4af1b6b392c8bf5fc26a5210a2f2c Mon Sep 17 00:00:00 2001 From: Harish Shan <140232061+perhapsmaple@users.noreply.github.com> Date: Wed, 1 Nov 2023 11:12:53 +0530 Subject: [PATCH 06/31] [BUILD] Fix exported definitions when building DLL with STL (#2387) --- CHANGELOG.md | 7 +++++++ ext/src/dll/opentelemetry_cpp.src | 10 ++++------ .../sdk/metrics/view/instrument_selector.h | 6 +++--- .../sdk/metrics/view/instrument_selector_factory.h | 7 ++++--- .../opentelemetry/sdk/metrics/view/meter_selector.h | 6 ++---- .../sdk/metrics/view/meter_selector_factory.h | 8 ++++---- sdk/src/metrics/view/instrument_selector_factory.cc | 4 ++-- sdk/src/metrics/view/meter_selector_factory.cc | 7 +++---- 8 files changed, 29 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a76b91692b..9acee42235 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -68,6 +68,13 @@ Breaking changes: * This header should not be included directly in an application. If this is the case, please remove any remaining include directives. +* [BUILD] Fix exported definitions when building DLL with STL + [#2387](https://github.com/open-telemetry/opentelemetry-cpp/pull/2387) + * The MeterSelector, MeterSelectorFactory, InstrumentSelector, + and InstrumentSelectorFactory APIs now use const std::string& + instead of nostd::string_view for name, version and schema to + maintain a single export definition for DLL. + ## [1.12.0] 2023-10-16 * [BUILD] Support `pkg-config` diff --git a/ext/src/dll/opentelemetry_cpp.src b/ext/src/dll/opentelemetry_cpp.src index 49226ec543..10172dbb3f 100644 --- a/ext/src/dll/opentelemetry_cpp.src +++ b/ext/src/dll/opentelemetry_cpp.src @@ -72,11 +72,10 @@ EXPORTS ?Create@ViewFactory@metrics@sdk@v1@opentelemetry@@SA?AV?$unique_ptr@VView@metrics@sdk@v1@opentelemetry@@U?$default_delete@VView@metrics@sdk@v1@opentelemetry@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@7@00W4AggregationType@2345@V?$shared_ptr@VAggregationConfig@metrics@sdk@v1@opentelemetry@@@7@@Z // public: static class std::unique_ptr > __cdecl opentelemetry::v1::sdk::metrics::ViewFactory::Create(class std::basic_string,class std::allocator > const &,class std::basic_string,class std::allocator > const &,class std::basic_string,class std::allocator > const &,enum opentelemetry::v1::sdk::metrics::AggregationType) ?Create@ViewFactory@metrics@sdk@v1@opentelemetry@@SA?AV?$unique_ptr@VView@metrics@sdk@v1@opentelemetry@@U?$default_delete@VView@metrics@sdk@v1@opentelemetry@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@7@00W4AggregationType@2345@@Z - // public: static class std::unique_ptr > __cdecl opentelemetry::v1::sdk::metrics::MeterSelectorFactory::Create(class opentelemetry::v1::nostd::string_view,class opentelemetry::v1::nostd::string_view,class opentelemetry::v1::nostd::string_view) - ?Create@MeterSelectorFactory@metrics@sdk@v1@opentelemetry@@SA?AV?$unique_ptr@VMeterSelector@metrics@sdk@v1@opentelemetry@@U?$default_delete@VMeterSelector@metrics@sdk@v1@opentelemetry@@@std@@@std@@Vstring_view@nostd@45@00@Z - // public: static class std::unique_ptr > __cdecl opentelemetry::v1::sdk::metrics::InstrumentSelectorFactory::Create(enum opentelemetry::v1::sdk::metrics::InstrumentType,class opentelemetry::v1::nostd::string_view,class opentelemetry::v1::nostd::string_view) - ?Create@InstrumentSelectorFactory@metrics@sdk@v1@opentelemetry@@SA?AV?$unique_ptr@VInstrumentSelector@metrics@sdk@v1@opentelemetry@@U?$default_delete@VInstrumentSelector@metrics@sdk@v1@opentelemetry@@@std@@@std@@W4InstrumentType@2345@Vstring_view@nostd@45@1@Z - + // public: static class std::unique_ptr > __cdecl opentelemetry::v1::sdk::metrics::MeterSelectorFactory::Create(class std::basic_string,class std::allocator > const &,class std::basic_string,class std::allocator > const &,class std::basic_string,class std::allocator > const &) + ?Create@MeterSelectorFactory@metrics@sdk@v1@opentelemetry@@SA?AV?$unique_ptr@VMeterSelector@metrics@sdk@v1@opentelemetry@@U?$default_delete@VMeterSelector@metrics@sdk@v1@opentelemetry@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@7@00@Z + // public: static class std::unique_ptr > __cdecl opentelemetry::v1::sdk::metrics::InstrumentSelectorFactory::Create(enum opentelemetry::v1::sdk::metrics::InstrumentType,class std::basic_string,class std::allocator > const &,class std::basic_string,class std::allocator > const &) + ?Create@InstrumentSelectorFactory@metrics@sdk@v1@opentelemetry@@SA?AV?$unique_ptr@VInstrumentSelector@metrics@sdk@v1@opentelemetry@@U?$default_delete@VInstrumentSelector@metrics@sdk@v1@opentelemetry@@@std@@@std@@W4InstrumentType@2345@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@7@1@Z // public: void __cdecl opentelemetry::v1::sdk::metrics::MeterContext::AddMetricReader(class std::shared_ptr) ?AddMetricReader@MeterContext@metrics@sdk@v1@opentelemetry@@QEAAXV?$shared_ptr@VMetricReader@metrics@sdk@v1@opentelemetry@@@std@@@Z // public: void __cdecl opentelemetry::v1::sdk::metrics::MeterProvider::AddMetricReader(class std::shared_ptr) @@ -84,7 +83,6 @@ EXPORTS // public: void __cdecl opentelemetry::v1::sdk::metrics::MeterProvider::AddView(class std::unique_ptr >,class std::unique_ptr >,class std::unique_ptr >) ?AddView@MeterProvider@metrics@sdk@v1@opentelemetry@@QEAAXV?$unique_ptr@VInstrumentSelector@metrics@sdk@v1@opentelemetry@@U?$default_delete@VInstrumentSelector@metrics@sdk@v1@opentelemetry@@@std@@@std@@V?$unique_ptr@VMeterSelector@metrics@sdk@v1@opentelemetry@@U?$default_delete@VMeterSelector@metrics@sdk@v1@opentelemetry@@@std@@@7@V?$unique_ptr@VView@metrics@sdk@v1@opentelemetry@@U?$default_delete@VView@metrics@sdk@v1@opentelemetry@@@std@@@7@@Z - #if defined(WITH_OTLP_GRPC) || defined(WITH_OTLP_HTTP) ?GetOtlpDefaultTracesTimeout@otlp@exporter@v1@opentelemetry@@YA?AV?$duration@_JU?$ratio@$00$0JIJGIA@@std@@@chrono@std@@XZ ?GetOtlpDefaultTracesHeaders@otlp@exporter@v1@opentelemetry@@YA?AV?$multimap@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V12@Ucmp_ic@otlp@exporter@v1@opentelemetry@@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V12@@std@@@2@@std@@XZ diff --git a/sdk/include/opentelemetry/sdk/metrics/view/instrument_selector.h b/sdk/include/opentelemetry/sdk/metrics/view/instrument_selector.h index 67c8592bb6..690a9168d0 100644 --- a/sdk/include/opentelemetry/sdk/metrics/view/instrument_selector.h +++ b/sdk/include/opentelemetry/sdk/metrics/view/instrument_selector.h @@ -4,8 +4,8 @@ #pragma once #include +#include -#include "opentelemetry/nostd/string_view.h" #include "opentelemetry/sdk/metrics/instruments.h" #include "opentelemetry/sdk/metrics/view/predicate_factory.h" #include "opentelemetry/version.h" @@ -19,8 +19,8 @@ class InstrumentSelector { public: InstrumentSelector(opentelemetry::sdk::metrics::InstrumentType instrument_type, - opentelemetry::nostd::string_view name, - opentelemetry::nostd::string_view units) + const std::string &name, + const std::string &units) : name_filter_{PredicateFactory::GetPredicate(name, PredicateType::kPattern)}, unit_filter_{PredicateFactory::GetPredicate(units, PredicateType::kExact)}, instrument_type_{instrument_type} diff --git a/sdk/include/opentelemetry/sdk/metrics/view/instrument_selector_factory.h b/sdk/include/opentelemetry/sdk/metrics/view/instrument_selector_factory.h index 0af1efe04b..3c221f123b 100644 --- a/sdk/include/opentelemetry/sdk/metrics/view/instrument_selector_factory.h +++ b/sdk/include/opentelemetry/sdk/metrics/view/instrument_selector_factory.h @@ -3,7 +3,8 @@ #pragma once -#include "opentelemetry/nostd/string_view.h" +#include + #include "opentelemetry/sdk/metrics/instruments.h" OPENTELEMETRY_BEGIN_NAMESPACE @@ -19,8 +20,8 @@ class OPENTELEMETRY_EXPORT InstrumentSelectorFactory public: static std::unique_ptr Create( opentelemetry::sdk::metrics::InstrumentType instrument_type, - opentelemetry::nostd::string_view name, - opentelemetry::nostd::string_view unit); + const std::string &name, + const std::string &unit); }; } // namespace metrics diff --git a/sdk/include/opentelemetry/sdk/metrics/view/meter_selector.h b/sdk/include/opentelemetry/sdk/metrics/view/meter_selector.h index 16d777b71f..65dba7d7b9 100644 --- a/sdk/include/opentelemetry/sdk/metrics/view/meter_selector.h +++ b/sdk/include/opentelemetry/sdk/metrics/view/meter_selector.h @@ -4,8 +4,8 @@ #pragma once #include +#include -#include "opentelemetry/nostd/string_view.h" #include "opentelemetry/sdk/metrics/view/predicate_factory.h" #include "opentelemetry/version.h" @@ -17,9 +17,7 @@ namespace metrics class MeterSelector { public: - MeterSelector(opentelemetry::nostd::string_view name, - opentelemetry::nostd::string_view version, - opentelemetry::nostd::string_view schema) + MeterSelector(const std::string &name, const std::string &version, const std::string &schema) : name_filter_{PredicateFactory::GetPredicate(name, PredicateType::kExact)}, version_filter_{PredicateFactory::GetPredicate(version, PredicateType::kExact)}, schema_filter_{PredicateFactory::GetPredicate(schema, PredicateType::kExact)} diff --git a/sdk/include/opentelemetry/sdk/metrics/view/meter_selector_factory.h b/sdk/include/opentelemetry/sdk/metrics/view/meter_selector_factory.h index bd599d9c4b..47aa77b772 100644 --- a/sdk/include/opentelemetry/sdk/metrics/view/meter_selector_factory.h +++ b/sdk/include/opentelemetry/sdk/metrics/view/meter_selector_factory.h @@ -4,8 +4,8 @@ #pragma once #include +#include -#include "opentelemetry/nostd/string_view.h" #include "opentelemetry/version.h" OPENTELEMETRY_BEGIN_NAMESPACE @@ -19,9 +19,9 @@ class MeterSelector; class OPENTELEMETRY_EXPORT MeterSelectorFactory { public: - static std::unique_ptr Create(opentelemetry::nostd::string_view name, - opentelemetry::nostd::string_view version, - opentelemetry::nostd::string_view schema); + static std::unique_ptr Create(const std::string &name, + const std::string &version, + const std::string &schema); }; } // namespace metrics diff --git a/sdk/src/metrics/view/instrument_selector_factory.cc b/sdk/src/metrics/view/instrument_selector_factory.cc index 98a587ea62..5cf4a5b968 100644 --- a/sdk/src/metrics/view/instrument_selector_factory.cc +++ b/sdk/src/metrics/view/instrument_selector_factory.cc @@ -13,8 +13,8 @@ namespace metrics std::unique_ptr InstrumentSelectorFactory::Create( opentelemetry::sdk::metrics::InstrumentType instrument_type, - opentelemetry::nostd::string_view name, - opentelemetry::nostd::string_view unit) + const std::string &name, + const std::string &unit) { std::unique_ptr instrument_selector( new InstrumentSelector(instrument_type, name, unit)); diff --git a/sdk/src/metrics/view/meter_selector_factory.cc b/sdk/src/metrics/view/meter_selector_factory.cc index f8f906d9ad..088dcd864e 100644 --- a/sdk/src/metrics/view/meter_selector_factory.cc +++ b/sdk/src/metrics/view/meter_selector_factory.cc @@ -11,10 +11,9 @@ namespace sdk namespace metrics { -std::unique_ptr MeterSelectorFactory::Create( - opentelemetry::nostd::string_view name, - opentelemetry::nostd::string_view version, - opentelemetry::nostd::string_view schema) +std::unique_ptr MeterSelectorFactory::Create(const std::string &name, + const std::string &version, + const std::string &schema) { std::unique_ptr meter_selector(new MeterSelector(name, version, schema)); return meter_selector; From 5bf2f8007f31cf0c0414c1c552edd1123c4cf018 Mon Sep 17 00:00:00 2001 From: Harish Shan <140232061+perhapsmaple@users.noreply.github.com> Date: Tue, 7 Nov 2023 01:12:59 +0530 Subject: [PATCH 07/31] [BUILD] Add missing includes to runtime_context_test (#2395) --- api/test/context/runtime_context_test.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/api/test/context/runtime_context_test.cc b/api/test/context/runtime_context_test.cc index e85fc6350d..40b11dde95 100644 --- a/api/test/context/runtime_context_test.cc +++ b/api/test/context/runtime_context_test.cc @@ -4,6 +4,9 @@ #include "opentelemetry/context/runtime_context.h" #include "opentelemetry/context/context.h" +#include +#include + #include using namespace opentelemetry; From 35a9362732216c00a24bdd4c98ebb5f9bbaab2c5 Mon Sep 17 00:00:00 2001 From: Marc Alff Date: Mon, 6 Nov 2023 23:27:16 +0100 Subject: [PATCH 08/31] [ADMIN] Add file .github/repository-settings.md (#2392) --- .github/repository-settings.md | 38 ++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 .github/repository-settings.md diff --git a/.github/repository-settings.md b/.github/repository-settings.md new file mode 100644 index 0000000000..fa86d02cfc --- /dev/null +++ b/.github/repository-settings.md @@ -0,0 +1,38 @@ +# Process + +This file documents local admin changes for opentelemetry-cpp, +per the community process: https://github.com/open-telemetry/community/blob/main/docs/how-to-configure-new-repository.md + +Please note that the EasyCLA check **MUST** stay **REQUIRED**, +it should never be disabled or bypassed, at the risk of tainting the repository. + +# Guidelines + +The best is to open a PR first that describes the change, +so it can be discussed during review (maybe it is not needed, +maybe there is an alternate solution, ...). + +The PR must add a log entry in this file, detailing: + +* the date the change is implemented +* what is changed exactly (which setting) +* a short rationale + +Admin changes are then applied only when the PR is merged. + +If for some reason a change is implemented in emergency, +before a PR can be discussed and merged, +a PR should still be prepared and pushed after the fact to +describe the settings changed. + +# Log of local changes + +## 2023-11-03 + +Created log file `.github/repository-settings.md`, since admin permissions are now granted to maintainers. + +See https://github.com/open-telemetry/community/issues/1727 + +No setting changed. + + From 86ee88615b813ea08901db029343847e77d0f38b Mon Sep 17 00:00:00 2001 From: Tom Tan Date: Fri, 10 Nov 2023 01:53:12 -0800 Subject: [PATCH 09/31] [SDK] Fix GetLogger with empty library name (#2398) --- CHANGELOG.md | 2 ++ sdk/src/logs/logger_provider.cc | 21 +++++++++------------ sdk/test/logs/logger_provider_sdk_test.cc | 14 ++++++++++++++ 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9acee42235..7317b2b5f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,8 @@ Increment the: [#2385](https://github.com/open-telemetry/opentelemetry-cpp/pull/2385) * [API] Add a new AddLink() operation to Span [#2380](https://github.com/open-telemetry/opentelemetry-cpp/pull/2380) +* [SDK] Fix GetLogger with empty library + name[#2398](https://github.com/open-telemetry/opentelemetry-cpp/pull/2398) Important changes: diff --git a/sdk/src/logs/logger_provider.cc b/sdk/src/logs/logger_provider.cc index d64863ed73..46eaa01054 100644 --- a/sdk/src/logs/logger_provider.cc +++ b/sdk/src/logs/logger_provider.cc @@ -57,6 +57,12 @@ nostd::shared_ptr LoggerProvider::GetLogger( nostd::string_view schema_url, const opentelemetry::common::KeyValueIterable &attributes) noexcept { + // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/data-model.md#field-instrumentationscope + if (library_name.empty()) + { + library_name = logger_name; + } + // Ensure only one thread can read/write from the map of loggers std::lock_guard lock_guard{lock_}; @@ -84,18 +90,9 @@ nostd::shared_ptr LoggerProvider::GetLogger( } */ - // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/data-model.md#field-instrumentationscope - std::unique_ptr lib; - if (library_name.empty()) - { - lib = instrumentationscope::InstrumentationScope::Create(logger_name, library_version, - schema_url, attributes); - } - else - { - lib = instrumentationscope::InstrumentationScope::Create(library_name, library_version, - schema_url, attributes); - } + std::unique_ptr lib = + instrumentationscope::InstrumentationScope::Create(library_name, library_version, schema_url, + attributes); loggers_.push_back(std::shared_ptr( new Logger(logger_name, context_, std::move(lib)))); diff --git a/sdk/test/logs/logger_provider_sdk_test.cc b/sdk/test/logs/logger_provider_sdk_test.cc index 51f40178ba..ecb9ea6f9c 100644 --- a/sdk/test/logs/logger_provider_sdk_test.cc +++ b/sdk/test/logs/logger_provider_sdk_test.cc @@ -111,6 +111,20 @@ TEST(LoggerProviderSDK, EventLoggerProviderFactory) auto event_logger = elp->CreateEventLogger(logger1, "otel-cpp.test"); } +TEST(LoggerPviderSDK, LoggerEquityCheck) +{ + auto lp = std::shared_ptr(new LoggerProvider()); + nostd::string_view schema_url{"https://opentelemetry.io/schemas/1.11.0"}; + + auto logger1 = lp->GetLogger("logger1", "opentelelemtry_library", "", schema_url); + auto logger2 = lp->GetLogger("logger1", "opentelelemtry_library", "", schema_url); + EXPECT_EQ(logger1, logger2); + + auto logger3 = lp->GetLogger("logger3"); + auto another_logger3 = lp->GetLogger("logger3"); + EXPECT_EQ(logger3, another_logger3); +} + class DummyLogRecordable final : public opentelemetry::sdk::logs::Recordable { public: From 63226075207c2807f61ae670355c1e705a4ce1d1 Mon Sep 17 00:00:00 2001 From: WenTao Ou Date: Sat, 11 Nov 2023 18:20:51 +0800 Subject: [PATCH 10/31] [TEST] Fix compiling problem and removed -DENABLE_TEST (#2401) --- CMakeLists.txt | 1 - ci/do_ci.ps1 | 2 +- ci/do_ci.sh | 2 +- .../otlp/test/otlp_http_exporter_test.cc | 3 ++- .../otlp_http_log_record_exporter_test.cc | 3 ++- .../test/otlp_http_metric_exporter_test.cc | 3 ++- .../ext/http/client/curl/http_client_curl.h | 5 +--- .../ext/http/client/http_client_factory.h | 4 --- .../http/client/http_client_test_factory.h | 22 ++++++++++++++++ .../http/client/nosend/http_client_nosend.h | 26 +++++++++---------- test_common/src/http/client/nosend/BUILD | 2 +- .../src/http/client/nosend/CMakeLists.txt | 2 +- .../http/client/nosend/http_client_nosend.cc | 4 +-- ..._nosend.cc => http_client_test_factory.cc} | 10 +++---- 14 files changed, 50 insertions(+), 39 deletions(-) create mode 100644 test_common/include/opentelemetry/test_common/ext/http/client/http_client_test_factory.h rename test_common/src/http/client/nosend/{http_client_factory_nosend.cc => http_client_test_factory.cc} (51%) diff --git a/CMakeLists.txt b/CMakeLists.txt index b72e58a963..de5e714916 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -579,7 +579,6 @@ list(APPEND CMAKE_PREFIX_PATH "${CMAKE_BINARY_DIR}") include(CTest) if(BUILD_TESTING) - add_definitions(-DENABLE_TEST) if(EXISTS ${CMAKE_BINARY_DIR}/lib/libgtest.a) # Prefer GTest from build tree. GTest is not always working with # CMAKE_PREFIX_PATH diff --git a/ci/do_ci.ps1 b/ci/do_ci.ps1 index b97617e96f..0b6cd9513e 100644 --- a/ci/do_ci.ps1 +++ b/ci/do_ci.ps1 @@ -27,7 +27,7 @@ $VCPKG_DIR = Join-Path "$SRC_DIR" "tools" "vcpkg" switch ($action) { "bazel.build" { - bazel build --copt=-DENABLE_TEST $BAZEL_OPTIONS --action_env=VCPKG_DIR=$VCPKG_DIR --deleted_packages=opentracing-shim -- //... + bazel build $BAZEL_OPTIONS --action_env=VCPKG_DIR=$VCPKG_DIR --deleted_packages=opentracing-shim -- //... $exit = $LASTEXITCODE if ($exit -ne 0) { exit $exit diff --git a/ci/do_ci.sh b/ci/do_ci.sh index d9dc0c178f..f679c6af04 100755 --- a/ci/do_ci.sh +++ b/ci/do_ci.sh @@ -69,7 +69,7 @@ fi echo "make command: ${MAKE_COMMAND}" echo "IWYU option: ${IWYU}" -BAZEL_OPTIONS_DEFAULT="--copt=-DENABLE_TEST --copt=-DENABLE_METRICS_EXEMPLAR_PREVIEW" +BAZEL_OPTIONS_DEFAULT="--copt=-DENABLE_METRICS_EXEMPLAR_PREVIEW" BAZEL_OPTIONS="--cxxopt=-std=c++14 $BAZEL_OPTIONS_DEFAULT" BAZEL_TEST_OPTIONS="$BAZEL_OPTIONS --test_output=errors" diff --git a/exporters/otlp/test/otlp_http_exporter_test.cc b/exporters/otlp/test/otlp_http_exporter_test.cc index 42258d2b45..1c76ad0d02 100644 --- a/exporters/otlp/test/otlp_http_exporter_test.cc +++ b/exporters/otlp/test/otlp_http_exporter_test.cc @@ -19,6 +19,7 @@ # include "opentelemetry/sdk/trace/batch_span_processor.h" # include "opentelemetry/sdk/trace/batch_span_processor_options.h" # include "opentelemetry/sdk/trace/tracer_provider.h" +# include "opentelemetry/test_common/ext/http/client/http_client_test_factory.h" # include "opentelemetry/test_common/ext/http/client/nosend/http_client_nosend.h" # include "opentelemetry/trace/provider.h" @@ -102,7 +103,7 @@ class OtlpHttpExporterTestPeer : public ::testing::Test static std::pair> GetMockOtlpHttpClient(HttpRequestContentType content_type, bool async_mode = false) { - auto http_client = http_client::HttpClientFactory::CreateNoSend(); + auto http_client = http_client::HttpClientTestFactory::Create(); return {new OtlpHttpClient(MakeOtlpHttpClientOptions(content_type, async_mode), http_client), http_client}; } diff --git a/exporters/otlp/test/otlp_http_log_record_exporter_test.cc b/exporters/otlp/test/otlp_http_log_record_exporter_test.cc index df89ca17fa..44fa812a35 100644 --- a/exporters/otlp/test/otlp_http_log_record_exporter_test.cc +++ b/exporters/otlp/test/otlp_http_log_record_exporter_test.cc @@ -22,6 +22,7 @@ # include "opentelemetry/sdk/logs/exporter.h" # include "opentelemetry/sdk/logs/logger_provider.h" # include "opentelemetry/sdk/resource/resource.h" +# include "opentelemetry/test_common/ext/http/client/http_client_test_factory.h" # include "opentelemetry/test_common/ext/http/client/nosend/http_client_nosend.h" # include @@ -103,7 +104,7 @@ class OtlpHttpLogRecordExporterTestPeer : public ::testing::Test static std::pair> GetMockOtlpHttpClient(HttpRequestContentType content_type, bool async_mode = false) { - auto http_client = http_client::HttpClientFactory::CreateNoSend(); + auto http_client = http_client::HttpClientTestFactory::Create(); return {new OtlpHttpClient(MakeOtlpHttpClientOptions(content_type, async_mode), http_client), http_client}; } diff --git a/exporters/otlp/test/otlp_http_metric_exporter_test.cc b/exporters/otlp/test/otlp_http_metric_exporter_test.cc index ed7c4dba30..8b7688adc0 100644 --- a/exporters/otlp/test/otlp_http_metric_exporter_test.cc +++ b/exporters/otlp/test/otlp_http_metric_exporter_test.cc @@ -24,6 +24,7 @@ #include "opentelemetry/sdk/metrics/export/metric_producer.h" #include "opentelemetry/sdk/metrics/instruments.h" #include "opentelemetry/sdk/resource/resource.h" +#include "opentelemetry/test_common/ext/http/client/http_client_test_factory.h" #include "opentelemetry/test_common/ext/http/client/nosend/http_client_nosend.h" #include @@ -109,7 +110,7 @@ class OtlpHttpMetricExporterTestPeer : public ::testing::Test static std::pair> GetMockOtlpHttpClient(HttpRequestContentType content_type, bool async_mode = false) { - auto http_client = http_client::HttpClientFactory::CreateNoSend(); + auto http_client = http_client::HttpClientTestFactory::Create(); return {new OtlpHttpClient(MakeOtlpHttpClientOptions(content_type, async_mode), http_client), http_client}; } diff --git a/ext/include/opentelemetry/ext/http/client/curl/http_client_curl.h b/ext/include/opentelemetry/ext/http/client/curl/http_client_curl.h index 876d9fab4f..45ee13d55c 100644 --- a/ext/include/opentelemetry/ext/http/client/curl/http_client_curl.h +++ b/ext/include/opentelemetry/ext/http/client/curl/http_client_curl.h @@ -37,6 +37,7 @@ class HttpCurlGlobalInitializer HttpCurlGlobalInitializer(HttpCurlGlobalInitializer &&) = delete; HttpCurlGlobalInitializer &operator=(const HttpCurlGlobalInitializer &) = delete; + HttpCurlGlobalInitializer &operator=(HttpCurlGlobalInitializer &&) = delete; HttpCurlGlobalInitializer(); @@ -190,9 +191,7 @@ class Session : public opentelemetry::ext::http::client::Session, */ const std::string &GetBaseUri() const { return host_; } -#ifdef ENABLE_TEST std::shared_ptr GetRequest() { return http_request_; } -#endif inline HttpClient &GetHttpClient() noexcept { return http_client_; } inline const HttpClient &GetHttpClient() const noexcept { return http_client_; } @@ -327,7 +326,6 @@ class HttpClient : public opentelemetry::ext::http::client::HttpClient void ScheduleAbortSession(uint64_t session_id); void ScheduleRemoveSession(uint64_t session_id, HttpCurlEasyResource &&resource); -#ifdef ENABLE_TEST void WaitBackgroundThreadExit() { std::unique_ptr background_thread; @@ -341,7 +339,6 @@ class HttpClient : public opentelemetry::ext::http::client::HttpClient background_thread->join(); } } -#endif private: void wakeupBackgroundThread(); diff --git a/ext/include/opentelemetry/ext/http/client/http_client_factory.h b/ext/include/opentelemetry/ext/http/client/http_client_factory.h index 8df1e578d2..43e15cf255 100644 --- a/ext/include/opentelemetry/ext/http/client/http_client_factory.h +++ b/ext/include/opentelemetry/ext/http/client/http_client_factory.h @@ -17,10 +17,6 @@ class HttpClientFactory static std::shared_ptr CreateSync(); static std::shared_ptr Create(); - -#ifdef ENABLE_TEST - static std::shared_ptr CreateNoSend(); -#endif }; } // namespace client } // namespace http diff --git a/test_common/include/opentelemetry/test_common/ext/http/client/http_client_test_factory.h b/test_common/include/opentelemetry/test_common/ext/http/client/http_client_test_factory.h new file mode 100644 index 0000000000..51f9502bb8 --- /dev/null +++ b/test_common/include/opentelemetry/test_common/ext/http/client/http_client_test_factory.h @@ -0,0 +1,22 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#include "opentelemetry/ext/http/client/http_client.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace ext +{ +namespace http +{ +namespace client +{ +class HttpClientTestFactory +{ +public: + static std::shared_ptr Create(); +}; +} // namespace client +} // namespace http +} // namespace ext +OPENTELEMETRY_END_NAMESPACE diff --git a/test_common/include/opentelemetry/test_common/ext/http/client/nosend/http_client_nosend.h b/test_common/include/opentelemetry/test_common/ext/http/client/nosend/http_client_nosend.h index 7a6fadbd11..7dddde13d4 100644 --- a/test_common/include/opentelemetry/test_common/ext/http/client/nosend/http_client_nosend.h +++ b/test_common/include/opentelemetry/test_common/ext/http/client/nosend/http_client_nosend.h @@ -3,17 +3,16 @@ #pragma once -#ifdef ENABLE_TEST -# include "opentelemetry/ext/http/client/http_client.h" -# include "opentelemetry/ext/http/common/url_parser.h" -# include "opentelemetry/version.h" +#include "opentelemetry/ext/http/client/http_client.h" +#include "opentelemetry/ext/http/common/url_parser.h" +#include "opentelemetry/version.h" -# include -# include -# include +#include +#include +#include -# include -# include "gmock/gmock.h" +#include +#include "gmock/gmock.h" OPENTELEMETRY_BEGIN_NAMESPACE namespace ext @@ -37,12 +36,12 @@ class Request : public opentelemetry::ext::http::client::Request method_ = method; } -# ifdef ENABLE_HTTP_SSL_PREVIEW +#ifdef ENABLE_HTTP_SSL_PREVIEW void SetSslOptions(const HttpSslOptions &ssl_options) noexcept override { ssl_options_ = ssl_options; } -# endif /* ENABLE_HTTP_SSL_PREVIEW */ +#endif /* ENABLE_HTTP_SSL_PREVIEW */ void SetBody(opentelemetry::ext::http::client::Body &body) noexcept override { @@ -66,9 +65,9 @@ class Request : public opentelemetry::ext::http::client::Request public: opentelemetry::ext::http::client::Method method_; -# ifdef ENABLE_HTTP_SSL_PREVIEW +#ifdef ENABLE_HTTP_SSL_PREVIEW opentelemetry::ext::http::client::HttpSslOptions ssl_options_; -# endif /* ENABLE_HTTP_SSL_PREVIEW */ +#endif /* ENABLE_HTTP_SSL_PREVIEW */ opentelemetry::ext::http::client::Body body_; opentelemetry::ext::http::client::Headers headers_; std::string uri_; @@ -186,4 +185,3 @@ class HttpClient : public opentelemetry::ext::http::client::HttpClient } // namespace http } // namespace ext OPENTELEMETRY_END_NAMESPACE -#endif diff --git a/test_common/src/http/client/nosend/BUILD b/test_common/src/http/client/nosend/BUILD index 7aaf2a61b5..fa7ba623ab 100644 --- a/test_common/src/http/client/nosend/BUILD +++ b/test_common/src/http/client/nosend/BUILD @@ -6,8 +6,8 @@ package(default_visibility = ["//visibility:public"]) cc_library( name = "http_client_nosend", srcs = [ - "http_client_factory_nosend.cc", "http_client_nosend.cc", + "http_client_test_factory.cc", ], include_prefix = "src/http/client/nosend", tags = [ diff --git a/test_common/src/http/client/nosend/CMakeLists.txt b/test_common/src/http/client/nosend/CMakeLists.txt index 1f32861b41..92a2c1f98c 100644 --- a/test_common/src/http/client/nosend/CMakeLists.txt +++ b/test_common/src/http/client/nosend/CMakeLists.txt @@ -2,7 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 if(${BUILD_TESTING}) - add_library(opentelemetry_http_client_nosend http_client_factory_nosend.cc + add_library(opentelemetry_http_client_nosend http_client_test_factory.cc http_client_nosend.cc) set_target_properties(opentelemetry_http_client_nosend diff --git a/test_common/src/http/client/nosend/http_client_nosend.cc b/test_common/src/http/client/nosend/http_client_nosend.cc index dd14e4404a..98cae0476a 100644 --- a/test_common/src/http/client/nosend/http_client_nosend.cc +++ b/test_common/src/http/client/nosend/http_client_nosend.cc @@ -1,8 +1,7 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -#ifdef ENABLE_TEST -# include "opentelemetry/test_common/ext/http/client/nosend/http_client_nosend.h" +#include "opentelemetry/test_common/ext/http/client/nosend/http_client_nosend.h" OPENTELEMETRY_BEGIN_NAMESPACE namespace ext @@ -96,4 +95,3 @@ void HttpClient::CleanupSession(uint64_t /* session_id */) {} } // namespace http } // namespace ext OPENTELEMETRY_END_NAMESPACE -#endif diff --git a/test_common/src/http/client/nosend/http_client_factory_nosend.cc b/test_common/src/http/client/nosend/http_client_test_factory.cc similarity index 51% rename from test_common/src/http/client/nosend/http_client_factory_nosend.cc rename to test_common/src/http/client/nosend/http_client_test_factory.cc index c70d1b9578..215c173549 100644 --- a/test_common/src/http/client/nosend/http_client_factory_nosend.cc +++ b/test_common/src/http/client/nosend/http_client_test_factory.cc @@ -1,15 +1,13 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -#ifdef ENABLE_TEST -# include "opentelemetry/ext/http/client/http_client.h" -# include "opentelemetry/ext/http/client/http_client_factory.h" -# include "opentelemetry/test_common/ext/http/client/nosend/http_client_nosend.h" +#include "opentelemetry/test_common/ext/http/client/http_client_test_factory.h" +#include "opentelemetry/ext/http/client/http_client.h" +#include "opentelemetry/test_common/ext/http/client/nosend/http_client_nosend.h" namespace http_client = opentelemetry::ext::http::client; -std::shared_ptr http_client::HttpClientFactory::CreateNoSend() +std::shared_ptr http_client::HttpClientTestFactory::Create() { return std::make_shared(); } -#endif From 5bd9c65c64e402bf17f73528693a9b4afe5aed2f Mon Sep 17 00:00:00 2001 From: Tom Tan Date: Sun, 12 Nov 2023 12:07:11 -0800 Subject: [PATCH 11/31] [BUILD] Check windows options are not passed to non-Windows build (#2399) --- CMakeLists.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index de5e714916..f795eadbb7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -248,6 +248,10 @@ set(OTELCPP_PROTO_PATH if(WIN32) option(WITH_ETW "Whether to include the ETW Exporter in the SDK" ON) +else() + if(DEFINED (WITH_ETW)) + message(FATAL_ERROR "WITH_ETW is only supported on Windows") + endif() endif(WIN32) # Do not convert deprecated message to error @@ -628,6 +632,9 @@ endif() include(CMakePackageConfigHelpers) if(DEFINED OPENTELEMETRY_BUILD_DLL) + if(NOT WIN32) + message(FATAL_ERROR "Build DLL is only supported on Windows!") + endif() if(NOT MSVC) message(WARNING "Build DLL is supposed to work with MSVC!") endif() From 3dfcf93c41bb1d487b3d4d1291791ea21a2a38ce Mon Sep 17 00:00:00 2001 From: Marc Alff Date: Mon, 13 Nov 2023 23:27:29 +0100 Subject: [PATCH 12/31] [EXPORTER] Rework OTLP/HTTP and OTLP/GRPC exporter options (#2388) --- CHANGELOG.md | 28 ++- examples/otlp/grpc_log_main.cc | 14 +- exporters/otlp/BUILD | 30 ++- exporters/otlp/CMakeLists.txt | 35 ++- .../exporters/otlp/otlp_grpc_client.h | 14 +- .../exporters/otlp/otlp_grpc_client_options.h | 58 +++++ .../otlp/otlp_grpc_exporter_options.h | 44 +--- .../otlp/otlp_grpc_log_record_exporter.h | 6 +- .../otlp_grpc_log_record_exporter_factory.h | 4 +- .../otlp_grpc_log_record_exporter_options.h | 31 +++ .../otlp/otlp_grpc_metric_exporter.h | 2 +- .../otlp/otlp_grpc_metric_exporter_options.h | 21 +- .../otlp/otlp_http_exporter_options.h | 98 ++++---- .../otlp_http_log_record_exporter_options.h | 98 ++++---- .../otlp/otlp_http_metric_exporter_options.h | 100 +++++---- exporters/otlp/src/otlp_grpc_client.cc | 10 +- .../otlp/src/otlp_grpc_exporter_options.cc | 38 ++++ .../otlp/src/otlp_grpc_log_record_exporter.cc | 7 +- .../otlp_grpc_log_record_exporter_factory.cc | 6 +- .../otlp_grpc_log_record_exporter_options.cc | 36 +++ .../src/otlp_grpc_metric_exporter_options.cc | 38 ++++ .../otlp/src/otlp_http_exporter_options.cc | 54 +++++ .../otlp_http_log_record_exporter_options.cc | 54 +++++ .../src/otlp_http_metric_exporter_options.cc | 55 +++++ ...p_grpc_log_record_exporter_factory_test.cc | 4 +- .../otlp_grpc_log_record_exporter_test.cc | 3 +- .../test/otlp_grpc_metric_exporter_test.cc | 209 ++++++++++++++++++ ext/src/dll/opentelemetry_cpp.src | 70 +++--- 28 files changed, 945 insertions(+), 222 deletions(-) create mode 100644 exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_client_options.h create mode 100644 exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_log_record_exporter_options.h create mode 100644 exporters/otlp/src/otlp_grpc_exporter_options.cc create mode 100644 exporters/otlp/src/otlp_grpc_log_record_exporter_options.cc create mode 100644 exporters/otlp/src/otlp_grpc_metric_exporter_options.cc create mode 100644 exporters/otlp/src/otlp_http_exporter_options.cc create mode 100644 exporters/otlp/src/otlp_http_log_record_exporter_options.cc create mode 100644 exporters/otlp/src/otlp_http_metric_exporter_options.cc create mode 100644 exporters/otlp/test/otlp_grpc_metric_exporter_test.cc diff --git a/CHANGELOG.md b/CHANGELOG.md index 7317b2b5f1..2f89ef1505 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,8 +25,10 @@ Increment the: [#2385](https://github.com/open-telemetry/opentelemetry-cpp/pull/2385) * [API] Add a new AddLink() operation to Span [#2380](https://github.com/open-telemetry/opentelemetry-cpp/pull/2380) -* [SDK] Fix GetLogger with empty library - name[#2398](https://github.com/open-telemetry/opentelemetry-cpp/pull/2398) +* [SDK] Fix GetLogger with empty library name + [#2398](https://github.com/open-telemetry/opentelemetry-cpp/pull/2398) +* [EXPORTER] Rework OTLP/HTTP and OTLP/GRPC exporter options + [#2388](https://github.com/open-telemetry/opentelemetry-cpp/pull/2388) Important changes: @@ -56,6 +58,14 @@ Important changes: * These build options are scheduled to be removed by the next release, building without SSL/TLS will no longer be possible. +* [EXPORTER] Rework OTLP/HTTP and OTLP/GRPC exporter options + [#2388](https://github.com/open-telemetry/opentelemetry-cpp/pull/2388) + * `OtlpGrpcMetricExporterOptions` used to honor `_TRACES_` + environment variables, instead of `_METRICS_` environment variables. + * The implementation of `OtlpGrpcMetricExporterOptions` is now fixed. + * Please check configuration variables, + to make sure `_METRICS_` variables are set as expected. + Breaking changes: * [BUILD] Remove WITH_REMOVE_METER_PREVIEW, use WITH_ABI_VERSION_2 instead @@ -77,6 +87,20 @@ Breaking changes: instead of nostd::string_view for name, version and schema to maintain a single export definition for DLL. +* [EXPORTER] Rework OTLP/HTTP and OTLP/GRPC exporter options + [#2388](https://github.com/open-telemetry/opentelemetry-cpp/pull/2388) + * `OtlpGrpcLogRecordExporter` incorrectly used `OtlpGrpcExporterOptions`, + which are options for traces and not logs. + * This created a bug: the `OtlpGrpcLogRecordExporter` honors `_TRACES_` + environment variables, instead of `_LOGS_` environment variables. + * `OtlpGrpcLogRecordExporter` is changed to use + `OtlpGrpcLogRecordExporterOptions` instead, fixing the bug. + * User code that initializes the SDK with a GRPC Log exporter, + and uses exporter options, should adjust to replace + `OtlpGrpcExporterOptions` with `OtlpGrpcLogRecordExporterOptions`. + * Please check configuration variables, + to make sure `_LOGS_` variables are set as expected. + ## [1.12.0] 2023-10-16 * [BUILD] Support `pkg-config` diff --git a/examples/otlp/grpc_log_main.cc b/examples/otlp/grpc_log_main.cc index b1726de358..9d7399dbaf 100644 --- a/examples/otlp/grpc_log_main.cc +++ b/examples/otlp/grpc_log_main.cc @@ -2,7 +2,9 @@ // SPDX-License-Identifier: Apache-2.0 #include "opentelemetry/exporters/otlp/otlp_grpc_exporter_factory.h" +#include "opentelemetry/exporters/otlp/otlp_grpc_exporter_options.h" #include "opentelemetry/exporters/otlp/otlp_grpc_log_record_exporter_factory.h" +#include "opentelemetry/exporters/otlp/otlp_grpc_log_record_exporter_options.h" #include "opentelemetry/logs/provider.h" #include "opentelemetry/sdk/logs/exporter.h" #include "opentelemetry/sdk/logs/logger_provider_factory.h" @@ -37,6 +39,7 @@ namespace trace_sdk = opentelemetry::sdk::trace; namespace { opentelemetry::exporter::otlp::OtlpGrpcExporterOptions opts; +opentelemetry::exporter::otlp::OtlpGrpcLogRecordExporterOptions log_opts; void InitTracer() { // Create OTLP exporter instance @@ -65,7 +68,7 @@ void CleanupTracer() void InitLogger() { // Create OTLP exporter instance - auto exporter = otlp::OtlpGrpcLogRecordExporterFactory::Create(opts); + auto exporter = otlp::OtlpGrpcLogRecordExporterFactory::Create(log_opts); auto processor = logs_sdk::SimpleLogRecordProcessorFactory::Create(std::move(exporter)); nostd::shared_ptr provider( logs_sdk::LoggerProviderFactory::Create(std::move(processor))); @@ -92,11 +95,14 @@ int main(int argc, char *argv[]) { if (argc > 1) { - opts.endpoint = argv[1]; + opts.endpoint = argv[1]; + log_opts.endpoint = argv[1]; if (argc > 2) { - opts.use_ssl_credentials = true; - opts.ssl_credentials_cacert_path = argv[2]; + opts.use_ssl_credentials = true; + log_opts.use_ssl_credentials = true; + opts.ssl_credentials_cacert_path = argv[2]; + log_opts.ssl_credentials_cacert_path = argv[2]; } } InitLogger(); diff --git a/exporters/otlp/BUILD b/exporters/otlp/BUILD index 5099b43510..a70153edd8 100644 --- a/exporters/otlp/BUILD +++ b/exporters/otlp/BUILD @@ -47,7 +47,7 @@ cc_library( hdrs = [ "include/opentelemetry/exporters/otlp/otlp_environment.h", "include/opentelemetry/exporters/otlp/otlp_grpc_client.h", - "include/opentelemetry/exporters/otlp/otlp_grpc_exporter_options.h", + "include/opentelemetry/exporters/otlp/otlp_grpc_client_options.h", "include/opentelemetry/exporters/otlp/otlp_grpc_utils.h", "include/opentelemetry/exporters/otlp/protobuf_include_prefix.h", "include/opentelemetry/exporters/otlp/protobuf_include_suffix.h", @@ -73,9 +73,11 @@ cc_library( srcs = [ "src/otlp_grpc_exporter.cc", "src/otlp_grpc_exporter_factory.cc", + "src/otlp_grpc_exporter_options.cc", ], hdrs = [ "include/opentelemetry/exporters/otlp/otlp_environment.h", + "include/opentelemetry/exporters/otlp/otlp_grpc_client_options.h", "include/opentelemetry/exporters/otlp/otlp_grpc_exporter.h", "include/opentelemetry/exporters/otlp/otlp_grpc_exporter_factory.h", "include/opentelemetry/exporters/otlp/otlp_grpc_exporter_options.h", @@ -143,6 +145,7 @@ cc_library( srcs = [ "src/otlp_http_exporter.cc", "src/otlp_http_exporter_factory.cc", + "src/otlp_http_exporter_options.cc", ], hdrs = [ "include/opentelemetry/exporters/otlp/otlp_environment.h", @@ -170,10 +173,11 @@ cc_library( srcs = [ "src/otlp_grpc_metric_exporter.cc", "src/otlp_grpc_metric_exporter_factory.cc", + "src/otlp_grpc_metric_exporter_options.cc", ], hdrs = [ "include/opentelemetry/exporters/otlp/otlp_environment.h", - "include/opentelemetry/exporters/otlp/otlp_grpc_exporter_options.h", + "include/opentelemetry/exporters/otlp/otlp_grpc_client_options.h", "include/opentelemetry/exporters/otlp/otlp_grpc_metric_exporter.h", "include/opentelemetry/exporters/otlp/otlp_grpc_metric_exporter_factory.h", "include/opentelemetry/exporters/otlp/otlp_grpc_metric_exporter_options.h", @@ -201,6 +205,7 @@ cc_library( srcs = [ "src/otlp_http_metric_exporter.cc", "src/otlp_http_metric_exporter_factory.cc", + "src/otlp_http_metric_exporter_options.cc", ], hdrs = [ "include/opentelemetry/exporters/otlp/otlp_environment.h", @@ -228,6 +233,7 @@ cc_library( srcs = [ "src/otlp_http_log_record_exporter.cc", "src/otlp_http_log_record_exporter_factory.cc", + "src/otlp_http_log_record_exporter_options.cc", ], hdrs = [ "include/opentelemetry/exporters/otlp/otlp_environment.h", @@ -255,12 +261,14 @@ cc_library( srcs = [ "src/otlp_grpc_log_record_exporter.cc", "src/otlp_grpc_log_record_exporter_factory.cc", + "src/otlp_grpc_log_record_exporter_options.cc", ], hdrs = [ "include/opentelemetry/exporters/otlp/otlp_environment.h", - "include/opentelemetry/exporters/otlp/otlp_grpc_exporter_options.h", + "include/opentelemetry/exporters/otlp/otlp_grpc_client_options.h", "include/opentelemetry/exporters/otlp/otlp_grpc_log_record_exporter.h", "include/opentelemetry/exporters/otlp/otlp_grpc_log_record_exporter_factory.h", + "include/opentelemetry/exporters/otlp/otlp_grpc_log_record_exporter_options.h", "include/opentelemetry/exporters/otlp/protobuf_include_prefix.h", "include/opentelemetry/exporters/otlp/protobuf_include_suffix.h", ], @@ -436,6 +444,22 @@ cc_test( ], ) +cc_test( + name = "otlp_grpc_metric_exporter_test", + srcs = ["test/otlp_grpc_metric_exporter_test.cc"], + tags = [ + "otlp", + "otlp_grpc_metric", + "test", + ], + deps = [ + ":otlp_grpc_metric_exporter", + "//api", + "//sdk/src/metrics", + "@com_google_googletest//:gtest_main", + ], +) + cc_test( name = "otlp_grpc_metric_exporter_factory_test", srcs = ["test/otlp_grpc_metric_exporter_factory_test.cc"], diff --git a/exporters/otlp/CMakeLists.txt b/exporters/otlp/CMakeLists.txt index adab87ff02..ec55211a6d 100644 --- a/exporters/otlp/CMakeLists.txt +++ b/exporters/otlp/CMakeLists.txt @@ -56,8 +56,10 @@ if(WITH_OTLP_GRPC) list(APPEND OPENTELEMETRY_OTLP_TARGETS opentelemetry_exporter_otlp_grpc_client) - add_library(opentelemetry_exporter_otlp_grpc - src/otlp_grpc_exporter.cc src/otlp_grpc_exporter_factory.cc) + add_library( + opentelemetry_exporter_otlp_grpc + src/otlp_grpc_exporter.cc src/otlp_grpc_exporter_factory.cc + src/otlp_grpc_exporter_options.cc) set_target_properties(opentelemetry_exporter_otlp_grpc PROPERTIES EXPORT_NAME otlp_grpc_exporter) @@ -73,7 +75,8 @@ if(WITH_OTLP_GRPC) add_library( opentelemetry_exporter_otlp_grpc_log src/otlp_grpc_log_record_exporter.cc - src/otlp_grpc_log_record_exporter_factory.cc) + src/otlp_grpc_log_record_exporter_factory.cc + src/otlp_grpc_log_record_exporter_options.cc) set_target_properties(opentelemetry_exporter_otlp_grpc_log PROPERTIES EXPORT_NAME otlp_grpc_log_record_exporter) @@ -88,7 +91,8 @@ if(WITH_OTLP_GRPC) add_library( opentelemetry_exporter_otlp_grpc_metrics - src/otlp_grpc_metric_exporter.cc src/otlp_grpc_metric_exporter_factory.cc) + src/otlp_grpc_metric_exporter.cc src/otlp_grpc_metric_exporter_factory.cc + src/otlp_grpc_metric_exporter_options.cc) set_target_properties(opentelemetry_exporter_otlp_grpc_metrics PROPERTIES EXPORT_NAME otlp_grpc_metrics_exporter) @@ -130,8 +134,10 @@ if(WITH_OTLP_HTTP) list(APPEND OPENTELEMETRY_OTLP_TARGETS opentelemetry_exporter_otlp_http_client) - add_library(opentelemetry_exporter_otlp_http - src/otlp_http_exporter.cc src/otlp_http_exporter_factory.cc) + add_library( + opentelemetry_exporter_otlp_http + src/otlp_http_exporter.cc src/otlp_http_exporter_factory.cc + src/otlp_http_exporter_options.cc) set_target_properties(opentelemetry_exporter_otlp_http PROPERTIES EXPORT_NAME otlp_http_exporter) @@ -147,7 +153,8 @@ if(WITH_OTLP_HTTP) add_library( opentelemetry_exporter_otlp_http_log src/otlp_http_log_record_exporter.cc - src/otlp_http_log_record_exporter_factory.cc) + src/otlp_http_log_record_exporter_factory.cc + src/otlp_http_log_record_exporter_options.cc) set_target_properties(opentelemetry_exporter_otlp_http_log PROPERTIES EXPORT_NAME otlp_http_log_record_exporter) @@ -162,7 +169,8 @@ if(WITH_OTLP_HTTP) add_library( opentelemetry_exporter_otlp_http_metric - src/otlp_http_metric_exporter.cc src/otlp_http_metric_exporter_factory.cc) + src/otlp_http_metric_exporter.cc src/otlp_http_metric_exporter_factory.cc + src/otlp_http_metric_exporter_options.cc) set_target_properties(opentelemetry_exporter_otlp_http_metric PROPERTIES EXPORT_NAME otlp_http_metric_exporter) @@ -295,6 +303,17 @@ if(BUILD_TESTING) TEST_PREFIX exporter.otlp. TEST_LIST otlp_grpc_log_record_exporter_factory_test) + add_executable(otlp_grpc_metric_exporter_test + test/otlp_grpc_metric_exporter_test.cc) + target_link_libraries( + otlp_grpc_metric_exporter_test ${GTEST_BOTH_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} ${GMOCK_LIB} opentelemetry_exporter_otlp_grpc + opentelemetry_exporter_otlp_grpc_metrics) + gtest_add_tests( + TARGET otlp_grpc_metric_exporter_test + TEST_PREFIX exporter.otlp. + TEST_LIST otlp_grpc_metric_exporter_test) + add_executable(otlp_grpc_metric_exporter_factory_test test/otlp_grpc_metric_exporter_factory_test.cc) target_link_libraries( diff --git a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_client.h b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_client.h index 7998bd2646..fa1a69d619 100644 --- a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_client.h +++ b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_client.h @@ -7,7 +7,7 @@ #include -#include "opentelemetry/exporters/otlp/otlp_grpc_exporter_options.h" +#include "opentelemetry/exporters/otlp/otlp_grpc_client_options.h" #include "opentelemetry/exporters/otlp/protobuf_include_prefix.h" @@ -23,6 +23,8 @@ namespace exporter namespace otlp { +struct OtlpGrpcClientOptions; + /** * The OTLP gRPC client contains utility functions of gRPC. */ @@ -32,13 +34,13 @@ class OtlpGrpcClient /** * Create gRPC channel from the exporter options. */ - static std::shared_ptr MakeChannel(const OtlpGrpcExporterOptions &options); + static std::shared_ptr MakeChannel(const OtlpGrpcClientOptions &options); /** * Create gRPC client context to call RPC. */ static std::unique_ptr MakeClientContext( - const OtlpGrpcExporterOptions &options); + const OtlpGrpcClientOptions &options); /** * Create gRPC CompletionQueue to async call RPC. @@ -49,19 +51,19 @@ class OtlpGrpcClient * Create trace service stub to communicate with the OpenTelemetry Collector. */ static std::unique_ptr - MakeTraceServiceStub(const OtlpGrpcExporterOptions &options); + MakeTraceServiceStub(const OtlpGrpcClientOptions &options); /** * Create metrics service stub to communicate with the OpenTelemetry Collector. */ static std::unique_ptr - MakeMetricsServiceStub(const OtlpGrpcExporterOptions &options); + MakeMetricsServiceStub(const OtlpGrpcClientOptions &options); /** * Create logs service stub to communicate with the OpenTelemetry Collector. */ static std::unique_ptr - MakeLogsServiceStub(const OtlpGrpcExporterOptions &options); + MakeLogsServiceStub(const OtlpGrpcClientOptions &options); static grpc::Status DelegateExport( proto::collector::trace::v1::TraceService::StubInterface *stub, diff --git a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_client_options.h b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_client_options.h new file mode 100644 index 0000000000..310fc94d4d --- /dev/null +++ b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_client_options.h @@ -0,0 +1,58 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/exporters/otlp/otlp_environment.h" +#include "opentelemetry/version.h" + +#include +#include + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace exporter +{ +namespace otlp +{ + +struct OtlpGrpcClientOptions +{ + /** The endpoint to export to. */ + std::string endpoint; + + /** Use SSL. */ + bool use_ssl_credentials; + + /** CA CERT, path to a file. */ + std::string ssl_credentials_cacert_path; + + /** CA CERT, as a string. */ + std::string ssl_credentials_cacert_as_string; + +#ifdef ENABLE_OTLP_GRPC_SSL_MTLS_PREVIEW + /** CLIENT KEY, path to a file. */ + std::string ssl_client_key_path; + + /** CLIENT KEY, as a string. */ + std::string ssl_client_key_string; + + /** CLIENT CERT, path to a file. */ + std::string ssl_client_cert_path; + + /** CLIENT CERT, as a string. */ + std::string ssl_client_cert_string; +#endif + + /** Export timeout. */ + std::chrono::system_clock::duration timeout; + + /** Additional HTTP headers. */ + OtlpHeaders metadata; + + /** User agent. */ + std::string user_agent; +}; + +} // namespace otlp +} // namespace exporter +OPENTELEMETRY_END_NAMESPACE diff --git a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_exporter_options.h b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_exporter_options.h index 01ac5b43f2..b2556f1f76 100644 --- a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_exporter_options.h +++ b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_exporter_options.h @@ -3,9 +3,8 @@ #pragma once -#include "opentelemetry/exporters/otlp/otlp_environment.h" - -#include +#include "opentelemetry/exporters/otlp/otlp_grpc_client_options.h" +#include "opentelemetry/version.h" OPENTELEMETRY_BEGIN_NAMESPACE namespace exporter @@ -15,38 +14,17 @@ namespace otlp /** * Struct to hold OTLP GRPC traces exporter options. + * + * See + * https://github.com/open-telemetry/opentelemetry-proto/blob/main/docs/specification.md#otlpgrpc + * + * See + * https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md */ -struct OtlpGrpcExporterOptions +struct OPENTELEMETRY_EXPORT OtlpGrpcExporterOptions : public OtlpGrpcClientOptions { - // The endpoint to export to. By default the OpenTelemetry Collector's default endpoint. - std::string endpoint = GetOtlpDefaultGrpcEndpoint(); - // By default when false, uses grpc::InsecureChannelCredentials(); If true, - // uses ssl_credentials_cacert_path if non-empty, else uses ssl_credentials_cacert_as_string - bool use_ssl_credentials = GetOtlpDefaultIsSslEnable(); - // ssl_credentials_cacert_path specifies path to .pem file to be used for SSL encryption. - std::string ssl_credentials_cacert_path = GetOtlpDefaultSslCertificatePath(); - // ssl_credentials_cacert_as_string in-memory string representation of .pem file to be used for - // SSL encryption. - std::string ssl_credentials_cacert_as_string = GetOtlpDefaultSslCertificateString(); - -#ifdef ENABLE_OTLP_GRPC_SSL_MTLS_PREVIEW - // At most one of ssl_client_key_* should be non-empty. If use_ssl_credentials, they will - // be read to allow for mTLS. - std::string ssl_client_key_path = GetOtlpDefaultTracesSslClientKeyPath(); - std::string ssl_client_key_string = GetOtlpDefaultTracesSslClientKeyString(); - - // At most one of ssl_client_cert_* should be non-empty. If use_ssl_credentials, they will - // be read to allow for mTLS. - std::string ssl_client_cert_path = GetOtlpDefaultTracesSslClientCertificatePath(); - std::string ssl_client_cert_string = GetOtlpDefaultTracesSslClientCertificateString(); -#endif - - // Timeout for grpc deadline - std::chrono::system_clock::duration timeout = GetOtlpDefaultTimeout(); - // Additional HTTP headers - OtlpHeaders metadata = GetOtlpDefaultHeaders(); - // User agent - std::string user_agent = GetOtlpDefaultUserAgent(); + OtlpGrpcExporterOptions(); + ~OtlpGrpcExporterOptions(); }; } // namespace otlp diff --git a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_log_record_exporter.h b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_log_record_exporter.h index 33476297cb..29333703b1 100644 --- a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_log_record_exporter.h +++ b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_log_record_exporter.h @@ -13,7 +13,7 @@ // clang-format on #include "opentelemetry/exporters/otlp/otlp_environment.h" -#include "opentelemetry/exporters/otlp/otlp_grpc_exporter_options.h" +#include "opentelemetry/exporters/otlp/otlp_grpc_log_record_exporter_options.h" #include "opentelemetry/sdk/logs/exporter.h" OPENTELEMETRY_BEGIN_NAMESPACE @@ -37,7 +37,7 @@ class OtlpGrpcLogRecordExporter : public opentelemetry::sdk::logs::LogRecordExpo * Create an OtlpGrpcLogRecordExporter with user specified options. * @param options An object containing the user's configuration options. */ - OtlpGrpcLogRecordExporter(const OtlpGrpcExporterOptions &options); + OtlpGrpcLogRecordExporter(const OtlpGrpcLogRecordExporterOptions &options); /** * Creates a recordable that stores the data in protobuf. @@ -71,7 +71,7 @@ class OtlpGrpcLogRecordExporter : public opentelemetry::sdk::logs::LogRecordExpo private: // Configuration options for the exporter - const OtlpGrpcExporterOptions options_; + const OtlpGrpcLogRecordExporterOptions options_; // For testing friend class OtlpGrpcLogRecordExporterTestPeer; diff --git a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_log_record_exporter_factory.h b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_log_record_exporter_factory.h index 5f81e60f2e..7a88615959 100644 --- a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_log_record_exporter_factory.h +++ b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_log_record_exporter_factory.h @@ -3,7 +3,7 @@ #pragma once -#include "opentelemetry/exporters/otlp/otlp_grpc_exporter_options.h" +#include "opentelemetry/exporters/otlp/otlp_grpc_log_record_exporter_options.h" #include "opentelemetry/sdk/logs/exporter.h" OPENTELEMETRY_BEGIN_NAMESPACE @@ -27,7 +27,7 @@ class OPENTELEMETRY_EXPORT OtlpGrpcLogRecordExporterFactory * Create a OtlpGrpcLogRecordExporter. */ static std::unique_ptr Create( - const OtlpGrpcExporterOptions &options); + const OtlpGrpcLogRecordExporterOptions &options); }; } // namespace otlp diff --git a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_log_record_exporter_options.h b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_log_record_exporter_options.h new file mode 100644 index 0000000000..cc1a199c4b --- /dev/null +++ b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_log_record_exporter_options.h @@ -0,0 +1,31 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/exporters/otlp/otlp_grpc_client_options.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace exporter +{ +namespace otlp +{ + +/** + * Struct to hold OTLP GRPC log record exporter options. + * + * See + * https://github.com/open-telemetry/opentelemetry-proto/blob/main/docs/specification.md#otlpgrpc + * + * See + * https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md + */ +struct OPENTELEMETRY_EXPORT OtlpGrpcLogRecordExporterOptions : public OtlpGrpcClientOptions +{ + OtlpGrpcLogRecordExporterOptions(); + ~OtlpGrpcLogRecordExporterOptions(); +}; + +} // namespace otlp +} // namespace exporter +OPENTELEMETRY_END_NAMESPACE diff --git a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_metric_exporter.h b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_metric_exporter.h index 11bb64c24f..5f975c8ce3 100644 --- a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_metric_exporter.h +++ b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_metric_exporter.h @@ -63,7 +63,7 @@ class OtlpGrpcMetricExporter : public opentelemetry::sdk::metrics::PushMetricExp const sdk::metrics::AggregationTemporalitySelector aggregation_temporality_selector_; // For testing - friend class OtlpGrpcExporterTestPeer; + friend class OtlpGrpcMetricExporterTestPeer; // Store service stub internally. Useful for testing. std::unique_ptr diff --git a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_metric_exporter_options.h b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_metric_exporter_options.h index a56cf8cb55..22be580972 100644 --- a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_metric_exporter_options.h +++ b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_grpc_metric_exporter_options.h @@ -3,11 +3,9 @@ #pragma once -#include "opentelemetry/exporters/otlp/otlp_grpc_exporter_options.h" +#include "opentelemetry/exporters/otlp/otlp_grpc_client_options.h" #include "opentelemetry/exporters/otlp/otlp_preferred_temporality.h" -#include "opentelemetry/sdk/metrics/instruments.h" - -#include +#include "opentelemetry/version.h" OPENTELEMETRY_BEGIN_NAMESPACE namespace exporter @@ -17,13 +15,20 @@ namespace otlp /** * Struct to hold OTLP GRPC metrics exporter options. + * + * See + * https://github.com/open-telemetry/opentelemetry-proto/blob/main/docs/specification.md#otlpgrpc + * + * See + * https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md */ -struct OtlpGrpcMetricExporterOptions : public OtlpGrpcExporterOptions +struct OPENTELEMETRY_EXPORT OtlpGrpcMetricExporterOptions : public OtlpGrpcClientOptions { + OtlpGrpcMetricExporterOptions(); + ~OtlpGrpcMetricExporterOptions(); - // Preferred Aggregation Temporality - PreferredAggregationTemporality aggregation_temporality = - PreferredAggregationTemporality::kCumulative; + /** Preferred Aggregation Temporality. */ + PreferredAggregationTemporality aggregation_temporality; }; } // namespace otlp diff --git a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_http_exporter_options.h b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_http_exporter_options.h index 29b4b76ec0..9200a506b8 100644 --- a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_http_exporter_options.h +++ b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_http_exporter_options.h @@ -3,9 +3,9 @@ #pragma once -#include "opentelemetry/exporters/otlp/otlp_http.h" - #include "opentelemetry/exporters/otlp/otlp_environment.h" +#include "opentelemetry/exporters/otlp/otlp_http.h" +#include "opentelemetry/version.h" #include #include @@ -20,65 +20,89 @@ namespace otlp /** * Struct to hold OTLP HTTP traces exporter options. + * + * See + * https://github.com/open-telemetry/opentelemetry-proto/blob/main/docs/specification.md#otlphttp + * + * See + * https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md */ -struct OtlpHttpExporterOptions +struct OPENTELEMETRY_EXPORT OtlpHttpExporterOptions { - // The endpoint to export to. By default - // @see - // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/otlp.md - // @see https://github.com/open-telemetry/opentelemetry-collector/tree/main/receiver/otlpreceiver - std::string url = GetOtlpDefaultHttpEndpoint(); + OtlpHttpExporterOptions(); + ~OtlpHttpExporterOptions(); - // By default, post json data - HttpRequestContentType content_type = HttpRequestContentType::kJson; + /** The endpoint to export to. */ + std::string url; - // If convert bytes into hex. By default, we will convert all bytes but id into base64 - // This option is ignored if content_type is not kJson - JsonBytesMappingKind json_bytes_mapping = JsonBytesMappingKind::kHexId; + /** HTTP content type. */ + HttpRequestContentType content_type; - // If using the json name of protobuf field to set the key of json. By default, we will use the - // field name just like proto files. - bool use_json_name = false; + /** + Json byte mapping. - // Whether to print the status of the exporter in the console - bool console_debug = false; + Used only for HttpRequestContentType::kJson. + Convert bytes to hex / base64. + */ + JsonBytesMappingKind json_bytes_mapping; - std::chrono::system_clock::duration timeout = GetOtlpDefaultTimeout(); + /** + Use json names (true) or protobuf field names (false) to set the json key. + */ + bool use_json_name; - // Additional HTTP headers - OtlpHeaders http_headers = GetOtlpDefaultHeaders(); + /** Print debug messages. */ + bool console_debug; + + /** Export timeout. */ + std::chrono::system_clock::duration timeout; + + /** Additional HTTP headers. */ + OtlpHeaders http_headers; #ifdef ENABLE_ASYNC_EXPORT - // Concurrent requests - // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/otlp.md#otlpgrpc-concurrent-requests - std::size_t max_concurrent_requests = 64; + /** Max number of concurrent requests. */ + std::size_t max_concurrent_requests; - // Requests per connections - std::size_t max_requests_per_connection = 8; + /** Max number of requests per connection. */ + std::size_t max_requests_per_connection; #endif #ifdef ENABLE_OTLP_HTTP_SSL_PREVIEW - bool ssl_insecure_skip_verify{false}; + /** True do disable SSL. */ + bool ssl_insecure_skip_verify; + + /** CA CERT, path to a file. */ + std::string ssl_ca_cert_path; - std::string ssl_ca_cert_path = GetOtlpDefaultTracesSslCertificatePath(); - std::string ssl_ca_cert_string = GetOtlpDefaultTracesSslCertificateString(); + /** CA CERT, as a string. */ + std::string ssl_ca_cert_string; - std::string ssl_client_key_path = GetOtlpDefaultTracesSslClientKeyPath(); - std::string ssl_client_key_string = GetOtlpDefaultTracesSslClientKeyString(); + /** CLIENT KEY, path to a file. */ + std::string ssl_client_key_path; - std::string ssl_client_cert_path = GetOtlpDefaultTracesSslClientCertificatePath(); - std::string ssl_client_cert_string = GetOtlpDefaultTracesSslClientCertificateString(); + /** CLIENT KEY, as a string. */ + std::string ssl_client_key_string; + + /** CLIENT CERT, path to a file. */ + std::string ssl_client_cert_path; + + /** CLIENT CERT, as a string. */ + std::string ssl_client_cert_string; #endif /* ENABLE_OTLP_HTTP_SSL_PREVIEW */ #ifdef ENABLE_OTLP_HTTP_SSL_TLS_PREVIEW /** Minimum TLS version. */ - std::string ssl_min_tls = GetOtlpDefaultTracesSslTlsMinVersion(); + std::string ssl_min_tls; + /** Maximum TLS version. */ - std::string ssl_max_tls = GetOtlpDefaultTracesSslTlsMaxVersion(); + std::string ssl_max_tls; + /** TLS cipher. */ - std::string ssl_cipher = GetOtlpDefaultTracesSslTlsCipher(); + std::string ssl_cipher; + /** TLS cipher suite. */ - std::string ssl_cipher_suite = GetOtlpDefaultTracesSslTlsCipherSuite(); + std::string ssl_cipher_suite; #endif /* ENABLE_OTLP_HTTP_SSL_TLS_PREVIEW */ }; diff --git a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_http_log_record_exporter_options.h b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_http_log_record_exporter_options.h index 65fd2b9b63..e2a6264675 100644 --- a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_http_log_record_exporter_options.h +++ b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_http_log_record_exporter_options.h @@ -5,7 +5,7 @@ #include "opentelemetry/exporters/otlp/otlp_environment.h" #include "opentelemetry/exporters/otlp/otlp_http.h" -#include "opentelemetry/sdk/logs/exporter.h" +#include "opentelemetry/version.h" #include #include @@ -19,66 +19,90 @@ namespace otlp { /** - * Struct to hold OTLP HTTP logs exporter options. + * Struct to hold OTLP HTTP log record exporter options. + * + * See + * https://github.com/open-telemetry/opentelemetry-proto/blob/main/docs/specification.md#otlphttp + * + * See + * https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md */ -struct OtlpHttpLogRecordExporterOptions +struct OPENTELEMETRY_EXPORT OtlpHttpLogRecordExporterOptions { - // The endpoint to export to. By default - // @see - // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/otlp.md - // @see https://github.com/open-telemetry/opentelemetry-collector/tree/main/receiver/otlpreceiver - std::string url = GetOtlpDefaultHttpLogsEndpoint(); + OtlpHttpLogRecordExporterOptions(); + ~OtlpHttpLogRecordExporterOptions(); - // By default, post json data - HttpRequestContentType content_type = HttpRequestContentType::kJson; + /** The endpoint to export to. */ + std::string url; - // If convert bytes into hex. By default, we will convert all bytes but id into base64 - // This option is ignored if content_type is not kJson - JsonBytesMappingKind json_bytes_mapping = JsonBytesMappingKind::kHexId; + /** HTTP content type. */ + HttpRequestContentType content_type; - // If using the json name of protobuf field to set the key of json. By default, we will use the - // field name just like proto files. - bool use_json_name = false; + /** + Json byte mapping. - // Whether to print the status of the exporter in the console - bool console_debug = false; + Used only for HttpRequestContentType::kJson. + Convert bytes to hex / base64. + */ + JsonBytesMappingKind json_bytes_mapping; - std::chrono::system_clock::duration timeout = GetOtlpDefaultLogsTimeout(); + /** + Use json names (true) or protobuf field names (false) to set the json key. + */ + bool use_json_name; - // Additional HTTP headers - OtlpHeaders http_headers = GetOtlpDefaultLogsHeaders(); + /** Print debug messages. */ + bool console_debug; + + /** Export timeout. */ + std::chrono::system_clock::duration timeout; + + /** Additional HTTP headers. */ + OtlpHeaders http_headers; #ifdef ENABLE_ASYNC_EXPORT - // Concurrent requests - // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/otlp.md#otlpgrpc-concurrent-requests - std::size_t max_concurrent_requests = 64; + /** Max number of concurrent requests. */ + std::size_t max_concurrent_requests; - // Requests per connections - std::size_t max_requests_per_connection = 8; + /** Max number of requests per connection. */ + std::size_t max_requests_per_connection; #endif #ifdef ENABLE_OTLP_HTTP_SSL_PREVIEW - bool ssl_insecure_skip_verify{false}; + /** True do disable SSL. */ + bool ssl_insecure_skip_verify; + + /** CA CERT, path to a file. */ + std::string ssl_ca_cert_path; + + /** CA CERT, as a string. */ + std::string ssl_ca_cert_string; - std::string ssl_ca_cert_path = GetOtlpDefaultLogsSslCertificatePath(); - std::string ssl_ca_cert_string = GetOtlpDefaultLogsSslCertificateString(); + /** CLIENT KEY, path to a file. */ + std::string ssl_client_key_path; - std::string ssl_client_key_path = GetOtlpDefaultLogsSslClientKeyPath(); - std::string ssl_client_key_string = GetOtlpDefaultLogsSslClientKeyString(); + /** CLIENT KEY, as a string. */ + std::string ssl_client_key_string; - std::string ssl_client_cert_path = GetOtlpDefaultLogsSslClientCertificatePath(); - std::string ssl_client_cert_string = GetOtlpDefaultLogsSslClientCertificateString(); + /** CLIENT CERT, path to a file. */ + std::string ssl_client_cert_path; + + /** CLIENT CERT, as a string. */ + std::string ssl_client_cert_string; #endif /* ENABLE_OTLP_HTTP_SSL_PREVIEW */ #ifdef ENABLE_OTLP_HTTP_SSL_TLS_PREVIEW /** Minimum TLS version. */ - std::string ssl_min_tls = GetOtlpDefaultLogsSslTlsMinVersion(); + std::string ssl_min_tls; + /** Maximum TLS version. */ - std::string ssl_max_tls = GetOtlpDefaultLogsSslTlsMaxVersion(); + std::string ssl_max_tls; + /** TLS cipher. */ - std::string ssl_cipher = GetOtlpDefaultLogsSslTlsCipher(); + std::string ssl_cipher; + /** TLS cipher suite. */ - std::string ssl_cipher_suite = GetOtlpDefaultLogsSslTlsCipherSuite(); + std::string ssl_cipher_suite; #endif /* ENABLE_OTLP_HTTP_SSL_TLS_PREVIEW */ }; diff --git a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_http_metric_exporter_options.h b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_http_metric_exporter_options.h index 8aa0ccad21..38446be73b 100644 --- a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_http_metric_exporter_options.h +++ b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_http_metric_exporter_options.h @@ -6,6 +6,7 @@ #include "opentelemetry/exporters/otlp/otlp_environment.h" #include "opentelemetry/exporters/otlp/otlp_http.h" #include "opentelemetry/exporters/otlp/otlp_preferred_temporality.h" +#include "opentelemetry/version.h" #include #include @@ -20,70 +21,91 @@ namespace otlp /** * Struct to hold OTLP HTTP metrics exporter options. + * + * See + * https://github.com/open-telemetry/opentelemetry-proto/blob/main/docs/specification.md#otlphttp + * + * See + * https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md */ -struct OtlpHttpMetricExporterOptions +struct OPENTELEMETRY_EXPORT OtlpHttpMetricExporterOptions { - // The endpoint to export to. By default - // @see - // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/otlp.md - // @see https://github.com/open-telemetry/opentelemetry-collector/tree/main/receiver/otlpreceiver - std::string url = GetOtlpDefaultMetricsEndpoint(); + OtlpHttpMetricExporterOptions(); + ~OtlpHttpMetricExporterOptions(); - // By default, post json data - HttpRequestContentType content_type = HttpRequestContentType::kJson; + /** The endpoint to export to. */ + std::string url; - // If convert bytes into hex. By default, we will convert all bytes but id into base64 - // This option is ignored if content_type is not kJson - JsonBytesMappingKind json_bytes_mapping = JsonBytesMappingKind::kHexId; + /** HTTP content type. */ + HttpRequestContentType content_type; - // If using the json name of protobuf field to set the key of json. By default, we will use the - // field name just like proto files. - bool use_json_name = false; + /** + Json byte mapping. - // Whether to print the status of the exporter in the console - bool console_debug = false; + Used only for HttpRequestContentType::kJson. + Convert bytes to hex / base64. + */ + JsonBytesMappingKind json_bytes_mapping; - // TODO: Enable/disable to verify SSL certificate - std::chrono::system_clock::duration timeout = GetOtlpDefaultMetricsTimeout(); + /** + Use json names (true) or protobuf field names (false) to set the json key. + */ + bool use_json_name; - // Additional HTTP headers - OtlpHeaders http_headers = GetOtlpDefaultMetricsHeaders(); + /** Print debug messages. */ + bool console_debug; - // Preferred Aggregation Temporality - PreferredAggregationTemporality aggregation_temporality = - PreferredAggregationTemporality::kCumulative; + /** Export timeout. */ + std::chrono::system_clock::duration timeout; + + /** Additional HTTP headers. */ + OtlpHeaders http_headers; + + PreferredAggregationTemporality aggregation_temporality; #ifdef ENABLE_ASYNC_EXPORT - // Concurrent requests - // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/otlp.md#otlpgrpc-concurrent-requests - std::size_t max_concurrent_requests = 64; + /** Max number of concurrent requests. */ + std::size_t max_concurrent_requests; - // Requests per connections - std::size_t max_requests_per_connection = 8; + /** Max number of requests per connection. */ + std::size_t max_requests_per_connection; #endif #ifdef ENABLE_OTLP_HTTP_SSL_PREVIEW - bool ssl_insecure_skip_verify{false}; + /** True do disable SSL. */ + bool ssl_insecure_skip_verify; + + /** CA CERT, path to a file. */ + std::string ssl_ca_cert_path; + + /** CA CERT, as a string. */ + std::string ssl_ca_cert_string; - std::string ssl_ca_cert_path = GetOtlpDefaultMetricsSslCertificatePath(); - std::string ssl_ca_cert_string = GetOtlpDefaultMetricsSslCertificateString(); + /** CLIENT KEY, path to a file. */ + std::string ssl_client_key_path; - std::string ssl_client_key_path = GetOtlpDefaultMetricsSslClientKeyPath(); - std::string ssl_client_key_string = GetOtlpDefaultMetricsSslClientKeyString(); + /** CLIENT KEY, as a string. */ + std::string ssl_client_key_string; - std::string ssl_client_cert_path = GetOtlpDefaultMetricsSslClientCertificatePath(); - std::string ssl_client_cert_string = GetOtlpDefaultMetricsSslClientCertificateString(); + /** CLIENT CERT, path to a file. */ + std::string ssl_client_cert_path; + + /** CLIENT CERT, as a string. */ + std::string ssl_client_cert_string; #endif /* ENABLE_OTLP_HTTP_SSL_PREVIEW */ #ifdef ENABLE_OTLP_HTTP_SSL_TLS_PREVIEW /** Minimum TLS version. */ - std::string ssl_min_tls = GetOtlpDefaultMetricsSslTlsMinVersion(); + std::string ssl_min_tls; + /** Maximum TLS version. */ - std::string ssl_max_tls = GetOtlpDefaultMetricsSslTlsMaxVersion(); + std::string ssl_max_tls; + /** TLS cipher. */ - std::string ssl_cipher = GetOtlpDefaultMetricsSslTlsCipher(); + std::string ssl_cipher; + /** TLS cipher suite. */ - std::string ssl_cipher_suite = GetOtlpDefaultMetricsSslTlsCipherSuite(); + std::string ssl_cipher_suite; #endif /* ENABLE_OTLP_HTTP_SSL_TLS_PREVIEW */ }; diff --git a/exporters/otlp/src/otlp_grpc_client.cc b/exporters/otlp/src/otlp_grpc_client.cc index 625781025e..c0436eddaf 100644 --- a/exporters/otlp/src/otlp_grpc_client.cc +++ b/exporters/otlp/src/otlp_grpc_client.cc @@ -48,7 +48,7 @@ static std::string GetFileContentsOrInMemoryContents(const std::string &file_pat } // namespace -std::shared_ptr OtlpGrpcClient::MakeChannel(const OtlpGrpcExporterOptions &options) +std::shared_ptr OtlpGrpcClient::MakeChannel(const OtlpGrpcClientOptions &options) { std::shared_ptr channel; @@ -94,7 +94,7 @@ std::shared_ptr OtlpGrpcClient::MakeChannel(const OtlpGrpcExporte } std::unique_ptr OtlpGrpcClient::MakeClientContext( - const OtlpGrpcExporterOptions &options) + const OtlpGrpcClientOptions &options) { std::unique_ptr context{new grpc::ClientContext()}; if (!context) @@ -121,19 +121,19 @@ std::unique_ptr OtlpGrpcClient::MakeCompletionQueue() } std::unique_ptr -OtlpGrpcClient::MakeTraceServiceStub(const OtlpGrpcExporterOptions &options) +OtlpGrpcClient::MakeTraceServiceStub(const OtlpGrpcClientOptions &options) { return proto::collector::trace::v1::TraceService::NewStub(MakeChannel(options)); } std::unique_ptr -OtlpGrpcClient::MakeMetricsServiceStub(const OtlpGrpcExporterOptions &options) +OtlpGrpcClient::MakeMetricsServiceStub(const OtlpGrpcClientOptions &options) { return proto::collector::metrics::v1::MetricsService::NewStub(MakeChannel(options)); } std::unique_ptr -OtlpGrpcClient::MakeLogsServiceStub(const OtlpGrpcExporterOptions &options) +OtlpGrpcClient::MakeLogsServiceStub(const OtlpGrpcClientOptions &options) { return proto::collector::logs::v1::LogsService::NewStub(MakeChannel(options)); } diff --git a/exporters/otlp/src/otlp_grpc_exporter_options.cc b/exporters/otlp/src/otlp_grpc_exporter_options.cc new file mode 100644 index 0000000000..3099303ac4 --- /dev/null +++ b/exporters/otlp/src/otlp_grpc_exporter_options.cc @@ -0,0 +1,38 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#include "opentelemetry/exporters/otlp/otlp_grpc_exporter_options.h" +#include "opentelemetry/version.h" + +#include + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace exporter +{ +namespace otlp +{ + +OtlpGrpcExporterOptions::OtlpGrpcExporterOptions() +{ + endpoint = GetOtlpDefaultGrpcTracesEndpoint(); + use_ssl_credentials = !GetOtlpDefaultGrpcTracesIsInsecure(); /* negation intended. */ + ssl_credentials_cacert_path = GetOtlpDefaultTracesSslCertificatePath(); + ssl_credentials_cacert_as_string = GetOtlpDefaultTracesSslCertificateString(); + +#ifdef ENABLE_OTLP_GRPC_SSL_MTLS_PREVIEW + ssl_client_key_path = GetOtlpDefaultTracesSslClientKeyPath(); + ssl_client_key_string = GetOtlpDefaultTracesSslClientKeyString(); + ssl_client_cert_path = GetOtlpDefaultTracesSslClientCertificatePath(); + ssl_client_cert_string = GetOtlpDefaultTracesSslClientCertificateString(); +#endif + + timeout = GetOtlpDefaultTracesTimeout(); + metadata = GetOtlpDefaultTracesHeaders(); + user_agent = GetOtlpDefaultUserAgent(); +} + +OtlpGrpcExporterOptions::~OtlpGrpcExporterOptions() {} + +} // namespace otlp +} // namespace exporter +OPENTELEMETRY_END_NAMESPACE diff --git a/exporters/otlp/src/otlp_grpc_log_record_exporter.cc b/exporters/otlp/src/otlp_grpc_log_record_exporter.cc index 01367da886..2b397262b0 100644 --- a/exporters/otlp/src/otlp_grpc_log_record_exporter.cc +++ b/exporters/otlp/src/otlp_grpc_log_record_exporter.cc @@ -30,16 +30,17 @@ namespace otlp // -------------------------------- Constructors -------------------------------- OtlpGrpcLogRecordExporter::OtlpGrpcLogRecordExporter() - : OtlpGrpcLogRecordExporter(OtlpGrpcExporterOptions()) + : OtlpGrpcLogRecordExporter(OtlpGrpcLogRecordExporterOptions()) {} -OtlpGrpcLogRecordExporter::OtlpGrpcLogRecordExporter(const OtlpGrpcExporterOptions &options) +OtlpGrpcLogRecordExporter::OtlpGrpcLogRecordExporter( + const OtlpGrpcLogRecordExporterOptions &options) : options_(options), log_service_stub_(OtlpGrpcClient::MakeLogsServiceStub(options)) {} OtlpGrpcLogRecordExporter::OtlpGrpcLogRecordExporter( std::unique_ptr stub) - : options_(OtlpGrpcExporterOptions()), log_service_stub_(std::move(stub)) + : options_(OtlpGrpcLogRecordExporterOptions()), log_service_stub_(std::move(stub)) {} // ----------------------------- Exporter methods ------------------------------ diff --git a/exporters/otlp/src/otlp_grpc_log_record_exporter_factory.cc b/exporters/otlp/src/otlp_grpc_log_record_exporter_factory.cc index b36eefa6cb..7229de569a 100644 --- a/exporters/otlp/src/otlp_grpc_log_record_exporter_factory.cc +++ b/exporters/otlp/src/otlp_grpc_log_record_exporter_factory.cc @@ -4,8 +4,8 @@ // MUST be first (absl) #include "opentelemetry/exporters/otlp/otlp_grpc_log_record_exporter.h" -#include "opentelemetry/exporters/otlp/otlp_grpc_exporter_options.h" #include "opentelemetry/exporters/otlp/otlp_grpc_log_record_exporter_factory.h" +#include "opentelemetry/exporters/otlp/otlp_grpc_log_record_exporter_options.h" OPENTELEMETRY_BEGIN_NAMESPACE namespace exporter @@ -16,12 +16,12 @@ namespace otlp std::unique_ptr OtlpGrpcLogRecordExporterFactory::Create() { - OtlpGrpcExporterOptions options; + OtlpGrpcLogRecordExporterOptions options; return Create(options); } std::unique_ptr -OtlpGrpcLogRecordExporterFactory::Create(const OtlpGrpcExporterOptions &options) +OtlpGrpcLogRecordExporterFactory::Create(const OtlpGrpcLogRecordExporterOptions &options) { std::unique_ptr exporter( new OtlpGrpcLogRecordExporter(options)); diff --git a/exporters/otlp/src/otlp_grpc_log_record_exporter_options.cc b/exporters/otlp/src/otlp_grpc_log_record_exporter_options.cc new file mode 100644 index 0000000000..697ef28f2a --- /dev/null +++ b/exporters/otlp/src/otlp_grpc_log_record_exporter_options.cc @@ -0,0 +1,36 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#include "opentelemetry/exporters/otlp/otlp_grpc_log_record_exporter_options.h" +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace exporter +{ +namespace otlp +{ + +OtlpGrpcLogRecordExporterOptions::OtlpGrpcLogRecordExporterOptions() +{ + endpoint = GetOtlpDefaultGrpcLogsEndpoint(); + use_ssl_credentials = !GetOtlpDefaultGrpcLogsIsInsecure(); /* negation intended. */ + ssl_credentials_cacert_path = GetOtlpDefaultLogsSslCertificatePath(); + ssl_credentials_cacert_as_string = GetOtlpDefaultLogsSslCertificateString(); + +#ifdef ENABLE_OTLP_GRPC_SSL_MTLS_PREVIEW + ssl_client_key_path = GetOtlpDefaultLogsSslClientKeyPath(); + ssl_client_key_string = GetOtlpDefaultLogsSslClientKeyString(); + ssl_client_cert_path = GetOtlpDefaultLogsSslClientCertificatePath(); + ssl_client_cert_string = GetOtlpDefaultLogsSslClientCertificateString(); +#endif + + timeout = GetOtlpDefaultLogsTimeout(); + metadata = GetOtlpDefaultLogsHeaders(); + user_agent = GetOtlpDefaultUserAgent(); +} + +OtlpGrpcLogRecordExporterOptions::~OtlpGrpcLogRecordExporterOptions() {} + +} // namespace otlp +} // namespace exporter +OPENTELEMETRY_END_NAMESPACE diff --git a/exporters/otlp/src/otlp_grpc_metric_exporter_options.cc b/exporters/otlp/src/otlp_grpc_metric_exporter_options.cc new file mode 100644 index 0000000000..cb99d1cc5a --- /dev/null +++ b/exporters/otlp/src/otlp_grpc_metric_exporter_options.cc @@ -0,0 +1,38 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#include "opentelemetry/exporters/otlp/otlp_grpc_metric_exporter_options.h" +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace exporter +{ +namespace otlp +{ + +OtlpGrpcMetricExporterOptions::OtlpGrpcMetricExporterOptions() +{ + endpoint = GetOtlpDefaultGrpcMetricsEndpoint(); + use_ssl_credentials = !GetOtlpDefaultGrpcMetricsIsInsecure(); /* negation intended. */ + ssl_credentials_cacert_path = GetOtlpDefaultMetricsSslCertificatePath(); + ssl_credentials_cacert_as_string = GetOtlpDefaultMetricsSslCertificateString(); + +#ifdef ENABLE_OTLP_GRPC_SSL_MTLS_PREVIEW + ssl_client_key_path = GetOtlpDefaultMetricsSslClientKeyPath(); + ssl_client_key_string = GetOtlpDefaultMetricsSslClientKeyString(); + ssl_client_cert_path = GetOtlpDefaultMetricsSslClientCertificatePath(); + ssl_client_cert_string = GetOtlpDefaultMetricsSslClientCertificateString(); +#endif + + timeout = GetOtlpDefaultMetricsTimeout(); + metadata = GetOtlpDefaultMetricsHeaders(); + user_agent = GetOtlpDefaultUserAgent(); + + aggregation_temporality = PreferredAggregationTemporality::kCumulative; +} + +OtlpGrpcMetricExporterOptions::~OtlpGrpcMetricExporterOptions() {} + +} // namespace otlp +} // namespace exporter +OPENTELEMETRY_END_NAMESPACE diff --git a/exporters/otlp/src/otlp_http_exporter_options.cc b/exporters/otlp/src/otlp_http_exporter_options.cc new file mode 100644 index 0000000000..91121e0c35 --- /dev/null +++ b/exporters/otlp/src/otlp_http_exporter_options.cc @@ -0,0 +1,54 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#include "opentelemetry/exporters/otlp/otlp_http_exporter_options.h" + +#include +#include +#include +#include + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace exporter +{ +namespace otlp +{ + +OtlpHttpExporterOptions::OtlpHttpExporterOptions() +{ + url = GetOtlpDefaultHttpTracesEndpoint(); + content_type = HttpRequestContentType::kJson; + json_bytes_mapping = JsonBytesMappingKind::kHexId; + use_json_name = false; + console_debug = false; + timeout = GetOtlpDefaultTracesTimeout(); + http_headers = GetOtlpDefaultTracesHeaders(); + +#ifdef ENABLE_ASYNC_EXPORT + max_concurrent_requests = 64; + max_requests_per_connection = 8; +#endif /* ENABLE_ASYNC_EXPORT */ + +#ifdef ENABLE_OTLP_HTTP_SSL_PREVIEW + ssl_insecure_skip_verify = false; + ssl_ca_cert_path = GetOtlpDefaultTracesSslCertificatePath(); + ssl_ca_cert_string = GetOtlpDefaultTracesSslCertificateString(); + ssl_client_key_path = GetOtlpDefaultTracesSslClientKeyPath(); + ssl_client_key_string = GetOtlpDefaultTracesSslClientKeyString(); + ssl_client_cert_path = GetOtlpDefaultTracesSslClientCertificatePath(); + ssl_client_cert_string = GetOtlpDefaultTracesSslClientCertificateString(); +#endif /* ENABLE_OTLP_HTTP_SSL_PREVIEW */ + +#ifdef ENABLE_OTLP_HTTP_SSL_TLS_PREVIEW + ssl_min_tls = GetOtlpDefaultTracesSslTlsMinVersion(); + ssl_max_tls = GetOtlpDefaultTracesSslTlsMaxVersion(); + ssl_cipher = GetOtlpDefaultTracesSslTlsCipher(); + ssl_cipher_suite = GetOtlpDefaultTracesSslTlsCipherSuite(); +#endif /* ENABLE_OTLP_HTTP_SSL_TLS_PREVIEW */ +} + +OtlpHttpExporterOptions::~OtlpHttpExporterOptions() {} + +} // namespace otlp +} // namespace exporter +OPENTELEMETRY_END_NAMESPACE diff --git a/exporters/otlp/src/otlp_http_log_record_exporter_options.cc b/exporters/otlp/src/otlp_http_log_record_exporter_options.cc new file mode 100644 index 0000000000..bda37b9730 --- /dev/null +++ b/exporters/otlp/src/otlp_http_log_record_exporter_options.cc @@ -0,0 +1,54 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#include "opentelemetry/exporters/otlp/otlp_http_log_record_exporter_options.h" + +#include +#include +#include +#include + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace exporter +{ +namespace otlp +{ + +OtlpHttpLogRecordExporterOptions::OtlpHttpLogRecordExporterOptions() +{ + url = GetOtlpDefaultHttpLogsEndpoint(); + content_type = HttpRequestContentType::kJson; + json_bytes_mapping = JsonBytesMappingKind::kHexId; + use_json_name = false; + console_debug = false; + timeout = GetOtlpDefaultLogsTimeout(); + http_headers = GetOtlpDefaultLogsHeaders(); + +#ifdef ENABLE_ASYNC_EXPORT + max_concurrent_requests = 64; + max_requests_per_connection = 8; +#endif + +#ifdef ENABLE_OTLP_HTTP_SSL_PREVIEW + ssl_insecure_skip_verify = false; + ssl_ca_cert_path = GetOtlpDefaultLogsSslCertificatePath(); + ssl_ca_cert_string = GetOtlpDefaultLogsSslCertificateString(); + ssl_client_key_path = GetOtlpDefaultLogsSslClientKeyPath(); + ssl_client_key_string = GetOtlpDefaultLogsSslClientKeyString(); + ssl_client_cert_path = GetOtlpDefaultLogsSslClientCertificatePath(); + ssl_client_cert_string = GetOtlpDefaultLogsSslClientCertificateString(); +#endif /* ENABLE_OTLP_HTTP_SSL_PREVIEW */ + +#ifdef ENABLE_OTLP_HTTP_SSL_TLS_PREVIEW + ssl_min_tls = GetOtlpDefaultLogsSslTlsMinVersion(); + ssl_max_tls = GetOtlpDefaultLogsSslTlsMaxVersion(); + ssl_cipher = GetOtlpDefaultLogsSslTlsCipher(); + ssl_cipher_suite = GetOtlpDefaultLogsSslTlsCipherSuite(); +#endif /* ENABLE_OTLP_HTTP_SSL_TLS_PREVIEW */ +} + +OtlpHttpLogRecordExporterOptions::~OtlpHttpLogRecordExporterOptions() {} + +} // namespace otlp +} // namespace exporter +OPENTELEMETRY_END_NAMESPACE diff --git a/exporters/otlp/src/otlp_http_metric_exporter_options.cc b/exporters/otlp/src/otlp_http_metric_exporter_options.cc new file mode 100644 index 0000000000..4dc0f40631 --- /dev/null +++ b/exporters/otlp/src/otlp_http_metric_exporter_options.cc @@ -0,0 +1,55 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#include "opentelemetry/exporters/otlp/otlp_http_metric_exporter_options.h" + +#include +#include +#include +#include + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace exporter +{ +namespace otlp +{ + +OtlpHttpMetricExporterOptions::OtlpHttpMetricExporterOptions() +{ + url = GetOtlpDefaultMetricsEndpoint(); + content_type = HttpRequestContentType::kJson; + json_bytes_mapping = JsonBytesMappingKind::kHexId; + use_json_name = false; + console_debug = false; + timeout = GetOtlpDefaultMetricsTimeout(); + http_headers = GetOtlpDefaultMetricsHeaders(); + aggregation_temporality = PreferredAggregationTemporality::kCumulative; + +#ifdef ENABLE_ASYNC_EXPORT + max_concurrent_requests = 64; + max_requests_per_connection = 8; +#endif + +#ifdef ENABLE_OTLP_HTTP_SSL_PREVIEW + ssl_insecure_skip_verify = false; + ssl_ca_cert_path = GetOtlpDefaultMetricsSslCertificatePath(); + ssl_ca_cert_string = GetOtlpDefaultMetricsSslCertificateString(); + ssl_client_key_path = GetOtlpDefaultMetricsSslClientKeyPath(); + ssl_client_key_string = GetOtlpDefaultMetricsSslClientKeyString(); + ssl_client_cert_path = GetOtlpDefaultMetricsSslClientCertificatePath(); + ssl_client_cert_string = GetOtlpDefaultMetricsSslClientCertificateString(); +#endif /* ENABLE_OTLP_HTTP_SSL_PREVIEW */ + +#ifdef ENABLE_OTLP_HTTP_SSL_TLS_PREVIEW + ssl_min_tls = GetOtlpDefaultMetricsSslTlsMinVersion(); + ssl_max_tls = GetOtlpDefaultMetricsSslTlsMaxVersion(); + ssl_cipher = GetOtlpDefaultMetricsSslTlsCipher(); + ssl_cipher_suite = GetOtlpDefaultMetricsSslTlsCipherSuite(); +#endif /* ENABLE_OTLP_HTTP_SSL_TLS_PREVIEW */ +} + +OtlpHttpMetricExporterOptions::~OtlpHttpMetricExporterOptions() {} + +} // namespace otlp +} // namespace exporter +OPENTELEMETRY_END_NAMESPACE diff --git a/exporters/otlp/test/otlp_grpc_log_record_exporter_factory_test.cc b/exporters/otlp/test/otlp_grpc_log_record_exporter_factory_test.cc index 2cc534277d..cb1d1849aa 100644 --- a/exporters/otlp/test/otlp_grpc_log_record_exporter_factory_test.cc +++ b/exporters/otlp/test/otlp_grpc_log_record_exporter_factory_test.cc @@ -3,8 +3,8 @@ #include -#include "opentelemetry/exporters/otlp/otlp_grpc_exporter_options.h" #include "opentelemetry/exporters/otlp/otlp_grpc_log_record_exporter_factory.h" +#include "opentelemetry/exporters/otlp/otlp_grpc_log_record_exporter_options.h" /* Make sure OtlpGrpcLogRecordExporterFactory does not require, @@ -22,7 +22,7 @@ namespace otlp TEST(OtlpGrpcLogRecordExporterFactoryTest, BuildTest) { - OtlpGrpcExporterOptions opts; + OtlpGrpcLogRecordExporterOptions opts; opts.endpoint = "localhost:45454"; std::unique_ptr exporter = diff --git a/exporters/otlp/test/otlp_grpc_log_record_exporter_test.cc b/exporters/otlp/test/otlp_grpc_log_record_exporter_test.cc index 547d21d056..6a31639219 100644 --- a/exporters/otlp/test/otlp_grpc_log_record_exporter_test.cc +++ b/exporters/otlp/test/otlp_grpc_log_record_exporter_test.cc @@ -59,7 +59,8 @@ class OtlpGrpcLogRecordExporterTestPeer : public ::testing::Test } // Get the options associated with the given exporter. - const OtlpGrpcExporterOptions &GetOptions(std::unique_ptr &exporter) + const OtlpGrpcLogRecordExporterOptions &GetOptions( + std::unique_ptr &exporter) { return exporter->options_; } diff --git a/exporters/otlp/test/otlp_grpc_metric_exporter_test.cc b/exporters/otlp/test/otlp_grpc_metric_exporter_test.cc new file mode 100644 index 0000000000..dc6dde9d79 --- /dev/null +++ b/exporters/otlp/test/otlp_grpc_metric_exporter_test.cc @@ -0,0 +1,209 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#ifndef OPENTELEMETRY_STL_VERSION +// Unfortunately as of 04/27/2021 the fix is NOT in the vcpkg snapshot of Google Test. +// Remove above `#ifdef` once the GMock fix for C++20 is in the mainline. +// +// Please refer to this GitHub issue for additional details: +// https://github.com/google/googletest/issues/2914 +// https://github.com/google/googletest/commit/61f010d703b32de9bfb20ab90ece38ab2f25977f +// +// If we compile using Visual Studio 2019 with `c++latest` (C++20) without the GMock fix, +// then the compilation here fails in `gmock-actions.h` from: +// .\tools\vcpkg\installed\x64-windows\include\gmock\gmock-actions.h(819): +// error C2653: 'result_of': is not a class or namespace name +// +// That is because `std::result_of` has been removed in C++20. + +# include "opentelemetry/exporters/otlp/otlp_grpc_metric_exporter.h" + +# include "opentelemetry/exporters/otlp/protobuf_include_prefix.h" + +// Problematic code that pulls in Gmock and breaks with vs2019/c++latest : +# include "opentelemetry/proto/collector/metrics/v1/metrics_service_mock.grpc.pb.h" + +# include "opentelemetry/exporters/otlp/protobuf_include_suffix.h" + +# include "opentelemetry/sdk/trace/simple_processor.h" +# include "opentelemetry/sdk/trace/tracer_provider.h" +# include "opentelemetry/trace/provider.h" + +# include + +# if defined(_MSC_VER) +# include "opentelemetry/sdk/common/env_variables.h" +using opentelemetry::sdk::common::setenv; +using opentelemetry::sdk::common::unsetenv; +# endif + +using namespace testing; + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace exporter +{ +namespace otlp +{ + +class OtlpGrpcMetricExporterTestPeer : public ::testing::Test +{ +public: + std::unique_ptr GetExporter( + std::unique_ptr &stub_interface) + { + return std::unique_ptr( + new OtlpGrpcMetricExporter(std::move(stub_interface))); + } + + // Get the options associated with the given exporter. + const OtlpGrpcMetricExporterOptions &GetOptions(std::unique_ptr &exporter) + { + return exporter->options_; + } +}; + +// Test exporter configuration options +TEST_F(OtlpGrpcMetricExporterTestPeer, ConfigTest) +{ + OtlpGrpcMetricExporterOptions opts; + opts.endpoint = "localhost:45454"; + std::unique_ptr exporter(new OtlpGrpcMetricExporter(opts)); + EXPECT_EQ(GetOptions(exporter).endpoint, "localhost:45454"); +} + +// Test exporter configuration options with use_ssl_credentials +TEST_F(OtlpGrpcMetricExporterTestPeer, ConfigSslCredentialsTest) +{ + std::string cacert_str = "--begin and end fake cert--"; + OtlpGrpcMetricExporterOptions opts; + opts.use_ssl_credentials = true; + opts.ssl_credentials_cacert_as_string = cacert_str; + std::unique_ptr exporter(new OtlpGrpcMetricExporter(opts)); + EXPECT_EQ(GetOptions(exporter).ssl_credentials_cacert_as_string, cacert_str); + EXPECT_EQ(GetOptions(exporter).use_ssl_credentials, true); +} + +# ifndef NO_GETENV +// Test exporter configuration options with use_ssl_credentials +TEST_F(OtlpGrpcMetricExporterTestPeer, ConfigFromEnv) +{ + const std::string cacert_str = "--begin and end fake cert--"; + setenv("OTEL_EXPORTER_OTLP_CERTIFICATE_STRING", cacert_str.c_str(), 1); + setenv("OTEL_EXPORTER_OTLP_SSL_ENABLE", "True", 1); + const std::string endpoint = "https://localhost:9999"; + setenv("OTEL_EXPORTER_OTLP_ENDPOINT", endpoint.c_str(), 1); + setenv("OTEL_EXPORTER_OTLP_TIMEOUT", "20050ms", 1); + setenv("OTEL_EXPORTER_OTLP_HEADERS", "k1=v1,k2=v2", 1); + setenv("OTEL_EXPORTER_OTLP_METRICS_HEADERS", "k1=v3,k1=v4", 1); + + std::unique_ptr exporter(new OtlpGrpcMetricExporter()); + EXPECT_EQ(GetOptions(exporter).ssl_credentials_cacert_as_string, cacert_str); + EXPECT_EQ(GetOptions(exporter).use_ssl_credentials, true); + EXPECT_EQ(GetOptions(exporter).endpoint, endpoint); + EXPECT_EQ(GetOptions(exporter).timeout.count(), + std::chrono::duration_cast( + std::chrono::milliseconds{20050}) + .count()); + EXPECT_EQ(GetOptions(exporter).metadata.size(), 3); + { + // Test k2 + auto range = GetOptions(exporter).metadata.equal_range("k2"); + EXPECT_TRUE(range.first != range.second); + EXPECT_EQ(range.first->second, std::string("v2")); + ++range.first; + EXPECT_TRUE(range.first == range.second); + } + { + // Test k1 + auto range = GetOptions(exporter).metadata.equal_range("k1"); + EXPECT_TRUE(range.first != range.second); + EXPECT_EQ(range.first->second, std::string("v3")); + ++range.first; + EXPECT_EQ(range.first->second, std::string("v4")); + ++range.first; + EXPECT_TRUE(range.first == range.second); + } + + unsetenv("OTEL_EXPORTER_OTLP_ENDPOINT"); + unsetenv("OTEL_EXPORTER_OTLP_CERTIFICATE_STRING"); + unsetenv("OTEL_EXPORTER_OTLP_SSL_ENABLE"); + unsetenv("OTEL_EXPORTER_OTLP_TIMEOUT"); + unsetenv("OTEL_EXPORTER_OTLP_HEADERS"); + unsetenv("OTEL_EXPORTER_OTLP_METRICS_HEADERS"); +} +# endif + +# ifndef NO_GETENV +// Test exporter configuration options with use_ssl_credentials +TEST_F(OtlpGrpcMetricExporterTestPeer, ConfigHttpsSecureFromEnv) +{ + // https takes precedence over insecure + const std::string endpoint = "https://localhost:9999"; + setenv("OTEL_EXPORTER_OTLP_ENDPOINT", endpoint.c_str(), 1); + setenv("OTEL_EXPORTER_OTLP_METRICS_INSECURE", "true", 1); + + std::unique_ptr exporter(new OtlpGrpcMetricExporter()); + EXPECT_EQ(GetOptions(exporter).use_ssl_credentials, true); + EXPECT_EQ(GetOptions(exporter).endpoint, endpoint); + + unsetenv("OTEL_EXPORTER_OTLP_ENDPOINT"); + unsetenv("OTEL_EXPORTER_OTLP_METRICS_INSECURE"); +} +# endif + +# ifndef NO_GETENV +// Test exporter configuration options with use_ssl_credentials +TEST_F(OtlpGrpcMetricExporterTestPeer, ConfigHttpInsecureFromEnv) +{ + // http takes precedence over secure + const std::string endpoint = "http://localhost:9999"; + setenv("OTEL_EXPORTER_OTLP_ENDPOINT", endpoint.c_str(), 1); + setenv("OTEL_EXPORTER_OTLP_METRICS_INSECURE", "false", 1); + + std::unique_ptr exporter(new OtlpGrpcMetricExporter()); + EXPECT_EQ(GetOptions(exporter).use_ssl_credentials, false); + EXPECT_EQ(GetOptions(exporter).endpoint, endpoint); + + unsetenv("OTEL_EXPORTER_OTLP_ENDPOINT"); + unsetenv("OTEL_EXPORTER_OTLP_METRICS_INSECURE"); +} +# endif + +# ifndef NO_GETENV +// Test exporter configuration options with use_ssl_credentials +TEST_F(OtlpGrpcMetricExporterTestPeer, ConfigUnknownSecureFromEnv) +{ + const std::string endpoint = "localhost:9999"; + setenv("OTEL_EXPORTER_OTLP_ENDPOINT", endpoint.c_str(), 1); + setenv("OTEL_EXPORTER_OTLP_METRICS_INSECURE", "false", 1); + + std::unique_ptr exporter(new OtlpGrpcMetricExporter()); + EXPECT_EQ(GetOptions(exporter).use_ssl_credentials, true); + EXPECT_EQ(GetOptions(exporter).endpoint, endpoint); + + unsetenv("OTEL_EXPORTER_OTLP_ENDPOINT"); + unsetenv("OTEL_EXPORTER_OTLP_METRICS_INSECURE"); +} +# endif + +# ifndef NO_GETENV +// Test exporter configuration options with use_ssl_credentials +TEST_F(OtlpGrpcMetricExporterTestPeer, ConfigUnknownInsecureFromEnv) +{ + const std::string endpoint = "localhost:9999"; + setenv("OTEL_EXPORTER_OTLP_ENDPOINT", endpoint.c_str(), 1); + setenv("OTEL_EXPORTER_OTLP_METRICS_INSECURE", "true", 1); + + std::unique_ptr exporter(new OtlpGrpcMetricExporter()); + EXPECT_EQ(GetOptions(exporter).use_ssl_credentials, false); + EXPECT_EQ(GetOptions(exporter).endpoint, endpoint); + + unsetenv("OTEL_EXPORTER_OTLP_ENDPOINT"); + unsetenv("OTEL_EXPORTER_OTLP_METRICS_INSECURE"); +} +# endif + +} // namespace otlp +} // namespace exporter +OPENTELEMETRY_END_NAMESPACE +#endif /* OPENTELEMETRY_STL_VERSION */ diff --git a/ext/src/dll/opentelemetry_cpp.src b/ext/src/dll/opentelemetry_cpp.src index 10172dbb3f..195b30640a 100644 --- a/ext/src/dll/opentelemetry_cpp.src +++ b/ext/src/dll/opentelemetry_cpp.src @@ -14,22 +14,6 @@ EXPORTS #endif // public: static class std::unique_ptr > __cdecl opentelemetry::v1::sdk::trace::TracerProviderFactory::Create(class std::unique_ptr >) ?Create@TracerProviderFactory@trace@sdk@v1@opentelemetry@@SA?AV?$unique_ptr@VTracerProvider@trace@v1@opentelemetry@@U?$default_delete@VTracerProvider@trace@v1@opentelemetry@@@std@@@std@@V?$unique_ptr@VSpanProcessor@trace@sdk@v1@opentelemetry@@U?$default_delete@VSpanProcessor@trace@sdk@v1@opentelemetry@@@std@@@7@@Z -#if defined(WITH_OTLP_GRPC) - // public: static class std::unique_ptr > __cdecl opentelemetry::v1::exporter::otlp::OtlpGrpcExporterFactory::Create(struct opentelemetry::v1::exporter::otlp::OtlpGrpcExporterOptions const & __ptr64) -#if defined(_WIN64) - ?Create@OtlpGrpcExporterFactory@otlp@exporter@v1@opentelemetry@@SA?AV?$unique_ptr@VSpanExporter@trace@sdk@v1@opentelemetry@@U?$default_delete@VSpanExporter@trace@sdk@v1@opentelemetry@@@std@@@std@@AEBUOtlpGrpcExporterOptions@2345@@Z -#else - ?Create@OtlpGrpcExporterFactory@otlp@exporter@v1@opentelemetry@@SA?AV?$unique_ptr@VSpanExporter@trace@sdk@v1@opentelemetry@@U?$default_delete@VSpanExporter@trace@sdk@v1@opentelemetry@@@std@@@std@@ABUOtlpGrpcExporterOptions@2345@@Z -#endif // defined(_WIN64) -#endif // defined(WITH_OTLP_GRPC) -#if defined(WITH_OTLP_HTTP) - // public: static class std::unique_ptr > __cdecl opentelemetry::v1::exporter::otlp::OtlpHttpExporterFactory::Create(struct opentelemetry::v1::exporter::otlp::OtlpHttpExporterOptions const & __ptr64) -#if defined(_WIN64) - ?Create@OtlpHttpExporterFactory@otlp@exporter@v1@opentelemetry@@SA?AV?$unique_ptr@VSpanExporter@trace@sdk@v1@opentelemetry@@U?$default_delete@VSpanExporter@trace@sdk@v1@opentelemetry@@@std@@@std@@AEBUOtlpHttpExporterOptions@2345@@Z -#else - ?Create@OtlpHttpExporterFactory@otlp@exporter@v1@opentelemetry@@SA?AV?$unique_ptr@VSpanExporter@trace@sdk@v1@opentelemetry@@U?$default_delete@VSpanExporter@trace@sdk@v1@opentelemetry@@@std@@@std@@ABUOtlpHttpExporterOptions@2345@@Z -#endif // defined(_WIN64) -#endif // defined(WITH_OTLP_HTTP) // public: static class std::unique_ptr > __cdecl opentelemetry::v1::sdk::logs::LoggerProviderFactory::Create(class std::unique_ptr > && __ptr64) #if defined(_WIN64) ?Create@LoggerProviderFactory@logs@sdk@v1@opentelemetry@@SA?AV?$unique_ptr@VLoggerProvider@logs@v1@opentelemetry@@U?$default_delete@VLoggerProvider@logs@v1@opentelemetry@@@std@@@std@@$$QEAV?$unique_ptr@VLogRecordProcessor@logs@sdk@v1@opentelemetry@@U?$default_delete@VLogRecordProcessor@logs@sdk@v1@opentelemetry@@@std@@@7@@Z @@ -82,7 +66,6 @@ EXPORTS ?AddMetricReader@MeterProvider@metrics@sdk@v1@opentelemetry@@QEAAXV?$shared_ptr@VMetricReader@metrics@sdk@v1@opentelemetry@@@std@@@Z // public: void __cdecl opentelemetry::v1::sdk::metrics::MeterProvider::AddView(class std::unique_ptr >,class std::unique_ptr >,class std::unique_ptr >) ?AddView@MeterProvider@metrics@sdk@v1@opentelemetry@@QEAAXV?$unique_ptr@VInstrumentSelector@metrics@sdk@v1@opentelemetry@@U?$default_delete@VInstrumentSelector@metrics@sdk@v1@opentelemetry@@@std@@@std@@V?$unique_ptr@VMeterSelector@metrics@sdk@v1@opentelemetry@@U?$default_delete@VMeterSelector@metrics@sdk@v1@opentelemetry@@@std@@@7@V?$unique_ptr@VView@metrics@sdk@v1@opentelemetry@@U?$default_delete@VView@metrics@sdk@v1@opentelemetry@@@std@@@7@@Z - #if defined(WITH_OTLP_GRPC) || defined(WITH_OTLP_HTTP) ?GetOtlpDefaultTracesTimeout@otlp@exporter@v1@opentelemetry@@YA?AV?$duration@_JU?$ratio@$00$0JIJGIA@@std@@@chrono@std@@XZ ?GetOtlpDefaultTracesHeaders@otlp@exporter@v1@opentelemetry@@YA?AV?$multimap@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V12@Ucmp_ic@otlp@exporter@v1@opentelemetry@@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V12@@std@@@2@@std@@XZ @@ -90,26 +73,63 @@ EXPORTS ?GetOtlpDefaultLogsHeaders@otlp@exporter@v1@opentelemetry@@YA?AV?$multimap@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V12@Ucmp_ic@otlp@exporter@v1@opentelemetry@@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V12@@std@@@2@@std@@XZ ?GetOtlpDefaultMetricsTimeout@otlp@exporter@v1@opentelemetry@@YA?AV?$duration@_JU?$ratio@$00$0JIJGIA@@std@@@chrono@std@@XZ ?GetOtlpDefaultMetricsHeaders@otlp@exporter@v1@opentelemetry@@YA?AV?$multimap@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V12@Ucmp_ic@otlp@exporter@v1@opentelemetry@@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V12@@std@@@2@@std@@XZ + ?GetOtlpDefaultTracesSslCertificatePath@otlp@exporter@v1@opentelemetry@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ + ?GetOtlpDefaultMetricsSslCertificatePath@otlp@exporter@v1@opentelemetry@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ + ?GetOtlpDefaultLogsSslCertificatePath@otlp@exporter@v1@opentelemetry@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ + ?GetOtlpDefaultTracesSslCertificateString@otlp@exporter@v1@opentelemetry@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ + ?GetOtlpDefaultMetricsSslCertificateString@otlp@exporter@v1@opentelemetry@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ + ?GetOtlpDefaultLogsSslCertificateString@otlp@exporter@v1@opentelemetry@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ #endif // defined(WITH_OTLP_GRPC) || defined(WITH_OTLP_HTTP) #if defined(WITH_OTLP_GRPC) - // public: static class std::unique_ptr > __cdecl opentelemetry::v1::exporter::otlp::OtlpGrpcLogRecordExporterFactory::Create(struct opentelemetry::v1::exporter::otlp::OtlpGrpcExporterOptions const & __ptr64) - ?Create@OtlpGrpcLogRecordExporterFactory@otlp@exporter@v1@opentelemetry@@SA?AV?$unique_ptr@VLogRecordExporter@logs@sdk@v1@opentelemetry@@U?$default_delete@VLogRecordExporter@logs@sdk@v1@opentelemetry@@@std@@@std@@AEBUOtlpGrpcExporterOptions@2345@@Z + // public: static class std::unique_ptr > __cdecl opentelemetry::v1::exporter::otlp::OtlpGrpcExporterFactory::Create(struct opentelemetry::v1::exporter::otlp::OtlpGrpcExporterOptions const & __ptr64) + ?Create@OtlpGrpcExporterFactory@otlp@exporter@v1@opentelemetry@@SA?AV?$unique_ptr@VSpanExporter@trace@sdk@v1@opentelemetry@@U?$default_delete@VSpanExporter@trace@sdk@v1@opentelemetry@@@std@@@std@@AEBUOtlpGrpcExporterOptions@2345@@Z // public: static class std::unique_ptr > __cdecl opentelemetry::v1::exporter::otlp::OtlpGrpcMetricExporterFactory::Create(struct opentelemetry::v1::exporter::otlp::OtlpGrpcMetricExporterOptions const & __ptr64) ?Create@OtlpGrpcMetricExporterFactory@otlp@exporter@v1@opentelemetry@@SA?AV?$unique_ptr@VPushMetricExporter@metrics@sdk@v1@opentelemetry@@U?$default_delete@VPushMetricExporter@metrics@sdk@v1@opentelemetry@@@std@@@std@@AEBUOtlpGrpcMetricExporterOptions@2345@@Z + // public: static class std::unique_ptr > __cdecl opentelemetry::v1::exporter::otlp::OtlpGrpcLogRecordExporterFactory::Create(struct opentelemetry::v1::exporter::otlp::OtlpGrpcLogRecordExporterOptions const &) + ?Create@OtlpGrpcLogRecordExporterFactory@otlp@exporter@v1@opentelemetry@@SA?AV?$unique_ptr@VLogRecordExporter@logs@sdk@v1@opentelemetry@@U?$default_delete@VLogRecordExporter@logs@sdk@v1@opentelemetry@@@std@@@std@@AEBUOtlpGrpcLogRecordExporterOptions@2345@@Z + // public: __cdecl opentelemetry::v1::exporter::otlp::OtlpGrpcExporterOptions::OtlpGrpcExporterOptions(void) + ??0OtlpGrpcExporterOptions@otlp@exporter@v1@opentelemetry@@QEAA@XZ + // public: __cdecl opentelemetry::v1::exporter::otlp::OtlpGrpcExporterOptions::~OtlpGrpcExporterOptions(void) + ??1OtlpGrpcExporterOptions@otlp@exporter@v1@opentelemetry@@QEAA@XZ + // public: __cdecl opentelemetry::v1::exporter::otlp::OtlpGrpcMetricExporterOptions::OtlpGrpcMetricExporterOptions(void) + ??0OtlpGrpcMetricExporterOptions@otlp@exporter@v1@opentelemetry@@QEAA@XZ + // public: __cdecl opentelemetry::v1::exporter::otlp::OtlpGrpcMetricExporterOptions::~OtlpGrpcMetricExporterOptions(void) + ??1OtlpGrpcMetricExporterOptions@otlp@exporter@v1@opentelemetry@@QEAA@XZ + // public: __cdecl opentelemetry::v1::exporter::otlp::OtlpGrpcLogRecordExporterOptions::OtlpGrpcLogRecordExporterOptions(void) + ??0OtlpGrpcLogRecordExporterOptions@otlp@exporter@v1@opentelemetry@@QEAA@XZ + // public: __cdecl opentelemetry::v1::exporter::otlp::OtlpGrpcLogRecordExporterOptions::~OtlpGrpcLogRecordExporterOptions(void) + ??1OtlpGrpcLogRecordExporterOptions@otlp@exporter@v1@opentelemetry@@QEAA@XZ ?GetOtlpDefaultGrpcTracesEndpoint@otlp@exporter@v1@opentelemetry@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ + ?GetOtlpDefaultGrpcMetricsEndpoint@otlp@exporter@v1@opentelemetry@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ + ?GetOtlpDefaultGrpcLogsEndpoint@otlp@exporter@v1@opentelemetry@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ ?GetOtlpDefaultGrpcTracesIsInsecure@otlp@exporter@v1@opentelemetry@@YA_NXZ - ?GetOtlpDefaultTracesSslCertificatePath@otlp@exporter@v1@opentelemetry@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ - ?GetOtlpDefaultTracesSslCertificateString@otlp@exporter@v1@opentelemetry@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ + ?GetOtlpDefaultGrpcMetricsIsInsecure@otlp@exporter@v1@opentelemetry@@YA_NXZ + ?GetOtlpDefaultGrpcLogsIsInsecure@otlp@exporter@v1@opentelemetry@@YA_NXZ #endif // defined(WITH_OTLP_GRPC) + #if defined(WITH_OTLP_HTTP) + // public: static class std::unique_ptr > __cdecl opentelemetry::v1::exporter::otlp::OtlpHttpExporterFactory::Create(struct opentelemetry::v1::exporter::otlp::OtlpHttpExporterOptions const & __ptr64) + ?Create@OtlpHttpExporterFactory@otlp@exporter@v1@opentelemetry@@SA?AV?$unique_ptr@VSpanExporter@trace@sdk@v1@opentelemetry@@U?$default_delete@VSpanExporter@trace@sdk@v1@opentelemetry@@@std@@@std@@AEBUOtlpHttpExporterOptions@2345@@Z + // public: static class std::unique_ptr > __cdecl opentelemetry::v1::exporter::otlp::OtlpHttpMetricExporterFactory::Create(struct opentelemetry::v1::exporter::otlp::OtlpHttpMetricExporterOptions const &) + ?Create@OtlpHttpMetricExporterFactory@otlp@exporter@v1@opentelemetry@@SA?AV?$unique_ptr@VPushMetricExporter@metrics@sdk@v1@opentelemetry@@U?$default_delete@VPushMetricExporter@metrics@sdk@v1@opentelemetry@@@std@@@std@@AEBUOtlpHttpMetricExporterOptions@2345@@Z // public: static class std::unique_ptr > __cdecl opentelemetry::v1::exporter::otlp::OtlpHttpLogRecordExporterFactory::Create(struct opentelemetry::v1::exporter::otlp::OtlpHttpLogRecordExporterOptions const & __ptr64) ?Create@OtlpHttpLogRecordExporterFactory@otlp@exporter@v1@opentelemetry@@SA?AV?$unique_ptr@VLogRecordExporter@logs@sdk@v1@opentelemetry@@U?$default_delete@VLogRecordExporter@logs@sdk@v1@opentelemetry@@@std@@@std@@AEBUOtlpHttpLogRecordExporterOptions@2345@@Z - ?GetOtlpDefaultHttpTracesEndpoint@otlp@exporter@v1@opentelemetry@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ - ?GetOtlpDefaultHttpLogsEndpoint@otlp@exporter@v1@opentelemetry@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ + // public: __cdecl opentelemetry::v1::exporter::otlp::OtlpHttpExporterOptions::OtlpHttpExporterOptions(void) + ??0OtlpHttpExporterOptions@otlp@exporter@v1@opentelemetry@@QEAA@XZ + // public: __cdecl opentelemetry::v1::exporter::otlp::OtlpHttpExporterOptions::~OtlpHttpExporterOptions(void) + ??1OtlpHttpExporterOptions@otlp@exporter@v1@opentelemetry@@QEAA@XZ + // public: __cdecl opentelemetry::v1::exporter::otlp::OtlpHttpMetricExporterOptions::OtlpHttpMetricExporterOptions(void) + ??0OtlpHttpMetricExporterOptions@otlp@exporter@v1@opentelemetry@@QEAA@XZ + // public: __cdecl opentelemetry::v1::exporter::otlp::OtlpHttpMetricExporterOptions::~OtlpHttpMetricExporterOptions(void) + ??1OtlpHttpMetricExporterOptions@otlp@exporter@v1@opentelemetry@@QEAA@XZ + // public: __cdecl opentelemetry::v1::exporter::otlp::OtlpHttpLogRecordExporterOptions::OtlpHttpLogRecordExporterOptions(void) + ??0OtlpHttpLogRecordExporterOptions@otlp@exporter@v1@opentelemetry@@QEAA@XZ + // public: __cdecl opentelemetry::v1::exporter::otlp::OtlpHttpLogRecordExporterOptions::~OtlpHttpLogRecordExporterOptions(void) + ??1OtlpHttpLogRecordExporterOptions@otlp@exporter@v1@opentelemetry@@QEAA@XZ - // public: static class std::unique_ptr > __cdecl opentelemetry::v1::exporter::otlp::OtlpHttpMetricExporterFactory::Create(struct opentelemetry::v1::exporter::otlp::OtlpHttpMetricExporterOptions const &) - ?Create@OtlpHttpMetricExporterFactory@otlp@exporter@v1@opentelemetry@@SA?AV?$unique_ptr@VPushMetricExporter@metrics@sdk@v1@opentelemetry@@U?$default_delete@VPushMetricExporter@metrics@sdk@v1@opentelemetry@@@std@@@std@@AEBUOtlpHttpMetricExporterOptions@2345@@Z + ?GetOtlpDefaultHttpTracesEndpoint@otlp@exporter@v1@opentelemetry@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ ?GetOtlpDefaultHttpMetricsEndpoint@otlp@exporter@v1@opentelemetry@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ + ?GetOtlpDefaultHttpLogsEndpoint@otlp@exporter@v1@opentelemetry@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ #endif // defined(WITH_OTLP_HTTP) // clang-format on From cb603ad97f33e52340e627e1cb43ba73bb1d7ef0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 Nov 2023 21:53:05 -0800 Subject: [PATCH 13/31] Bump actions/github-script from 6 to 7 (#2403) Bumps [actions/github-script](https://github.com/actions/github-script) from 6 to 7. - [Release notes](https://github.com/actions/github-script/releases) - [Commits](https://github.com/actions/github-script/compare/v6...v7) --- updated-dependencies: - dependency-name: actions/github-script dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/project_management_issue_open.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/project_management_issue_open.yml b/.github/workflows/project_management_issue_open.yml index e68e9ab152..28ee771ed1 100644 --- a/.github/workflows/project_management_issue_open.yml +++ b/.github/workflows/project_management_issue_open.yml @@ -10,7 +10,7 @@ jobs: permissions: issues: write steps: - - uses: actions/github-script@v6 + - uses: actions/github-script@v7 with: script: | github.rest.issues.addLabels({ From 8cba762d0d0d2cfe5ffaa8792f0b6cf64d24c75f Mon Sep 17 00:00:00 2001 From: Tom Tan Date: Mon, 20 Nov 2023 23:52:17 -0800 Subject: [PATCH 14/31] [BUILD] Update vcpkg to latest release (#2412) --- tools/vcpkg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/vcpkg b/tools/vcpkg index acc3bcf76b..8eb57355a4 160000 --- a/tools/vcpkg +++ b/tools/vcpkg @@ -1 +1 @@ -Subproject commit acc3bcf76b84ae5041c86ab55fe138ae7b8255c7 +Subproject commit 8eb57355a4ffb410a2e94c07b4dca2dffbee8e50 From 9b89843553d09afbae428913573d12afbb99be75 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Tue, 21 Nov 2023 01:06:06 -0800 Subject: [PATCH 15/31] [SDK] Cardinality limits for metrics streams (Sync Instruments + Delta Temporality) (#2255) --- .../sdk/metrics/state/attributes_hashmap.h | 63 ++++++++++ .../sdk/metrics/state/sync_metric_storage.h | 5 +- sdk/test/metrics/CMakeLists.txt | 1 + sdk/test/metrics/cardinality_limit_test.cc | 108 ++++++++++++++++++ 4 files changed, 175 insertions(+), 2 deletions(-) create mode 100644 sdk/test/metrics/cardinality_limit_test.cc diff --git a/sdk/include/opentelemetry/sdk/metrics/state/attributes_hashmap.h b/sdk/include/opentelemetry/sdk/metrics/state/attributes_hashmap.h index a4b53a37c5..85009a9fcb 100644 --- a/sdk/include/opentelemetry/sdk/metrics/state/attributes_hashmap.h +++ b/sdk/include/opentelemetry/sdk/metrics/state/attributes_hashmap.h @@ -23,6 +23,15 @@ namespace metrics using opentelemetry::sdk::common::OrderedAttributeMap; +constexpr size_t kAggregationCardinalityLimit = 2000; +const std::string kAggregationCardinalityLimitOverflowError = + "Maximum data points for metric stream exceeded. Entry added to overflow"; +const std::string kAttributesLimitOverflowKey = "otel.metrics.overflow"; +const bool kAttributesLimitOverflowValue = true; +const size_t kOverflowAttributesHash = common::GetHashForAttributeMap( + {{kAttributesLimitOverflowKey, + kAttributesLimitOverflowValue}}); // precalculated for optimization + class AttributeHashGenerator { public: @@ -35,6 +44,9 @@ class AttributeHashGenerator class AttributesHashMap { public: + AttributesHashMap(size_t attributes_limit = kAggregationCardinalityLimit) + : attributes_limit_(attributes_limit) + {} Aggregation *Get(size_t hash) const { auto it = hash_map_.find(hash); @@ -66,6 +78,11 @@ class AttributesHashMap return it->second.second.get(); } + if (IsOverflowAttributes()) + { + return GetOrSetOveflowAttributes(aggregation_callback); + } + MetricAttributes attr{attributes}; hash_map_[hash] = {attr, aggregation_callback()}; @@ -80,6 +97,12 @@ class AttributesHashMap { return it->second.second.get(); } + + if (IsOverflowAttributes()) + { + return GetOrSetOveflowAttributes(aggregation_callback); + } + MetricAttributes attr{}; hash_map_[hash] = {attr, aggregation_callback()}; return hash_map_[hash].second.get(); @@ -95,6 +118,11 @@ class AttributesHashMap return it->second.second.get(); } + if (IsOverflowAttributes()) + { + return GetOrSetOveflowAttributes(aggregation_callback); + } + MetricAttributes attr{attributes}; hash_map_[hash] = {attr, aggregation_callback()}; @@ -113,6 +141,12 @@ class AttributesHashMap { it->second.second = std::move(aggr); } + else if (IsOverflowAttributes()) + { + hash_map_[kOverflowAttributesHash] = { + MetricAttributes{{kAttributesLimitOverflowKey, kAttributesLimitOverflowValue}}, + std::move(aggr)}; + } else { MetricAttributes attr{attributes}; @@ -127,6 +161,12 @@ class AttributesHashMap { it->second.second = std::move(aggr); } + else if (IsOverflowAttributes()) + { + hash_map_[kOverflowAttributesHash] = { + MetricAttributes{{kAttributesLimitOverflowKey, kAttributesLimitOverflowValue}}, + std::move(aggr)}; + } else { MetricAttributes attr{attributes}; @@ -157,6 +197,29 @@ class AttributesHashMap private: std::unordered_map>> hash_map_; + size_t attributes_limit_; + + Aggregation *GetOrSetOveflowAttributes( + std::function()> aggregation_callback) + { + auto agg = aggregation_callback(); + return GetOrSetOveflowAttributes(std::move(agg)); + } + + Aggregation *GetOrSetOveflowAttributes(std::unique_ptr agg) + { + auto it = hash_map_.find(kOverflowAttributesHash); + if (it != hash_map_.end()) + { + return it->second.second.get(); + } + + MetricAttributes attr{{kAttributesLimitOverflowKey, kAttributesLimitOverflowValue}}; + hash_map_[kOverflowAttributesHash] = {attr, std::move(agg)}; + return hash_map_[kOverflowAttributesHash].second.get(); + } + + bool IsOverflowAttributes() const { return (hash_map_.size() + 1 >= attributes_limit_); } }; } // namespace metrics diff --git a/sdk/include/opentelemetry/sdk/metrics/state/sync_metric_storage.h b/sdk/include/opentelemetry/sdk/metrics/state/sync_metric_storage.h index b450b92179..cf249c39f2 100644 --- a/sdk/include/opentelemetry/sdk/metrics/state/sync_metric_storage.h +++ b/sdk/include/opentelemetry/sdk/metrics/state/sync_metric_storage.h @@ -40,9 +40,10 @@ class SyncMetricStorage : public MetricStorage, public SyncWritableMetricStorage const AttributesProcessor *attributes_processor, nostd::shared_ptr &&exemplar_reservoir OPENTELEMETRY_MAYBE_UNUSED, - const AggregationConfig *aggregation_config) + const AggregationConfig *aggregation_config, + size_t attributes_limit = kAggregationCardinalityLimit) : instrument_descriptor_(instrument_descriptor), - attributes_hashmap_(new AttributesHashMap()), + attributes_hashmap_(new AttributesHashMap(attributes_limit)), attributes_processor_(attributes_processor), #ifdef ENABLE_METRICS_EXEMPLAR_PREVIEW exemplar_reservoir_(exemplar_reservoir), diff --git a/sdk/test/metrics/CMakeLists.txt b/sdk/test/metrics/CMakeLists.txt index b30d71ae22..ccc31de689 100644 --- a/sdk/test/metrics/CMakeLists.txt +++ b/sdk/test/metrics/CMakeLists.txt @@ -16,6 +16,7 @@ foreach( attributes_hashmap_test base2_exponential_histogram_indexer_test circular_buffer_counter_test + cardinality_limit_test histogram_test sync_metric_storage_counter_test sync_metric_storage_histogram_test diff --git a/sdk/test/metrics/cardinality_limit_test.cc b/sdk/test/metrics/cardinality_limit_test.cc new file mode 100644 index 0000000000..d290f889b5 --- /dev/null +++ b/sdk/test/metrics/cardinality_limit_test.cc @@ -0,0 +1,108 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#include "common.h" +#include "opentelemetry/common/key_value_iterable_view.h" +#include "opentelemetry/sdk/metrics/aggregation/sum_aggregation.h" +#include "opentelemetry/sdk/metrics/instruments.h" +#include "opentelemetry/sdk/metrics/state/attributes_hashmap.h" +#include "opentelemetry/sdk/metrics/state/sync_metric_storage.h" + +#include +#include + +using namespace opentelemetry::sdk::metrics; +using namespace opentelemetry::common; +namespace nostd = opentelemetry::nostd; + +TEST(CardinalityLimit, AttributesHashMapBasicTests) +{ + AttributesHashMap hash_map(10); + std::function()> aggregation_callback = + []() -> std::unique_ptr { + return std::unique_ptr(new LongSumAggregation(true)); + }; + // add 10 unique metric points. 9 should be added to hashmap, 10th should be overflow. + long record_value = 100; + for (auto i = 0; i < 10; i++) + { + OrderedAttributeMap attributes = {{"key", std::to_string(i)}}; + auto hash = opentelemetry::sdk::common::GetHashForAttributeMap(attributes); + static_cast( + hash_map.GetOrSetDefault(attributes, aggregation_callback, hash)) + ->Aggregate(record_value); + } + EXPECT_EQ(hash_map.Size(), 10); + // add 5 unique metric points above limit, they all should get consolidated as single + // overflowmetric point. + for (auto i = 10; i < 15; i++) + { + OrderedAttributeMap attributes = {{"key", std::to_string(i)}}; + auto hash = opentelemetry::sdk::common::GetHashForAttributeMap(attributes); + static_cast( + hash_map.GetOrSetDefault(attributes, aggregation_callback, hash)) + ->Aggregate(record_value); + } + EXPECT_EQ(hash_map.Size(), 10); // only one more metric point should be added as overflow. + // get the overflow metric point + auto agg = hash_map.GetOrSetDefault( + OrderedAttributeMap({{kAttributesLimitOverflowKey, kAttributesLimitOverflowValue}}), + aggregation_callback, kOverflowAttributesHash); + EXPECT_NE(agg, nullptr); + auto sum_agg = static_cast(agg); + EXPECT_EQ(nostd::get(nostd::get(sum_agg->ToPoint()).value_), + record_value * 6); // 1 from previous 10, 5 from current 5. +} + +class WritableMetricStorageCardinalityLimitTestFixture + : public ::testing::TestWithParam +{}; + +TEST_P(WritableMetricStorageCardinalityLimitTestFixture, LongCounterSumAggregation) +{ + auto sdk_start_ts = std::chrono::system_clock::now(); + const size_t attributes_limit = 10; + InstrumentDescriptor instr_desc = {"name", "desc", "1unit", InstrumentType::kCounter, + InstrumentValueType::kLong}; + std::unique_ptr default_attributes_processor{ + new DefaultAttributesProcessor{}}; + SyncMetricStorage storage(instr_desc, AggregationType::kSum, default_attributes_processor.get(), + ExemplarReservoir::GetNoExemplarReservoir(), nullptr, attributes_limit); + + long record_value = 100; + // add 9 unique metric points, and 6 more above limit. + for (auto i = 0; i < 15; i++) + { + std::map attributes = {{"key", std::to_string(i)}}; + storage.RecordLong(record_value, + KeyValueIterableView>(attributes), + opentelemetry::context::Context{}); + } + AggregationTemporality temporality = GetParam(); + std::shared_ptr collector(new MockCollectorHandle(temporality)); + std::vector> collectors; + collectors.push_back(collector); + //... Some computation here + auto collection_ts = std::chrono::system_clock::now(); + size_t count_attributes = 0; + bool overflow_present = false; + storage.Collect( + collector.get(), collectors, sdk_start_ts, collection_ts, [&](const MetricData &metric_data) { + for (const auto &data_attr : metric_data.point_data_attr_) + { + const auto &data = opentelemetry::nostd::get(data_attr.point_data); + count_attributes++; + if (data_attr.attributes.begin()->first == kAttributesLimitOverflowKey) + { + EXPECT_EQ(nostd::get(data.value_), record_value * 6); + overflow_present = true; + } + } + return true; + }); + EXPECT_EQ(count_attributes, attributes_limit); + EXPECT_EQ(overflow_present, true); +} +INSTANTIATE_TEST_SUITE_P(All, + WritableMetricStorageCardinalityLimitTestFixture, + ::testing::Values(AggregationTemporality::kDelta)); From 71d0e50b12769375e0d84bbcfdf78f9b69a02dff Mon Sep 17 00:00:00 2001 From: Ehsan Saei <71217171+esigo@users.noreply.github.com> Date: Wed, 22 Nov 2023 17:26:14 +0100 Subject: [PATCH 16/31] [EXPORTER] Prometheus: Add unit to names, convert to word (#2213) --- .../exporters/prometheus/exporter_utils.h | 93 +++++- exporters/prometheus/src/exporter_utils.cc | 269 +++++++++++++++--- .../prometheus/test/exporter_utils_test.cc | 167 ++++++++--- 3 files changed, 454 insertions(+), 75 deletions(-) diff --git a/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h b/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h index 96c7ac8826..fa3eedd2c4 100644 --- a/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h +++ b/exporters/prometheus/include/opentelemetry/exporters/prometheus/exporter_utils.h @@ -7,6 +7,7 @@ #include #include #include "opentelemetry/metrics/provider.h" +#include "opentelemetry/nostd/string_view.h" #include "opentelemetry/sdk/metrics/meter.h" #include "opentelemetry/version.h" @@ -35,7 +36,17 @@ class PrometheusExporterUtils private: /** - * Append key-value pair to prometheus labels. + * Sanitize the given metric name or label according to Prometheus rule. + * + * This function is needed because names in OpenTelemetry can contain + * alphanumeric characters, '_', '.', and '-', whereas in Prometheus the + * name should only contain alphanumeric characters and '_'. + * @param name name + */ + static std::string SanitizeNames(std::string name); + + /** + * Sanitize the given metric name or label according to Prometheus rule. * * @param name label name * @param value label value @@ -45,6 +56,79 @@ class PrometheusExporterUtils std::string value, std::vector<::prometheus::ClientMetric::Label> *labels); + static std::string MapToPrometheusName(const std::string &name, + const std::string &unit, + ::prometheus::MetricType prometheus_type); + + /** + * A utility function that returns the equivalent Prometheus name for the provided OTLP metric + * unit. + * + * @param raw_metric_unitName The raw metric unit for which Prometheus metric unit needs to be + * computed. + * @return the computed Prometheus metric unit equivalent of the OTLP metric unit + */ + static std::string GetEquivalentPrometheusUnit(const std::string &raw_metric_unitName); + + /** + * This method retrieves the expanded Prometheus unit name for known abbreviations. OTLP metrics + * use the c/s notation as specified at UCUM. The list of + * mappings is adopted from OpenTelemetry + * Collector Contrib. + * + * @param unit_abbreviation The unit that name that needs to be expanded/converted to Prometheus + * units. + * @return The expanded/converted unit name if known, otherwise returns the input unit name as-is. + */ + static std::string GetPrometheusUnit(const std::string &unit_abbreviation); + + /** + * This method retrieves the expanded Prometheus unit name to be used with "per" units for known + * units. For example: s => per second (singular) + * + * @param per_unit_abbreviation The unit abbreviation used in a 'per' unit. + * @return The expanded unit equivalent to be used in 'per' unit if the input is a known unit, + * otherwise returns the input as-is. + */ + static std::string GetPrometheusPerUnit(const std::string &per_unit_abbreviation); + + /** + * Replaces all characters that are not a letter or a digit with '_' to make the resulting string + * Prometheus compliant. This method also removes leading and trailing underscores - this is done + * to keep the resulting unit similar to what is produced from the collector's implementation. + * + * @param str The string input that needs to be made Prometheus compliant. + * @return the cleaned-up Prometheus compliant string. + */ + static std::string CleanUpString(const std::string &str); + + /** + * This method is used to convert the units expressed as a rate via '/' symbol in their name to + * their expanded text equivalent. For instance, km/h => km_per_hour. The method operates on the + * input by splitting it in 2 parts - before and after '/' symbol and will attempt to expand any + * known unit abbreviation in both parts. Unknown abbreviations & unsupported characters will + * remain unchanged in the final output of this function. + * + * @param rate_expressed_unit The rate unit input that needs to be converted to its text + * equivalent. + * @return The text equivalent of unit expressed as rate. If the input does not contain '/', the + * function returns it as-is. + */ + static std::string ConvertRateExpressedToPrometheusUnit(const std::string &rate_expressed_unit); + + /** + * This method drops all characters enclosed within '{}' (including the curly braces) by replacing + * them with an empty string. Note that this method will not produce the intended effect if there + * are nested curly braces within the outer enclosure of '{}'. + * + *

For instance, {packet{s}s} => s}. + * + * @param unit The input unit from which text within curly braces needs to be removed. + * @return The resulting unit after removing the text within '{}'. + */ + static std::string RemoveUnitPortionInBraces(const std::string &unit); + static opentelemetry::sdk::metrics::AggregationType getAggregationType( const opentelemetry::sdk::metrics::PointType &point_type); @@ -58,6 +142,7 @@ class PrometheusExporterUtils * Add a target_info metric to collect resource attributes */ static void SetTarget(const sdk::metrics::ResourceMetrics &data, + std::chrono::nanoseconds time, const opentelemetry::sdk::instrumentationscope::InstrumentationScope *scope, std::vector<::prometheus::MetricFamily> *output); @@ -70,6 +155,7 @@ class PrometheusExporterUtils const opentelemetry::sdk::metrics::PointAttributes &labels, const opentelemetry::sdk::instrumentationscope::InstrumentationScope *scope, ::prometheus::MetricType type, + std::chrono::nanoseconds time, ::prometheus::MetricFamily *metric_family, const opentelemetry::sdk::resource::Resource *resource); @@ -83,6 +169,7 @@ class PrometheusExporterUtils const std::vector &counts, const opentelemetry::sdk::metrics::PointAttributes &labels, const opentelemetry::sdk::instrumentationscope::InstrumentationScope *scope, + std::chrono::nanoseconds time, ::prometheus::MetricFamily *metric_family, const opentelemetry::sdk::resource::Resource *resource); @@ -92,6 +179,7 @@ class PrometheusExporterUtils static void SetMetricBasic( ::prometheus::ClientMetric &metric, const opentelemetry::sdk::metrics::PointAttributes &labels, + std::chrono::nanoseconds time, const opentelemetry::sdk::instrumentationscope::InstrumentationScope *scope, const opentelemetry::sdk::resource::Resource *resource); @@ -122,6 +210,9 @@ class PrometheusExporterUtils const std::vector &boundaries, const std::vector &counts, ::prometheus::ClientMetric *metric); + + // For testing + friend class SanitizeNameTester; }; } // namespace metrics } // namespace exporter diff --git a/exporters/prometheus/src/exporter_utils.cc b/exporters/prometheus/src/exporter_utils.cc index 42fafc6336..4b1ee054c4 100644 --- a/exporters/prometheus/src/exporter_utils.cc +++ b/exporters/prometheus/src/exporter_utils.cc @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 #include +#include #include #include #include @@ -93,22 +94,6 @@ std::string SanitizeLabel(std::string label_key) }); } -/** - * Sanitize the given metric name according to Prometheus rule. - * Prometheus metric names are required to match the following regex: - * [a-zA-Z_:]([a-zA-Z0-9_:])* - * and multiple consecutive _ characters must be collapsed to a single _. - */ -std::string SanitizeName(std::string name) -{ - return Sanitize(name, [](int i, char c) { - return (c >= 'a' && c <= 'z') || // - (c >= 'A' && c <= 'Z') || // - c == '_' || // - c == ':' || // - (c >= '0' && c <= '9' && i > 0); - }); -} } // namespace /** @@ -132,11 +117,16 @@ std::vector PrometheusExporterUtils::TranslateT std::vector output; output.reserve(reserve_size); - + if (data.scope_metric_data_.empty()) + { + return output; + } // Append target_info as the first metric if (populate_target_info && !data.scope_metric_data_.empty()) { - SetTarget(data, (*data.scope_metric_data_.begin()).scope_, &output); + SetTarget(data, + data.scope_metric_data_.begin()->metric_data_.begin()->end_ts.time_since_epoch(), + (*data.scope_metric_data_.begin()).scope_, &output); } for (const auto &instrumentation_info : data.scope_metric_data_) @@ -145,21 +135,22 @@ std::vector PrometheusExporterUtils::TranslateT { auto origin_name = metric_data.instrument_descriptor.name_; auto unit = metric_data.instrument_descriptor.unit_; - auto sanitized = SanitizeName(origin_name); prometheus_client::MetricFamily metric_family; - metric_family.name = sanitized + "_" + unit; metric_family.help = metric_data.instrument_descriptor.description_; + auto time = metric_data.end_ts.time_since_epoch(); + auto front = metric_data.point_data_attr_.front(); + auto kind = getAggregationType(front.point_data); + bool is_monotonic = true; + if (kind == sdk::metrics::AggregationType::kSum) + { + is_monotonic = nostd::get(front.point_data).is_monotonic_; + } + const prometheus_client::MetricType type = TranslateType(kind, is_monotonic); + metric_family.name = MapToPrometheusName(metric_data.instrument_descriptor.name_, + metric_data.instrument_descriptor.unit_, type); + metric_family.type = type; for (const auto &point_data_attr : metric_data.point_data_attr_) { - auto kind = getAggregationType(point_data_attr.point_data); - bool is_monotonic = true; - if (kind == sdk::metrics::AggregationType::kSum) - { - is_monotonic = - nostd::get(point_data_attr.point_data).is_monotonic_; - } - const prometheus_client::MetricType type = TranslateType(kind, is_monotonic); - metric_family.type = type; if (type == prometheus_client::MetricType::Histogram) // Histogram { auto histogram_point_data = @@ -176,7 +167,7 @@ std::vector PrometheusExporterUtils::TranslateT sum = static_cast(nostd::get(histogram_point_data.sum_)); } SetData(std::vector{sum, (double)histogram_point_data.count_}, boundaries, counts, - point_data_attr.attributes, instrumentation_info.scope_, &metric_family, + point_data_attr.attributes, instrumentation_info.scope_, time, &metric_family, data.resource_); } else if (type == prometheus_client::MetricType::Gauge) @@ -187,7 +178,7 @@ std::vector PrometheusExporterUtils::TranslateT auto last_value_point_data = nostd::get(point_data_attr.point_data); std::vector values{last_value_point_data.value_}; - SetData(values, point_data_attr.attributes, instrumentation_info.scope_, type, + SetData(values, point_data_attr.attributes, instrumentation_info.scope_, type, time, &metric_family, data.resource_); } else if (nostd::holds_alternative(point_data_attr.point_data)) @@ -195,7 +186,7 @@ std::vector PrometheusExporterUtils::TranslateT auto sum_point_data = nostd::get(point_data_attr.point_data); std::vector values{sum_point_data.value_}; - SetData(values, point_data_attr.attributes, instrumentation_info.scope_, type, + SetData(values, point_data_attr.attributes, instrumentation_info.scope_, type, time, &metric_family, data.resource_); } else @@ -212,7 +203,7 @@ std::vector PrometheusExporterUtils::TranslateT auto sum_point_data = nostd::get(point_data_attr.point_data); std::vector values{sum_point_data.value_}; - SetData(values, point_data_attr.attributes, instrumentation_info.scope_, type, + SetData(values, point_data_attr.attributes, instrumentation_info.scope_, type, time, &metric_family, data.resource_); } else @@ -240,6 +231,205 @@ void PrometheusExporterUtils::AddPrometheusLabel( labels->emplace_back(std::move(prometheus_label)); } +/** + * Sanitize the given metric name or label according to Prometheus rule. + * + * This function is needed because names in OpenTelemetry can contain + * alphanumeric characters, '_', '.', and '-', whereas in Prometheus the + * name should only contain alphanumeric characters and '_'. + */ +std::string PrometheusExporterUtils::SanitizeNames(std::string name) +{ + constexpr const auto replacement = '_'; + constexpr const auto replacement_dup = '='; + + auto valid = [](int i, char c) { + if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == ':' || + (c >= '0' && c <= '9' && i > 0)) + { + return true; + } + return false; + }; + + bool has_dup = false; + for (int i = 0; i < (int)name.size(); ++i) + { + if (valid(i, name[i])) + { + continue; + } + if (i > 0 && (name[i - 1] == replacement || name[i - 1] == replacement_dup)) + { + has_dup = true; + name[i] = replacement_dup; + } + else + { + name[i] = replacement; + } + } + if (has_dup) + { + auto end = std::remove(name.begin(), name.end(), replacement_dup); + return std::string{name.begin(), end}; + } + return name; +} + +std::regex INVALID_CHARACTERS_PATTERN("[^a-zA-Z0-9]"); +std::regex CHARACTERS_BETWEEN_BRACES_PATTERN("\\{(.*?)\\}"); +std::regex SANITIZE_LEADING_UNDERSCORES("^_+"); +std::regex SANITIZE_TRAILING_UNDERSCORES("_+$"); +std::regex SANITIZE_CONSECUTIVE_UNDERSCORES("[_]{2,}"); + +std::string PrometheusExporterUtils::GetEquivalentPrometheusUnit( + const std::string &raw_metric_unit_name) +{ + if (raw_metric_unit_name.empty()) + { + return raw_metric_unit_name; + } + + std::string converted_metric_unit_name = RemoveUnitPortionInBraces(raw_metric_unit_name); + converted_metric_unit_name = ConvertRateExpressedToPrometheusUnit(converted_metric_unit_name); + + return CleanUpString(GetPrometheusUnit(converted_metric_unit_name)); +} + +std::string PrometheusExporterUtils::GetPrometheusUnit(const std::string &unit_abbreviation) +{ + static std::unordered_map units{// Time + {"d", "days"}, + {"h", "hours"}, + {"min", "minutes"}, + {"s", "seconds"}, + {"ms", "milliseconds"}, + {"us", "microseconds"}, + {"ns", "nanoseconds"}, + // Bytes + {"By", "bytes"}, + {"KiBy", "kibibytes"}, + {"MiBy", "mebibytes"}, + {"GiBy", "gibibytes"}, + {"TiBy", "tibibytes"}, + {"KBy", "kilobytes"}, + {"MBy", "megabytes"}, + {"GBy", "gigabytes"}, + {"TBy", "terabytes"}, + {"By", "bytes"}, + {"KBy", "kilobytes"}, + {"MBy", "megabytes"}, + {"GBy", "gigabytes"}, + {"TBy", "terabytes"}, + // SI + {"m", "meters"}, + {"V", "volts"}, + {"A", "amperes"}, + {"J", "joules"}, + {"W", "watts"}, + {"g", "grams"}, + // Misc + {"Cel", "celsius"}, + {"Hz", "hertz"}, + {"1", ""}, + {"%", "percent"}}; + auto res_it = units.find(unit_abbreviation); + if (res_it == units.end()) + { + return unit_abbreviation; + } + return res_it->second; +} + +std::string PrometheusExporterUtils::GetPrometheusPerUnit(const std::string &per_unit_abbreviation) +{ + static std::unordered_map per_units{ + {"s", "second"}, {"m", "minute"}, {"h", "hour"}, {"d", "day"}, + {"w", "week"}, {"mo", "month"}, {"y", "year"}}; + auto res_it = per_units.find(per_unit_abbreviation); + if (res_it == per_units.end()) + { + return per_unit_abbreviation; + } + return res_it->second; +} + +std::string PrometheusExporterUtils::RemoveUnitPortionInBraces(const std::string &unit) +{ + return std::regex_replace(unit, CHARACTERS_BETWEEN_BRACES_PATTERN, ""); +} + +std::string PrometheusExporterUtils::ConvertRateExpressedToPrometheusUnit( + const std::string &rate_expressed_unit) +{ + size_t pos = rate_expressed_unit.find("/"); + if (pos == std::string::npos) + { + return rate_expressed_unit; + } + + std::vector rate_entities; + rate_entities.push_back(rate_expressed_unit.substr(0, pos)); + rate_entities.push_back(rate_expressed_unit.substr(pos + 1)); + + if (rate_entities[1].empty()) + { + return rate_expressed_unit; + } + + std::string prometheus_unit = GetPrometheusUnit(rate_entities[0]); + std::string prometheus_per_unit = GetPrometheusPerUnit(rate_entities[1]); + + return prometheus_unit + "_per_" + prometheus_per_unit; +} + +std::string PrometheusExporterUtils::CleanUpString(const std::string &str) +{ + std::string cleaned_string = std::regex_replace(str, INVALID_CHARACTERS_PATTERN, "_"); + cleaned_string = std::regex_replace(cleaned_string, SANITIZE_CONSECUTIVE_UNDERSCORES, "_"); + cleaned_string = std::regex_replace(cleaned_string, SANITIZE_TRAILING_UNDERSCORES, ""); + cleaned_string = std::regex_replace(cleaned_string, SANITIZE_LEADING_UNDERSCORES, ""); + + return cleaned_string; +} + +std::string PrometheusExporterUtils::MapToPrometheusName( + const std::string &name, + const std::string &unit, + prometheus_client::MetricType prometheus_type) +{ + auto sanitized_name = SanitizeNames(name); + std::string prometheus_equivalent_unit = GetEquivalentPrometheusUnit(unit); + + // Append prometheus unit if not null or empty. + if (!prometheus_equivalent_unit.empty() && + sanitized_name.find(prometheus_equivalent_unit) == std::string::npos) + { + sanitized_name += "_" + prometheus_equivalent_unit; + } + + // Special case - counter + if (prometheus_type == prometheus_client::MetricType::Counter) + { + auto t_pos = sanitized_name.rfind("_total"); + bool ends_with_total = t_pos == sanitized_name.size() - 6; + if (!ends_with_total) + { + sanitized_name += "_total"; + } + } + + // Special case - gauge + if (unit == "1" && prometheus_type == prometheus_client::MetricType::Gauge && + sanitized_name.find("ratio") == std::string::npos) + { + sanitized_name += "_ratio"; + } + + return CleanUpString(SanitizeNames(sanitized_name)); +} + metric_sdk::AggregationType PrometheusExporterUtils::getAggregationType( const metric_sdk::PointType &point_type) { @@ -295,6 +485,7 @@ prometheus_client::MetricType PrometheusExporterUtils::TranslateType( void PrometheusExporterUtils::SetTarget( const sdk::metrics::ResourceMetrics &data, + std::chrono::nanoseconds time, const opentelemetry::sdk::instrumentationscope::InstrumentationScope *scope, std::vector<::prometheus::MetricFamily> *output) { @@ -313,11 +504,11 @@ void PrometheusExporterUtils::SetTarget( metric.info.value = 1.0; metric_sdk::PointAttributes empty_attributes; - SetMetricBasic(metric, empty_attributes, scope, data.resource_); + SetMetricBasic(metric, empty_attributes, time, scope, data.resource_); for (auto &label : data.resource_->GetAttributes()) { - AddPrometheusLabel(SanitizeName(label.first), AttributeValueToString(label.second), + AddPrometheusLabel(SanitizeNames(label.first), AttributeValueToString(label.second), &metric.label); } @@ -334,12 +525,13 @@ void PrometheusExporterUtils::SetData( const metric_sdk::PointAttributes &labels, const opentelemetry::sdk::instrumentationscope::InstrumentationScope *scope, prometheus_client::MetricType type, + std::chrono::nanoseconds time, prometheus_client::MetricFamily *metric_family, const opentelemetry::sdk::resource::Resource *resource) { metric_family->metric.emplace_back(); prometheus_client::ClientMetric &metric = metric_family->metric.back(); - SetMetricBasic(metric, labels, scope, resource); + SetMetricBasic(metric, labels, time, scope, resource); SetValue(values, type, &metric); } @@ -354,12 +546,13 @@ void PrometheusExporterUtils::SetData( const std::vector &counts, const metric_sdk::PointAttributes &labels, const opentelemetry::sdk::instrumentationscope::InstrumentationScope *scope, + std::chrono::nanoseconds time, prometheus_client::MetricFamily *metric_family, const opentelemetry::sdk::resource::Resource *resource) { metric_family->metric.emplace_back(); prometheus_client::ClientMetric &metric = metric_family->metric.back(); - SetMetricBasic(metric, labels, scope, resource); + SetMetricBasic(metric, labels, time, scope, resource); SetValue(values, boundaries, counts, &metric); } @@ -369,9 +562,11 @@ void PrometheusExporterUtils::SetData( void PrometheusExporterUtils::SetMetricBasic( prometheus_client::ClientMetric &metric, const metric_sdk::PointAttributes &labels, + std::chrono::nanoseconds time, const opentelemetry::sdk::instrumentationscope::InstrumentationScope *scope, const opentelemetry::sdk::resource::Resource *resource) { + metric.timestamp_ms = time.count() / 1000000; if (labels.empty() && nullptr == resource) { return; diff --git a/exporters/prometheus/test/exporter_utils_test.cc b/exporters/prometheus/test/exporter_utils_test.cc index 8ff324d7ac..b876e7369c 100644 --- a/exporters/prometheus/test/exporter_utils_test.cc +++ b/exporters/prometheus/test/exporter_utils_test.cc @@ -15,17 +15,62 @@ namespace prometheus_client = ::prometheus; OPENTELEMETRY_BEGIN_NAMESPACE +namespace exporter +{ +namespace metrics +{ +class SanitizeNameTester +{ +public: + static std::string sanitize(std::string name) + { + return PrometheusExporterUtils::SanitizeNames(name); + } + static std::string getPrometheusUnit(const std::string &unit_abbreviation) + { + return PrometheusExporterUtils::GetPrometheusUnit(unit_abbreviation); + } + static std::string getPrometheusPerUnit(const std::string &per_unit_abbreviation) + { + return PrometheusExporterUtils::GetPrometheusPerUnit(per_unit_abbreviation); + } + static std::string removeUnitPortionInBraces(const std::string &unit) + { + return PrometheusExporterUtils::RemoveUnitPortionInBraces(unit); + } + static std::string convertRateExpressedToPrometheusUnit(const std::string &rate_expressed_unit) + { + return PrometheusExporterUtils::ConvertRateExpressedToPrometheusUnit(rate_expressed_unit); + } + static std::string cleanUpString(const std::string &str) + { + return PrometheusExporterUtils::CleanUpString(str); + } + static std::string getEquivalentPrometheusUnit(const std::string &raw_metric_unit_name) + { + return PrometheusExporterUtils::GetEquivalentPrometheusUnit(raw_metric_unit_name); + } + static std::string mapToPrometheusName(const std::string &name, + const std::string &unit, + prometheus_client::MetricType prometheus_type) + { + return PrometheusExporterUtils::MapToPrometheusName(name, unit, prometheus_type); + } +}; +} // namespace metrics +} // namespace exporter + template void assert_basic(prometheus_client::MetricFamily &metric, - const std::string &sanitized_name, + const std::string &expected_name, const std::string &description, prometheus_client::MetricType type, size_t label_num, std::vector vals) { - ASSERT_EQ(metric.name, sanitized_name + "_unit"); // name sanitized - ASSERT_EQ(metric.help, description); // description not changed - ASSERT_EQ(metric.type, type); // type translated + ASSERT_EQ(metric.name, expected_name); // name sanitized + ASSERT_EQ(metric.help, description); // description not changed + ASSERT_EQ(metric.type, type); // type translated // Prometheus metric data points should not have explicit timestamps for (const prometheus::ClientMetric &cm : metric.metric) @@ -109,12 +154,10 @@ TEST(PrometheusExporterUtils, TranslateToPrometheusIntegerCounter) auto translated = PrometheusExporterUtils::TranslateToPrometheus(metrics_data); ASSERT_EQ(translated.size(), 2); - auto metric1 = translated[1]; std::vector vals = {10}; - assert_basic(metric1, "library_name", "description", prometheus_client::MetricType::Counter, 3, - vals); - + assert_basic(metric1, "library_name_unit_total", "description", + prometheus_client::MetricType::Counter, 3, vals); int checked_label_num = 0; for (auto &label : translated[0].metric[0].label) { @@ -157,7 +200,7 @@ TEST(PrometheusExporterUtils, TranslateToPrometheusIntegerLastValue) auto metric1 = translated[1]; std::vector vals = {10}; - assert_basic(metric1, "library_name", "description", prometheus_client::MetricType::Gauge, 3, + assert_basic(metric1, "library_name_unit", "description", prometheus_client::MetricType::Gauge, 3, vals); int checked_label_num = 0; @@ -196,8 +239,8 @@ TEST(PrometheusExporterUtils, TranslateToPrometheusHistogramNormal) auto metric = translated[1]; std::vector vals = {3, 900.5, 4}; - assert_basic(metric, "library_name", "description", prometheus_client::MetricType::Histogram, 3, - vals); + assert_basic(metric, "library_name_unit", "description", prometheus_client::MetricType::Histogram, + 3, vals); assert_histogram(metric, std::list{10.1, 20.2, 30.2}, {200, 300, 400, 500}); int checked_label_num = 0; @@ -230,27 +273,12 @@ class SanitizeTest : public ::testing::Test InstrumentationScope::Create("library_name", "1.2.0"); protected: - void CheckSanitizeName(const std::string &original, const std::string &sanitized) - { - metric_sdk::InstrumentDescriptor instrument_descriptor{ - original, "description", "unit", metric_sdk::InstrumentType::kCounter, - metric_sdk::InstrumentValueType::kDouble}; - std::vector result = PrometheusExporterUtils::TranslateToPrometheus( - {&resource_, - std::vector{ - {instrumentation_scope_.get(), - std::vector{ - {{instrument_descriptor, {}, {}, {}, {{{}, {}}}}}}}}}, - false); - EXPECT_EQ(result.begin()->name, sanitized + "_unit"); - } - void CheckSanitizeLabel(const std::string &original, const std::string &sanitized) { metric_sdk::InstrumentDescriptor instrument_descriptor{ "name", "description", "unit", metric_sdk::InstrumentType::kCounter, metric_sdk::InstrumentValueType::kDouble}; - std::vector result = PrometheusExporterUtils::TranslateToPrometheus( + auto result = PrometheusExporterUtils::TranslateToPrometheus( {&resource_, std::vector{ {instrumentation_scope_.get(), @@ -261,16 +289,6 @@ class SanitizeTest : public ::testing::Test } }; -TEST_F(SanitizeTest, Name) -{ - CheckSanitizeName("name", "name"); - CheckSanitizeName("name?", "name_"); - CheckSanitizeName("name???", "name_"); - CheckSanitizeName("name?__", "name_"); - CheckSanitizeName("name?__name", "name_name"); - CheckSanitizeName("name?__name:", "name_name:"); -} - TEST_F(SanitizeTest, Label) { CheckSanitizeLabel("name", "name"); @@ -281,6 +299,8 @@ TEST_F(SanitizeTest, Label) CheckSanitizeLabel("name?__name:", "name_name_"); } +TEST_F(SanitizeTest, Name) {} + class AttributeCollisionTest : public ::testing::Test { Resource resource_ = Resource::Create(ResourceAttributes{}); @@ -325,6 +345,79 @@ TEST_F(AttributeCollisionTest, SeparatesDistinctKeys) {"otel_scope_version", "1.2.0"}}); } +TEST(PrometheusExporterUtils, PrometheusUnit) +{ + ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("d"), "days"); + ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("h"), "hours"); + ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("min"), "minutes"); + ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("s"), "seconds"); + ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("ms"), "milliseconds"); + ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("us"), "microseconds"); + ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("ns"), "nanoseconds"); + + ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("By"), "bytes"); + ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("KiBy"), "kibibytes"); + ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("MiBy"), "mebibytes"); + ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("GiBy"), "gibibytes"); + ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("TiBy"), "tibibytes"); + ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("KBy"), "kilobytes"); + ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("MBy"), "megabytes"); + ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("GBy"), "gigabytes"); + ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("TBy"), "terabytes"); + ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("By"), "bytes"); + ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("KBy"), "kilobytes"); + ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("MBy"), "megabytes"); + ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("GBy"), "gigabytes"); + ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("TBy"), "terabytes"); + + ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("m"), "meters"); + ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("V"), "volts"); + ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("A"), "amperes"); + ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("J"), "joules"); + ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("W"), "watts"); + ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("g"), "grams"); + + ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("Cel"), "celsius"); + ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("Hz"), "hertz"); + ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("1"), ""); + ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusUnit("%"), "percent"); +} + +TEST(PrometheusExporterUtils, PrometheusPerUnit) +{ + ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusPerUnit("s"), "second"); + ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusPerUnit("m"), "minute"); + ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusPerUnit("h"), "hour"); + ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusPerUnit("d"), "day"); + ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusPerUnit("w"), "week"); + ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusPerUnit("mo"), "month"); + ASSERT_EQ(exporter::metrics::SanitizeNameTester::getPrometheusPerUnit("y"), "year"); +} + +TEST(PrometheusExporterUtils, RemoveUnitPortionInBraces) +{ + ASSERT_EQ(exporter::metrics::SanitizeNameTester::removeUnitPortionInBraces("{unit}"), ""); + ASSERT_EQ(exporter::metrics::SanitizeNameTester::removeUnitPortionInBraces("unit{unit}"), "unit"); + ASSERT_EQ(exporter::metrics::SanitizeNameTester::removeUnitPortionInBraces("unit_{unit}"), + "unit_"); +} + +TEST(PrometheusExporterUtils, ConvertRateExpressedToPrometheusUnit) +{ + ASSERT_EQ(exporter::metrics::SanitizeNameTester::convertRateExpressedToPrometheusUnit("unit/d"), + "unit_per_day"); + ASSERT_EQ(exporter::metrics::SanitizeNameTester::convertRateExpressedToPrometheusUnit("unit/s"), + "unit_per_second"); + ASSERT_EQ(exporter::metrics::SanitizeNameTester::convertRateExpressedToPrometheusUnit("unit/"), + "unit/"); + ASSERT_EQ(exporter::metrics::SanitizeNameTester::convertRateExpressedToPrometheusUnit("unit"), + "unit"); + ASSERT_EQ(exporter::metrics::SanitizeNameTester::convertRateExpressedToPrometheusUnit("unit/m"), + "unit_per_minute"); + ASSERT_EQ(exporter::metrics::SanitizeNameTester::convertRateExpressedToPrometheusUnit("/m"), + "_per_minute"); +} + TEST_F(AttributeCollisionTest, JoinsCollidingKeys) { CheckTranslation({{"foo.a", "value1"}, {"foo_a", "value2"}}, {{"foo_a", "value1;value2"}, From 064fef0d871c57ffac6739d3311659a5770a9db4 Mon Sep 17 00:00:00 2001 From: Tom Tan Date: Wed, 29 Nov 2023 09:45:09 -0800 Subject: [PATCH 17/31] [Metrics] Make context optional for histogram instruments in Metrics SDK (#2416) --- api/include/opentelemetry/metrics/noop.h | 7 + .../opentelemetry/metrics/sync_instruments.h | 99 +++++-- .../sdk/metrics/sync_instruments.h | 122 +++----- sdk/src/metrics/meter.cc | 4 +- sdk/src/metrics/sync_instruments.cc | 265 ++++++++++++++++-- sdk/test/metrics/sync_instruments_test.cc | 17 +- 6 files changed, 375 insertions(+), 139 deletions(-) diff --git a/api/include/opentelemetry/metrics/noop.h b/api/include/opentelemetry/metrics/noop.h index f20e855cb7..d34a0e681b 100644 --- a/api/include/opentelemetry/metrics/noop.h +++ b/api/include/opentelemetry/metrics/noop.h @@ -44,6 +44,13 @@ class NoopHistogram : public Histogram const common::KeyValueIterable & /* attributes */, const context::Context & /* context */) noexcept override {} +#if OPENTELEMETRY_ABI_VERSION_NO >= 2 + void Record(T /*value*/, + const opentelemetry::common::KeyValueIterable & /*attributes*/) noexcept override + {} + + void Record(T /*value*/) noexcept override {} +#endif }; template diff --git a/api/include/opentelemetry/metrics/sync_instruments.h b/api/include/opentelemetry/metrics/sync_instruments.h index b26e527c2c..4471677433 100644 --- a/api/include/opentelemetry/metrics/sync_instruments.h +++ b/api/include/opentelemetry/metrics/sync_instruments.h @@ -22,31 +22,43 @@ class SynchronousInstrument virtual ~SynchronousInstrument() = default; }; +/* A Counter instrument that adds values. */ template class Counter : public SynchronousInstrument { public: /** - * Add adds the value to the counter's sum + * Record a value * * @param value The increment amount. MUST be non-negative. */ virtual void Add(T value) noexcept = 0; + /** + * Record a value + * + * @param value The increment amount. MUST be non-negative. + * @param context The explicit context to associate with this measurement. + */ virtual void Add(T value, const context::Context &context) noexcept = 0; /** - * Add adds the value to the counter's sum. The attributes should contain - * the keys and values to be associated with this value. Counters only - * accept positive valued updates. + * Record a value with a set of attributes. * * @param value The increment amount. MUST be non-negative. - * @param attributes the set of attributes, as key-value pairs + * @param attributes A set of attributes to associate with the value. */ virtual void Add(T value, const common::KeyValueIterable &attributes) noexcept = 0; + /** + * Record a value with a set of attributes. + * + * @param value The increment amount. MUST be non-negative. + * @param attributes A set of attributes to associate with the value. + * @param context The explicit context to associate with this measurement. + */ virtual void Add(T value, const common::KeyValueIterable &attributes, const context::Context &context) noexcept = 0; @@ -55,8 +67,7 @@ class Counter : public SynchronousInstrument nostd::enable_if_t::value> * = nullptr> void Add(T value, const U &attributes) noexcept { - auto context = context::Context{}; - this->Add(value, common::KeyValueIterableView{attributes}, context); + this->Add(value, common::KeyValueIterableView{attributes}); } template > attributes) noexcept { - auto context = context::Context{}; - this->Add(value, - nostd::span>{ - attributes.begin(), attributes.end()}, - context); + this->Add(value, nostd::span>{ + attributes.begin(), attributes.end()}); } void Add(T value, @@ -94,18 +102,54 @@ template class Histogram : public SynchronousInstrument { public: +#if OPENTELEMETRY_ABI_VERSION_NO >= 2 /** + * @since ABI_VERSION 2 * Records a value. * * @param value The measurement value. MUST be non-negative. */ + virtual void Record(T value) noexcept = 0; + + /** + * @since ABI_VERSION 2 + * Records a value with a set of attributes. + * + * @param value The measurement value. MUST be non-negative. + * @param attribute A set of attributes to associate with the value. + */ + virtual void Record(T value, const common::KeyValueIterable &attribute) noexcept = 0; + + template ::value> * = nullptr> + void Record(T value, const U &attributes) noexcept + { + this->Record(value, common::KeyValueIterableView{attributes}); + } + + void Record(T value, + std::initializer_list> + attributes) noexcept + { + this->Record(value, nostd::span>{ + attributes.begin(), attributes.end()}); + } +#endif + + /** + * Records a value. + * + * @param value The measurement value. MUST be non-negative. + * @param context The explicit context to associate with this measurement. + */ virtual void Record(T value, const context::Context &context) noexcept = 0; /** * Records a value with a set of attributes. * * @param value The measurement value. MUST be non-negative. - * @param attributes A set of attributes to associate with the count. + * @param attributes A set of attributes to associate with the value.. + * @param context The explicit context to associate with this measurement. */ virtual void Record(T value, const common::KeyValueIterable &attributes, @@ -137,22 +181,35 @@ class UpDownCounter : public SynchronousInstrument { public: /** - * Adds a value. + * Record a value. * - * @param value The amount of the measurement. + * @param value The increment amount. May be positive, negative or zero. */ virtual void Add(T value) noexcept = 0; + /** + * Record a value. + * + * @param value The increment amount. May be positive, negative or zero. + * @param context The explicit context to associate with this measurement. + */ virtual void Add(T value, const context::Context &context) noexcept = 0; /** - * Add a value with a set of attributes. + * Record a value with a set of attributes. * * @param value The increment amount. May be positive, negative or zero. * @param attributes A set of attributes to associate with the count. */ virtual void Add(T value, const common::KeyValueIterable &attributes) noexcept = 0; + /** + * Record a value with a set of attributes. + * + * @param value The increment amount. May be positive, negative or zero. + * @param attributes A set of attributes to associate with the count. + * @param context The explicit context to associate with this measurement. + */ virtual void Add(T value, const common::KeyValueIterable &attributes, const context::Context &context) noexcept = 0; @@ -161,8 +218,7 @@ class UpDownCounter : public SynchronousInstrument nostd::enable_if_t::value> * = nullptr> void Add(T value, const U &attributes) noexcept { - auto context = context::Context{}; - this->Add(value, common::KeyValueIterableView{attributes}, context); + this->Add(value, common::KeyValueIterableView{attributes}); } template > attributes) noexcept { - auto context = context::Context{}; - this->Add(value, - nostd::span>{ - attributes.begin(), attributes.end()}, - context); + this->Add(value, nostd::span>{ + attributes.begin(), attributes.end()}); } void Add(T value, diff --git a/sdk/include/opentelemetry/sdk/metrics/sync_instruments.h b/sdk/include/opentelemetry/sdk/metrics/sync_instruments.h index 825547a846..f08b629fe2 100644 --- a/sdk/include/opentelemetry/sdk/metrics/sync_instruments.h +++ b/sdk/include/opentelemetry/sdk/metrics/sync_instruments.h @@ -33,61 +33,22 @@ class Synchronous std::unique_ptr storage_; }; -template -class LongCounter : public Synchronous, public opentelemetry::metrics::Counter +class LongCounter : public Synchronous, public opentelemetry::metrics::Counter { public: LongCounter(InstrumentDescriptor instrument_descriptor, - std::unique_ptr storage) - : Synchronous(instrument_descriptor, std::move(storage)) - { - if (!storage_) - { - OTEL_INTERNAL_LOG_ERROR("[LongCounter::LongCounter] - Error during constructing LongCounter." - << "The metric storage is invalid" - << "No value will be added"); - } - } - - void Add(T value, const opentelemetry::common::KeyValueIterable &attributes) noexcept override - { - if (!storage_) - { - return; - } - auto context = opentelemetry::context::Context{}; - return storage_->RecordLong(value, attributes, context); - } - - void Add(T value, + std::unique_ptr storage); + + void Add(uint64_t value, + const opentelemetry::common::KeyValueIterable &attributes) noexcept override; + + void Add(uint64_t value, const opentelemetry::common::KeyValueIterable &attributes, - const opentelemetry::context::Context &context) noexcept override - { - if (!storage_) - { - return; - } - return storage_->RecordLong(value, attributes, context); - } - - void Add(T value) noexcept override - { - auto context = opentelemetry::context::Context{}; - if (!storage_) - { - return; - } - return storage_->RecordLong(value, context); - } - - void Add(T value, const opentelemetry::context::Context &context) noexcept override - { - if (!storage_) - { - return; - } - return storage_->RecordLong(value, context); - } + const opentelemetry::context::Context &context) noexcept override; + + void Add(uint64_t value) noexcept override; + + void Add(uint64_t value, const opentelemetry::context::Context &context) noexcept override; }; class DoubleCounter : public Synchronous, public opentelemetry::metrics::Counter @@ -139,48 +100,24 @@ class DoubleUpDownCounter : public Synchronous, public opentelemetry::metrics::U void Add(double value, const opentelemetry::context::Context &context) noexcept override; }; -template -class LongHistogram : public Synchronous, public opentelemetry::metrics::Histogram +class LongHistogram : public Synchronous, public opentelemetry::metrics::Histogram { public: LongHistogram(InstrumentDescriptor instrument_descriptor, - std::unique_ptr storage) - : Synchronous(instrument_descriptor, std::move(storage)) - { - if (!storage_) - { - OTEL_INTERNAL_LOG_ERROR( - "[LongHistogram::LongHistogram] - Error during constructing LongHistogram." - << "The metric storage is invalid" - << "No value will be added"); - } - } - - void Record(T value, + std::unique_ptr storage); + +#if OPENTELEMETRY_ABI_VERSION_NO >= 2 + void Record(uint64_t value, + const opentelemetry::common::KeyValueIterable &attributes) noexcept override; + + void Record(uint64_t value) noexcept override; +#endif + + void Record(uint64_t value, const opentelemetry::common::KeyValueIterable &attributes, - const opentelemetry::context::Context &context) noexcept override - { - if (value < 0) - { - OTEL_INTERNAL_LOG_WARN( - "[LongHistogram::Record(value, attributes)] negative value provided to histogram Name:" - << instrument_descriptor_.name_ << " Value:" << value); - return; - } - return storage_->RecordLong(value, attributes, context); - } - - void Record(T value, const opentelemetry::context::Context &context) noexcept override - { - if (value < 0) - { - OTEL_INTERNAL_LOG_WARN( - "[LongHistogram::Record(value)] negative value provided to histogram Name:" - << instrument_descriptor_.name_ << " Value:" << value); - return; - } - return storage_->RecordLong(value, context); - } + const opentelemetry::context::Context &context) noexcept override; + + void Record(uint64_t value, const opentelemetry::context::Context &context) noexcept override; }; class DoubleHistogram : public Synchronous, public opentelemetry::metrics::Histogram @@ -189,6 +126,13 @@ class DoubleHistogram : public Synchronous, public opentelemetry::metrics::Histo DoubleHistogram(InstrumentDescriptor instrument_descriptor, std::unique_ptr storage); +#if OPENTELEMETRY_ABI_VERSION_NO >= 2 + void Record(double value, + const opentelemetry::common::KeyValueIterable &attributes) noexcept override; + + void Record(double value) noexcept override; +#endif + void Record(double value, const opentelemetry::common::KeyValueIterable &attributes, const opentelemetry::context::Context &context) noexcept override; diff --git a/sdk/src/metrics/meter.cc b/sdk/src/metrics/meter.cc index 4f7c4c1207..0ae3776111 100644 --- a/sdk/src/metrics/meter.cc +++ b/sdk/src/metrics/meter.cc @@ -52,7 +52,7 @@ nostd::unique_ptr> Meter::CreateUInt64Counter( std::string{unit.data(), unit.size()}, InstrumentType::kCounter, InstrumentValueType::kLong}; auto storage = RegisterSyncMetricStorage(instrument_descriptor); return nostd::unique_ptr>( - new LongCounter(instrument_descriptor, std::move(storage))); + new LongCounter(instrument_descriptor, std::move(storage))); } nostd::unique_ptr> Meter::CreateDoubleCounter( @@ -138,7 +138,7 @@ nostd::unique_ptr> Meter::CreateUInt64Histogram( InstrumentValueType::kLong}; auto storage = RegisterSyncMetricStorage(instrument_descriptor); return nostd::unique_ptr>{ - new LongHistogram(instrument_descriptor, std::move(storage))}; + new LongHistogram(instrument_descriptor, std::move(storage))}; } nostd::unique_ptr> Meter::CreateDoubleHistogram( diff --git a/sdk/src/metrics/sync_instruments.cc b/sdk/src/metrics/sync_instruments.cc index 6fe72b55bf..bdeff150ae 100644 --- a/sdk/src/metrics/sync_instruments.cc +++ b/sdk/src/metrics/sync_instruments.cc @@ -10,27 +10,93 @@ namespace sdk { namespace metrics { +LongCounter::LongCounter(InstrumentDescriptor instrument_descriptor, + std::unique_ptr storage) + : Synchronous(instrument_descriptor, std::move(storage)) +{ + if (!storage_) + { + OTEL_INTERNAL_LOG_ERROR("[LongCounter::LongCounter] - Error constructing LongCounter." + << "The metric storage is invalid for " << instrument_descriptor.name_); + } +} + +void LongCounter::Add(uint64_t value, + const opentelemetry::common::KeyValueIterable &attributes) noexcept +{ + auto context = opentelemetry::context::Context{}; + if (!storage_) + { + OTEL_INTERNAL_LOG_WARN("[LongCounter::Add(V,A)] Value not recorded - invalid storage for: " + << instrument_descriptor_.name_); + return; + } + return storage_->RecordLong(value, attributes, context); +} + +void LongCounter::Add(uint64_t value, + const opentelemetry::common::KeyValueIterable &attributes, + const opentelemetry::context::Context &context) noexcept +{ + if (!storage_) + { + OTEL_INTERNAL_LOG_WARN("[LongCounter::Add(V,A,C)] Value not recorded - invalid storage for: " + << instrument_descriptor_.name_); + return; + } + return storage_->RecordLong(value, attributes, context); +} + +void LongCounter::Add(uint64_t value) noexcept +{ + auto context = opentelemetry::context::Context{}; + if (!storage_) + { + OTEL_INTERNAL_LOG_WARN("[LongCounter::Add(V)] Value not recorded - invalid storage for: " + << instrument_descriptor_.name_); + return; + } + return storage_->RecordLong(value, context); +} + +void LongCounter::Add(uint64_t value, const opentelemetry::context::Context &context) noexcept +{ + if (!storage_) + { + OTEL_INTERNAL_LOG_WARN("[LongCounter::Add(V,C)] Value not recorded - invalid storage for: " + << instrument_descriptor_.name_); + return; + } + return storage_->RecordLong(value, context); +} + DoubleCounter::DoubleCounter(InstrumentDescriptor instrument_descriptor, std::unique_ptr storage) : Synchronous(instrument_descriptor, std::move(storage)) { if (!storage_) { - OTEL_INTERNAL_LOG_ERROR( - "[DoubleCounter::DoubleCounter] - Error during constructing DoubleCounter." - << "The metric storage is invalid" - << "No value will be added"); + OTEL_INTERNAL_LOG_ERROR("[DoubleCounter::DoubleCounter] - Error constructing DoubleCounter." + << "The metric storage is invalid for " << instrument_descriptor.name_); } } void DoubleCounter::Add(double value, const opentelemetry::common::KeyValueIterable &attributes) noexcept { - auto context = opentelemetry::context::Context{}; + if (value < 0) + { + OTEL_INTERNAL_LOG_WARN("[DoubleCounter::Add(V,A)] Value not recorded - negative value for: " + << instrument_descriptor_.name_); + return; + } if (!storage_) { + OTEL_INTERNAL_LOG_WARN("[DoubleCounter::Add(V,A)] Value not recorded - invalid storage for: " + << instrument_descriptor_.name_); return; } + auto context = opentelemetry::context::Context{}; return storage_->RecordDouble(value, attributes, context); } @@ -38,8 +104,16 @@ void DoubleCounter::Add(double value, const opentelemetry::common::KeyValueIterable &attributes, const opentelemetry::context::Context &context) noexcept { + if (value < 0) + { + OTEL_INTERNAL_LOG_WARN("[DoubleCounter::Add(V,A,C)] Value not recorded - negative value for: " + << instrument_descriptor_.name_); + return; + } if (!storage_) { + OTEL_INTERNAL_LOG_WARN("[DoubleCounter::Add(V,A,C)] Value not recorded - invalid storage for: " + << instrument_descriptor_.name_); return; } return storage_->RecordDouble(value, attributes, context); @@ -47,18 +121,34 @@ void DoubleCounter::Add(double value, void DoubleCounter::Add(double value) noexcept { - auto context = opentelemetry::context::Context{}; + if (value < 0) + { + OTEL_INTERNAL_LOG_WARN("[DoubleCounter::Add(V)] Value not recorded - negative value for: " + << instrument_descriptor_.name_); + return; + } if (!storage_) { + OTEL_INTERNAL_LOG_WARN("[DoubleCounter::Add(V)] Value not recorded - invalid storage for: " + << instrument_descriptor_.name_); return; } + auto context = opentelemetry::context::Context{}; return storage_->RecordDouble(value, context); } void DoubleCounter::Add(double value, const opentelemetry::context::Context &context) noexcept { + if (value < 0) + { + OTEL_INTERNAL_LOG_WARN("[DoubleCounter::Add(V)] Value not recorded - negative value for: " + << instrument_descriptor_.name_); + return; + } if (!storage_) { + OTEL_INTERNAL_LOG_WARN("[DoubleCounter::Add(V,C)] Value not recorded - invalid storage for: " + << instrument_descriptor_.name_); return; } return storage_->RecordDouble(value, context); @@ -71,9 +161,8 @@ LongUpDownCounter::LongUpDownCounter(InstrumentDescriptor instrument_descriptor, if (!storage_) { OTEL_INTERNAL_LOG_ERROR( - "[LongUpDownCounter::LongUpDownCounter] - Error during constructing LongUpDownCounter." - << "The metric storage is invalid" - << "No value will be added"); + "[LongUpDownCounter::LongUpDownCounter] - Error constructing LongUpDownCounter." + << "The metric storage is invalid for " << instrument_descriptor.name_); } } @@ -83,6 +172,9 @@ void LongUpDownCounter::Add(int64_t value, auto context = opentelemetry::context::Context{}; if (!storage_) { + OTEL_INTERNAL_LOG_WARN( + "[LongUpDownCounter::Add(V,A)] Value not recorded - invalid storage for: " + << instrument_descriptor_.name_); return; } return storage_->RecordLong(value, attributes, context); @@ -94,6 +186,9 @@ void LongUpDownCounter::Add(int64_t value, { if (!storage_) { + OTEL_INTERNAL_LOG_WARN( + "[LongUpDownCounter::Add(V,A,C)] Value not recorded - invalid storage for: " + << instrument_descriptor_.name_); return; } return storage_->RecordLong(value, attributes, context); @@ -104,6 +199,8 @@ void LongUpDownCounter::Add(int64_t value) noexcept auto context = opentelemetry::context::Context{}; if (!storage_) { + OTEL_INTERNAL_LOG_WARN("[LongUpDownCounter::Add(V)] Value not recorded - invalid storage for: " + << instrument_descriptor_.name_); return; } return storage_->RecordLong(value, context); @@ -113,6 +210,9 @@ void LongUpDownCounter::Add(int64_t value, const opentelemetry::context::Context { if (!storage_) { + OTEL_INTERNAL_LOG_WARN( + "[LongUpDownCounter::Add(V,C)] Value not recorded - invalid storage for: " + << instrument_descriptor_.name_); return; } return storage_->RecordLong(value, context); @@ -125,16 +225,20 @@ DoubleUpDownCounter::DoubleUpDownCounter(InstrumentDescriptor instrument_descrip if (!storage_) { OTEL_INTERNAL_LOG_ERROR( - "[DoubleUpDownCounter::DoubleUpDownCounter] - Error during constructing " - "DoubleUpDownCounter." - << "The metric storage is invalid" - << "No value will be added"); + "[DoubleUpDownCounter::DoubleUpDownCounter] - Error constructing DoubleUpDownCounter." + << "The metric storage is invalid for " << instrument_descriptor.name_); } } void DoubleUpDownCounter::Add(double value, const opentelemetry::common::KeyValueIterable &attributes) noexcept { + if (!storage_) + { + OTEL_INTERNAL_LOG_WARN( + "[DoubleUpDownCounter::Add(V,A)] Value not recorded - invalid storage for: " + << instrument_descriptor_.name_); + } auto context = opentelemetry::context::Context{}; return storage_->RecordDouble(value, attributes, context); } @@ -145,6 +249,9 @@ void DoubleUpDownCounter::Add(double value, { if (!storage_) { + OTEL_INTERNAL_LOG_WARN( + "[DoubleUpDownCounter::Add(V,A,C)] Value not recorded - invalid storage for: " + << instrument_descriptor_.name_); return; } return storage_->RecordDouble(value, attributes, context); @@ -154,6 +261,9 @@ void DoubleUpDownCounter::Add(double value) noexcept { if (!storage_) { + OTEL_INTERNAL_LOG_WARN( + "[DoubleUpDownCounter::Add(V)] Value not recorded - invalid storage for: " + << instrument_descriptor_.name_); return; } auto context = opentelemetry::context::Context{}; @@ -164,11 +274,77 @@ void DoubleUpDownCounter::Add(double value, const opentelemetry::context::Contex { if (!storage_) { + OTEL_INTERNAL_LOG_WARN( + "[DoubleUpDownCounter::Add(V,C)] Value not recorded - invalid storage for: " + << instrument_descriptor_.name_); return; } return storage_->RecordDouble(value, context); } +LongHistogram::LongHistogram(InstrumentDescriptor instrument_descriptor, + std::unique_ptr storage) + : Synchronous(instrument_descriptor, std::move(storage)) +{ + if (!storage_) + { + OTEL_INTERNAL_LOG_ERROR("[LongHistogram::LongHistogram] - Error constructing LongHistogram." + << "The metric storage is invalid for " << instrument_descriptor.name_); + } +} + +void LongHistogram::Record(uint64_t value, + const opentelemetry::common::KeyValueIterable &attributes, + const opentelemetry::context::Context &context) noexcept +{ + if (!storage_) + { + OTEL_INTERNAL_LOG_WARN( + "[LongHistogram::Record(V,A,C)] Value not recorded - invalid storage for: " + << instrument_descriptor_.name_); + return; + } + return storage_->RecordLong(value, attributes, context); +} + +void LongHistogram::Record(uint64_t value, const opentelemetry::context::Context &context) noexcept +{ + if (!storage_) + { + OTEL_INTERNAL_LOG_WARN("[LongHistogram::Record(V,C)] Value not recorded - invalid storage for: " + << instrument_descriptor_.name_); + return; + } + return storage_->RecordLong(value, context); +} + +#if OPENTELEMETRY_ABI_VERSION_NO >= 2 +void LongHistogram::Record(uint64_t value, + const opentelemetry::common::KeyValueIterable &attributes) noexcept +{ + if (!storage_) + { + OTEL_INTERNAL_LOG_WARN("[LongHistogram::Record(V,A)] Value not recorded - invalid storage for: " + << instrument_descriptor_.name_); + return; + } + auto context = opentelemetry::context::Context{}; + return storage_->RecordLong(value, attributes, context); +} + +void LongHistogram::Record(uint64_t value) noexcept +{ + if (!storage_) + { + OTEL_INTERNAL_LOG_WARN("[LongHistogram::Record(V)] Value not recorded - invalid storage for: " + << instrument_descriptor_.name_); + return; + } + auto context = opentelemetry::context::Context{}; + return storage_->RecordLong(value, context); +} +#endif + DoubleHistogram::DoubleHistogram(InstrumentDescriptor instrument_descriptor, std::unique_ptr storage) : Synchronous(instrument_descriptor, std::move(storage)) @@ -176,9 +352,8 @@ DoubleHistogram::DoubleHistogram(InstrumentDescriptor instrument_descriptor, if (!storage_) { OTEL_INTERNAL_LOG_ERROR( - "[DoubleHistogram::DoubleHistogram] - Error during constructing DoubleHistogram." - << "The metric storage is invalid" - << "No value will be added"); + "[DoubleHistogram::DoubleHistogram] - Error constructing DoubleHistogram." + << "The metric storage is invalid for " << instrument_descriptor.name_); } } @@ -186,15 +361,17 @@ void DoubleHistogram::Record(double value, const opentelemetry::common::KeyValueIterable &attributes, const opentelemetry::context::Context &context) noexcept { - if (!storage_) + if (value < 0) { + OTEL_INTERNAL_LOG_WARN( + "[DoubleHistogram::Record(V,A,C)] Value not recorded - negative value for: " + << instrument_descriptor_.name_); return; } - if (value < 0 || std::isnan(value) || std::isinf(value)) + if (!storage_) { OTEL_INTERNAL_LOG_WARN( - "[DoubleHistogram::Record(value, attributes)] negative/nan/infinite value provided to " - "histogram Name:" + "[DoubleHistogram::Record(V,A,C)] Value not recorded - invalid storage for: " << instrument_descriptor_.name_); return; } @@ -203,19 +380,63 @@ void DoubleHistogram::Record(double value, void DoubleHistogram::Record(double value, const opentelemetry::context::Context &context) noexcept { + if (value < 0) + { + OTEL_INTERNAL_LOG_WARN( + "[DoubleHistogram::Record(V,C)] Value not recorded - negative value for: " + << instrument_descriptor_.name_); + return; + } if (!storage_) { + OTEL_INTERNAL_LOG_WARN( + "[DoubleHistogram::Record(V,C)] Value not recorded - invalid storage for: " + << instrument_descriptor_.name_); + return; + } + return storage_->RecordDouble(value, context); +} + +#if OPENTELEMETRY_ABI_VERSION_NO >= 2 +void DoubleHistogram::Record(double value, + const opentelemetry::common::KeyValueIterable &attributes) noexcept +{ + if (value < 0) + { + OTEL_INTERNAL_LOG_WARN( + "[DoubleHistogram::Record(V,A)] Value not recorded - negative value for: " + << instrument_descriptor_.name_); return; } - if (value < 0 || std::isnan(value) || std::isinf(value)) + if (!storage_) { OTEL_INTERNAL_LOG_WARN( - "[DoubleHistogram::Record(value)] negative/nan/infinite value provided to histogram Name:" + "[DoubleHistogram::Record(V,A)] Value not recorded - invalid storage for: " << instrument_descriptor_.name_); return; } + auto context = opentelemetry::context::Context{}; + return storage_->RecordDouble(value, attributes, context); +} + +void DoubleHistogram::Record(double value) noexcept +{ + if (value < 0) + { + OTEL_INTERNAL_LOG_WARN("[DoubleHistogram::Record(V)] Value not recorded - negative value for: " + << instrument_descriptor_.name_); + return; + } + if (!storage_) + { + OTEL_INTERNAL_LOG_WARN("[DoubleHistogram::Record(V)] Value not recorded - invalid storage for: " + << instrument_descriptor_.name_); + return; + } + auto context = opentelemetry::context::Context{}; return storage_->RecordDouble(value, context); } +#endif } // namespace metrics } // namespace sdk diff --git a/sdk/test/metrics/sync_instruments_test.cc b/sdk/test/metrics/sync_instruments_test.cc index a1ff2325e2..723d29f20e 100644 --- a/sdk/test/metrics/sync_instruments_test.cc +++ b/sdk/test/metrics/sync_instruments_test.cc @@ -24,7 +24,7 @@ TEST(SyncInstruments, LongCounter) InstrumentDescriptor instrument_descriptor = { "long_counter", "description", "1", InstrumentType::kCounter, InstrumentValueType::kLong}; std::unique_ptr metric_storage(new SyncMultiMetricStorage()); - LongCounter counter(instrument_descriptor, std::move(metric_storage)); + LongCounter counter(instrument_descriptor, std::move(metric_storage)); counter.Add(10); counter.Add(10, opentelemetry::context::Context{}); @@ -71,6 +71,18 @@ TEST(SyncInstruments, LongUpDownCounter) counter.Add(10, opentelemetry::common::KeyValueIterableView({})); counter.Add(10, opentelemetry::common::KeyValueIterableView({}), opentelemetry::context::Context{}); + + // negative values + counter.Add(-10); + counter.Add(-10, opentelemetry::context::Context{}); + + counter.Add(-10, + opentelemetry::common::KeyValueIterableView({{"abc", "123"}, {"xyz", "456"}})); + counter.Add(-10, opentelemetry::common::KeyValueIterableView({{"abc", "123"}, {"xyz", "456"}}), + opentelemetry::context::Context{}); + counter.Add(-10, opentelemetry::common::KeyValueIterableView({})); + counter.Add(-10, opentelemetry::common::KeyValueIterableView({}), + opentelemetry::context::Context{}); } TEST(SyncInstruments, DoubleUpDownCounter) @@ -98,9 +110,8 @@ TEST(SyncInstruments, LongHistogram) InstrumentDescriptor instrument_descriptor = { "long_histogram", "description", "1", InstrumentType::kHistogram, InstrumentValueType::kLong}; std::unique_ptr metric_storage(new SyncMultiMetricStorage()); - LongHistogram histogram(instrument_descriptor, std::move(metric_storage)); + LongHistogram histogram(instrument_descriptor, std::move(metric_storage)); histogram.Record(10, opentelemetry::context::Context{}); - histogram.Record(-10, opentelemetry::context::Context{}); // This is ignored histogram.Record(10, opentelemetry::common::KeyValueIterableView({{"abc", "123"}, {"xyz", "456"}}), From 27a58cdc259b0d5d4c0ed8732eaf7949c21559f0 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Fri, 1 Dec 2023 00:25:25 -0800 Subject: [PATCH 18/31] [BUILD] Fix references to trace namespace to be fully qualified (#2422) --- .../opentelemetry/sdk/metrics/data/exemplar_data.h | 8 ++++---- .../opentelemetry/sdk/metrics/exemplar/reservoir_cell.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/sdk/include/opentelemetry/sdk/metrics/data/exemplar_data.h b/sdk/include/opentelemetry/sdk/metrics/data/exemplar_data.h index 0420b50aab..efad19b098 100644 --- a/sdk/include/opentelemetry/sdk/metrics/data/exemplar_data.h +++ b/sdk/include/opentelemetry/sdk/metrics/data/exemplar_data.h @@ -26,7 +26,7 @@ using MetricAttributes = opentelemetry::sdk::common::OrderedAttributeMap; class ExemplarData { public: - static ExemplarData Create(std::shared_ptr context, + static ExemplarData Create(std::shared_ptr context, const opentelemetry::common::SystemTimestamp ×tamp, const PointDataAttributes &point_data_attr) { @@ -47,7 +47,7 @@ class ExemplarData * Returns the SpanContext associated with this exemplar. If the exemplar was not recorded * inside a sampled trace, the Context will be invalid. */ - const trace::SpanContext &GetSpanContext() const noexcept { return context_; } + const opentelemetry::trace::SpanContext &GetSpanContext() const noexcept { return context_; } static PointType CreateSumPointData(ValueType value) { @@ -68,13 +68,13 @@ class ExemplarData static PointType CreateDropPointData() { return DropPointData{}; } private: - ExemplarData(std::shared_ptr context, + ExemplarData(std::shared_ptr context, opentelemetry::common::SystemTimestamp timestamp, const PointDataAttributes &point_data_attr) : context_(*context.get()), timestamp_(timestamp), point_data_attr_(point_data_attr) {} - trace::SpanContext context_; + opentelemetry::trace::SpanContext context_; opentelemetry::common::SystemTimestamp timestamp_; PointDataAttributes point_data_attr_; }; diff --git a/sdk/include/opentelemetry/sdk/metrics/exemplar/reservoir_cell.h b/sdk/include/opentelemetry/sdk/metrics/exemplar/reservoir_cell.h index 6074393d2d..772c1cc1f1 100644 --- a/sdk/include/opentelemetry/sdk/metrics/exemplar/reservoir_cell.h +++ b/sdk/include/opentelemetry/sdk/metrics/exemplar/reservoir_cell.h @@ -137,13 +137,13 @@ class ReservoirCell auto current_ctx = span->GetContext(); if (current_ctx.IsValid()) { - context_.reset(new trace::SpanContext{current_ctx}); + context_.reset(new opentelemetry::trace::SpanContext{current_ctx}); } } } // Cell stores either long or double values, but must not store both - std::shared_ptr context_; + std::shared_ptr context_; nostd::variant value_; opentelemetry::common::SystemTimestamp record_time_; MetricAttributes attributes_; From 25343e6e3ba5e85645684bc36d18001eddfc9700 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Fri, 1 Dec 2023 01:08:25 -0800 Subject: [PATCH 19/31] Bump third_party/googletest to same version as bazel (#2421) --- third_party/googletest | 2 +- third_party_release | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/third_party/googletest b/third_party/googletest index 58d77fa807..b796f7d446 160000 --- a/third_party/googletest +++ b/third_party/googletest @@ -1 +1 @@ -Subproject commit 58d77fa8070e8cec2dc1ed015d66b454c8d78850 +Subproject commit b796f7d44681514f58a683a3a71ff17c94edb0c1 diff --git a/third_party_release b/third_party_release index 9fae12fc31..817d9b728e 100644 --- a/third_party_release +++ b/third_party_release @@ -16,7 +16,7 @@ gRPC=v1.49.2 abseil=20220623.1 benchmark=v1.7.1 -googletest=release-1.13.0 +googletest=1.13.0 ms-gsl=v3.1.0-67-g6f45293 nlohmann-json=v3.11.2 opentelemetry-proto=v1.0.0 From abad83d03ea5d936be166faf069d1d91002236e7 Mon Sep 17 00:00:00 2001 From: Tom Tan Date: Sat, 2 Dec 2023 03:46:18 -0800 Subject: [PATCH 20/31] [BUILD] Remove defining NOMINMAX from api (#2420) --- api/CMakeLists.txt | 1 - .../opentelemetry/common/spin_lock_mutex.h | 3 --- api/include/opentelemetry/common/timestamp.h | 6 +++--- .../plugin/detail/dynamic_load_windows.h | 3 --- .../exporters/ostream/log_record_exporter.h | 4 ++-- .../exporters/ostream/span_exporter.h | 4 ++-- .../exporters/zipkin/zipkin_exporter.h | 4 ++-- sdk/include/opentelemetry/sdk/logs/exporter.h | 2 +- .../opentelemetry/sdk/logs/logger_context.h | 2 +- sdk/include/opentelemetry/sdk/logs/processor.h | 4 ++-- .../sdk/logs/simple_log_record_processor.h | 4 ++-- .../metrics/aggregation/histogram_aggregation.h | 4 ++-- .../opentelemetry/sdk/metrics/metric_reader.h | 4 ++-- .../sdk/metrics/state/metric_collector.h | 4 ++-- sdk/include/opentelemetry/sdk/trace/exporter.h | 2 +- sdk/src/logs/batch_log_record_processor.cc | 2 +- .../metrics/aggregation/histogram_aggregation.cc | 16 ++++++++-------- .../export/periodic_exporting_metric_reader.cc | 2 +- sdk/src/metrics/meter_context.cc | 4 ++-- sdk/src/trace/batch_span_processor.cc | 2 +- 20 files changed, 35 insertions(+), 42 deletions(-) diff --git a/api/CMakeLists.txt b/api/CMakeLists.txt index ecbb377725..fc26d9083f 100644 --- a/api/CMakeLists.txt +++ b/api/CMakeLists.txt @@ -104,7 +104,6 @@ if(WITH_NO_GETENV) endif() if(WIN32) - target_compile_definitions(opentelemetry_api INTERFACE NOMINMAX) if(WITH_ETW) target_compile_definitions(opentelemetry_api INTERFACE HAVE_MSGPACK) endif() diff --git a/api/include/opentelemetry/common/spin_lock_mutex.h b/api/include/opentelemetry/common/spin_lock_mutex.h index 1877c8eb40..ac52f700bc 100644 --- a/api/include/opentelemetry/common/spin_lock_mutex.h +++ b/api/include/opentelemetry/common/spin_lock_mutex.h @@ -10,9 +10,6 @@ #include "opentelemetry/version.h" #if defined(_MSC_VER) -# ifndef NOMINMAX -# define NOMINMAX -# endif # define _WINSOCKAPI_ // stops including winsock.h # include #elif defined(__i386__) || defined(__x86_64__) diff --git a/api/include/opentelemetry/common/timestamp.h b/api/include/opentelemetry/common/timestamp.h index 14aa457b5b..f7c79b8b57 100644 --- a/api/include/opentelemetry/common/timestamp.h +++ b/api/include/opentelemetry/common/timestamp.h @@ -178,7 +178,7 @@ class DurationUtil std::chrono::duration indefinite_value) noexcept { // Do not call now() when this duration is max value, now() may have a expensive cost. - if (timeout == std::chrono::duration::max()) + if (timeout == (std::chrono::duration::max)()) { return indefinite_value; } @@ -186,13 +186,13 @@ class DurationUtil // std::future::wait_for, std::this_thread::sleep_for, and std::condition_variable::wait_for // may use steady_clock or system_clock.We need make sure now() + timeout do not overflow. auto max_timeout = std::chrono::duration_cast>( - std::chrono::steady_clock::time_point::max() - std::chrono::steady_clock::now()); + (std::chrono::steady_clock::time_point::max)() - std::chrono::steady_clock::now()); if (timeout >= max_timeout) { return indefinite_value; } max_timeout = std::chrono::duration_cast>( - std::chrono::system_clock::time_point::max() - std::chrono::system_clock::now()); + (std::chrono::system_clock::time_point::max)() - std::chrono::system_clock::now()); if (timeout >= max_timeout) { return indefinite_value; diff --git a/api/include/opentelemetry/plugin/detail/dynamic_load_windows.h b/api/include/opentelemetry/plugin/detail/dynamic_load_windows.h index 3f5e05f198..5ed2833756 100644 --- a/api/include/opentelemetry/plugin/detail/dynamic_load_windows.h +++ b/api/include/opentelemetry/plugin/detail/dynamic_load_windows.h @@ -12,9 +12,6 @@ #include "opentelemetry/plugin/hook.h" #include "opentelemetry/version.h" -#ifndef NOMINMAX -# define NOMINMAX -#endif #include #include diff --git a/exporters/ostream/include/opentelemetry/exporters/ostream/log_record_exporter.h b/exporters/ostream/include/opentelemetry/exporters/ostream/log_record_exporter.h index 7b196ec9e8..a2897a5f26 100644 --- a/exporters/ostream/include/opentelemetry/exporters/ostream/log_record_exporter.h +++ b/exporters/ostream/include/opentelemetry/exporters/ostream/log_record_exporter.h @@ -47,13 +47,13 @@ class OStreamLogRecordExporter final : public opentelemetry::sdk::logs::LogRecor * @return return true when all data are exported, and false when timeout */ bool ForceFlush( - std::chrono::microseconds timeout = std::chrono::microseconds::max()) noexcept override; + std::chrono::microseconds timeout = (std::chrono::microseconds::max)()) noexcept override; /** * Marks the OStream Log Exporter as shut down. */ bool Shutdown( - std::chrono::microseconds timeout = std::chrono::microseconds::max()) noexcept override; + std::chrono::microseconds timeout = (std::chrono::microseconds::max)()) noexcept override; private: // The OStream to send the logs to diff --git a/exporters/ostream/include/opentelemetry/exporters/ostream/span_exporter.h b/exporters/ostream/include/opentelemetry/exporters/ostream/span_exporter.h index 05c8a89982..03c95c23f9 100644 --- a/exporters/ostream/include/opentelemetry/exporters/ostream/span_exporter.h +++ b/exporters/ostream/include/opentelemetry/exporters/ostream/span_exporter.h @@ -44,10 +44,10 @@ class OStreamSpanExporter final : public opentelemetry::sdk::trace::SpanExporter * @return return true when all data are exported, and false when timeout */ bool ForceFlush( - std::chrono::microseconds timeout = std::chrono::microseconds::max()) noexcept override; + std::chrono::microseconds timeout = (std::chrono::microseconds::max)()) noexcept override; bool Shutdown( - std::chrono::microseconds timeout = std::chrono::microseconds::max()) noexcept override; + std::chrono::microseconds timeout = (std::chrono::microseconds::max)()) noexcept override; private: std::ostream &sout_; diff --git a/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h b/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h index 2bf12b3a35..4de6513bfb 100644 --- a/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h +++ b/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h @@ -55,14 +55,14 @@ class ZipkinExporter final : public opentelemetry::sdk::trace::SpanExporter * @return return true when all data are exported, and false when timeout */ bool ForceFlush( - std::chrono::microseconds timeout = std::chrono::microseconds::max()) noexcept override; + std::chrono::microseconds timeout = (std::chrono::microseconds::max)()) noexcept override; /** * Shut down the exporter. * @param timeout an optional timeout, default to max. */ bool Shutdown( - std::chrono::microseconds timeout = std::chrono::microseconds::max()) noexcept override; + std::chrono::microseconds timeout = (std::chrono::microseconds::max)()) noexcept override; private: void InitializeLocalEndpoint(); diff --git a/sdk/include/opentelemetry/sdk/logs/exporter.h b/sdk/include/opentelemetry/sdk/logs/exporter.h index bdddc4209c..68c61603fa 100644 --- a/sdk/include/opentelemetry/sdk/logs/exporter.h +++ b/sdk/include/opentelemetry/sdk/logs/exporter.h @@ -62,7 +62,7 @@ class OPENTELEMETRY_EXPORT LogRecordExporter * @return true if the exporter shutdown succeeded, false otherwise */ virtual bool Shutdown( - std::chrono::microseconds timeout = std::chrono::microseconds::max()) noexcept = 0; + std::chrono::microseconds timeout = (std::chrono::microseconds::max)()) noexcept = 0; }; } // namespace logs } // namespace sdk diff --git a/sdk/include/opentelemetry/sdk/logs/logger_context.h b/sdk/include/opentelemetry/sdk/logs/logger_context.h index ee47c56a7f..bab002b231 100644 --- a/sdk/include/opentelemetry/sdk/logs/logger_context.h +++ b/sdk/include/opentelemetry/sdk/logs/logger_context.h @@ -70,7 +70,7 @@ class LoggerContext /** * Shutdown the log processor associated with this tracer provider. */ - bool Shutdown(std::chrono::microseconds timeout = std::chrono::microseconds::max()) noexcept; + bool Shutdown(std::chrono::microseconds timeout = (std::chrono::microseconds::max)()) noexcept; private: // order of declaration is important here - resource object should be destroyed after processor. diff --git a/sdk/include/opentelemetry/sdk/logs/processor.h b/sdk/include/opentelemetry/sdk/logs/processor.h index 79a25ff260..57dbdb2130 100644 --- a/sdk/include/opentelemetry/sdk/logs/processor.h +++ b/sdk/include/opentelemetry/sdk/logs/processor.h @@ -46,7 +46,7 @@ class LogRecordProcessor * @return a result code indicating whether it succeeded, failed or timed out */ virtual bool ForceFlush( - std::chrono::microseconds timeout = std::chrono::microseconds::max()) noexcept = 0; + std::chrono::microseconds timeout = (std::chrono::microseconds::max)()) noexcept = 0; /** * Shuts down the processor and does any cleanup required. @@ -56,7 +56,7 @@ class LogRecordProcessor * @return true if the shutdown succeeded, false otherwise */ virtual bool Shutdown( - std::chrono::microseconds timeout = std::chrono::microseconds::max()) noexcept = 0; + std::chrono::microseconds timeout = (std::chrono::microseconds::max)()) noexcept = 0; }; } // namespace logs } // namespace sdk diff --git a/sdk/include/opentelemetry/sdk/logs/simple_log_record_processor.h b/sdk/include/opentelemetry/sdk/logs/simple_log_record_processor.h index e195f89c10..a65c0eb7a9 100644 --- a/sdk/include/opentelemetry/sdk/logs/simple_log_record_processor.h +++ b/sdk/include/opentelemetry/sdk/logs/simple_log_record_processor.h @@ -39,10 +39,10 @@ class SimpleLogRecordProcessor : public LogRecordProcessor void OnEmit(std::unique_ptr &&record) noexcept override; bool ForceFlush( - std::chrono::microseconds timeout = std::chrono::microseconds::max()) noexcept override; + std::chrono::microseconds timeout = (std::chrono::microseconds::max)()) noexcept override; bool Shutdown( - std::chrono::microseconds timeout = std::chrono::microseconds::max()) noexcept override; + std::chrono::microseconds timeout = (std::chrono::microseconds::max)()) noexcept override; bool IsShutdown() const noexcept; diff --git a/sdk/include/opentelemetry/sdk/metrics/aggregation/histogram_aggregation.h b/sdk/include/opentelemetry/sdk/metrics/aggregation/histogram_aggregation.h index 4419ee81f3..04293e696f 100644 --- a/sdk/include/opentelemetry/sdk/metrics/aggregation/histogram_aggregation.h +++ b/sdk/include/opentelemetry/sdk/metrics/aggregation/histogram_aggregation.h @@ -93,8 +93,8 @@ void HistogramMerge(HistogramPointData ¤t, merge.record_min_max_ = current.record_min_max_ && delta.record_min_max_; if (merge.record_min_max_) { - merge.min_ = std::min(nostd::get(current.min_), nostd::get(delta.min_)); - merge.max_ = std::max(nostd::get(current.max_), nostd::get(delta.max_)); + merge.min_ = (std::min)(nostd::get(current.min_), nostd::get(delta.min_)); + merge.max_ = (std::max)(nostd::get(current.max_), nostd::get(delta.max_)); } } diff --git a/sdk/include/opentelemetry/sdk/metrics/metric_reader.h b/sdk/include/opentelemetry/sdk/metrics/metric_reader.h index 96b34a4427..21249439d6 100644 --- a/sdk/include/opentelemetry/sdk/metrics/metric_reader.h +++ b/sdk/include/opentelemetry/sdk/metrics/metric_reader.h @@ -48,12 +48,12 @@ class MetricReader /** * Shutdown the metric reader. */ - bool Shutdown(std::chrono::microseconds timeout = std::chrono::microseconds::max()) noexcept; + bool Shutdown(std::chrono::microseconds timeout = (std::chrono::microseconds::max)()) noexcept; /** * Force flush the metric read by the reader. */ - bool ForceFlush(std::chrono::microseconds timeout = std::chrono::microseconds::max()) noexcept; + bool ForceFlush(std::chrono::microseconds timeout = (std::chrono::microseconds::max)()) noexcept; /** * Return the status of Metric reader. diff --git a/sdk/include/opentelemetry/sdk/metrics/state/metric_collector.h b/sdk/include/opentelemetry/sdk/metrics/state/metric_collector.h index e94c005ecc..bf0a9ba86b 100644 --- a/sdk/include/opentelemetry/sdk/metrics/state/metric_collector.h +++ b/sdk/include/opentelemetry/sdk/metrics/state/metric_collector.h @@ -53,9 +53,9 @@ class MetricCollector : public MetricProducer, public CollectorHandle */ bool Collect(nostd::function_ref callback) noexcept override; - bool ForceFlush(std::chrono::microseconds timeout = std::chrono::microseconds::max()) noexcept; + bool ForceFlush(std::chrono::microseconds timeout = (std::chrono::microseconds::max)()) noexcept; - bool Shutdown(std::chrono::microseconds timeout = std::chrono::microseconds::max()) noexcept; + bool Shutdown(std::chrono::microseconds timeout = (std::chrono::microseconds::max)()) noexcept; private: MeterContext *meter_context_; diff --git a/sdk/include/opentelemetry/sdk/trace/exporter.h b/sdk/include/opentelemetry/sdk/trace/exporter.h index f9ed068b64..8795b69837 100644 --- a/sdk/include/opentelemetry/sdk/trace/exporter.h +++ b/sdk/include/opentelemetry/sdk/trace/exporter.h @@ -61,7 +61,7 @@ class OPENTELEMETRY_EXPORT SpanExporter * @return return the status of the operation. */ virtual bool Shutdown( - std::chrono::microseconds timeout = std::chrono::microseconds::max()) noexcept = 0; + std::chrono::microseconds timeout = (std::chrono::microseconds::max)()) noexcept = 0; }; } // namespace trace } // namespace sdk diff --git a/sdk/src/logs/batch_log_record_processor.cc b/sdk/src/logs/batch_log_record_processor.cc index 92536d1c00..44e623e4f7 100644 --- a/sdk/src/logs/batch_log_record_processor.cc +++ b/sdk/src/logs/batch_log_record_processor.cc @@ -104,7 +104,7 @@ bool BatchLogRecordProcessor::ForceFlush(std::chrono::microseconds timeout) noex std::chrono::duration_cast(timeout); if (timeout_steady <= std::chrono::steady_clock::duration::zero()) { - timeout_steady = std::chrono::steady_clock::duration::max(); + timeout_steady = (std::chrono::steady_clock::duration::max)(); } bool result = false; diff --git a/sdk/src/metrics/aggregation/histogram_aggregation.cc b/sdk/src/metrics/aggregation/histogram_aggregation.cc index 3213c27f16..1aa02637ea 100644 --- a/sdk/src/metrics/aggregation/histogram_aggregation.cc +++ b/sdk/src/metrics/aggregation/histogram_aggregation.cc @@ -38,8 +38,8 @@ LongHistogramAggregation::LongHistogramAggregation(const AggregationConfig *aggr point_data_.sum_ = (int64_t)0; point_data_.count_ = 0; point_data_.record_min_max_ = record_min_max_; - point_data_.min_ = std::numeric_limits::max(); - point_data_.max_ = std::numeric_limits::min(); + point_data_.min_ = (std::numeric_limits::max)(); + point_data_.max_ = (std::numeric_limits::min)(); } LongHistogramAggregation::LongHistogramAggregation(HistogramPointData &&data) @@ -58,8 +58,8 @@ void LongHistogramAggregation::Aggregate(int64_t value, point_data_.sum_ = nostd::get(point_data_.sum_) + value; if (record_min_max_) { - point_data_.min_ = std::min(nostd::get(point_data_.min_), value); - point_data_.max_ = std::max(nostd::get(point_data_.max_), value); + point_data_.min_ = (std::min)(nostd::get(point_data_.min_), value); + point_data_.max_ = (std::max)(nostd::get(point_data_.max_), value); } size_t index = BucketBinarySearch(value, point_data_.boundaries_); point_data_.counts_[index] += 1; @@ -118,8 +118,8 @@ DoubleHistogramAggregation::DoubleHistogramAggregation(const AggregationConfig * point_data_.sum_ = 0.0; point_data_.count_ = 0; point_data_.record_min_max_ = record_min_max_; - point_data_.min_ = std::numeric_limits::max(); - point_data_.max_ = std::numeric_limits::min(); + point_data_.min_ = (std::numeric_limits::max)(); + point_data_.max_ = (std::numeric_limits::min)(); } DoubleHistogramAggregation::DoubleHistogramAggregation(HistogramPointData &&data) @@ -138,8 +138,8 @@ void DoubleHistogramAggregation::Aggregate(double value, point_data_.sum_ = nostd::get(point_data_.sum_) + value; if (record_min_max_) { - point_data_.min_ = std::min(nostd::get(point_data_.min_), value); - point_data_.max_ = std::max(nostd::get(point_data_.max_), value); + point_data_.min_ = (std::min)(nostd::get(point_data_.min_), value); + point_data_.max_ = (std::max)(nostd::get(point_data_.max_), value); } size_t index = BucketBinarySearch(value, point_data_.boundaries_); point_data_.counts_[index] += 1; diff --git a/sdk/src/metrics/export/periodic_exporting_metric_reader.cc b/sdk/src/metrics/export/periodic_exporting_metric_reader.cc index dfa4a5ee6b..91f604195e 100644 --- a/sdk/src/metrics/export/periodic_exporting_metric_reader.cc +++ b/sdk/src/metrics/export/periodic_exporting_metric_reader.cc @@ -133,7 +133,7 @@ bool PeriodicExportingMetricReader::OnForceFlush(std::chrono::microseconds timeo std::chrono::duration_cast(wait_timeout); if (timeout_steady <= std::chrono::steady_clock::duration::zero()) { - timeout_steady = std::chrono::steady_clock::duration::max(); + timeout_steady = (std::chrono::steady_clock::duration::max)(); } bool result = false; diff --git a/sdk/src/metrics/meter_context.cc b/sdk/src/metrics/meter_context.cc index 7a299bfc63..79f254fa93 100644 --- a/sdk/src/metrics/meter_context.cc +++ b/sdk/src/metrics/meter_context.cc @@ -136,7 +136,7 @@ bool MeterContext::ForceFlush(std::chrono::microseconds timeout) noexcept // Simultaneous flush not allowed. const std::lock_guard locked(forceflush_lock_); // Convert to nanos to prevent overflow - auto timeout_ns = std::chrono::nanoseconds::max(); + auto timeout_ns = (std::chrono::nanoseconds::max)(); if (std::chrono::duration_cast(timeout_ns) > timeout) { timeout_ns = std::chrono::duration_cast(timeout); @@ -144,7 +144,7 @@ bool MeterContext::ForceFlush(std::chrono::microseconds timeout) noexcept auto current_time = std::chrono::system_clock::now(); std::chrono::system_clock::time_point expire_time; - auto overflow_checker = std::chrono::system_clock::time_point::max(); + auto overflow_checker = (std::chrono::system_clock::time_point::max)(); // check if the expected expire time doesn't overflow. if (overflow_checker - current_time > timeout_ns) diff --git a/sdk/src/trace/batch_span_processor.cc b/sdk/src/trace/batch_span_processor.cc index 719a072e64..d5b96f2cc8 100644 --- a/sdk/src/trace/batch_span_processor.cc +++ b/sdk/src/trace/batch_span_processor.cc @@ -102,7 +102,7 @@ bool BatchSpanProcessor::ForceFlush(std::chrono::microseconds timeout) noexcept std::chrono::duration_cast(timeout); if (timeout_steady <= std::chrono::steady_clock::duration::zero()) { - timeout_steady = std::chrono::steady_clock::duration::max(); + timeout_steady = (std::chrono::steady_clock::duration::max)(); } bool result = false; From d1143ab37ef7a7e9bbc4289513dbd21b9fe134d2 Mon Sep 17 00:00:00 2001 From: Thomas-Barbier-1A Date: Tue, 5 Dec 2023 10:54:00 +0100 Subject: [PATCH 21/31] [BUILD] 'uint8_t' not declared in this scope with gcc 13.2.1 (#2423) --- api/include/opentelemetry/trace/propagation/detail/hex.h | 1 + 1 file changed, 1 insertion(+) diff --git a/api/include/opentelemetry/trace/propagation/detail/hex.h b/api/include/opentelemetry/trace/propagation/detail/hex.h index c8bd58f8b8..157f5ec42a 100644 --- a/api/include/opentelemetry/trace/propagation/detail/hex.h +++ b/api/include/opentelemetry/trace/propagation/detail/hex.h @@ -4,6 +4,7 @@ #pragma once #include +#include #include #include "opentelemetry/nostd/string_view.h" From a86f8f094a5d63a214a34bc528dd88b7ccf69cac Mon Sep 17 00:00:00 2001 From: Kyle L Date: Tue, 5 Dec 2023 14:39:39 -0500 Subject: [PATCH 22/31] [BUILD] Improve the handling of OPENTELEMETRY_HAVE_WORKING_REGEX. (#2430) --- api/include/opentelemetry/trace/trace_state.h | 6 ++++-- sdk/include/opentelemetry/sdk/metrics/view/predicate.h | 2 +- sdk/src/metrics/instrument_metadata_validator.cc | 2 +- sdk/test/metrics/histogram_test.cc | 6 +++--- sdk/test/metrics/view_registry_test.cc | 2 +- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/api/include/opentelemetry/trace/trace_state.h b/api/include/opentelemetry/trace/trace_state.h index f424b01997..8a25f4da5c 100644 --- a/api/include/opentelemetry/trace/trace_state.h +++ b/api/include/opentelemetry/trace/trace_state.h @@ -14,7 +14,7 @@ #include "opentelemetry/nostd/unique_ptr.h" #include "opentelemetry/version.h" -#if defined(OPENTELEMETRY_HAVE_WORKING_REGEX) +#if OPENTELEMETRY_HAVE_WORKING_REGEX # include #endif @@ -246,6 +246,7 @@ class OPENTELEMETRY_EXPORT TraceState return str.substr(left, right - left + 1); } +#if OPENTELEMETRY_HAVE_WORKING_REGEX static bool IsValidKeyRegEx(nostd::string_view key) { static std::regex reg_key("^[a-z0-9][a-z0-9*_\\-/]{0,255}$"); @@ -267,7 +268,7 @@ class OPENTELEMETRY_EXPORT TraceState // Need to benchmark without regex, as a string object is created here. return std::regex_match(std::string(value.data(), value.size()), reg_value); } - +#else static bool IsValidKeyNonRegEx(nostd::string_view key) { if (key.empty() || key.size() > kKeyMaxSize || !IsLowerCaseAlphaOrDigit(key[0])) @@ -307,6 +308,7 @@ class OPENTELEMETRY_EXPORT TraceState } return true; } +#endif static bool IsLowerCaseAlphaOrDigit(char c) { return isdigit(c) || islower(c); } diff --git a/sdk/include/opentelemetry/sdk/metrics/view/predicate.h b/sdk/include/opentelemetry/sdk/metrics/view/predicate.h index 5346a753ff..cfa1b16eb3 100644 --- a/sdk/include/opentelemetry/sdk/metrics/view/predicate.h +++ b/sdk/include/opentelemetry/sdk/metrics/view/predicate.h @@ -8,7 +8,7 @@ #include "opentelemetry/nostd/string_view.h" #include "opentelemetry/sdk/common/global_log_handler.h" -#if defined(OPENTELEMETRY_HAVE_WORKING_REGEX) +#if OPENTELEMETRY_HAVE_WORKING_REGEX # include #endif diff --git a/sdk/src/metrics/instrument_metadata_validator.cc b/sdk/src/metrics/instrument_metadata_validator.cc index ff963c3dd1..0b00404447 100644 --- a/sdk/src/metrics/instrument_metadata_validator.cc +++ b/sdk/src/metrics/instrument_metadata_validator.cc @@ -8,7 +8,7 @@ #include #include -#if defined(OPENTELEMETRY_HAVE_WORKING_REGEX) +#if OPENTELEMETRY_HAVE_WORKING_REGEX # include #endif diff --git a/sdk/test/metrics/histogram_test.cc b/sdk/test/metrics/histogram_test.cc index a11a9c1f59..4daceb685b 100644 --- a/sdk/test/metrics/histogram_test.cc +++ b/sdk/test/metrics/histogram_test.cc @@ -13,7 +13,7 @@ #include -#if defined(OPENTELEMETRY_HAVE_WORKING_REGEX) +#if OPENTELEMETRY_HAVE_WORKING_REGEX # include #endif @@ -73,7 +73,7 @@ TEST(Histogram, Double) actual.counts_); } -#if (OPENTELEMETRY_HAVE_WORKING_REGEX) +#if OPENTELEMETRY_HAVE_WORKING_REGEX // FIXME - View Preficate search is only supported through regex TEST(Histogram, DoubleCustomBuckets) { @@ -188,7 +188,7 @@ TEST(Histogram, UInt64) actual.counts_); } -#if (OPENTELEMETRY_HAVE_WORKING_REGEX) +#if OPENTELEMETRY_HAVE_WORKING_REGEX // FIXME - View Preficate search is only supported through regex TEST(Histogram, UInt64CustomBuckets) { diff --git a/sdk/test/metrics/view_registry_test.cc b/sdk/test/metrics/view_registry_test.cc index 49e475a9f1..fb188e7124 100644 --- a/sdk/test/metrics/view_registry_test.cc +++ b/sdk/test/metrics/view_registry_test.cc @@ -8,7 +8,7 @@ #include -#if defined(OPENTELEMETRY_HAVE_WORKING_REGEX) +#if OPENTELEMETRY_HAVE_WORKING_REGEX # include #endif From 39ad238f55adbdd53149f8f10d3c060ce85cb751 Mon Sep 17 00:00:00 2001 From: Marc Alff Date: Tue, 5 Dec 2023 21:22:33 +0100 Subject: [PATCH 23/31] [SEMANTIC CONVENTIONS] Upgrade to semconv version 1.23.1 (#2428) --- CHANGELOG.md | 2 + .../trace/semantic_conventions.h | 2017 +++++++++-------- buildscripts/semantic-convention/generate.sh | 4 +- .../sdk/resource/semantic_conventions.h | 311 +-- 4 files changed, 1199 insertions(+), 1135 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f89ef1505..85bdbadc28 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,8 @@ Increment the: [#2398](https://github.com/open-telemetry/opentelemetry-cpp/pull/2398) * [EXPORTER] Rework OTLP/HTTP and OTLP/GRPC exporter options [#2388](https://github.com/open-telemetry/opentelemetry-cpp/pull/2388) +* [SEMANTIC CONVENTION] Upgrade to semconv 1.23.1 + [#2428](https://github.com/open-telemetry/opentelemetry-cpp/pull/2428) Important changes: diff --git a/api/include/opentelemetry/trace/semantic_conventions.h b/api/include/opentelemetry/trace/semantic_conventions.h index 16d6562ee9..49f507c90b 100644 --- a/api/include/opentelemetry/trace/semantic_conventions.h +++ b/api/include/opentelemetry/trace/semantic_conventions.h @@ -22,16 +22,16 @@ namespace SemanticConventions /** * The URL of the OpenTelemetry schema for these keys and values. */ -static constexpr const char *kSchemaUrl = "https://opentelemetry.io/schemas/1.22.0"; +static constexpr const char *kSchemaUrl = "https://opentelemetry.io/schemas/1.23.1"; /** - * Client address - domain name if available without reverse DNS lookup, otherwise IP address or + * Client address - domain name if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name. * *

Notes:

  • When observed from the server side, and when communicating through an intermediary, - {@code client.address} SHOULD represent the client address behind any intermediaries (e.g. proxies) - if it's available.
+ {@code client.address} SHOULD represent the client address behind any intermediaries, for example + proxies, if it's available. */ static constexpr const char *kClientAddress = "client.address"; @@ -40,125 +40,19 @@ static constexpr const char *kClientAddress = "client.address"; * *

Notes:

  • When observed from the server side, and when communicating through an intermediary, - {@code client.port} SHOULD represent the client port behind any intermediaries (e.g. proxies) if - it's available.
+ {@code client.port} SHOULD represent the client port behind any intermediaries, for example + proxies, if it's available. */ static constexpr const char *kClientPort = "client.port"; /** - * Deprecated, use {@code server.address}. - * - * @deprecated Deprecated, use `server.address`. - */ -OPENTELEMETRY_DEPRECATED -static constexpr const char *kNetHostName = "net.host.name"; - -/** - * Deprecated, use {@code server.port}. - * - * @deprecated Deprecated, use `server.port`. - */ -OPENTELEMETRY_DEPRECATED -static constexpr const char *kNetHostPort = "net.host.port"; - -/** - * Deprecated, use {@code server.address} on client spans and {@code client.address} on server - * spans. - * - * @deprecated Deprecated, use `server.address` on client spans and `client.address` on server - * spans. - */ -OPENTELEMETRY_DEPRECATED -static constexpr const char *kNetPeerName = "net.peer.name"; - -/** - * Deprecated, use {@code server.port} on client spans and {@code client.port} on server spans. - * - * @deprecated Deprecated, use `server.port` on client spans and `client.port` on server spans. - */ -OPENTELEMETRY_DEPRECATED -static constexpr const char *kNetPeerPort = "net.peer.port"; - -/** - * Deprecated, use {@code network.protocol.name}. - * - * @deprecated Deprecated, use `network.protocol.name`. - */ -OPENTELEMETRY_DEPRECATED -static constexpr const char *kNetProtocolName = "net.protocol.name"; - -/** - * Deprecated, use {@code network.protocol.version}. - * - * @deprecated Deprecated, use `network.protocol.version`. - */ -OPENTELEMETRY_DEPRECATED -static constexpr const char *kNetProtocolVersion = "net.protocol.version"; - -/** - * Deprecated, use {@code network.transport} and {@code network.type}. - * - * @deprecated Deprecated, use `network.transport` and `network.type`. - */ -OPENTELEMETRY_DEPRECATED -static constexpr const char *kNetSockFamily = "net.sock.family"; - -/** - * Deprecated, use {@code network.local.address}. - * - * @deprecated Deprecated, use `network.local.address`. - */ -OPENTELEMETRY_DEPRECATED -static constexpr const char *kNetSockHostAddr = "net.sock.host.addr"; - -/** - * Deprecated, use {@code network.local.port}. - * - * @deprecated Deprecated, use `network.local.port`. - */ -OPENTELEMETRY_DEPRECATED -static constexpr const char *kNetSockHostPort = "net.sock.host.port"; - -/** - * Deprecated, use {@code network.peer.address}. - * - * @deprecated Deprecated, use `network.peer.address`. - */ -OPENTELEMETRY_DEPRECATED -static constexpr const char *kNetSockPeerAddr = "net.sock.peer.addr"; - -/** - * Deprecated, no replacement at this time. - * - * @deprecated Deprecated, no replacement at this time. - */ -OPENTELEMETRY_DEPRECATED -static constexpr const char *kNetSockPeerName = "net.sock.peer.name"; - -/** - * Deprecated, use {@code network.peer.port}. - * - * @deprecated Deprecated, use `network.peer.port`. - */ -OPENTELEMETRY_DEPRECATED -static constexpr const char *kNetSockPeerPort = "net.sock.peer.port"; - -/** - * Deprecated, use {@code network.transport}. - * - * @deprecated Deprecated, use `network.transport`. - */ -OPENTELEMETRY_DEPRECATED -static constexpr const char *kNetTransport = "net.transport"; - -/** - * Destination address - domain name if available without reverse DNS lookup, otherwise IP address + * Destination address - domain name if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name. * *

Notes:

  • When observed from the source side, and when communicating through an intermediary, - {@code destination.address} SHOULD represent the destination address behind any intermediaries - (e.g. proxies) if it's available.
+ {@code destination.address} SHOULD represent the destination address behind any intermediaries, for + example proxies, if it's available. */ static constexpr const char *kDestinationAddress = "destination.address"; @@ -173,14 +67,15 @@ static constexpr const char *kDestinationPort = "destination.port"; *

Notes:

  • The {@code error.type} SHOULD be predictable and SHOULD have low cardinality. Instrumentations SHOULD document the list of errors they report.
  • The cardinality of {@code -error.type} within one instrumentation library SHOULD be low, but telemetry consumers that aggregate +error.type} within one instrumentation library SHOULD be low. Telemetry consumers that aggregate data from multiple instrumentation libraries and applications should be prepared for {@code -error.type} to have high cardinality at query time, when no additional filters are +error.type} to have high cardinality at query time when no additional filters are applied.
  • If the operation has completed successfully, instrumentations SHOULD NOT set {@code -error.type}.
  • If a specific domain defines its own set of error codes (such as HTTP or gRPC -status codes), it's RECOMMENDED to use a domain-specific attribute and also set {@code error.type} -to capture all errors, regardless of whether they are defined within the domain-specific set or -not.
+error.type}.
  • If a specific domain defines its own set of error identifiers (such as HTTP or +gRPC status codes), it's RECOMMENDED to:
  • Use a domain-specific attribute
  • Set {@code +error.type} to capture all errors, regardless of whether they are defined within the domain-specific +set or not.
  • + */ static constexpr const char *kErrorType = "error.type"; @@ -263,57 +158,12 @@ static constexpr const char *kEnduserRole = "enduser.role"; */ static constexpr const char *kEnduserScope = "enduser.scope"; -/** - * Whether the thread is daemon or not. - */ -static constexpr const char *kThreadDaemon = "thread.daemon"; - -/** - * Current "managed" thread ID (as opposed to OS thread ID). - */ -static constexpr const char *kThreadId = "thread.id"; - -/** - * Current thread name. - */ -static constexpr const char *kThreadName = "thread.name"; - -/** - * The column number in {@code code.filepath} best representing the operation. It SHOULD point - * within the code unit named in {@code code.function}. - */ -static constexpr const char *kCodeColumn = "code.column"; - -/** - * The source code file name that identifies the code unit as uniquely as possible (preferably an - * absolute file path). - */ -static constexpr const char *kCodeFilepath = "code.filepath"; - -/** - * The method or function name, or equivalent (usually rightmost part of the code unit's name). - */ -static constexpr const char *kCodeFunction = "code.function"; - -/** - * The line number in {@code code.filepath} best representing the operation. It SHOULD point within - * the code unit named in {@code code.function}. - */ -static constexpr const char *kCodeLineno = "code.lineno"; - -/** - * The "namespace" within which {@code code.function} is defined. Usually the qualified - * class or module name, such that {@code code.namespace} + some separator + {@code code.function} - * form a unique identifier for the code unit. - */ -static constexpr const char *kCodeNamespace = "code.namespace"; - /** * The domain identifies the business context for the events. * *

    Notes: -

    • Events across different domains may have same {@code event.name}, yet be -unrelated events.
    +
    • Events across different domains may have same {@code event.name}, yet be unrelated + events.
    */ static constexpr const char *kEventDomain = "event.domain"; @@ -358,9 +208,31 @@ static constexpr const char *kLogFilePath = "log.file.path"; */ static constexpr const char *kLogFilePathResolved = "log.file.path_resolved"; +/** + * This attribute represents the state the application has transitioned into at the occurrence of + the event. + * + *

    Notes: +

    + */ +static constexpr const char *kIosState = "ios.state"; + +/** + * This attribute represents the state the application has transitioned into at the occurrence of + the event. + * + *

    Notes: +

    + */ +static constexpr const char *kAndroidState = "android.state"; + /** * The name of the connection pool; unique within the instrumented application. In case the - * connection pool implementation does not provide a name, then the db.connection_string * should be used */ @@ -474,96 +346,34 @@ static constexpr const char *kSystemNetworkState = "system.network.state"; static constexpr const char *kSystemProcessesStatus = "system.processes.status"; /** - * Local address of the network connection - IP address or Unix domain socket name. - */ -static constexpr const char *kNetworkLocalAddress = "network.local.address"; - -/** - * Local port number of the network connection. - */ -static constexpr const char *kNetworkLocalPort = "network.local.port"; - -/** - * Peer address of the network connection - IP address or Unix domain socket name. - */ -static constexpr const char *kNetworkPeerAddress = "network.peer.address"; - -/** - * Peer port number of the network connection. - */ -static constexpr const char *kNetworkPeerPort = "network.peer.port"; - -/** - * OSI application layer or non-OSI - equivalent. - * - *

    Notes: -

    • The value SHOULD be normalized to lowercase.
    - */ -static constexpr const char *kNetworkProtocolName = "network.protocol.name"; - -/** - * Version of the protocol specified in {@code network.protocol.name}. - * - *

    Notes: -

    • {@code network.protocol.version} refers to the version of the protocol used and might be - different from the protocol client's version. If the HTTP client used has a version of {@code - 0.27.2}, but sends HTTP version {@code 1.1}, this attribute should be set to {@code 1.1}.
    • -
    - */ -static constexpr const char *kNetworkProtocolVersion = "network.protocol.version"; - -/** - * OSI transport layer or inter-process communication -method. - * - *

    Notes: -

    • The value SHOULD be normalized to lowercase.
    • Consider always setting the -transport when setting a port number, since a port number is ambiguous without knowing the -transport, for example different processes could be listening on TCP port 12345 and UDP port -12345.
    - */ -static constexpr const char *kNetworkTransport = "network.transport"; - -/** - * OSI network layer or non-OSI equivalent. - * - *

    Notes: -

    • The value SHOULD be normalized to lowercase.
    - */ -static constexpr const char *kNetworkType = "network.type"; - -/** - * The ISO 3166-1 alpha-2 2-character country code associated with the mobile carrier network. - */ -static constexpr const char *kNetworkCarrierIcc = "network.carrier.icc"; - -/** - * The mobile carrier country code. + * The column number in {@code code.filepath} best representing the operation. It SHOULD point + * within the code unit named in {@code code.function}. */ -static constexpr const char *kNetworkCarrierMcc = "network.carrier.mcc"; +static constexpr const char *kCodeColumn = "code.column"; /** - * The mobile carrier network code. + * The source code file name that identifies the code unit as uniquely as possible (preferably an + * absolute file path). */ -static constexpr const char *kNetworkCarrierMnc = "network.carrier.mnc"; +static constexpr const char *kCodeFilepath = "code.filepath"; /** - * The name of the mobile carrier. + * The method or function name, or equivalent (usually rightmost part of the code unit's name). */ -static constexpr const char *kNetworkCarrierName = "network.carrier.name"; +static constexpr const char *kCodeFunction = "code.function"; /** - * This describes more details regarding the connection.type. It may be the type of cell technology - * connection, but it could be used for describing details about a wifi connection. + * The line number in {@code code.filepath} best representing the operation. It SHOULD point within + * the code unit named in {@code code.function}. */ -static constexpr const char *kNetworkConnectionSubtype = "network.connection.subtype"; +static constexpr const char *kCodeLineno = "code.lineno"; /** - * The internet connection type. + * The "namespace" within which {@code code.function} is defined. Usually the qualified + * class or module name, such that {@code code.namespace} + some separator + {@code code.function} + * form a unique identifier for the code unit. */ -static constexpr const char *kNetworkConnectionType = "network.connection.type"; +static constexpr const char *kCodeNamespace = "code.namespace"; /** * Deprecated, use {@code http.request.method} instead. @@ -574,17 +384,17 @@ OPENTELEMETRY_DEPRECATED static constexpr const char *kHttpMethod = "http.method"; /** - * Deprecated, use {@code http.request.body.size} instead. + * Deprecated, use {@code http.request.header.content-length} instead. * - * @deprecated Deprecated, use `http.request.body.size` instead. + * @deprecated Deprecated, use `http.request.header.content-length` instead. */ OPENTELEMETRY_DEPRECATED static constexpr const char *kHttpRequestContentLength = "http.request_content_length"; /** - * Deprecated, use {@code http.response.body.size} instead. + * Deprecated, use {@code http.response.header.content-length} instead. * - * @deprecated Deprecated, use `http.response.body.size` instead. + * @deprecated Deprecated, use `http.response.header.content-length` instead. */ OPENTELEMETRY_DEPRECATED static constexpr const char *kHttpResponseContentLength = "http.response_content_length"; @@ -622,12 +432,118 @@ OPENTELEMETRY_DEPRECATED static constexpr const char *kHttpUrl = "http.url"; /** - * The size of the request payload body in bytes. This is the number of bytes transferred excluding - * headers and is often, but not always, present as the Content-Length - * header. For requests using transport encoding, this should be the compressed size. + * Deprecated, use {@code server.address}. + * + * @deprecated Deprecated, use `server.address`. */ -static constexpr const char *kHttpRequestBodySize = "http.request.body.size"; +OPENTELEMETRY_DEPRECATED +static constexpr const char *kNetHostName = "net.host.name"; + +/** + * Deprecated, use {@code server.port}. + * + * @deprecated Deprecated, use `server.port`. + */ +OPENTELEMETRY_DEPRECATED +static constexpr const char *kNetHostPort = "net.host.port"; + +/** + * Deprecated, use {@code server.address} on client spans and {@code client.address} on server + * spans. + * + * @deprecated Deprecated, use `server.address` on client spans and `client.address` on server + * spans. + */ +OPENTELEMETRY_DEPRECATED +static constexpr const char *kNetPeerName = "net.peer.name"; + +/** + * Deprecated, use {@code server.port} on client spans and {@code client.port} on server spans. + * + * @deprecated Deprecated, use `server.port` on client spans and `client.port` on server spans. + */ +OPENTELEMETRY_DEPRECATED +static constexpr const char *kNetPeerPort = "net.peer.port"; + +/** + * Deprecated, use {@code network.protocol.name}. + * + * @deprecated Deprecated, use `network.protocol.name`. + */ +OPENTELEMETRY_DEPRECATED +static constexpr const char *kNetProtocolName = "net.protocol.name"; + +/** + * Deprecated, use {@code network.protocol.version}. + * + * @deprecated Deprecated, use `network.protocol.version`. + */ +OPENTELEMETRY_DEPRECATED +static constexpr const char *kNetProtocolVersion = "net.protocol.version"; + +/** + * Deprecated, use {@code network.transport} and {@code network.type}. + * + * @deprecated Deprecated, use `network.transport` and `network.type`. + */ +OPENTELEMETRY_DEPRECATED +static constexpr const char *kNetSockFamily = "net.sock.family"; + +/** + * Deprecated, use {@code network.local.address}. + * + * @deprecated Deprecated, use `network.local.address`. + */ +OPENTELEMETRY_DEPRECATED +static constexpr const char *kNetSockHostAddr = "net.sock.host.addr"; + +/** + * Deprecated, use {@code network.local.port}. + * + * @deprecated Deprecated, use `network.local.port`. + */ +OPENTELEMETRY_DEPRECATED +static constexpr const char *kNetSockHostPort = "net.sock.host.port"; + +/** + * Deprecated, use {@code network.peer.address}. + * + * @deprecated Deprecated, use `network.peer.address`. + */ +OPENTELEMETRY_DEPRECATED +static constexpr const char *kNetSockPeerAddr = "net.sock.peer.addr"; + +/** + * Deprecated, no replacement at this time. + * + * @deprecated Deprecated, no replacement at this time. + */ +OPENTELEMETRY_DEPRECATED +static constexpr const char *kNetSockPeerName = "net.sock.peer.name"; + +/** + * Deprecated, use {@code network.peer.port}. + * + * @deprecated Deprecated, use `network.peer.port`. + */ +OPENTELEMETRY_DEPRECATED +static constexpr const char *kNetSockPeerPort = "net.sock.peer.port"; + +/** + * Deprecated, use {@code network.transport}. + * + * @deprecated Deprecated, use `network.transport`. + */ +OPENTELEMETRY_DEPRECATED +static constexpr const char *kNetTransport = "net.transport"; + +/** + * The size of the request payload body in bytes. This is the number of bytes transferred excluding + * headers and is often, but not always, present as the Content-Length + * header. For requests using transport encoding, this should be the compressed size. + */ +static constexpr const char *kHttpRequestBodySize = "http.request.body.size"; /** * HTTP request method. @@ -664,7 +580,7 @@ static constexpr const char *kHttpRequestMethodOriginal = "http.request.method_o regardless of what was the cause of the resending (e.g. redirection, authorization failure, 503 Server Unavailable, network issues, or any other). */ -static constexpr const char *kHttpResendCount = "http.resend_count"; +static constexpr const char *kHttpRequestResendCount = "http.request.resend_count"; /** * The size of the response payload body in bytes. This is the number of bytes transferred excluding @@ -680,8 +596,8 @@ static constexpr const char *kHttpResponseBodySize = "http.response.body.size"; static constexpr const char *kHttpResponseStatusCode = "http.response.status_code"; /** - * The matched route (path template in the format used by the respective server framework). See note -below + * The matched route, that is, the path template in the format used by the respective server +framework. * *

    Notes:

    • MUST NOT be populated when this is not supported by the HTTP server framework as the @@ -692,878 +608,1036 @@ one.
    static constexpr const char *kHttpRoute = "http.route"; /** - * Server address - domain name if available without reverse DNS lookup, otherwise IP address or -Unix domain socket name. + * The number of messages sent, received, or processed in the scope of the batching operation. * *

    Notes: -

    • When observed from the client side, and when communicating through an intermediary, -{@code server.address} SHOULD represent the server address behind any intermediaries (e.g. proxies) -if it's available.
    +
    • Instrumentations SHOULD NOT set {@code messaging.batch.message_count} on spans that + operate with a single message. When a messaging client library supports both batch and + single-message API for the same operation, instrumentations SHOULD use {@code + messaging.batch.message_count} for batching APIs and SHOULD NOT use it for single-message + APIs.
    */ -static constexpr const char *kServerAddress = "server.address"; +static constexpr const char *kMessagingBatchMessageCount = "messaging.batch.message_count"; /** - * Server port number. - * - *

    Notes: -

    • When observed from the client side, and when communicating through an intermediary, - {@code server.port} SHOULD represent the server port behind any intermediaries (e.g. proxies) if - it's available.
    + * A unique identifier for the client that consumes or produces a message. */ -static constexpr const char *kServerPort = "server.port"; +static constexpr const char *kMessagingClientId = "messaging.client_id"; /** - * A unique id to identify a session. + * A boolean that is true if the message destination is anonymous (could be unnamed or have + * auto-generated name). */ -static constexpr const char *kSessionId = "session.id"; +static constexpr const char *kMessagingDestinationAnonymous = "messaging.destination.anonymous"; /** - * Source address - domain name if available without reverse DNS lookup, otherwise IP address or - Unix domain socket name. + * The message destination name * *

    Notes: -

    • When observed from the destination side, and when communicating through an intermediary, - {@code source.address} SHOULD represent the source address behind any intermediaries (e.g. proxies) - if it's available.
    - */ -static constexpr const char *kSourceAddress = "source.address"; - -/** - * Source port number +
    • Destination name SHOULD uniquely identify a specific queue, topic or other entity within +the broker. If the broker doesn't have such notion, the destination name SHOULD uniquely identify +the broker.
    */ -static constexpr const char *kSourcePort = "source.port"; +static constexpr const char *kMessagingDestinationName = "messaging.destination.name"; /** - * The full invoked ARN as provided on the {@code Context} passed to the function ({@code - Lambda-Runtime-Invoked-Function-Arn} header on the {@code /runtime/invocation/next} applicable). + * Low cardinality representation of the messaging destination name * *

    Notes: -

    • This may be different from {@code cloud.resource_id} if an alias is involved.
    +
    • Destination names could be constructed from templates. An example would be a destination + name involving a user name or product id. Although the destination name in this case is of high + cardinality, the underlying template is of low cardinality and can be effectively used for grouping + and aggregation.
    */ -static constexpr const char *kAwsLambdaInvokedArn = "aws.lambda.invoked_arn"; +static constexpr const char *kMessagingDestinationTemplate = "messaging.destination.template"; /** - * The event_id - * uniquely identifies the event. + * A boolean that is true if the message destination is temporary and might not exist anymore after + * messages are processed. */ -static constexpr const char *kCloudeventsEventId = "cloudevents.event_id"; +static constexpr const char *kMessagingDestinationTemporary = "messaging.destination.temporary"; /** - * The source - * identifies the context in which an event happened. + * A boolean that is true if the publish message destination is anonymous (could be unnamed or have + * auto-generated name). */ -static constexpr const char *kCloudeventsEventSource = "cloudevents.event_source"; +static constexpr const char *kMessagingDestinationPublishAnonymous = + "messaging.destination_publish.anonymous"; /** - * The version of - * the CloudEvents specification which the event uses. + * The name of the original destination the message was published to + * + *

    Notes: +

    • The name SHOULD uniquely identify a specific queue, topic, or other entity within the +broker. If the broker doesn't have such notion, the original destination name SHOULD uniquely +identify the broker.
    */ -static constexpr const char *kCloudeventsEventSpecVersion = "cloudevents.event_spec_version"; +static constexpr const char *kMessagingDestinationPublishName = + "messaging.destination_publish.name"; /** - * The subject of - * the event in the context of the event producer (identified by source). + * Name of the Kafka Consumer Group that is handling the message. Only applies to consumers, not + * producers. */ -static constexpr const char *kCloudeventsEventSubject = "cloudevents.event_subject"; +static constexpr const char *kMessagingKafkaConsumerGroup = "messaging.kafka.consumer.group"; /** - * The event_type - * contains a value describing the type of event related to the originating occurrence. + * Partition the message is sent to. */ -static constexpr const char *kCloudeventsEventType = "cloudevents.event_type"; +static constexpr const char *kMessagingKafkaDestinationPartition = + "messaging.kafka.destination.partition"; /** - * Parent-child Reference type + * Message keys in Kafka are used for grouping alike messages to ensure they're processed on the + same partition. They differ from {@code messaging.message.id} in that they're not unique. If the + key is {@code null}, the attribute MUST NOT be set. * *

    Notes: -

    • The causal relationship between a child Span and a parent Span.
    +
    • If the key type is not string, it's string representation has to be supplied for the + attribute. If the key has no unambiguous, canonical string form, don't include its value.
    • +
    */ -static constexpr const char *kOpentracingRefType = "opentracing.ref_type"; +static constexpr const char *kMessagingKafkaMessageKey = "messaging.kafka.message.key"; /** - * The connection string used to connect to the database. It is recommended to remove embedded - * credentials. + * The offset of a record in the corresponding Kafka partition. */ -static constexpr const char *kDbConnectionString = "db.connection_string"; +static constexpr const char *kMessagingKafkaMessageOffset = "messaging.kafka.message.offset"; /** - * The fully-qualified class name of the Java Database Connectivity - * (JDBC) driver used to connect. + * A boolean that is true if the message is a tombstone. */ -static constexpr const char *kDbJdbcDriverClassname = "db.jdbc.driver_classname"; +static constexpr const char *kMessagingKafkaMessageTombstone = "messaging.kafka.message.tombstone"; /** - * This attribute is used to report the name of the database being accessed. For commands that - switch the database, this should be set to the target database (even if the command fails). + * The size of the message body in bytes. * *

    Notes: -

    • In some SQL databases, the database name to be used is called "schema name". In - case there are multiple layers that could be considered for database name (e.g. Oracle instance - name and schema name), the database name to be used is the more specific layer (e.g. Oracle schema - name).
    +
    • This can refer to both the compressed or uncompressed body size. If both sizes are known, +the uncompressed body size should be used.
    */ -static constexpr const char *kDbName = "db.name"; +static constexpr const char *kMessagingMessageBodySize = "messaging.message.body.size"; /** - * The name of the operation being executed, e.g. the MongoDB command - name such as {@code findAndModify}, or the SQL keyword. + * The conversation ID identifying the conversation to which the message belongs, represented as a + * string. Sometimes called "Correlation ID". + */ +static constexpr const char *kMessagingMessageConversationId = "messaging.message.conversation_id"; + +/** + * The size of the message body and metadata in bytes. * *

    Notes: -

    • When setting this to an SQL keyword, it is not recommended to attempt any client-side - parsing of {@code db.statement} just to get this property, but it should be set if the operation - name is provided by the library being instrumented. If the SQL statement has an ambiguous - operation, or performs more than one operation, this value may be omitted.
    +
    • This can refer to both the compressed or uncompressed size. If both sizes are known, the +uncompressed size should be used.
    */ -static constexpr const char *kDbOperation = "db.operation"; +static constexpr const char *kMessagingMessageEnvelopeSize = "messaging.message.envelope.size"; /** - * The database statement being executed. + * A value used by the messaging system as an identifier for the message, represented as a string. */ -static constexpr const char *kDbStatement = "db.statement"; +static constexpr const char *kMessagingMessageId = "messaging.message.id"; /** - * An identifier for the database management system (DBMS) product being used. See below for a list - * of well-known identifiers. + * A string identifying the kind of messaging operation. + * + *

    Notes: +

    • If a custom value is used, it MUST be of low cardinality.
    */ -static constexpr const char *kDbSystem = "db.system"; +static constexpr const char *kMessagingOperation = "messaging.operation"; /** - * Username for accessing the database. + * RabbitMQ message routing key. */ -static constexpr const char *kDbUser = "db.user"; +static constexpr const char *kMessagingRabbitmqDestinationRoutingKey = + "messaging.rabbitmq.destination.routing_key"; /** - * The Microsoft SQL Server instance - name connecting to. This name is used to determine the port of a named instance. - * - *

    Notes: -

    • If setting a {@code db.mssql.instance_name}, {@code server.port} is no longer required - (but still recommended if non-standard).
    + * Name of the RocketMQ producer/consumer group that is handling the message. The client type is + * identified by the SpanKind. */ -static constexpr const char *kDbMssqlInstanceName = "db.mssql.instance_name"; +static constexpr const char *kMessagingRocketmqClientGroup = "messaging.rocketmq.client_group"; /** - * The consistency level of the query. Based on consistency values from CQL. + * Model of message consumption. This only applies to consumer spans. */ -static constexpr const char *kDbCassandraConsistencyLevel = "db.cassandra.consistency_level"; +static constexpr const char *kMessagingRocketmqConsumptionModel = + "messaging.rocketmq.consumption_model"; /** - * The data center of the coordinating node for a query. + * The delay time level for delay message, which determines the message delay time. */ -static constexpr const char *kDbCassandraCoordinatorDc = "db.cassandra.coordinator.dc"; +static constexpr const char *kMessagingRocketmqMessageDelayTimeLevel = + "messaging.rocketmq.message.delay_time_level"; /** - * The ID of the coordinating node for a query. + * The timestamp in milliseconds that the delay message is expected to be delivered to consumer. */ -static constexpr const char *kDbCassandraCoordinatorId = "db.cassandra.coordinator.id"; +static constexpr const char *kMessagingRocketmqMessageDeliveryTimestamp = + "messaging.rocketmq.message.delivery_timestamp"; /** - * Whether or not the query is idempotent. + * It is essential for FIFO message. Messages that belong to the same message group are always + * processed one by one within the same consumer group. */ -static constexpr const char *kDbCassandraIdempotence = "db.cassandra.idempotence"; +static constexpr const char *kMessagingRocketmqMessageGroup = "messaging.rocketmq.message.group"; /** - * The fetch size used for paging, i.e. how many rows will be returned at once. + * Key(s) of message, another way to mark message besides message id. */ -static constexpr const char *kDbCassandraPageSize = "db.cassandra.page_size"; +static constexpr const char *kMessagingRocketmqMessageKeys = "messaging.rocketmq.message.keys"; /** - * The number of times a query was speculatively executed. Not set or {@code 0} if the query was not - * executed speculatively. + * The secondary classifier of message besides topic. */ -static constexpr const char *kDbCassandraSpeculativeExecutionCount = - "db.cassandra.speculative_execution_count"; +static constexpr const char *kMessagingRocketmqMessageTag = "messaging.rocketmq.message.tag"; /** - * The name of the primary table that the operation is acting upon, including the keyspace name (if - applicable). - * - *

    Notes: -

    • This mirrors the db.sql.table attribute but references cassandra rather than sql. It is - not recommended to attempt any client-side parsing of {@code db.statement} just to get this - property, but it should be set if it is provided by the library being instrumented. If the - operation is acting upon an anonymous table, or more than one table, this value MUST NOT be - set.
    + * Type of message. */ -static constexpr const char *kDbCassandraTable = "db.cassandra.table"; +static constexpr const char *kMessagingRocketmqMessageType = "messaging.rocketmq.message.type"; /** - * The index of the database being accessed as used in the {@code SELECT} command, provided as an integer. To be - * used instead of the generic {@code db.name} attribute. + * Namespace of RocketMQ resources, resources in different namespaces are individual. */ -static constexpr const char *kDbRedisDatabaseIndex = "db.redis.database_index"; +static constexpr const char *kMessagingRocketmqNamespace = "messaging.rocketmq.namespace"; /** - * The collection being accessed within the database stated in {@code db.name}. + * A string identifying the messaging system. */ -static constexpr const char *kDbMongodbCollection = "db.mongodb.collection"; +static constexpr const char *kMessagingSystem = "messaging.system"; /** - * Represents the identifier of an Elasticsearch cluster. + * The ISO 3166-1 alpha-2 2-character country code associated with the mobile carrier network. */ -static constexpr const char *kDbElasticsearchClusterName = "db.elasticsearch.cluster.name"; +static constexpr const char *kNetworkCarrierIcc = "network.carrier.icc"; /** - * Represents the human-readable identifier of the node/instance to which a request was routed. + * The mobile carrier country code. */ -static constexpr const char *kDbElasticsearchNodeName = "db.elasticsearch.node.name"; +static constexpr const char *kNetworkCarrierMcc = "network.carrier.mcc"; /** - * The name of the primary table that the operation is acting upon, including the database name (if - applicable). - * - *

    Notes: -

    • It is not recommended to attempt any client-side parsing of {@code db.statement} just to - get this property, but it should be set if it is provided by the library being instrumented. If the - operation is acting upon an anonymous table, or more than one table, this value MUST NOT be - set.
    + * The mobile carrier network code. */ -static constexpr const char *kDbSqlTable = "db.sql.table"; +static constexpr const char *kNetworkCarrierMnc = "network.carrier.mnc"; /** - * Unique Cosmos client instance id. + * The name of the mobile carrier. */ -static constexpr const char *kDbCosmosdbClientId = "db.cosmosdb.client_id"; +static constexpr const char *kNetworkCarrierName = "network.carrier.name"; /** - * Cosmos client connection mode. + * This describes more details regarding the connection.type. It may be the type of cell technology + * connection, but it could be used for describing details about a wifi connection. */ -static constexpr const char *kDbCosmosdbConnectionMode = "db.cosmosdb.connection_mode"; +static constexpr const char *kNetworkConnectionSubtype = "network.connection.subtype"; /** - * Cosmos DB container name. + * The internet connection type. */ -static constexpr const char *kDbCosmosdbContainer = "db.cosmosdb.container"; +static constexpr const char *kNetworkConnectionType = "network.connection.type"; /** - * CosmosDB Operation Type. + * Local address of the network connection - IP address or Unix domain socket name. */ -static constexpr const char *kDbCosmosdbOperationType = "db.cosmosdb.operation_type"; +static constexpr const char *kNetworkLocalAddress = "network.local.address"; /** - * RU consumed for that operation + * Local port number of the network connection. */ -static constexpr const char *kDbCosmosdbRequestCharge = "db.cosmosdb.request_charge"; +static constexpr const char *kNetworkLocalPort = "network.local.port"; /** - * Request payload size in bytes + * Peer address of the network connection - IP address or Unix domain socket name. */ -static constexpr const char *kDbCosmosdbRequestContentLength = "db.cosmosdb.request_content_length"; +static constexpr const char *kNetworkPeerAddress = "network.peer.address"; /** - * Cosmos DB status code. + * Peer port number of the network connection. */ -static constexpr const char *kDbCosmosdbStatusCode = "db.cosmosdb.status_code"; +static constexpr const char *kNetworkPeerPort = "network.peer.port"; /** - * Cosmos DB sub status code. + * OSI application layer or non-OSI + equivalent. + * + *

    Notes: +

    • The value SHOULD be normalized to lowercase.
    */ -static constexpr const char *kDbCosmosdbSubStatusCode = "db.cosmosdb.sub_status_code"; +static constexpr const char *kNetworkProtocolName = "network.protocol.name"; /** - * Name of the code, either "OK" or "ERROR". MUST NOT be set if the status code - * is UNSET. + * Version of the protocol specified in {@code network.protocol.name}. + * + *

    Notes: +

    • {@code network.protocol.version} refers to the version of the protocol used and might be + different from the protocol client's version. If the HTTP client has a version of {@code 0.27.2}, + but sends HTTP version {@code 1.1}, this attribute should be set to {@code 1.1}.
    */ -static constexpr const char *kOtelStatusCode = "otel.status_code"; +static constexpr const char *kNetworkProtocolVersion = "network.protocol.version"; /** - * Description of the Status if it has a value, otherwise not set. + * OSI transport layer or inter-process communication +method. + * + *

    Notes: +

    • The value SHOULD be normalized to lowercase.
    • Consider always setting the +transport when setting a port number, since a port number is ambiguous without knowing the +transport. For example different processes could be listening on TCP port 12345 and UDP port +12345.
    */ -static constexpr const char *kOtelStatusDescription = "otel.status_description"; +static constexpr const char *kNetworkTransport = "network.transport"; /** - * The invocation ID of the current function invocation. + * OSI network layer or non-OSI equivalent. + * + *

    Notes: +

    • The value SHOULD be normalized to lowercase.
    */ -static constexpr const char *kFaasInvocationId = "faas.invocation_id"; +static constexpr const char *kNetworkType = "network.type"; /** - * The name of the source on which the triggering operation was performed. For example, in Cloud - * Storage or S3 corresponds to the bucket name, and in Cosmos DB to the database name. + * The error codes of the Connect + * request. Error codes are always string values. */ -static constexpr const char *kFaasDocumentCollection = "faas.document.collection"; +static constexpr const char *kRpcConnectRpcErrorCode = "rpc.connect_rpc.error_code"; /** - * The document name/table subjected to the operation. For example, in Cloud Storage or S3 is the - * name of the file, and in Cosmos DB the table name. + * The numeric status + * code of the gRPC request. */ -static constexpr const char *kFaasDocumentName = "faas.document.name"; +static constexpr const char *kRpcGrpcStatusCode = "rpc.grpc.status_code"; /** - * Describes the type of the operation that was performed on the data. + * {@code error.code} property of response if it is an error response. */ -static constexpr const char *kFaasDocumentOperation = "faas.document.operation"; +static constexpr const char *kRpcJsonrpcErrorCode = "rpc.jsonrpc.error_code"; /** - * A string containing the time when the data was accessed in the ISO 8601 format expressed in UTC. + * {@code error.message} property of response if it is an error response. */ -static constexpr const char *kFaasDocumentTime = "faas.document.time"; +static constexpr const char *kRpcJsonrpcErrorMessage = "rpc.jsonrpc.error_message"; /** - * A string containing the schedule period as Cron - * Expression. + * {@code id} property of request or response. Since protocol allows id to be int, string, {@code + * null} or missing (for notifications), value is expected to be cast to string for simplicity. Use + * empty string in case of {@code null} value. Omit entirely if this is a notification. */ -static constexpr const char *kFaasCron = "faas.cron"; +static constexpr const char *kRpcJsonrpcRequestId = "rpc.jsonrpc.request_id"; /** - * A string containing the function invocation time in the ISO 8601 format expressed in UTC. + * Protocol version as in {@code jsonrpc} property of request/response. Since JSON-RPC 1.0 doesn't + * specify this, the value can be omitted. */ -static constexpr const char *kFaasTime = "faas.time"; +static constexpr const char *kRpcJsonrpcVersion = "rpc.jsonrpc.version"; /** - * A boolean that is true if the serverless function is executed for the first time (aka - * cold-start). + * The name of the (logical) method being called, must be equal to the $method part in the span + name. + * + *

    Notes: +

    • This is the logical name of the method from the RPC interface perspective, which can be + different from the name of any implementing method/function. The {@code code.function} attribute + may be used to store the latter (e.g., method actually executing the call on the server side, RPC + client stub method on the client side).
    */ -static constexpr const char *kFaasColdstart = "faas.coldstart"; +static constexpr const char *kRpcMethod = "rpc.method"; /** - * The unique identifier of the feature flag. + * The full (logical) name of the service being called, including its package name, if applicable. + * + *

    Notes: +

    • This is the logical name of the service from the RPC interface perspective, which can be + different from the name of any implementing class. The {@code code.namespace} attribute may be used + to store the latter (despite the attribute name, it may include a class name; e.g., class with + method actually executing the call on the server side, RPC client stub class on the client + side).
    */ -static constexpr const char *kFeatureFlagKey = "feature_flag.key"; +static constexpr const char *kRpcService = "rpc.service"; /** - * The name of the service provider that performs the flag evaluation. + * A string identifying the remoting system. See below for a list of well-known identifiers. */ -static constexpr const char *kFeatureFlagProviderName = "feature_flag.provider_name"; +static constexpr const char *kRpcSystem = "rpc.system"; /** - * SHOULD be a semantic identifier for a value. If one is unavailable, a stringified version of the -value can be used. - * - *

    Notes: -

    • A semantic identifier, commonly referred to as a variant, provides a means -for referring to a value without including the value itself. This can -provide additional context for understanding the meaning behind a value. -For example, the variant {@code red} maybe be used for the value {@code #c05543}.
    • A -stringified version of the value can be used in situations where a semantic identifier is -unavailable. String representation of the value should be determined by the implementer.
    + * Current "managed" thread ID (as opposed to OS thread ID). */ -static constexpr const char *kFeatureFlagVariant = "feature_flag.variant"; +static constexpr const char *kThreadId = "thread.id"; /** - * The AWS request ID as returned in the response headers {@code x-amz-request-id} or {@code - * x-amz-requestid}. + * Current thread name. */ -static constexpr const char *kAwsRequestId = "aws.request_id"; +static constexpr const char *kThreadName = "thread.name"; /** - * The value of the {@code AttributesToGet} request parameter. + * The URI fragment component */ -static constexpr const char *kAwsDynamodbAttributesToGet = "aws.dynamodb.attributes_to_get"; +static constexpr const char *kUrlFragment = "url.fragment"; /** - * The value of the {@code ConsistentRead} request parameter. + * Absolute URL describing a network resource according to RFC3986 + * + *

    Notes: +

    • For network calls, URL usually has {@code scheme://host[:port][path][?query][#fragment]} +format, where the fragment is not transmitted over HTTP, but if it is known, it SHOULD be included +nevertheless. +{@code url.full} MUST NOT contain credentials passed via URL in form of {@code +https://username:password@www.example.com/}. In such case username and password SHOULD be redacted +and attribute's value SHOULD be {@code https://REDACTED:REDACTED@www.example.com/}. +{@code url.full} SHOULD capture the absolute URL when it is available (or can be reconstructed) and +SHOULD NOT be validated or modified except for sanitizing purposes.
    */ -static constexpr const char *kAwsDynamodbConsistentRead = "aws.dynamodb.consistent_read"; +static constexpr const char *kUrlFull = "url.full"; /** - * The JSON-serialized value of each item in the {@code ConsumedCapacity} response field. + * The URI path component */ -static constexpr const char *kAwsDynamodbConsumedCapacity = "aws.dynamodb.consumed_capacity"; +static constexpr const char *kUrlPath = "url.path"; /** - * The value of the {@code IndexName} request parameter. + * The URI query component + * + *

    Notes: +

    • Sensitive content provided in query string SHOULD be scrubbed when instrumentations can + identify it.
    */ -static constexpr const char *kAwsDynamodbIndexName = "aws.dynamodb.index_name"; +static constexpr const char *kUrlQuery = "url.query"; /** - * The JSON-serialized value of the {@code ItemCollectionMetrics} response field. + * The URI scheme component + * identifying the used protocol. */ -static constexpr const char *kAwsDynamodbItemCollectionMetrics = - "aws.dynamodb.item_collection_metrics"; +static constexpr const char *kUrlScheme = "url.scheme"; /** - * The value of the {@code Limit} request parameter. + * Value of the HTTP + * User-Agent header sent by the client. */ -static constexpr const char *kAwsDynamodbLimit = "aws.dynamodb.limit"; +static constexpr const char *kUserAgentOriginal = "user_agent.original"; /** - * The value of the {@code ProjectionExpression} request parameter. + * Server domain name if available without reverse DNS lookup; otherwise, IP address or Unix domain + socket name. + * + *

    Notes: +

    • When observed from the client side, and when communicating through an intermediary, + {@code server.address} SHOULD represent the server address behind any intermediaries, for example + proxies, if it's available.
    */ -static constexpr const char *kAwsDynamodbProjection = "aws.dynamodb.projection"; +static constexpr const char *kServerAddress = "server.address"; /** - * The value of the {@code ProvisionedThroughput.ReadCapacityUnits} request parameter. + * Server port number. + * + *

    Notes: +

    • When observed from the client side, and when communicating through an intermediary, + {@code server.port} SHOULD represent the server port behind any intermediaries, for example + proxies, if it's available.
    */ -static constexpr const char *kAwsDynamodbProvisionedReadCapacity = - "aws.dynamodb.provisioned_read_capacity"; +static constexpr const char *kServerPort = "server.port"; /** - * The value of the {@code ProvisionedThroughput.WriteCapacityUnits} request parameter. + * A unique id to identify a session. */ -static constexpr const char *kAwsDynamodbProvisionedWriteCapacity = - "aws.dynamodb.provisioned_write_capacity"; +static constexpr const char *kSessionId = "session.id"; /** - * The value of the {@code Select} request parameter. + * The previous {@code session.id} for this user, when known. */ -static constexpr const char *kAwsDynamodbSelect = "aws.dynamodb.select"; +static constexpr const char *kSessionPreviousId = "session.previous_id"; /** - * The keys in the {@code RequestItems} object field. + * Source address - domain name if available without reverse DNS lookup; otherwise, IP address or + Unix domain socket name. + * + *

    Notes: +

    • When observed from the destination side, and when communicating through an intermediary, + {@code source.address} SHOULD represent the source address behind any intermediaries, for example + proxies, if it's available.
    */ -static constexpr const char *kAwsDynamodbTableNames = "aws.dynamodb.table_names"; +static constexpr const char *kSourceAddress = "source.address"; /** - * The JSON-serialized value of each item of the {@code GlobalSecondaryIndexes} request field + * Source port number */ -static constexpr const char *kAwsDynamodbGlobalSecondaryIndexes = - "aws.dynamodb.global_secondary_indexes"; +static constexpr const char *kSourcePort = "source.port"; /** - * The JSON-serialized value of each item of the {@code LocalSecondaryIndexes} request field. + * The full invoked ARN as provided on the {@code Context} passed to the function ({@code + Lambda-Runtime-Invoked-Function-Arn} header on the {@code /runtime/invocation/next} applicable). + * + *

    Notes: +

    • This may be different from {@code cloud.resource_id} if an alias is involved.
    */ -static constexpr const char *kAwsDynamodbLocalSecondaryIndexes = - "aws.dynamodb.local_secondary_indexes"; +static constexpr const char *kAwsLambdaInvokedArn = "aws.lambda.invoked_arn"; /** - * The value of the {@code ExclusiveStartTableName} request parameter. + * The event_id + * uniquely identifies the event. */ -static constexpr const char *kAwsDynamodbExclusiveStartTable = "aws.dynamodb.exclusive_start_table"; +static constexpr const char *kCloudeventsEventId = "cloudevents.event_id"; /** - * The the number of items in the {@code TableNames} response parameter. + * The source + * identifies the context in which an event happened. */ -static constexpr const char *kAwsDynamodbTableCount = "aws.dynamodb.table_count"; +static constexpr const char *kCloudeventsEventSource = "cloudevents.event_source"; /** - * The value of the {@code ScanIndexForward} request parameter. + * The version of + * the CloudEvents specification which the event uses. */ -static constexpr const char *kAwsDynamodbScanForward = "aws.dynamodb.scan_forward"; +static constexpr const char *kCloudeventsEventSpecVersion = "cloudevents.event_spec_version"; /** - * The value of the {@code Count} response parameter. + * The subject of + * the event in the context of the event producer (identified by source). */ -static constexpr const char *kAwsDynamodbCount = "aws.dynamodb.count"; +static constexpr const char *kCloudeventsEventSubject = "cloudevents.event_subject"; /** - * The value of the {@code ScannedCount} response parameter. + * The event_type + * contains a value describing the type of event related to the originating occurrence. */ -static constexpr const char *kAwsDynamodbScannedCount = "aws.dynamodb.scanned_count"; +static constexpr const char *kCloudeventsEventType = "cloudevents.event_type"; /** - * The value of the {@code Segment} request parameter. + * Parent-child Reference type + * + *

    Notes: +

    • The causal relationship between a child Span and a parent Span.
    */ -static constexpr const char *kAwsDynamodbSegment = "aws.dynamodb.segment"; +static constexpr const char *kOpentracingRefType = "opentracing.ref_type"; /** - * The value of the {@code TotalSegments} request parameter. + * The connection string used to connect to the database. It is recommended to remove embedded + * credentials. */ -static constexpr const char *kAwsDynamodbTotalSegments = "aws.dynamodb.total_segments"; +static constexpr const char *kDbConnectionString = "db.connection_string"; /** - * The JSON-serialized value of each item in the {@code AttributeDefinitions} request field. + * The fully-qualified class name of the Java Database Connectivity + * (JDBC) driver used to connect. */ -static constexpr const char *kAwsDynamodbAttributeDefinitions = - "aws.dynamodb.attribute_definitions"; +static constexpr const char *kDbJdbcDriverClassname = "db.jdbc.driver_classname"; /** - * The JSON-serialized value of each item in the the {@code GlobalSecondaryIndexUpdates} request - * field. + * This attribute is used to report the name of the database being accessed. For commands that + switch the database, this should be set to the target database (even if the command fails). + * + *

    Notes: +

    • In some SQL databases, the database name to be used is called "schema name". In + case there are multiple layers that could be considered for database name (e.g. Oracle instance + name and schema name), the database name to be used is the more specific layer (e.g. Oracle schema + name).
    */ -static constexpr const char *kAwsDynamodbGlobalSecondaryIndexUpdates = - "aws.dynamodb.global_secondary_index_updates"; +static constexpr const char *kDbName = "db.name"; /** - * The S3 bucket name the request refers to. Corresponds to the {@code --bucket} parameter of the S3 API operations. + * The name of the operation being executed, e.g. the MongoDB command + name such as {@code findAndModify}, or the SQL keyword. * *

    Notes: -

    • The {@code bucket} attribute is applicable to all S3 operations that reference a bucket, -i.e. that require the bucket name as a mandatory parameter. This applies to almost all S3 operations -except {@code list-buckets}.
    +
    • When setting this to an SQL keyword, it is not recommended to attempt any client-side + parsing of {@code db.statement} just to get this property, but it should be set if the operation + name is provided by the library being instrumented. If the SQL statement has an ambiguous + operation, or performs more than one operation, this value may be omitted.
    */ -static constexpr const char *kAwsS3Bucket = "aws.s3.bucket"; +static constexpr const char *kDbOperation = "db.operation"; /** - * The source object (in the form {@code bucket}/{@code key}) for the copy operation. - * - *

    Notes: -

    + * The database statement being executed. */ -static constexpr const char *kAwsS3CopySource = "aws.s3.copy_source"; +static constexpr const char *kDbStatement = "db.statement"; /** - * The delete request container that specifies the objects to be deleted. + * An identifier for the database management system (DBMS) product being used. See below for a list + * of well-known identifiers. + */ +static constexpr const char *kDbSystem = "db.system"; + +/** + * Username for accessing the database. + */ +static constexpr const char *kDbUser = "db.user"; + +/** + * The Microsoft SQL Server instance + name connecting to. This name is used to determine the port of a named instance. * *

    Notes: -

    +
    • If setting a {@code db.mssql.instance_name}, {@code server.port} is no longer required + (but still recommended if non-standard).
    */ -static constexpr const char *kAwsS3Delete = "aws.s3.delete"; +static constexpr const char *kDbMssqlInstanceName = "db.mssql.instance_name"; /** - * The S3 object key the request refers to. Corresponds to the {@code --key} parameter of the S3 API operations. + * The consistency level of the query. Based on consistency values from CQL. + */ +static constexpr const char *kDbCassandraConsistencyLevel = "db.cassandra.consistency_level"; + +/** + * The data center of the coordinating node for a query. + */ +static constexpr const char *kDbCassandraCoordinatorDc = "db.cassandra.coordinator.dc"; + +/** + * The ID of the coordinating node for a query. + */ +static constexpr const char *kDbCassandraCoordinatorId = "db.cassandra.coordinator.id"; + +/** + * Whether or not the query is idempotent. + */ +static constexpr const char *kDbCassandraIdempotence = "db.cassandra.idempotence"; + +/** + * The fetch size used for paging, i.e. how many rows will be returned at once. + */ +static constexpr const char *kDbCassandraPageSize = "db.cassandra.page_size"; + +/** + * The number of times a query was speculatively executed. Not set or {@code 0} if the query was not + * executed speculatively. + */ +static constexpr const char *kDbCassandraSpeculativeExecutionCount = + "db.cassandra.speculative_execution_count"; + +/** + * The name of the primary table that the operation is acting upon, including the keyspace name (if + applicable). * *

    Notes: -

    +
    • This mirrors the db.sql.table attribute but references cassandra rather than sql. It is + not recommended to attempt any client-side parsing of {@code db.statement} just to get this + property, but it should be set if it is provided by the library being instrumented. If the + operation is acting upon an anonymous table, or more than one table, this value MUST NOT be + set.
    */ -static constexpr const char *kAwsS3Key = "aws.s3.key"; +static constexpr const char *kDbCassandraTable = "db.cassandra.table"; /** - * The part number of the part being uploaded in a multipart-upload operation. This is a positive -integer between 1 and 10,000. + * The index of the database being accessed as used in the {@code SELECT} command, provided as an integer. To be + * used instead of the generic {@code db.name} attribute. + */ +static constexpr const char *kDbRedisDatabaseIndex = "db.redis.database_index"; + +/** + * The collection being accessed within the database stated in {@code db.name}. + */ +static constexpr const char *kDbMongodbCollection = "db.mongodb.collection"; + +/** + * Represents the identifier of an Elasticsearch cluster. + */ +static constexpr const char *kDbElasticsearchClusterName = "db.elasticsearch.cluster.name"; + +/** + * Represents the human-readable identifier of the node/instance to which a request was routed. + */ +static constexpr const char *kDbElasticsearchNodeName = "db.elasticsearch.node.name"; + +/** + * The name of the primary table that the operation is acting upon, including the database name (if + applicable). * *

    Notes: -

    +
    • It is not recommended to attempt any client-side parsing of {@code db.statement} just to + get this property, but it should be set if it is provided by the library being instrumented. If the + operation is acting upon an anonymous table, or more than one table, this value MUST NOT be + set.
    + */ +static constexpr const char *kDbSqlTable = "db.sql.table"; + +/** + * Unique Cosmos client instance id. + */ +static constexpr const char *kDbCosmosdbClientId = "db.cosmosdb.client_id"; + +/** + * Cosmos client connection mode. + */ +static constexpr const char *kDbCosmosdbConnectionMode = "db.cosmosdb.connection_mode"; + +/** + * Cosmos DB container name. + */ +static constexpr const char *kDbCosmosdbContainer = "db.cosmosdb.container"; + +/** + * CosmosDB Operation Type. + */ +static constexpr const char *kDbCosmosdbOperationType = "db.cosmosdb.operation_type"; + +/** + * RU consumed for that operation + */ +static constexpr const char *kDbCosmosdbRequestCharge = "db.cosmosdb.request_charge"; + +/** + * Request payload size in bytes + */ +static constexpr const char *kDbCosmosdbRequestContentLength = "db.cosmosdb.request_content_length"; + +/** + * Cosmos DB status code. + */ +static constexpr const char *kDbCosmosdbStatusCode = "db.cosmosdb.status_code"; + +/** + * Cosmos DB sub status code. + */ +static constexpr const char *kDbCosmosdbSubStatusCode = "db.cosmosdb.sub_status_code"; + +/** + * Name of the code, either "OK" or "ERROR". MUST NOT be set if the status code + * is UNSET. + */ +static constexpr const char *kOtelStatusCode = "otel.status_code"; + +/** + * Description of the Status if it has a value, otherwise not set. */ -static constexpr const char *kAwsS3PartNumber = "aws.s3.part_number"; +static constexpr const char *kOtelStatusDescription = "otel.status_description"; /** - * Upload ID that identifies the multipart upload. - * - *

    Notes: -

    + * The invocation ID of the current function invocation. */ -static constexpr const char *kAwsS3UploadId = "aws.s3.upload_id"; +static constexpr const char *kFaasInvocationId = "faas.invocation_id"; /** - * The GraphQL document being executed. - * - *

    Notes: -

    • The value may be sanitized to exclude sensitive information.
    + * The name of the source on which the triggering operation was performed. For example, in Cloud + * Storage or S3 corresponds to the bucket name, and in Cosmos DB to the database name. */ -static constexpr const char *kGraphqlDocument = "graphql.document"; +static constexpr const char *kFaasDocumentCollection = "faas.document.collection"; /** - * The name of the operation being executed. + * The document name/table subjected to the operation. For example, in Cloud Storage or S3 is the + * name of the file, and in Cosmos DB the table name. */ -static constexpr const char *kGraphqlOperationName = "graphql.operation.name"; +static constexpr const char *kFaasDocumentName = "faas.document.name"; /** - * The type of the operation being executed. + * Describes the type of the operation that was performed on the data. */ -static constexpr const char *kGraphqlOperationType = "graphql.operation.type"; +static constexpr const char *kFaasDocumentOperation = "faas.document.operation"; /** - * The size of the message body in bytes. - * - *

    Notes: -

    • This can refer to both the compressed or uncompressed body size. If both sizes are known, -the uncompressed body size should be used.
    + * A string containing the time when the data was accessed in the ISO 8601 format expressed in UTC. */ -static constexpr const char *kMessagingMessageBodySize = "messaging.message.body.size"; +static constexpr const char *kFaasDocumentTime = "faas.document.time"; /** - * The conversation ID identifying the conversation to which the - * message belongs, represented as a string. Sometimes called "Correlation ID". + * A string containing the schedule period as Cron + * Expression. */ -static constexpr const char *kMessagingMessageConversationId = "messaging.message.conversation_id"; +static constexpr const char *kFaasCron = "faas.cron"; /** - * The size of the message body and metadata in bytes. - * - *

    Notes: -

    • This can refer to both the compressed or uncompressed size. If both sizes are known, the -uncompressed size should be used.
    + * A string containing the function invocation time in the ISO 8601 format expressed in UTC. */ -static constexpr const char *kMessagingMessageEnvelopeSize = "messaging.message.envelope.size"; +static constexpr const char *kFaasTime = "faas.time"; /** - * A value used by the messaging system as an identifier for the message, represented as a string. + * A boolean that is true if the serverless function is executed for the first time (aka + * cold-start). */ -static constexpr const char *kMessagingMessageId = "messaging.message.id"; +static constexpr const char *kFaasColdstart = "faas.coldstart"; /** - * A boolean that is true if the message destination is anonymous (could be unnamed or have - * auto-generated name). + * The unique identifier of the feature flag. */ -static constexpr const char *kMessagingDestinationAnonymous = "messaging.destination.anonymous"; +static constexpr const char *kFeatureFlagKey = "feature_flag.key"; /** - * The message destination name - * - *

    Notes: -

    • Destination name SHOULD uniquely identify a specific queue, topic or other entity within -the broker. If the broker does not have such notion, the destination name SHOULD uniquely identify -the broker.
    + * The name of the service provider that performs the flag evaluation. */ -static constexpr const char *kMessagingDestinationName = "messaging.destination.name"; +static constexpr const char *kFeatureFlagProviderName = "feature_flag.provider_name"; /** - * Low cardinality representation of the messaging destination name + * SHOULD be a semantic identifier for a value. If one is unavailable, a stringified version of the +value can be used. * *

    Notes: -

    • Destination names could be constructed from templates. An example would be a destination - name involving a user name or product id. Although the destination name in this case is of high - cardinality, the underlying template is of low cardinality and can be effectively used for grouping - and aggregation.
    +
    • A semantic identifier, commonly referred to as a variant, provides a means +for referring to a value without including the value itself. This can +provide additional context for understanding the meaning behind a value. +For example, the variant {@code red} maybe be used for the value {@code #c05543}.
    • A +stringified version of the value can be used in situations where a semantic identifier is +unavailable. String representation of the value should be determined by the implementer.
    */ -static constexpr const char *kMessagingDestinationTemplate = "messaging.destination.template"; +static constexpr const char *kFeatureFlagVariant = "feature_flag.variant"; /** - * A boolean that is true if the message destination is temporary and might not exist anymore after - * messages are processed. + * The AWS request ID as returned in the response headers {@code x-amz-request-id} or {@code + * x-amz-requestid}. */ -static constexpr const char *kMessagingDestinationTemporary = "messaging.destination.temporary"; +static constexpr const char *kAwsRequestId = "aws.request_id"; /** - * A boolean that is true if the publish message destination is anonymous (could be unnamed or have - * auto-generated name). + * The value of the {@code AttributesToGet} request parameter. */ -static constexpr const char *kMessagingDestinationPublishAnonymous = - "messaging.destination_publish.anonymous"; +static constexpr const char *kAwsDynamodbAttributesToGet = "aws.dynamodb.attributes_to_get"; /** - * The name of the original destination the message was published to - * - *

    Notes: -

    • The name SHOULD uniquely identify a specific queue, topic, or other entity within the -broker. If the broker does not have such notion, the original destination name SHOULD uniquely -identify the broker.
    + * The value of the {@code ConsistentRead} request parameter. */ -static constexpr const char *kMessagingDestinationPublishName = - "messaging.destination_publish.name"; +static constexpr const char *kAwsDynamodbConsistentRead = "aws.dynamodb.consistent_read"; /** - * The number of messages sent, received, or processed in the scope of the batching operation. - * - *

    Notes: -

    • Instrumentations SHOULD NOT set {@code messaging.batch.message_count} on spans that - operate with a single message. When a messaging client library supports both batch and - single-message API for the same operation, instrumentations SHOULD use {@code - messaging.batch.message_count} for batching APIs and SHOULD NOT use it for single-message - APIs.
    + * The JSON-serialized value of each item in the {@code ConsumedCapacity} response field. */ -static constexpr const char *kMessagingBatchMessageCount = "messaging.batch.message_count"; +static constexpr const char *kAwsDynamodbConsumedCapacity = "aws.dynamodb.consumed_capacity"; /** - * A unique identifier for the client that consumes or produces a message. + * The value of the {@code IndexName} request parameter. */ -static constexpr const char *kMessagingClientId = "messaging.client_id"; +static constexpr const char *kAwsDynamodbIndexName = "aws.dynamodb.index_name"; /** - * A string identifying the kind of messaging operation as defined in the Operation names section above. - * - *

    Notes: -

    • If a custom value is used, it MUST be of low cardinality.
    + * The JSON-serialized value of the {@code ItemCollectionMetrics} response field. */ -static constexpr const char *kMessagingOperation = "messaging.operation"; +static constexpr const char *kAwsDynamodbItemCollectionMetrics = + "aws.dynamodb.item_collection_metrics"; /** - * A string identifying the messaging system. + * The value of the {@code Limit} request parameter. */ -static constexpr const char *kMessagingSystem = "messaging.system"; +static constexpr const char *kAwsDynamodbLimit = "aws.dynamodb.limit"; /** - * RabbitMQ message routing key. + * The value of the {@code ProjectionExpression} request parameter. */ -static constexpr const char *kMessagingRabbitmqDestinationRoutingKey = - "messaging.rabbitmq.destination.routing_key"; +static constexpr const char *kAwsDynamodbProjection = "aws.dynamodb.projection"; /** - * Name of the Kafka Consumer Group that is handling the message. Only applies to consumers, not - * producers. + * The value of the {@code ProvisionedThroughput.ReadCapacityUnits} request parameter. */ -static constexpr const char *kMessagingKafkaConsumerGroup = "messaging.kafka.consumer.group"; +static constexpr const char *kAwsDynamodbProvisionedReadCapacity = + "aws.dynamodb.provisioned_read_capacity"; /** - * Partition the message is sent to. + * The value of the {@code ProvisionedThroughput.WriteCapacityUnits} request parameter. */ -static constexpr const char *kMessagingKafkaDestinationPartition = - "messaging.kafka.destination.partition"; +static constexpr const char *kAwsDynamodbProvisionedWriteCapacity = + "aws.dynamodb.provisioned_write_capacity"; /** - * Message keys in Kafka are used for grouping alike messages to ensure they're processed on the - same partition. They differ from {@code messaging.message.id} in that they're not unique. If the - key is {@code null}, the attribute MUST NOT be set. - * - *

    Notes: -

    • If the key type is not string, it's string representation has to be supplied for the - attribute. If the key has no unambiguous, canonical string form, don't include its value.
    • -
    + * The value of the {@code Select} request parameter. */ -static constexpr const char *kMessagingKafkaMessageKey = "messaging.kafka.message.key"; +static constexpr const char *kAwsDynamodbSelect = "aws.dynamodb.select"; /** - * The offset of a record in the corresponding Kafka partition. + * The keys in the {@code RequestItems} object field. */ -static constexpr const char *kMessagingKafkaMessageOffset = "messaging.kafka.message.offset"; +static constexpr const char *kAwsDynamodbTableNames = "aws.dynamodb.table_names"; /** - * A boolean that is true if the message is a tombstone. + * The JSON-serialized value of each item of the {@code GlobalSecondaryIndexes} request field */ -static constexpr const char *kMessagingKafkaMessageTombstone = "messaging.kafka.message.tombstone"; +static constexpr const char *kAwsDynamodbGlobalSecondaryIndexes = + "aws.dynamodb.global_secondary_indexes"; /** - * Name of the RocketMQ producer/consumer group that is handling the message. The client type is - * identified by the SpanKind. + * The JSON-serialized value of each item of the {@code LocalSecondaryIndexes} request field. */ -static constexpr const char *kMessagingRocketmqClientGroup = "messaging.rocketmq.client_group"; +static constexpr const char *kAwsDynamodbLocalSecondaryIndexes = + "aws.dynamodb.local_secondary_indexes"; /** - * Model of message consumption. This only applies to consumer spans. + * The value of the {@code ExclusiveStartTableName} request parameter. */ -static constexpr const char *kMessagingRocketmqConsumptionModel = - "messaging.rocketmq.consumption_model"; +static constexpr const char *kAwsDynamodbExclusiveStartTable = "aws.dynamodb.exclusive_start_table"; /** - * The delay time level for delay message, which determines the message delay time. + * The the number of items in the {@code TableNames} response parameter. */ -static constexpr const char *kMessagingRocketmqMessageDelayTimeLevel = - "messaging.rocketmq.message.delay_time_level"; +static constexpr const char *kAwsDynamodbTableCount = "aws.dynamodb.table_count"; /** - * The timestamp in milliseconds that the delay message is expected to be delivered to consumer. + * The value of the {@code ScanIndexForward} request parameter. */ -static constexpr const char *kMessagingRocketmqMessageDeliveryTimestamp = - "messaging.rocketmq.message.delivery_timestamp"; +static constexpr const char *kAwsDynamodbScanForward = "aws.dynamodb.scan_forward"; /** - * It is essential for FIFO message. Messages that belong to the same message group are always - * processed one by one within the same consumer group. + * The value of the {@code Count} response parameter. */ -static constexpr const char *kMessagingRocketmqMessageGroup = "messaging.rocketmq.message.group"; +static constexpr const char *kAwsDynamodbCount = "aws.dynamodb.count"; /** - * Key(s) of message, another way to mark message besides message id. + * The value of the {@code ScannedCount} response parameter. */ -static constexpr const char *kMessagingRocketmqMessageKeys = "messaging.rocketmq.message.keys"; +static constexpr const char *kAwsDynamodbScannedCount = "aws.dynamodb.scanned_count"; /** - * The secondary classifier of message besides topic. + * The value of the {@code Segment} request parameter. */ -static constexpr const char *kMessagingRocketmqMessageTag = "messaging.rocketmq.message.tag"; +static constexpr const char *kAwsDynamodbSegment = "aws.dynamodb.segment"; /** - * Type of message. + * The value of the {@code TotalSegments} request parameter. */ -static constexpr const char *kMessagingRocketmqMessageType = "messaging.rocketmq.message.type"; +static constexpr const char *kAwsDynamodbTotalSegments = "aws.dynamodb.total_segments"; /** - * Namespace of RocketMQ resources, resources in different namespaces are individual. + * The JSON-serialized value of each item in the {@code AttributeDefinitions} request field. */ -static constexpr const char *kMessagingRocketmqNamespace = "messaging.rocketmq.namespace"; +static constexpr const char *kAwsDynamodbAttributeDefinitions = + "aws.dynamodb.attribute_definitions"; /** - * The name of the (logical) method being called, must be equal to the $method part in the span - name. + * The JSON-serialized value of each item in the the {@code GlobalSecondaryIndexUpdates} request + * field. + */ +static constexpr const char *kAwsDynamodbGlobalSecondaryIndexUpdates = + "aws.dynamodb.global_secondary_index_updates"; + +/** + * The S3 bucket name the request refers to. Corresponds to the {@code --bucket} parameter of the S3 API operations. * *

    Notes: -

    • This is the logical name of the method from the RPC interface perspective, which can be - different from the name of any implementing method/function. The {@code code.function} attribute - may be used to store the latter (e.g., method actually executing the call on the server side, RPC - client stub method on the client side).
    +
    • The {@code bucket} attribute is applicable to all S3 operations that reference a bucket, +i.e. that require the bucket name as a mandatory parameter. This applies to almost all S3 operations +except {@code list-buckets}.
    + */ +static constexpr const char *kAwsS3Bucket = "aws.s3.bucket"; + +/** + * The source object (in the form {@code bucket}/{@code key}) for the copy operation. + * + *

    Notes: +

    */ -static constexpr const char *kRpcMethod = "rpc.method"; +static constexpr const char *kAwsS3CopySource = "aws.s3.copy_source"; /** - * The full (logical) name of the service being called, including its package name, if applicable. + * The delete request container that specifies the objects to be deleted. * *

    Notes: -

    • This is the logical name of the service from the RPC interface perspective, which can be - different from the name of any implementing class. The {@code code.namespace} attribute may be used - to store the latter (despite the attribute name, it may include a class name; e.g., class with - method actually executing the call on the server side, RPC client stub class on the client - side).
    + */ -static constexpr const char *kRpcService = "rpc.service"; +static constexpr const char *kAwsS3Delete = "aws.s3.delete"; /** - * A string identifying the remoting system. See below for a list of well-known identifiers. + * The S3 object key the request refers to. Corresponds to the {@code --key} parameter of the S3 API operations. + * + *

    Notes: +

    */ -static constexpr const char *kRpcSystem = "rpc.system"; +static constexpr const char *kAwsS3Key = "aws.s3.key"; /** - * The numeric status - * code of the gRPC request. + * The part number of the part being uploaded in a multipart-upload operation. This is a positive +integer between 1 and 10,000. + * + *

    Notes: +

    */ -static constexpr const char *kRpcGrpcStatusCode = "rpc.grpc.status_code"; +static constexpr const char *kAwsS3PartNumber = "aws.s3.part_number"; /** - * {@code error.code} property of response if it is an error response. + * Upload ID that identifies the multipart upload. + * + *

    Notes: +

    */ -static constexpr const char *kRpcJsonrpcErrorCode = "rpc.jsonrpc.error_code"; +static constexpr const char *kAwsS3UploadId = "aws.s3.upload_id"; /** - * {@code error.message} property of response if it is an error response. + * The GraphQL document being executed. + * + *

    Notes: +

    • The value may be sanitized to exclude sensitive information.
    */ -static constexpr const char *kRpcJsonrpcErrorMessage = "rpc.jsonrpc.error_message"; +static constexpr const char *kGraphqlDocument = "graphql.document"; /** - * {@code id} property of request or response. Since protocol allows id to be int, string, {@code - * null} or missing (for notifications), value is expected to be cast to string for simplicity. Use - * empty string in case of {@code null} value. Omit entirely if this is a notification. + * The name of the operation being executed. */ -static constexpr const char *kRpcJsonrpcRequestId = "rpc.jsonrpc.request_id"; +static constexpr const char *kGraphqlOperationName = "graphql.operation.name"; /** - * Protocol version as in {@code jsonrpc} property of request/response. Since JSON-RPC 1.0 does not - * specify this, the value can be omitted. + * The type of the operation being executed. */ -static constexpr const char *kRpcJsonrpcVersion = "rpc.jsonrpc.version"; +static constexpr const char *kGraphqlOperationType = "graphql.operation.type"; /** * Compressed size of the message in bytes. @@ -1590,12 +1664,6 @@ static constexpr const char *kMessageType = "message.type"; */ static constexpr const char *kMessageUncompressedSize = "message.uncompressed_size"; -/** - * The error codes of the Connect - * request. Error codes are always string values. - */ -static constexpr const char *kRpcConnectRpcErrorCode = "rpc.connect_rpc.error_code"; - /** * SHOULD be set to true if the exception event is recorded at a point where it is known that the exception is escaping the scope of the span. @@ -1615,85 +1683,10 @@ recorded at a time where it was not clear whether the exception will escape.URI fragment component - */ -static constexpr const char *kUrlFragment = "url.fragment"; - -/** - * Absolute URL describing a network resource according to RFC3986 - * - *

    Notes: -

    • For network calls, URL usually has {@code scheme://host[:port][path][?query][#fragment]} -format, where the fragment is not transmitted over HTTP, but if it is known, it should be included -nevertheless. -{@code url.full} MUST NOT contain credentials passed via URL in form of {@code -https://username:password@www.example.com/}. In such case username and password should be redacted -and attribute's value should be {@code https://REDACTED:REDACTED@www.example.com/}. -{@code url.full} SHOULD capture the absolute URL when it is available (or can be reconstructed) and -SHOULD NOT be validated or modified except for sanitizing purposes.
    - */ -static constexpr const char *kUrlFull = "url.full"; - -/** - * The URI path component - * - *

    Notes: -

    • When missing, the value is assumed to be {@code /}
    - */ -static constexpr const char *kUrlPath = "url.path"; - -/** - * The URI query component - * - *

    Notes: -

    • Sensitive content provided in query string SHOULD be scrubbed when instrumentations can - identify it.
    - */ -static constexpr const char *kUrlQuery = "url.query"; - -/** - * The URI scheme component - * identifying the used protocol. - */ -static constexpr const char *kUrlScheme = "url.scheme"; - -/** - * Value of the HTTP - * User-Agent header sent by the client. - */ -static constexpr const char *kUserAgentOriginal = "user_agent.original"; - // Enum definitions -namespace NetSockFamilyValues -{ -/** IPv4 address. */ -static constexpr const char *kInet = "inet"; -/** IPv6 address. */ -static constexpr const char *kInet6 = "inet6"; -/** Unix domain socket path. */ -static constexpr const char *kUnix = "unix"; -} // namespace NetSockFamilyValues - -namespace NetTransportValues -{ -/** ip_tcp. */ -static constexpr const char *kIpTcp = "ip_tcp"; -/** ip_udp. */ -static constexpr const char *kIpUdp = "ip_udp"; -/** Named or anonymous pipe. */ -static constexpr const char *kPipe = "pipe"; -/** In-process communication. */ -static constexpr const char *kInproc = "inproc"; -/** Something else (non IP-based). */ -static constexpr const char *kOther = "other"; -} // namespace NetTransportValues - namespace ErrorTypeValues { -/** A fallback error value to be used when the instrumentation does not define a custom value for - * it. */ +/** A fallback error value to be used when the instrumentation doesn't define a custom value. */ static constexpr const char *kOther = "_OTHER"; } // namespace ErrorTypeValues @@ -1743,6 +1736,35 @@ static constexpr const char *kStdout = "stdout"; static constexpr const char *kStderr = "stderr"; } // namespace LogIostreamValues +namespace IosStateValues +{ +/** The app has become `active`. Associated with UIKit notification `applicationDidBecomeActive`. */ +static constexpr const char *kActive = "active"; +/** The app is now `inactive`. Associated with UIKit notification `applicationWillResignActive`. */ +static constexpr const char *kInactive = "inactive"; +/** The app is now in the background. This value is associated with UIKit notification + * `applicationDidEnterBackground`. */ +static constexpr const char *kBackground = "background"; +/** The app is now in the foreground. This value is associated with UIKit notification + * `applicationWillEnterForeground`. */ +static constexpr const char *kForeground = "foreground"; +/** The app is about to terminate. Associated with UIKit notification `applicationWillTerminate`. */ +static constexpr const char *kTerminate = "terminate"; +} // namespace IosStateValues + +namespace AndroidStateValues +{ +/** Any time before Activity.onResume() or, if the app has no Activity, Context.startService() has + * been called in the app for the first time. */ +static constexpr const char *kCreated = "created"; +/** Any time after Activity.onPause() or, if the app has no Activity, Context.stopService() has been + * called when the app was in the foreground state. */ +static constexpr const char *kBackground = "background"; +/** Any time after Activity.onResume() or, if the app has no Activity, Context.startService() has + * been called when the app was in either the created or background states. */ +static constexpr const char *kForeground = "foreground"; +} // namespace AndroidStateValues + namespace StateValues { /** idle. */ @@ -1779,8 +1801,6 @@ static constexpr const char *kSteal = "steal"; namespace SystemMemoryStateValues { -/** total. */ -static constexpr const char *kTotal = "total"; /** used. */ static constexpr const char *kUsed = "used"; /** free. */ @@ -1899,25 +1919,90 @@ static constexpr const char *kStopped = "stopped"; static constexpr const char *kDefunct = "defunct"; } // namespace SystemProcessesStatusValues -namespace NetworkTransportValues +namespace NetSockFamilyValues { -/** TCP. */ -static constexpr const char *kTcp = "tcp"; -/** UDP. */ -static constexpr const char *kUdp = "udp"; -/** Named or anonymous pipe. See note below. */ -static constexpr const char *kPipe = "pipe"; -/** Unix domain socket. */ +/** IPv4 address. */ +static constexpr const char *kInet = "inet"; +/** IPv6 address. */ +static constexpr const char *kInet6 = "inet6"; +/** Unix domain socket path. */ static constexpr const char *kUnix = "unix"; -} // namespace NetworkTransportValues +} // namespace NetSockFamilyValues -namespace NetworkTypeValues +namespace NetTransportValues { -/** IPv4. */ -static constexpr const char *kIpv4 = "ipv4"; -/** IPv6. */ -static constexpr const char *kIpv6 = "ipv6"; -} // namespace NetworkTypeValues +/** ip_tcp. */ +static constexpr const char *kIpTcp = "ip_tcp"; +/** ip_udp. */ +static constexpr const char *kIpUdp = "ip_udp"; +/** Named or anonymous pipe. */ +static constexpr const char *kPipe = "pipe"; +/** In-process communication. */ +static constexpr const char *kInproc = "inproc"; +/** Something else (non IP-based). */ +static constexpr const char *kOther = "other"; +} // namespace NetTransportValues + +namespace HttpRequestMethodValues +{ +/** CONNECT method. */ +static constexpr const char *kConnect = "CONNECT"; +/** DELETE method. */ +static constexpr const char *kDelete = "DELETE"; +/** GET method. */ +static constexpr const char *kGet = "GET"; +/** HEAD method. */ +static constexpr const char *kHead = "HEAD"; +/** OPTIONS method. */ +static constexpr const char *kOptions = "OPTIONS"; +/** PATCH method. */ +static constexpr const char *kPatch = "PATCH"; +/** POST method. */ +static constexpr const char *kPost = "POST"; +/** PUT method. */ +static constexpr const char *kPut = "PUT"; +/** TRACE method. */ +static constexpr const char *kTrace = "TRACE"; +/** Any HTTP method that the instrumentation has no prior knowledge of. */ +static constexpr const char *kOther = "_OTHER"; +} // namespace HttpRequestMethodValues + +namespace MessagingOperationValues +{ +/** One or more messages are provided for publishing to an intermediary. If a single message is + * published, the context of the "Publish" span can be used as the creation context and no + * "Create" span needs to be created. */ +static constexpr const char *kPublish = "publish"; +/** A message is created. "Create" spans always refer to a single message and are used to + * provide a unique creation context for messages in batch publishing scenarios. */ +static constexpr const char *kCreate = "create"; +/** One or more messages are requested by a consumer. This operation refers to pull-based scenarios, + * where consumers explicitly call methods of messaging SDKs to receive messages. */ +static constexpr const char *kReceive = "receive"; +/** One or more messages are passed to a consumer. This operation refers to push-based scenarios, + * where consumer register callbacks which get called by messaging SDKs. */ +static constexpr const char *kDeliver = "deliver"; +} // namespace MessagingOperationValues + +namespace MessagingRocketmqConsumptionModelValues +{ +/** Clustering consumption model. */ +static constexpr const char *kClustering = "clustering"; +/** Broadcasting consumption model. */ +static constexpr const char *kBroadcasting = "broadcasting"; +} // namespace MessagingRocketmqConsumptionModelValues + +namespace MessagingRocketmqMessageTypeValues +{ +/** Normal message. */ +static constexpr const char *kNormal = "normal"; +/** FIFO message. */ +static constexpr const char *kFifo = "fifo"; +/** Delay message. */ +static constexpr const char *kDelay = "delay"; +/** Transaction message. */ +static constexpr const char *kTransaction = "transaction"; +} // namespace MessagingRocketmqMessageTypeValues namespace NetworkConnectionSubtypeValues { @@ -1979,35 +2064,119 @@ static constexpr const char *kUnavailable = "unavailable"; static constexpr const char *kUnknown = "unknown"; } // namespace NetworkConnectionTypeValues -namespace HttpRequestMethodValues +namespace NetworkTransportValues { -/** CONNECT method. */ -static constexpr const char *kConnect = "CONNECT"; -/** DELETE method. */ -static constexpr const char *kDelete = "DELETE"; -/** GET method. */ -static constexpr const char *kGet = "GET"; -/** HEAD method. */ -static constexpr const char *kHead = "HEAD"; -/** OPTIONS method. */ -static constexpr const char *kOptions = "OPTIONS"; -/** PATCH method. */ -static constexpr const char *kPatch = "PATCH"; -/** POST method. */ -static constexpr const char *kPost = "POST"; -/** PUT method. */ -static constexpr const char *kPut = "PUT"; -/** TRACE method. */ -static constexpr const char *kTrace = "TRACE"; -/** Any HTTP method that the instrumentation has no prior knowledge of. */ -static constexpr const char *kOther = "_OTHER"; -} // namespace HttpRequestMethodValues +/** TCP. */ +static constexpr const char *kTcp = "tcp"; +/** UDP. */ +static constexpr const char *kUdp = "udp"; +/** Named or anonymous pipe. */ +static constexpr const char *kPipe = "pipe"; +/** Unix domain socket. */ +static constexpr const char *kUnix = "unix"; +} // namespace NetworkTransportValues + +namespace NetworkTypeValues +{ +/** IPv4. */ +static constexpr const char *kIpv4 = "ipv4"; +/** IPv6. */ +static constexpr const char *kIpv6 = "ipv6"; +} // namespace NetworkTypeValues + +namespace RpcConnectRpcErrorCodeValues +{ +/** cancelled. */ +static constexpr const char *kCancelled = "cancelled"; +/** unknown. */ +static constexpr const char *kUnknown = "unknown"; +/** invalid_argument. */ +static constexpr const char *kInvalidArgument = "invalid_argument"; +/** deadline_exceeded. */ +static constexpr const char *kDeadlineExceeded = "deadline_exceeded"; +/** not_found. */ +static constexpr const char *kNotFound = "not_found"; +/** already_exists. */ +static constexpr const char *kAlreadyExists = "already_exists"; +/** permission_denied. */ +static constexpr const char *kPermissionDenied = "permission_denied"; +/** resource_exhausted. */ +static constexpr const char *kResourceExhausted = "resource_exhausted"; +/** failed_precondition. */ +static constexpr const char *kFailedPrecondition = "failed_precondition"; +/** aborted. */ +static constexpr const char *kAborted = "aborted"; +/** out_of_range. */ +static constexpr const char *kOutOfRange = "out_of_range"; +/** unimplemented. */ +static constexpr const char *kUnimplemented = "unimplemented"; +/** internal. */ +static constexpr const char *kInternal = "internal"; +/** unavailable. */ +static constexpr const char *kUnavailable = "unavailable"; +/** data_loss. */ +static constexpr const char *kDataLoss = "data_loss"; +/** unauthenticated. */ +static constexpr const char *kUnauthenticated = "unauthenticated"; +} // namespace RpcConnectRpcErrorCodeValues + +namespace RpcGrpcStatusCodeValues +{ +/** OK. */ +static constexpr const int kOk = 0; +/** CANCELLED. */ +static constexpr const int kCancelled = 1; +/** UNKNOWN. */ +static constexpr const int kUnknown = 2; +/** INVALID_ARGUMENT. */ +static constexpr const int kInvalidArgument = 3; +/** DEADLINE_EXCEEDED. */ +static constexpr const int kDeadlineExceeded = 4; +/** NOT_FOUND. */ +static constexpr const int kNotFound = 5; +/** ALREADY_EXISTS. */ +static constexpr const int kAlreadyExists = 6; +/** PERMISSION_DENIED. */ +static constexpr const int kPermissionDenied = 7; +/** RESOURCE_EXHAUSTED. */ +static constexpr const int kResourceExhausted = 8; +/** FAILED_PRECONDITION. */ +static constexpr const int kFailedPrecondition = 9; +/** ABORTED. */ +static constexpr const int kAborted = 10; +/** OUT_OF_RANGE. */ +static constexpr const int kOutOfRange = 11; +/** UNIMPLEMENTED. */ +static constexpr const int kUnimplemented = 12; +/** INTERNAL. */ +static constexpr const int kInternal = 13; +/** UNAVAILABLE. */ +static constexpr const int kUnavailable = 14; +/** DATA_LOSS. */ +static constexpr const int kDataLoss = 15; +/** UNAUTHENTICATED. */ +static constexpr const int kUnauthenticated = 16; +} // namespace RpcGrpcStatusCodeValues + +namespace RpcSystemValues +{ +/** gRPC. */ +static constexpr const char *kGrpc = "grpc"; +/** Java RMI. */ +static constexpr const char *kJavaRmi = "java_rmi"; +/** .NET WCF. */ +static constexpr const char *kDotnetWcf = "dotnet_wcf"; +/** Apache Dubbo. */ +static constexpr const char *kApacheDubbo = "apache_dubbo"; +/** Connect RPC. */ +static constexpr const char *kConnectRpc = "connect_rpc"; +} // namespace RpcSystemValues namespace OpentracingRefTypeValues { /** The parent Span depends on the child Span in some capacity. */ static constexpr const char *kChildOf = "child_of"; -/** The parent Span does not depend in any way on the result of the child Span. */ +/** The parent Span doesn't depend in any way on the result of the child Span. */ static constexpr const char *kFollowsFrom = "follows_from"; } // namespace OpentracingRefTypeValues @@ -2216,88 +2385,6 @@ static constexpr const char *kMutation = "mutation"; static constexpr const char *kSubscription = "subscription"; } // namespace GraphqlOperationTypeValues -namespace MessagingOperationValues -{ -/** publish. */ -static constexpr const char *kPublish = "publish"; -/** receive. */ -static constexpr const char *kReceive = "receive"; -/** process. */ -static constexpr const char *kProcess = "process"; -} // namespace MessagingOperationValues - -namespace MessagingRocketmqConsumptionModelValues -{ -/** Clustering consumption model. */ -static constexpr const char *kClustering = "clustering"; -/** Broadcasting consumption model. */ -static constexpr const char *kBroadcasting = "broadcasting"; -} // namespace MessagingRocketmqConsumptionModelValues - -namespace MessagingRocketmqMessageTypeValues -{ -/** Normal message. */ -static constexpr const char *kNormal = "normal"; -/** FIFO message. */ -static constexpr const char *kFifo = "fifo"; -/** Delay message. */ -static constexpr const char *kDelay = "delay"; -/** Transaction message. */ -static constexpr const char *kTransaction = "transaction"; -} // namespace MessagingRocketmqMessageTypeValues - -namespace RpcSystemValues -{ -/** gRPC. */ -static constexpr const char *kGrpc = "grpc"; -/** Java RMI. */ -static constexpr const char *kJavaRmi = "java_rmi"; -/** .NET WCF. */ -static constexpr const char *kDotnetWcf = "dotnet_wcf"; -/** Apache Dubbo. */ -static constexpr const char *kApacheDubbo = "apache_dubbo"; -/** Connect RPC. */ -static constexpr const char *kConnectRpc = "connect_rpc"; -} // namespace RpcSystemValues - -namespace RpcGrpcStatusCodeValues -{ -/** OK. */ -static constexpr const int kOk = 0; -/** CANCELLED. */ -static constexpr const int kCancelled = 1; -/** UNKNOWN. */ -static constexpr const int kUnknown = 2; -/** INVALID_ARGUMENT. */ -static constexpr const int kInvalidArgument = 3; -/** DEADLINE_EXCEEDED. */ -static constexpr const int kDeadlineExceeded = 4; -/** NOT_FOUND. */ -static constexpr const int kNotFound = 5; -/** ALREADY_EXISTS. */ -static constexpr const int kAlreadyExists = 6; -/** PERMISSION_DENIED. */ -static constexpr const int kPermissionDenied = 7; -/** RESOURCE_EXHAUSTED. */ -static constexpr const int kResourceExhausted = 8; -/** FAILED_PRECONDITION. */ -static constexpr const int kFailedPrecondition = 9; -/** ABORTED. */ -static constexpr const int kAborted = 10; -/** OUT_OF_RANGE. */ -static constexpr const int kOutOfRange = 11; -/** UNIMPLEMENTED. */ -static constexpr const int kUnimplemented = 12; -/** INTERNAL. */ -static constexpr const int kInternal = 13; -/** UNAVAILABLE. */ -static constexpr const int kUnavailable = 14; -/** DATA_LOSS. */ -static constexpr const int kDataLoss = 15; -/** UNAUTHENTICATED. */ -static constexpr const int kUnauthenticated = 16; -} // namespace RpcGrpcStatusCodeValues - namespace MessageTypeValues { /** sent. */ @@ -2306,42 +2393,6 @@ static constexpr const char *kSent = "SENT"; static constexpr const char *kReceived = "RECEIVED"; } // namespace MessageTypeValues -namespace RpcConnectRpcErrorCodeValues -{ -/** cancelled. */ -static constexpr const char *kCancelled = "cancelled"; -/** unknown. */ -static constexpr const char *kUnknown = "unknown"; -/** invalid_argument. */ -static constexpr const char *kInvalidArgument = "invalid_argument"; -/** deadline_exceeded. */ -static constexpr const char *kDeadlineExceeded = "deadline_exceeded"; -/** not_found. */ -static constexpr const char *kNotFound = "not_found"; -/** already_exists. */ -static constexpr const char *kAlreadyExists = "already_exists"; -/** permission_denied. */ -static constexpr const char *kPermissionDenied = "permission_denied"; -/** resource_exhausted. */ -static constexpr const char *kResourceExhausted = "resource_exhausted"; -/** failed_precondition. */ -static constexpr const char *kFailedPrecondition = "failed_precondition"; -/** aborted. */ -static constexpr const char *kAborted = "aborted"; -/** out_of_range. */ -static constexpr const char *kOutOfRange = "out_of_range"; -/** unimplemented. */ -static constexpr const char *kUnimplemented = "unimplemented"; -/** internal. */ -static constexpr const char *kInternal = "internal"; -/** unavailable. */ -static constexpr const char *kUnavailable = "unavailable"; -/** data_loss. */ -static constexpr const char *kDataLoss = "data_loss"; -/** unauthenticated. */ -static constexpr const char *kUnauthenticated = "unauthenticated"; -} // namespace RpcConnectRpcErrorCodeValues - } // namespace SemanticConventions } // namespace trace OPENTELEMETRY_END_NAMESPACE diff --git a/buildscripts/semantic-convention/generate.sh b/buildscripts/semantic-convention/generate.sh index daa5131dc5..401e6daf60 100755 --- a/buildscripts/semantic-convention/generate.sh +++ b/buildscripts/semantic-convention/generate.sh @@ -18,10 +18,10 @@ ROOT_DIR="${SCRIPT_DIR}/../../" # https://github.com/open-telemetry/opentelemetry-specification # Repository from 1.21.0: # https://github.com/open-telemetry/semantic-conventions -SEMCONV_VERSION=1.22.0 +SEMCONV_VERSION=1.23.1 # repository: https://github.com/open-telemetry/build-tools -GENERATOR_VERSION=0.22.0 +GENERATOR_VERSION=0.23.0 SPEC_VERSION=v$SEMCONV_VERSION SCHEMA_URL=https://opentelemetry.io/schemas/$SEMCONV_VERSION diff --git a/sdk/include/opentelemetry/sdk/resource/semantic_conventions.h b/sdk/include/opentelemetry/sdk/resource/semantic_conventions.h index 1b45f80c36..37ad328ae5 100644 --- a/sdk/include/opentelemetry/sdk/resource/semantic_conventions.h +++ b/sdk/include/opentelemetry/sdk/resource/semantic_conventions.h @@ -24,60 +24,7 @@ namespace SemanticConventions /** * The URL of the OpenTelemetry schema for these keys and values. */ -static constexpr const char *kSchemaUrl = "https://opentelemetry.io/schemas/1.22.0"; - -/** - * Uniquely identifies the framework API revision offered by a version ({@code os.version}) of the - * android operating system. More information can be found here. - */ -static constexpr const char *kAndroidOsApiLevel = "android.os.api_level"; - -/** - * Array of brand name and version separated by a space - * - *

    Notes: -

    • This value is intended to be taken from the UA client hints API ({@code - navigator.userAgentData.brands}).
    - */ -static constexpr const char *kBrowserBrands = "browser.brands"; - -/** - * Preferred language of the user using the browser - * - *

    Notes: -

    • This value is intended to be taken from the Navigator API {@code - navigator.language}.
    - */ -static constexpr const char *kBrowserLanguage = "browser.language"; - -/** - * A boolean that is true if the browser is running on a mobile device - * - *

    Notes: -

    • This value is intended to be taken from the UA client hints API ({@code - navigator.userAgentData.mobile}). If unavailable, this attribute SHOULD be left unset.
    - */ -static constexpr const char *kBrowserMobile = "browser.mobile"; - -/** - * The platform on which the browser is running - * - *

    Notes: -

    • This value is intended to be taken from the UA client hints API ({@code -navigator.userAgentData.platform}). If unavailable, the legacy {@code navigator.platform} API SHOULD -NOT be used instead and this attribute SHOULD be left unset in order for the values to be -consistent. The list of possible values is defined in the W3C User-Agent Client Hints -specification. Note that some (but not all) of these values can overlap with values in the {@code os.type} and {@code os.name} attributes. However, for consistency, the -values in the {@code browser.platform} attribute should capture the exact value that the user agent -provides.
    - */ -static constexpr const char *kBrowserPlatform = "browser.platform"; +static constexpr const char *kSchemaUrl = "https://opentelemetry.io/schemas/1.23.1"; /** * The cloud account ID the resource is assigned to. @@ -115,7 +62,7 @@ static constexpr const char *kCloudProvider = "cloud.provider"; */ @@ -124,7 +71,7 @@ static constexpr const char *kCloudRegion = "cloud.region"; /** * Cloud provider-specific native identifier of the monitored cloud resource (e.g. an ARN on AWS, a -fully qualified +fully qualified resource ID on Azure, a full resource name on GCP) @@ -142,8 +89,8 @@ the resolved function version, as the same runtime instance may be invokable wit aliases.
  • GCP: The URI of the resource
  • Azure: The Fully Qualified -Resource ID of the invoked function, not the function app, having the form +href="https://docs.microsoft.com/rest/api/resources/resources/get-by-id">Fully Qualified Resource +ID of the invoked function, not the function app, having the form {@code /subscriptions//resourceGroups//providers/Microsoft.Web/sites//functions/}. This means that a span attribute MUST be used, as an Azure function app can host multiple functions @@ -152,6 +99,149 @@ that would usually share a TracerProvider.
  • */ static constexpr const char *kCloudResourceId = "cloud.resource_id"; +/** + * The command used to run the container (i.e. the command name). + * + *

    Notes: +

    • If using embedded credentials or sensitive data, it is recommended to remove them to + prevent potential leakage.
    + */ +static constexpr const char *kContainerCommand = "container.command"; + +/** + * All the command arguments (including the command/executable itself) run by the container. [2] + */ +static constexpr const char *kContainerCommandArgs = "container.command_args"; + +/** + * The full command run by the container as a single string representing the full command. [2] + */ +static constexpr const char *kContainerCommandLine = "container.command_line"; + +/** + * Container ID. Usually a UUID, as for example used to identify Docker + * containers. The UUID might be abbreviated. + */ +static constexpr const char *kContainerId = "container.id"; + +/** + * Runtime specific image identifier. Usually a hash algorithm followed by a UUID. + * + *

    Notes: +

    • Docker defines a sha256 of the image id; {@code container.image.id} corresponds to the +{@code Image} field from the Docker container inspect API +endpoint. K8s defines a link to the container registry repository with digest {@code "imageID": +"registry.azurecr.io +/namespace/service/dockerfile@sha256:bdeabd40c3a8a492eaf9e8e44d0ebbb84bac7ee25ac0cf8a7159d25f62555625"}. +The ID is assinged by the container runtime and can vary in different environments. Consider using +{@code oci.manifest.digest} if it is important to identify the same image in different +environments/runtimes.
    + */ +static constexpr const char *kContainerImageId = "container.image.id"; + +/** + * Name of the image the container was built on. + */ +static constexpr const char *kContainerImageName = "container.image.name"; + +/** + * Repo digests of the container image as provided by the container runtime. + * + *

    Notes: +

    • Docker and CRI + report those under the {@code RepoDigests} field.
    + */ +static constexpr const char *kContainerImageRepoDigests = "container.image.repo_digests"; + +/** + * Container image tags. An example can be found in Docker Image + * Inspect. Should be only the {@code } section of the full name for example from {@code + * registry.example.com/my-org/my-image:}. + */ +static constexpr const char *kContainerImageTags = "container.image.tags"; + +/** + * Container name used by container runtime. + */ +static constexpr const char *kContainerName = "container.name"; + +/** + * The container runtime managing this container. + */ +static constexpr const char *kContainerRuntime = "container.runtime"; + +/** + * The digest of the OCI image manifest. For container images specifically is the digest by which +the container image is known. + * + *

    Notes: +

    + */ +static constexpr const char *kOciManifestDigest = "oci.manifest.digest"; + +/** + * Uniquely identifies the framework API revision offered by a version ({@code os.version}) of the + * android operating system. More information can be found here. + */ +static constexpr const char *kAndroidOsApiLevel = "android.os.api_level"; + +/** + * Array of brand name and version separated by a space + * + *

    Notes: +

    • This value is intended to be taken from the UA client hints API ({@code + navigator.userAgentData.brands}).
    + */ +static constexpr const char *kBrowserBrands = "browser.brands"; + +/** + * Preferred language of the user using the browser + * + *

    Notes: +

    • This value is intended to be taken from the Navigator API {@code + navigator.language}.
    + */ +static constexpr const char *kBrowserLanguage = "browser.language"; + +/** + * A boolean that is true if the browser is running on a mobile device + * + *

    Notes: +

    • This value is intended to be taken from the UA client hints API ({@code + navigator.userAgentData.mobile}). If unavailable, this attribute SHOULD be left unset.
    + */ +static constexpr const char *kBrowserMobile = "browser.mobile"; + +/** + * The platform on which the browser is running + * + *

    Notes: +

    • This value is intended to be taken from the UA client hints API ({@code +navigator.userAgentData.platform}). If unavailable, the legacy {@code navigator.platform} API SHOULD +NOT be used instead and this attribute SHOULD be left unset in order for the values to be +consistent. The list of possible values is defined in the W3C User-Agent Client Hints +specification. Note that some (but not all) of these values can overlap with values in the {@code os.type} and {@code os.name} attributes. However, for consistency, the +values in the {@code browser.platform} attribute should capture the exact value that the user agent +provides.
    + */ +static constexpr const char *kBrowserPlatform = "browser.platform"; + /** * The ARN of an ECS cluster. @@ -276,83 +366,7 @@ static constexpr const char *kHerokuReleaseCommit = "heroku.release.commit"; static constexpr const char *kHerokuReleaseCreationTimestamp = "heroku.release.creation_timestamp"; /** - * The command used to run the container (i.e. the command name). - * - *

    Notes: -

    • If using embedded credentials or sensitive data, it is recommended to remove them to - prevent potential leakage.
    - */ -static constexpr const char *kContainerCommand = "container.command"; - -/** - * All the command arguments (including the command/executable itself) run by the container. [2] - */ -static constexpr const char *kContainerCommandArgs = "container.command_args"; - -/** - * The full command run by the container as a single string representing the full command. [2] - */ -static constexpr const char *kContainerCommandLine = "container.command_line"; - -/** - * Container ID. Usually a UUID, as for example used to identify Docker - * containers. The UUID might be abbreviated. - */ -static constexpr const char *kContainerId = "container.id"; - -/** - * Runtime specific image identifier. Usually a hash algorithm followed by a UUID. - * - *

    Notes: -

    • Docker defines a sha256 of the image id; {@code container.image.id} corresponds to the -{@code Image} field from the Docker container inspect API -endpoint. K8s defines a link to the container registry repository with digest {@code "imageID": -"registry.azurecr.io -/namespace/service/dockerfile@sha256:bdeabd40c3a8a492eaf9e8e44d0ebbb84bac7ee25ac0cf8a7159d25f62555625"}. -The ID is assinged by the container runtime and can vary in different environments. Consider using -{@code oci.manifest.digest} if it is important to identify the same image in different -environments/runtimes.
    - */ -static constexpr const char *kContainerImageId = "container.image.id"; - -/** - * Name of the image the container was built on. - */ -static constexpr const char *kContainerImageName = "container.image.name"; - -/** - * Repo digests of the container image as provided by the container runtime. - * - *

    Notes: -

    • Docker and CRI - report those under the {@code RepoDigests} field.
    - */ -static constexpr const char *kContainerImageRepoDigests = "container.image.repo_digests"; - -/** - * Container image tags. An example can be found in Docker Image - * Inspect. Should be only the {@code } section of the full name for example from {@code - * registry.example.com/my-org/my-image:}. - */ -static constexpr const char *kContainerImageTags = "container.image.tags"; - -/** - * Container name used by container runtime. - */ -static constexpr const char *kContainerName = "container.name"; - -/** - * The container runtime managing this container. - */ -static constexpr const char *kContainerRuntime = "container.runtime"; - -/** - * Name of the deployment + * Name of the deployment * environment (aka deployment tier). */ static constexpr const char *kDeploymentEnvironment = "deployment.environment"; @@ -499,6 +513,17 @@ static constexpr const char *kHostImageVersion = "host.image.version"; */ static constexpr const char *kHostIp = "host.ip"; +/** + * Available MAC addresses of the host, excluding loopback interfaces. + * + *

    Notes: +

    • MAC Addresses MUST be represented in IEEE RA + hexadecimal form: as hyphen-separated octets in uppercase hexadecimal form from most to least + significant.
    + */ +static constexpr const char *kHostMac = "host.mac"; + /** * Name of the host. On Unix systems, it may contain what the hostname command returns, or the fully * qualified hostname, or another name specified by the user. @@ -555,7 +580,7 @@ static constexpr const char *kK8sClusterName = "k8s.cluster.name"; * A pseudo-ID for the cluster, set to the UID of the {@code kube-system} namespace. * *

    Notes: -

    • K8s does not have support for obtaining a cluster ID. If this is ever +
      • K8s doesn't have support for obtaining a cluster ID. If this is ever added, we will recommend collecting the {@code k8s.cluster.uid} through the official APIs. In the meantime, we are able to use the {@code uid} of the {@code kube-system} namespace as a proxy for cluster ID. Read on for the @@ -672,20 +697,6 @@ static constexpr const char *kK8sCronjobName = "k8s.cronjob.name"; */ static constexpr const char *kK8sCronjobUid = "k8s.cronjob.uid"; -/** - * The digest of the OCI image manifest. For container images specifically is the digest by which -the container image is known. - * - *

        Notes: -

        - */ -static constexpr const char *kOciManifestDigest = "oci.manifest.digest"; - /** * Unique identifier for a particular build or compilation of the operating system. */ From d91e5bac17732b7c233defe789b26c474f66be0b Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Tue, 5 Dec 2023 13:46:01 -0800 Subject: [PATCH 24/31] [BUILD] Use fully qualified references to trace/common namespace (#2424) --- .../trace/span_context_kv_iterable_view.h | 2 +- .../opentelemetry/exporters/etw/etw_logger.h | 13 ++-- .../exporters/etw/etw_properties.h | 62 +++++++-------- .../exporters/etw/etw_provider.h | 2 +- .../opentelemetry/exporters/etw/etw_tracer.h | 77 ++++++++++--------- .../exporters/otlp/otlp_recordable.h | 13 ++-- .../exporters/zipkin/recordable.h | 10 +-- .../sdk/common/global_log_handler.h | 6 +- .../instrumentation_scope.h | 3 +- .../sdk/logs/batch_log_record_processor.h | 2 +- .../exemplar/fixed_size_exemplar_reservoir.h | 4 +- .../exemplar/histogram_exemplar_reservoir.h | 2 +- .../sdk/metrics/exemplar/reservoir.h | 2 +- .../sdk/metrics/state/attributes_hashmap.h | 2 +- .../sdk/trace/batch_span_processor.h | 2 +- .../opentelemetry/sdk/trace/span_data.h | 15 ++-- sdk/src/trace/span.h | 2 +- 17 files changed, 116 insertions(+), 103 deletions(-) diff --git a/api/include/opentelemetry/trace/span_context_kv_iterable_view.h b/api/include/opentelemetry/trace/span_context_kv_iterable_view.h index 6a21aaf54a..8c4584dc2e 100644 --- a/api/include/opentelemetry/trace/span_context_kv_iterable_view.h +++ b/api/include/opentelemetry/trace/span_context_kv_iterable_view.h @@ -24,7 +24,7 @@ namespace trace namespace detail { template -inline void take_span_context_kv(SpanContext, common::KeyValueIterableView) +inline void take_span_context_kv(SpanContext, opentelemetry::common::KeyValueIterableView) {} template ::value> * = nullptr> diff --git a/exporters/etw/include/opentelemetry/exporters/etw/etw_logger.h b/exporters/etw/include/opentelemetry/exporters/etw/etw_logger.h index 819caf7105..494211ea0b 100644 --- a/exporters/etw/include/opentelemetry/exporters/etw/etw_logger.h +++ b/exporters/etw/include/opentelemetry/exporters/etw/etw_logger.h @@ -229,7 +229,7 @@ class Logger : public opentelemetry::logs::Logger opentelemetry::trace::TraceId trace_id, opentelemetry::trace::SpanId span_id, opentelemetry::trace::TraceFlags trace_flags, - common::SystemTimestamp timestamp) noexcept + opentelemetry::common::SystemTimestamp timestamp) noexcept { UNREFERENCED_PARAMETER(trace_flags); @@ -358,11 +358,12 @@ class LoggerProvider : public opentelemetry::logs::LoggerProvider } nostd::shared_ptr GetLogger( - nostd::string_view logger_name, - nostd::string_view library_name, - nostd::string_view version = "", - nostd::string_view schema_url = "", - const common::KeyValueIterable &attributes = common::NoopKeyValueIterable()) override + opentelemetry::nostd::string_view logger_name, + opentelemetry::nostd::string_view library_name, + opentelemetry::nostd::string_view version = "", + opentelemetry::nostd::string_view schema_url = "", + const opentelemetry::common::KeyValueIterable &attributes = + opentelemetry::common::NoopKeyValueIterable()) override { UNREFERENCED_PARAMETER(library_name); UNREFERENCED_PARAMETER(version); diff --git a/exporters/etw/include/opentelemetry/exporters/etw/etw_properties.h b/exporters/etw/include/opentelemetry/exporters/etw/etw_properties.h index 3cf365c8a0..f35b5f11b4 100644 --- a/exporters/etw/include/opentelemetry/exporters/etw/etw_properties.h +++ b/exporters/etw/include/opentelemetry/exporters/etw/etw_properties.h @@ -195,67 +195,67 @@ class PropertyValue : public PropertyVariant * @brief Convert non-owning common::AttributeValue to owning PropertyValue. * @return */ - PropertyValue &FromAttributeValue(const common::AttributeValue &v) + PropertyValue &FromAttributeValue(const opentelemetry::common::AttributeValue &v) { switch (v.index()) { - case common::AttributeType::kTypeBool: + case opentelemetry::common::AttributeType::kTypeBool: PropertyVariant::operator=(nostd::get(v)); break; - case common::AttributeType::kTypeInt: + case opentelemetry::common::AttributeType::kTypeInt: PropertyVariant::operator=(nostd::get(v)); break; - case common::AttributeType::kTypeInt64: + case opentelemetry::common::AttributeType::kTypeInt64: PropertyVariant::operator=(nostd::get(v)); break; - case common::AttributeType::kTypeUInt: + case opentelemetry::common::AttributeType::kTypeUInt: PropertyVariant::operator=(nostd::get(v)); break; - case common::AttributeType::kTypeUInt64: + case opentelemetry::common::AttributeType::kTypeUInt64: PropertyVariant::operator=(nostd::get(v)); break; - case common::AttributeType::kTypeDouble: + case opentelemetry::common::AttributeType::kTypeDouble: PropertyVariant::operator=(nostd::get(v)); break; - case common::AttributeType::kTypeCString: { + case opentelemetry::common::AttributeType::kTypeCString: { PropertyVariant::operator=(nostd::get(v)); break; } - case common::AttributeType::kTypeString: { + case opentelemetry::common::AttributeType::kTypeString: { PropertyVariant::operator= (std::string{nostd::string_view(nostd::get(v)).data()}); break; } - case common::AttributeType::kTypeSpanByte: + case opentelemetry::common::AttributeType::kTypeSpanByte: PropertyVariant::operator=(to_vector(nostd::get>(v))); break; - case common::AttributeType::kTypeSpanBool: + case opentelemetry::common::AttributeType::kTypeSpanBool: PropertyVariant::operator=(to_vector(nostd::get>(v))); break; - case common::AttributeType::kTypeSpanInt: + case opentelemetry::common::AttributeType::kTypeSpanInt: PropertyVariant::operator=(to_vector(nostd::get>(v))); break; - case common::AttributeType::kTypeSpanInt64: + case opentelemetry::common::AttributeType::kTypeSpanInt64: PropertyVariant::operator=(to_vector(nostd::get>(v))); break; - case common::AttributeType::kTypeSpanUInt: + case opentelemetry::common::AttributeType::kTypeSpanUInt: PropertyVariant::operator=(to_vector(nostd::get>(v))); break; - case common::AttributeType::kTypeSpanUInt64: + case opentelemetry::common::AttributeType::kTypeSpanUInt64: PropertyVariant::operator=(to_vector(nostd::get>(v))); break; - case common::AttributeType::kTypeSpanDouble: + case opentelemetry::common::AttributeType::kTypeSpanDouble: PropertyVariant::operator=(to_vector(nostd::get>(v))); break; - case common::AttributeType::kTypeSpanString: + case opentelemetry::common::AttributeType::kTypeSpanString: PropertyVariant::operator=(to_vector(nostd::get>(v))); break; @@ -269,9 +269,9 @@ class PropertyValue : public PropertyVariant * @brief Convert owning PropertyValue to non-owning common::AttributeValue * @param other */ - common::AttributeValue ToAttributeValue() const + opentelemetry::common::AttributeValue ToAttributeValue() const { - common::AttributeValue value; + opentelemetry::common::AttributeValue value; switch (this->index()) { @@ -353,7 +353,7 @@ using PropertyValueMap = std::map; /** * @brief Map of PropertyValue with common::KeyValueIterable interface. */ -class Properties : public common::KeyValueIterable, public PropertyValueMap +class Properties : public opentelemetry::common::KeyValueIterable, public PropertyValueMap { /** @@ -404,19 +404,20 @@ class Properties : public common::KeyValueIterable, public PropertyValueMap * container. * */ - Properties(const common::KeyValueIterable &other) { (*this) = other; } + Properties(const opentelemetry::common::KeyValueIterable &other) { (*this) = other; } /** * @brief PropertyValueMap assignment operator. */ - Properties &operator=(const common::KeyValueIterable &other) + Properties &operator=(const opentelemetry::common::KeyValueIterable &other) { clear(); - other.ForEachKeyValue([&](nostd::string_view key, common::AttributeValue value) noexcept { - std::string k(key.data(), key.length()); - (*this)[k].FromAttributeValue(value); - return true; - }); + other.ForEachKeyValue( + [&](nostd::string_view key, opentelemetry::common::AttributeValue value) noexcept { + std::string k(key.data(), key.length()); + (*this)[k].FromAttributeValue(value); + return true; + }); return (*this); } @@ -431,12 +432,13 @@ class Properties : public common::KeyValueIterable, public PropertyValueMap * the iteration is aborted. * @return true if every key-value pair was iterated over */ - bool ForEachKeyValue(nostd::function_ref - callback) const noexcept override + bool ForEachKeyValue( + nostd::function_ref callback) + const noexcept override { for (const auto &kv : (*this)) { - const common::AttributeValue &value = kv.second.ToAttributeValue(); + const opentelemetry::common::AttributeValue &value = kv.second.ToAttributeValue(); if (!callback(nostd::string_view{kv.first}, value)) { return false; diff --git a/exporters/etw/include/opentelemetry/exporters/etw/etw_provider.h b/exporters/etw/include/opentelemetry/exporters/etw/etw_provider.h index 51cca03a60..4d7e37a98c 100644 --- a/exporters/etw/include/opentelemetry/exporters/etw/etw_provider.h +++ b/exporters/etw/include/opentelemetry/exporters/etw/etw_provider.h @@ -344,7 +344,7 @@ class ETWProvider } # if HAVE_TYPE_GUID // TODO: consider adding UUID/GUID to spec - case common::AttributeType::TYPE_GUID: { + case opentelemetry::common::AttributeType::TYPE_GUID: { auto temp = nostd::get(value); // TODO: add transform from GUID type to string? jObj[name] = temp; diff --git a/exporters/etw/include/opentelemetry/exporters/etw/etw_tracer.h b/exporters/etw/include/opentelemetry/exporters/etw/etw_tracer.h index 6601f850df..454f6cff5a 100644 --- a/exporters/etw/include/opentelemetry/exporters/etw/etw_tracer.h +++ b/exporters/etw/include/opentelemetry/exporters/etw/etw_tracer.h @@ -107,7 +107,7 @@ std::string GetName(T &t) * @return Span Start timestamp */ template -common::SystemTimestamp GetStartTime(T &t) +opentelemetry::common::SystemTimestamp GetStartTime(T &t) { return t.GetStartTime(); } @@ -119,7 +119,7 @@ common::SystemTimestamp GetStartTime(T &t) * @return Span Stop timestamp */ template -common::SystemTimestamp GetEndTime(T &t) +opentelemetry::common::SystemTimestamp GetEndTime(T &t) { return t.GetEndTime(); } @@ -161,7 +161,7 @@ void UpdateStatus(T &t, Properties &props) */ class Tracer : public opentelemetry::trace::Tracer, - public std::enable_shared_from_this + public std::enable_shared_from_this { /** @@ -214,16 +214,16 @@ class Tracer : public opentelemetry::trace::Tracer, { size_t idx = 0; std::string linksValue; - links.ForEachKeyValue( - [&](opentelemetry::trace::SpanContext ctx, const common::KeyValueIterable &) { - if (!linksValue.empty()) - { - linksValue += ','; - linksValue += ToLowerBase16(ctx.span_id()); - } - idx++; - return true; - }); + links.ForEachKeyValue([&](opentelemetry::trace::SpanContext ctx, + const opentelemetry::common::KeyValueIterable &) { + if (!linksValue.empty()) + { + linksValue += ','; + linksValue += ToLowerBase16(ctx.span_id()); + } + idx++; + return true; + }); attributes[ETW_FIELD_SPAN_LINKS] = linksValue; } } @@ -414,7 +414,7 @@ class Tracer : public opentelemetry::trace::Tracer, */ nostd::shared_ptr StartSpan( nostd::string_view name, - const common::KeyValueIterable &attributes, + const opentelemetry::common::KeyValueIterable &attributes, const opentelemetry::trace::SpanContextKeyValueIterable &links, const opentelemetry::trace::StartSpanOptions &options = {}) noexcept override { @@ -425,8 +425,9 @@ class Tracer : public opentelemetry::trace::Tracer, Properties evtCopy = attributes; return StartSpan(name, evtCopy, links, options); #else // OPENTELEMETRY_RTTI_ENABLED is defined - common::KeyValueIterable &attribs = const_cast(attributes); - Properties *evt = dynamic_cast(&attribs); + opentelemetry::common::KeyValueIterable &attribs = + const_cast(attributes); + Properties *evt = dynamic_cast(&attribs); if (evt != nullptr) { // Pass as a reference to original modifyable collection without creating a copy @@ -491,8 +492,9 @@ class Tracer : public opentelemetry::trace::Tracer, if (sampling_result.decision == sdk::trace::Decision::DROP) { - auto noopSpan = nostd::shared_ptr{ - new (std::nothrow) trace::NoopSpan(this->shared_from_this(), std::move(spanContext))}; + auto noopSpan = nostd::shared_ptr{ + new (std::nothrow) + opentelemetry::trace::NoopSpan(this->shared_from_this(), std::move(spanContext))}; return noopSpan; } @@ -602,9 +604,9 @@ class Tracer : public opentelemetry::trace::Tracer, * @return */ void AddEvent(opentelemetry::trace::Span &span, - nostd::string_view name, - common::SystemTimestamp timestamp, - const common::KeyValueIterable &attributes) noexcept + opentelemetry::nostd::string_view name, + opentelemetry::common::SystemTimestamp timestamp, + const opentelemetry::common::KeyValueIterable &attributes) noexcept { // If RTTI is enabled by compiler, the below code modifies the attributes object passed as arg, // which is sometime not desirable, set OPENTELEMETRY_NOT_USE_RTTI in application @@ -614,8 +616,9 @@ class Tracer : public opentelemetry::trace::Tracer, Properties evtCopy = attributes; return AddEvent(span, name, timestamp, evtCopy); #else // OPENTELEMETRY_RTTI_ENABLED is defined - common::KeyValueIterable &attribs = const_cast(attributes); - Properties *evt = dynamic_cast(&attribs); + opentelemetry::common::KeyValueIterable &attribs = + const_cast(attributes); + Properties *evt = dynamic_cast(&attribs); if (evt != nullptr) { // Pass as a reference to original modifyable collection without creating a copy @@ -635,8 +638,8 @@ class Tracer : public opentelemetry::trace::Tracer, * @return */ void AddEvent(opentelemetry::trace::Span &span, - nostd::string_view name, - common::SystemTimestamp timestamp, + opentelemetry::nostd::string_view name, + opentelemetry::common::SystemTimestamp timestamp, Properties &evt) noexcept { // TODO: respect originating timestamp. Do we need to reserve @@ -693,8 +696,8 @@ class Tracer : public opentelemetry::trace::Tracer, * @return */ void AddEvent(opentelemetry::trace::Span &span, - nostd::string_view name, - common::SystemTimestamp timestamp) noexcept + opentelemetry::nostd::string_view name, + opentelemetry::common::SystemTimestamp timestamp) noexcept { AddEvent(span, name, timestamp, sdk::GetEmptyAttributes()); } @@ -728,8 +731,8 @@ class Span : public opentelemetry::trace::Span */ Properties attributes_; - common::SystemTimestamp start_time_; - common::SystemTimestamp end_time_; + opentelemetry::common::SystemTimestamp start_time_; + opentelemetry::common::SystemTimestamp end_time_; opentelemetry::trace::StatusCode status_code_{opentelemetry::trace::StatusCode::kUnset}; std::string status_description_; @@ -794,13 +797,13 @@ class Span : public opentelemetry::trace::Span * @brief Get start time of this Span. * @return */ - common::SystemTimestamp GetStartTime() { return start_time_; } + opentelemetry::common::SystemTimestamp GetStartTime() { return start_time_; } /** * @brief Get end time of this Span. * @return */ - common::SystemTimestamp GetEndTime() { return end_time_; } + opentelemetry::common::SystemTimestamp GetEndTime() { return end_time_; } /** * @brief Get Span Name. @@ -849,7 +852,8 @@ class Span : public opentelemetry::trace::Span * @param timestamp * @return */ - void AddEvent(nostd::string_view name, common::SystemTimestamp timestamp) noexcept override + void AddEvent(nostd::string_view name, + opentelemetry::common::SystemTimestamp timestamp) noexcept override { owner_.AddEvent(*this, name, timestamp); } @@ -861,9 +865,9 @@ class Span : public opentelemetry::trace::Span * @param attributes Event attributes. * @return */ - void AddEvent(nostd::string_view name, - common::SystemTimestamp timestamp, - const common::KeyValueIterable &attributes) noexcept override + void AddEvent(opentelemetry::nostd::string_view name, + opentelemetry::common::SystemTimestamp timestamp, + const opentelemetry::common::KeyValueIterable &attributes) noexcept override { owner_.AddEvent(*this, name, timestamp, attributes); } @@ -901,7 +905,8 @@ class Span : public opentelemetry::trace::Span * @param value * @return */ - void SetAttribute(nostd::string_view key, const common::AttributeValue &value) noexcept override + void SetAttribute(nostd::string_view key, + const opentelemetry::common::AttributeValue &value) noexcept override { // don't override fields propagated from span data. if (key == ETW_FIELD_NAME || key == ETW_FIELD_SPAN_ID || key == ETW_FIELD_TRACE_ID || diff --git a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_recordable.h b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_recordable.h index bc505a959b..76e8856330 100644 --- a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_recordable.h +++ b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_recordable.h @@ -38,17 +38,18 @@ class OtlpRecordable final : public opentelemetry::sdk::trace::Recordable void SetIdentity(const opentelemetry::trace::SpanContext &span_context, opentelemetry::trace::SpanId parent_span_id) noexcept override; - void SetAttribute(nostd::string_view key, + void SetAttribute(opentelemetry::nostd::string_view key, const opentelemetry::common::AttributeValue &value) noexcept override; - void AddEvent(nostd::string_view name, - common::SystemTimestamp timestamp, - const common::KeyValueIterable &attributes) noexcept override; + void AddEvent(opentelemetry::nostd::string_view name, + opentelemetry::common::SystemTimestamp timestamp, + const opentelemetry::common::KeyValueIterable &attributes) noexcept override; void AddLink(const opentelemetry::trace::SpanContext &span_context, - const common::KeyValueIterable &attributes) noexcept override; + const opentelemetry::common::KeyValueIterable &attributes) noexcept override; - void SetStatus(trace::StatusCode code, nostd::string_view description) noexcept override; + void SetStatus(opentelemetry::trace::StatusCode code, + nostd::string_view description) noexcept override; void SetName(nostd::string_view name) noexcept override; diff --git a/exporters/zipkin/include/opentelemetry/exporters/zipkin/recordable.h b/exporters/zipkin/include/opentelemetry/exporters/zipkin/recordable.h index 78079adee7..64894082fd 100644 --- a/exporters/zipkin/include/opentelemetry/exporters/zipkin/recordable.h +++ b/exporters/zipkin/include/opentelemetry/exporters/zipkin/recordable.h @@ -24,15 +24,15 @@ class Recordable final : public sdk::trace::Recordable void SetIdentity(const opentelemetry::trace::SpanContext &span_context, opentelemetry::trace::SpanId parent_span_id) noexcept override; - void SetAttribute(nostd::string_view key, + void SetAttribute(opentelemetry::nostd::string_view key, const opentelemetry::common::AttributeValue &value) noexcept override; - void AddEvent(nostd::string_view name, - common::SystemTimestamp timestamp, - const common::KeyValueIterable &attributes) noexcept override; + void AddEvent(opentelemetry::nostd::string_view name, + opentelemetry::common::SystemTimestamp timestamp, + const opentelemetry::common::KeyValueIterable &attributes) noexcept override; void AddLink(const opentelemetry::trace::SpanContext &span_context, - const common::KeyValueIterable &attributes) noexcept override; + const opentelemetry::common::KeyValueIterable &attributes) noexcept override; void SetStatus(opentelemetry::trace::StatusCode code, nostd::string_view description) noexcept override; diff --git a/sdk/include/opentelemetry/sdk/common/global_log_handler.h b/sdk/include/opentelemetry/sdk/common/global_log_handler.h index a36bd4a8a3..14c956b96e 100644 --- a/sdk/include/opentelemetry/sdk/common/global_log_handler.h +++ b/sdk/include/opentelemetry/sdk/common/global_log_handler.h @@ -60,7 +60,7 @@ class LogHandler const char *file, int line, const char *msg, - const sdk::common::AttributeMap &attributes) noexcept = 0; + const opentelemetry::sdk::common::AttributeMap &attributes) noexcept = 0; }; class DefaultLogHandler : public LogHandler @@ -70,7 +70,7 @@ class DefaultLogHandler : public LogHandler const char *file, int line, const char *msg, - const sdk::common::AttributeMap &attributes) noexcept override; + const opentelemetry::sdk::common::AttributeMap &attributes) noexcept override; }; class NoopLogHandler : public LogHandler @@ -80,7 +80,7 @@ class NoopLogHandler : public LogHandler const char *file, int line, const char *msg, - const sdk::common::AttributeMap &error_attributes) noexcept override; + const opentelemetry::sdk::common::AttributeMap &error_attributes) noexcept override; }; /** diff --git a/sdk/include/opentelemetry/sdk/instrumentationscope/instrumentation_scope.h b/sdk/include/opentelemetry/sdk/instrumentationscope/instrumentation_scope.h index 9bae218ba4..35b0dc6863 100644 --- a/sdk/include/opentelemetry/sdk/instrumentationscope/instrumentation_scope.h +++ b/sdk/include/opentelemetry/sdk/instrumentationscope/instrumentation_scope.h @@ -129,7 +129,8 @@ class InstrumentationScope void SetAttribute(nostd::string_view key, const opentelemetry::common::AttributeValue &value) noexcept { - attributes_[std::string(key)] = nostd::visit(common::AttributeConverter(), value); + attributes_[std::string(key)] = + nostd::visit(opentelemetry::sdk::common::AttributeConverter(), value); } private: diff --git a/sdk/include/opentelemetry/sdk/logs/batch_log_record_processor.h b/sdk/include/opentelemetry/sdk/logs/batch_log_record_processor.h index d0b3577491..e93ebf3d6b 100644 --- a/sdk/include/opentelemetry/sdk/logs/batch_log_record_processor.h +++ b/sdk/include/opentelemetry/sdk/logs/batch_log_record_processor.h @@ -143,7 +143,7 @@ class BatchLogRecordProcessor : public LogRecordProcessor const std::chrono::milliseconds scheduled_delay_millis_; const size_t max_export_batch_size_; /* The buffer/queue to which the ended logs are added */ - common::CircularBuffer buffer_; + opentelemetry::sdk::common::CircularBuffer buffer_; std::shared_ptr synchronization_data_; diff --git a/sdk/include/opentelemetry/sdk/metrics/exemplar/fixed_size_exemplar_reservoir.h b/sdk/include/opentelemetry/sdk/metrics/exemplar/fixed_size_exemplar_reservoir.h index 76f5742ca2..509b2affce 100644 --- a/sdk/include/opentelemetry/sdk/metrics/exemplar/fixed_size_exemplar_reservoir.h +++ b/sdk/include/opentelemetry/sdk/metrics/exemplar/fixed_size_exemplar_reservoir.h @@ -27,7 +27,7 @@ class FixedSizeExemplarReservoir : public ExemplarReservoir FixedSizeExemplarReservoir(size_t size, std::shared_ptr reservoir_cell_selector, std::shared_ptr (ReservoirCell::*map_and_reset_cell)( - const common::OrderedAttributeMap &attributes)) + const opentelemetry::sdk::common::OrderedAttributeMap &attributes)) : storage_(size), reservoir_cell_selector_(reservoir_cell_selector), map_and_reset_cell_(map_and_reset_cell) @@ -96,7 +96,7 @@ class FixedSizeExemplarReservoir : public ExemplarReservoir std::vector storage_; std::shared_ptr reservoir_cell_selector_; std::shared_ptr (ReservoirCell::*map_and_reset_cell_)( - const common::OrderedAttributeMap &attributes); + const opentelemetry::sdk::common::OrderedAttributeMap &attributes); }; } // namespace metrics diff --git a/sdk/include/opentelemetry/sdk/metrics/exemplar/histogram_exemplar_reservoir.h b/sdk/include/opentelemetry/sdk/metrics/exemplar/histogram_exemplar_reservoir.h index bbc032df3b..6f9bf803f0 100644 --- a/sdk/include/opentelemetry/sdk/metrics/exemplar/histogram_exemplar_reservoir.h +++ b/sdk/include/opentelemetry/sdk/metrics/exemplar/histogram_exemplar_reservoir.h @@ -42,7 +42,7 @@ class HistogramExemplarReservoir : public FixedSizeExemplarReservoir HistogramExemplarReservoir(size_t size, std::shared_ptr reservoir_cell_selector, std::shared_ptr (ReservoirCell::*map_and_reset_cell)( - const common::OrderedAttributeMap &attributes)) + const opentelemetry::sdk::common::OrderedAttributeMap &attributes)) : FixedSizeExemplarReservoir(size, reservoir_cell_selector, map_and_reset_cell) {} diff --git a/sdk/include/opentelemetry/sdk/metrics/exemplar/reservoir.h b/sdk/include/opentelemetry/sdk/metrics/exemplar/reservoir.h index 258e099f0f..3187e0da26 100644 --- a/sdk/include/opentelemetry/sdk/metrics/exemplar/reservoir.h +++ b/sdk/include/opentelemetry/sdk/metrics/exemplar/reservoir.h @@ -72,7 +72,7 @@ class ExemplarReservoir size_t size, std::shared_ptr reservoir_cell_selector, std::shared_ptr (ReservoirCell::*map_and_reset_cell)( - const common::OrderedAttributeMap &attributes)); + const opentelemetry::sdk::common::OrderedAttributeMap &attributes)); static nostd::shared_ptr GetNoExemplarReservoir(); }; diff --git a/sdk/include/opentelemetry/sdk/metrics/state/attributes_hashmap.h b/sdk/include/opentelemetry/sdk/metrics/state/attributes_hashmap.h index 85009a9fcb..8dd820fd95 100644 --- a/sdk/include/opentelemetry/sdk/metrics/state/attributes_hashmap.h +++ b/sdk/include/opentelemetry/sdk/metrics/state/attributes_hashmap.h @@ -28,7 +28,7 @@ const std::string kAggregationCardinalityLimitOverflowError = "Maximum data points for metric stream exceeded. Entry added to overflow"; const std::string kAttributesLimitOverflowKey = "otel.metrics.overflow"; const bool kAttributesLimitOverflowValue = true; -const size_t kOverflowAttributesHash = common::GetHashForAttributeMap( +const size_t kOverflowAttributesHash = opentelemetry::sdk::common::GetHashForAttributeMap( {{kAttributesLimitOverflowKey, kAttributesLimitOverflowValue}}); // precalculated for optimization diff --git a/sdk/include/opentelemetry/sdk/trace/batch_span_processor.h b/sdk/include/opentelemetry/sdk/trace/batch_span_processor.h index b93631eafa..a748b06361 100644 --- a/sdk/include/opentelemetry/sdk/trace/batch_span_processor.h +++ b/sdk/include/opentelemetry/sdk/trace/batch_span_processor.h @@ -143,7 +143,7 @@ class BatchSpanProcessor : public SpanProcessor const size_t max_export_batch_size_; /* The buffer/queue to which the ended spans are added */ - common::CircularBuffer buffer_; + opentelemetry::sdk::common::CircularBuffer buffer_; std::shared_ptr synchronization_data_; diff --git a/sdk/include/opentelemetry/sdk/trace/span_data.h b/sdk/include/opentelemetry/sdk/trace/span_data.h index 4e1a52ce5d..ef2c57a092 100644 --- a/sdk/include/opentelemetry/sdk/trace/span_data.h +++ b/sdk/include/opentelemetry/sdk/trace/span_data.h @@ -55,7 +55,8 @@ class SpanDataEvent * Get the attributes for this event * @return the attributes for this event */ - const std::unordered_map &GetAttributes() const noexcept + const std::unordered_map + &GetAttributes() const noexcept { return attribute_map_.GetAttributes(); } @@ -63,7 +64,7 @@ class SpanDataEvent private: std::string name_; opentelemetry::common::SystemTimestamp timestamp_; - common::AttributeMap attribute_map_; + opentelemetry::sdk::common::AttributeMap attribute_map_; }; /** @@ -81,7 +82,8 @@ class SpanDataLink * Get the attributes for this link * @return the attributes for this link */ - const std::unordered_map &GetAttributes() const noexcept + const std::unordered_map + &GetAttributes() const noexcept { return attribute_map_.GetAttributes(); } @@ -94,7 +96,7 @@ class SpanDataLink private: opentelemetry::trace::SpanContext span_context_; - common::AttributeMap attribute_map_; + opentelemetry::sdk::common::AttributeMap attribute_map_; }; /** @@ -210,7 +212,8 @@ class SpanData final : public Recordable * Get the attributes for this span * @return the attributes for this span */ - const std::unordered_map &GetAttributes() const noexcept + const std::unordered_map + &GetAttributes() const noexcept { return attribute_map_.GetAttributes(); } @@ -300,7 +303,7 @@ class SpanData final : public Recordable std::string name_; opentelemetry::trace::StatusCode status_code_{opentelemetry::trace::StatusCode::kUnset}; std::string status_desc_; - common::AttributeMap attribute_map_; + opentelemetry::sdk::common::AttributeMap attribute_map_; std::vector events_; std::vector links_; opentelemetry::trace::SpanKind span_kind_{opentelemetry::trace::SpanKind::kInternal}; diff --git a/sdk/src/trace/span.h b/sdk/src/trace/span.h index eb603b9025..7fe86bd3f5 100644 --- a/sdk/src/trace/span.h +++ b/sdk/src/trace/span.h @@ -26,7 +26,7 @@ class Span final : public opentelemetry::trace::Span ~Span() override; - // trace::Span + // opentelemetry::trace::Span void SetAttribute(nostd::string_view key, const opentelemetry::common::AttributeValue &value) noexcept override; From 48e633e740007beb65394620af759436b15f10e8 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Tue, 5 Dec 2023 15:26:16 -0800 Subject: [PATCH 25/31] [API] Create root span with active span (#2427) --- api/include/opentelemetry/trace/context.h | 10 +++++++ .../opentelemetry/trace/span_metadata.h | 3 ++- .../opentelemetry/trace/span_startoptions.h | 27 +++++++++++++++++-- sdk/src/trace/tracer.cc | 7 +++++ sdk/test/trace/tracer_test.cc | 20 ++++++++++++++ 5 files changed, 64 insertions(+), 3 deletions(-) diff --git a/api/include/opentelemetry/trace/context.h b/api/include/opentelemetry/trace/context.h index b68fe9e95a..cd8395d768 100644 --- a/api/include/opentelemetry/trace/context.h +++ b/api/include/opentelemetry/trace/context.h @@ -23,6 +23,16 @@ inline nostd::shared_ptr GetSpan(const context::Context &context) noexcept return nostd::shared_ptr(new DefaultSpan(SpanContext::GetInvalid())); } +inline bool IsRootSpan(const context::Context &context) noexcept +{ + context::ContextValue is_root_span = context.GetValue(kIsRootSpanKey); + if (nostd::holds_alternative(is_root_span)) + { + return nostd::get(is_root_span); + } + return false; +} + // Set Span into explicit context inline context::Context SetSpan(context::Context &context, nostd::shared_ptr span) noexcept { diff --git a/api/include/opentelemetry/trace/span_metadata.h b/api/include/opentelemetry/trace/span_metadata.h index 5e615ea537..d2d6a9f85d 100644 --- a/api/include/opentelemetry/trace/span_metadata.h +++ b/api/include/opentelemetry/trace/span_metadata.h @@ -20,7 +20,8 @@ enum class SpanKind }; // The key identifies the active span in the current context. -constexpr char kSpanKey[] = "active_span"; +constexpr char kSpanKey[] = "active_span"; +constexpr char kIsRootSpanKey[] = "is_root_span"; // StatusCode - Represents the canonical set of status codes of a finished Span. enum class StatusCode diff --git a/api/include/opentelemetry/trace/span_startoptions.h b/api/include/opentelemetry/trace/span_startoptions.h index 2180394d72..8a2165b0f0 100644 --- a/api/include/opentelemetry/trace/span_startoptions.h +++ b/api/include/opentelemetry/trace/span_startoptions.h @@ -34,8 +34,31 @@ struct StartSpanOptions // Explicitly set the parent of a Span. // - // This defaults to an invalid span context. In this case, the Span is - // automatically parented to the currently active span. + // The `parent` field is designed to establish parent-child relationships + // in tracing spans. It can be set to either a `SpanContext` or a + // `context::Context` object. + // + // - When set to valid `SpanContext`, it directly assigns a specific Span as the parent + // of the newly created Span. + // + // - Alternatively, setting the `parent` field to a `context::Context` allows for + // more nuanced parent identification: + // 1. If the `Context` contains a Span object, this Span is treated as the parent. + // 2. If the `Context` contains the boolean flag `is_root_span` set to `true`, + // it indicates that the new Span should be treated as a root Span, i.e., it + // does not have a parent Span. + // Example Usage: + // ```cpp + // trace_api::StartSpanOptions options; + // opentelemetry::context::Context root; + // root = root.SetValue(kIsRootSpanKey, true); + // options.parent = root; + // auto root_span = tracer->StartSpan("span root", options); + // ``` + // + // - If the `parent` field is not set, the newly created Span will inherit the + // parent of the currently active Span (if any) in the current context. + // nostd::variant parent = SpanContext::GetInvalid(); // TODO: diff --git a/sdk/src/trace/tracer.cc b/sdk/src/trace/tracer.cc index 6ca7b37df5..c722d60326 100644 --- a/sdk/src/trace/tracer.cc +++ b/sdk/src/trace/tracer.cc @@ -43,6 +43,13 @@ nostd::shared_ptr Tracer::StartSpan( { parent_context = span_context; } + else + { + if (opentelemetry::trace::IsRootSpan(context)) + { + parent_context = opentelemetry::trace::SpanContext{false, false}; + } + } } opentelemetry::trace::TraceId trace_id; diff --git a/sdk/test/trace/tracer_test.cc b/sdk/test/trace/tracer_test.cc index 36cc135a1d..61ad24be1d 100644 --- a/sdk/test/trace/tracer_test.cc +++ b/sdk/test/trace/tracer_test.cc @@ -1008,6 +1008,26 @@ TEST(Tracer, WithActiveSpan) spans = span_data->GetSpans(); ASSERT_EQ(1, spans.size()); EXPECT_EQ("span 2", spans.at(0)->GetName()); + EXPECT_EQ(spans.at(0).get()->GetParentSpanId(), span_first->GetContext().span_id()); + EXPECT_EQ(spans.at(0).get()->GetTraceId(), span_first->GetContext().trace_id()); + + { + trace_api::StartSpanOptions options; + opentelemetry::context::Context c1; + c1 = c1.SetValue(opentelemetry::trace::kIsRootSpanKey, true); + options.parent = c1; + auto root_span = tracer->StartSpan("span root", options); + + spans = span_data->GetSpans(); + ASSERT_EQ(0, spans.size()); + + root_span->End(); + } + spans = span_data->GetSpans(); + ASSERT_EQ(1, spans.size()); + EXPECT_EQ("span root", spans.at(0)->GetName()); + EXPECT_EQ(spans.at(0).get()->GetParentSpanId(), opentelemetry::trace::SpanId()); + EXPECT_NE(spans.at(0).get()->GetTraceId(), span_first->GetContext().trace_id()); span_first->End(); } From 9f6d1453e7b4207eeac20ac3f5b748a1159224af Mon Sep 17 00:00:00 2001 From: Marc Alff Date: Wed, 6 Dec 2023 01:25:11 +0100 Subject: [PATCH 26/31] [REMOVAL] Remove ZPAGES (#2433) --- CHANGELOG.md | 7 + CMakeLists.txt | 12 - DEPRECATED.md | 84 +-- INSTALL.md | 4 - ci/do_ci.sh | 3 +- cmake/opentelemetry-cpp-config.cmake.in | 2 - docs/dependencies.md | 3 - examples/zpages/BUILD | 21 - examples/zpages/zpages_example.cc | 60 -- .../ext/zpages/latency_boundaries.h | 60 -- .../ext/zpages/static/tracez_index.h | 48 -- .../ext/zpages/static/tracez_script.h | 293 -------- .../ext/zpages/static/tracez_style.h | 165 ----- .../ext/zpages/threadsafe_span_data.h | 249 ------- .../opentelemetry/ext/zpages/tracez_data.h | 84 --- .../ext/zpages/tracez_data_aggregator.h | 168 ----- .../ext/zpages/tracez_http_server.h | 179 ----- .../ext/zpages/tracez_processor.h | 92 --- .../ext/zpages/tracez_shared_data.h | 67 -- ext/include/opentelemetry/ext/zpages/zpages.h | 96 --- .../ext/zpages/zpages_http_server.h | 120 --- ext/src/CMakeLists.txt | 4 - ext/src/zpages/BUILD | 17 - ext/src/zpages/CMakeLists.txt | 27 - ext/src/zpages/README.md | 53 -- ext/src/zpages/tracez_data_aggregator.cc | 189 ----- ext/src/zpages/tracez_http_server.cc | 163 ---- ext/src/zpages/tracez_processor.cc | 28 - ext/src/zpages/tracez_shared_data.cc | 41 - ext/test/CMakeLists.txt | 3 - ext/test/zpages/BUILD | 41 - ext/test/zpages/CMakeLists.txt | 14 - ext/test/zpages/threadsafe_span_data_test.cc | 73 -- .../zpages/tracez_data_aggregator_test.cc | 698 ------------------ ext/test/zpages/tracez_processor_test.cc | 647 ---------------- 35 files changed, 9 insertions(+), 3806 deletions(-) delete mode 100644 examples/zpages/BUILD delete mode 100644 examples/zpages/zpages_example.cc delete mode 100644 ext/include/opentelemetry/ext/zpages/latency_boundaries.h delete mode 100644 ext/include/opentelemetry/ext/zpages/static/tracez_index.h delete mode 100644 ext/include/opentelemetry/ext/zpages/static/tracez_script.h delete mode 100644 ext/include/opentelemetry/ext/zpages/static/tracez_style.h delete mode 100644 ext/include/opentelemetry/ext/zpages/threadsafe_span_data.h delete mode 100644 ext/include/opentelemetry/ext/zpages/tracez_data.h delete mode 100644 ext/include/opentelemetry/ext/zpages/tracez_data_aggregator.h delete mode 100644 ext/include/opentelemetry/ext/zpages/tracez_http_server.h delete mode 100644 ext/include/opentelemetry/ext/zpages/tracez_processor.h delete mode 100644 ext/include/opentelemetry/ext/zpages/tracez_shared_data.h delete mode 100644 ext/include/opentelemetry/ext/zpages/zpages.h delete mode 100644 ext/include/opentelemetry/ext/zpages/zpages_http_server.h delete mode 100644 ext/src/zpages/BUILD delete mode 100644 ext/src/zpages/CMakeLists.txt delete mode 100644 ext/src/zpages/README.md delete mode 100644 ext/src/zpages/tracez_data_aggregator.cc delete mode 100644 ext/src/zpages/tracez_http_server.cc delete mode 100644 ext/src/zpages/tracez_processor.cc delete mode 100644 ext/src/zpages/tracez_shared_data.cc delete mode 100644 ext/test/zpages/BUILD delete mode 100644 ext/test/zpages/CMakeLists.txt delete mode 100644 ext/test/zpages/threadsafe_span_data_test.cc delete mode 100644 ext/test/zpages/tracez_data_aggregator_test.cc delete mode 100644 ext/test/zpages/tracez_processor_test.cc diff --git a/CHANGELOG.md b/CHANGELOG.md index 85bdbadc28..d2d28461cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,8 @@ Increment the: [#2388](https://github.com/open-telemetry/opentelemetry-cpp/pull/2388) * [SEMANTIC CONVENTION] Upgrade to semconv 1.23.1 [#2428](https://github.com/open-telemetry/opentelemetry-cpp/pull/2428) +* [REMOVAL] Remove ZPAGES + [#2433](https://github.com/open-telemetry/opentelemetry-cpp/pull/2433) Important changes: @@ -103,6 +105,11 @@ Breaking changes: * Please check configuration variables, to make sure `_LOGS_` variables are set as expected. +* [REMOVAL] Remove ZPAGES + [#2433](https://github.com/open-telemetry/opentelemetry-cpp/pull/2433) + * As announced in release 1.12.0, + the deprecated ZPAGES exporter is now removed. + ## [1.12.0] 2023-10-16 * [BUILD] Support `pkg-config` diff --git a/CMakeLists.txt b/CMakeLists.txt index f795eadbb7..c27a910f4e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -212,9 +212,6 @@ option(WITH_PROMETHEUS "Whether to include the Prometheus Client in the SDK" option(WITH_ELASTICSEARCH "Whether to include the Elasticsearch Client in the SDK" OFF) -option(WITH_ZPAGES - "DEPRECATED - Whether to include the Zpages Server in the SDK" OFF) - option(WITH_NO_GETENV "Whether the platform supports environment variables" OFF) option(BUILD_TESTING "Whether to enable tests" ON) @@ -290,14 +287,6 @@ option(WITH_OTLP_HTTP_SSL_TLS_PREVIEW option(WITH_METRICS_EXEMPLAR_PREVIEW "Whether to enable exemplar within metrics" OFF) -if(WITH_ZPAGES) - if(WITH_NO_DEPRECATED_CODE) - message(FATAL_ERROR "WITH_ZPAGES is DEPRECATED.") - else() - message(WARNING "WITH_ZPAGES is DEPRECATED.") - endif() -endif() - # # Verify options dependencies # @@ -480,7 +469,6 @@ endif() if(WITH_ELASTICSEARCH OR WITH_ZIPKIN OR WITH_OTLP_HTTP - OR WITH_ZPAGES OR BUILD_W3CTRACECONTEXT_TEST OR WITH_ETW) set(USE_NLOHMANN_JSON ON) diff --git a/DEPRECATED.md b/DEPRECATED.md index c9ad356696..0632f50503 100644 --- a/DEPRECATED.md +++ b/DEPRECATED.md @@ -92,89 +92,7 @@ N/A ## [opentelemetry-cpp Exporter] -### ZPages exporter - -#### Announcement (ZPages) - -* Version: 1.11.0 -* Date: 2023-09-01 -* PR: [DEPRECATION] Deprecate ZPAGES - [#2291](https://github.com/open-telemetry/opentelemetry-cpp/pull/2291) - -#### Motivation (ZPages) - -The ZPages specification itself was introduced in 2020, -and has been experimental ever since, -not getting a lot of attention, and never reaching a stable status. - -Several other opentelemetry projects have implemented support for zpages, -only to later deprecate and then remove the zpages implementation (Java, -C#), abandoning the zpages feature. - -In this context, it does not make sense to continue to maintain the zpages -code in opentelemetry-cpp. - -#### Scope (ZPages) - -The following are deprecated and planned for removal: - -* all the API headers located under - `ext/include/opentelemetry/ext/zpages/`, including: - * the C++ class `ThreadsafeSpanData` - * the C++ class `TracezDataAggregator` - * the C++ class `TracezHttpServer` - * the C++ class `TracezSpanProcessor` - * the C++ class `TracezSharedData` - * the C++ class `ZPages` - * the C++ class `zPagesHttpServer` -* all the code and doc located under `ext/src/zpages/` -* all the tests located under `ext/test/zpages/` -* the zpages exporter library(`opentelemetry_zpages`) -* the zpages build options in CMake (`WITH_ZPAGES`) - -The following code is no longer considered public, will no longer be -installed, and will no longer be useable outside of -the opentelemetry-cpp implementation: - -* all the API headers located under - `ext/include/opentelemetry/ext/http/server`, including: - * the C++ class `FileHttpServer` - * the C++ class `HttpRequestCallback` - * the C++ class `HttpServer` - * the C++ class `HttpRequestHandler` - * the C++ class `SocketCallback` - -This implementation of an HTTP server is meant to be used for testing only, -it is not production ready. - -#### Mitigation (ZPages) - -Consider using a different exporter, -for example the OTLP exporter (both OTLP HTTP and OTLP GRPC are supported), -to expose trace data to a separate trace backend. - -Note that this changes the access pattern: - -* with zpages, data is only available locally (in process) -* with other exporters, data is available externally (not in process) - -Our assessment is that the zpages implementation is no longer in use, -and can be removed. - -If that assessment is incorrect (i.e., if you own a project that depends -on the zpage exporter from opentelemetry-cpp), please comment on the -removal issue -[#2292](https://github.com/open-telemetry/opentelemetry-cpp/issues/2292). - -An alternative to zpage removal is to move the code to the -opentelemetry-cpp-contrib github -[repository](https://github.com/open-telemetry/opentelemetry-cpp-contrib). - -Contributions to migrate the code, and maintain zpages, are welcome. - -#### Planned removal (ZPages) - -* Date: December, 2023 +N/A ## [Documentation] diff --git a/INSTALL.md b/INSTALL.md index 68fefff1fe..9cd9cef6e2 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -124,10 +124,6 @@ You can link OpenTelemetry C++ SDK with libraries provided in -- Installing: //lib/cmake/opentelemetry-cpp/opentelemetry-cpp-config.cmake -- Installing: //lib/cmake/opentelemetry-cpp/opentelemetry-cpp-config-version.cmake ... - -- Installing: //include/opentelemetry//ext/zpages/static/tracez_index.h - -- Installing: //include/opentelemetry//ext/zpages/static/tracez_style.h - -- Installing: //include/opentelemetry//ext/zpages/threadsafe_span_data.h - -- Installing: //lib/libopentelemetry_zpages.a $ ``` diff --git a/ci/do_ci.sh b/ci/do_ci.sh index f679c6af04..de03a2585e 100755 --- a/ci/do_ci.sh +++ b/ci/do_ci.sh @@ -459,8 +459,7 @@ elif [[ "$1" == "bazel.asan" ]]; then elif [[ "$1" == "bazel.tsan" ]]; then # TODO - potential race condition in Civetweb server used by prometheus-cpp during shutdown # https://github.com/civetweb/civetweb/issues/861, so removing prometheus from the test -# zpages test failing with tsan. Ignoring the tests for now, as zpages will be removed soon. - bazel $BAZEL_STARTUP_OPTIONS test --config=tsan $BAZEL_TEST_OPTIONS_ASYNC -- //... -//exporters/prometheus/... -//ext/test/zpages/... + bazel $BAZEL_STARTUP_OPTIONS test --config=tsan $BAZEL_TEST_OPTIONS_ASYNC -- //... -//exporters/prometheus/... exit 0 elif [[ "$1" == "bazel.valgrind" ]]; then bazel $BAZEL_STARTUP_OPTIONS build $BAZEL_OPTIONS_ASYNC //... diff --git a/cmake/opentelemetry-cpp-config.cmake.in b/cmake/opentelemetry-cpp-config.cmake.in index 5c450c1df6..86098f7d7c 100644 --- a/cmake/opentelemetry-cpp-config.cmake.in +++ b/cmake/opentelemetry-cpp-config.cmake.in @@ -46,7 +46,6 @@ # opentelemetry-cpp::ostream_span_exporter - Imported target of opentelemetry-cpp::ostream_span_exporter # opentelemetry-cpp::elasticsearch_log_record_exporter - Imported target of opentelemetry-cpp::elasticsearch_log_record_exporter # opentelemetry-cpp::etw_exporter - Imported target of opentelemetry-cpp::etw_exporter -# opentelemetry-cpp::zpages - Imported target of opentelemetry-cpp::zpages # opentelemetry-cpp::http_client_curl - Imported target of opentelemetry-cpp::http_client_curl # opentelemetry-cpp::opentracing_shim - Imported target of opentelemetry-cpp::opentracing_shim # @@ -100,7 +99,6 @@ set(_OPENTELEMETRY_CPP_LIBRARIES_TEST_TARGETS prometheus_exporter elasticsearch_log_record_exporter etw_exporter - zpages http_client_curl opentracing_shim) foreach(_TEST_TARGET IN LISTS _OPENTELEMETRY_CPP_LIBRARIES_TEST_TARGETS) diff --git a/docs/dependencies.md b/docs/dependencies.md index 2f2f2368f6..da6c584fe8 100644 --- a/docs/dependencies.md +++ b/docs/dependencies.md @@ -92,9 +92,6 @@ Both these dependencies are listed here: - `libcurl` for connecting with Elasticsearch server over HTTP protocol. - `nlohmann/json` for encoding Elastic Search messages. -- [Zpages](/ext/src/zpages): - - None - - [Opentracing](/opentracing-shim) shim: - [`opentracing-cpp`](https://github.com/opentracing/opentracing-cpp) diff --git a/examples/zpages/BUILD b/examples/zpages/BUILD deleted file mode 100644 index 529c839cb7..0000000000 --- a/examples/zpages/BUILD +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright The OpenTelemetry Authors -# SPDX-License-Identifier: Apache-2.0 - -package(default_visibility = ["//visibility:public"]) - -cc_binary( - name = "zpages_example", - srcs = [ - "zpages_example.cc", - ], - linkopts = select({ - "//bazel:windows": [], - "//conditions:default": ["-pthread"], - }), - tags = ["examples"], - deps = [ - "//ext:headers", - "//ext/src/zpages", - "//sdk/src/trace", - ], -) diff --git a/examples/zpages/zpages_example.cc b/examples/zpages/zpages_example.cc deleted file mode 100644 index 2691a73158..0000000000 --- a/examples/zpages/zpages_example.cc +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -/** - * This is a basic example for zpages that helps users get familiar with how to - * use this feature in OpenTelemetery - */ -#include -#include -#include - -#include "opentelemetry/ext/zpages/zpages.h" // Required file include for zpages - -using opentelemetry::common::SteadyTimestamp; -namespace trace_api = opentelemetry::trace; - -int main(int argc, char *argv[]) -{ - - /** - * The following line initializes zPages and starts a webserver at - * http://localhost:30000/tracez/ where spans that are created in the application - * can be viewed. - * Note that the webserver is destroyed after the application ends execution. - */ - ZPages::Initialize(); - auto tracer = trace_api::Provider::GetTracerProvider()->GetTracer(""); - - std::cout << "This example for zPages creates a few types of spans and then " - << "creates a span every second for the duration of the application" - << "\n"; - - // Error span - std::map attribute_map; - attribute_map["completed_search_for"] = "Unknown user"; - tracer->StartSpan("find user", attribute_map) - ->SetStatus(trace_api::StatusCode::kError, "User not found"); - - // Long time duration span - std::map attribute_map2; - attribute_map2["completed_search_for"] = "John Doe"; - trace_api::StartSpanOptions start; - start.start_steady_time = SteadyTimestamp(nanoseconds(1)); - trace_api::EndSpanOptions end; - end.end_steady_time = SteadyTimestamp(nanoseconds(1000000000000)); - tracer->StartSpan("find user", attribute_map2, start)->End(end); - - // Running(deadlock) span - std::map attribute_map3; - attribute_map3["searching_for"] = "Deleted user"; - auto running_span = tracer->StartSpan("find user", attribute_map3); - - // Create a completed span every second till user stops the loop - std::cout << "Presss CTRL+C to stop...\n"; - while (true) - { - std::this_thread::sleep_for(seconds(1)); - tracer->StartSpan("ping user")->End(); - } -} diff --git a/ext/include/opentelemetry/ext/zpages/latency_boundaries.h b/ext/include/opentelemetry/ext/zpages/latency_boundaries.h deleted file mode 100644 index cc03b169b2..0000000000 --- a/ext/include/opentelemetry/ext/zpages/latency_boundaries.h +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include -#include - -#include "opentelemetry/version.h" - -using std::chrono::microseconds; -using std::chrono::milliseconds; -using std::chrono::nanoseconds; -using std::chrono::seconds; - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace ext -{ -namespace zpages -{ -/** - * kLatencyBoundaries is a constant array that contains the 9 latency - * boundaries. Each value in the array represents the lower limit(inclusive) of - * the boundary(in nano seconds) and the upper limit(exclusive) of the boundary - * is the lower limit of the next one. The upper limit of the last boundary is - * INF. - */ -const std::array kLatencyBoundaries = { - nanoseconds(0), - nanoseconds(microseconds(10)), - nanoseconds(microseconds(100)), - nanoseconds(milliseconds(1)), - nanoseconds(milliseconds(10)), - nanoseconds(milliseconds(100)), - nanoseconds(seconds(1)), - nanoseconds(seconds(10)), - nanoseconds(seconds(100)), -}; - -/** - * LatencyBoundary enum is used to index into the kLatencyBoundaries container. - * Using this enum lets you access the latency boundary at each index without - * using magic numbers - */ -enum LatencyBoundary -{ - k0MicroTo10Micro, - k10MicroTo100Micro, - k100MicroTo1Milli, - k1MilliTo10Milli, - k10MilliTo100Milli, - k100MilliTo1Second, - k1SecondTo10Second, - k10SecondTo100Second, - k100SecondToMax -}; - -} // namespace zpages -} // namespace ext -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/include/opentelemetry/ext/zpages/static/tracez_index.h b/ext/include/opentelemetry/ext/zpages/static/tracez_index.h deleted file mode 100644 index c4c5b4933d..0000000000 --- a/ext/include/opentelemetry/ext/zpages/static/tracez_index.h +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -const char tracez_index[] = - "" - "" - "" - " " - " zPages TraceZ" - " " - " " - " " - " " - "

        zPages TraceZ

        " - " Data last fetched:
        " - "
        " - "

        " - "
        " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - "
        Span NameError SamplesRunningLatency Samples
        " - " " - "
        " - "
        Row count: 0
        " - "
        " - "
        " - "
        " - " " - "
        " - " " - "
        " - "
        Row count: 0
        " - "
        " - " " - ""; diff --git a/ext/include/opentelemetry/ext/zpages/static/tracez_script.h b/ext/include/opentelemetry/ext/zpages/static/tracez_script.h deleted file mode 100644 index b21ceea8ee..0000000000 --- a/ext/include/opentelemetry/ext/zpages/static/tracez_script.h +++ /dev/null @@ -1,293 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -const char tracez_script[] = - "" - "window.onload = () => refreshData();" - "" - "const latencies = [" - " '>0s', '>10µs', '>100µs'," - " '>1ms', '>10ms', '>100ms'," - " '>1s', '>10s', '>100s'," - "];" - "" - "const statusCodeDescriptions = {" - " 'OK': 'The operation completed successfully.'," - " 'CANCELLED': 'The operation was cancelled (typically by the caller).'," - " 'UNKNOWN': `Unknown error. An example of where this error may be returned is if a Status " - "value received" - " from another address space belongs to an error-space that is not known in this " - "address space." - " Also errors raised by APIs that do not return enough error information may be " - "converted to" - " this error.`," - " 'INVALID_ARGUMENT': `Client specified an invalid argument. Note that this differs from " - "FAILED_PRECONDITION." - " INVALID_ARGUMENT indicates arguments that are problematic regardless of the state " - "of the" - " system (e.g., a malformed file name).`," - " 'DEADLINE_EXCEEDED': `Deadline expired before operation could complete. For operations that " - "change the state of the" - " system, this error may be returned even if the operation has completed " - "successfully. For" - " example, a successful response from a server could have been delayed long enough " - "for the" - " deadline to expire.`," - " 'NOT_FOUND' : 'Some requested entity (e.g., file or directory) was not found.'," - " 'ALREADY_EXISTS': 'Some entity that we attempted to create (e.g., file or directory) " - "already exists.'," - " 'PERMISSION_DENIED': `The caller does not have permission to execute the specified " - "operation. PERMISSION_DENIED" - " must not be used for rejections caused by exhausting some resource (use " - "RESOURCE_EXHAUSTED" - " instead for those errors). PERMISSION_DENIED must not be used if the caller cannot " - "be" - " identified (use UNAUTHENTICATED instead for those errors).`," - " 'RESOURCE_EXHAUSTED': `Some resource has been exhausted, perhaps a per-user quota, or " - "perhaps the entire file system" - " is out of space.`," - " 'FAILED_PRECONDITION': `Operation was rejected because the system is not in a state " - "required for the operation's" - " execution. For example, directory to be deleted may be non-empty, an rmdir " - "operation is" - " applied to a non-directory, etc.`," - " 'ABORTED': `The operation was aborted, typically due to a concurrency issue like sequencer " - "check" - " failures, transaction aborts, etc`," - " 'OUT_OF_RANGE': `Operation was attempted past the valid range. E.g., seeking or reading " - "past end of file.`," - " 'UNIMPLEMENTED': 'Operation is not implemented or not supported/enabled in this service.'," - " 'INTERNAL': `Internal errors. Means some invariants expected by underlying system has been " - "broken. If you" - " see one of these errors, something is very broken.`," - " 'UNAVAILABLE': `The service is currently unavailable. This is a most likely a transient " - "condition and may be" - " corrected by retrying with a backoff.`," - " 'DATA_LOSS': 'Unrecoverable data loss or corruption.'," - " 'UNAUTHENTICATED': 'The request does not have valid authentication credentials for the " - "operation.'," - "};" - "" - "const units = {'duration': 'ns'};" - "" - "" - "const details = {'status': statusCodeDescriptions};" - "" - "/* Latency info is returned as an array, so they need to be parsed accordingly */" - "const getLatencyCell = (span, i, h) => `${span[h][i]}`;" - "" - "/* Pretty print a cell with a map */" - "const getKeyValueCell = (span, h) => `" - " ${JSON.stringify(span[h], null, 2)}" - " `;" - "" - "/* Standard categories when checking span details */" - "const idCols = ['spanid', 'parentid', 'traceid'];" - "const detailCols = ['attributes']; /* Columns error, running, and latency spans all share */" - "const dateCols = ['start']; /* Categories to change to date */" - "const numCols = ['duration']; /* Categories to change to num */" - "const clickCols = ['error', 'running']; /* Non-latency clickable cols */" - "const arrayCols = { " - " 'latency': getLatencyCell," - " 'events': getKeyValueCell," - " 'attributes': getKeyValueCell" - "};" - "" - "const base_endpt = '/tracez/get/'; /* For making GET requests */" - "" - "/* Maps table types to their approporiate formatting */" - "const tableFormatting = {" - " 'all': {" - " 'url': base_endpt + 'aggregations'," - " 'html_id': 'overview_table'," - " 'sizing': [" - " {'sz': 'md', 'repeats': 1}," - " {'sz': 'sm', 'repeats': 11}," - " ]," - " 'headings': ['name', ...clickCols, 'latency']," - " 'cell_headings': ['name', ...clickCols, ...latencies]," - " }," - " 'error': {" - " 'url': base_endpt + 'error/'," - " 'html_id': 'name_type_detail_table'," - " 'sizing': [" - " {'sz': 'sm', 'repeats': 5}," - " {'sz': 'sm-md', 'repeats': 1}," - " ]," - " 'headings': [...idCols, ...dateCols, 'status', ...detailCols]," - " 'has_subheading': true," - " }," - " 'running': {" - " 'url': base_endpt + 'running/'," - " 'html_id': 'name_type_detail_table'," - " 'sizing': [" - " {'sz': 'sm', 'repeats': 4}," - " {'sz': 'sm-md', 'repeats': 1}," - " ]," - " 'headings': [...idCols, ...dateCols, ...detailCols]," - " 'has_subheading': true," - " 'status': 'pending'," - " }," - " 'latency': {" - " 'url': base_endpt + 'latency/'," - " 'html_id': 'name_type_detail_table'," - " 'sizing': [" - " {'sz': 'sm', 'repeats': 5}," - " {'sz': 'sm-md', 'repeats': 1}," - " ]," - " 'headings': [...idCols, ...dateCols, ...numCols, ...detailCols]," - " 'has_subheading': true," - " 'status': 'ok'" - " }" - "};" - "const getFormat = group => tableFormatting[group];" - "" - "/* Getters using formatting config variable */" - "const getURL = group => getFormat(group)['url'];" - "const getHeadings = group => getFormat(group)['headings'];" - "const getCellHeadings = group => 'cell_headings' in getFormat(group)" - " ? getFormat(group)['cell_headings'] : getHeadings(group); " - "const getSizing = group => getFormat(group)['sizing'];" - "const getStatus = group => isLatency(group) ? 'ok' : getFormat(group)['status'];" - "const getHTML = group => getFormat(group)['html_id'];" - "" - "const isDate = col => new Set(dateCols).has(col);" - "const isLatency = group => !(new Set(clickCols).has(group)); /* non latency clickable cols, " - "change to include latency? */" - "const isArrayCol = group => (new Set(Object.keys(arrayCols)).has(group));" - "const hasCallback = col => new Set(clickCols).has(col); /* Non-latency cb columns */" - "const hideHeader = h => new Set([...clickCols, 'name']).has(h); /* Headers to not show render " - "twice */" - "const hasSubheading = group => isLatency(group) || 'has_subheading' in getFormat(group); " - "const hasStatus = group => isLatency(group) || 'status' in getFormat(group);" - "" - "const toTitlecase = word => word.charAt(0).toUpperCase() + word.slice(1);" - "const updateLastRefreshStr = () => document.getElementById('lastUpdateTime').innerHTML = new " - "Date().toLocaleString();" - "" - "const getStatusHTML = group => !hasStatus(group) ? ''" - " : `All of these spans have status code ${getStatus(group)}`;" - "" - "/* Returns an HTML string that handlles width formatting" - " for a table group */" - "const tableSizing = group => ''" - " + getSizing(group).map(sz =>" - " (``).repeat(sz['repeats']))" - " .join('')" - " + '';" - "" - "/* Returns an HTML string for a table group's headings," - " hiding headings where needed */" - "const tableHeadings = group => ''" - " + getCellHeadings(group).map(h => `${(hideHeader(h) ? '' : h)}`).join('')" - " + '';" - "" - "/* Returns an HTML string, which represents the formatting for" - " the entire header for a table group. This doesn't change, and" - " includes the width formatting and the actual table headers */" - "const tableHeader = group => tableSizing(group) + tableHeadings(group);" - "" - "/* Return formatting for an array-based value based on its header */" - "const getArrayCells = (h, span) => span[h].length" - " ? (span[h].map((_, i) => arrayCols[h](span, i, h))).join('')" - " : (Object.keys(span[h]).length ? arrayCols[h](span, h) : `${emptyContent()}`);" - "" - "const emptyContent = () => `(not set)`;" - "" - "const dateStr = nanosec => {" - " const mainDate = new Date(nanosec / 1000000).toLocaleString();" - " let lostPrecision = String(nanosec % 1000000);" - " while (lostPrecision.length < 6) lostPrecision = 0 + lostPrecision;" - " const endingLocation = mainDate.indexOf('M') - 2;" - " return `${mainDate.substr(0, " - "endingLocation)}:${lostPrecision}${mainDate.substr(endingLocation)}`;" - "};" - "" - "const detailCell = (h, span) => {" - " const detailKey = Object.keys(details[h])[span[h]];" - " const detailVal = details[h][detailKey];" - " return `" - " ${detailKey}" - " ${detailVal}" - " `;" - "};" - "" - "/* Format cells as needed */" - "const getCellContent = (h, span) => {" - " if (h in details) return detailCell(h, span);" - " else if (h in units) return `${span[h]} ${units[h]}`;" - " else if (span[h] === '') return emptyContent();" - " else if (!isDate(h)) return span[h];" - " return dateStr(span[h]);" - "};" - "" - "/* Create cell based on what header we want to render */" - "const getCell = (h, span) => (isArrayCol(h)) ? getArrayCells(h, span)" - " : `` + `${getCellContent(h, span)}`;" - "" - "/* Returns an HTML string with for a span's aggregated data" - " while columns are ordered according to its table group */" - "const tableRow = (group, span) => ''" - " + getHeadings(group).map(h => getCell(h, span)).join('')" - " + '';" - "" - "/* Returns an HTML string from all the data given as" - " table rows, with each row being a group of spans by name */" - "const tableRows = (group, data) => data.map(span => tableRow(group, span)).join('');" - "" - "/* Overwrite a table on the DOM based on the group given by adding" - " its headers and fetching data for its url */" - "function overwriteTable(group, url_end = '') {" - " fetch(getURL(group) + url_end).then(res => res.json())" - " .then(data => {" - " document.getElementById(getHTML(group))" - " .innerHTML = tableHeader(group)" - " + tableRows(group, data);" - " document.getElementById(getHTML(group) + '_count')" - " .innerHTML = data.length;" - " })" - " .catch(err => console.log(err));" - "};" - "" - "/* Adds a title subheading where needed */" - "function updateSubheading(group, name) {" - " if (hasSubheading(group)) {" - " document.getElementById(getHTML(isLatency(group) ? 'latency' : group) + '_header')" - " .innerHTML = `

        ${name}" - " ${(isLatency(group) ? `${latencies[group]} Bucket` : toTitlecase(group))}" - " Spans

        Showing span details for up to 5 most recent spans. " - " ${getStatusHTML(group)}

        `;" - " }" - "};" - "" - "/* Overwrites a table on the DOM based on the group and also" - " changes the subheader, since this a looking at sampled spans */" - "function overwriteDetailedTable(group, name) {" - " if (isLatency(group)) overwriteTable('latency', group + '/' + name);" - " else overwriteTable(group, name);" - " updateSubheading(group, name);" - "};" - "" - "/* Append to a table on the DOM based on the group given */" - "function addToTable(group, url_end = '') {" - " fetch(getURL(group) + url_end).then(res => res.json())" - " .then(data => {" - " const rowsStr = tableRows(group, data);" - " if (!rowsStr) console.log(`No rows added for ${group} table`);" - " document.getElementById(getHTML(group))" - " .getElementsByTagName('tbody')[0]" - " .innerHTML += rowsStr;" - " })" - " .catch(err => console.log(err));" - "};" - "" - "const refreshData = () => {" - " updateLastRefreshStr();" - " overwriteTable('all');" - "};" - ""; diff --git a/ext/include/opentelemetry/ext/zpages/static/tracez_style.h b/ext/include/opentelemetry/ext/zpages/static/tracez_style.h deleted file mode 100644 index 16b83f897e..0000000000 --- a/ext/include/opentelemetry/ext/zpages/static/tracez_style.h +++ /dev/null @@ -1,165 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -const char tracez_style[] = - "" - "body {" - " color: #252525;" - " text-align: center;" - " font-family: monospace, sans-serif;" - " word-break: break-all;" - " font-size: .9em" - "}" - "" - "code {" - " font-size: 12px;" - "}" - "" - "h1 {" - " margin: 20px 0 0;" - "}" - "" - "table {" - " font-family: monospace, sans-serif;" - " border-collapse: collapse;" - " font-size: 1.05em;" - " width: 100%;" - "}" - "" - ".table-wrap {" - " width: 100%;" - " min-width: 700px;" - " max-width: 2000px;" - " margin: auto;" - "}" - "" - "td, th {" - " word-break: break-word;" - " border: 1px solid #f5f5f5;" - " padding: 6px;" - " text-align: center;" - "}" - "" - "#overview_table th, #overview_table tr {" - " border-top: none;" - "}" - "" - "#headers th, #headers tr {" - " border-bottom: none;" - "}" - "" - "#top-right {" - " text-align: right;" - " position: absolute;" - " top: 10px;" - " right: 10px;" - " text-shadow: .5px .5px .25px #fff;" - "}" - "" - "#top-right button {" - " color: #f6a81c;" - " border: 2px solid #f6a81c;" - " padding: 10px;" - " margin: 10px;" - " text-transform: uppercase;" - " letter-spacing: 1px;" - " background-color: white;" - " border-radius: 10px;" - " font-weight: bold;" - "}" - "" - ".right {" - " text-align: right;" - " padding: 10px;" - "}" - "" - ":hover {" - " transition-duration: .15s;" - "}" - "" - "#top-right button:hover {" - " border-color: #4b5fab;" - " color: #4b5fab;" - " cursor: pointer;" - "}" - "" - "tr:nth-child(even) {" - " background-color: #eee;" - "}" - "" - ".click {" - " text-decoration: underline dotted #4b5fab;" - "}" - "" - "tr:hover, td:hover, .click:hover {" - " color: white;" - " background-color: #4b5fab;" - "}" - "" - "tr:hover {" - " background-color: #4b5fabcb;" - "}" - "" - "th {" - " background-color: white;" - " color: #252525;" - "}" - "" - ".click:hover {" - " cursor: pointer;" - " color: #f6a81ccc;" - "}" - "" - ".empty {" - " color: #999;" - "}" - "" - ".sm {" - " width: 7%;" - "}" - "" - ".sm-md {" - " width: 13%;" - "}" - "" - ".md {" - " width: 23%;" - "}" - "" - ".lg {" - " width: 63%;" - "}" - "" - "img {" - " width: 50%;" - " max-width: 500px;" - "}" - "" - ".subhead-name {" - " color: #4b5fab;" - "}" - "" - ".has-tooltip {" - " text-decoration: underline dotted #f6a81c;" - "}" - "" - ".has-tooltip:hover .tooltip {" - " display: block;" - "}" - "" - ".tooltip {" - " display: none;" - " position: absolute;" - "}" - "" - ".tooltip, .tooltip:hover {" - " background: #ffffffd9;" - " padding: 10px;" - " z-index: 1000;" - " color: #252525 !important;" - " border-radius: 10px;" - " margin: 3px 20px 0 0;" - "}" - ""; diff --git a/ext/include/opentelemetry/ext/zpages/threadsafe_span_data.h b/ext/include/opentelemetry/ext/zpages/threadsafe_span_data.h deleted file mode 100644 index bd1f716ad8..0000000000 --- a/ext/include/opentelemetry/ext/zpages/threadsafe_span_data.h +++ /dev/null @@ -1,249 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include -#include -#include -#include - -#include "opentelemetry/common/timestamp.h" -#include "opentelemetry/nostd/string_view.h" -#include "opentelemetry/sdk/trace/recordable.h" -#include "opentelemetry/sdk/trace/span_data.h" -#include "opentelemetry/trace/span.h" -#include "opentelemetry/trace/span_id.h" -#include "opentelemetry/trace/trace_id.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace ext -{ -namespace zpages -{ - -/** - * This class is a threadsafe version of span data used for zpages in OT - */ -class ThreadsafeSpanData final : public opentelemetry::sdk::trace::Recordable -{ -public: - /** - * Get the trace id for this span - * @return the trace id for this span - */ - opentelemetry::trace::TraceId GetTraceId() const noexcept - { - std::lock_guard lock(mutex_); - return span_context_.trace_id(); - } - - /** - * Get the span id for this span - * @return the span id for this span - */ - opentelemetry::trace::SpanId GetSpanId() const noexcept - { - std::lock_guard lock(mutex_); - return span_context_.span_id(); - } - - /** - * Get the span context for this span - * @return the span context for this span - */ - const opentelemetry::trace::SpanContext &GetSpanContext() const noexcept - { - std::lock_guard lock(mutex_); - return span_context_; - } - - /** - * Get the parent span id for this span - * @return the span id for this span's parent - */ - opentelemetry::trace::SpanId GetParentSpanId() const noexcept - { - std::lock_guard lock(mutex_); - return parent_span_id_; - } - - /** - * Get the name for this span - * @return the name for this span - */ - opentelemetry::nostd::string_view GetName() const noexcept - { - std::lock_guard lock(mutex_); - return name_; - } - - /** - * Get the status for this span - * @return the status for this span - */ - opentelemetry::trace::StatusCode GetStatus() const noexcept - { - std::lock_guard lock(mutex_); - return status_code_; - } - - /** - * Get the status description for this span - * @return the description of the the status of this span - */ - opentelemetry::nostd::string_view GetDescription() const noexcept - { - std::lock_guard lock(mutex_); - return status_desc_; - } - - /** - * Get the start time for this span - * @return the start time for this span - */ - opentelemetry::common::SystemTimestamp GetStartTime() const noexcept - { - std::lock_guard lock(mutex_); - return start_time_; - } - - /** - * Get the duration for this span - * @return the duration for this span - */ - std::chrono::nanoseconds GetDuration() const noexcept - { - std::lock_guard lock(mutex_); - return duration_; - } - - /** - * Get the attributes for this span - * @return the attributes for this span - */ - std::unordered_map GetAttributes() - const noexcept - { - std::lock_guard lock(mutex_); - return attributes_; - } - - void SetIdentity(const opentelemetry::trace::SpanContext &span_context, - opentelemetry::trace::SpanId parent_span_id) noexcept override - { - std::lock_guard lock(mutex_); - span_context_ = span_context; - parent_span_id_ = parent_span_id; - } - - void SetAttribute(nostd::string_view key, const common::AttributeValue &value) noexcept override - { - std::lock_guard lock(mutex_); - attributes_[std::string(key)] = nostd::visit(converter_, value); - } - - void SetStatus(opentelemetry::trace::StatusCode code, - nostd::string_view description) noexcept override - { - std::lock_guard lock(mutex_); - status_code_ = code; - status_desc_ = std::string(description); - } - - void SetName(nostd::string_view name) noexcept override - { - std::lock_guard lock(mutex_); - name_ = std::string(name); - } - - void SetSpanKind(opentelemetry::trace::SpanKind span_kind) noexcept override - { - span_kind_ = span_kind; - } - - void SetResource(const opentelemetry::sdk::resource::Resource & /*resource*/) noexcept override - { - // Not Implemented - } - - void SetStartTime(opentelemetry::common::SystemTimestamp start_time) noexcept override - { - std::lock_guard lock(mutex_); - start_time_ = start_time; - } - - void SetDuration(std::chrono::nanoseconds duration) noexcept override - { - std::lock_guard lock(mutex_); - duration_ = duration; - } - - void SetInstrumentationScope(const opentelemetry::sdk::instrumentationscope::InstrumentationScope - &instrumentation_scope) noexcept override - { - std::lock_guard lock(mutex_); - instrumentation_scope_ = &instrumentation_scope; - } - - void AddLink(const opentelemetry::trace::SpanContext &span_context, - const opentelemetry::common::KeyValueIterable &attributes = - opentelemetry::common::KeyValueIterableView>( - {})) noexcept override - { - std::lock_guard lock(mutex_); - (void)span_context; - (void)attributes; - } - - void AddEvent( - nostd::string_view name, - common::SystemTimestamp timestamp = common::SystemTimestamp(std::chrono::system_clock::now()), - const opentelemetry::common::KeyValueIterable &attributes = - opentelemetry::common::KeyValueIterableView>( - {})) noexcept override - { - std::lock_guard lock(mutex_); - events_.push_back( - opentelemetry::sdk::trace::SpanDataEvent(std::string(name), timestamp, attributes)); - } - - ThreadsafeSpanData() {} - ThreadsafeSpanData(const ThreadsafeSpanData &threadsafe_span_data) - : ThreadsafeSpanData(threadsafe_span_data, - std::lock_guard(threadsafe_span_data.mutex_)) - {} - -private: - ThreadsafeSpanData(const ThreadsafeSpanData &threadsafe_span_data, - const std::lock_guard &) - : span_context_(threadsafe_span_data.span_context_), - parent_span_id_(threadsafe_span_data.parent_span_id_), - start_time_(threadsafe_span_data.start_time_), - duration_(threadsafe_span_data.duration_), - name_(threadsafe_span_data.name_), - status_code_(threadsafe_span_data.status_code_), - status_desc_(threadsafe_span_data.status_desc_), - attributes_(threadsafe_span_data.attributes_), - events_(threadsafe_span_data.events_), - converter_(threadsafe_span_data.converter_), - instrumentation_scope_(threadsafe_span_data.instrumentation_scope_) - {} - - mutable std::mutex mutex_; - opentelemetry::trace::SpanContext span_context_{false, false}; - opentelemetry::trace::SpanId parent_span_id_; - common::SystemTimestamp start_time_; - std::chrono::nanoseconds duration_{0}; - std::string name_; - opentelemetry::trace::SpanKind span_kind_; - opentelemetry::trace::StatusCode status_code_{opentelemetry::trace::StatusCode::kUnset}; - std::string status_desc_; - std::unordered_map attributes_; - std::vector events_; - opentelemetry::sdk::common::AttributeConverter converter_; - const opentelemetry::sdk::instrumentationscope::InstrumentationScope *instrumentation_scope_; -}; -} // namespace zpages -} // namespace ext -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/include/opentelemetry/ext/zpages/tracez_data.h b/ext/include/opentelemetry/ext/zpages/tracez_data.h deleted file mode 100644 index 5f36a6b047..0000000000 --- a/ext/include/opentelemetry/ext/zpages/tracez_data.h +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include -#include -#include -#include - -#include "opentelemetry/ext/zpages/threadsafe_span_data.h" -#include "opentelemetry/nostd/span.h" -#include "opentelemetry/nostd/string_view.h" -#include "opentelemetry/sdk/trace/span_data.h" -#include "opentelemetry/trace/span_id.h" -#include "opentelemetry/trace/trace_id.h" -#include "opentelemetry/version.h" - -using opentelemetry::ext::zpages::ThreadsafeSpanData; -using opentelemetry::trace::SpanId; -using opentelemetry::trace::TraceId; - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace ext -{ -namespace zpages -{ - -/** - * kMaxNumberOfSampleSpans is the maximum number of running, completed or error - * sample spans stored at any given time for a given span name. - * This limit is introduced to reduce memory usage by trimming sample spans - * stored. - */ -const int kMaxNumberOfSampleSpans = 5; - -/** - * TracezData is the data to be displayed for tracez zpages that is stored for - * each span name. - */ -struct TracezData -{ - /** - * TODO: At this time the maximum count is unknown but a larger data type - * might have to be used in the future to store these counts to avoid overflow - */ - unsigned int running_span_count; - unsigned int error_span_count; - - /** - * completed_span_count_per_latency_bucket is an array that stores the count - * of spans for each of the 9 latency buckets. - */ - std::array completed_span_count_per_latency_bucket; - - /** - * sample_latency_spans is an array of lists, each index of the array - * corresponds to a latency boundary(of which there are 9). - * The list in each index stores the sample spans for that latency boundary. - */ - std::array, kLatencyBoundaries.size()> sample_latency_spans; - - /** - * sample_error_spans is a list that stores the error samples for a span name. - */ - std::list sample_error_spans; - - /** - * sample_running_spans is a list that stores the running span samples for a - * span name. - */ - std::list sample_running_spans; - - TracezData() - { - running_span_count = 0; - error_span_count = 0; - completed_span_count_per_latency_bucket.fill(0); - } -}; - -} // namespace zpages -} // namespace ext -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/include/opentelemetry/ext/zpages/tracez_data_aggregator.h b/ext/include/opentelemetry/ext/zpages/tracez_data_aggregator.h deleted file mode 100644 index 5bc7e847db..0000000000 --- a/ext/include/opentelemetry/ext/zpages/tracez_data_aggregator.h +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "opentelemetry/ext/zpages/latency_boundaries.h" -#include "opentelemetry/ext/zpages/tracez_data.h" -#include "opentelemetry/ext/zpages/tracez_shared_data.h" -#include "opentelemetry/nostd/span.h" -#include "opentelemetry/nostd/string_view.h" -#include "opentelemetry/sdk/trace/span_data.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace ext -{ -namespace zpages -{ -/** - * TracezDataAggregator object is responsible for collecting raw data and - * converting it to useful information that can be made available to - * display on the tracez zpage. - * - * When this object is created it starts a thread that calls a function - * periodically to update the aggregated data with new spans. - * - * The only exposed function is a getter that returns a copy of the aggregated - * data when requested. This function is ensured to be called in sequence to the - * aggregate spans function which is called periodically. - * - * TODO: Consider a singleton pattern for this class, not sure if multiple - * instances of this class should exist. - */ -class TracezDataAggregator -{ -public: - /** - * Constructor creates a thread that calls a function to aggregate span data - * at regular intervals. - * @param shared_data is the shared set of spans to expose. - * @param update_interval the time duration for updating the aggregated data. - */ - TracezDataAggregator(std::shared_ptr shared_data, - milliseconds update_interval = milliseconds(10)); - - /** Ends the thread set up in the constructor and destroys the object **/ - ~TracezDataAggregator(); - - /** - * GetAggregatedTracezData returns a copy of the updated data. - * @returns a map with the span name as key and the tracez span data as value. - */ - std::map GetAggregatedTracezData(); - -private: - /** - * AggregateSpans is the function that is called to update the aggregated data - * with newly completed and running span data - */ - void AggregateSpans(); - - /** - * AggregateCompletedSpans is the function that is called to update the - * aggregation with the data of newly completed spans. - * @param completed_spans are the newly completed spans. - */ - void AggregateCompletedSpans(std::vector> &completed_spans); - - /** - * AggregateRunningSpans aggregates the data for all running spans received - * from the span processor. Running spans are not cleared by the span - * processor and multiple calls to this function may contain running spans for - * which data has already been collected in a previous call. Additionally, - * span names can change while span is running and there seems to be - * no trivial to way to know if it is a new or old running span so at every - * call to this function the available running span data is reset and - * recalculated. At this time there is no unique way to identify a span - * object once this is done, there might be some better ways to do this. - * TODO : SpanProcessor is never notified when a span name is changed while it - * is running and that is propogated to the data aggregator. The running span - * name if changed while it is running will not be updated in the data - * aggregator till the span is completed. - * @param running_spans is the running spans to be aggregated. - */ - void AggregateRunningSpans(std::unordered_set &running_spans); - - /** - * AggregateStatusOKSpans is the function called to update the data of spans - * with status code OK. - * @param ok_span is the span who's data is to be aggregated - */ - void AggregateStatusOKSpan(std::unique_ptr &ok_span); - - /** - * AggregateStatusErrorSpans is the function that is called to update the - * data of error spans - * @param error_span is the error span who's data is to be aggregated - */ - void AggregateStatusErrorSpan(std::unique_ptr &error_span); - - /** - * ClearRunningSpanData is a function that is used to clear all running span - * at the beginning of a call to AggregateSpan data. - * Running span data has to be cleared before aggregation because running - * span data is recalculated at every call to AggregateSpans. - */ - void ClearRunningSpanData(); - - /** - * FindLatencyBoundary finds the latency boundary to which the duration of - * the given span_data belongs to - * @ param span_data is the ThreadsafeSpanData whose duration for which the latency - * boundary is to be found - * @ returns LatencyBoundary is the latency boundary that the duration belongs - * to - */ - LatencyBoundary FindLatencyBoundary(std::unique_ptr &ok_span); - - /** - * InsertIntoSampleSpanList is a helper function that is called to insert - * a given span into a sample span list. A function is used for insertion - * because list size is to be limited at a set maximum. - * @param sample_spans the sample span list into which span is to be inserted - * @param span_data the span_data to be inserted into list - */ - void InsertIntoSampleSpanList(std::list &sample_spans, - ThreadsafeSpanData &span_data); - - /** Instance of shared spans used to collect raw data **/ - std::shared_ptr tracez_shared_data_; - - /** - * Tree map with key being the name of the span and value being a unique ptr - * that stores the tracez span data for the given span name - * A tree map is preferred to a hash map because the the data is to be ordered - * in alphabetical order of span name. - * TODO : A possible memory concern if there are too many unique - * span names, one solution could be to implement a LRU cache that trims the - * DS based on frequency of usage of a span name. - */ - std::map aggregated_tracez_data_; - std::mutex mtx_; - - /** A boolean that is set to true in the constructor and false in the - * destructor to start and end execution of aggregate spans **/ - std::atomic execute_{false}; - - /** Thread that executes aggregate spans at regurlar intervals during this - object's lifetime**/ - std::thread aggregate_spans_thread_; - - /** Condition variable that notifies the thread when object is about to be - destroyed **/ - std::condition_variable cv_; -}; - -} // namespace zpages -} // namespace ext -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/include/opentelemetry/ext/zpages/tracez_http_server.h b/ext/include/opentelemetry/ext/zpages/tracez_http_server.h deleted file mode 100644 index eaa3fac8d3..0000000000 --- a/ext/include/opentelemetry/ext/zpages/tracez_http_server.h +++ /dev/null @@ -1,179 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include -#include -#include -#include -#include -#include - -#include "nlohmann/json.hpp" -#include "opentelemetry/ext/zpages/static/tracez_index.h" -#include "opentelemetry/ext/zpages/static/tracez_script.h" -#include "opentelemetry/ext/zpages/static/tracez_style.h" -#include "opentelemetry/ext/zpages/tracez_data_aggregator.h" -#include "opentelemetry/ext/zpages/zpages_http_server.h" - -#define HAVE_HTTP_DEBUG -#define HAVE_CONSOLE_LOG - -using json = nlohmann::json; - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace ext -{ -namespace zpages -{ - -class TracezHttpServer : public opentelemetry::ext::zpages::zPagesHttpServer -{ -public: - /** - * Construct the server by initializing the endpoint for querying TraceZ aggregation data and - * files, along with taking ownership of the aggregator whose data is used to send data to the - * frontend - * @param aggregator is the TraceZ Data Aggregator, which calculates aggregation info - * @param host is the host where the TraceZ webpages will be displayed, default being localhost - * @param port is the port where the TraceZ webpages will be displayed, default being 30000 - */ - TracezHttpServer(std::unique_ptr &&aggregator, - const std::string &host = "localhost", - int port = 30000) - : opentelemetry::ext::zpages::zPagesHttpServer("/tracez", host, port), - data_aggregator_(std::move(aggregator)) - { - InitializeTracezEndpoint(*this); - }; - -private: - /** - * Set the HTTP server to use the "Serve" callback to send the appropriate data when queried - * @param server, which should be an instance of this object - */ - void InitializeTracezEndpoint(TracezHttpServer &server) { server[endpoint_] = Serve; } - - /** - * Updates the stored aggregation data (aggregations_) using the data aggregator - */ - void UpdateAggregations(); - - /** - * First updates the stored aggregations, then translates that data from a C++ map to - * a JSON object - * @returns JSON object of collected spans bucket counts by name - */ - json GetAggregations(); - - /** - * Using the stored aggregations, finds the span group with the right name and returns - * its running span data as a JSON, only grabbing the fields needed for the frontend - * @param name of the span group whose running data we want - * @returns JSON representing running span data with the passed in name - */ - json GetRunningSpansJSON(const std::string &name); - - /** - * Using the stored aggregations, finds the span group with the right name and returns - * its error span data as a JSON, only grabbing the fields needed for the frontend - * @param name of the span group whose running data we want - * @returns JSON representing eoor span data with the passed in name - */ - json GetErrorSpansJSON(const std::string &name); - - /** - * Using the stored aggregations, finds the span group with the right name and bucket index - * returning its latency span data as a JSON, only grabbing the fields needed for the frontend - * @param name of the span group whose latency data we want - * @param index of which latency bucket to grab from - * @returns JSON representing bucket span data with the passed in name and latency range - */ - json GetLatencySpansJSON(const std::string &name, int latency_range_index); - - /** - * Returns attributes, which have varied types, from a span data to convert into JSON - * @param sample current span data, whose attributes we want to extract - * @returns JSON representing attributes for a given threadsafe span data - */ - json GetAttributesJSON(const opentelemetry::ext::zpages::ThreadsafeSpanData &sample); - - /** - * Sets the response object with the TraceZ aggregation data based on the request endpoint - * @param req is the HTTP request, which we use to figure out the response to send - * @param resp is the HTTP response we want to send to the frontend, either webpage or TraceZ - * aggregation data - */ - HTTP_SERVER_NS::HttpRequestCallback Serve{ - [&](HTTP_SERVER_NS::HttpRequest const &req, HTTP_SERVER_NS::HttpResponse &resp) { - std::string query = GetQuery(req.uri); // tracez - - if (StartsWith(query, "get")) - { - resp.headers[HTTP_SERVER_NS::CONTENT_TYPE] = "application/json"; - query = GetAfterSlash(query); - if (StartsWith(query, "latency")) - { - auto queried_latency_name = GetAfterSlash(query); - auto queried_latency_index = std::stoi(GetBeforeSlash(queried_latency_name)); - auto queried_name = GetAfterSlash(queried_latency_name); - ReplaceHtmlChars(queried_name); - resp.body = GetLatencySpansJSON(queried_name, queried_latency_index).dump(); - } - else - { - auto queried_name = GetAfterSlash(query); - ReplaceHtmlChars(queried_name); - if (StartsWith(query, "aggregations")) - { - resp.body = GetAggregations().dump(); - } - else if (StartsWith(query, "running")) - { - resp.body = GetRunningSpansJSON(queried_name).dump(); - } - else if (StartsWith(query, "error")) - { - resp.body = GetErrorSpansJSON(queried_name).dump(); - } - else - { - resp.body = json::array().dump(); - } - } - } - else - { - if (StartsWith(query, "script.js")) - { - resp.headers[HTTP_SERVER_NS::CONTENT_TYPE] = "text/javascript"; - resp.body = tracez_script; - } - else if (StartsWith(query, "style.css")) - { - resp.headers[HTTP_SERVER_NS::CONTENT_TYPE] = "text/css"; - resp.body = tracez_style; - } - else if (query.empty() || query == "/tracez" || StartsWith(query, "index.html")) - { - resp.headers[HTTP_SERVER_NS::CONTENT_TYPE] = "text/html"; - resp.body = tracez_index; - } - else - { - resp.headers[HTTP_SERVER_NS::CONTENT_TYPE] = "text/plain"; - resp.body = "Invalid query: " + query; - } - } - - return 200; - }}; - - std::map aggregated_data_; - std::unique_ptr data_aggregator_; -}; - -} // namespace zpages -} // namespace ext -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/include/opentelemetry/ext/zpages/tracez_processor.h b/ext/include/opentelemetry/ext/zpages/tracez_processor.h deleted file mode 100644 index 081dd41117..0000000000 --- a/ext/include/opentelemetry/ext/zpages/tracez_processor.h +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include -#include -#include -#include -#include -#include - -#include "opentelemetry/ext/zpages/threadsafe_span_data.h" -#include "opentelemetry/ext/zpages/tracez_shared_data.h" -#include "opentelemetry/sdk/trace/processor.h" -#include "opentelemetry/sdk/trace/recordable.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace ext -{ -namespace zpages -{ -/* - * The span processor passes and stores running and completed recordables (casted as span_data) - * to be used by the TraceZ Data Aggregator. - */ -class TracezSpanProcessor : public opentelemetry::sdk::trace::SpanProcessor -{ -public: - /* - * Initialize a span processor. - */ - explicit TracezSpanProcessor(std::shared_ptr shared_data) noexcept - : shared_data_(shared_data) - {} - - /* - * Create a span recordable, which is span_data - * @return a newly initialized recordable - */ - std::unique_ptr MakeRecordable() noexcept override - { - return std::unique_ptr(new ThreadsafeSpanData); - } - - /* - * OnStart is called when a span starts; the recordable is cast to span_data and added to - * running_spans. - * @param span a recordable for a span that was just started - */ - void OnStart(opentelemetry::sdk::trace::Recordable &span, - const opentelemetry::trace::SpanContext &parent_context) noexcept override; - - /* - * OnEnd is called when a span ends; that span_data is moved from running_spans to - * completed_spans - * @param span a recordable for a span that was ended - */ - void OnEnd(std::unique_ptr &&span) noexcept override; - - /* - * For now, does nothing. In the future, it - * may send all ended spans that have not yet been sent to the aggregator. - * @param timeout an optional timeout. Currently, timeout does nothing. - * @return return the status of the operation. - */ - bool ForceFlush(std::chrono::microseconds timeout OPENTELEMETRY_MAYBE_UNUSED = - std::chrono::microseconds::max()) noexcept override - { - return true; - } - - /* - * Shut down the processor and do any cleanup required, which is none. - * After the call to Shutdown, subsequent calls to OnStart, OnEnd, ForceFlush - * or Shutdown will return immediately without doing anything. - * @param timeout an optional timeout, the default timeout of 0 means that no - * timeout is applied. Currently, timeout does nothing. - * @return return the status of the operation. - */ - bool Shutdown(std::chrono::microseconds timeout OPENTELEMETRY_MAYBE_UNUSED = - std::chrono::microseconds::max()) noexcept override - { - return true; - } - -private: - std::shared_ptr shared_data_; -}; -} // namespace zpages -} // namespace ext -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/include/opentelemetry/ext/zpages/tracez_shared_data.h b/ext/include/opentelemetry/ext/zpages/tracez_shared_data.h deleted file mode 100644 index 571661550f..0000000000 --- a/ext/include/opentelemetry/ext/zpages/tracez_shared_data.h +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include -#include -#include -#include -#include -#include - -#include "opentelemetry/ext/zpages/threadsafe_span_data.h" -#include "opentelemetry/sdk/trace/processor.h" -#include "opentelemetry/sdk/trace/recordable.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace ext -{ -namespace zpages -{ -/* - * The span processor passes and stores running and completed recordables (casted as span_data) - * to be used by the TraceZ Data Aggregator. - */ -class TracezSharedData -{ -public: - struct CollectedSpans - { - std::unordered_set running; - std::vector> completed; - }; - - /* - * Initialize a shared data storage. - */ - explicit TracezSharedData() noexcept {} - - /* - * Called when a span has been started. - */ - void OnStart(ThreadsafeSpanData *span) noexcept; - - /* - * Called when a span has ended. - */ - void OnEnd(std::unique_ptr &&span) noexcept; - - /* - * Returns a snapshot of all spans stored. This snapshot has a copy of the - * stored running_spans and gives ownership of completed spans to the caller. - * Stored completed_spans are cleared from the processor. Currently, - * copy-on-write is utilized where possible to minimize contention, but locks - * may be added in the future. - * @return snapshot of all currently running spans and newly completed spans - * (spans never sent while complete) at the time that the function is called - */ - CollectedSpans GetSpanSnapshot() noexcept; - -private: - mutable std::mutex mtx_; - CollectedSpans spans_; -}; -} // namespace zpages -} // namespace ext -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/include/opentelemetry/ext/zpages/zpages.h b/ext/include/opentelemetry/ext/zpages/zpages.h deleted file mode 100644 index f0242d92d7..0000000000 --- a/ext/include/opentelemetry/ext/zpages/zpages.h +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include -#include - -#include "opentelemetry/ext/zpages/tracez_data_aggregator.h" -#include "opentelemetry/ext/zpages/tracez_http_server.h" -#include "opentelemetry/ext/zpages/tracez_processor.h" -#include "opentelemetry/ext/zpages/tracez_shared_data.h" - -#include "opentelemetry/nostd/shared_ptr.h" -#include "opentelemetry/sdk/trace/tracer_provider.h" -#include "opentelemetry/trace/provider.h" - -using opentelemetry::ext::zpages::TracezDataAggregator; -using opentelemetry::ext::zpages::TracezHttpServer; -using opentelemetry::ext::zpages::TracezSharedData; -using opentelemetry::ext::zpages::TracezSpanProcessor; -using std::chrono::microseconds; - -/** - * Wrapper for zPages that initializes all the components required for zPages, - * and starts the HTTP server in the constructor and ends it in the destructor. - * The constructor and destructor for this object is private to prevent - * creation other than by calling the static function Initialize(). This follows the - * meyers singleton pattern and only a single instance of the class is allowed. - */ -class ZPages -{ -public: - /** - * This function is called if the user wishes to include zPages in their - * application. It creates a static instance of this class and replaces the - * global TracerProvider with one that delegates spans to tracez. - */ - static void Initialize() { Instance().ReplaceGlobalProvider(); } - - /** - * Returns the singletone instnace of ZPages, useful for attaching z-pages span processors to - * non-global providers. - * - * Note: This will instantiate the Tracez instance and webserver if it hasn't already been - * instantiated. - */ - static ZPages &Instance() - { - static ZPages instance; - return instance; - } - - /** Replaces the global tracer provider with an instance that exports to tracez. */ - void ReplaceGlobalProvider() - { - // GCC 4.8 can't infer the type coercion. - std::unique_ptr processor( - MakeSpanProcessor().release()); - auto tracez_provider_ = opentelemetry::nostd::shared_ptr( - new opentelemetry::sdk::trace::TracerProvider(std::move(processor))); - opentelemetry::trace::Provider::SetTracerProvider(tracez_provider_); - } - - /** Retruns a new span processor that will output to z-pages. */ - std::unique_ptr MakeSpanProcessor() - { - return std::unique_ptr(new TracezSpanProcessor(tracez_shared_)); - } - -private: - /** - * Constructor is responsible for initializing the tracer, tracez processor, - * tracez data aggregator and the tracez server. The server is also started in - * constructor. - */ - ZPages() - { - // Construct shared data nd start tracez webserver. - tracez_shared_ = std::make_shared(); - auto tracez_aggregator = - std::unique_ptr(new TracezDataAggregator(tracez_shared_)); - tracez_server_ = - std::unique_ptr(new TracezHttpServer(std::move(tracez_aggregator))); - tracez_server_->start(); - } - - ~ZPages() - { - // shut down the server when the object goes out of scope(at the end of the - // program) - tracez_server_->stop(); - } - std::shared_ptr tracez_shared_; - std::unique_ptr tracez_server_; -}; diff --git a/ext/include/opentelemetry/ext/zpages/zpages_http_server.h b/ext/include/opentelemetry/ext/zpages/zpages_http_server.h deleted file mode 100644 index abf6c1a5b4..0000000000 --- a/ext/include/opentelemetry/ext/zpages/zpages_http_server.h +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include -#include -#include -#include -#include -#include - -#include "opentelemetry/ext/http/server/http_server.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace ext -{ -namespace zpages -{ - -class zPagesHttpServer : public HTTP_SERVER_NS::HttpServer -{ -protected: - /** - * Construct the server by initializing the endpoint for serving static files, which show up on - * the web if the user is on the given host:port. Static files can be seen relative to the folder - * where the executable was ran. - * @param host is the host where the TraceZ webpages will be displayed - * @param port is the port where the TraceZ webpages will be displayed - * @param endpoint is where this specific zPage will server files - */ - zPagesHttpServer(const std::string &endpoint, - const std::string &host = "127.0.0.1", - int port = 52620) - : HttpServer(), endpoint_(endpoint) - { - std::ostringstream os; - os << host << ":" << port; - setServerName(os.str()); - addListeningPort(port); - }; - - /** - * Helper function that returns query information by isolating it from the base endpoint - * @param uri is the full query - */ - std::string GetQuery(const std::string &uri) - { - if (endpoint_.length() + 1 > uri.length()) - return uri; - return uri.substr(endpoint_.length() + 1); - } - - /** - * Helper that returns whether a str starts with pre - * @param str is the string we're checking - * @param pre is the prefix we're checking against - */ - bool StartsWith(const std::string &str, const std::string &pre) { return str.rfind(pre, 0) == 0; } - - /** - * Helper that returns the remaining string after the leftmost backslash - * @param str is the string we're extracting from - */ - std::string GetAfterSlash(const std::string &str) - { - std::size_t backslash = str.find("/"); - if (backslash == std::string::npos || backslash == str.length()) - return ""; - return str.substr(backslash + 1); - } - - /** - * Helper that returns the remaining string after the leftmost backslash - * @param str is the string we're extracting from - */ - std::string GetBeforeSlash(const std::string &str) - { - std::size_t backslash = str.find("/"); - if (backslash == std::string::npos || backslash == str.length()) - return str; - return str.substr(0, backslash); - } - - /** - * Helper that replaces all occurrences a string within a string - * @param str string to modify - * @param search substring to remove from str - * @param replacement string to replace search with whenever search is found - */ - void ReplaceAll(std::string &str, const std::string &search, const std::string &replacement) - { - size_t idx = str.find(search, 0); - while (idx != std::string::npos) - { - str.replace(idx, search.length(), replacement); - idx = str.find(search, idx); - } - } - - /** - * Helper that replaces all special HTML/address base encoded characters - * into what they're originally supposed to be - * @param str string to conduct replacements for - */ - void ReplaceHtmlChars(std::string &str) - { - for (const auto &replace_pair : replace_map_) - { - ReplaceAll(str, replace_pair.first, replace_pair.second); - } - } - - const std::string endpoint_; - const std::unordered_map replace_map_ = {{"%20", " "}}; -}; - -} // namespace zpages -} // namespace ext -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/src/CMakeLists.txt b/ext/src/CMakeLists.txt index bc1f614eb9..65aaa307c0 100644 --- a/ext/src/CMakeLists.txt +++ b/ext/src/CMakeLists.txt @@ -1,10 +1,6 @@ # Copyright The OpenTelemetry Authors # SPDX-License-Identifier: Apache-2.0 -if(WITH_ZPAGES) - add_subdirectory(zpages) -endif() - if(WITH_HTTP_CLIENT_CURL) add_subdirectory(http/client/curl) endif() diff --git a/ext/src/zpages/BUILD b/ext/src/zpages/BUILD deleted file mode 100644 index ce23147df5..0000000000 --- a/ext/src/zpages/BUILD +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright The OpenTelemetry Authors -# SPDX-License-Identifier: Apache-2.0 - -package(default_visibility = ["//visibility:public"]) - -cc_library( - name = "zpages", - srcs = glob(["**/*.cc"]), - hdrs = glob(["**/*.h"]), - include_prefix = "ext/zpages", - deps = [ - "//api", - "//ext:headers", - "//sdk:headers", - "@github_nlohmann_json//:json", - ], -) diff --git a/ext/src/zpages/CMakeLists.txt b/ext/src/zpages/CMakeLists.txt deleted file mode 100644 index 8ff225112b..0000000000 --- a/ext/src/zpages/CMakeLists.txt +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright The OpenTelemetry Authors -# SPDX-License-Identifier: Apache-2.0 - -add_library( - opentelemetry_zpages - tracez_processor.cc - tracez_shared_data.cc - tracez_data_aggregator.cc - ../../include/opentelemetry/ext/zpages/tracez_shared_data.h - ../../include/opentelemetry/ext/zpages/tracez_processor.h - ../../include/opentelemetry/ext/zpages/tracez_data_aggregator.h - ../../include/opentelemetry/ext/zpages/tracez_http_server.h) - -set_target_properties(opentelemetry_zpages PROPERTIES EXPORT_NAME zpages) -set_target_version(opentelemetry_zpages) - -target_link_libraries(opentelemetry_zpages PUBLIC opentelemetry_ext - opentelemetry_trace) - -if(OPENTELEMETRY_INSTALL) - install( - TARGETS opentelemetry_zpages - EXPORT "${PROJECT_NAME}-target" - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) -endif() diff --git a/ext/src/zpages/README.md b/ext/src/zpages/README.md deleted file mode 100644 index f182fd43f3..0000000000 --- a/ext/src/zpages/README.md +++ /dev/null @@ -1,53 +0,0 @@ -# zPages - -## Overview - -zPages are a quick and light way to view tracing and metrics information on -standard OpenTelemetry C++ instrumented applications. It requires no external -dependencies or backend setup. See more information in the OTel zPages -experimental -[spec](https://github.com/open-telemetry/opentelemetry-specification/blob/5b86d4b6c42e6d1e47d9155ac1e2e27f0f0b7769/experimental/trace/zpages.md). -OTel C++ currently only offers Tracez; future zPages to potentially add include -TraceConfigz, RPCz, and Statsz. Events and links need to be added to Tracez. - -## Usage - -> TODO: Add CMake instructions - -1: Add the following 2 lines of code - -* `#include opentelemetry/ext/zpages/zpages.h // include zPages` -* `zpages::Initialize; // start up zPages in your app, before any tracing/span - code` - -2: Build and run your application normally - -For example, you can do this for the zPages example while at the root -`opentelemetry-cpp` directory with: - -```sh -bazel build //examples/zpages:zpages_example -bazel-bin/examples/zpages/zpages_example -``` - -If you look at the [zPages example's source -code](https://github.com/open-telemetry/opentelemetry-cpp/blob/main/examples/zpages/zpages_example.cc), -it demonstrates adding zPages, manual application instrumentation (which sends -data to zPages for viewing), and simulated use cases for zPages. - -3: View zPages at `http://localhost:3000/tracez` - -## More Information - -* OTel zPages experimental - [spec](https://github.com/open-telemetry/opentelemetry-specification/blob/5b86d4b6c42e6d1e47d9155ac1e2e27f0f0b7769/experimental/trace/zpages.md) -* [zPages General Direction Spec - (OTEP)](https://github.com/open-telemetry/oteps/blob/main/text/0110-z-pages.md) -* OTel C++ Design Docs - * [Tracez Span - Processor](https://docs.google.com/document/d/1kO4iZARYyr-EGBlY2VNM3ELU3iw6ZrC58Omup_YT-fU/edit#) - * [Tracez Data - Aggregator](https://docs.google.com/document/d/1ziKFgvhXFfRXZjOlAHQRR-TzcNcTXzg1p2I9oPCEIoU/edit?ts=5ef0d177#heading=h.5irk4csrpu0y) - * [Tracez Http - Server](https://docs.google.com/document/d/1U1V8QZ5LtGl4Mich-aJ6KZGLHrMIE8pWyspmzvnIefI/edit#) - * includes reference pictures of the zPages/Tracez UI diff --git a/ext/src/zpages/tracez_data_aggregator.cc b/ext/src/zpages/tracez_data_aggregator.cc deleted file mode 100644 index 993fc182ce..0000000000 --- a/ext/src/zpages/tracez_data_aggregator.cc +++ /dev/null @@ -1,189 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#include "opentelemetry/ext/zpages/tracez_data_aggregator.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace ext -{ -namespace zpages -{ - -TracezDataAggregator::TracezDataAggregator(std::shared_ptr shared_data, - milliseconds update_interval) -{ - tracez_shared_data_ = shared_data; - - // Start a thread that calls AggregateSpans periodically or till notified. - execute_.store(true, std::memory_order_release); - aggregate_spans_thread_ = std::thread([this, update_interval]() { - while (execute_.load(std::memory_order_acquire)) - { - std::unique_lock lock(mtx_); - AggregateSpans(); - cv_.wait_for(lock, update_interval); - } - }); -} - -TracezDataAggregator::~TracezDataAggregator() -{ - // Notify and join the thread so object can be destroyed without wait for wake - if (execute_.load(std::memory_order_acquire)) - { - execute_.store(false, std::memory_order_release); - cv_.notify_one(); - aggregate_spans_thread_.join(); - } -} - -std::map TracezDataAggregator::GetAggregatedTracezData() -{ - std::unique_lock lock(mtx_); - return aggregated_tracez_data_; -} - -LatencyBoundary TracezDataAggregator::FindLatencyBoundary( - std::unique_ptr &span_data) -{ - const auto &span_data_duration = span_data->GetDuration(); - for (unsigned int boundary = 0; boundary < kLatencyBoundaries.size() - 1; boundary++) - { - if (span_data_duration < kLatencyBoundaries[boundary + 1]) - return (LatencyBoundary)boundary; - } - return LatencyBoundary::k100SecondToMax; -} - -void TracezDataAggregator::InsertIntoSampleSpanList(std::list &sample_spans, - ThreadsafeSpanData &span_data) -{ - /** - * Check to see if the sample span list size exceeds the set limit, if it does - * free up memory and remove the earliest inserted sample before appending - */ - if (sample_spans.size() == kMaxNumberOfSampleSpans) - { - sample_spans.pop_front(); - } - sample_spans.push_back(ThreadsafeSpanData(span_data)); -} - -void TracezDataAggregator::ClearRunningSpanData() -{ - auto it = aggregated_tracez_data_.begin(); - while (it != aggregated_tracez_data_.end()) - { - it->second.running_span_count = 0; - it->second.sample_running_spans.clear(); - - // Check if any data exists in the struct, if not delete entry - bool is_completed_span_count_zero = true; - for (const auto &completed_span_count : it->second.completed_span_count_per_latency_bucket) - { - if (completed_span_count > 0) - is_completed_span_count_zero = false; - } - - if (it->second.error_span_count == 0 && is_completed_span_count_zero) - { - it = aggregated_tracez_data_.erase(it); - } - else - { - ++it; - } - } -} - -void TracezDataAggregator::AggregateStatusOKSpan(std::unique_ptr &ok_span) -{ - // Find and update boundary of aggregated data that span belongs - auto boundary_name = FindLatencyBoundary(ok_span); - - // Get the data for name in aggrgation and update count and sample spans - auto &tracez_data = aggregated_tracez_data_.at(ok_span->GetName().data()); - InsertIntoSampleSpanList(tracez_data.sample_latency_spans[boundary_name], *ok_span.get()); - tracez_data.completed_span_count_per_latency_bucket[boundary_name]++; -} - -void TracezDataAggregator::AggregateStatusErrorSpan(std::unique_ptr &error_span) -{ - // Get data for name in aggregation and update count and sample spans - auto &tracez_data = aggregated_tracez_data_.at(error_span->GetName().data()); - InsertIntoSampleSpanList(tracez_data.sample_error_spans, *error_span.get()); - tracez_data.error_span_count++; -} - -void TracezDataAggregator::AggregateCompletedSpans( - std::vector> &completed_spans) -{ - for (auto &completed_span : completed_spans) - { - std::string span_name = completed_span->GetName().data(); - - if (aggregated_tracez_data_.find(span_name) == aggregated_tracez_data_.end()) - { - aggregated_tracez_data_[span_name] = TracezData(); - } - - if (completed_span->GetStatus() == trace::StatusCode::kOk || - completed_span->GetStatus() == trace::StatusCode::kUnset) - AggregateStatusOKSpan(completed_span); - else - AggregateStatusErrorSpan(completed_span); - } -} - -void TracezDataAggregator::AggregateRunningSpans( - std::unordered_set &running_spans) -{ - for (auto &running_span : running_spans) - { - std::string span_name = running_span->GetName().data(); - - if (aggregated_tracez_data_.find(span_name) == aggregated_tracez_data_.end()) - { - aggregated_tracez_data_[span_name] = TracezData(); - } - - auto &tracez_data = aggregated_tracez_data_[span_name]; - InsertIntoSampleSpanList(aggregated_tracez_data_[span_name].sample_running_spans, - *running_span); - tracez_data.running_span_count++; - } -} - -void TracezDataAggregator::AggregateSpans() -{ - auto span_snapshot = tracez_shared_data_->GetSpanSnapshot(); - /** - * TODO: At this time in the project, there is no way of uniquely identifying - * a span(their id's are not being set yet). - * If in the future this is added then clearing of running spans will not bee - * required. - * For now this step of clearing and recalculating running span data is - * required because it is unknown which spans have moved from running to - * completed since the previous call. Additionally, the span name can change - * for spans while they are running. - * - * A better approach for identifying moved spans would have been to map - * span id to span name, find these span names in the aggregated data and then - * delete only this information for running span data as opposed to clearing - * all running span data. However this cannot be done at this time because, - * unique identifiers to span data have not been added yet. - * - * A few things to note: - * i) Duplicate running spans may be received from the span processor in one - * multiple successive calls to this function. - * ii) Only the newly completed spans are received by this function. - * Completed spans will not be seen more than once - **/ - ClearRunningSpanData(); - AggregateCompletedSpans(span_snapshot.completed); - AggregateRunningSpans(span_snapshot.running); -} - -} // namespace zpages -} // namespace ext -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/src/zpages/tracez_http_server.cc b/ext/src/zpages/tracez_http_server.cc deleted file mode 100644 index a5d0072787..0000000000 --- a/ext/src/zpages/tracez_http_server.cc +++ /dev/null @@ -1,163 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#include "opentelemetry/ext/zpages/tracez_http_server.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace ext -{ -namespace zpages -{ -namespace nostd = opentelemetry::nostd; - -json TracezHttpServer::GetAggregations() -{ - aggregated_data_ = data_aggregator_->GetAggregatedTracezData(); - auto counts_json = json::array(); - - for (const auto &aggregation_group : aggregated_data_) - { - const auto &buckets = aggregation_group.second; - const auto &complete_ok_counts = buckets.completed_span_count_per_latency_bucket; - - auto latency_counts = json::array(); - for (unsigned int boundary = 0; boundary < kLatencyBoundaries.size(); boundary++) - { - latency_counts.push_back(complete_ok_counts[boundary]); - } - - counts_json.push_back({{"name", aggregation_group.first}, - {"error", buckets.error_span_count}, - {"running", buckets.running_span_count}, - {"latency", latency_counts}}); - } - return counts_json; -} - -json TracezHttpServer::GetRunningSpansJSON(const std::string &name) -{ - auto running_json = json::array(); - - auto grouping = aggregated_data_.find(name); - - if (grouping != aggregated_data_.end()) - { - const auto &running_samples = grouping->second.sample_running_spans; - for (const auto &sample : running_samples) - { - running_json.push_back({ - {"spanid", std::string(reinterpret_cast(sample.GetSpanId().Id().data()))}, - {"parentid", - std::string(reinterpret_cast(sample.GetParentSpanId().Id().data()))}, - {"traceid", std::string(reinterpret_cast(sample.GetTraceId().Id().data()))}, - {"start", sample.GetStartTime().time_since_epoch().count()}, - {"attributes", GetAttributesJSON(sample)}, - }); - } - } - return running_json; -} - -json TracezHttpServer::GetErrorSpansJSON(const std::string &name) -{ - auto error_json = json::array(); - - auto grouping = aggregated_data_.find(name); - - if (grouping != aggregated_data_.end()) - { - const auto &error_samples = grouping->second.sample_error_spans; - for (const auto &sample : error_samples) - { - error_json.push_back({ - {"spanid", std::string(reinterpret_cast(sample.GetSpanId().Id().data()))}, - {"parentid", - std::string(reinterpret_cast(sample.GetParentSpanId().Id().data()))}, - {"traceid", std::string(reinterpret_cast(sample.GetTraceId().Id().data()))}, - {"start", sample.GetStartTime().time_since_epoch().count()}, - {"status", (unsigned short)sample.GetStatus()}, - {"attributes", GetAttributesJSON(sample)}, - }); - } - } - return error_json; -} - -json TracezHttpServer::GetLatencySpansJSON(const std::string &name, int latency_range_index) -{ - auto latency_json = json::array(); - - auto grouping = aggregated_data_.find(name); - - if (grouping != aggregated_data_.end()) - { - const auto &latency_samples = grouping->second.sample_latency_spans[latency_range_index]; - for (const auto &sample : latency_samples) - { - latency_json.push_back({ - {"spanid", std::string(reinterpret_cast(sample.GetSpanId().Id().data()))}, - {"parentid", - std::string(reinterpret_cast(sample.GetParentSpanId().Id().data()))}, - {"traceid", std::string(reinterpret_cast(sample.GetTraceId().Id().data()))}, - {"start", sample.GetStartTime().time_since_epoch().count()}, - {"duration", sample.GetDuration().count()}, - {"attributes", GetAttributesJSON(sample)}, - }); - } - } - return latency_json; -} - -json TracezHttpServer::GetAttributesJSON( - const opentelemetry::ext::zpages::ThreadsafeSpanData &sample) -{ - auto attributes_json = json::object(); - for (const auto &sample_attribute : sample.GetAttributes()) - { - auto &key = sample_attribute.first; - auto &val = sample_attribute.second; // OwnedAttributeValue - - /* Convert variant types to into their nonvariant form. This is done this way because - the frontend and JSON doesn't care about type, and variant's get function only allows - const integers or literals */ - - switch (val.index()) - { - case 0: - attributes_json[key] = nostd::get<0>(val); - break; - case 1: - attributes_json[key] = nostd::get<1>(val); - break; - case 2: - attributes_json[key] = nostd::get<2>(val); - break; - case 3: - attributes_json[key] = nostd::get<3>(val); - break; - case 4: - attributes_json[key] = nostd::get<4>(val); - break; - case 5: - attributes_json[key] = nostd::get<5>(val); - break; - case 6: - attributes_json[key] = nostd::get<6>(val); - break; - case 7: - attributes_json[key] = nostd::get<7>(val); - break; - case 8: - attributes_json[key] = nostd::get<8>(val); - break; - case 9: - attributes_json[key] = nostd::get<9>(val); - break; - } - } - return attributes_json; -} - -} // namespace zpages -} // namespace ext -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/src/zpages/tracez_processor.cc b/ext/src/zpages/tracez_processor.cc deleted file mode 100644 index e7d68350d7..0000000000 --- a/ext/src/zpages/tracez_processor.cc +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#include "opentelemetry/ext/zpages/tracez_processor.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace ext -{ -namespace zpages -{ -namespace trace_sdk = opentelemetry::sdk::trace; - -void TracezSpanProcessor::OnStart(trace_sdk::Recordable &span, - const opentelemetry::trace::SpanContext & - /* parent_context */) noexcept -{ - shared_data_->OnStart(static_cast(&span)); -} - -void TracezSpanProcessor::OnEnd(std::unique_ptr &&span) noexcept -{ - shared_data_->OnEnd( - std::unique_ptr(static_cast(span.release()))); -} - -} // namespace zpages -} // namespace ext -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/src/zpages/tracez_shared_data.cc b/ext/src/zpages/tracez_shared_data.cc deleted file mode 100644 index 4f4e4f5e91..0000000000 --- a/ext/src/zpages/tracez_shared_data.cc +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#include "opentelemetry/ext/zpages/tracez_shared_data.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace ext -{ -namespace zpages -{ - -void TracezSharedData::OnStart(ThreadsafeSpanData *span) noexcept -{ - std::lock_guard lock(mtx_); - spans_.running.insert(span); -} - -void TracezSharedData::OnEnd(std::unique_ptr &&span) noexcept -{ - std::lock_guard lock(mtx_); - auto span_it = spans_.running.find(span.get()); - if (span_it != spans_.running.end()) - { - spans_.running.erase(span_it); - spans_.completed.push_back(std::unique_ptr(span.release())); - } -} - -TracezSharedData::CollectedSpans TracezSharedData::GetSpanSnapshot() noexcept -{ - CollectedSpans snapshot; - std::lock_guard lock(mtx_); - snapshot.running = spans_.running; - snapshot.completed = std::move(spans_.completed); - spans_.completed.clear(); - return snapshot; -} - -} // namespace zpages -} // namespace ext -OPENTELEMETRY_END_NAMESPACE diff --git a/ext/test/CMakeLists.txt b/ext/test/CMakeLists.txt index 2d2cc0d9fa..cc3d4cd1e1 100644 --- a/ext/test/CMakeLists.txt +++ b/ext/test/CMakeLists.txt @@ -1,9 +1,6 @@ # Copyright The OpenTelemetry Authors # SPDX-License-Identifier: Apache-2.0 -if(WITH_ZPAGES) - add_subdirectory(zpages) -endif() add_subdirectory(http) if(BUILD_W3CTRACECONTEXT_TEST) add_subdirectory(w3c_tracecontext_test) diff --git a/ext/test/zpages/BUILD b/ext/test/zpages/BUILD deleted file mode 100644 index e3371b8e93..0000000000 --- a/ext/test/zpages/BUILD +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright The OpenTelemetry Authors -# SPDX-License-Identifier: Apache-2.0 - -cc_test( - name = "threadsafe_span_data_tests", - srcs = [ - "threadsafe_span_data_test.cc", - ], - tags = ["test"], - deps = [ - "//ext/src/zpages", - "//sdk/src/trace", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "tracez_data_aggregator_tests", - srcs = [ - "tracez_data_aggregator_test.cc", - ], - tags = ["test"], - deps = [ - "//ext/src/zpages", - "//sdk/src/trace", - "@com_google_googletest//:gtest_main", - ], -) - -cc_test( - name = "tracez_processor_tests", - srcs = [ - "tracez_processor_test.cc", - ], - tags = ["test"], - deps = [ - "//ext/src/zpages", - "//sdk/src/trace", - "@com_google_googletest//:gtest_main", - ], -) diff --git a/ext/test/zpages/CMakeLists.txt b/ext/test/zpages/CMakeLists.txt deleted file mode 100644 index f3ecf5cdf2..0000000000 --- a/ext/test/zpages/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright The OpenTelemetry Authors -# SPDX-License-Identifier: Apache-2.0 - -foreach(testname tracez_processor_test tracez_data_aggregator_test - threadsafe_span_data_test) - add_executable(${testname} "${testname}.cc") - target_link_libraries(${testname} ${GTEST_BOTH_LIBRARIES} - ${CMAKE_THREAD_LIBS_INIT} opentelemetry_zpages) - - gtest_add_tests( - TARGET ${testname} - TEST_PREFIX ext. - TEST_LIST ${testname}) -endforeach() diff --git a/ext/test/zpages/threadsafe_span_data_test.cc b/ext/test/zpages/threadsafe_span_data_test.cc deleted file mode 100644 index cee29672ed..0000000000 --- a/ext/test/zpages/threadsafe_span_data_test.cc +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#include "opentelemetry/ext/zpages/threadsafe_span_data.h" -#include "opentelemetry/nostd/variant.h" -#include "opentelemetry/trace/span_id.h" -#include "opentelemetry/trace/trace_id.h" - -#include -#include - -using opentelemetry::ext::zpages::ThreadsafeSpanData; -using opentelemetry::sdk::common::AttributeConverter; -using opentelemetry::sdk::common::OwnedAttributeValue; - -namespace trace_api = opentelemetry::trace; - -TEST(ThreadsafeSpanData, DefaultValues) -{ - trace_api::SpanContext empty_span_context{false, false}; - trace_api::SpanId zero_span_id; - ThreadsafeSpanData data; - - ASSERT_EQ(data.GetTraceId(), empty_span_context.trace_id()); - ASSERT_EQ(data.GetSpanId(), empty_span_context.span_id()); - ASSERT_EQ(data.GetSpanContext(), empty_span_context); - ASSERT_EQ(data.GetParentSpanId(), zero_span_id); - ASSERT_EQ(data.GetName(), ""); - ASSERT_EQ(data.GetStatus(), trace_api::StatusCode::kUnset); - ASSERT_EQ(data.GetDescription(), ""); - ASSERT_EQ(data.GetStartTime().time_since_epoch(), std::chrono::nanoseconds(0)); - ASSERT_EQ(data.GetDuration(), std::chrono::nanoseconds(0)); - ASSERT_EQ(data.GetAttributes().size(), 0); -} - -TEST(ThreadsafeSpanData, Set) -{ - constexpr uint8_t trace_id_buf[] = {1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8}; - constexpr uint8_t span_id_buf[] = {1, 2, 3, 4, 5, 6, 7, 8}; - constexpr uint8_t parent_span_id_buf[] = {8, 7, 6, 5, 4, 3, 2, 1}; - trace_api::TraceId trace_id{trace_id_buf}; - trace_api::SpanId span_id{span_id_buf}; - trace_api::SpanId parent_span_id{parent_span_id_buf}; - const auto trace_state = trace_api::TraceState::GetDefault()->Set("key1", "value"); - const trace_api::SpanContext span_context{ - trace_id, span_id, trace_api::TraceFlags{trace_api::TraceFlags::kIsSampled}, true, - trace_state}; - opentelemetry::common::SystemTimestamp now(std::chrono::system_clock::now()); - - ThreadsafeSpanData data; - data.SetIdentity(span_context, parent_span_id); - data.SetName("span name"); - data.SetSpanKind(trace_api::SpanKind::kServer); - data.SetStatus(trace_api::StatusCode::kOk, "description"); - data.SetStartTime(now); - data.SetDuration(std::chrono::nanoseconds(1000000)); - data.SetAttribute("attr1", (int64_t)314159); - data.AddEvent("event1", now); - - ASSERT_EQ(data.GetTraceId(), trace_id); - ASSERT_EQ(data.GetSpanId(), span_id); - ASSERT_EQ(data.GetSpanContext(), span_context); - std::string trace_state_key1_value; - ASSERT_EQ(data.GetSpanContext().trace_state()->Get("key1", trace_state_key1_value), true); - ASSERT_EQ(trace_state_key1_value, "value"); - ASSERT_EQ(data.GetParentSpanId(), parent_span_id); - ASSERT_EQ(data.GetName(), "span name"); - ASSERT_EQ(data.GetStatus(), trace_api::StatusCode::kOk); - ASSERT_EQ(data.GetDescription(), "description"); - ASSERT_EQ(data.GetStartTime().time_since_epoch(), now.time_since_epoch()); - ASSERT_EQ(data.GetDuration(), std::chrono::nanoseconds(1000000)); - ASSERT_EQ(opentelemetry::nostd::get(data.GetAttributes().at("attr1")), 314159); -} diff --git a/ext/test/zpages/tracez_data_aggregator_test.cc b/ext/test/zpages/tracez_data_aggregator_test.cc deleted file mode 100644 index 5139c9e914..0000000000 --- a/ext/test/zpages/tracez_data_aggregator_test.cc +++ /dev/null @@ -1,698 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#include "opentelemetry/ext/zpages/tracez_data_aggregator.h" - -#include - -#include "opentelemetry/ext/zpages/tracez_processor.h" -#include "opentelemetry/sdk/resource/resource.h" -#include "opentelemetry/sdk/trace/recordable.h" -#include "opentelemetry/sdk/trace/tracer.h" - -using namespace opentelemetry::sdk::trace; -using namespace opentelemetry::ext::zpages; -namespace nostd = opentelemetry::nostd; -namespace common = opentelemetry::common; -using opentelemetry::common::SteadyTimestamp; -using opentelemetry::trace::Span; - -const std::string span_name1 = "span 1"; -const std::string span_name2 = "span 2"; -const std::string span_name3 = "span 3"; - -/** - * TODO: Due to the absence of way to simulate the passing of time in the - * testing framework, synthetic delays had to be added in the tests to get the - * object in question to perform correctly. Later on if something like this is - * added the tests should be modified accordingly so that there is no external - * dependency. - * Additionally later on it would be better check for the span id(when set) - * rather than span name. - */ - -/** Test fixture for setting up the data aggregator and tracer for each test **/ -class TracezDataAggregatorTest : public ::testing::Test -{ -protected: - void SetUp() override - { - std::shared_ptr shared_data(new TracezSharedData()); - auto resource = opentelemetry::sdk::resource::Resource::Create({}); - std::unique_ptr processor(new TracezSpanProcessor(shared_data)); - std::vector> processors; - processors.push_back(std::move(processor)); - - auto context = std::make_shared(std::move(processors), resource); - tracer = std::shared_ptr(new Tracer(context)); - tracez_data_aggregator = std::unique_ptr( - new TracezDataAggregator(shared_data, milliseconds(10))); - } - - std::unique_ptr tracez_data_aggregator; - std::shared_ptr tracer; -}; - -/** - * Helper function to check if the counts of running, error and latency spans - * match what is expected - */ -void VerifySpanCountsInTracezData( - const std::string &span_name, - const TracezData &aggregated_data, - size_t running_span_count, - size_t error_span_count, - std::array completed_span_count_per_latency_bucket) -{ - // Asserts are needed to check the size of the container because they may need - // to be checked and if size checks fail it must be stopped - EXPECT_EQ(aggregated_data.running_span_count, running_span_count) - << " Count of running spans incorrect for " << span_name << "\n"; - - EXPECT_EQ(aggregated_data.sample_running_spans.size(), - std::min(running_span_count, kMaxNumberOfSampleSpans)) - << " Size of sample running spans incorrect for " << span_name << "\n"; - - EXPECT_EQ(aggregated_data.error_span_count, error_span_count) - << " Count of error spans incorrect for " << span_name << "\n"; - - EXPECT_EQ(aggregated_data.sample_error_spans.size(), - std::min(error_span_count, kMaxNumberOfSampleSpans)) - << " Count of running spans incorrect for " << span_name << "\n"; - - for (unsigned int boundary = 0; boundary < kLatencyBoundaries.size(); boundary++) - { - EXPECT_EQ(aggregated_data.completed_span_count_per_latency_bucket[boundary], - completed_span_count_per_latency_bucket[boundary]) - << " Count of completed spans in latency boundary " << boundary << " incorrect for " - << span_name << "\n"; - EXPECT_EQ(aggregated_data.sample_latency_spans[boundary].size(), - std::min(completed_span_count_per_latency_bucket[boundary], - kMaxNumberOfSampleSpans)) - << " Count of sample completed spans in latency boundary " << boundary << " incorrect for " - << span_name << "\n"; - } -} - -/**************************** No Span Test ************************************/ - -/** Test to check if data aggregator works as expected when there are no spans - * **/ -TEST_F(TracezDataAggregatorTest, NoSpans) -{ - auto data = tracez_data_aggregator->GetAggregatedTracezData(); - ASSERT_EQ(data.size(), 0); -} - -/*********************** Single span tests ************************************/ - -/** Test to check if data aggregator works as expected when there are - * is exactly a single running span **/ -TEST_F(TracezDataAggregatorTest, SingleRunningSpan) -{ - // Start the span get the data - auto span_first = tracer->StartSpan(span_name1); - std::this_thread::sleep_for(milliseconds(500)); - auto data = tracez_data_aggregator->GetAggregatedTracezData(); - - // Check to see if span name exists - ASSERT_EQ(data.size(), 1); - ASSERT_TRUE(data.find(span_name1) != data.end()); - auto &aggregated_data = data.at(span_name1); - - // Verify span counts then content of spans - VerifySpanCountsInTracezData(span_name1, aggregated_data, 1, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0}); - - ASSERT_EQ(aggregated_data.sample_running_spans.size(), 1); - ASSERT_EQ(aggregated_data.sample_running_spans.front().GetName().data(), span_name1); - span_first->End(); -} - -/** Test to check if data aggregator works as expected when there is exactly one - * completed span **/ -TEST_F(TracezDataAggregatorTest, SingleCompletedSpan) -{ - // Start and end the span at a specified times - opentelemetry::trace::StartSpanOptions start; - start.start_steady_time = SteadyTimestamp(nanoseconds(10)); - opentelemetry::trace::EndSpanOptions end; - end.end_steady_time = SteadyTimestamp(nanoseconds(40)); - tracer->StartSpan(span_name1, start)->End(end); - - // Get the data and make sure span name exists in the data - std::this_thread::sleep_for(milliseconds(500)); - auto data = tracez_data_aggregator->GetAggregatedTracezData(); - ASSERT_EQ(data.size(), 1); - ASSERT_TRUE(data.find(span_name1) != data.end()); - - auto &aggregated_data = data.at(span_name1); - // Make sure counts of spans are in order - VerifySpanCountsInTracezData(span_name1, aggregated_data, 0, 0, {1, 0, 0, 0, 0, 0, 0, 0, 0}); - - // Check if the span is correctly updated in the first boundary - ASSERT_EQ(aggregated_data.sample_latency_spans[LatencyBoundary::k0MicroTo10Micro].size(), 1); - ASSERT_EQ(aggregated_data.sample_latency_spans[LatencyBoundary::k0MicroTo10Micro] - .front() - .GetDuration() - .count(), - 30); -} - -/** Test to check if data aggregator works as expected when there is exactly - * one error span **/ -TEST_F(TracezDataAggregatorTest, SingleErrorSpan) -{ - // Start and end a single error span - auto span = tracer->StartSpan(span_name1); - span->SetStatus(opentelemetry::trace::StatusCode::kError, "span cancelled"); - span->End(); - std::this_thread::sleep_for(milliseconds(500)); - auto data = tracez_data_aggregator->GetAggregatedTracezData(); - - // Check to see if span name can be found in aggregation - ASSERT_EQ(data.size(), 1); - ASSERT_TRUE(data.find(span_name1) != data.end()); - - auto &aggregated_data = data.at(span_name1); - // Make sure counts of spans are in order - VerifySpanCountsInTracezData(span_name1, aggregated_data, 0, 1, {0, 0, 0, 0, 0, 0, 0, 0, 0}); - - // Check the value of the error span introduced - ASSERT_EQ(aggregated_data.sample_error_spans.size(), 1); - ASSERT_EQ(aggregated_data.sample_error_spans.front().GetName().data(), span_name1); -} - -/************************* Multiple span tests ********************************/ - -/** Test to check if multiple running spans behaves as expected**/ -TEST_F(TracezDataAggregatorTest, MultipleRunningSpans) -{ - // A container that maps a span name to the number of spans to start with that - // span name - std::unordered_map running_span_name_to_count({ - {span_name1, 1}, - {span_name2, 2}, - {span_name3, 3}, - }); - - // Start and store spans based on the above map - std::vector> running_span_container; - for (auto span_name : running_span_name_to_count) - { - for (int count = 0; count < span_name.second; count++) - running_span_container.push_back(tracer->StartSpan(span_name.first)); - } - - // give time for aggregation and then get data - std::this_thread::sleep_for(milliseconds(500)); - auto data = tracez_data_aggregator->GetAggregatedTracezData(); - ASSERT_EQ(data.size(), running_span_name_to_count.size()); - - // Check to see if the running span counts were updated correctly - for (auto &span_name : running_span_name_to_count) - { - ASSERT_TRUE(data.find(span_name.first) != data.end()); - - // Make sure counts of spans are in order - VerifySpanCountsInTracezData(span_name.first, data.at(span_name.first), span_name.second, 0, - {0, 0, 0, 0, 0, 0, 0, 0, 0}); - - ASSERT_EQ(data.at(span_name.first).sample_running_spans.size(), span_name.second); - for (auto &span_sample : data.at(span_name.first).sample_running_spans) - { - ASSERT_EQ(span_sample.GetName().data(), span_name.first); - } - } - - for (auto i = running_span_container.begin(); i != running_span_container.end(); i++) - (*i)->End(); -} - -/** Test to check if multiple completed spans updates the aggregated data - * correctly **/ -TEST_F(TracezDataAggregatorTest, MultipleCompletedSpan) -{ - // Start spans with span name and the corresponding durations in one of the 9 - // latency buckets - const std::unordered_map>> - span_name_to_duration( - {{span_name1, {{nanoseconds(10), nanoseconds(4600)}, {}, {}, {}, {}, {}, {}, {}, {}}}, - {span_name2, - {{}, - {nanoseconds(38888), nanoseconds(98768)}, - {nanoseconds(983251)}, - {}, - {}, - {}, - {}, - {}, - {}}}, - {span_name3, - {{}, - {}, - {}, - {nanoseconds(1234567), nanoseconds(1234567)}, - {}, - {}, - {}, - {}, - {nanoseconds(9999999999999)}}}}); - opentelemetry::trace::StartSpanOptions start; - opentelemetry::trace::EndSpanOptions end; - for (auto &span : span_name_to_duration) - { - for (auto &buckets : span.second) - { - for (auto &duration : buckets) - { - long long int end_time = duration.count() + 1; - start.start_steady_time = SteadyTimestamp(nanoseconds(1)); - end.end_steady_time = SteadyTimestamp(nanoseconds(end_time)); - tracer->StartSpan(span.first, start)->End(end); - } - } - } - - // Give time for aggregation and get data - std::this_thread::sleep_for(milliseconds(500)); - auto data = tracez_data_aggregator->GetAggregatedTracezData(); - - ASSERT_EQ(data.size(), span_name_to_duration.size()); - - for (auto &span : span_name_to_duration) - { - ASSERT_TRUE(data.find(span.first) != data.end()); - auto &aggregated_data = data.at(span.first); - - // Make sure counts of spans are in order - VerifySpanCountsInTracezData( - span.first, aggregated_data, 0, 0, - {(unsigned int)span.second[0].size(), (unsigned int)span.second[1].size(), - (unsigned int)span.second[2].size(), (unsigned int)span.second[3].size(), - (unsigned int)span.second[4].size(), (unsigned int)span.second[5].size(), - (unsigned int)span.second[6].size(), (unsigned int)span.second[7].size(), - (unsigned int)span.second[8].size()}); - - for (unsigned int boundary = 0; boundary < kLatencyBoundaries.size(); boundary++) - { - ASSERT_EQ(aggregated_data.sample_latency_spans[boundary].size(), - span.second[boundary].size()); - auto latency_sample = aggregated_data.sample_latency_spans[boundary].begin(); - for (unsigned int idx = 0; idx < span.second[boundary].size(); idx++) - { - ASSERT_EQ(span.second[boundary][idx].count(), latency_sample->GetDuration().count()); - latency_sample = std::next(latency_sample); - } - } - } -} - -/** - * This test checks to see if the aggregated data is updated correctly - * when there are multiple error spans. - * It checks both the count of error spans and the error samples - */ -TEST_F(TracezDataAggregatorTest, MultipleErrorSpans) -{ - // Container to store the span names --> error messges for the span name - std::unordered_map> span_name_to_error( - {{span_name1, {"span 1 error"}}, - {span_name2, {"span 2 error 1", "span 2 error 2"}}, - {span_name3, - {"span 3 error 1", "span 3 error 2", "span 3 error 3", "span 3 error 4", - "span 3 error 5"}}}); - - // Start spans with the error messages based on the map - for (auto &span_error : span_name_to_error) - { - for (auto error_desc : span_error.second) - { - auto span = tracer->StartSpan(span_error.first); - span->SetStatus(opentelemetry::trace::StatusCode::kError, error_desc); - span->End(); - } - } - - // Give some time and then get data - std::this_thread::sleep_for(milliseconds(500)); - auto data = tracez_data_aggregator->GetAggregatedTracezData(); - ASSERT_EQ(data.size(), span_name_to_error.size()); - - // Check if error spans were updated correctly for the different span names - for (auto &span_error : span_name_to_error) - { - // First try to find the span name in aggregation, then check the count of - // the error spans and then check values - ASSERT_TRUE(data.find(span_error.first) != data.end()); - - auto &aggregated_data = data.at(span_error.first); - - // Make sure counts of spans are in order - VerifySpanCountsInTracezData(span_error.first, aggregated_data, 0, span_error.second.size(), - {0, 0, 0, 0, 0, 0, 0, 0, 0}); - ASSERT_EQ(aggregated_data.error_span_count, span_error.second.size()); - - auto error_sample = aggregated_data.sample_error_spans.begin(); - for (unsigned int idx = 0; idx < span_error.second.size(); idx++) - { - ASSERT_EQ(span_error.second[idx], error_sample->GetDescription()); - error_sample = std::next(error_sample); - } - } -} - -/************************ Sample spans tests **********************************/ - -/** - * This test checks to see that the maximum number of running samples(5) for a - * bucket is not exceeded. If there are more spans than this for a single bucket - * it removes the earliest span that was received - */ -TEST_F(TracezDataAggregatorTest, RunningSampleSpansOverCapacity) -{ - int running_span_count = 6; - // Start and store spans based on the above map - std::vector> running_span_container; - for (int count = 0; count < running_span_count; count++) - running_span_container.push_back(tracer->StartSpan(span_name1)); - - std::this_thread::sleep_for(milliseconds(500)); - // Fetch data and check if span name is spresent - auto data = tracez_data_aggregator->GetAggregatedTracezData(); - ASSERT_EQ(data.size(), 1); - ASSERT_TRUE(data.find(span_name1) != data.end()); - - // Check if error spans are updated according to spans started - auto &aggregated_data = data.at(span_name1); - VerifySpanCountsInTracezData(span_name1, aggregated_data, 6, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0}); - - ASSERT_EQ(aggregated_data.sample_running_spans.size(), kMaxNumberOfSampleSpans); - - for (auto i = running_span_container.begin(); i != running_span_container.end(); i++) - { - (*i)->End(); - } -} - -/** - * This test checks to see that the maximum number of error samples(5) for a - * bucket is not exceeded. If there are more spans than this for a single bucket - * it removes the earliest span that was received - */ -TEST_F(TracezDataAggregatorTest, ErrorSampleSpansOverCapacity) -{ - // Create error spans with the descriptions in the vector - std::vector span_error_descriptions = {"error span 1", "error span 2", - "error span 3", "error span 4", - "error span 5", "error span 6"}; - for (auto span_error_description : span_error_descriptions) - { - auto span = tracer->StartSpan(span_name1); - span->SetStatus(opentelemetry::trace::StatusCode::kError, span_error_description); - span->End(); - } - - std::this_thread::sleep_for(milliseconds(500)); - - // Fetch data and check if span name is spresent - auto data = tracez_data_aggregator->GetAggregatedTracezData(); - ASSERT_EQ(data.size(), 1); - ASSERT_TRUE(data.find(span_name1) != data.end()); - - std::this_thread::sleep_for(milliseconds(500)); - - // Check if error spans are updated according to spans started - auto &aggregated_data = data.at(span_name1); - VerifySpanCountsInTracezData(span_name1, aggregated_data, 0, span_error_descriptions.size(), - {0, 0, 0, 0, 0, 0, 0, 0, 0}); - - // Check if the latest 5 error spans exist out of the total 6 that were - // introduced - auto error_sample = aggregated_data.sample_error_spans.begin(); - for (unsigned int idx = 1; idx < span_error_descriptions.size(); idx++) - { - ASSERT_EQ(error_sample->GetDescription(), span_error_descriptions[idx]); - error_sample = std::next(error_sample); - } -} - -/** - * This test checks to see that the maximum number of latency samples(5) for a - * bucket is not exceeded. If there are more spans than this for a single bucket - * it removes the earliest span that was received - */ -TEST_F(TracezDataAggregatorTest, CompletedSampleSpansOverCapacity) -{ - opentelemetry::trace::StartSpanOptions start; - opentelemetry::trace::EndSpanOptions end; - - // Start and end 6 spans with the same name that fall into the first latency - // bucket - std::vector> timestamps = { - make_pair(nanoseconds(10), nanoseconds(100)), - make_pair(nanoseconds(1), nanoseconds(10000)), - make_pair(nanoseconds(1000), nanoseconds(3000)), - make_pair(nanoseconds(12), nanoseconds(12)), - make_pair(nanoseconds(10), nanoseconds(5000)), - make_pair(nanoseconds(10), nanoseconds(60))}; - for (auto timestamp : timestamps) - { - start.start_steady_time = SteadyTimestamp(timestamp.first); - end.end_steady_time = SteadyTimestamp(timestamp.second); - tracer->StartSpan(span_name1, start)->End(end); - } - - // Give some time and get data - std::this_thread::sleep_for(milliseconds(500)); - auto data = tracez_data_aggregator->GetAggregatedTracezData(); - - ASSERT_EQ(data.size(), 1); - ASSERT_TRUE(data.find(span_name1) != data.end()); - - std::this_thread::sleep_for(milliseconds(500)); - auto &aggregated_data = data.at(span_name1); - VerifySpanCountsInTracezData(span_name1, aggregated_data, 0, 0, - {(unsigned int)timestamps.size(), 0, 0, 0, 0, 0, 0, 0, 0}); - - // Check the count of completed spans in the buckets and the samples stored - auto latency_sample = - aggregated_data.sample_latency_spans[LatencyBoundary::k0MicroTo10Micro].begin(); - - // idx starts from 1 and not 0 because there are 6 completed spans in the same - // bucket the and the first one is removed - for (unsigned int idx = 1; idx < timestamps.size(); idx++) - { - ASSERT_EQ(latency_sample->GetDuration().count(), - timestamps[idx].second.count() - timestamps[idx].first.count()); - latency_sample = std::next(latency_sample); - } -} - -/************************* Miscellaneous tests ********************************/ - -/** Test to see if the span names are in alphabetical order **/ -TEST_F(TracezDataAggregatorTest, SpanNameInAlphabeticalOrder) -{ - std::vector span_names = {span_name1, span_name2, span_name3}; - - auto span_first = tracer->StartSpan(span_name2); - tracer->StartSpan(span_name1)->End(); - auto span_third = tracer->StartSpan(span_name3); - span_third->SetStatus(opentelemetry::trace::StatusCode::kError, "span cancelled"); - span_third->End(); - std::this_thread::sleep_for(milliseconds(500)); - // Get data and check if span name exists in aggregation - auto data = tracez_data_aggregator->GetAggregatedTracezData(); - ASSERT_EQ(data.size(), span_names.size()); - - int span_names_idx = 0; - for (auto &spans : data) - { - ASSERT_EQ(spans.first, span_names[span_names_idx]); - span_names_idx++; - } - span_first->End(); -} - -/** This test checks to see that there is no double counting of running spans - * when get aggregated data is called twice**/ -TEST_F(TracezDataAggregatorTest, AdditionToRunningSpans) -{ - // Start a span and check the data - auto span_first = tracer->StartSpan(span_name1); - std::this_thread::sleep_for(milliseconds(500)); - auto data = tracez_data_aggregator->GetAggregatedTracezData(); - ASSERT_EQ(data.size(), 1); - ASSERT_TRUE(data.find(span_name1) != data.end()); - VerifySpanCountsInTracezData(span_name1, data.at(span_name1), 1, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0}); - - // Start another span and check to see if there is no double counting of spans - auto span_second = tracer->StartSpan(span_name1); - - // Give some time and get updated data - std::this_thread::sleep_for(milliseconds(500)); - data = tracez_data_aggregator->GetAggregatedTracezData(); - ASSERT_EQ(data.size(), 1); - ASSERT_TRUE(data.find(span_name1) != data.end()); - auto &aggregated_data = data.at(span_name1); - VerifySpanCountsInTracezData(span_name1, aggregated_data, 2, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0}); - - ASSERT_EQ(aggregated_data.sample_running_spans.size(), 2); - for (auto &sample_span : aggregated_data.sample_running_spans) - { - ASSERT_EQ(sample_span.GetName().data(), span_name1); - } - span_first->End(); - span_second->End(); -} - -/** This test checks to see that once a running span is completed it the - * aggregated data is updated correctly **/ -TEST_F(TracezDataAggregatorTest, RemovalOfRunningSpanWhenCompleted) -{ - opentelemetry::trace::StartSpanOptions start; - start.start_steady_time = SteadyTimestamp(nanoseconds(10)); - opentelemetry::trace::EndSpanOptions end; - end.end_steady_time = SteadyTimestamp(nanoseconds(40)); - - // Start a span and make sure data is updated - auto span_first = tracer->StartSpan(span_name1, start); - std::this_thread::sleep_for(milliseconds(500)); - auto data = tracez_data_aggregator->GetAggregatedTracezData(); - ASSERT_EQ(data.size(), 1); - ASSERT_TRUE(data.find(span_name1) != data.end()); - VerifySpanCountsInTracezData(span_name1, data.at(span_name1), 1, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0}); - ASSERT_EQ(data.at(span_name1).sample_running_spans.front().GetName().data(), span_name1); - // End the span and make sure running span is removed and completed span is - // updated, there should be only one completed span - span_first->End(end); - std::this_thread::sleep_for(milliseconds(500)); - - // Make sure sample span still exists before next aggregation - ASSERT_TRUE(data.find(span_name1) != data.end()); - ASSERT_EQ(data.at(span_name1).sample_running_spans.front().GetName().data(), span_name1); - - data = tracez_data_aggregator->GetAggregatedTracezData(); - - ASSERT_EQ(data.size(), 1); - ASSERT_TRUE(data.find(span_name1) != data.end()); - - // Check if completed span fields are correctly updated - auto &aggregated_data = data.at(span_name1); - VerifySpanCountsInTracezData(span_name1, aggregated_data, 0, 0, {1, 0, 0, 0, 0, 0, 0, 0, 0}); - ASSERT_EQ(aggregated_data.sample_latency_spans[LatencyBoundary::k0MicroTo10Micro] - .front() - .GetDuration() - .count(), - 30); -} - -TEST_F(TracezDataAggregatorTest, RunningSpanChangesNameBeforeCompletion) -{ - opentelemetry::trace::StartSpanOptions start; - start.start_steady_time = SteadyTimestamp(nanoseconds(10)); - opentelemetry::trace::EndSpanOptions end; - end.end_steady_time = SteadyTimestamp(nanoseconds(40)); - - // Start a span and make sure data is updated - auto span_first = tracer->StartSpan(span_name1, start); - std::this_thread::sleep_for(milliseconds(500)); - auto data = tracez_data_aggregator->GetAggregatedTracezData(); - ASSERT_EQ(data.size(), 1); - ASSERT_TRUE(data.find(span_name1) != data.end()); - VerifySpanCountsInTracezData(span_name1, data.at(span_name1), 1, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0}); - ASSERT_EQ(data.at(span_name1).sample_running_spans.front().GetName().data(), span_name1); - - // End the span and make sure running span is removed and completed span is - // updated, there should be only one completed span - span_first->UpdateName(span_name2); - span_first->End(end); - - // Check if sample span is present before fetching updated data - std::this_thread::sleep_for(milliseconds(500)); - ASSERT_TRUE(data.find(span_name1) != data.end()); - ASSERT_EQ(data.at(span_name1).sample_running_spans.front().GetName(), span_name1); - - data = tracez_data_aggregator->GetAggregatedTracezData(); - - ASSERT_EQ(data.size(), 1); - ASSERT_TRUE(data.find(span_name2) != data.end()); - - // Check if completed span fields are correctly updated - auto &aggregated_data = data.at(span_name2); - VerifySpanCountsInTracezData(span_name2, aggregated_data, 0, 0, {1, 0, 0, 0, 0, 0, 0, 0, 0}); - ASSERT_EQ(aggregated_data.sample_latency_spans[LatencyBoundary::k0MicroTo10Micro] - .front() - .GetDuration() - .count(), - 30); -} - -/** Test to check if the span latencies with duration at the edge of boundaries - * fall in the correct bucket **/ -TEST_F(TracezDataAggregatorTest, EdgeSpanLatenciesFallInCorrectBoundaries) -{ - opentelemetry::trace::StartSpanOptions start; - opentelemetry::trace::EndSpanOptions end; - - // Start and end 6 spans with the same name that fall into the first latency - // bucket - std::vector durations = { - nanoseconds(0), nanoseconds(10000), nanoseconds(100000), - nanoseconds(1000000), nanoseconds(10000000), nanoseconds(100000000), - nanoseconds(1000000000), nanoseconds(10000000000), nanoseconds(100000000000)}; - for (auto duration : durations) - { - start.start_steady_time = SteadyTimestamp(nanoseconds(1)); - end.end_steady_time = SteadyTimestamp(nanoseconds(duration.count() + 1)); - tracer->StartSpan(span_name1, start)->End(end); - } - - std::this_thread::sleep_for(milliseconds(500)); - auto data = tracez_data_aggregator->GetAggregatedTracezData(); - ASSERT_EQ(data.size(), 1); - ASSERT_TRUE(data.find(span_name1) != data.end()); - - std::this_thread::sleep_for(milliseconds(500)); - auto &aggregated_data = data.at(span_name1); - VerifySpanCountsInTracezData(span_name1, aggregated_data, 0, 0, {1, 1, 1, 1, 1, 1, 1, 1, 1}); - - // Check if the latency boundary is updated correctly - for (unsigned int boundary = 0; boundary < kLatencyBoundaries.size(); boundary++) - { - ASSERT_EQ(aggregated_data.sample_latency_spans[boundary].front().GetDuration().count(), - durations[boundary].count()); - } -} - -/** This test makes sure that the data is consistent when there are multiple - * calls to the data aggegator with no change in data **/ -TEST_F(TracezDataAggregatorTest, NoChangeInBetweenCallsToAggregator) -{ - opentelemetry::trace::StartSpanOptions start; - start.start_steady_time = SteadyTimestamp(nanoseconds(1)); - - opentelemetry::trace::EndSpanOptions end; - end.end_steady_time = SteadyTimestamp(nanoseconds(1)); - - tracer->StartSpan(span_name1, start)->End(end); - auto running_span = tracer->StartSpan(span_name2); - auto span = tracer->StartSpan(span_name3); - span->SetStatus(opentelemetry::trace::StatusCode::kError, "span cancelled"); - span->End(); - std::this_thread::sleep_for(milliseconds(500)); - auto data = tracez_data_aggregator->GetAggregatedTracezData(); - std::this_thread::sleep_for(milliseconds(500)); - // Get data and check if span name exists in aggregation - data = tracez_data_aggregator->GetAggregatedTracezData(); - ASSERT_TRUE(data.find(span_name1) != data.end()); - VerifySpanCountsInTracezData(span_name1, data.at(span_name1), 0, 0, {1, 0, 0, 0, 0, 0, 0, 0, 0}); - - ASSERT_TRUE(data.find(span_name2) != data.end()); - VerifySpanCountsInTracezData(span_name2, data.at(span_name2), 1, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0}); - - ASSERT_TRUE(data.find(span_name3) != data.end()); - VerifySpanCountsInTracezData(span_name3, data.at(span_name3), 0, 1, {0, 0, 0, 0, 0, 0, 0, 0, 0}); - - running_span->End(); -} diff --git a/ext/test/zpages/tracez_processor_test.cc b/ext/test/zpages/tracez_processor_test.cc deleted file mode 100644 index 6cc3640651..0000000000 --- a/ext/test/zpages/tracez_processor_test.cc +++ /dev/null @@ -1,647 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#include "opentelemetry/ext/zpages/tracez_processor.h" - -#include - -#include - -#include "opentelemetry/ext/zpages/threadsafe_span_data.h" -#include "opentelemetry/nostd/span.h" -#include "opentelemetry/sdk/resource/resource.h" -#include "opentelemetry/sdk/trace/tracer.h" - -using namespace opentelemetry::sdk::trace; -using namespace opentelemetry::ext::zpages; -using namespace testing; - -//////////////////////////////////// TEST HELPER FUNCTIONS ////////////////////////////// - -/* - * Helper function uses the current processor to update spans contained in completed_spans - * and running_spans. completed_spans contains all spans (cumulative), unless marked otherwise - */ -void UpdateSpans(std::shared_ptr &data, - std::vector> &completed, - std::unordered_set &running, - bool store_only_new_completed = false) -{ - auto spans = data->GetSpanSnapshot(); - running = spans.running; - if (store_only_new_completed) - { - completed.clear(); - completed = std::move(spans.completed); - } - else - { - std::move(spans.completed.begin(), spans.completed.end(), - std::inserter(completed, completed.end())); - } - spans.completed.clear(); -} - -/* - * Returns true if all the span names in the name vector within the given range appears in - * at least the same frequency as they do in running_spans. - * - * If no start value is given, start at index 0 - * If no end value is given, end at name vector end - * If 1-1 correspondance marked, return true if completed has all names in same frequency, - * no more or less - */ -bool ContainsNames(const std::vector &names, - std::unordered_set &running, - size_t name_start = 0, - size_t name_end = 0, - bool one_to_one_correspondence = false) -{ - if (name_end == 0) - name_end = names.size(); - - size_t num_names = name_end - name_start; - - if (num_names > running.size() || // More names than spans, can't have all names - (one_to_one_correspondence && num_names != running.size())) - { - return false; - } - std::vector is_contained(num_names, false); - - // Mark all names that are contained only once - // in the order they appear - for (auto &span : running) - { - for (unsigned int i = 0; i < num_names; i++) - { - if (span->GetName() == names[name_start + i] && !is_contained[i]) - { - is_contained[i] = true; - break; - } - } - } - - for (auto &&b : is_contained) - if (!b) - return false; - - return true; -} - -/* - * Returns true if all the span names in the nam vector within the given range appears in - * at least the same frequency as they do in completed_spans - * - * If no start value is given, start at index 0 - * If no end value is given, end at name vector end - * If 1-1 correspondance marked, return true if completed has all names in same frequency, - * no more or less - */ -bool ContainsNames(const std::vector &names, - std::vector> &completed, - size_t name_start = 0, - size_t name_end = 0, - bool one_to_one_correspondence = false) -{ - - if (name_end == 0) - name_end = names.size(); - - size_t num_names = name_end - name_start; - - if (num_names > completed.size() || (one_to_one_correspondence && num_names != completed.size())) - { - return false; - } - std::vector is_contained(num_names, false); - - for (auto &span : completed) - { - for (unsigned int i = 0; i < num_names; i++) - { - if (span->GetName() == names[name_start + i] && !is_contained[i]) - { - is_contained[i] = true; - break; - } - } - } - - for (auto &&b : is_contained) - if (!b) - return false; - - return true; -} - -/* - * Helper function calls GetSpanSnapshot() i times and does nothing with it - * otherwise. Used for testing thread safety - */ -void GetManySnapshots(std::shared_ptr &data, int i) -{ - for (; i > 0; i--) - data->GetSpanSnapshot(); -} - -/* - * Helper function that creates i spans, which are added into the passed - * in vector. Used for testing thread safety - */ -void StartManySpans( - std::vector> &spans, - std::shared_ptr tracer, - int i) -{ - for (; i > 0; i--) - spans.push_back(tracer->StartSpan("span")); -} - -/* - * Helper function that ends all spans in the passed in span vector. Used - * for testing thread safety - */ -void EndAllSpans(std::vector> &spans) -{ - for (auto &span : spans) - span->End(); -} - -//////////////////////////////// TEST FIXTURE ////////////////////////////////////// - -/* - * Reduce code duplication by having single area with shared setup code - */ -class TracezProcessor : public ::testing::Test -{ -protected: - void SetUp() override - { - shared_data = std::shared_ptr(new TracezSharedData()); - processor = std::shared_ptr(new TracezSpanProcessor(shared_data)); - std::unique_ptr processor2(new TracezSpanProcessor(shared_data)); - std::vector> processors; - processors.push_back(std::move(processor2)); - auto resource = opentelemetry::sdk::resource::Resource::Create({}); - - // Note: we make a *different* processor for the tracercontext. THis is because - // all the tests use shared data, and we want to make sure this works correctly. - auto context = std::make_shared(std::move(processors), resource); - - tracer = std::shared_ptr(new Tracer(context)); - auto spans = shared_data->GetSpanSnapshot(); - running = spans.running; - completed = std::move(spans.completed); - - span_names = {"s0", "s2", "s1", "s1", "s"}; - } - - std::shared_ptr shared_data; - std::shared_ptr processor; - std::shared_ptr tracer; - - std::vector span_names; - std::vector> span_vars; - - std::unordered_set running; - std::vector> completed; -}; - -///////////////////////////////////////// TESTS /////////////////////////////////// - -/* - * Test if both span containers are empty when no spans exist or are added. - * Ensures no rogue spans appear in the containers somehow. - */ -TEST_F(TracezProcessor, NoSpans) -{ - auto recordable = processor->MakeRecordable(); - - EXPECT_EQ(running.size(), 0); - EXPECT_EQ(completed.size(), 0); -} - -/* - * Test if a single span moves from running to completed at expected times. - * All completed spans are stored. Ensures basic functionality and that accumulation - * can happen - */ -TEST_F(TracezProcessor, OneSpanCumulative) -{ - auto span = tracer->StartSpan(span_names[0]); - UpdateSpans(shared_data, completed, running); - - EXPECT_TRUE(ContainsNames(span_names, running, 0, 1, true)); - EXPECT_EQ(running.size(), 1); - EXPECT_EQ(completed.size(), 0); - - span->End(); - UpdateSpans(shared_data, completed, running); - - EXPECT_TRUE(ContainsNames(span_names, completed, 0, 1, true)); - EXPECT_EQ(running.size(), 0); - EXPECT_EQ(completed.size(), 1); -} - -/* - * Test if multiple spans move from running to completed at expected times. Check if - * all are in a container, either running/completed during checks. Ensures basic functionality - * and that accumulation can happen for many spans - * All completed spans are stored. - */ -TEST_F(TracezProcessor, MultipleSpansCumulative) -{ - EXPECT_EQ(running.size(), 0); - EXPECT_EQ(completed.size(), 0); - - // Start and store spans using span_names - for (const auto &name : span_names) - span_vars.push_back(tracer->StartSpan(name)); - UpdateSpans(shared_data, completed, running); - - EXPECT_TRUE(ContainsNames(span_names, running)); // s0 s2 s1 s1 s - EXPECT_EQ(running.size(), span_names.size()); - EXPECT_EQ(completed.size(), 0); - - // End all spans - for (auto &span : span_vars) - span->End(); - UpdateSpans(shared_data, completed, running); - - EXPECT_TRUE(ContainsNames(span_names, completed)); // s0 s2 s1 s1 s - EXPECT_EQ(running.size(), 0); - EXPECT_EQ(completed.size(), span_names.size()); -} - -/* - * Test if multiple spans move from running to completed at expected times, - * running/completed spans are split. Middle spans end first. Ensures basic functionality - * and that accumulation can happen for many spans even spans that start and end non- - * sequentially. All completed spans are stored. - */ -TEST_F(TracezProcessor, MultipleSpansMiddleSplitCumulative) -{ - for (const auto &name : span_names) - span_vars.push_back(tracer->StartSpan(name)); - UpdateSpans(shared_data, completed, running); - - EXPECT_TRUE(ContainsNames(span_names, running)); // s0 s2 s1 s1 s - EXPECT_EQ(running.size(), span_names.size()); - EXPECT_EQ(completed.size(), 0); - - // End 4th span - span_vars[3]->End(); - UpdateSpans(shared_data, completed, running); - - EXPECT_TRUE(ContainsNames(span_names, running, 0, 3)); // s0 s2 s1 - EXPECT_TRUE(ContainsNames(span_names, running, 4)); // + s - EXPECT_TRUE(ContainsNames(span_names, completed, 3, 4)); // s1 - EXPECT_EQ(running.size(), 4); - EXPECT_EQ(completed.size(), 1); - - // End 2nd span - span_vars[1]->End(); - UpdateSpans(shared_data, completed, running); - - EXPECT_TRUE(ContainsNames(span_names, running, 0, 1)); // s0 - EXPECT_TRUE(ContainsNames(span_names, running, 2, 3)); // + s1 - EXPECT_TRUE(ContainsNames(span_names, running, 4)); // + s - EXPECT_TRUE(ContainsNames(span_names, completed, 1, 2)); // s2 - EXPECT_TRUE(ContainsNames(span_names, completed, 3, 4)); // s1 - EXPECT_EQ(running.size(), 3); - EXPECT_EQ(completed.size(), 2); - - // End 3rd span (last middle span) - span_vars[2]->End(); - UpdateSpans(shared_data, completed, running); - - EXPECT_TRUE(ContainsNames(span_names, running, 0, 1)); // s0 - EXPECT_TRUE(ContainsNames(span_names, running, 4)); // + s - EXPECT_TRUE(ContainsNames(span_names, completed, 1, 4)); // s2 s1 s1 - EXPECT_EQ(running.size(), 2); - EXPECT_EQ(completed.size(), 3); - - // End remaining Spans - span_vars[0]->End(); - span_vars[4]->End(); - UpdateSpans(shared_data, completed, running); - - EXPECT_TRUE(ContainsNames(span_names, completed)); // s0 s2 s1 s1 s - EXPECT_EQ(running.size(), 0); - EXPECT_EQ(completed.size(), 5); -} - -/* - * Test if multiple spans move from running to completed at expected times, - * running/completed spans are split. Ensures basic functionality and that - * accumulation can happen for many spans even spans that start and end non- - * sequentially. All completed spans are stored. - */ -TEST_F(TracezProcessor, MultipleSpansOuterSplitCumulative) -{ - for (const auto &name : span_names) - span_vars.push_back(tracer->StartSpan(name)); - - // End last span - span_vars[4]->End(); - UpdateSpans(shared_data, completed, running); - - EXPECT_TRUE(ContainsNames(span_names, running, 0, 4)); // s0 s2 s1 s1 - EXPECT_TRUE(ContainsNames(span_names, completed, 4)); // s - EXPECT_EQ(running.size(), 4); - EXPECT_EQ(completed.size(), 1); - - // End first span - span_vars[0]->End(); - UpdateSpans(shared_data, completed, running); - - EXPECT_TRUE(ContainsNames(span_names, running, 1, 4)); // s2 s1 s1 - EXPECT_TRUE(ContainsNames(span_names, completed, 0, 1)); // s0 - EXPECT_TRUE(ContainsNames(span_names, completed, 4)); // s - EXPECT_EQ(running.size(), 3); - EXPECT_EQ(completed.size(), 2); - - // End remaining Spans - for (int i = 1; i < 4; i++) - span_vars[i]->End(); - UpdateSpans(shared_data, completed, running); - - EXPECT_TRUE(ContainsNames(span_names, completed)); // s0 s2 s1 s1 s - EXPECT_EQ(running.size(), 0); - EXPECT_EQ(completed.size(), 5); -} - -/* - * Test if a single span moves from running to completed at expected times. - * Ensure correct behavior even when spans are discarded. Only new completed - * spans are stored. - */ -TEST_F(TracezProcessor, OneSpanNewOnly) -{ - auto span = tracer->StartSpan(span_names[0]); - UpdateSpans(shared_data, completed, running, true); - - EXPECT_TRUE(ContainsNames(span_names, running, 0, 1, true)); - EXPECT_EQ(running.size(), 1); - EXPECT_EQ(completed.size(), 0); - - span->End(); - UpdateSpans(shared_data, completed, running, true); - - EXPECT_TRUE(ContainsNames(span_names, completed, 0, 1, true)); - EXPECT_EQ(running.size(), 0); - EXPECT_EQ(completed.size(), 1); - - UpdateSpans(shared_data, completed, running, true); - - EXPECT_EQ(running.size(), 0); - EXPECT_EQ(completed.size(), 0); -} - -/* - * Test if multiple spans move from running to completed at expected times, - * running/completed spans are split. Middle spans end first. Ensure correct - * behavior even when multiple spans are discarded, even when span starting and - * ending is non-sequential. Only new completed spans are stored. - */ -TEST_F(TracezProcessor, MultipleSpansMiddleSplitNewOnly) -{ - for (const auto &name : span_names) - span_vars.push_back(tracer->StartSpan(name)); - UpdateSpans(shared_data, completed, running); - - EXPECT_TRUE(ContainsNames(span_names, running, 0, 5, true)); // s0 s2 s1 s1 s - EXPECT_EQ(running.size(), span_names.size()); - EXPECT_EQ(completed.size(), 0); - - // End 4th span - span_vars[3]->End(); - UpdateSpans(shared_data, completed, running, true); - - EXPECT_TRUE(ContainsNames(span_names, running, 0, 3)); // s0 s2 s1 - EXPECT_TRUE(ContainsNames(span_names, running, 4)); // + s - EXPECT_TRUE(ContainsNames(span_names, completed, 3, 4, true)); // s1 - EXPECT_EQ(running.size(), 4); - EXPECT_EQ(completed.size(), 1); - - // End 2nd and 3rd span - span_vars[1]->End(); - span_vars[2]->End(); - UpdateSpans(shared_data, completed, running, true); - - EXPECT_TRUE(ContainsNames(span_names, running, 0, 1)); // s0 - EXPECT_TRUE(ContainsNames(span_names, running, 4)); // + s - EXPECT_TRUE(ContainsNames(span_names, completed, 1, 3, true)); // s2 s1 - EXPECT_EQ(running.size(), 2); - EXPECT_EQ(completed.size(), 2); - - // End remaining Spans - span_vars[0]->End(); - span_vars[4]->End(); - UpdateSpans(shared_data, completed, running, true); - - EXPECT_TRUE(ContainsNames(span_names, completed, 0, 1)); // s0 - EXPECT_TRUE(ContainsNames(span_names, completed, 4)); // s - EXPECT_EQ(running.size(), 0); - EXPECT_EQ(completed.size(), 2); - - UpdateSpans(shared_data, completed, running, true); - - EXPECT_EQ(running.size(), 0); - EXPECT_EQ(completed.size(), 0); -} - -/* - * Test if multiple spans move from running to completed at expected times, - * running/completed spans are split. Ensure correct behavior even when - * multiple spans are discarded, even when span starting and ending is - * non-sequential. Only new completed spans are stored. - */ -TEST_F(TracezProcessor, MultipleSpansOuterSplitNewOnly) -{ - for (const auto &name : span_names) - span_vars.push_back(tracer->StartSpan(name)); - - // End last span - span_vars[4]->End(); - UpdateSpans(shared_data, completed, running, true); - - EXPECT_TRUE(ContainsNames(span_names, running, 0, 4, true)); // s0 s2 s1 s1 - EXPECT_TRUE(ContainsNames(span_names, completed, 4, 5, true)); // s - EXPECT_EQ(running.size(), 4); - EXPECT_EQ(completed.size(), 1); - - // End first span - span_vars[0]->End(); - UpdateSpans(shared_data, completed, running, true); - - EXPECT_TRUE(ContainsNames(span_names, running, 1, 4, true)); // s2 s1 s1 - EXPECT_TRUE(ContainsNames(span_names, completed, 0, 1, true)); // s0 - EXPECT_EQ(running.size(), 3); - EXPECT_EQ(completed.size(), 1); - - // End remaining middle spans - for (int i = 1; i < 4; i++) - span_vars[i]->End(); - UpdateSpans(shared_data, completed, running, true); - - EXPECT_TRUE(ContainsNames(span_names, completed, 1, 4, true)); // s2 s1 s1 - EXPECT_EQ(running.size(), 0); - EXPECT_EQ(completed.size(), 3); - - UpdateSpans(shared_data, completed, running, true); - - EXPECT_EQ(running.size(), 0); - EXPECT_EQ(completed.size(), 0); -} - -/* - * Test for ForceFlush and Shutdown code coverage, which do nothing. - */ -TEST_F(TracezProcessor, FlushShutdown) -{ - auto pre_running_sz = running.size(); - auto pre_completed_sz = completed.size(); - - EXPECT_TRUE(processor->ForceFlush()); - EXPECT_TRUE(processor->Shutdown()); - - UpdateSpans(shared_data, completed, running); - - EXPECT_EQ(pre_running_sz, running.size()); - EXPECT_EQ(pre_completed_sz, completed.size()); -} - -/* - * Test for thread safety when many spans start at the same time. - */ -TEST_F(TracezProcessor, RunningThreadSafety) -{ - std::vector> spans1; - std::vector> spans2; - - std::thread start1(StartManySpans, std::ref(spans1), tracer, 500); - std::thread start2(StartManySpans, std::ref(spans2), tracer, 500); - - start1.join(); - start2.join(); - - EndAllSpans(spans1); - EndAllSpans(spans2); -} - -/* - * Test for thread safety when many spans end at the same time - */ -TEST_F(TracezProcessor, CompletedThreadSafety) -{ - std::vector> spans1; - std::vector> spans2; - - StartManySpans(spans1, tracer, 500); - StartManySpans(spans2, tracer, 500); - - std::thread end1(EndAllSpans, std::ref(spans1)); - std::thread end2(EndAllSpans, std::ref(spans2)); - - end1.join(); - end2.join(); -} - -/* - * Test for thread safety when many snapshots are grabbed at the same time. - */ -TEST_F(TracezProcessor, SnapshotThreadSafety) -{ - std::vector> spans; - - std::thread snap1(GetManySnapshots, std::ref(shared_data), 500); - std::thread snap2(GetManySnapshots, std::ref(shared_data), 500); - - snap1.join(); - snap2.join(); - - StartManySpans(spans, tracer, 500); - - std::thread snap3(GetManySnapshots, std::ref(shared_data), 500); - std::thread snap4(GetManySnapshots, std::ref(shared_data), 500); - - snap3.join(); - snap4.join(); - - EndAllSpans(spans); -} - -/* - * Test for thread safety when many spans start while others are ending. - */ -TEST_F(TracezProcessor, RunningCompletedThreadSafety) -{ - std::vector> spans1; - std::vector> spans2; - - StartManySpans(spans1, tracer, 500); - - std::thread start(StartManySpans, std::ref(spans2), tracer, 500); - std::thread end(EndAllSpans, std::ref(spans1)); - - start.join(); - end.join(); - - EndAllSpans(spans2); -} - -/* - * Test for thread safety when many span start while snapshots are being grabbed. - */ -TEST_F(TracezProcessor, RunningSnapshotThreadSafety) -{ - std::vector> spans; - - std::thread start(StartManySpans, std::ref(spans), tracer, 500); - std::thread snapshots(GetManySnapshots, std::ref(shared_data), 500); - - start.join(); - snapshots.join(); - - EndAllSpans(spans); -} - -/* - * Test for thread safety when many spans end while snapshots are being grabbed. - */ -TEST_F(TracezProcessor, SnapshotCompletedThreadSafety) -{ - std::vector> spans; - - StartManySpans(spans, tracer, 500); - - std::thread snapshots(GetManySnapshots, std::ref(shared_data), 500); - std::thread end(EndAllSpans, std::ref(spans)); - - snapshots.join(); - end.join(); -} - -/* - * Test for thread safety when many spans start and end while snapshots are being grabbed. - */ -TEST_F(TracezProcessor, RunningSnapshotCompletedThreadSafety) -{ - std::vector> spans1; - std::vector> spans2; - - StartManySpans(spans1, tracer, 500); - - std::thread start(StartManySpans, std::ref(spans2), tracer, 500); - std::thread snapshots(GetManySnapshots, std::ref(shared_data), 500); - std::thread end(EndAllSpans, std::ref(spans1)); - - start.join(); - snapshots.join(); - end.join(); - - EndAllSpans(spans2); -} From 4bd64c9a336fd438d6c4c9dad2e6b61b0585311f Mon Sep 17 00:00:00 2001 From: Marc Alff Date: Wed, 6 Dec 2023 20:39:21 +0100 Subject: [PATCH 27/31] [RELEASE] Prepare release 1.13.0 (#2432) --- CHANGELOG.md | 45 +++++++++++++++++++ api/include/opentelemetry/version.h | 4 +- docs/public/conf.py | 2 +- .../opentelemetry/sdk/version/version.h | 2 +- sdk/src/version/version.cc | 8 ++-- 5 files changed, 53 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d2d28461cb..6ba0da393c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,22 +15,67 @@ Increment the: ## [Unreleased] +## [1.13.0] 2023-12-06 + * [BUILD] Remove WITH_REMOVE_METER_PREVIEW, use WITH_ABI_VERSION_2 instead [#2370](https://github.com/open-telemetry/opentelemetry-cpp/pull/2370) +* [SDK] Metrics ObservableRegistry Cleanup + [#2376](https://github.com/open-telemetry/opentelemetry-cpp/pull/2376) * [BUILD] Make WITH_OTLP_HTTP_SSL_PREVIEW mainstream [#2378](https://github.com/open-telemetry/opentelemetry-cpp/pull/2378) +* [SDK] Creating DoubleUpDownCounter with no matching view + [#2379](https://github.com/open-telemetry/opentelemetry-cpp/pull/2379) * [API] Add InstrumentationScope attributes in TracerProvider::GetTracer() [#2371](https://github.com/open-telemetry/opentelemetry-cpp/pull/2371) +* [BUILD] DLL export interface for Metrics + [#2344](https://github.com/open-telemetry/opentelemetry-cpp/pull/2344) * [BUILD] enum CanonicalCode names too generic... conflict with old C defines [#2385](https://github.com/open-telemetry/opentelemetry-cpp/pull/2385) +* [BUILD] Fix cpack broken package version + [#2386](https://github.com/open-telemetry/opentelemetry-cpp/pull/2386) * [API] Add a new AddLink() operation to Span [#2380](https://github.com/open-telemetry/opentelemetry-cpp/pull/2380) +* [opentracing-shim] Add check for sampled context + [#2390](https://github.com/open-telemetry/opentelemetry-cpp/pull/2390) +* [BUILD] Fix exported definitions when building DLL with STL + [#2387](https://github.com/open-telemetry/opentelemetry-cpp/pull/2387) +* [BUILD] Add missing includes to runtime_context_test + [#2395](https://github.com/open-telemetry/opentelemetry-cpp/pull/2395) +* [ADMIN] Add file .github/repository-settings.md + [#2392](https://github.com/open-telemetry/opentelemetry-cpp/pull/2392) * [SDK] Fix GetLogger with empty library name [#2398](https://github.com/open-telemetry/opentelemetry-cpp/pull/2398) +* [TEST] Fix compiling problem and removed -DENABLE_TEST + [#2401](https://github.com/open-telemetry/opentelemetry-cpp/pull/2401) +* [BUILD] Check windows options are not passed to non-Windows build + [#2399](https://github.com/open-telemetry/opentelemetry-cpp/pull/2399) * [EXPORTER] Rework OTLP/HTTP and OTLP/GRPC exporter options [#2388](https://github.com/open-telemetry/opentelemetry-cpp/pull/2388) +* [Build] Update vcpkg to latest release + [#2412](https://github.com/open-telemetry/opentelemetry-cpp/pull/2412) +* [SDK] Cardinality limits for metrics streams + (Sync Instruments + Delta Temporality) + [#2255](https://github.com/open-telemetry/opentelemetry-cpp/pull/2255) +* [EXPORTER] Prometheus: Add unit to names, convert to word + [#2213](https://github.com/open-telemetry/opentelemetry-cpp/pull/2213) +* [Metrics] Make context optional for histogram instruments in Metrics SDK + [#2416](https://github.com/open-telemetry/opentelemetry-cpp/pull/2416) +* [BUILD] Fix references to trace namespace to be fully qualified + [#2422](https://github.com/open-telemetry/opentelemetry-cpp/pull/2422) +* [BUILD] Bump third_party/googletest to same version as bazel + [#2421](https://github.com/open-telemetry/opentelemetry-cpp/pull/2421) +* [BUILD] Remove defining NOMINMAX from api + [#2420](https://github.com/open-telemetry/opentelemetry-cpp/pull/2420) +* [BUILD] 'uint8_t' not declared in this scope with gcc 13.2.1 + [#2423](https://github.com/open-telemetry/opentelemetry-cpp/pull/2423) +* [BUILD] Improve the handling of OPENTELEMETRY_HAVE_WORKING_REGEX + [#2430](https://github.com/open-telemetry/opentelemetry-cpp/pull/2430) * [SEMANTIC CONVENTION] Upgrade to semconv 1.23.1 [#2428](https://github.com/open-telemetry/opentelemetry-cpp/pull/2428) +* [BUILD] Use fully qualified references to trace/common namespace + [#2424](https://github.com/open-telemetry/opentelemetry-cpp/pull/2424) +* [API] Create root span with active span + [#2427](https://github.com/open-telemetry/opentelemetry-cpp/pull/2427) * [REMOVAL] Remove ZPAGES [#2433](https://github.com/open-telemetry/opentelemetry-cpp/pull/2433) diff --git a/api/include/opentelemetry/version.h b/api/include/opentelemetry/version.h index 79284c1501..7b9fa1da02 100644 --- a/api/include/opentelemetry/version.h +++ b/api/include/opentelemetry/version.h @@ -10,9 +10,9 @@ # define OPENTELEMETRY_ABI_VERSION_NO 1 #endif -#define OPENTELEMETRY_VERSION "1.12.0" +#define OPENTELEMETRY_VERSION "1.13.0" #define OPENTELEMETRY_VERSION_MAJOR 1 -#define OPENTELEMETRY_VERSION_MINOR 12 +#define OPENTELEMETRY_VERSION_MINOR 13 #define OPENTELEMETRY_VERSION_PATCH 0 #define OPENTELEMETRY_ABI_VERSION OPENTELEMETRY_STRINGIFY(OPENTELEMETRY_ABI_VERSION_NO) diff --git a/docs/public/conf.py b/docs/public/conf.py index 2375c45924..592f7340fe 100644 --- a/docs/public/conf.py +++ b/docs/public/conf.py @@ -24,7 +24,7 @@ author = 'OpenTelemetry authors' # The full version, including alpha/beta/rc tags -release = "1.12.0" +release = "1.13.0" # Run sphinx on subprojects and copy output # ----------------------------------------- diff --git a/sdk/include/opentelemetry/sdk/version/version.h b/sdk/include/opentelemetry/sdk/version/version.h index 16bd121b92..ce34bd399a 100644 --- a/sdk/include/opentelemetry/sdk/version/version.h +++ b/sdk/include/opentelemetry/sdk/version/version.h @@ -5,7 +5,7 @@ #include "opentelemetry/detail/preprocessor.h" -#define OPENTELEMETRY_SDK_VERSION "1.12.0" +#define OPENTELEMETRY_SDK_VERSION "1.13.0" #include "opentelemetry/version.h" diff --git a/sdk/src/version/version.cc b/sdk/src/version/version.cc index fb2db64c30..3154140120 100644 --- a/sdk/src/version/version.cc +++ b/sdk/src/version/version.cc @@ -12,13 +12,13 @@ namespace sdk namespace version { const int major_version = 1; -const int minor_version = 12; +const int minor_version = 13; const int patch_version = 0; const char *pre_release = "NONE"; const char *build_metadata = "NONE"; -const char *short_version = "1.12.0"; -const char *full_version = "1.12.0-NONE-NONE"; -const char *build_date = "Mon 16 Oct 2023 07:42:23 AM UTC"; +const char *short_version = "1.13.0"; +const char *full_version = "1.13.0-NONE-NONE"; +const char *build_date = "Wed Dec 6 00:27:20 UTC 2023"; } // namespace version } // namespace sdk From a8b11a35036c1e8ada5ce6a6e471c9311cc827e4 Mon Sep 17 00:00:00 2001 From: Tom Tan Date: Thu, 7 Dec 2023 00:04:59 -0800 Subject: [PATCH 28/31] [BUILD] Remove gmock from GTEST_BOTH_LIBRARIES (#2437) --- CMakeLists.txt | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c27a910f4e..c61925e97b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -578,12 +578,10 @@ if(BUILD_TESTING) ${CMAKE_CURRENT_SOURCE_DIR}/third_party/googletest/googletest/include ${CMAKE_CURRENT_SOURCE_DIR}/third_party/googletest/googlemock/include) if(TARGET gtest) - set(GTEST_BOTH_LIBRARIES gtest gtest_main gmock) + set(GTEST_BOTH_LIBRARIES gtest gtest_main) else() - set(GTEST_BOTH_LIBRARIES - ${CMAKE_BINARY_DIR}/lib/libgtest.a - ${CMAKE_BINARY_DIR}/lib/libgtest_main.a - ${CMAKE_BINARY_DIR}/lib/libgmock.a) + set(GTEST_BOTH_LIBRARIES ${CMAKE_BINARY_DIR}/lib/libgtest.a + ${CMAKE_BINARY_DIR}/lib/libgtest_main.a) endif() elseif(WIN32) # Make sure we are always bootsrapped with vcpkg on Windows @@ -600,7 +598,7 @@ if(BUILD_TESTING) if(NOT GTEST_BOTH_LIBRARIES) # New GTest package names if(TARGET GTest::gtest) - set(GTEST_BOTH_LIBRARIES GTest::gtest GTest::gtest_main GTest::gmock) + set(GTEST_BOTH_LIBRARIES GTest::gtest GTest::gtest_main) elseif(TARGET GTest::GTest) set(GTEST_BOTH_LIBRARIES GTest::GTest GTest::Main) endif() From cd626c2ae9973db08c3b306269cec90da462e3de Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 7 Dec 2023 22:46:12 -0800 Subject: [PATCH 29/31] Bump actions/stale from 8 to 9 (#2441) --- .github/workflows/stale.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 65c084eb93..8949173a42 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -7,7 +7,7 @@ jobs: stale: runs-on: ubuntu-latest steps: - - uses: actions/stale@v8 + - uses: actions/stale@v9 with: stale-issue-message: "This issue was marked as stale due to lack of activity." days-before-issue-stale: 60 From 96e5078cfffbf35dca590326e321db607730d3f6 Mon Sep 17 00:00:00 2001 From: Tom Tan Date: Fri, 8 Dec 2023 13:54:37 -0800 Subject: [PATCH 30/31] [BUILD] Accept path list in OPENTELEMETRY_EXTERNAL_COMPONENT_PATH (#2439) --- ...entelemetry-build-external-component.cmake | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/cmake/opentelemetry-build-external-component.cmake b/cmake/opentelemetry-build-external-component.cmake index 2d8d78afbf..74b6515209 100644 --- a/cmake/opentelemetry-build-external-component.cmake +++ b/cmake/opentelemetry-build-external-component.cmake @@ -1,10 +1,19 @@ # Copyright The OpenTelemetry Authors # SPDX-License-Identifier: Apache-2.0 +function(get_directory_name_in_path PATH_VAR RESULT_VAR) + # get_filename_component does not work with paths ending in / or \, so remove it. + string(REGEX REPLACE "[/\\]$" "" PATH_TRIMMED "${PATH_VAR}") + + get_filename_component(DIR_NAME ${PATH_TRIMMED} NAME) + + set(${RESULT_VAR} "${DIR_NAME}" PARENT_SCOPE) +endfunction() + # Enable building external components through otel-cpp build # The config options are -# - OPENTELEMETRY_EXTERNAL_COMPONENT_PATH - Setting local path of the external -# component as env variable +# - OPENTELEMETRY_EXTERNAL_COMPONENT_PATH - Setting local paths of the external +# component as env variable. Multiple paths can be set by separating them with. # - OPENTELEMETRY_EXTERNAL_COMPONENT_URL Setting github-repo of external component # as env variable @@ -13,13 +22,18 @@ if(OPENTELEMETRY_EXTERNAL_COMPONENT_PATH) # Add custom component path to build tree and consolidate binary artifacts in # current project binary output directory. - add_subdirectory(${OPENTELEMETRY_EXTERNAL_COMPONENT_PATH} - ${PROJECT_BINARY_DIR}/external) + foreach(DIR IN LISTS OPENTELEMETRY_EXTERNAL_COMPONENT_PATH) + get_directory_name_in_path(${DIR} EXTERNAL_EXPORTER_DIR_NAME) + add_subdirectory(${DIR} ${PROJECT_BINARY_DIR}/external/${EXTERNAL_EXPORTER_DIR_NAME}) + endforeach() elseif(DEFINED ENV{OPENTELEMETRY_EXTERNAL_COMPONENT_PATH}) # Add custom component path to build tree and consolidate binary artifacts in # current project binary output directory. - add_subdirectory($ENV{OPENTELEMETRY_EXTERNAL_COMPONENT_PATH} - ${PROJECT_BINARY_DIR}/external) + set(OPENTELEMETRY_EXTERNAL_COMPONENT_PATH_VAR $ENV{OPENTELEMETRY_EXTERNAL_COMPONENT_PATH}) + foreach(DIR IN LISTS OPENTELEMETRY_EXTERNAL_COMPONENT_PATH_VAR) + get_directory_name_in_path(${DIR} EXTERNAL_EXPORTER_DIR_NAME) + add_subdirectory(${DIR} ${PROJECT_BINARY_DIR}/external/${EXTERNAL_EXPORTER_DIR_NAME}) + endforeach() elseif(DEFINED $ENV{OPENTELEMETRY_EXTERNAL_COMPONENT_URL}) # This option requires CMake 3.11+: add standard remote repo to build tree. include(FetchContent) From 0b9371dcc5d26b2721482a7c0f89eb154dbe364f Mon Sep 17 00:00:00 2001 From: Tom Tan Date: Wed, 13 Dec 2023 12:37:55 -0800 Subject: [PATCH 31/31] [BUILD] Fix removing of NOMINMAX on Windows (#2449) --- CHANGELOG.md | 3 +++ api/include/opentelemetry/std/span.h | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ba0da393c..e305d85948 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,9 @@ Increment the: ## [Unreleased] +* [BUILD] Fix removing of NOMINMAX on Windows + [#2449](https://github.com/open-telemetry/opentelemetry-cpp/pull/2449) + ## [1.13.0] 2023-12-06 * [BUILD] Remove WITH_REMOVE_METER_PREVIEW, use WITH_ABI_VERSION_2 instead diff --git a/api/include/opentelemetry/std/span.h b/api/include/opentelemetry/std/span.h index 2a3dc12a84..1160d54fbe 100644 --- a/api/include/opentelemetry/std/span.h +++ b/api/include/opentelemetry/std/span.h @@ -60,7 +60,7 @@ OPENTELEMETRY_END_NAMESPACE OPENTELEMETRY_BEGIN_NAMESPACE namespace nostd { -constexpr std::size_t dynamic_extent = (std::numeric_limits::max()); +constexpr std::size_t dynamic_extent = (std::numeric_limits::max)(); template using span = std::span;