diff --git a/.bazelversion b/.bazelversion index 944880fa15..15a2799817 100644 --- a/.bazelversion +++ b/.bazelversion @@ -1 +1 @@ -3.2.0 +3.3.0 diff --git a/WORKSPACE b/WORKSPACE index 1dd2ea37fc..b8d0fb0752 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -16,6 +16,31 @@ workspace(name = "io_opentelemetry_cpp") load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") +# Load gRPC dependency +# Note that this dependency needs to be loaded first due to +# https://github.com/bazelbuild/bazel/issues/6664 +http_archive( + name = "com_github_grpc_grpc", + sha256 = "d6af0859d3ae4693b1955e972aa2e590d6f4d44baaa82651467c6beea453e30e", + strip_prefix = "grpc-1.26.0-pre1", + urls = [ + "https://github.com/grpc/grpc/archive/v1.26.0-pre1.tar.gz", + ], +) + +load("@com_github_grpc_grpc//bazel:grpc_deps.bzl", "grpc_deps") + +grpc_deps() + +# Load extra gRPC dependencies due to https://github.com/grpc/grpc/issues/20511 +load("@com_github_grpc_grpc//bazel:grpc_extra_deps.bzl", "grpc_extra_deps") + +grpc_extra_deps() + +load("@upb//bazel:repository_defs.bzl", "bazel_version_repository") + +bazel_version_repository(name = "upb_bazel_version") + # Uses older protobuf version because of # https://github.com/protocolbuffers/protobuf/issues/7179 http_archive( diff --git a/api/include/opentelemetry/nostd/string_view.h b/api/include/opentelemetry/nostd/string_view.h index 02f6b326a7..e947d23259 100644 --- a/api/include/opentelemetry/nostd/string_view.h +++ b/api/include/opentelemetry/nostd/string_view.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include #include @@ -11,6 +12,9 @@ OPENTELEMETRY_BEGIN_NAMESPACE namespace nostd { + +using Traits = std::char_traits; + /** * Back port of std::string_view to work with pre-cpp-17 compilers. * @@ -20,7 +24,9 @@ namespace nostd class string_view { public: - static constexpr std::size_t npos = static_cast(-1); + typedef std::size_t size_type; + + static constexpr size_type npos = static_cast(-1); string_view() noexcept : length_(0), data_(nullptr) {} @@ -30,7 +36,7 @@ class string_view : length_(str.length()), data_(str.c_str()) {} - string_view(const char *str, size_t len) noexcept : length_(len), data_(str) {} + string_view(const char *str, size_type len) noexcept : length_(len), data_(str) {} explicit operator std::string() const { return {data_, length_}; } @@ -38,17 +44,17 @@ class string_view bool empty() const noexcept { return length_ == 0; } - size_t length() const noexcept { return length_; } + size_type length() const noexcept { return length_; } - size_t size() const noexcept { return length_; } + size_type size() const noexcept { return length_; } const char *begin() const noexcept { return data(); } const char *end() const noexcept { return data() + length(); } - const char &operator[](std::size_t i) { return *(data() + i); } + const char &operator[](size_type i) { return *(data() + i); } - string_view substr(std::size_t pos, std::size_t n = npos) const + string_view substr(size_type pos, size_type n = npos) const { if (pos > length_) { @@ -62,11 +68,55 @@ class string_view return string_view(data_ + pos, n); } + int compare(string_view v) const noexcept + { + size_type len = std::min(size(), v.size()); + int result = Traits::compare(data(), v.data(), len); + if (result == 0) + result = size() == v.size() ? 0 : (size() < v.size() ? -1 : 1); + return result; + }; + + int compare(size_type pos1, size_type count1, string_view v) const + { + return substr(pos1, count1).compare(v); + }; + + int compare(size_type pos1, size_type count1, string_view v, size_type pos2, size_type count2) const + { + return substr(pos1, count1).compare(v.substr(pos2, count2)); + }; + + int compare(const char *s) const + { + return compare(string_view(s)); + }; + + int compare(size_type pos1, size_type count1, const char *s) const + { + return substr(pos1, count1).compare(string_view(s)); + }; + + int compare(size_type pos1, size_type count1, const char *s, size_type count2) const + { + return substr(pos1, count1).compare(string_view(s, count2)); + }; + + bool operator<(const string_view v) const noexcept + { + return compare(v) < 0; + } + + bool operator>(const string_view v) const noexcept + { + return compare(v) > 0; + } + private: // Note: uses the same binary layout as libstdc++'s std::string_view // See // https://github.com/gcc-mirror/gcc/blob/e0c554e4da7310df83bb1dcc7b8e6c4c9c5a2a4f/libstdc%2B%2B-v3/include/std/string_view#L466-L467 - size_t length_; + size_type length_; const char *data_; }; diff --git a/api/test/nostd/string_view_test.cc b/api/test/nostd/string_view_test.cc index 17c52bf6cb..074d3bee49 100644 --- a/api/test/nostd/string_view_test.cc +++ b/api/test/nostd/string_view_test.cc @@ -2,6 +2,8 @@ #include +#include "map" + using opentelemetry::nostd::string_view; TEST(StringViewTest, DefaultConstruction) @@ -72,3 +74,31 @@ TEST(StringViewTest, SubstrOutOfRange) EXPECT_DEATH({ s.substr(10); }, ""); #endif } + +TEST(StringViewTest, Compare) +{ + string_view s1 = "aaa"; + string_view s2 = "bbb"; + string_view s3 = "aaa"; + + // Equals + EXPECT_EQ(s1, s3); + EXPECT_EQ(s1, s1); + + // Less then + EXPECT_LT(s1, s2); + + // Greater then + EXPECT_GT(s2, s1); +} + +TEST(StringViewTest, MapKeyOrdering) +{ + std::map m = {{"bbb", 2}, {"aaa", 1}, {"ccc", 3}}; + size_t i = 1; + for (const auto &kv : m) + { + EXPECT_EQ(kv.second, i); + i++; + } +} diff --git a/bazel/opentelemetry_proto.BUILD b/bazel/opentelemetry_proto.BUILD index ddb9915bf2..8b6c50d680 100644 --- a/bazel/opentelemetry_proto.BUILD +++ b/bazel/opentelemetry_proto.BUILD @@ -16,6 +16,8 @@ package(default_visibility = ["//visibility:public"]) load("@rules_proto//proto:defs.bzl", "proto_library") +load("@com_github_grpc_grpc//bazel:cc_grpc_library.bzl", "cc_grpc_library") + proto_library( name = "common_proto", srcs = [ @@ -58,3 +60,26 @@ cc_proto_library( name = "trace_proto_cc", deps = [":trace_proto"], ) + +proto_library( + name = "trace_service_proto", + srcs = [ + "opentelemetry/proto/collector/trace/v1/trace_service.proto", + ], + deps = [ + ":trace_proto", + ], +) + +cc_proto_library( + name = "trace_service_proto_cc", + deps = [":trace_service_proto"], +) + +cc_grpc_library( + name = "trace_service_grpc_cc", + srcs = [":trace_service_proto"], + grpc_only = True, + deps = [":trace_service_proto_cc"], + generate_mocks = True, +) diff --git a/exporters/otlp/BUILD b/exporters/otlp/BUILD index 09b1516ab5..3b80a00380 100644 --- a/exporters/otlp/BUILD +++ b/exporters/otlp/BUILD @@ -25,6 +25,44 @@ cc_library( include_prefix = "exporters/otlp", deps = [ "//sdk/src/trace", + "//sdk/src/common:random", "@com_github_opentelemetry_proto//:trace_proto_cc", ], ) + +cc_library( + name = "otlp_exporter", + srcs = [ + 'otlp_exporter.h', + 'otlp_exporter.cc', + ], + deps = [ + ":recordable", + "//api", + "//sdk/src/trace", + "@com_github_opentelemetry_proto//:trace_proto_cc", + "@com_github_opentelemetry_proto//:trace_service_proto_cc", + + # For gRPC + "@com_github_opentelemetry_proto//:trace_service_grpc_cc", + "@com_github_grpc_grpc//:grpc++", + ], +) + +cc_test( + name = "recordable_test", + srcs = ["recordable_test.cc"], + deps = [ + ":recordable", + "@com_google_googletest//:gtest_main", + ], +) + +cc_test( + name = "otlp_exporter_test", + srcs = ["otlp_exporter_test.cc"], + deps = [ + ":otlp_exporter", + "@com_google_googletest//:gtest_main", + ], +) diff --git a/exporters/otlp/CMakeLists.txt b/exporters/otlp/CMakeLists.txt index 07311ce909..3cfc1a5832 100644 --- a/exporters/otlp/CMakeLists.txt +++ b/exporters/otlp/CMakeLists.txt @@ -1,3 +1,11 @@ add_library(opentelemetry_exporter_otprotocol recordable.cc) target_link_libraries(opentelemetry_exporter_otprotocol $) + +add_executable(recordable_test recordable_test.cc) +target_link_libraries(recordable_test + ${GTEST_BOTH_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} + opentelemetry_exporter_otprotocol + protobuf::libprotobuf) +gtest_add_tests(TARGET recordable_test TEST_PREFIX exporter. TEST_LIST recordable_test) diff --git a/exporters/otlp/otlp_exporter.cc b/exporters/otlp/otlp_exporter.cc new file mode 100644 index 0000000000..d3c274cb65 --- /dev/null +++ b/exporters/otlp/otlp_exporter.cc @@ -0,0 +1,71 @@ +#include "otlp_exporter.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace exporter +{ +namespace otlp +{ + +const std::string KCollectorAddress = "localhost:55678"; + +// ----------------------------- Helper functions ------------------------------ + +// Add span protobufs contained in recordables to request +void PopulateRequest(const nostd::span> &spans, + proto::collector::trace::v1::ExportTraceServiceRequest *request) +{ + auto resource_span = request->add_resource_spans(); + auto instrumentation_lib = resource_span->add_instrumentation_library_spans(); + + for (auto &recordable : spans) { + auto rec = std::unique_ptr( + static_cast(recordable.release())); + + proto::trace::v1::Span* span = instrumentation_lib->add_spans(); + span->CopyFrom(rec->span()); + } +} + +// Establish connection to OpenTelemetry Collector +std::unique_ptr MakeServiceStub() +{ + auto channel = grpc::CreateChannel(KCollectorAddress, grpc::InsecureChannelCredentials()); + return proto::collector::trace::v1::TraceService::NewStub(channel); +} + +// -------------------------------- Contructors -------------------------------- + +OtlpExporter::OtlpExporter(): OtlpExporter(MakeServiceStub()) {} + +OtlpExporter::OtlpExporter( + std::unique_ptr stub): + trace_service_stub_(std::move(stub)) {} + +// ----------------------------- Exporter methods ------------------------------ + +std::unique_ptr OtlpExporter::MakeRecordable() noexcept +{ + return std::unique_ptr(new Recordable); +} + +sdk::trace::ExportResult OtlpExporter::Export( + const nostd::span> &spans) noexcept +{ + proto::collector::trace::v1::ExportTraceServiceRequest request; + + PopulateRequest(spans, &request); + + grpc::ClientContext context; + proto::collector::trace::v1::ExportTraceServiceResponse response; + + grpc::Status status = trace_service_stub_->Export(&context, request, &response); + + if(!status.ok()){ + std::cerr << "OTLP trace exporter: Export() failed\n"; + return sdk::trace::ExportResult::kFailure; + } + return sdk::trace::ExportResult::kSuccess; +} +} // namespace otlp +} // namespace exporter +OPENTELEMETRY_END_NAMESPACE diff --git a/exporters/otlp/otlp_exporter.h b/exporters/otlp/otlp_exporter.h new file mode 100644 index 0000000000..3565f96b1e --- /dev/null +++ b/exporters/otlp/otlp_exporter.h @@ -0,0 +1,41 @@ +#pragma once + +#include "opentelemetry/sdk/trace/exporter.h" +#include "opentelemetry/sdk/trace/span_data.h" +#include "opentelemetry/proto/collector/trace/v1/trace_service.pb.h" +#include "opentelemetry/proto/collector/trace/v1/trace_service.grpc.pb.h" +#include "opentelemetry/proto/trace/v1/trace.pb.h" +#include "src/common/random.h" +#include "recordable.h" + +#include +#include + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace exporter +{ +namespace otlp +{ +class OtlpExporter final : public opentelemetry::sdk::trace::SpanExporter +{ +public: + OtlpExporter(); + + std::unique_ptr MakeRecordable() noexcept override; + + sdk::trace::ExportResult Export( + const nostd::span> &spans) noexcept override; + + void Shutdown(std::chrono::microseconds timeout = std::chrono::microseconds(0)) noexcept override {}; + +private: + // For testing + friend class OtlpExporterTestPeer; + + std::unique_ptr trace_service_stub_; + + OtlpExporter(std::unique_ptr stub); +}; +} // namespace otlp +} // namespace exporter +OPENTELEMETRY_END_NAMESPACE diff --git a/exporters/otlp/otlp_exporter_test.cc b/exporters/otlp/otlp_exporter_test.cc new file mode 100644 index 0000000000..17e8cb9eb0 --- /dev/null +++ b/exporters/otlp/otlp_exporter_test.cc @@ -0,0 +1,74 @@ +#include "otlp_exporter.h" +#include "opentelemetry/sdk/trace/simple_processor.h" +#include "opentelemetry/sdk/trace/tracer_provider.h" +#include "opentelemetry/trace/provider.h" +#include "opentelemetry/proto/collector/trace/v1/trace_service_mock.grpc.pb.h" + +#include + +using namespace testing; + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace exporter +{ +namespace otlp +{ + +class OtlpExporterTestPeer : public ::testing::Test +{ +public: + std::unique_ptr GetExporter( + proto::collector::trace::v1::TraceService::StubInterface* mock_stub) + { + return std::unique_ptr( + new OtlpExporter(std::unique_ptr(mock_stub))); + } +}; + +// Call Export() directly +TEST_F(OtlpExporterTestPeer, ExportUnitTest) +{ + auto mock_stub = new proto::collector::trace::v1::MockTraceServiceStub(); + auto exporter = std::shared_ptr(GetExporter(mock_stub)); + + auto recordable_1 = exporter->MakeRecordable(); + recordable_1->SetName("Test span 1"); + auto recordable_2 = exporter->MakeRecordable(); + recordable_2->SetName("Test span 2"); + + // Test successful RPC + nostd::span> batch_1(&recordable_1, 1); + EXPECT_CALL(*mock_stub, Export(_,_,_)).Times(Exactly(1)).WillOnce(Return(grpc::Status::OK)); + auto result = exporter->Export(batch_1); + EXPECT_EQ(sdk::trace::ExportResult::kSuccess, result); + + // Test failed RPC + nostd::span> batch_2(&recordable_2, 1); + EXPECT_CALL(*mock_stub, Export(_,_,_)).Times(Exactly(1)).WillOnce(Return(grpc::Status::CANCELLED)); + result = exporter->Export(batch_2); + EXPECT_EQ(sdk::trace::ExportResult::kFailure, result); +} + +// Create spans, let processor call Export() +TEST_F(OtlpExporterTestPeer, ExportIntegrationTest) +{ + auto mock_stub = new proto::collector::trace::v1::MockTraceServiceStub(); + auto exporter = std::unique_ptr(GetExporter(mock_stub)); + + auto processor = std::shared_ptr( + new sdk::trace::SimpleSpanProcessor(std::move(exporter))); + auto provider = nostd::shared_ptr(new sdk::trace::TracerProvider(processor)); + trace::Provider::SetTracerProvider(provider); + + nostd::shared_ptr tracer = provider->GetTracer("test"); + + EXPECT_CALL(*mock_stub, Export(_,_,_)).Times(AtLeast(1)).WillRepeatedly(Return(grpc::Status::OK)); + + auto parent_span = tracer->StartSpan("Test parent span"); + auto child_span = tracer->StartSpan("Test child span"); + child_span->End(); + parent_span->End(); +} +} // namespace otlp +} // namespace exporter +OPENTELEMETRY_END_NAMESPACE diff --git a/exporters/otlp/recordable.cc b/exporters/otlp/recordable.cc index d38f284577..1677bb6be1 100644 --- a/exporters/otlp/recordable.cc +++ b/exporters/otlp/recordable.cc @@ -5,6 +5,23 @@ namespace exporter { namespace otlp { +void Recordable::SetIds(trace::TraceId trace_id, + trace::SpanId span_id, + trace::SpanId parent_span_id) noexcept +{ + span_.set_trace_id(reinterpret_cast(trace_id.Id().data()), trace::TraceId::kSize); + span_.set_span_id(reinterpret_cast(span_id.Id().data()), trace::SpanId::kSize); + span_.set_parent_span_id(reinterpret_cast(parent_span_id.Id().data()), + trace::SpanId::kSize); +} + +void Recordable::SetAttribute(nostd::string_view key, + const opentelemetry::common::AttributeValue &&value) noexcept +{ + (void)key; + (void)value; +} + void Recordable::AddEvent(nostd::string_view name, core::SystemTimestamp timestamp) noexcept { (void)name; @@ -20,6 +37,18 @@ void Recordable::SetName(nostd::string_view name) noexcept { span_.set_name(name.data(), name.size()); } + +void Recordable::SetStartTime(opentelemetry::core::SystemTimestamp start_time) noexcept +{ + const uint64_t nano_unix_time = start_time.time_since_epoch().count(); + span_.set_start_time_unix_nano(nano_unix_time); +} + +void Recordable::SetDuration(std::chrono::nanoseconds duration) noexcept +{ + const uint64_t unix_end_time = span_.start_time_unix_nano() + duration.count(); + span_.set_end_time_unix_nano(unix_end_time); +} } // namespace otlp } // namespace exporter OPENTELEMETRY_END_NAMESPACE diff --git a/exporters/otlp/recordable.h b/exporters/otlp/recordable.h index 5ea1edf497..8490bc9141 100644 --- a/exporters/otlp/recordable.h +++ b/exporters/otlp/recordable.h @@ -14,13 +14,23 @@ class Recordable final : public sdk::trace::Recordable public: const proto::trace::v1::Span &span() const noexcept { return span_; } - // sdk::trace::Recordable + void SetIds(trace::TraceId trace_id, + trace::SpanId span_id, + trace::SpanId parent_span_id) noexcept override; + + void SetAttribute(nostd::string_view key, + const opentelemetry::common::AttributeValue &&value) noexcept override; + void AddEvent(nostd::string_view name, core::SystemTimestamp timestamp) noexcept override; void SetStatus(trace::CanonicalCode code, nostd::string_view description) noexcept override; void SetName(nostd::string_view name) noexcept override; + void SetStartTime(opentelemetry::core::SystemTimestamp start_time) noexcept override; + + void SetDuration(std::chrono::nanoseconds duration) noexcept override; + private: proto::trace::v1::Span span_; }; diff --git a/exporters/otlp/recordable_test.cc b/exporters/otlp/recordable_test.cc new file mode 100644 index 0000000000..b086c46b36 --- /dev/null +++ b/exporters/otlp/recordable_test.cc @@ -0,0 +1,73 @@ +#include "exporters/otlp/recordable.h" + +#include + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace exporter +{ +namespace otlp +{ +TEST(Recordable, SetIds) +{ + const trace::TraceId trace_id( + std::array( + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1})); + + const trace::SpanId span_id( + std::array( + {0, 0, 0, 0, 0, 0, 0, 2})); + + const trace::SpanId parent_span_id( + std::array( + {0, 0, 0, 0, 0, 0, 0, 3})); + + Recordable rec; + + rec.SetIds(trace_id, span_id, parent_span_id); + + EXPECT_EQ(rec.span().trace_id(), + std::string(reinterpret_cast(trace_id.Id().data()), trace::TraceId::kSize)); + EXPECT_EQ(rec.span().span_id(), + std::string(reinterpret_cast(span_id.Id().data()), trace::SpanId::kSize)); + EXPECT_EQ(rec.span().parent_span_id(), + std::string(reinterpret_cast(parent_span_id.Id().data()), trace::SpanId::kSize)); +} + +TEST(Recordable, SetName) +{ + Recordable rec; + nostd::string_view name = "TestSpan"; + rec.SetName(name); + EXPECT_EQ(rec.span().name(), name); +} + +TEST(Recordable, SetStartTime) +{ + Recordable rec; + std::chrono::system_clock::time_point start_time = std::chrono::system_clock::now(); + core::SystemTimestamp start_timestamp(start_time); + + uint64_t unix_start = + std::chrono::duration_cast(start_time.time_since_epoch()).count(); + + rec.SetStartTime(start_timestamp); + EXPECT_EQ(rec.span().start_time_unix_nano(), unix_start); +} + +TEST(Recordable, SetDuration) +{ + Recordable rec; + // Start time is 0 + core::SystemTimestamp start_timestamp; + + std::chrono::nanoseconds duration(10); + uint64_t unix_end = duration.count(); + + rec.SetStartTime(start_timestamp); + rec.SetDuration(duration); + + EXPECT_EQ(rec.span().end_time_unix_nano(), unix_end); +} +} // namespace otlp +} // namespace exporter +OPENTELEMETRY_END_NAMESPACE diff --git a/ext/src/zpages/README.md b/ext/src/zpages/README.md new file mode 100644 index 0000000000..f1bad98516 --- /dev/null +++ b/ext/src/zpages/README.md @@ -0,0 +1,46 @@ +# zPages +> Last updated 6/26/20 + +# Table of Contents +- [Summary](#summary) + - [TraceZ](#tracez) + - [RPCz](#rpcz) +- [Usage](#usage) +- [Links of Interest](#links-of-interest) + +## Summary +zPages allow easy viewing of tracing information. When included for a process, zPages will display basic information about that process on a webpage. There are currently two types of zPages: TraceZ and RPCz. + +Including a zPage within a page is useful for developers because it's quicker to get running than adding extra code and installing external exporters like Jaeger and Zipkin. zPages tend to be more lightweight than these external exporters, but are also helpful for debugging latency issues and deadlocks. + +The idea of "zPages" originates from one of OpenTelemetry's predecessors, [OpenCensus](https://opencensus.io/). You can read more about it [here](https://opencensus.io/zpages). OpenCensus has different zPage implementations in [Java](https://opencensus.io/zpages/java/), [Go](https://opencensus.io/zpages/go/), and [Node](https://opencensus.io/zpages/node/) and there has been similar internal solutions developed at companies like Uber, but *this is the first major open-source implementation of zPages in C++*. Within OpenTelemetry, zPages are also being developed in [Java](https://github.com/open-telemetry/opentelemetry-java). + +#### How It Works +On a high level, zPages work by reading a process' spans using a SpanProcessor, which exports spans to the appropriate DataAggregator that a HttpServer uses. + +> TODO: Add picture examples for span overview and individual span view + +### TraceZ +TraceZ is a type of zPage that shows information on tracing spans, and allows users to look closer at specific and individual spans. Details a user would view include span id, name, status, and timestamps. The individual components of TraceZ are as follows: + +- TracezSpanProcessor (TSP) + - Contact point for TraceZ to connect with a process, which collects tracing information and provides an interface for TDA. +- TracezDataAggregator (TDA) + - Intermediary between the TSP and THS, which also performs various functions and calculations to send the correct tracing information to the THS. +- TracezHttpServer (THS) + - User-facing web page generator, which creates HTML pages using TDA that display 1) overall information on all of the process's spans and 2) more detailed information on specific spans when clicked. + +### RPCz +RPCz is a type of zPage that provides details on instrumented sent and received RPC messages. Although there is currently no ongoing development of RPCz for OpenTelemetry, OpenCensus zPages have implementations of RPCz (linked above). + +# Usage + +> TODO: Add instructions to add zPages + +## Links of Interest +- [TracezSpanProcessor Design Doc](https://docs.google.com/document/d/1kO4iZARYyr-EGBlY2VNM3ELU3iw6ZrC58Omup_YT-fU/edit#) (pending review) +- [TracezDataAggregator Design Doc](https://docs.google.com/document/d/1ziKFgvhXFfRXZjOlAHQRR-TzcNcTXzg1p2I9oPCEIoU/edit?ts=5ef0d177#heading=h.5irk4csrpu0y) (pending review) +- [TracezHttpServer Design Doc](https://docs.google.com/document/d/1U1V8QZ5LtGl4Mich-aJ6KZGLHrMIE8pWyspmzvnIefI/edit#) (draft) +- [Contribution Guidelines](https://github.com/open-telemetry/opentelemetry-cpp/blob/master/CONTRIBUTING.md) + + diff --git a/sdk/include/opentelemetry/sdk/trace/sampler.h b/sdk/include/opentelemetry/sdk/trace/sampler.h index 93599b18e7..27071b458c 100644 --- a/sdk/include/opentelemetry/sdk/trace/sampler.h +++ b/sdk/include/opentelemetry/sdk/trace/sampler.h @@ -17,7 +17,7 @@ namespace trace namespace trace_api = opentelemetry::trace; /** - * A sampling Decision for a Span to be created. + * A sampling Decision for a Span to be created. */ enum class Decision { @@ -31,7 +31,7 @@ enum class Decision }; /** - * The output of ShouldSample. + * The output of ShouldSample. * It contains a sampling Decision and a set of Span Attributes. */ struct SamplingResult diff --git a/sdk/include/opentelemetry/sdk/trace/samplers/always_off.h b/sdk/include/opentelemetry/sdk/trace/samplers/always_off.h new file mode 100644 index 0000000000..0547068280 --- /dev/null +++ b/sdk/include/opentelemetry/sdk/trace/samplers/always_off.h @@ -0,0 +1,41 @@ +#pragma once + +#include "opentelemetry/sdk/trace/sampler.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace trace +{ +namespace trace_api = opentelemetry::trace; +/** + * The always off sampler always returns NOT_RECORD, effectively disabling + * tracing functionality. + */ +class AlwaysOffSampler : public Sampler +{ +public: + /** + * @return Returns NOT_RECORD always + */ + SamplingResult ShouldSample( + const SpanContext * /*parent_context*/, + trace_api::TraceId /*trace_id*/, + nostd::string_view /*name*/, + trace_api::SpanKind /*span_kind*/, + const trace_api::KeyValueIterable & /*attributes*/) noexcept override + { + return { Decision::NOT_RECORD, nullptr }; + } + + /** + * @return Description MUST be AlwaysOffSampler + */ + std::string GetDescription() const noexcept override + { + return "AlwaysOffSampler"; + } +}; +} // namespace trace +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE diff --git a/sdk/include/opentelemetry/sdk/trace/samplers/always_on.h b/sdk/include/opentelemetry/sdk/trace/samplers/always_on.h new file mode 100644 index 0000000000..e50d15829f --- /dev/null +++ b/sdk/include/opentelemetry/sdk/trace/samplers/always_on.h @@ -0,0 +1,36 @@ +#pragma once + +#include "opentelemetry/sdk/trace/sampler.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace trace +{ +namespace trace_api = opentelemetry::trace; +/** + * The always on sampler is a default sampler which always return Decision::RECORD_AND_SAMPLE + */ +class AlwaysOnSampler : public Sampler +{ +public: + /** + * @return Always return Decision RECORD_AND_SAMPLE + */ + inline SamplingResult ShouldSample(const SpanContext * /*parent_context*/, + trace_api::TraceId /*trace_id*/, + nostd::string_view /*name*/, + trace_api::SpanKind /*span_kind*/, + const trace_api::KeyValueIterable & /*attributes*/) noexcept override + { + return {Decision::RECORD_AND_SAMPLE, nullptr}; + } + + /** + * @return Description MUST be AlwaysOnSampler + */ + inline std::string GetDescription() const noexcept override { return "AlwaysOnSampler"; } +}; +} // namespace trace +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE diff --git a/sdk/test/trace/BUILD b/sdk/test/trace/BUILD index 6748cde17f..37018d7eeb 100644 --- a/sdk/test/trace/BUILD +++ b/sdk/test/trace/BUILD @@ -41,3 +41,27 @@ cc_test( "@com_google_googletest//:gtest_main", ], ) + +cc_test( + name = "always_on_sampler_test", + srcs = [ + "always_on_sampler_test.cc", + ], + deps = [ + "//sdk/src/trace", + "@com_google_googletest//:gtest_main", + ], +) + + + +cc_test( + name = "always_off_sampler_test", + srcs = [ + "always_off_sampler_test.cc", + ], + deps = [ + "//sdk/src/trace", + "@com_google_googletest//:gtest_main", + ], +) \ No newline at end of file diff --git a/sdk/test/trace/CMakeLists.txt b/sdk/test/trace/CMakeLists.txt index 5bca38440a..75bfd4f97a 100644 --- a/sdk/test/trace/CMakeLists.txt +++ b/sdk/test/trace/CMakeLists.txt @@ -1,5 +1,5 @@ foreach(testname tracer_provider_test span_data_test simple_processor_test - tracer_test) + tracer_test always_off_sampler_test always_on_sampler_test) add_executable(${testname} "${testname}.cc") target_link_libraries(${testname} ${GTEST_BOTH_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} opentelemetry_trace) diff --git a/sdk/test/trace/always_off_sampler_test.cc b/sdk/test/trace/always_off_sampler_test.cc new file mode 100644 index 0000000000..2c892fcfa7 --- /dev/null +++ b/sdk/test/trace/always_off_sampler_test.cc @@ -0,0 +1,30 @@ +#include "opentelemetry/sdk/trace/samplers/always_off.h" + +#include + +using opentelemetry::sdk::trace::AlwaysOffSampler; +using opentelemetry::sdk::trace::Decision; + +TEST(AlwaysOffSampler, ShouldSample) +{ + AlwaysOffSampler sampler; + + opentelemetry::trace::TraceId trace_id; + opentelemetry::trace::SpanKind span_kind = opentelemetry::trace::SpanKind::kInternal; + + using M = std::map; + M m1 = {{}}; + opentelemetry::trace::KeyValueIterableView view{m1}; + + auto sampling_result = sampler.ShouldSample(nullptr, trace_id, "", span_kind, view); + + ASSERT_EQ(Decision::NOT_RECORD, sampling_result.decision); + ASSERT_EQ(nullptr, sampling_result.attributes); +} + +TEST(AlwaysOffSampler, GetDescription) +{ + AlwaysOffSampler sampler; + + ASSERT_EQ("AlwaysOffSampler", sampler.GetDescription()); +} diff --git a/sdk/test/trace/always_on_sampler_test.cc b/sdk/test/trace/always_on_sampler_test.cc new file mode 100644 index 0000000000..a933cd0073 --- /dev/null +++ b/sdk/test/trace/always_on_sampler_test.cc @@ -0,0 +1,43 @@ +#include "opentelemetry/nostd/span.h" +#include "opentelemetry/sdk/trace/samplers/always_on.h" + +#include +#include + +using namespace opentelemetry::sdk::trace; +using namespace opentelemetry::nostd; + +TEST(AlwaysOnSampler, ShouldSample) +{ + AlwaysOnSampler sampler; + + // A buffer of trace_id with no specific meaning + constexpr uint8_t buf[] = {0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7}; + + trace_api::TraceId trace_id_invalid; + trace_api::TraceId trace_id_valid(buf); + std::map key_value_container = {{"key", 0}}; + + // Test with invalid (empty) trace id and empty parent context + auto sampling_result = sampler.ShouldSample( + nullptr, trace_id_invalid, "invalid trace id test", trace_api::SpanKind::kServer, + trace_api::KeyValueIterableView>(key_value_container)); + + ASSERT_EQ(Decision::RECORD_AND_SAMPLE, sampling_result.decision); + ASSERT_EQ(nullptr, sampling_result.attributes); + + // Test with a valid trace id and empty parent context + sampling_result = sampler.ShouldSample( + nullptr, trace_id_valid, "valid trace id test", trace_api::SpanKind::kServer, + trace_api::KeyValueIterableView>(key_value_container)); + + ASSERT_EQ(Decision::RECORD_AND_SAMPLE, sampling_result.decision); + ASSERT_EQ(nullptr, sampling_result.attributes); +} + +TEST(AlwaysOnSampler, GetDescription) +{ + AlwaysOnSampler sampler; + + ASSERT_EQ("AlwaysOnSampler", sampler.GetDescription()); +} diff --git a/third_party/opentelemetry-proto/README b/third_party/opentelemetry-proto/README index dfd3a68e21..e32d7de183 100644 --- a/third_party/opentelemetry-proto/README +++ b/third_party/opentelemetry-proto/README @@ -1,2 +1,2 @@ From: https://github.com/open-telemetry/opentelemetry-proto -Commit: d496c80b353bc4a4f754ae686b59ca3c41de0946 +Commit: e43e1abc40428a6ee98e3bfd79bec1dfa2ed18cd diff --git a/third_party/opentelemetry-proto/opentelemetry/proto/collector/metrics/v1/metrics_service_http.yaml b/third_party/opentelemetry-proto/opentelemetry/proto/collector/metrics/v1/metrics_service_http.yaml new file mode 100644 index 0000000000..bc5f9ff241 --- /dev/null +++ b/third_party/opentelemetry-proto/opentelemetry/proto/collector/metrics/v1/metrics_service_http.yaml @@ -0,0 +1,9 @@ +# This is an API configuration to generate an HTTP/JSON -> gRPC gateway for the +# OpenTelemetry service using github.com/grpc-ecosystem/grpc-gateway. +type: google.api.Service +config_version: 3 +http: + rules: + - selector: opentelemetry.proto.collector.metrics.v1.MetricsService.Export + post: /v1/metrics + body: "*" diff --git a/third_party/opentelemetry-proto/opentelemetry/proto/collector/trace/v1/trace_service_http.yaml b/third_party/opentelemetry-proto/opentelemetry/proto/collector/trace/v1/trace_service_http.yaml index 7754e5ff12..10eae48d51 100644 --- a/third_party/opentelemetry-proto/opentelemetry/proto/collector/trace/v1/trace_service_http.yaml +++ b/third_party/opentelemetry-proto/opentelemetry/proto/collector/trace/v1/trace_service_http.yaml @@ -7,6 +7,3 @@ http: - selector: opentelemetry.proto.collector.trace.v1.TraceService.Export post: /v1/trace body: "*" - - selector: opentelemetry.proto.collector.metrics.v1.MetricsService.Export - post: /v1/trace - body: "*" \ No newline at end of file diff --git a/third_party/opentelemetry-proto/opentelemetry/proto/common/v1/common.proto b/third_party/opentelemetry-proto/opentelemetry/proto/common/v1/common.proto index b3b1852459..dc67e43fb6 100644 --- a/third_party/opentelemetry-proto/opentelemetry/proto/common/v1/common.proto +++ b/third_party/opentelemetry-proto/opentelemetry/proto/common/v1/common.proto @@ -21,35 +21,57 @@ option java_package = "io.opentelemetry.proto.common.v1"; option java_outer_classname = "CommonProto"; option go_package = "github.com/open-telemetry/opentelemetry-proto/gen/go/common/v1"; -// AttributeKeyValue is a key-value pair that is used to store Span attributes, Link -// attributes, etc. -message AttributeKeyValue { - // ValueType is the enumeration of possible types that value can have. - enum ValueType { - STRING = 0; - INT = 1; - DOUBLE = 2; - BOOL = 3; - }; - - // key part of the key-value pair. - string key = 1; +// AnyValue is used to represent any type of attribute value. AnyValue may contain a +// primitive value such as a string or integer or it may contain an arbitrary nested +// object containing arrays, key-value lists and primitives. +message AnyValue { + // The value is one of the listed fields. It is valid for all values to be unspecified + // in which case this AnyValue is considered to be "null". + oneof value { + string string_value = 1; + bool bool_value = 2; + int64 int_value = 3; + double double_value = 4; + ArrayValue array_value = 5; + KeyValueList kvlist_value = 6; + } +} - // type of the value. - ValueType type = 2; +// ArrayValue is a list of AnyValue messages. We need ArrayValue as a message +// since oneof in AnyValue does not allow repeated fields. +message ArrayValue { + // Array of values. The array may be empty (contain 0 elements). + repeated AnyValue values = 1; +} - // Only one of the following fields is supposed to contain data (determined by `type` field). - // This is deliberately not using Protobuf `oneof` for performance reasons (verified by benchmarks). +// KeyValueList is a list of KeyValue messages. We need KeyValueList as a message +// since `oneof` in AnyValue does not allow repeated fields. Everywhere else where we need +// a list of KeyValue messages (e.g. in Span) we use `repeated KeyValue` directly to +// avoid unnecessary extra wrapping (which slows down the protocol). The 2 approaches +// are semantically equivalent. +message KeyValueList { + // A collection of key/value pairs of key-value pairs. The list may be empty (may + // contain 0 elements). + repeated KeyValue values = 1; +} - string string_value = 3; - int64 int_value = 4; - double double_value = 5; - bool bool_value = 6; +// KeyValue is a key-value pair that is used to store Span attributes, Link +// attributes, etc. +message KeyValue { + string key = 1; + AnyValue value = 2; } // StringKeyValue is a pair of key/value strings. This is the simpler (and faster) version -// of AttributeKeyValue that only supports string values. +// of KeyValue that only supports string values. message StringKeyValue { string key = 1; string value = 2; } + +// InstrumentationLibrary is a message representing the instrumentation library information +// such as the fully qualified name and version. +message InstrumentationLibrary { + string name = 1; + string version = 2; +} diff --git a/third_party/opentelemetry-proto/opentelemetry/proto/metrics/v1/metrics.proto b/third_party/opentelemetry-proto/opentelemetry/proto/metrics/v1/metrics.proto index a15a7b6c2b..1d458824fe 100644 --- a/third_party/opentelemetry-proto/opentelemetry/proto/metrics/v1/metrics.proto +++ b/third_party/opentelemetry-proto/opentelemetry/proto/metrics/v1/metrics.proto @@ -24,14 +24,24 @@ option java_package = "io.opentelemetry.proto.metrics.v1"; option java_outer_classname = "MetricsProto"; option go_package = "github.com/open-telemetry/opentelemetry-proto/gen/go/metrics/v1"; -// A collection of metrics from a Resource. +// A collection of InstrumentationLibraryMetrics from a Resource. message ResourceMetrics { - // A list of metrics that originate from a resource. - repeated Metric metrics = 1; - // The resource for the metrics in this message. // If this field is not set then no resource info is known. - opentelemetry.proto.resource.v1.Resource resource = 2; + opentelemetry.proto.resource.v1.Resource resource = 1; + + // A list of metrics that originate from a resource. + repeated InstrumentationLibraryMetrics instrumentation_library_metrics = 2; +} + +// A collection of Metrics produced by an InstrumentationLibrary. +message InstrumentationLibraryMetrics { + // The instrumentation library information for the metrics in this message. + // If this field is not set then no library info is known. + opentelemetry.proto.common.v1.InstrumentationLibrary instrumentation_library = 1; + + // A list of metrics that originate from an instrumentation library. + repeated Metric metrics = 2; } // Defines a Metric which has one or more timeseries. @@ -90,10 +100,10 @@ message Metric { // Data is a list of one or more DataPoints for a single metric. Only one of the // following fields is used for the data, depending on the type of the metric defined // by MetricDescriptor.type field. - repeated Int64DataPoint int64_datapoints = 2; - repeated DoubleDataPoint double_datapoints = 3; - repeated HistogramDataPoint histogram_datapoints = 4; - repeated SummaryDataPoint summary_datapoints = 5; + repeated Int64DataPoint int64_data_points = 2; + repeated DoubleDataPoint double_data_points = 3; + repeated HistogramDataPoint histogram_data_points = 4; + repeated SummaryDataPoint summary_data_points = 5; } // Defines a metric type and its schema. @@ -108,49 +118,36 @@ message MetricDescriptor { // described by http://unitsofmeasure.org/ucum.html. string unit = 3; - // Type of the metric. It describes how the data is reported. - // - // A gauge is an instantaneous measurement of a value. - // - // A counter/cumulative measurement is a value accumulated over a time - // interval. In a time series, cumulative measurements should have the same - // start time, increasing values, until an event resets the cumulative value - // to zero and sets a new start time for the subsequent points. + // Type is the type of values a metric has. enum Type { - // Do not use this default value. - UNSPECIFIED = 0; - - // Integer gauge. The value can go both up and down over time. - // Corresponding values are stored in Int64DataPoint. - GAUGE_INT64 = 1; - - // Floating point gauge. The value can go both up and down over time. - // Corresponding values are stored in DoubleDataPoint. - GAUGE_DOUBLE = 2; - - // Histogram gauge measurement. - // Used in scenarios like a snapshot of time that current items in a queue - // have spent there. - // Corresponding values are stored in HistogramDataPoint. The count and sum of the - // histogram can go both up and down over time. Recorded values are always >= 0. - GAUGE_HISTOGRAM = 3; - - // Integer counter measurement. The value cannot decrease; if value is reset then - // start_time_unixnano should also be reset. - // Corresponding values are stored in Int64DataPoint. - COUNTER_INT64 = 4; - - // Floating point counter measurement. The value cannot decrease, if - // resets then the start_time_unixnano should also be reset. - // Recorded values are always >= 0. - // Corresponding values are stored in DoubleDataPoint. - COUNTER_DOUBLE = 5; - - // Histogram cumulative measurement. - // Corresponding values are stored in HistogramDataPoint. The count and sum of the - // histogram cannot decrease; if values are reset then start_time_unixnano - // should also be reset to the new start timestamp. - CUMULATIVE_HISTOGRAM = 6; + // INVALID_TYPE is the default Type, it MUST not be used. + INVALID_TYPE = 0; + + // INT64 values are signed 64-bit integers. + // + // A Metric of this Type MUST store its values as Int64DataPoint. + INT64 = 1; + + // MONOTONIC_INT64 values are monotonically increasing signed 64-bit + // integers. + // + // A Metric of this Type MUST store its values as Int64DataPoint. + MONOTONIC_INT64 = 2; + + // DOUBLE values are double-precision floating-point numbers. + // + // A Metric of this Type MUST store its values as DoubleDataPoint. + DOUBLE = 3; + + // MONOTONIC_DOUBLE values are monotonically increasing double-precision + // floating-point numbers. + // + // A Metric of this Type MUST store its values as DoubleDataPoint. + MONOTONIC_DOUBLE = 4; + + // Histogram measurement. + // Corresponding values are stored in HistogramDataPoint. + HISTOGRAM = 5; // Summary value. Some frameworks implemented Histograms as a summary of observations // (usually things like request durations and response sizes). While it @@ -158,13 +155,88 @@ message MetricDescriptor { // values, it calculates configurable percentiles over a sliding time // window. // Corresponding values are stored in SummaryDataPoint. - SUMMARY = 7; + SUMMARY = 6; } + + // type is the type of values this metric has. Type type = 4; - // The set of labels associated with the metric descriptor. Labels in this list apply to - // all data points. - repeated opentelemetry.proto.common.v1.StringKeyValue labels = 5; + // Temporality is the temporal quality values of a metric have. It + // describes how those values relate to the time interval over which they + // are reported. + enum Temporality { + // INVALID_TEMPORALITY is the default Temporality, it MUST not be + // used. + INVALID_TEMPORALITY = 0; + + // INSTANTANEOUS is a metric whose values are measured at a particular + // instant. The values are not aggregated over any time interval and are + // unique per timestamp. As such, these metrics are not expected to have + // an associated start time. + INSTANTANEOUS = 1; + + // DELTA is a metric whose values are the aggregation of measurements + // made over a time interval. Successive metrics contain aggregation of + // values from continuous and non-overlapping intervals. + // + // The values for a DELTA metric are based only on the time interval + // associated with one measurement cycle. There is no dependency on + // previous measurements like is the case for CUMULATIVE metrics. + // + // For example, consider a system measuring the number of requests that + // it receives and reports the sum of these requests every second as a + // DELTA metric: + // + // 1. The system starts receiving at time=t_0. + // 2. A request is received, the system measures 1 request. + // 3. A request is received, the system measures 1 request. + // 4. A request is received, the system measures 1 request. + // 5. The 1 second collection cycle ends. A metric is exported for the + // number of requests received over the interval of time t_0 to + // t_0+1 with a value of 3. + // 6. A request is received, the system measures 1 request. + // 7. A request is received, the system measures 1 request. + // 8. The 1 second collection cycle ends. A metric is exported for the + // number of requests received over the interval of time t_0+1 to + // t_0+2 with a value of 2. + DELTA = 2; + + // CUMULATIVE is a metric whose values are the aggregation of + // successively made measurements from a fixed start time until the last + // reported measurement. This means that current values of a CUMULATIVE + // metric depend on all previous measurements since the start time. + // Because of this, the sender is required to retain this state in some + // form. If this state is lost or invalidated, the CUMULATIVE metric + // values MUST be reset and a new fixed start time following the last + // reported measurement time sent MUST be used. + // + // For example, consider a system measuring the number of requests that + // it receives and reports the sum of these requests every second as a + // CUMULATIVE metric: + // + // 1. The system starts receiving at time=t_0. + // 2. A request is received, the system measures 1 request. + // 3. A request is received, the system measures 1 request. + // 4. A request is received, the system measures 1 request. + // 5. The 1 second collection cycle ends. A metric is exported for the + // number of requests received over the interval of time t_0 to + // t_0+1 with a value of 3. + // 6. A request is received, the system measures 1 request. + // 7. A request is received, the system measures 1 request. + // 8. The 1 second collection cycle ends. A metric is exported for the + // number of requests received over the interval of time t_0 to + // t_0+2 with a value of 5. + // 9. The system experiences a fault and loses state. + // 10. The system recovers and resumes receiving at time=t_1. + // 11. A request is received, the system measures 1 request. + // 12. The 1 second collection cycle ends. A metric is exported for the + // number of requests received over the interval of time t_1 to + // t_0+1 with a value of 1. + CUMULATIVE = 3; + } + + // temporality is the Temporality of values this metric has. + Temporality temporality = 5; } // Int64DataPoint is a single data point in a timeseries that describes the time-varying @@ -173,20 +245,20 @@ message Int64DataPoint { // The set of labels that uniquely identify this timeseries. repeated opentelemetry.proto.common.v1.StringKeyValue labels = 1; - // start_time_unixnano is the time when the cumulative value was reset to zero. + // start_time_unix_nano is the time when the cumulative value was reset to zero. // This is used for Counter type only. For Gauge the value is not specified and // defaults to 0. // - // The cumulative value is over the time interval (start_time_unixnano, timestamp_unixnano]. + // The cumulative value is over the time interval (start_time_unix_nano, time_unix_nano]. // Value is UNIX Epoch time in nanoseconds since 00:00:00 UTC on 1 January 1970. // // Value of 0 indicates that the timestamp is unspecified. In that case the timestamp // may be decided by the backend. - fixed64 start_time_unixnano = 2; + fixed64 start_time_unix_nano = 2; - // timestamp_unixnano is the moment when this value was recorded. + // time_unix_nano is the moment when this value was recorded. // Value is UNIX Epoch time in nanoseconds since 00:00:00 UTC on 1 January 1970. - fixed64 timestamp_unixnano = 3; + fixed64 time_unix_nano = 3; // value itself. int64 value = 4; @@ -198,20 +270,20 @@ message DoubleDataPoint { // The set of labels that uniquely identify this timeseries. repeated opentelemetry.proto.common.v1.StringKeyValue labels = 1; - // start_time_unixnano is the time when the cumulative value was reset to zero. + // start_time_unix_nano is the time when the cumulative value was reset to zero. // This is used for Counter type only. For Gauge the value is not specified and // defaults to 0. // - // The cumulative value is over the time interval (start_time_unixnano, timestamp_unixnano]. + // The cumulative value is over the time interval (start_time_unix_nano, time_unix_nano]. // Value is UNIX Epoch time in nanoseconds since 00:00:00 UTC on 1 January 1970. // // Value of 0 indicates that the timestamp is unspecified. In that case the timestamp // may be decided by the backend. - fixed64 start_time_unixnano = 2; + fixed64 start_time_unix_nano = 2; - // timestamp_unixnano is the moment when this value was recorded. + // time_unix_nano is the moment when this value was recorded. // Value is UNIX Epoch time in nanoseconds since 00:00:00 UTC on 1 January 1970. - fixed64 timestamp_unixnano = 3; + fixed64 time_unix_nano = 3; // value itself. double value = 4; @@ -224,19 +296,19 @@ message HistogramDataPoint { // The set of labels that uniquely identify this timeseries. repeated opentelemetry.proto.common.v1.StringKeyValue labels = 1; - // start_time_unixnano is the time when the cumulative value was reset to zero. + // start_time_unix_nano is the time when the cumulative value was reset to zero. // - // The cumulative value is over the time interval (start_time_unixnano, timestamp_unixnano]. + // The cumulative value is over the time interval (start_time_unix_nano, time_unix_nano]. // Value is UNIX Epoch time in nanoseconds since 00:00:00 UTC on 1 January 1970. // // Value of 0 indicates that the timestamp is unspecified. In that case the timestamp // may be decided by the backend. // Note: this field is always unspecified and ignored if MetricDescriptor.type==GAUGE_HISTOGRAM. - fixed64 start_time_unixnano = 2; + fixed64 start_time_unix_nano = 2; - // timestamp_unixnano is the moment when this value was recorded. + // time_unix_nano is the moment when this value was recorded. // Value is UNIX Epoch time in nanoseconds since 00:00:00 UTC on 1 January 1970. - fixed64 timestamp_unixnano = 3; + fixed64 time_unix_nano = 3; // count is the number of values in the population. Must be non-negative. This value // must be equal to the sum of the "count" fields in buckets if a histogram is provided. @@ -262,9 +334,9 @@ message HistogramDataPoint { // the defined bounds. double value = 1; - // timestamp_unixnano is the moment when this exemplar was recorded. + // time_unix_nano is the moment when this exemplar was recorded. // Value is UNIX Epoch time in nanoseconds since 00:00:00 UTC on 1 January 1970. - fixed64 timestamp_unixnano = 2; + fixed64 time_unix_nano = 2; // exemplar_attachments are contextual information about the example value. // Keys in this list must be unique. @@ -318,18 +390,18 @@ message SummaryDataPoint { // The set of labels that uniquely identify this timeseries. repeated opentelemetry.proto.common.v1.StringKeyValue labels = 1; - // start_time_unixnano is the time when the cumulative value was reset to zero. + // start_time_unix_nano is the time when the cumulative value was reset to zero. // - // The cumulative value is over the time interval (start_time_unixnano, timestamp_unixnano]. + // The cumulative value is over the time interval (start_time_unix_nano, time_unix_nano]. // Value is UNIX Epoch time in nanoseconds since 00:00:00 UTC on 1 January 1970. // // Value of 0 indicates that the timestamp is unspecified. In that case the timestamp // may be decided by the backend. - fixed64 start_time_unixnano = 2; + fixed64 start_time_unix_nano = 2; - // timestamp_unixnano is the moment when this value was recorded. + // time_unix_nano is the moment when this value was recorded. // Value is UNIX Epoch time in nanoseconds since 00:00:00 UTC on 1 January 1970. - fixed64 timestamp_unixnano = 3; + fixed64 time_unix_nano = 3; // The total number of recorded values since start_time. Optional since // some systems don't expose this. @@ -340,6 +412,13 @@ message SummaryDataPoint { double sum = 5; // Represents the value at a given percentile of a distribution. + // + // To record Min and Max values following conventions are used: + // - The 100th percentile is equivalent to the maximum value observed. + // - The 0th percentile is equivalent to the minimum value observed. + // + // See the following issue for more context: + // https://github.com/open-telemetry/opentelemetry-proto/issues/125 message ValueAtPercentile { // The percentile of a distribution. Must be in the interval // [0.0, 100.0]. diff --git a/third_party/opentelemetry-proto/opentelemetry/proto/resource/v1/resource.proto b/third_party/opentelemetry-proto/opentelemetry/proto/resource/v1/resource.proto index a9e1711af4..fa5d97c6f8 100644 --- a/third_party/opentelemetry-proto/opentelemetry/proto/resource/v1/resource.proto +++ b/third_party/opentelemetry-proto/opentelemetry/proto/resource/v1/resource.proto @@ -26,7 +26,7 @@ option go_package = "github.com/open-telemetry/opentelemetry-proto/gen/go/resour // Resource information. message Resource { // Set of labels that describe the resource. - repeated opentelemetry.proto.common.v1.AttributeKeyValue attributes = 1; + repeated opentelemetry.proto.common.v1.KeyValue attributes = 1; // dropped_attributes_count is the number of dropped attributes. If the value is 0, then // no attributes were dropped. diff --git a/third_party/opentelemetry-proto/opentelemetry/proto/trace/v1/trace.proto b/third_party/opentelemetry-proto/opentelemetry/proto/trace/v1/trace.proto index 7f0e4a75c0..5a2350fdee 100644 --- a/third_party/opentelemetry-proto/opentelemetry/proto/trace/v1/trace.proto +++ b/third_party/opentelemetry-proto/opentelemetry/proto/trace/v1/trace.proto @@ -24,13 +24,23 @@ option java_package = "io.opentelemetry.proto.trace.v1"; option java_outer_classname = "TraceProto"; option go_package = "github.com/open-telemetry/opentelemetry-proto/gen/go/trace/v1"; -// A collection of spans from a Resource. +// A collection of InstrumentationLibrarySpans from a Resource. message ResourceSpans { // The resource for the spans in this message. // If this field is not set then no resource info is known. opentelemetry.proto.resource.v1.Resource resource = 1; - // A list of Spans that originate from a resource. + // A list of InstrumentationLibrarySpans that originate from a resource. + repeated InstrumentationLibrarySpans instrumentation_library_spans = 2; +} + +// A collection of Spans produced by an InstrumentationLibrary. +message InstrumentationLibrarySpans { + // The instrumentation library information for the spans in this message. + // If this field is not set then no library info is known. + opentelemetry.proto.common.v1.InstrumentationLibrary instrumentation_library = 1; + + // A list of Spans that originate from an instrumentation library. repeated Span spans = 2; } @@ -123,21 +133,21 @@ message Span { // and `SERVER` (callee) to identify queueing latency associated with the span. SpanKind kind = 6; - // start_time_unixnano is the start time of the span. On the client side, this is the time + // start_time_unix_nano is the start time of the span. On the client side, this is the time // kept by the local machine where the span execution starts. On the server side, this // is the time when the server's application handler starts running. // Value is UNIX Epoch time in nanoseconds since 00:00:00 UTC on 1 January 1970. // // This field is semantically required and it is expected that end_time >= start_time. - fixed64 start_time_unixnano = 7; + fixed64 start_time_unix_nano = 7; - // end_time_unixnano is the end time of the span. On the client side, this is the time + // end_time_unix_nano is the end time of the span. On the client side, this is the time // kept by the local machine where the span execution ends. On the server side, this // is the time when the server application handler stops running. // Value is UNIX Epoch time in nanoseconds since 00:00:00 UTC on 1 January 1970. // // This field is semantically required and it is expected that end_time >= start_time. - fixed64 end_time_unixnano = 8; + fixed64 end_time_unix_nano = 8; // attributes is a collection of key/value pairs. The value can be a string, // an integer, a double or the Boolean values `true` or `false`. Note, global attributes @@ -147,7 +157,7 @@ message Span { // "/http/server_latency": 300 // "abc.com/myattribute": true // "abc.com/score": 10.239 - repeated opentelemetry.proto.common.v1.AttributeKeyValue attributes = 9; + repeated opentelemetry.proto.common.v1.KeyValue attributes = 9; // dropped_attributes_count is the number of attributes that were discarded. Attributes // can be discarded because their keys are too long or because there are too many @@ -157,15 +167,15 @@ message Span { // Event is a time-stamped annotation of the span, consisting of user-supplied // text description and key-value pairs. message Event { - // time_unixnano is the time the event occurred. - fixed64 time_unixnano = 1; + // time_unix_nano is the time the event occurred. + fixed64 time_unix_nano = 1; // name of the event. // This field is semantically required to be set to non-empty string. string name = 2; // attributes is a collection of attribute key/value pairs on the event. - repeated opentelemetry.proto.common.v1.AttributeKeyValue attributes = 3; + repeated opentelemetry.proto.common.v1.KeyValue attributes = 3; // dropped_attributes_count is the number of dropped attributes. If the value is 0, // then no attributes were dropped. @@ -195,7 +205,7 @@ message Span { string trace_state = 3; // attributes is a collection of attribute key/value pairs on the link. - repeated opentelemetry.proto.common.v1.AttributeKeyValue attributes = 4; + repeated opentelemetry.proto.common.v1.KeyValue attributes = 4; // dropped_attributes_count is the number of dropped attributes. If the value is 0, // then no attributes were dropped.