From 8fd81b03d1449c4a9f5108ec5d1e6363188df68e Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Fri, 18 Dec 2020 15:58:10 +0530 Subject: [PATCH 01/33] zipkin changes --- CMakeLists.txt | 1 + exporters/CMakeLists.txt | 4 + .../exporters/zipkin/recordable.h | 52 +++++ .../exporters/zipkin/zipkin_exporter.h | 89 ++++++++ exporters/zipkin/src/recordable.cc | 185 +++++++++++++++ exporters/zipkin/src/zipkin_exporter.cc | 109 +++++++++ .../zipkin/test/zipkin_recordable_test.cc | 216 ++++++++++++++++++ .../ext/http/client/curl/http_client_curl.h | 29 ++- .../http/client/curl/http_operation_curl.h | 30 ++- .../ext/http/client/http_client.h | 16 ++ .../ext/http/client/http_client_factory.h | 27 +++ .../ext/http/common/url_parser.h | 108 +++++++++ ext/test/http/BUILD | 1 + ext/test/http/CMakeLists.txt | 13 +- ext/test/http/curl_http_test.cc | 56 ++++- ext/test/http/url_parser_test.cc | 70 ++++++ 16 files changed, 986 insertions(+), 20 deletions(-) create mode 100644 exporters/zipkin/include/opentelemetry/exporters/zipkin/recordable.h create mode 100644 exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h create mode 100644 exporters/zipkin/src/recordable.cc create mode 100644 exporters/zipkin/src/zipkin_exporter.cc create mode 100644 exporters/zipkin/test/zipkin_recordable_test.cc create mode 100644 ext/include/opentelemetry/ext/http/client/http_client_factory.h create mode 100644 ext/include/opentelemetry/ext/http/common/url_parser.h create mode 100644 ext/test/http/url_parser_test.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index c67451ec01..ef563be8be 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,6 +11,7 @@ if(NOT DEFINED CMAKE_CXX_STANDARD) endif() option(WITH_OTLP "Whether to include the OpenTelemetry Protocol in the SDK" OFF) +option(WITH_ZIPKIN "Whether to include the Zipkin exporter in the SDK" OFF) option(WITH_PROMETHEUS "Whether to include the Prometheus Client in the SDK" OFF) diff --git a/exporters/CMakeLists.txt b/exporters/CMakeLists.txt index 83bb91c6c4..e9458829bb 100644 --- a/exporters/CMakeLists.txt +++ b/exporters/CMakeLists.txt @@ -8,3 +8,7 @@ add_subdirectory(memory) if(WITH_PROMETHEUS) add_subdirectory(prometheus) endif() + +if (WITH_ZIPKIN) + add_subdirectory(zipkin) +endif() diff --git a/exporters/zipkin/include/opentelemetry/exporters/zipkin/recordable.h b/exporters/zipkin/include/opentelemetry/exporters/zipkin/recordable.h new file mode 100644 index 0000000000..6b195b2d21 --- /dev/null +++ b/exporters/zipkin/include/opentelemetry/exporters/zipkin/recordable.h @@ -0,0 +1,52 @@ +#pragma once + +#include "opentelemetry/sdk/trace/recordable.h" +#include "opentelemetry/version.h" +#include "nlohmann/json.hpp" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace exporter +{ +namespace zipkin +{ +using ZipkinSpan = nlohmann::json; + +enum class TransportFormat { + JSON, + PROTOBUF +}; + +class Recordable final : public sdk::trace::Recordable +{ +public: + const ZipkinSpan &span() const noexcept { return span_; } + + 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, + const common::KeyValueIterable &attributes) noexcept override; + + void AddLink(const opentelemetry::trace::SpanContext &span_context, + const common::KeyValueIterable &attributes) 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: + + ZipkinSpan span_; +}; +} // namespace zipkin +} // namespace exporter +OPENTELEMETRY_END_NAMESPACE diff --git a/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h b/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h new file mode 100644 index 0000000000..789c069101 --- /dev/null +++ b/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h @@ -0,0 +1,89 @@ +#pragma once + +#include "opentelemetry/sdk/trace/exporter.h" +#include "opentelemetry/sdk/trace/span_data.h" +#include "opentelemetry/exporters/zipkin/recordable.h" +#include "opentelemetry/ext/http/client/http_client_factory.h" +#include "opentelemetry/ext/http/common/url_parser.h" + +#include "nlohmann/json.hpp" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace exporter +{ +namespace zipkin +{ +/** + * Struct to hold OTLP exporter options. + */ + +struct ZipkinExporterOptions +{ + // The endpoint to export to. By default the OpenTelemetry Collector's default endpoint. + std::string endpoint = "http:://localhost:9411/api/v2/spans"; + TransportFormat format = TransportFormat::JSON; + std::string service_name = "default-service"; + std::string ipv4; + std::string ipv6; +}; + +namespace trace_sdk = opentelemetry::sdk::trace; +namespace http_client = opentelemetry::ext::http::client; + +/** + * The OTLP exporter exports span data in OpenTelemetry Protocol (OTLP) format. + */ +class ZipkinExporter final : public trace_sdk::SpanExporter, public http_client::EventHandler +{ +public: + /** + * Create an OtlpExporter using all default options. + */ + ZipkinExporter(); + + /** + * Create an OtlpExporter using the given options. + */ + ZipkinExporter(const ZipkinExporterOptions &options); + + /** + * Create a span recordable. + * @return a newly initialized Recordable object + */ + std::unique_ptr MakeRecordable() noexcept override; + + /** + * Export a batch of span recordables in OTLP format. + * @param spans a span of unique pointers to span recordables + */ + trace_sdk::ExportResult Export( + const nostd::span> &spans) noexcept override; + + /** + * Shut down the exporter. + * @param timeout an optional timeout, the default timeout of 0 means that no + * timeout is applied. + */ + void Shutdown( + std::chrono::microseconds timeout = std::chrono::microseconds(0)) noexcept override{}; + + void OnResponse(http_client::Response &response) noexcept override {/*Not required */} + + virtual void OnEvent(http_client::SessionState state, nostd::string_view msg) noexcept override { /* Not required */}; + + virtual void OnConnecting(const http_client::SSLCertificate &) noexcept override { /* Not required */}; + +private: + void InitializeLocalEndpoint(); + +private: + // The configuration options associated with this exporter. + bool isShutdown_ = false; + std::shared_ptr http_session_manager_; + nlohmann::json local_end_point_; + ZipkinExporterOptions options_; + ext::http::common::UrlParser url_parser_; +}; +} // namespace zipkin +} // namespace exporter +OPENTELEMETRY_END_NAMESPACE \ No newline at end of file diff --git a/exporters/zipkin/src/recordable.cc b/exporters/zipkin/src/recordable.cc new file mode 100644 index 0000000000..5966a8aae5 --- /dev/null +++ b/exporters/zipkin/src/recordable.cc @@ -0,0 +1,185 @@ +#include "opentelemetry/exporters/zipkin/recordable.h" + +#include + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace exporter +{ +namespace zipkin +{ + +const int kAttributeValueSize = 14; +const char *EMPTY_PARENT_SPAN= "0000000000000000"; + +void Recordable::SetIds(trace::TraceId trace_id, + trace::SpanId span_id, + trace::SpanId parent_span_id) noexcept +{ + char traceid[trace::TraceId::kSize*2] = {0}; + trace_id.ToLowerBase16(traceid); + char spanid[trace::SpanId::kSize*2] = {0}; + span_id.ToLowerBase16(spanid); + char parentid[trace::SpanId::kSize*2] = {0}; + parent_span_id.ToLowerBase16(parentid); + span_["id"] = std::string(spanid, 16); + span_["parentId"] = std::string(parentid, 16); + span_["traceId"] = std::string(traceid, 32); +} + +void PopulateAttribute( nlohmann::json &attribute, + nostd::string_view key, + const opentelemetry::common::AttributeValue &value) +{ + // Assert size of variant to ensure that this method gets updated if the variant + // definition changes + static_assert( + nostd::variant_size::value == kAttributeValueSize, + "AttributeValue contains unknown type"); + + //attribute->set_key(key.data(), key.size()); + + if (nostd::holds_alternative(value)) + { + attribute[key.data()] = nostd::get(value); + } + else if (nostd::holds_alternative(value)) + { + attribute[key.data()] = nostd::get(value); + } + else if (nostd::holds_alternative(value)) + { + + attribute[key.data()] = nostd::get(value); + } + else if (nostd::holds_alternative(value)) + { + attribute[key.data()] = nostd::get(value); + } + else if (nostd::holds_alternative(value)) + { + attribute[key.data()] = nostd::get(value); + } + else if (nostd::holds_alternative(value)) + { + attribute[key.data()] = nostd::get(value); + } + else if (nostd::holds_alternative(value)) + { + attribute[key.data()] = nostd::string_view(nostd::get(value).data(), + nostd::get(value).size()); + } + else if (nostd::holds_alternative>(value)) + { + attribute[key.data()] = {}; + for (const auto &val : nostd::get>(value)) + { + attribute[key.data()].push_back(val); + } + } + else if (nostd::holds_alternative>(value)) + { + attribute[key.data()] = {}; + for (const auto &val : nostd::get>(value)) + { + attribute[key.data()].push_back(val); + } + } + else if (nostd::holds_alternative>(value)) + { + attribute[key.data()] = {}; + for (const auto &val : nostd::get>(value)) + { + attribute[key.data()].push_back(val); + } + } + else if (nostd::holds_alternative>(value)) + { + attribute[key.data()] = {}; + for (const auto &val : nostd::get>(value)) + { + attribute[key.data()].push_back(val); + } + } + else if (nostd::holds_alternative>(value)) + { + attribute[key.data()] = {}; + for (const auto &val : nostd::get>(value)) + { + attribute[key.data()].push_back(val); + } + } + else if (nostd::holds_alternative>(value)) + { + attribute[key.data()] = {}; + for (const auto &val : nostd::get>(value)) + { + attribute[key.data()].push_back(val); + } + } + else if (nostd::holds_alternative>(value)) + { + attribute[key.data()] = {}; + for (const auto &val : nostd::get>(value)) + { + attribute[key.data()].push_back(std::string(val.data(), val.size())); + } + } +} + +void Recordable::SetAttribute(nostd::string_view key, + const opentelemetry::common::AttributeValue &value) noexcept +{ + if (! span_.contains("tags")) { + span_["tags"] = nlohmann::json::object(); + } + PopulateAttribute(span_["tags"], key, value); +} + +void Recordable::AddEvent(nostd::string_view name, + core::SystemTimestamp timestamp, + const common::KeyValueIterable &attributes) noexcept +{ + nlohmann::json annotations = nlohmann::json::object(); // empty object + attributes.ForEachKeyValue([&](nostd::string_view key, common::AttributeValue value) noexcept { + PopulateAttribute(annotations, key, value); + return true; + }); + span_["annotations"][name.data()]["value"] = annotations; + span_["annotations"]["timestamp"] = std::chrono::duration_cast(timestamp.time_since_epoch()).count(); +} + +void Recordable::AddLink(const opentelemetry::trace::SpanContext &span_context, + const common::KeyValueIterable &attributes) noexcept +{ + // TODO: Populate once supported + // https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/sdk_exporters/zipkin.md +} + +void Recordable::SetStatus(trace::CanonicalCode code, nostd::string_view description) noexcept +{ + span_["tags"]["otel.status_code"] = code; + if ( description.size()) + span_["tags"]["otel.status_description"] = description; +} + +void Recordable::SetName(nostd::string_view name) noexcept +{ + span_["name"] = name.data(); + //span_.set_name(name.data(), name.size()); +} + +void Recordable::SetStartTime(opentelemetry::core::SystemTimestamp start_time) noexcept +{ + span_["timestamp"] = start_time.time_since_epoch().count(); + // span_.set_start_time_unix_nano(start_time.time_since_epoch().count()); +} + +void Recordable::SetDuration(std::chrono::nanoseconds duration) noexcept +{ + span_["duration"] = duration.count(); + /*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/zipkin/src/zipkin_exporter.cc b/exporters/zipkin/src/zipkin_exporter.cc new file mode 100644 index 0000000000..8d949249fd --- /dev/null +++ b/exporters/zipkin/src/zipkin_exporter.cc @@ -0,0 +1,109 @@ +#include "opentelemetry/exporters/zipkin/zipkin_exporter.h" +#include "opentelemetry/exporters/zipkin/recordable.h" +#include "opentelemetry/ext/http/client/http_client_factory.h" +#include "opentelemetry/ext/http/common/url_parser.h" +#include + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace exporter +{ +namespace zipkin +{ + +// -------------------------------- Contructors -------------------------------- + +ZipkinExporter::ZipkinExporter(const ZipkinExporterOptions &options) + : options_(options), url_parser_(options_.endpoint) +{ + http_session_manager_ = ext::http::client::HttpClientFactory::Create(); + InitializeLocalEndpoint(); + +} + +ZipkinExporter::ZipkinExporter() + : options_(ZipkinExporterOptions()), + url_parser_(options_.endpoint) +{ + http_session_manager_ = ext::http::client::HttpClientFactory::Create(); + std::cout<< "URL: "<< options_.endpoint << " " << url_parser_.host_ << " " << url_parser_.port_ << "\n"; + InitializeLocalEndpoint(); +} + +// ----------------------------- Exporter methods ------------------------------ + +std::unique_ptr ZipkinExporter::MakeRecordable() noexcept +{ + return std::unique_ptr(new Recordable); +} + +sdk::trace::ExportResult ZipkinExporter::Export( + const nostd::span> &spans) noexcept +{ + if (isShutdown_) + { + return sdk::trace::ExportResult::kFailure; + } + auto session = http_session_manager_->CreateSession(url_parser_.host_, url_parser_.port_); + auto request = session->CreateRequest(); + request->SetUri(url_parser_.path_); + exporter::zipkin::ZipkinSpan json_spans = {}; + for (auto &recordable : spans) + { + auto rec = std::unique_ptr(static_cast(recordable.release())); + if (rec != nullptr) + { + auto json_span = rec->span(); + // add localEndPoint + json_span["localEndpoint"] = local_end_point_; + json_spans.push_back(json_span); + } + } + auto body_s = json_spans.dump(); + std::cout << "FINAL JSON:" << body_s << "\n"; + http_client::Body body_v(body_s.begin(), body_s.end()); + request->SetMethod(opentelemetry::ext::http::client::Method::Post); + request->SetBody(body_v); + request->AddHeader("Content-Type", "application/json"); + http_client::SessionState session_state; + auto response = session->SendRequestSync(session_state); + if (response){ + + std::cout << "Response Code." << response->GetStatusCode() << "\n"; + auto body = response->GetBody(); + std::cout << "\nBody:" ; + for (auto &c : body) + { + std::cout << static_cast(c) ; + } + std::cout << "\n"; + } + if (response && ( response->GetStatusCode() == 200 || response->GetStatusCode() == 202)) + { + std::cout << " SUCCESS\n"; + return sdk::trace::ExportResult::kSuccess; + } + else { + std::cout << " FAILURE\n"; + if (session_state == http_client::SessionState::ConnectFailed) { std::cout << "Connect failed\n";} + //TBD -> Handle error / retries + return sdk::trace::ExportResult::kFailure; + } +} + +void ZipkinExporter::InitializeLocalEndpoint() +{ + if (options_.service_name.length()) { + local_end_point_["serviceName"] = options_.service_name; + } + if (options_.ipv4.length()) { + local_end_point_["ipv4"] = options_.ipv4; + } + if (options_.ipv6.length()) { + local_end_point_["ipv6"] = options_.ipv6; + } + local_end_point_["port"] = url_parser_.port_; +} + +} +} +OPENTELEMETRY_END_NAMESPACE \ No newline at end of file diff --git a/exporters/zipkin/test/zipkin_recordable_test.cc b/exporters/zipkin/test/zipkin_recordable_test.cc new file mode 100644 index 0000000000..768625830d --- /dev/null +++ b/exporters/zipkin/test/zipkin_recordable_test.cc @@ -0,0 +1,216 @@ +#include "opentelemetry/sdk/trace/recordable.h" +#include "opentelemetry/sdk/trace/simple_processor.h" +#include "opentelemetry/sdk/trace/span_data.h" +#include "opentelemetry/sdk/trace/tracer_provider.h" +#include "opentelemetry/trace/provider.h" + +#include "opentelemetry/sdk/trace/exporter.h" + +#include "opentelemetry/exporters/zipkin/recordable.h" +#include "opentelemetry/core/timestamp.h" + +#include + +#include + +namespace trace = opentelemetry::trace; +namespace nostd = opentelemetry::nostd; +namespace sdktrace = opentelemetry::sdk::trace; +using json = nlohmann::json; + +// Testing Shutdown functionality of OStreamSpanExporter, should expect no data to be sent to Stream +TEST(ZipkinSpanRecordable, SetIds) +{ + json j_span = {{"id","0000000000000002"}, {"parentId", "0000000000000003"}, {"traceId", "00000000000000000000000000000001"}}; + opentelemetry::exporter::zipkin::Recordable rec; + 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})); + + rec.SetIds(trace_id, span_id, parent_span_id); + EXPECT_EQ(rec.span(), j_span); +} + +TEST(Recordable, SetName) +{ + nostd::string_view name = "Test Span"; + json j_span = {{"name", name}}; + opentelemetry::exporter::zipkin::Recordable rec; + rec.SetName(name); + EXPECT_EQ(rec.span(), j_span); +} + +TEST(Recordable, SetStartTime) +{ + opentelemetry::exporter::zipkin::Recordable rec; + std::chrono::system_clock::time_point start_time = std::chrono::system_clock::now(); + opentelemetry::core::SystemTimestamp start_timestamp(start_time); + + uint64_t unix_start = + std::chrono::duration_cast(start_time.time_since_epoch()).count(); + json j_span = {{"timestamp",unix_start}}; + rec.SetStartTime(start_timestamp); + EXPECT_EQ(rec.span(), j_span); +} + +TEST(Recordable, SetDuration) +{ + json j_span = {{"duration",10},{"timestamp",0}}; + opentelemetry::exporter::zipkin::Recordable rec; + // Start time is 0 + opentelemetry::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(), j_span); +} + +TEST(Recordable, SetStatus) +{ + opentelemetry::exporter::zipkin::Recordable rec; + trace::CanonicalCode code(trace::CanonicalCode::OK); + nostd::string_view description = "For test"; + json j_span = {{"tags",{{"otel.status_code",code},{"otel.status_description",description}}}}; + rec.SetStatus(code, description); + EXPECT_EQ(rec.span(), j_span); +} + +TEST(Recordable, AddEventDefault) +{ + opentelemetry::exporter::zipkin::Recordable rec; + nostd::string_view name = "Test Event"; + + std::chrono::system_clock::time_point event_time = std::chrono::system_clock::now(); + opentelemetry::core::SystemTimestamp event_timestamp(event_time); + + rec.opentelemetry::sdk::trace::Recordable::AddEvent(name, event_timestamp); + + uint64_t unix_event_time = + std::chrono::duration_cast(event_time.time_since_epoch()).count(); + + json j_span = {{"annotations", {{name, {{"value",nlohmann::json::object()}}},{"timestamp",unix_event_time}}}}; + EXPECT_EQ(rec.span(), j_span); +} + +TEST(Recordable, AddEventWithAttributes) +{ + opentelemetry::exporter::zipkin::Recordable rec; + nostd::string_view name = "Test Event"; + + std::chrono::system_clock::time_point event_time = std::chrono::system_clock::now(); + opentelemetry::core::SystemTimestamp event_timestamp(event_time); + uint64_t unix_event_time = + std::chrono::duration_cast(event_time.time_since_epoch()).count(); + + const int kNumAttributes = 3; + std::string keys[kNumAttributes] = {"attr1", "attr2", "attr3"}; + int values[kNumAttributes] = {4, 7, 23}; + std::map attributes = { + {keys[0], values[0]}, {keys[1], values[1]}, {keys[2], values[2]}}; + + rec.AddEvent("Test Event", event_timestamp, + opentelemetry::common::KeyValueIterableView>(attributes)); + + nlohmann::json j_span = {{"annotations",{{"Test Event",{{"value", {{"attr1", 4}, {"attr2", 7}, {"attr3", 23}}}}},{"timestamp", unix_event_time}}}}; + EXPECT_EQ(rec.span(), j_span); + +} + +// Test non-int single types. Int single types are tested using templates (see IntAttributeTest) +TEST(Recordable, SetSingleAtrribute) +{ + opentelemetry::exporter::zipkin::Recordable rec; + nostd::string_view bool_key = "bool_attr"; + opentelemetry::common::AttributeValue bool_val(true); + rec.SetAttribute(bool_key, bool_val); + + nostd::string_view double_key = "double_attr"; + opentelemetry::common::AttributeValue double_val(3.3); + rec.SetAttribute(double_key, double_val); + + nostd::string_view str_key = "str_attr"; + opentelemetry::common::AttributeValue str_val(nostd::string_view("Test")); + rec.SetAttribute(str_key, str_val); + nlohmann::json j_span = {{"tags", {{"bool_attr",true},{"double_attr",3.3},{"str_attr","Test"}}}}; + + EXPECT_EQ(rec.span(), j_span); +} + +// Test non-int array types. Int array types are tested using templates (see IntAttributeTest) +TEST(Recordable, SetArrayAtrribute) +{ + opentelemetry::exporter::zipkin::Recordable rec; + nlohmann::json j_span = + {{"tags", + { + {"bool_arr_attr", {true, false, true}}, + {"double_arr_attr", {22.3, 33.4, 44.5}}, + {"str_arr_attr", {"Hello", "World", "Test"}} + } + }}; + const int kArraySize = 3; + + bool bool_arr[kArraySize] = {true, false, true}; + nostd::span bool_span(bool_arr); + rec.SetAttribute("bool_arr_attr", bool_span); + + double double_arr[kArraySize] = {22.3, 33.4, 44.5}; + nostd::span double_span(double_arr); + rec.SetAttribute("double_arr_attr", double_span); + + nostd::string_view str_arr[kArraySize] = {"Hello", "World", "Test"}; + nostd::span str_span(str_arr); + rec.SetAttribute("str_arr_attr", str_span); + + EXPECT_EQ(rec.span(), j_span); +} + +/** + * AttributeValue can contain different int types, such as int, int64_t, + * unsigned int, and uint64_t. To avoid writing test cases for each, we can + * use a template approach to test all int types. + */ +template +struct IntAttributeTest : public testing::Test +{ + using IntParamType = T; +}; + +using IntTypes = testing::Types; +TYPED_TEST_CASE(IntAttributeTest, IntTypes); + +TYPED_TEST(IntAttributeTest, SetIntSingleAttribute) +{ + using IntType = typename TestFixture::IntParamType; + IntType i = 2; + opentelemetry::common::AttributeValue int_val(i); + + opentelemetry::exporter::zipkin::Recordable rec; + rec.SetAttribute("int_attr", int_val); + nlohmann::json j_span = {{"tags", {{"int_attr", 2}}}}; + EXPECT_EQ(rec.span(), j_span); +} + +TYPED_TEST(IntAttributeTest, SetIntArrayAttribute) +{ + using IntType = typename TestFixture::IntParamType; + + const int kArraySize = 3; + IntType int_arr[kArraySize] = {4, 5, 6}; + nostd::span int_span(int_arr); + + opentelemetry::exporter::zipkin::Recordable rec; + rec.SetAttribute("int_arr_attr", int_span); + nlohmann::json j_span = {{"tags", {{"int_arr_attr", {4, 5, 6}}}}}; + EXPECT_EQ(rec.span(), j_span); +} + + 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 0605edc9fc..5d12d4e9d7 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 @@ -131,7 +131,7 @@ class Session : public http_client::Session is_session_active_ = true; std::string url = host_ + std::string(http_request_->uri_); auto callback_ptr = &callback; - curl_operation_.reset(new HttpOperation(http_request_->method_, url, callback_ptr, + curl_operation_.reset(new HttpOperation(http_request_->method_, url, callback_ptr, RequestMode::Sync, http_request_->headers_, http_request_->body_, false, http_request_->timeout_ms_)); curl_operation_->SendAsync([this, callback_ptr](HttpOperation &operation) { @@ -153,6 +153,33 @@ class Session : public http_client::Session }); } + virtual std::unique_ptr SendRequestSync( + http_client::SessionState &session_state) noexcept override + { + is_session_active_ = true; + std::string url = host_ + std::string(http_request_->uri_); + curl_operation_.reset(new HttpOperation(http_request_->method_, url, nullptr, RequestMode::Sync, + http_request_->headers_, http_request_->body_, false, + http_request_->timeout_ms_)); + curl_operation_->SendSync(); + session_state = curl_operation_->GetSessionState(); + if (curl_operation_->WasAborted()) + { + session_state = http_client::SessionState::Cancelled; + } + if (curl_operation_->GetResponseCode() >= CURL_LAST) + { + // we have a http response + auto response = std::unique_ptr(new Response()); + response->headers_ = curl_operation_->GetResponseHeaders(); + response->body_ = curl_operation_->GetResponseBody(); + is_session_active_ = false; + return std::move(response); + } + is_session_active_ = false; + return nullptr; + } + virtual bool CancelSession() noexcept override { curl_operation_->Abort(); diff --git a/ext/include/opentelemetry/ext/http/client/curl/http_operation_curl.h b/ext/include/opentelemetry/ext/http/client/curl/http_operation_curl.h index 1c11f6a9e2..86de597a6e 100644 --- a/ext/include/opentelemetry/ext/http/client/curl/http_operation_curl.h +++ b/ext/include/opentelemetry/ext/http/client/curl/http_operation_curl.h @@ -29,6 +29,12 @@ const std::chrono::milliseconds default_http_conn_timeout(5000); // ms const std::string http_status_regexp = "HTTP\\/\\d\\.\\d (\\d+)\\ .*"; const std::string http_header_regexp = "(.*)\\: (.*)\\n*"; +enum class RequestMode +{ + Sync, + Async +}; + struct curl_ci { bool operator()(const std::string &s1, const std::string &s2) const @@ -45,10 +51,14 @@ class HttpOperation public: void DispatchEvent(http_client::SessionState type, std::string reason = "") { - if (callback_ != nullptr) + if (request_mode_ == RequestMode::Async && callback_ != nullptr) { callback_->OnEvent(type, reason); } + else + { + session_state_ = type; + } } std::atomic is_aborted_; // Set to 'true' when async callback is aborted @@ -56,9 +66,10 @@ class HttpOperation /** * Create local CURL instance for url and body - * - * @param url + * @param method // HTTP Method + * @param url * @param callback + * @param request_mode // sync or async * @param request Request Headers * @param body Reques Body * @param raw_response whether to parse the response @@ -67,6 +78,7 @@ class HttpOperation HttpOperation(http_client::Method method, std::string url, http_client::EventHandler *callback, + RequestMode request_mode = RequestMode::Async, // Default empty headers and empty request body const Headers &request_headers = Headers(), const http_client::Body &request_body = http_client::Body(), @@ -77,7 +89,7 @@ class HttpOperation method_(method), url_(url), callback_(callback), - + request_mode_(request_mode), // Local vars request_headers_(request_headers), request_body_(request_body), @@ -179,6 +191,7 @@ class HttpOperation // Perform initial connect, handling the timeout if needed curl_easy_setopt(curl_, CURLOPT_CONNECT_ONLY, 1L); + curl_easy_setopt(curl_, CURLOPT_TIMEOUT, http_conn_timeout_.count() / 1000); DispatchEvent(http_client::SessionState::Connecting); res_ = curl_easy_perform(curl_); @@ -298,11 +311,18 @@ class HttpOperation return result_; } + void SendSync() { Send(); } + /** * Get HTTP response code. This function returns CURL error code if HTTP response code is invalid. */ long GetResponseCode() { return res_; } + /** + * Get last session state. + */ + http_client::SessionState GetSessionState() { return session_state_; } + /** * Get whether or not response was programmatically aborted */ @@ -393,6 +413,7 @@ class HttpOperation protected: const bool is_raw_response_; // Do not split response headers from response body const std::chrono::milliseconds http_conn_timeout_; // Timeout for connect. Default: 5000ms + RequestMode request_mode_; CURL *curl_; // Local curl instance CURLcode res_; // Curl result OR HTTP status code if successful @@ -405,6 +426,7 @@ class HttpOperation const Headers &request_headers_; const http_client::Body &request_body_; struct curl_slist *headers_chunk_ = nullptr; + http_client::SessionState session_state_; // Processed response headers and body std::vector resp_headers_; diff --git a/ext/include/opentelemetry/ext/http/client/http_client.h b/ext/include/opentelemetry/ext/http/client/http_client.h index a6f1c3e924..de7bdb195f 100644 --- a/ext/include/opentelemetry/ext/http/client/http_client.h +++ b/ext/include/opentelemetry/ext/http/client/http_client.h @@ -10,6 +10,8 @@ /* Usage Example +Async Request: + struct SimpleReponseHandler: public ResponseHandler { void OnResponse(Response& res) noexcept override { @@ -37,6 +39,17 @@ session->FinishSession() // optionally in the end ...shutdown sessionManager.FinishAllSessions() + +Sync Request: + + SessionMamager sessionManager; + auto session = sessionManager.createSession("localhost", 8000); + auto request = session->CreateRequest(); + request->AddHeader(..); + SessionState session_state; + auto response = session->SendRequestSync(session_state); + // session_state will contain SessionState::Response if successful. + */ OPENTELEMETRY_BEGIN_NAMESPACE @@ -138,6 +151,9 @@ class Session virtual void SendRequest(EventHandler &) noexcept = 0; + virtual std::unique_ptr SendRequestSync(SessionState &) noexcept = 0; + + virtual bool IsSessionActive() noexcept = 0; virtual bool CancelSession() noexcept = 0; diff --git a/ext/include/opentelemetry/ext/http/client/http_client_factory.h b/ext/include/opentelemetry/ext/http/client/http_client_factory.h new file mode 100644 index 0000000000..95481199dc --- /dev/null +++ b/ext/include/opentelemetry/ext/http/client/http_client_factory.h @@ -0,0 +1,27 @@ +#pragma once +#include "opentelemetry/ext/http/client/http_client.h" +#ifdef WITH_CURL +# include "opentelemetry/ext/http/client/curl/http_client_curl.h" +#endif + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace ext +{ +namespace http +{ +namespace client +{ +class HttpClientFactory +{ +public: +#ifdef WITH_CURL + static std::shared_ptr Create() + { + return std::make_shared(); + } +#endif +}; +} // namespace client +} // namespace http +} // namespace ext +OPENTELEMETRY_END_NAMESPACE \ No newline at end of file diff --git a/ext/include/opentelemetry/ext/http/common/url_parser.h b/ext/include/opentelemetry/ext/http/common/url_parser.h new file mode 100644 index 0000000000..e2ad4eb556 --- /dev/null +++ b/ext/include/opentelemetry/ext/http/common/url_parser.h @@ -0,0 +1,108 @@ +#pragma once + +#include +#include +#include "opentelemetry/nostd/string_view.h" +#include "opentelemetry/version.h" +OPENTELEMETRY_BEGIN_NAMESPACE +namespace ext +{ +namespace http +{ +namespace common +{ +// http://user:password@host:port/path1/path2?key1=val2&key2=val2 +// http://host:port/path1/path2?key1=val1&key2=val2 +// host:port/path1 +// host:port ( path defaults to "/") +// host:port? + +class UrlParser{ + public: + std::string url_; + std::string host_; + std::string scheme_; + std::string path_; + size_t port_; + std::string query_; + bool success_; + + UrlParser(std::string url):url_(url), success_(true) + { + if (url_.length() == 0) { + return; + } + size_t cpos = 0; + //scheme + size_t pos = url_.find("://", cpos); + if (pos == std::string::npos) { + // scheme missing, use default as http + scheme_ = "http"; + } else { + scheme_ = std::string(url_.begin() + cpos, url_.begin() + pos); + cpos = pos + 3; + } + + //credentials + pos = url_.find_first_of("@", cpos); + if (pos != std::string::npos) + { + //TODO - handle credentials + cpos = pos + 1; + } + pos = url_.find_first_of(":", cpos); + bool is_port = false; + if (pos == std::string::npos){ + // port missing. Used default 80 / 443 + if (scheme_ == "http") port_ = 80; + if (scheme_ == "https") port_ = 443; + } else { + // port present + is_port = true; + host_ = std::string(url_.begin() + cpos, url_.begin() + pos ); + cpos = pos + 1; + } + pos = url_.find_first_of("/?", cpos); + if (pos == std::string::npos) + { + path_ = "/" ; // use default path + if (is_port){ + //std::cout << url_[cpos] + "-" + url_[url_.length()-1] << "\n"; + port_ = std::stoi(std::string(url_.begin() + cpos , url_.begin() + url_.length() )); + } else { + host_ = std::string(url_.begin() + cpos , url_.begin() + url_.length() ); + } + return; + } + if (is_port){ + port_ = std::stoi(std::string(url_.begin() + cpos, url_.begin() + pos )); + } else { + host_ = std::string(url_.begin() + cpos, url_.begin() + pos ); + } + cpos = pos ; + + if (url_[cpos] == '/') { + pos = url_.find('?', cpos); + if (pos == std::string::npos) { + path_ = std::string(url_.begin() + cpos, url_.begin() + url_.length()); + query_ = ""; + } + else { + path_ = std::string(url_.begin() + cpos, url_.begin() + pos ); + cpos = pos + 1; + query_ = std::string(url_.begin() + cpos, url_.begin() +url_.length() ); + } + return ; + } + path_ = "/"; + if (url_[cpos] == '?') { + query_ = std::string(url_.begin() + cpos, url_.begin() +url_.length()); + } + } +}; + +} + +} +} +OPENTELEMETRY_END_NAMESPACE \ No newline at end of file diff --git a/ext/test/http/BUILD b/ext/test/http/BUILD index 678b2e5da7..99c3c0427a 100644 --- a/ext/test/http/BUILD +++ b/ext/test/http/BUILD @@ -6,6 +6,7 @@ cc_test( # TODO: Move copts/linkopts for static CURL usage into shared bzl file. copts = [ "-DCURL_STATICLIB", + "-DWITH_CURL", ], linkopts = select({ "//bazel:windows": [ diff --git a/ext/test/http/CMakeLists.txt b/ext/test/http/CMakeLists.txt index a32c012492..a7306eff1e 100644 --- a/ext/test/http/CMakeLists.txt +++ b/ext/test/http/CMakeLists.txt @@ -2,12 +2,17 @@ find_package(CURL) if(CURL_FOUND) set(CURL_LIBRARY "-lcurl") set(FILENAME curl_http_test) + add_compile_definitions(WITH_CURL) + add_executable(${FILENAME} ${FILENAME}.cc) include_directories(${CURL_INCLUDE_DIR}) target_link_libraries(${FILENAME} ${GTEST_BOTH_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${CURL_LIBRARIES}) - gtest_add_tests( - TARGET ${FILENAME} - TEST_PREFIX ext.http.curl. - TEST_LIST ${FILENAME}) + gtest_add_tests(TARGET ${FILENAME} TEST_PREFIX ext.http.curl. TEST_LIST + ${FILENAME}) endif() +set(URL_PARSER_FILENAME url_parser_test) +add_executable(${URL_PARSER_FILENAME} ${URL_PARSER_FILENAME}.cc) +target_link_libraries(${URL_PARSER_FILENAME} ${GTEST_BOTH_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) +gtest_add_tests(TARGET ${URL_PARSER_FILENAME} TEST_PREFIX ext.http.urlparser. TEST_LIST + ${URL_PARSER_FILENAME}) \ No newline at end of file diff --git a/ext/test/http/curl_http_test.cc b/ext/test/http/curl_http_test.cc index 70ec4b414e..21984a5c5e 100644 --- a/ext/test/http/curl_http_test.cc +++ b/ext/test/http/curl_http_test.cc @@ -1,4 +1,5 @@ #include "opentelemetry/ext//http/client/curl//http_client_curl.h" +#include "opentelemetry/ext/http/client/http_client_factory.h" #include "opentelemetry/ext/http/server/http_server.h" #include @@ -183,9 +184,10 @@ TEST_F(BasicCurlHttpTests, HttpResponse) TEST_F(BasicCurlHttpTests, SendGetRequest) { received_requests_.clear(); - curl::SessionManager session_manager; + auto session_manager = http_client::HttpClientFactory::Create(); + EXPECT_TRUE(session_manager != nullptr); - auto session = session_manager.CreateSession("127.0.0.1", HTTP_PORT); + auto session = session_manager->CreateSession("127.0.0.1", HTTP_PORT); auto request = session->CreateRequest(); request->SetUri("get/"); GetEventHandler *handler = new GetEventHandler(); @@ -199,9 +201,10 @@ TEST_F(BasicCurlHttpTests, SendGetRequest) TEST_F(BasicCurlHttpTests, SendPostRequest) { received_requests_.clear(); - curl::SessionManager session_manager; + auto session_manager = http_client::HttpClientFactory::Create(); + EXPECT_TRUE(session_manager != nullptr); - auto session = session_manager.CreateSession("127.0.0.1", HTTP_PORT); + auto session = session_manager->CreateSession("127.0.0.1", HTTP_PORT); auto request = session->CreateRequest(); request->SetUri("post/"); request->SetMethod(http_client::Method::Post); @@ -216,8 +219,8 @@ TEST_F(BasicCurlHttpTests, SendPostRequest) session->FinishSession(); ASSERT_TRUE(handler->is_called_); - session_manager.CancelAllSessions(); - session_manager.FinishAllSessions(); + session_manager->CancelAllSessions(); + session_manager->FinishAllSessions(); delete handler; } @@ -225,10 +228,11 @@ TEST_F(BasicCurlHttpTests, SendPostRequest) TEST_F(BasicCurlHttpTests, RequestTimeout) { received_requests_.clear(); - curl::SessionManager session_manager; + auto session_manager = http_client::HttpClientFactory::Create(); + EXPECT_TRUE(session_manager != nullptr); auto session = - session_manager.CreateSession("222.222.222.200", HTTP_PORT); // Non Existing address + session_manager->CreateSession("222.222.222.200", HTTP_PORT); // Non Existing address auto request = session->CreateRequest(); request->SetUri("get/"); GetEventHandler *handler = new GetEventHandler(); @@ -248,16 +252,46 @@ TEST_F(BasicCurlHttpTests, CurlHttpOperations) std::multimap m1 = { {"name1", "value1_1"}, {"name1", "value1_2"}, {"name2", "value3"}, {"name3", "value3"}}; curl::Headers headers = m1; - curl::HttpOperation http_operations1(http_client::Method::Head, "/get", handler, headers, body, + curl::HttpOperation http_operations1(http_client::Method::Head, "/get", handler, curl::RequestMode::Async, headers, body, true); http_operations1.Send(); - curl::HttpOperation http_operations2(http_client::Method::Get, "/get", handler, headers, body, + curl::HttpOperation http_operations2(http_client::Method::Get, "/get", handler, curl::RequestMode::Async, headers, body, true); http_operations2.Send(); - curl::HttpOperation http_operations3(http_client::Method::Get, "/get", handler, headers, body, + curl::HttpOperation http_operations3(http_client::Method::Get, "/get", handler, curl::RequestMode::Async, headers, body, false); http_operations3.Send(); delete handler; } + +TEST_F(BasicCurlHttpTests, SendGetRequestSync) +{ + received_requests_.clear(); + curl::SessionManager session_manager; + + auto session = session_manager.CreateSession("127.0.0.1", HTTP_PORT); + auto request = session->CreateRequest(); + request->SetUri("get/"); + http_client::SessionState session_state; + auto response = session->SendRequestSync(session_state); + EXPECT_EQ(response->GetStatusCode(), 200); + EXPECT_EQ(session_state, http_client::SessionState::Response); +} + +TEST_F(BasicCurlHttpTests, SendGetRequestSyncTimeout) +{ + received_requests_.clear(); + curl::SessionManager session_manager; + + auto session = + session_manager.CreateSession("222.222.222.200", HTTP_PORT); // Non Existing address + auto request = session->CreateRequest(); + request->SetTimeoutMs(std::chrono::milliseconds(3000)); + request->SetUri("get/"); + http_client::SessionState session_state; + auto response = session->SendRequestSync(session_state); + EXPECT_EQ(session_state, http_client::SessionState::ConnectFailed); + EXPECT_TRUE(response == nullptr); +} diff --git a/ext/test/http/url_parser_test.cc b/ext/test/http/url_parser_test.cc new file mode 100644 index 0000000000..4f8cc7c1a4 --- /dev/null +++ b/ext/test/http/url_parser_test.cc @@ -0,0 +1,70 @@ +#include "opentelemetry/ext/http/common/url_parser.h" + +#include + +namespace http_common = opentelemetry::ext::http::common; + +inline const char * const BoolToString(bool b) +{ + return b ? "true" : "false"; +} + +TEST(UrlParserTests, BasicTests) +{ + std::map> urls_map + { + { + "www.abc.com" , { { "host", "www.abc.com"}, {"port", "80"}, {"scheme", "http"}, {"path", "/"}, {"query",""}, {"success","true"}} + }, + { + "http://www.abc.com" , { { "host", "www.abc.com"}, {"port", "80"}, {"scheme", "http"}, {"path", "/"}, {"query",""},{"success","true"}} + }, + { + "https://www.abc.com" , { { "host", "www.abc.com"}, {"port", "443"}, {"scheme", "https"}, {"path", "/"}, {"query",""}, {"success","true"}} + }, + { + "https://www.abc.com:4431" , { { "host", "www.abc.com"}, {"port", "4431"}, {"scheme", "https"}, {"path", "/"}, {"query",""}, {"success","true"}} + }, + { + "https://www.abc.com:4431" , { { "host", "www.abc.com"}, {"port", "4431"}, {"scheme", "https"}, {"path", "/"}, {"query",""}, {"success","true"}} + }, + { + "https://www.abc.com:4431/path1" , { { "host", "www.abc.com"}, {"port", "4431"}, {"scheme", "https"}, {"path", "/path1"}, {"query",""}, {"success","true"}} + }, + { + "https://www.abc.com:4431/path1/path2" , { { "host", "www.abc.com"}, {"port", "4431"}, {"scheme", "https"}, {"path", "/path1/path2"}, {"query",""}, {"success","true"}} + }, + { + "https://www.abc.com/path1/path2" , { { "host", "www.abc.com"}, {"port", "443"}, {"scheme", "https"}, {"path", "/path1/path2"}, {"query",""}, {"success","true"}} + }, + { + "http://www.abc.com/path1/path2?q1=a1&q2=a2" , { { "host", "www.abc.com"}, {"port", "80"}, {"scheme", "http"}, {"path", "/path1/path2"}, {"query","q1=a1&q2=a2"}, {"success","true"}} + }, + { + "http://www.abc.com:8080/path1/path2?q1=a1&q2=a2" , { { "host", "www.abc.com"}, {"port", "8080"}, {"scheme", "http"}, {"path", "/path1/path2"}, {"query","q1=a1&q2=a2"}, {"success","true"}} + }, + { + "www.abc.com:8080/path1/path2?q1=a1&q2=a2" , { { "host", "www.abc.com"}, {"port", "8080"}, {"scheme", "http"}, {"path", "/path1/path2"}, {"query","q1=a1&q2=a2"},{"success","true"} } + }, + { + "http://user:password@www.abc.com:8080/path1/path2?q1=a1&q2=a2" , { { "host", "www.abc.com"}, {"port", "8080"}, {"scheme", "http"}, {"path", "/path1/path2"}, {"query","q1=a1&q2=a2"}, {"success","true"}} + }, + { + "user:password@www.abc.com:8080/path1/path2?q1=a1&q2=a2" , { { "host", "www.abc.com"}, {"port", "8080"}, {"scheme", "http"}, {"path", "/path1/path2"}, {"query","q1=a1&q2=a2"}, {"success","true"}} + }, + { + "https://user@www.abc.com/path1/path2?q1=a1&q2=a2" , { { "host", "www.abc.com"}, {"port", "443"}, {"scheme", "https"}, {"path", "/path1/path2"}, {"query","q1=a1&q2=a2"}, {"success","true"}} + }, + + }; + for (auto &url_map : urls_map) { + http_common::UrlParser url(url_map.first); + auto url_properties = url_map.second; + ASSERT_EQ(BoolToString(url.success_), url_properties["success"]); + ASSERT_EQ(url.host_, url_properties["host"]); + ASSERT_EQ(std::to_string(url.port_), url_properties["port"]); + ASSERT_EQ(url.scheme_, url_properties["scheme"]); + ASSERT_EQ(url.path_, url_properties["path"]); + ASSERT_EQ(url.query_, url_properties["query"]); + } +} From a532b72a4291f572040bda96ed0d1f9e9088b4aa Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Fri, 18 Dec 2020 16:00:22 +0530 Subject: [PATCH 02/33] reformat --- exporters/CMakeLists.txt | 2 +- .../exporters/zipkin/recordable.h | 10 +- .../exporters/zipkin/zipkin_exporter.h | 26 +-- exporters/zipkin/src/recordable.cc | 40 ++-- exporters/zipkin/src/zipkin_exporter.cc | 64 +++--- .../zipkin/test/zipkin_recordable_test.cc | 70 +++---- .../ext/http/client/curl/http_client_curl.h | 6 +- .../http/client/curl/http_operation_curl.h | 4 +- .../ext/http/client/http_client.h | 1 - .../ext/http/common/url_parser.h | 184 ++++++++++-------- ext/test/http/CMakeLists.txt | 7 +- ext/test/http/curl_http_test.cc | 12 +- ext/test/http/url_parser_test.cc | 168 ++++++++++------ 13 files changed, 341 insertions(+), 253 deletions(-) diff --git a/exporters/CMakeLists.txt b/exporters/CMakeLists.txt index e9458829bb..456f549573 100644 --- a/exporters/CMakeLists.txt +++ b/exporters/CMakeLists.txt @@ -9,6 +9,6 @@ if(WITH_PROMETHEUS) add_subdirectory(prometheus) endif() -if (WITH_ZIPKIN) +if(WITH_ZIPKIN) add_subdirectory(zipkin) endif() diff --git a/exporters/zipkin/include/opentelemetry/exporters/zipkin/recordable.h b/exporters/zipkin/include/opentelemetry/exporters/zipkin/recordable.h index 6b195b2d21..a340759c6e 100644 --- a/exporters/zipkin/include/opentelemetry/exporters/zipkin/recordable.h +++ b/exporters/zipkin/include/opentelemetry/exporters/zipkin/recordable.h @@ -1,8 +1,8 @@ #pragma once +#include "nlohmann/json.hpp" #include "opentelemetry/sdk/trace/recordable.h" #include "opentelemetry/version.h" -#include "nlohmann/json.hpp" OPENTELEMETRY_BEGIN_NAMESPACE namespace exporter @@ -11,9 +11,10 @@ namespace zipkin { using ZipkinSpan = nlohmann::json; -enum class TransportFormat { - JSON, - PROTOBUF +enum class TransportFormat +{ + JSON, + PROTOBUF }; class Recordable final : public sdk::trace::Recordable @@ -44,7 +45,6 @@ class Recordable final : public sdk::trace::Recordable void SetDuration(std::chrono::nanoseconds duration) noexcept override; private: - ZipkinSpan span_; }; } // namespace zipkin diff --git a/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h b/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h index 789c069101..e4db446c24 100644 --- a/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h +++ b/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h @@ -1,10 +1,10 @@ #pragma once -#include "opentelemetry/sdk/trace/exporter.h" -#include "opentelemetry/sdk/trace/span_data.h" #include "opentelemetry/exporters/zipkin/recordable.h" #include "opentelemetry/ext/http/client/http_client_factory.h" #include "opentelemetry/ext/http/common/url_parser.h" +#include "opentelemetry/sdk/trace/exporter.h" +#include "opentelemetry/sdk/trace/span_data.h" #include "nlohmann/json.hpp" @@ -20,14 +20,14 @@ namespace zipkin struct ZipkinExporterOptions { // The endpoint to export to. By default the OpenTelemetry Collector's default endpoint. - std::string endpoint = "http:://localhost:9411/api/v2/spans"; - TransportFormat format = TransportFormat::JSON; + std::string endpoint = "http:://localhost:9411/api/v2/spans"; + TransportFormat format = TransportFormat::JSON; std::string service_name = "default-service"; std::string ipv4; std::string ipv6; }; -namespace trace_sdk = opentelemetry::sdk::trace; +namespace trace_sdk = opentelemetry::sdk::trace; namespace http_client = opentelemetry::ext::http::client; /** @@ -66,15 +66,19 @@ class ZipkinExporter final : public trace_sdk::SpanExporter, public http_client: */ void Shutdown( std::chrono::microseconds timeout = std::chrono::microseconds(0)) noexcept override{}; - - void OnResponse(http_client::Response &response) noexcept override {/*Not required */} - - virtual void OnEvent(http_client::SessionState state, nostd::string_view msg) noexcept override { /* Not required */}; - virtual void OnConnecting(const http_client::SSLCertificate &) noexcept override { /* Not required */}; + void OnResponse(http_client::Response &response) noexcept override + { /*Not required */ + } + + virtual void OnEvent(http_client::SessionState state, + nostd::string_view msg) noexcept override{/* Not required */}; + + virtual void OnConnecting(const http_client::SSLCertificate &) noexcept override{ + /* Not required */}; private: - void InitializeLocalEndpoint(); + void InitializeLocalEndpoint(); private: // The configuration options associated with this exporter. diff --git a/exporters/zipkin/src/recordable.cc b/exporters/zipkin/src/recordable.cc index 5966a8aae5..8f091222cf 100644 --- a/exporters/zipkin/src/recordable.cc +++ b/exporters/zipkin/src/recordable.cc @@ -9,24 +9,24 @@ namespace zipkin { const int kAttributeValueSize = 14; -const char *EMPTY_PARENT_SPAN= "0000000000000000"; +const char *EMPTY_PARENT_SPAN = "0000000000000000"; void Recordable::SetIds(trace::TraceId trace_id, trace::SpanId span_id, trace::SpanId parent_span_id) noexcept { - char traceid[trace::TraceId::kSize*2] = {0}; + char traceid[trace::TraceId::kSize * 2] = {0}; trace_id.ToLowerBase16(traceid); - char spanid[trace::SpanId::kSize*2] = {0}; + char spanid[trace::SpanId::kSize * 2] = {0}; span_id.ToLowerBase16(spanid); - char parentid[trace::SpanId::kSize*2] = {0}; + char parentid[trace::SpanId::kSize * 2] = {0}; parent_span_id.ToLowerBase16(parentid); - span_["id"] = std::string(spanid, 16); + span_["id"] = std::string(spanid, 16); span_["parentId"] = std::string(parentid, 16); - span_["traceId"] = std::string(traceid, 32); + span_["traceId"] = std::string(traceid, 32); } -void PopulateAttribute( nlohmann::json &attribute, +void PopulateAttribute(nlohmann::json &attribute, nostd::string_view key, const opentelemetry::common::AttributeValue &value) { @@ -36,7 +36,7 @@ void PopulateAttribute( nlohmann::json &attribute, nostd::variant_size::value == kAttributeValueSize, "AttributeValue contains unknown type"); - //attribute->set_key(key.data(), key.size()); + // attribute->set_key(key.data(), key.size()); if (nostd::holds_alternative(value)) { @@ -48,7 +48,7 @@ void PopulateAttribute( nlohmann::json &attribute, } else if (nostd::holds_alternative(value)) { - + attribute[key.data()] = nostd::get(value); } else if (nostd::holds_alternative(value)) @@ -65,8 +65,8 @@ void PopulateAttribute( nlohmann::json &attribute, } else if (nostd::holds_alternative(value)) { - attribute[key.data()] = nostd::string_view(nostd::get(value).data(), - nostd::get(value).size()); + attribute[key.data()] = nostd::string_view(nostd::get(value).data(), + nostd::get(value).size()); } else if (nostd::holds_alternative>(value)) { @@ -129,7 +129,8 @@ void PopulateAttribute( nlohmann::json &attribute, void Recordable::SetAttribute(nostd::string_view key, const opentelemetry::common::AttributeValue &value) noexcept { - if (! span_.contains("tags")) { + if (!span_.contains("tags")) + { span_["tags"] = nlohmann::json::object(); } PopulateAttribute(span_["tags"], key, value); @@ -139,39 +140,40 @@ void Recordable::AddEvent(nostd::string_view name, core::SystemTimestamp timestamp, const common::KeyValueIterable &attributes) noexcept { - nlohmann::json annotations = nlohmann::json::object(); // empty object + nlohmann::json annotations = nlohmann::json::object(); // empty object attributes.ForEachKeyValue([&](nostd::string_view key, common::AttributeValue value) noexcept { PopulateAttribute(annotations, key, value); return true; }); span_["annotations"][name.data()]["value"] = annotations; - span_["annotations"]["timestamp"] = std::chrono::duration_cast(timestamp.time_since_epoch()).count(); + span_["annotations"]["timestamp"] = + std::chrono::duration_cast(timestamp.time_since_epoch()).count(); } void Recordable::AddLink(const opentelemetry::trace::SpanContext &span_context, const common::KeyValueIterable &attributes) noexcept { - // TODO: Populate once supported + // TODO: Populate once supported // https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/sdk_exporters/zipkin.md } void Recordable::SetStatus(trace::CanonicalCode code, nostd::string_view description) noexcept { span_["tags"]["otel.status_code"] = code; - if ( description.size()) + if (description.size()) span_["tags"]["otel.status_description"] = description; } void Recordable::SetName(nostd::string_view name) noexcept { span_["name"] = name.data(); - //span_.set_name(name.data(), name.size()); + // span_.set_name(name.data(), name.size()); } void Recordable::SetStartTime(opentelemetry::core::SystemTimestamp start_time) noexcept { span_["timestamp"] = start_time.time_since_epoch().count(); - // span_.set_start_time_unix_nano(start_time.time_since_epoch().count()); + // span_.set_start_time_unix_nano(start_time.time_since_epoch().count()); } void Recordable::SetDuration(std::chrono::nanoseconds duration) noexcept @@ -180,6 +182,6 @@ 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 zipkin } // namespace exporter OPENTELEMETRY_END_NAMESPACE diff --git a/exporters/zipkin/src/zipkin_exporter.cc b/exporters/zipkin/src/zipkin_exporter.cc index 8d949249fd..34607bb7e1 100644 --- a/exporters/zipkin/src/zipkin_exporter.cc +++ b/exporters/zipkin/src/zipkin_exporter.cc @@ -1,8 +1,8 @@ #include "opentelemetry/exporters/zipkin/zipkin_exporter.h" +#include #include "opentelemetry/exporters/zipkin/recordable.h" #include "opentelemetry/ext/http/client/http_client_factory.h" #include "opentelemetry/ext/http/common/url_parser.h" -#include OPENTELEMETRY_BEGIN_NAMESPACE namespace exporter @@ -17,15 +17,13 @@ ZipkinExporter::ZipkinExporter(const ZipkinExporterOptions &options) { http_session_manager_ = ext::http::client::HttpClientFactory::Create(); InitializeLocalEndpoint(); - } -ZipkinExporter::ZipkinExporter() - : options_(ZipkinExporterOptions()), - url_parser_(options_.endpoint) -{ +ZipkinExporter::ZipkinExporter() : options_(ZipkinExporterOptions()), url_parser_(options_.endpoint) +{ http_session_manager_ = ext::http::client::HttpClientFactory::Create(); - std::cout<< "URL: "<< options_.endpoint << " " << url_parser_.host_ << " " << url_parser_.port_ << "\n"; + std::cout << "URL: " << options_.endpoint << " " << url_parser_.host_ << " " << url_parser_.port_ + << "\n"; InitializeLocalEndpoint(); } @@ -54,7 +52,7 @@ sdk::trace::ExportResult ZipkinExporter::Export( { auto json_span = rec->span(); // add localEndPoint - json_span["localEndpoint"] = local_end_point_; + json_span["localEndpoint"] = local_end_point_; json_spans.push_back(json_span); } } @@ -66,44 +64,52 @@ sdk::trace::ExportResult ZipkinExporter::Export( request->AddHeader("Content-Type", "application/json"); http_client::SessionState session_state; auto response = session->SendRequestSync(session_state); - if (response){ - + if (response) + { + std::cout << "Response Code." << response->GetStatusCode() << "\n"; auto body = response->GetBody(); - std::cout << "\nBody:" ; + std::cout << "\nBody:"; for (auto &c : body) { - std::cout << static_cast(c) ; + std::cout << static_cast(c); } std::cout << "\n"; } - if (response && ( response->GetStatusCode() == 200 || response->GetStatusCode() == 202)) + if (response && (response->GetStatusCode() == 200 || response->GetStatusCode() == 202)) { std::cout << " SUCCESS\n"; return sdk::trace::ExportResult::kSuccess; } - else { + else + { std::cout << " FAILURE\n"; - if (session_state == http_client::SessionState::ConnectFailed) { std::cout << "Connect failed\n";} - //TBD -> Handle error / retries + if (session_state == http_client::SessionState::ConnectFailed) + { + std::cout << "Connect failed\n"; + } + // TBD -> Handle error / retries return sdk::trace::ExportResult::kFailure; } } - + void ZipkinExporter::InitializeLocalEndpoint() { - if (options_.service_name.length()) { - local_end_point_["serviceName"] = options_.service_name; - } - if (options_.ipv4.length()) { - local_end_point_["ipv4"] = options_.ipv4; - } - if (options_.ipv6.length()) { - local_end_point_["ipv6"] = options_.ipv6; - } - local_end_point_["port"] = url_parser_.port_; + if (options_.service_name.length()) + { + local_end_point_["serviceName"] = options_.service_name; + } + if (options_.ipv4.length()) + { + local_end_point_["ipv4"] = options_.ipv4; + } + if (options_.ipv6.length()) + { + local_end_point_["ipv6"] = options_.ipv6; + } + local_end_point_["port"] = url_parser_.port_; } -} -} +} // namespace zipkin +} // namespace exporter OPENTELEMETRY_END_NAMESPACE \ No newline at end of file diff --git a/exporters/zipkin/test/zipkin_recordable_test.cc b/exporters/zipkin/test/zipkin_recordable_test.cc index 768625830d..09e90bf63c 100644 --- a/exporters/zipkin/test/zipkin_recordable_test.cc +++ b/exporters/zipkin/test/zipkin_recordable_test.cc @@ -6,8 +6,8 @@ #include "opentelemetry/sdk/trace/exporter.h" -#include "opentelemetry/exporters/zipkin/recordable.h" #include "opentelemetry/core/timestamp.h" +#include "opentelemetry/exporters/zipkin/recordable.h" #include @@ -16,30 +16,32 @@ namespace trace = opentelemetry::trace; namespace nostd = opentelemetry::nostd; namespace sdktrace = opentelemetry::sdk::trace; -using json = nlohmann::json; +using json = nlohmann::json; // Testing Shutdown functionality of OStreamSpanExporter, should expect no data to be sent to Stream TEST(ZipkinSpanRecordable, SetIds) { - json j_span = {{"id","0000000000000002"}, {"parentId", "0000000000000003"}, {"traceId", "00000000000000000000000000000001"}}; - opentelemetry::exporter::zipkin::Recordable rec; - 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})); - - rec.SetIds(trace_id, span_id, parent_span_id); - EXPECT_EQ(rec.span(), j_span); + json j_span = {{"id", "0000000000000002"}, + {"parentId", "0000000000000003"}, + {"traceId", "00000000000000000000000000000001"}}; + opentelemetry::exporter::zipkin::Recordable rec; + 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})); + + rec.SetIds(trace_id, span_id, parent_span_id); + EXPECT_EQ(rec.span(), j_span); } TEST(Recordable, SetName) { - nostd::string_view name = "Test Span"; - json j_span = {{"name", name}}; + nostd::string_view name = "Test Span"; + json j_span = {{"name", name}}; opentelemetry::exporter::zipkin::Recordable rec; rec.SetName(name); EXPECT_EQ(rec.span(), j_span); @@ -53,14 +55,14 @@ TEST(Recordable, SetStartTime) uint64_t unix_start = std::chrono::duration_cast(start_time.time_since_epoch()).count(); - json j_span = {{"timestamp",unix_start}}; + json j_span = {{"timestamp", unix_start}}; rec.SetStartTime(start_timestamp); EXPECT_EQ(rec.span(), j_span); } TEST(Recordable, SetDuration) { - json j_span = {{"duration",10},{"timestamp",0}}; + json j_span = {{"duration", 10}, {"timestamp", 0}}; opentelemetry::exporter::zipkin::Recordable rec; // Start time is 0 opentelemetry::core::SystemTimestamp start_timestamp; @@ -78,7 +80,7 @@ TEST(Recordable, SetStatus) opentelemetry::exporter::zipkin::Recordable rec; trace::CanonicalCode code(trace::CanonicalCode::OK); nostd::string_view description = "For test"; - json j_span = {{"tags",{{"otel.status_code",code},{"otel.status_description",description}}}}; + json j_span = {{"tags", {{"otel.status_code", code}, {"otel.status_description", description}}}}; rec.SetStatus(code, description); EXPECT_EQ(rec.span(), j_span); } @@ -96,7 +98,8 @@ TEST(Recordable, AddEventDefault) uint64_t unix_event_time = std::chrono::duration_cast(event_time.time_since_epoch()).count(); - json j_span = {{"annotations", {{name, {{"value",nlohmann::json::object()}}},{"timestamp",unix_event_time}}}}; + json j_span = {{"annotations", + {{name, {{"value", nlohmann::json::object()}}}, {"timestamp", unix_event_time}}}}; EXPECT_EQ(rec.span(), j_span); } @@ -119,9 +122,11 @@ TEST(Recordable, AddEventWithAttributes) rec.AddEvent("Test Event", event_timestamp, opentelemetry::common::KeyValueIterableView>(attributes)); - nlohmann::json j_span = {{"annotations",{{"Test Event",{{"value", {{"attr1", 4}, {"attr2", 7}, {"attr3", 23}}}}},{"timestamp", unix_event_time}}}}; + nlohmann::json j_span = { + {"annotations", + {{"Test Event", {{"value", {{"attr1", 4}, {"attr2", 7}, {"attr3", 23}}}}}, + {"timestamp", unix_event_time}}}}; EXPECT_EQ(rec.span(), j_span); - } // Test non-int single types. Int single types are tested using templates (see IntAttributeTest) @@ -139,7 +144,8 @@ TEST(Recordable, SetSingleAtrribute) nostd::string_view str_key = "str_attr"; opentelemetry::common::AttributeValue str_val(nostd::string_view("Test")); rec.SetAttribute(str_key, str_val); - nlohmann::json j_span = {{"tags", {{"bool_attr",true},{"double_attr",3.3},{"str_attr","Test"}}}}; + nlohmann::json j_span = { + {"tags", {{"bool_attr", true}, {"double_attr", 3.3}, {"str_attr", "Test"}}}}; EXPECT_EQ(rec.span(), j_span); } @@ -148,15 +154,11 @@ TEST(Recordable, SetSingleAtrribute) TEST(Recordable, SetArrayAtrribute) { opentelemetry::exporter::zipkin::Recordable rec; - nlohmann::json j_span = - {{"tags", - { - {"bool_arr_attr", {true, false, true}}, - {"double_arr_attr", {22.3, 33.4, 44.5}}, - {"str_arr_attr", {"Hello", "World", "Test"}} - } - }}; - const int kArraySize = 3; + nlohmann::json j_span = {{"tags", + {{"bool_arr_attr", {true, false, true}}, + {"double_arr_attr", {22.3, 33.4, 44.5}}, + {"str_arr_attr", {"Hello", "World", "Test"}}}}}; + const int kArraySize = 3; bool bool_arr[kArraySize] = {true, false, true}; nostd::span bool_span(bool_arr); @@ -212,5 +214,3 @@ TYPED_TEST(IntAttributeTest, SetIntArrayAttribute) nlohmann::json j_span = {{"tags", {{"int_arr_attr", {4, 5, 6}}}}}; EXPECT_EQ(rec.span(), j_span); } - - 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 5d12d4e9d7..6ab71ae4e2 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 @@ -131,9 +131,9 @@ class Session : public http_client::Session is_session_active_ = true; std::string url = host_ + std::string(http_request_->uri_); auto callback_ptr = &callback; - curl_operation_.reset(new HttpOperation(http_request_->method_, url, callback_ptr, RequestMode::Sync, - http_request_->headers_, http_request_->body_, false, - http_request_->timeout_ms_)); + curl_operation_.reset(new HttpOperation( + http_request_->method_, url, callback_ptr, RequestMode::Sync, http_request_->headers_, + http_request_->body_, false, http_request_->timeout_ms_)); curl_operation_->SendAsync([this, callback_ptr](HttpOperation &operation) { if (operation.WasAborted()) { diff --git a/ext/include/opentelemetry/ext/http/client/curl/http_operation_curl.h b/ext/include/opentelemetry/ext/http/client/curl/http_operation_curl.h index 86de597a6e..87030db8d0 100644 --- a/ext/include/opentelemetry/ext/http/client/curl/http_operation_curl.h +++ b/ext/include/opentelemetry/ext/http/client/curl/http_operation_curl.h @@ -67,7 +67,7 @@ class HttpOperation /** * Create local CURL instance for url and body * @param method // HTTP Method - * @param url + * @param url * @param callback * @param request_mode // sync or async * @param request Request Headers @@ -318,7 +318,7 @@ class HttpOperation */ long GetResponseCode() { return res_; } - /** + /** * Get last session state. */ http_client::SessionState GetSessionState() { return session_state_; } diff --git a/ext/include/opentelemetry/ext/http/client/http_client.h b/ext/include/opentelemetry/ext/http/client/http_client.h index de7bdb195f..cea425e25b 100644 --- a/ext/include/opentelemetry/ext/http/client/http_client.h +++ b/ext/include/opentelemetry/ext/http/client/http_client.h @@ -153,7 +153,6 @@ class Session virtual std::unique_ptr SendRequestSync(SessionState &) noexcept = 0; - virtual bool IsSessionActive() noexcept = 0; virtual bool CancelSession() noexcept = 0; diff --git a/ext/include/opentelemetry/ext/http/common/url_parser.h b/ext/include/opentelemetry/ext/http/common/url_parser.h index e2ad4eb556..f07daedd4b 100644 --- a/ext/include/opentelemetry/ext/http/common/url_parser.h +++ b/ext/include/opentelemetry/ext/http/common/url_parser.h @@ -17,92 +17,112 @@ namespace common // host:port ( path defaults to "/") // host:port? -class UrlParser{ - public: - std::string url_; - std::string host_; - std::string scheme_; - std::string path_; - size_t port_; - std::string query_; - bool success_; +class UrlParser +{ +public: + std::string url_; + std::string host_; + std::string scheme_; + std::string path_; + size_t port_; + std::string query_; + bool success_; - UrlParser(std::string url):url_(url), success_(true) - { - if (url_.length() == 0) { - return; - } - size_t cpos = 0; - //scheme - size_t pos = url_.find("://", cpos); - if (pos == std::string::npos) { - // scheme missing, use default as http - scheme_ = "http"; - } else { - scheme_ = std::string(url_.begin() + cpos, url_.begin() + pos); - cpos = pos + 3; - } + UrlParser(std::string url) : url_(url), success_(true) + { + if (url_.length() == 0) + { + return; + } + size_t cpos = 0; + // scheme + size_t pos = url_.find("://", cpos); + if (pos == std::string::npos) + { + // scheme missing, use default as http + scheme_ = "http"; + } + else + { + scheme_ = std::string(url_.begin() + cpos, url_.begin() + pos); + cpos = pos + 3; + } - //credentials - pos = url_.find_first_of("@", cpos); - if (pos != std::string::npos) - { - //TODO - handle credentials - cpos = pos + 1; - } - pos = url_.find_first_of(":", cpos); - bool is_port = false; - if (pos == std::string::npos){ - // port missing. Used default 80 / 443 - if (scheme_ == "http") port_ = 80; - if (scheme_ == "https") port_ = 443; - } else { - // port present - is_port = true; - host_ = std::string(url_.begin() + cpos, url_.begin() + pos ); - cpos = pos + 1; - } - pos = url_.find_first_of("/?", cpos); - if (pos == std::string::npos) - { - path_ = "/" ; // use default path - if (is_port){ - //std::cout << url_[cpos] + "-" + url_[url_.length()-1] << "\n"; - port_ = std::stoi(std::string(url_.begin() + cpos , url_.begin() + url_.length() )); - } else { - host_ = std::string(url_.begin() + cpos , url_.begin() + url_.length() ); - } - return; - } - if (is_port){ - port_ = std::stoi(std::string(url_.begin() + cpos, url_.begin() + pos )); - } else { - host_ = std::string(url_.begin() + cpos, url_.begin() + pos ); - } - cpos = pos ; + // credentials + pos = url_.find_first_of("@", cpos); + if (pos != std::string::npos) + { + // TODO - handle credentials + cpos = pos + 1; + } + pos = url_.find_first_of(":", cpos); + bool is_port = false; + if (pos == std::string::npos) + { + // port missing. Used default 80 / 443 + if (scheme_ == "http") + port_ = 80; + if (scheme_ == "https") + port_ = 443; + } + else + { + // port present + is_port = true; + host_ = std::string(url_.begin() + cpos, url_.begin() + pos); + cpos = pos + 1; + } + pos = url_.find_first_of("/?", cpos); + if (pos == std::string::npos) + { + path_ = "/"; // use default path + if (is_port) + { + // std::cout << url_[cpos] + "-" + url_[url_.length()-1] << "\n"; + port_ = std::stoi(std::string(url_.begin() + cpos, url_.begin() + url_.length())); + } + else + { + host_ = std::string(url_.begin() + cpos, url_.begin() + url_.length()); + } + return; + } + if (is_port) + { + port_ = std::stoi(std::string(url_.begin() + cpos, url_.begin() + pos)); + } + else + { + host_ = std::string(url_.begin() + cpos, url_.begin() + pos); + } + cpos = pos; - if (url_[cpos] == '/') { - pos = url_.find('?', cpos); - if (pos == std::string::npos) { - path_ = std::string(url_.begin() + cpos, url_.begin() + url_.length()); - query_ = ""; - } - else { - path_ = std::string(url_.begin() + cpos, url_.begin() + pos ); - cpos = pos + 1; - query_ = std::string(url_.begin() + cpos, url_.begin() +url_.length() ); - } - return ; - } - path_ = "/"; - if (url_[cpos] == '?') { - query_ = std::string(url_.begin() + cpos, url_.begin() +url_.length()); - } - } + if (url_[cpos] == '/') + { + pos = url_.find('?', cpos); + if (pos == std::string::npos) + { + path_ = std::string(url_.begin() + cpos, url_.begin() + url_.length()); + query_ = ""; + } + else + { + path_ = std::string(url_.begin() + cpos, url_.begin() + pos); + cpos = pos + 1; + query_ = std::string(url_.begin() + cpos, url_.begin() + url_.length()); + } + return; + } + path_ = "/"; + if (url_[cpos] == '?') + { + query_ = std::string(url_.begin() + cpos, url_.begin() + url_.length()); + } + } }; -} +} // namespace common -} -} +} // namespace http +} // namespace ext OPENTELEMETRY_END_NAMESPACE \ No newline at end of file diff --git a/ext/test/http/CMakeLists.txt b/ext/test/http/CMakeLists.txt index a7306eff1e..67a87222f4 100644 --- a/ext/test/http/CMakeLists.txt +++ b/ext/test/http/CMakeLists.txt @@ -13,6 +13,7 @@ if(CURL_FOUND) endif() set(URL_PARSER_FILENAME url_parser_test) add_executable(${URL_PARSER_FILENAME} ${URL_PARSER_FILENAME}.cc) -target_link_libraries(${URL_PARSER_FILENAME} ${GTEST_BOTH_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) -gtest_add_tests(TARGET ${URL_PARSER_FILENAME} TEST_PREFIX ext.http.urlparser. TEST_LIST - ${URL_PARSER_FILENAME}) \ No newline at end of file +target_link_libraries(${URL_PARSER_FILENAME} ${GTEST_BOTH_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT}) +gtest_add_tests(TARGET ${URL_PARSER_FILENAME} TEST_PREFIX ext.http.urlparser. + TEST_LIST ${URL_PARSER_FILENAME}) diff --git a/ext/test/http/curl_http_test.cc b/ext/test/http/curl_http_test.cc index 21984a5c5e..a0480a9e1e 100644 --- a/ext/test/http/curl_http_test.cc +++ b/ext/test/http/curl_http_test.cc @@ -252,16 +252,16 @@ TEST_F(BasicCurlHttpTests, CurlHttpOperations) std::multimap m1 = { {"name1", "value1_1"}, {"name1", "value1_2"}, {"name2", "value3"}, {"name3", "value3"}}; curl::Headers headers = m1; - curl::HttpOperation http_operations1(http_client::Method::Head, "/get", handler, curl::RequestMode::Async, headers, body, - true); + curl::HttpOperation http_operations1(http_client::Method::Head, "/get", handler, + curl::RequestMode::Async, headers, body, true); http_operations1.Send(); - curl::HttpOperation http_operations2(http_client::Method::Get, "/get", handler, curl::RequestMode::Async, headers, body, - true); + curl::HttpOperation http_operations2(http_client::Method::Get, "/get", handler, + curl::RequestMode::Async, headers, body, true); http_operations2.Send(); - curl::HttpOperation http_operations3(http_client::Method::Get, "/get", handler, curl::RequestMode::Async, headers, body, - false); + curl::HttpOperation http_operations3(http_client::Method::Get, "/get", handler, + curl::RequestMode::Async, headers, body, false); http_operations3.Send(); delete handler; } diff --git a/ext/test/http/url_parser_test.cc b/ext/test/http/url_parser_test.cc index 4f8cc7c1a4..dfc9c3f961 100644 --- a/ext/test/http/url_parser_test.cc +++ b/ext/test/http/url_parser_test.cc @@ -4,67 +4,123 @@ namespace http_common = opentelemetry::ext::http::common; -inline const char * const BoolToString(bool b) +inline const char *const BoolToString(bool b) { return b ? "true" : "false"; } TEST(UrlParserTests, BasicTests) { - std::map> urls_map - { - { - "www.abc.com" , { { "host", "www.abc.com"}, {"port", "80"}, {"scheme", "http"}, {"path", "/"}, {"query",""}, {"success","true"}} - }, - { - "http://www.abc.com" , { { "host", "www.abc.com"}, {"port", "80"}, {"scheme", "http"}, {"path", "/"}, {"query",""},{"success","true"}} - }, - { - "https://www.abc.com" , { { "host", "www.abc.com"}, {"port", "443"}, {"scheme", "https"}, {"path", "/"}, {"query",""}, {"success","true"}} - }, - { - "https://www.abc.com:4431" , { { "host", "www.abc.com"}, {"port", "4431"}, {"scheme", "https"}, {"path", "/"}, {"query",""}, {"success","true"}} - }, - { - "https://www.abc.com:4431" , { { "host", "www.abc.com"}, {"port", "4431"}, {"scheme", "https"}, {"path", "/"}, {"query",""}, {"success","true"}} - }, - { - "https://www.abc.com:4431/path1" , { { "host", "www.abc.com"}, {"port", "4431"}, {"scheme", "https"}, {"path", "/path1"}, {"query",""}, {"success","true"}} - }, - { - "https://www.abc.com:4431/path1/path2" , { { "host", "www.abc.com"}, {"port", "4431"}, {"scheme", "https"}, {"path", "/path1/path2"}, {"query",""}, {"success","true"}} - }, - { - "https://www.abc.com/path1/path2" , { { "host", "www.abc.com"}, {"port", "443"}, {"scheme", "https"}, {"path", "/path1/path2"}, {"query",""}, {"success","true"}} - }, - { - "http://www.abc.com/path1/path2?q1=a1&q2=a2" , { { "host", "www.abc.com"}, {"port", "80"}, {"scheme", "http"}, {"path", "/path1/path2"}, {"query","q1=a1&q2=a2"}, {"success","true"}} - }, - { - "http://www.abc.com:8080/path1/path2?q1=a1&q2=a2" , { { "host", "www.abc.com"}, {"port", "8080"}, {"scheme", "http"}, {"path", "/path1/path2"}, {"query","q1=a1&q2=a2"}, {"success","true"}} - }, - { - "www.abc.com:8080/path1/path2?q1=a1&q2=a2" , { { "host", "www.abc.com"}, {"port", "8080"}, {"scheme", "http"}, {"path", "/path1/path2"}, {"query","q1=a1&q2=a2"},{"success","true"} } - }, - { - "http://user:password@www.abc.com:8080/path1/path2?q1=a1&q2=a2" , { { "host", "www.abc.com"}, {"port", "8080"}, {"scheme", "http"}, {"path", "/path1/path2"}, {"query","q1=a1&q2=a2"}, {"success","true"}} - }, - { - "user:password@www.abc.com:8080/path1/path2?q1=a1&q2=a2" , { { "host", "www.abc.com"}, {"port", "8080"}, {"scheme", "http"}, {"path", "/path1/path2"}, {"query","q1=a1&q2=a2"}, {"success","true"}} - }, - { - "https://user@www.abc.com/path1/path2?q1=a1&q2=a2" , { { "host", "www.abc.com"}, {"port", "443"}, {"scheme", "https"}, {"path", "/path1/path2"}, {"query","q1=a1&q2=a2"}, {"success","true"}} - }, + std::map> urls_map{ + {"www.abc.com", + {{"host", "www.abc.com"}, + {"port", "80"}, + {"scheme", "http"}, + {"path", "/"}, + {"query", ""}, + {"success", "true"}}}, + {"http://www.abc.com", + {{"host", "www.abc.com"}, + {"port", "80"}, + {"scheme", "http"}, + {"path", "/"}, + {"query", ""}, + {"success", "true"}}}, + {"https://www.abc.com", + {{"host", "www.abc.com"}, + {"port", "443"}, + {"scheme", "https"}, + {"path", "/"}, + {"query", ""}, + {"success", "true"}}}, + {"https://www.abc.com:4431", + {{"host", "www.abc.com"}, + {"port", "4431"}, + {"scheme", "https"}, + {"path", "/"}, + {"query", ""}, + {"success", "true"}}}, + {"https://www.abc.com:4431", + {{"host", "www.abc.com"}, + {"port", "4431"}, + {"scheme", "https"}, + {"path", "/"}, + {"query", ""}, + {"success", "true"}}}, + {"https://www.abc.com:4431/path1", + {{"host", "www.abc.com"}, + {"port", "4431"}, + {"scheme", "https"}, + {"path", "/path1"}, + {"query", ""}, + {"success", "true"}}}, + {"https://www.abc.com:4431/path1/path2", + {{"host", "www.abc.com"}, + {"port", "4431"}, + {"scheme", "https"}, + {"path", "/path1/path2"}, + {"query", ""}, + {"success", "true"}}}, + {"https://www.abc.com/path1/path2", + {{"host", "www.abc.com"}, + {"port", "443"}, + {"scheme", "https"}, + {"path", "/path1/path2"}, + {"query", ""}, + {"success", "true"}}}, + {"http://www.abc.com/path1/path2?q1=a1&q2=a2", + {{"host", "www.abc.com"}, + {"port", "80"}, + {"scheme", "http"}, + {"path", "/path1/path2"}, + {"query", "q1=a1&q2=a2"}, + {"success", "true"}}}, + {"http://www.abc.com:8080/path1/path2?q1=a1&q2=a2", + {{"host", "www.abc.com"}, + {"port", "8080"}, + {"scheme", "http"}, + {"path", "/path1/path2"}, + {"query", "q1=a1&q2=a2"}, + {"success", "true"}}}, + {"www.abc.com:8080/path1/path2?q1=a1&q2=a2", + {{"host", "www.abc.com"}, + {"port", "8080"}, + {"scheme", "http"}, + {"path", "/path1/path2"}, + {"query", "q1=a1&q2=a2"}, + {"success", "true"}}}, + {"http://user:password@www.abc.com:8080/path1/path2?q1=a1&q2=a2", + {{"host", "www.abc.com"}, + {"port", "8080"}, + {"scheme", "http"}, + {"path", "/path1/path2"}, + {"query", "q1=a1&q2=a2"}, + {"success", "true"}}}, + {"user:password@www.abc.com:8080/path1/path2?q1=a1&q2=a2", + {{"host", "www.abc.com"}, + {"port", "8080"}, + {"scheme", "http"}, + {"path", "/path1/path2"}, + {"query", "q1=a1&q2=a2"}, + {"success", "true"}}}, + {"https://user@www.abc.com/path1/path2?q1=a1&q2=a2", + {{"host", "www.abc.com"}, + {"port", "443"}, + {"scheme", "https"}, + {"path", "/path1/path2"}, + {"query", "q1=a1&q2=a2"}, + {"success", "true"}}}, - }; - for (auto &url_map : urls_map) { - http_common::UrlParser url(url_map.first); - auto url_properties = url_map.second; - ASSERT_EQ(BoolToString(url.success_), url_properties["success"]); - ASSERT_EQ(url.host_, url_properties["host"]); - ASSERT_EQ(std::to_string(url.port_), url_properties["port"]); - ASSERT_EQ(url.scheme_, url_properties["scheme"]); - ASSERT_EQ(url.path_, url_properties["path"]); - ASSERT_EQ(url.query_, url_properties["query"]); - } + }; + for (auto &url_map : urls_map) + { + http_common::UrlParser url(url_map.first); + auto url_properties = url_map.second; + ASSERT_EQ(BoolToString(url.success_), url_properties["success"]); + ASSERT_EQ(url.host_, url_properties["host"]); + ASSERT_EQ(std::to_string(url.port_), url_properties["port"]); + ASSERT_EQ(url.scheme_, url_properties["scheme"]); + ASSERT_EQ(url.path_, url_properties["path"]); + ASSERT_EQ(url.query_, url_properties["query"]); + } } From 861da229182ea7438777966e2a452bdd426f2842 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Fri, 18 Dec 2020 16:19:49 +0530 Subject: [PATCH 03/33] fix cmake format --- ext/test/http/CMakeLists.txt | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/ext/test/http/CMakeLists.txt b/ext/test/http/CMakeLists.txt index 67a87222f4..742ce99409 100644 --- a/ext/test/http/CMakeLists.txt +++ b/ext/test/http/CMakeLists.txt @@ -8,12 +8,16 @@ if(CURL_FOUND) include_directories(${CURL_INCLUDE_DIR}) target_link_libraries(${FILENAME} ${GTEST_BOTH_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${CURL_LIBRARIES}) - gtest_add_tests(TARGET ${FILENAME} TEST_PREFIX ext.http.curl. TEST_LIST - ${FILENAME}) + gtest_add_tests( + TARGET ${FILENAME} + TEST_PREFIX ext.http.curl. + TEST_LIST ${FILENAME}) endif() set(URL_PARSER_FILENAME url_parser_test) add_executable(${URL_PARSER_FILENAME} ${URL_PARSER_FILENAME}.cc) target_link_libraries(${URL_PARSER_FILENAME} ${GTEST_BOTH_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) -gtest_add_tests(TARGET ${URL_PARSER_FILENAME} TEST_PREFIX ext.http.urlparser. - TEST_LIST ${URL_PARSER_FILENAME}) +gtest_add_tests( + TARGET ${URL_PARSER_FILENAME} + TEST_PREFIX ext.http.urlparser. + TEST_LIST ${URL_PARSER_FILENAME}) From 586d5c9dd14fe058d98be5af21108e3b71132b12 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Fri, 18 Dec 2020 18:44:07 +0530 Subject: [PATCH 04/33] fix build --- CMakeLists.txt | 1 + exporters/zipkin/CMakeLists.txt | 31 +++++++++++++++++++ .../exporters/zipkin/recordable.h | 2 ++ .../exporters/zipkin/zipkin_exporter.h | 12 ++++--- exporters/zipkin/src/recordable.cc | 2 ++ 5 files changed, 43 insertions(+), 5 deletions(-) create mode 100644 exporters/zipkin/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index ef563be8be..390536f42f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -115,6 +115,7 @@ include_directories(sdk/include) include_directories(sdk) add_subdirectory(sdk) include_directories(.) +include_directories(ext/include) add_subdirectory(exporters) if(WITH_EXAMPLES) add_subdirectory(examples) diff --git a/exporters/zipkin/CMakeLists.txt b/exporters/zipkin/CMakeLists.txt new file mode 100644 index 0000000000..cfe0a8f8e3 --- /dev/null +++ b/exporters/zipkin/CMakeLists.txt @@ -0,0 +1,31 @@ +# Copyright 2020, OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +include_directories(include) +find_package(CURL) +if(CURL_FOUND) + add_compile_definitions(WITH_CURL) +endif() +add_library(zipkin_trace_exporter src/zipkin_exporter.cc src/recordable.cc) +if(BUILD_TESTING) + add_executable(zipkin_recordable_test test/zipkin_recordable_test.cc) + + target_link_libraries(zipkin_recordable_test ${GTEST_BOTH_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} zipkin_trace_exporter) + + gtest_add_tests( + TARGET zipkin_recordable_test + TEST_PREFIX exporter. + TEST_LIST zipkin_recordable_test) +endif() # BUILD_TESTING diff --git a/exporters/zipkin/include/opentelemetry/exporters/zipkin/recordable.h b/exporters/zipkin/include/opentelemetry/exporters/zipkin/recordable.h index a340759c6e..3bce9b09dd 100644 --- a/exporters/zipkin/include/opentelemetry/exporters/zipkin/recordable.h +++ b/exporters/zipkin/include/opentelemetry/exporters/zipkin/recordable.h @@ -42,6 +42,8 @@ class Recordable final : public sdk::trace::Recordable void SetStartTime(opentelemetry::core::SystemTimestamp start_time) noexcept override; + virtual void SetSpanKind(opentelemetry::trace::SpanKind span_kind) noexcept override; + void SetDuration(std::chrono::nanoseconds duration) noexcept override; private: diff --git a/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h b/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h index e4db446c24..ec1a062dad 100644 --- a/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h +++ b/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h @@ -61,11 +61,13 @@ class ZipkinExporter final : public trace_sdk::SpanExporter, public http_client: /** * Shut down the exporter. - * @param timeout an optional timeout, the default timeout of 0 means that no - * timeout is applied. + * @param timeout an optional timeout, default to max. */ - void Shutdown( - std::chrono::microseconds timeout = std::chrono::microseconds(0)) noexcept override{}; + bool Shutdown( + std::chrono::microseconds timeout = std::chrono::microseconds::max()) noexcept override + { + return true; + }; void OnResponse(http_client::Response &response) noexcept override { /*Not required */ @@ -90,4 +92,4 @@ class ZipkinExporter final : public trace_sdk::SpanExporter, public http_client: }; } // namespace zipkin } // namespace exporter -OPENTELEMETRY_END_NAMESPACE \ No newline at end of file +OPENTELEMETRY_END_NAMESPACE diff --git a/exporters/zipkin/src/recordable.cc b/exporters/zipkin/src/recordable.cc index 8f091222cf..38ff7432f0 100644 --- a/exporters/zipkin/src/recordable.cc +++ b/exporters/zipkin/src/recordable.cc @@ -182,6 +182,8 @@ 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);*/ } + +void Recordable::SetSpanKind(opentelemetry::trace::SpanKind span_kind) noexcept {} } // namespace zipkin } // namespace exporter OPENTELEMETRY_END_NAMESPACE From babbc5dd918561617606b5a766bddccb1834d0de Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Fri, 18 Dec 2020 19:55:54 +0530 Subject: [PATCH 05/33] remove formats --- exporters/zipkin/src/recordable.cc | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/exporters/zipkin/src/recordable.cc b/exporters/zipkin/src/recordable.cc index 38ff7432f0..78d28b5207 100644 --- a/exporters/zipkin/src/recordable.cc +++ b/exporters/zipkin/src/recordable.cc @@ -9,7 +9,6 @@ namespace zipkin { const int kAttributeValueSize = 14; -const char *EMPTY_PARENT_SPAN = "0000000000000000"; void Recordable::SetIds(trace::TraceId trace_id, trace::SpanId span_id, @@ -153,7 +152,7 @@ void Recordable::AddEvent(nostd::string_view name, void Recordable::AddLink(const opentelemetry::trace::SpanContext &span_context, const common::KeyValueIterable &attributes) noexcept { - // TODO: Populate once supported + // TODO: Currently not supported by specs: // https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/sdk_exporters/zipkin.md } @@ -167,20 +166,16 @@ void Recordable::SetStatus(trace::CanonicalCode code, nostd::string_view descrip void Recordable::SetName(nostd::string_view name) noexcept { span_["name"] = name.data(); - // span_.set_name(name.data(), name.size()); } void Recordable::SetStartTime(opentelemetry::core::SystemTimestamp start_time) noexcept { span_["timestamp"] = start_time.time_since_epoch().count(); - // span_.set_start_time_unix_nano(start_time.time_since_epoch().count()); } void Recordable::SetDuration(std::chrono::nanoseconds duration) noexcept { span_["duration"] = duration.count(); - /*const uint64_t unix_end_time = span_.start_time_unix_nano() + duration.count(); - span_.set_end_time_unix_nano(unix_end_time);*/ } void Recordable::SetSpanKind(opentelemetry::trace::SpanKind span_kind) noexcept {} From 5570d18fc4074ba30069a68297bb218e38031c20 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Fri, 18 Dec 2020 20:10:10 +0530 Subject: [PATCH 06/33] remove console debugs --- exporters/zipkin/src/zipkin_exporter.cc | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/exporters/zipkin/src/zipkin_exporter.cc b/exporters/zipkin/src/zipkin_exporter.cc index 34607bb7e1..930e4b6b65 100644 --- a/exporters/zipkin/src/zipkin_exporter.cc +++ b/exporters/zipkin/src/zipkin_exporter.cc @@ -1,5 +1,4 @@ #include "opentelemetry/exporters/zipkin/zipkin_exporter.h" -#include #include "opentelemetry/exporters/zipkin/recordable.h" #include "opentelemetry/ext/http/client/http_client_factory.h" #include "opentelemetry/ext/http/common/url_parser.h" @@ -22,8 +21,6 @@ ZipkinExporter::ZipkinExporter(const ZipkinExporterOptions &options) ZipkinExporter::ZipkinExporter() : options_(ZipkinExporterOptions()), url_parser_(options_.endpoint) { http_session_manager_ = ext::http::client::HttpClientFactory::Create(); - std::cout << "URL: " << options_.endpoint << " " << url_parser_.host_ << " " << url_parser_.port_ - << "\n"; InitializeLocalEndpoint(); } @@ -57,40 +54,25 @@ sdk::trace::ExportResult ZipkinExporter::Export( } } auto body_s = json_spans.dump(); - std::cout << "FINAL JSON:" << body_s << "\n"; http_client::Body body_v(body_s.begin(), body_s.end()); request->SetMethod(opentelemetry::ext::http::client::Method::Post); request->SetBody(body_v); request->AddHeader("Content-Type", "application/json"); http_client::SessionState session_state; auto response = session->SendRequestSync(session_state); - if (response) - { - - std::cout << "Response Code." << response->GetStatusCode() << "\n"; - auto body = response->GetBody(); - std::cout << "\nBody:"; - for (auto &c : body) - { - std::cout << static_cast(c); - } - std::cout << "\n"; - } if (response && (response->GetStatusCode() == 200 || response->GetStatusCode() == 202)) { - std::cout << " SUCCESS\n"; return sdk::trace::ExportResult::kSuccess; } else { - std::cout << " FAILURE\n"; if (session_state == http_client::SessionState::ConnectFailed) { - std::cout << "Connect failed\n"; + // TODO -> Handle error / retries } - // TBD -> Handle error / retries return sdk::trace::ExportResult::kFailure; } + return sdk::trace::ExportResult::kSuccess; } void ZipkinExporter::InitializeLocalEndpoint() From 1039f4c2b947f3b3fd0880457ec77743fd7a80e7 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Fri, 18 Dec 2020 20:12:17 +0530 Subject: [PATCH 07/33] remove debug --- ext/include/opentelemetry/ext/http/common/url_parser.h | 1 - 1 file changed, 1 deletion(-) diff --git a/ext/include/opentelemetry/ext/http/common/url_parser.h b/ext/include/opentelemetry/ext/http/common/url_parser.h index f07daedd4b..bf05f35b9b 100644 --- a/ext/include/opentelemetry/ext/http/common/url_parser.h +++ b/ext/include/opentelemetry/ext/http/common/url_parser.h @@ -78,7 +78,6 @@ class UrlParser path_ = "/"; // use default path if (is_port) { - // std::cout << url_[cpos] + "-" + url_[url_.length()-1] << "\n"; port_ = std::stoi(std::string(url_.begin() + cpos, url_.begin() + url_.length())); } else From fd5a5b6fe610af1cd7f9bc1edefbcecd052b8967 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Mon, 21 Dec 2020 22:57:42 +0530 Subject: [PATCH 08/33] Update exporters/zipkin/CMakeLists.txt Co-authored-by: Max Golovanov --- exporters/zipkin/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exporters/zipkin/CMakeLists.txt b/exporters/zipkin/CMakeLists.txt index cfe0a8f8e3..27f214247f 100644 --- a/exporters/zipkin/CMakeLists.txt +++ b/exporters/zipkin/CMakeLists.txt @@ -13,7 +13,7 @@ # limitations under the License. include_directories(include) -find_package(CURL) +find_package(CURL REQUIRED) if(CURL_FOUND) add_compile_definitions(WITH_CURL) endif() From d4f22e38fd4fda04f6e7be5e513af1abf5cfed77 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Mon, 21 Dec 2020 23:49:47 +0530 Subject: [PATCH 09/33] fix endpoint --- .../include/opentelemetry/exporters/zipkin/zipkin_exporter.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h b/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h index ec1a062dad..19b2315f54 100644 --- a/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h +++ b/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h @@ -16,11 +16,12 @@ namespace zipkin /** * Struct to hold OTLP exporter options. */ +std::string ZIPKIN_ENDPOINT_DEFAULT = "http://localhost:9411/api/v2/spans"; struct ZipkinExporterOptions { // The endpoint to export to. By default the OpenTelemetry Collector's default endpoint. - std::string endpoint = "http:://localhost:9411/api/v2/spans"; + std::string endpoint = ZIPKIN_ENDPOINT_DEFAULT; TransportFormat format = TransportFormat::JSON; std::string service_name = "default-service"; std::string ipv4; From 0fbe3afa1f7b6fc11669fb65a981d418808856ce Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Tue, 22 Dec 2020 21:05:57 +0530 Subject: [PATCH 10/33] add noop response --- .../ext/http/client/curl/http_client_curl.h | 5 ++- .../opentelemetry/ext/http/client/noop.h | 40 +++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 ext/include/opentelemetry/ext/http/client/noop.h 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 6ab71ae4e2..d58acdf616 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 @@ -1,6 +1,7 @@ #pragma once #include "http_operation_curl.h" +#include "opentelemetry/ext/http/client/noop.h" #include #include @@ -177,7 +178,8 @@ class Session : public http_client::Session return std::move(response); } is_session_active_ = false; - return nullptr; + auto response = std::unique_ptr(new NoopResponse()); + return std::move(response); } virtual bool CancelSession() noexcept override @@ -203,6 +205,7 @@ class Session : public http_client::Session uint64_t session_id_; SessionManager &session_manager_; bool is_session_active_; + std::shared_ptr noop_response; }; class SessionManager : public http_client::SessionManager diff --git a/ext/include/opentelemetry/ext/http/client/noop.h b/ext/include/opentelemetry/ext/http/client/noop.h new file mode 100644 index 0000000000..56073ff50b --- /dev/null +++ b/ext/include/opentelemetry/ext/http/client/noop.h @@ -0,0 +1,40 @@ +#pragma once +#include "http_client.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace ext +{ +namespace http +{ +namespace client +{ + +class NoopResponse : public Response +{ +public: + const Body &GetBody() const noexcept override { return body; } + + bool ForEachHeader( + nostd::function_ref callable) const + noexcept override + { + return true; + } + + bool ForEachHeader( + const nostd::string_view &key, + nostd::function_ref callable) const + noexcept override + { + return true; + } + + StatusCode GetStatusCode() const noexcept override { return 0; } + +private: + Body body; +}; +} // namespace client +} // namespace http +} // namespace ext +OPENTELEMETRY_END_NAMESPACE \ No newline at end of file From cdf5dc48106c0d38ff4546cf434036cd04a68836 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Tue, 22 Dec 2020 22:34:37 +0530 Subject: [PATCH 11/33] fix nullptr for http errors --- .../ext/http/client/curl/http_client_curl.h | 10 ++++++---- ext/test/http/curl_http_test.cc | 3 ++- 2 files changed, 8 insertions(+), 5 deletions(-) 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 a6e4929bb5..559cd9db06 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 @@ -172,17 +172,19 @@ class Session : public http_client::Session { session_state = http_client::SessionState::Cancelled; } + auto response = std::unique_ptr(new Response()); if (curl_operation_->GetResponseCode() >= CURL_LAST) { // we have a http response - auto response = std::unique_ptr(new Response()); response->headers_ = curl_operation_->GetResponseHeaders(); response->body_ = curl_operation_->GetResponseBody(); - is_session_active_ = false; - return std::move(response); + } + else + { + // No http response + response->status_code_ = 0; } is_session_active_ = false; - auto response = std::unique_ptr(new NoopResponse()); return std::move(response); } diff --git a/ext/test/http/curl_http_test.cc b/ext/test/http/curl_http_test.cc index 2260eddfca..91c07da3bb 100644 --- a/ext/test/http/curl_http_test.cc +++ b/ext/test/http/curl_http_test.cc @@ -294,7 +294,8 @@ TEST_F(BasicCurlHttpTests, SendGetRequestSyncTimeout) http_client::SessionState session_state; auto response = session->SendRequestSync(session_state); EXPECT_EQ(session_state, http_client::SessionState::ConnectFailed); - EXPECT_TRUE(response == nullptr); + EXPECT_EQ(response->GetStatusCode(), 0); + EXPECT_EQ(response->GetBody().size(), 0); } TEST_F(BasicCurlHttpTests, GetBaseUri) From 19d789f2985f280cdc35cddae0abc595e111d112 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Tue, 22 Dec 2020 23:01:15 +0530 Subject: [PATCH 12/33] remove otlp stuff --- .../exporters/zipkin/zipkin_exporter.h | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h b/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h index 19b2315f54..5adb46cb05 100644 --- a/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h +++ b/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h @@ -13,11 +13,12 @@ namespace exporter { namespace zipkin { -/** - * Struct to hold OTLP exporter options. - */ + std::string ZIPKIN_ENDPOINT_DEFAULT = "http://localhost:9411/api/v2/spans"; +/** + * Struct to hold Zipkin exporter options. + */ struct ZipkinExporterOptions { // The endpoint to export to. By default the OpenTelemetry Collector's default endpoint. @@ -32,18 +33,18 @@ namespace trace_sdk = opentelemetry::sdk::trace; namespace http_client = opentelemetry::ext::http::client; /** - * The OTLP exporter exports span data in OpenTelemetry Protocol (OTLP) format. + * The Zipkin exporter exports span data in JSON format as expected by Zipkin */ class ZipkinExporter final : public trace_sdk::SpanExporter, public http_client::EventHandler { public: /** - * Create an OtlpExporter using all default options. + * Create an ZipkinExporter using all default options. */ ZipkinExporter(); /** - * Create an OtlpExporter using the given options. + * Create an ZipkinExporter using the given options. */ ZipkinExporter(const ZipkinExporterOptions &options); @@ -54,7 +55,7 @@ class ZipkinExporter final : public trace_sdk::SpanExporter, public http_client: std::unique_ptr MakeRecordable() noexcept override; /** - * Export a batch of span recordables in OTLP format. + * Export a batch of span recordables in JSON format. * @param spans a span of unique pointers to span recordables */ trace_sdk::ExportResult Export( From 84b0458ad857bf656dc72046982c9b31a8b7ad18 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Mon, 28 Dec 2020 19:28:12 +0530 Subject: [PATCH 13/33] fix sync mode --- .../opentelemetry/ext/http/client/curl/http_client_curl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 559cd9db06..c1dc711d79 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 @@ -137,7 +137,7 @@ class Session : public http_client::Session std::string url = host_ + std::string(http_request_->uri_); auto callback_ptr = &callback; curl_operation_.reset(new HttpOperation( - http_request_->method_, url, callback_ptr, RequestMode::Sync, http_request_->headers_, + http_request_->method_, url, callback_ptr, RequestMode::Async, http_request_->headers_, http_request_->body_, false, http_request_->timeout_ms_)); curl_operation_->SendAsync([this, callback_ptr](HttpOperation &operation) { if (operation.WasAborted()) From 791e2a163afb99868c1921df909b65d4c575514b Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Wed, 27 Jan 2021 13:58:26 +0530 Subject: [PATCH 14/33] fixes --- .../exporters/elasticsearch/es_log_exporter.h | 2 +- .../exporters/zipkin/zipkin_exporter.h | 15 ++------- exporters/zipkin/src/zipkin_exporter.cc | 23 +++++++------- .../ext/http/client/curl/http_client_curl.h | 2 +- ext/test/http/curl_http_test.cc | 31 ------------------- 5 files changed, 16 insertions(+), 57 deletions(-) diff --git a/exporters/elasticsearch/include/opentelemetry/exporters/elasticsearch/es_log_exporter.h b/exporters/elasticsearch/include/opentelemetry/exporters/elasticsearch/es_log_exporter.h index 02b0493306..7cd2e2c53c 100644 --- a/exporters/elasticsearch/include/opentelemetry/exporters/elasticsearch/es_log_exporter.h +++ b/exporters/elasticsearch/include/opentelemetry/exporters/elasticsearch/es_log_exporter.h @@ -117,7 +117,7 @@ class ElasticsearchLogExporter final : public sdklogs::LogExporter ElasticsearchExporterOptions options_; // Object that stores the HTTP sessions that have been created - std::unique_ptr http_client_; + std::unique_ptr http_client_; }; } // namespace logs } // namespace exporter diff --git a/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h b/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h index 5adb46cb05..f0d63c1475 100644 --- a/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h +++ b/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h @@ -35,7 +35,7 @@ namespace http_client = opentelemetry::ext::http::client; /** * The Zipkin exporter exports span data in JSON format as expected by Zipkin */ -class ZipkinExporter final : public trace_sdk::SpanExporter, public http_client::EventHandler +class ZipkinExporter final : public trace_sdk::SpanExporter { public: /** @@ -71,26 +71,15 @@ class ZipkinExporter final : public trace_sdk::SpanExporter, public http_client: return true; }; - void OnResponse(http_client::Response &response) noexcept override - { /*Not required */ - } - - virtual void OnEvent(http_client::SessionState state, - nostd::string_view msg) noexcept override{/* Not required */}; - - virtual void OnConnecting(const http_client::SSLCertificate &) noexcept override{ - /* Not required */}; - private: void InitializeLocalEndpoint(); private: // The configuration options associated with this exporter. bool isShutdown_ = false; - std::shared_ptr http_session_manager_; + std::shared_ptr http_client; nlohmann::json local_end_point_; ZipkinExporterOptions options_; - ext::http::common::UrlParser url_parser_; }; } // namespace zipkin } // namespace exporter diff --git a/exporters/zipkin/src/zipkin_exporter.cc b/exporters/zipkin/src/zipkin_exporter.cc index 930e4b6b65..3ea2fb77c6 100644 --- a/exporters/zipkin/src/zipkin_exporter.cc +++ b/exporters/zipkin/src/zipkin_exporter.cc @@ -14,13 +14,13 @@ namespace zipkin ZipkinExporter::ZipkinExporter(const ZipkinExporterOptions &options) : options_(options), url_parser_(options_.endpoint) { - http_session_manager_ = ext::http::client::HttpClientFactory::Create(); + http_client_ = ext::http::client::HttpClientFactory::CreateSync(); InitializeLocalEndpoint(); } ZipkinExporter::ZipkinExporter() : options_(ZipkinExporterOptions()), url_parser_(options_.endpoint) { - http_session_manager_ = ext::http::client::HttpClientFactory::Create(); + http_client_ = ext::http::client::HttpClientFactory::CreateSync(); InitializeLocalEndpoint(); } @@ -38,9 +38,9 @@ sdk::trace::ExportResult ZipkinExporter::Export( { return sdk::trace::ExportResult::kFailure; } - auto session = http_session_manager_->CreateSession(url_parser_.host_, url_parser_.port_); - auto request = session->CreateRequest(); - request->SetUri(url_parser_.path_); + // auto session = http_session_manager_->CreateSession(url_parser_.host_, url_parser_.port_); + // auto request = session->CreateRequest(); + // request->SetUri(url_parser_.path_); exporter::zipkin::ZipkinSpan json_spans = {}; for (auto &recordable : spans) { @@ -55,12 +55,13 @@ sdk::trace::ExportResult ZipkinExporter::Export( } auto body_s = json_spans.dump(); http_client::Body body_v(body_s.begin(), body_s.end()); - request->SetMethod(opentelemetry::ext::http::client::Method::Post); - request->SetBody(body_v); - request->AddHeader("Content-Type", "application/json"); - http_client::SessionState session_state; - auto response = session->SendRequestSync(session_state); - if (response && (response->GetStatusCode() == 200 || response->GetStatusCode() == 202)) + // request->SetMethod(opentelemetry::ext::http::client::Method::Post); + // request->SetBody(body_v); + // request->AddHeader("Content-Type", "application/json"); + // http_client::SessionState session_state; + // auto response = session->SendRequestSync(session_state); + auto result = http_client_ if (response && (response->GetStatusCode() == 200 || + response->GetStatusCode() == 202)) { return sdk::trace::ExportResult::kSuccess; } 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 b1720cab7e..3cbd29ee97 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 @@ -1,8 +1,8 @@ #pragma once +#include "http_operation_curl.h" #include "opentelemetry/ext/http/client/http_client.h" #include "opentelemetry/version.h" -#include "http_operation_curl.h" #include #include diff --git a/ext/test/http/curl_http_test.cc b/ext/test/http/curl_http_test.cc index f81c6f6c17..f5f2738518 100644 --- a/ext/test/http/curl_http_test.cc +++ b/ext/test/http/curl_http_test.cc @@ -267,37 +267,6 @@ TEST_F(BasicCurlHttpTests, CurlHttpOperations) delete handler; } -TEST_F(BasicCurlHttpTests, SendGetRequestSync) -{ - received_requests_.clear(); - curl::SessionManager session_manager; - - auto session = session_manager.CreateSession("127.0.0.1", HTTP_PORT); - auto request = session->CreateRequest(); - request->SetUri("get/"); - http_client::SessionState session_state; - auto response = session->SendRequestSync(session_state); - EXPECT_EQ(response->GetStatusCode(), 200); - EXPECT_EQ(session_state, http_client::SessionState::Response); -} - -TEST_F(BasicCurlHttpTests, SendGetRequestSyncTimeout) -{ - received_requests_.clear(); - curl::SessionManager session_manager; - - auto session = - session_manager.CreateSession("222.222.222.200", HTTP_PORT); // Non Existing address - auto request = session->CreateRequest(); - request->SetTimeoutMs(std::chrono::milliseconds(3000)); - request->SetUri("get/"); - http_client::SessionState session_state; - auto response = session->SendRequestSync(session_state); - EXPECT_EQ(session_state, http_client::SessionState::ConnectFailed); - EXPECT_EQ(response->GetStatusCode(), 0); - EXPECT_EQ(response->GetBody().size(), 0); -} - TEST_F(BasicCurlHttpTests, SendGetRequestSync) { received_requests_.clear(); From aff76e2e66954c8a2c1624726ec66e00a180b5e0 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Wed, 27 Jan 2021 15:32:40 +0530 Subject: [PATCH 15/33] fix --- .../exporters/zipkin/zipkin_exporter.h | 3 ++- exporters/zipkin/src/zipkin_exporter.cc | 15 ++++-------- .../zipkin/test/zipkin_recordable_test.cc | 24 +++++++++---------- .../ext/http/client/curl/http_client_curl.h | 4 ++-- .../ext/http/client/http_client.h | 3 +-- 5 files changed, 21 insertions(+), 28 deletions(-) diff --git a/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h b/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h index f0d63c1475..0a048a2ff1 100644 --- a/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h +++ b/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h @@ -77,7 +77,8 @@ class ZipkinExporter final : public trace_sdk::SpanExporter private: // The configuration options associated with this exporter. bool isShutdown_ = false; - std::shared_ptr http_client; + std::shared_ptr http_client_; + opentelemetry::ext::http::common::UrlParser url_parser_; nlohmann::json local_end_point_; ZipkinExporterOptions options_; }; diff --git a/exporters/zipkin/src/zipkin_exporter.cc b/exporters/zipkin/src/zipkin_exporter.cc index 3ea2fb77c6..1d4d62fdfd 100644 --- a/exporters/zipkin/src/zipkin_exporter.cc +++ b/exporters/zipkin/src/zipkin_exporter.cc @@ -38,9 +38,6 @@ sdk::trace::ExportResult ZipkinExporter::Export( { return sdk::trace::ExportResult::kFailure; } - // auto session = http_session_manager_->CreateSession(url_parser_.host_, url_parser_.port_); - // auto request = session->CreateRequest(); - // request->SetUri(url_parser_.path_); exporter::zipkin::ZipkinSpan json_spans = {}; for (auto &recordable : spans) { @@ -55,19 +52,15 @@ sdk::trace::ExportResult ZipkinExporter::Export( } auto body_s = json_spans.dump(); http_client::Body body_v(body_s.begin(), body_s.end()); - // request->SetMethod(opentelemetry::ext::http::client::Method::Post); - // request->SetBody(body_v); - // request->AddHeader("Content-Type", "application/json"); - // http_client::SessionState session_state; - // auto response = session->SendRequestSync(session_state); - auto result = http_client_ if (response && (response->GetStatusCode() == 200 || - response->GetStatusCode() == 202)) + auto result = http_client_->Post(url_parser_.url_, body_v); + if (result && result.GetResponse().GetStatusCode() == 200 || + result.GetResponse().GetStatusCode() == 202) { return sdk::trace::ExportResult::kSuccess; } else { - if (session_state == http_client::SessionState::ConnectFailed) + if (result.GetSessionState() == http_client::SessionState::ConnectFailed) { // TODO -> Handle error / retries } diff --git a/exporters/zipkin/test/zipkin_recordable_test.cc b/exporters/zipkin/test/zipkin_recordable_test.cc index 09e90bf63c..2fbcc265c0 100644 --- a/exporters/zipkin/test/zipkin_recordable_test.cc +++ b/exporters/zipkin/test/zipkin_recordable_test.cc @@ -38,7 +38,7 @@ TEST(ZipkinSpanRecordable, SetIds) EXPECT_EQ(rec.span(), j_span); } -TEST(Recordable, SetName) +TEST(ZipkinSpanRecordable, SetName) { nostd::string_view name = "Test Span"; json j_span = {{"name", name}}; @@ -47,7 +47,7 @@ TEST(Recordable, SetName) EXPECT_EQ(rec.span(), j_span); } -TEST(Recordable, SetStartTime) +TEST(ZipkinSpanRecordable, SetStartTime) { opentelemetry::exporter::zipkin::Recordable rec; std::chrono::system_clock::time_point start_time = std::chrono::system_clock::now(); @@ -60,7 +60,7 @@ TEST(Recordable, SetStartTime) EXPECT_EQ(rec.span(), j_span); } -TEST(Recordable, SetDuration) +TEST(ZipkinSpanRecordable, SetDuration) { json j_span = {{"duration", 10}, {"timestamp", 0}}; opentelemetry::exporter::zipkin::Recordable rec; @@ -75,7 +75,7 @@ TEST(Recordable, SetDuration) EXPECT_EQ(rec.span(), j_span); } -TEST(Recordable, SetStatus) +TEST(ZipkinSpanRecordable, SetStatus) { opentelemetry::exporter::zipkin::Recordable rec; trace::CanonicalCode code(trace::CanonicalCode::OK); @@ -85,7 +85,7 @@ TEST(Recordable, SetStatus) EXPECT_EQ(rec.span(), j_span); } -TEST(Recordable, AddEventDefault) +TEST(ZipkinSpanRecordable, AddEventDefault) { opentelemetry::exporter::zipkin::Recordable rec; nostd::string_view name = "Test Event"; @@ -103,7 +103,7 @@ TEST(Recordable, AddEventDefault) EXPECT_EQ(rec.span(), j_span); } -TEST(Recordable, AddEventWithAttributes) +TEST(ZipkinSpanRecordable, AddEventWithAttributes) { opentelemetry::exporter::zipkin::Recordable rec; nostd::string_view name = "Test Event"; @@ -130,7 +130,7 @@ TEST(Recordable, AddEventWithAttributes) } // Test non-int single types. Int single types are tested using templates (see IntAttributeTest) -TEST(Recordable, SetSingleAtrribute) +TEST(ZipkinSpanRecordable, SetSingleAtrribute) { opentelemetry::exporter::zipkin::Recordable rec; nostd::string_view bool_key = "bool_attr"; @@ -151,7 +151,7 @@ TEST(Recordable, SetSingleAtrribute) } // Test non-int array types. Int array types are tested using templates (see IntAttributeTest) -TEST(Recordable, SetArrayAtrribute) +TEST(ZipkinSpanRecordable, SetArrayAtrribute) { opentelemetry::exporter::zipkin::Recordable rec; nlohmann::json j_span = {{"tags", @@ -181,15 +181,15 @@ TEST(Recordable, SetArrayAtrribute) * use a template approach to test all int types. */ template -struct IntAttributeTest : public testing::Test +struct ZipkinIntAttributeTest : public testing::Test { using IntParamType = T; }; using IntTypes = testing::Types; -TYPED_TEST_CASE(IntAttributeTest, IntTypes); +TYPED_TEST_CASE(ZipkinIntAttributeTest, IntTypes); -TYPED_TEST(IntAttributeTest, SetIntSingleAttribute) +TYPED_TEST(ZipkinIntAttributeTest, SetIntSingleAttribute) { using IntType = typename TestFixture::IntParamType; IntType i = 2; @@ -201,7 +201,7 @@ TYPED_TEST(IntAttributeTest, SetIntSingleAttribute) EXPECT_EQ(rec.span(), j_span); } -TYPED_TEST(IntAttributeTest, SetIntArrayAttribute) +TYPED_TEST(ZipkinIntAttributeTest, SetIntArrayAttribute) { using IntType = typename TestFixture::IntParamType; 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 3cbd29ee97..16c27a5e0c 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 @@ -243,11 +243,11 @@ class HttpClientSync : public http_client::HttpClientSync } http_client::Result Post(const nostd::string_view &url, - const Data &data, + const Body &body, const http_client::Headers &headers) noexcept override { HttpOperation curl_operation(http_client::Method::Post, url.data(), nullptr, RequestMode::Sync, - headers); + headers, body); curl_operation.SendSync(); auto session_state = curl_operation.GetSessionState(); if (curl_operation.WasAborted()) diff --git a/ext/include/opentelemetry/ext/http/client/http_client.h b/ext/include/opentelemetry/ext/http/client/http_client.h index 9bf3b68ed4..3c5ce6cb52 100644 --- a/ext/include/opentelemetry/ext/http/client/http_client.h +++ b/ext/include/opentelemetry/ext/http/client/http_client.h @@ -94,7 +94,6 @@ enum class SessionState using Byte = uint8_t; using StatusCode = uint16_t; using Body = std::vector; -using Data = std::map; using SSLCertificate = std::vector; struct cmp_ic @@ -243,7 +242,7 @@ class HttpClientSync virtual Result Get(const nostd::string_view &url, const Headers & = {{}}) noexcept = 0; virtual Result Post(const nostd::string_view &url, - const Data &data, + const Body &body, const Headers & = {{"content-type", "application/json"}}) noexcept = 0; virtual ~HttpClientSync() = default; From dcc758b76de53ea0903968518805448ea1f9a894 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Wed, 27 Jan 2021 16:08:55 +0530 Subject: [PATCH 16/33] fix --- .../opentelemetry/exporters/elasticsearch/es_log_exporter.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exporters/elasticsearch/include/opentelemetry/exporters/elasticsearch/es_log_exporter.h b/exporters/elasticsearch/include/opentelemetry/exporters/elasticsearch/es_log_exporter.h index 7cd2e2c53c..02b0493306 100644 --- a/exporters/elasticsearch/include/opentelemetry/exporters/elasticsearch/es_log_exporter.h +++ b/exporters/elasticsearch/include/opentelemetry/exporters/elasticsearch/es_log_exporter.h @@ -117,7 +117,7 @@ class ElasticsearchLogExporter final : public sdklogs::LogExporter ElasticsearchExporterOptions options_; // Object that stores the HTTP sessions that have been created - std::unique_ptr http_client_; + std::unique_ptr http_client_; }; } // namespace logs } // namespace exporter From b3e96c7de59ccc7e8588c4f9917c27294e9ae8f7 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Wed, 27 Jan 2021 17:18:29 +0530 Subject: [PATCH 17/33] fix spell --- exporters/zipkin/src/zipkin_exporter.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exporters/zipkin/src/zipkin_exporter.cc b/exporters/zipkin/src/zipkin_exporter.cc index 1d4d62fdfd..1929fab7ee 100644 --- a/exporters/zipkin/src/zipkin_exporter.cc +++ b/exporters/zipkin/src/zipkin_exporter.cc @@ -9,7 +9,7 @@ namespace exporter namespace zipkin { -// -------------------------------- Contructors -------------------------------- +// -------------------------------- Constructors -------------------------------- ZipkinExporter::ZipkinExporter(const ZipkinExporterOptions &options) : options_(options), url_parser_(options_.endpoint) From 4c97dc74c9186bec423ac6a15bec34a6a52b7a0b Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Wed, 27 Jan 2021 17:28:48 +0530 Subject: [PATCH 18/33] fix --- exporters/zipkin/CMakeLists.txt | 2 +- .../exporters/zipkin/zipkin_exporter.h | 2 +- .../ext/http/client/curl/http_client_curl.h | 30 -------------- .../opentelemetry/ext/http/client/noop.h | 40 ------------------- 4 files changed, 2 insertions(+), 72 deletions(-) delete mode 100644 ext/include/opentelemetry/ext/http/client/noop.h diff --git a/exporters/zipkin/CMakeLists.txt b/exporters/zipkin/CMakeLists.txt index 27f214247f..cfe0a8f8e3 100644 --- a/exporters/zipkin/CMakeLists.txt +++ b/exporters/zipkin/CMakeLists.txt @@ -13,7 +13,7 @@ # limitations under the License. include_directories(include) -find_package(CURL REQUIRED) +find_package(CURL) if(CURL_FOUND) add_compile_definitions(WITH_CURL) endif() diff --git a/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h b/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h index 0a048a2ff1..3dd6305cdd 100644 --- a/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h +++ b/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h @@ -46,7 +46,7 @@ class ZipkinExporter final : public trace_sdk::SpanExporter /** * Create an ZipkinExporter using the given options. */ - ZipkinExporter(const ZipkinExporterOptions &options); + explicit ZipkinExporter(const ZipkinExporterOptions &options); /** * Create a span recordable. 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 16c27a5e0c..ded5c1ce2b 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 @@ -160,36 +160,6 @@ class Session : public http_client::Session }); } - virtual std::unique_ptr SendRequestSync( - http_client::SessionState &session_state) noexcept override - { - is_session_active_ = true; - std::string url = host_ + std::string(http_request_->uri_); - curl_operation_.reset(new HttpOperation(http_request_->method_, url, nullptr, RequestMode::Sync, - http_request_->headers_, http_request_->body_, false, - http_request_->timeout_ms_)); - curl_operation_->SendSync(); - session_state = curl_operation_->GetSessionState(); - if (curl_operation_->WasAborted()) - { - session_state = http_client::SessionState::Cancelled; - } - auto response = std::unique_ptr(new Response()); - if (curl_operation_->GetResponseCode() >= CURL_LAST) - { - // we have a http response - response->headers_ = curl_operation_->GetResponseHeaders(); - response->body_ = curl_operation_->GetResponseBody(); - } - else - { - // No http response - response->status_code_ = 0; - } - is_session_active_ = false; - return std::move(response); - } - virtual bool CancelSession() noexcept override; virtual bool FinishSession() noexcept override; diff --git a/ext/include/opentelemetry/ext/http/client/noop.h b/ext/include/opentelemetry/ext/http/client/noop.h deleted file mode 100644 index 56073ff50b..0000000000 --- a/ext/include/opentelemetry/ext/http/client/noop.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once -#include "http_client.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace ext -{ -namespace http -{ -namespace client -{ - -class NoopResponse : public Response -{ -public: - const Body &GetBody() const noexcept override { return body; } - - bool ForEachHeader( - nostd::function_ref callable) const - noexcept override - { - return true; - } - - bool ForEachHeader( - const nostd::string_view &key, - nostd::function_ref callable) const - noexcept override - { - return true; - } - - StatusCode GetStatusCode() const noexcept override { return 0; } - -private: - Body body; -}; -} // namespace client -} // namespace http -} // namespace ext -OPENTELEMETRY_END_NAMESPACE \ No newline at end of file From 3806ee2f3494af79e5c81ac3fcd2553ec9f668ed Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Wed, 27 Jan 2021 17:56:38 +0530 Subject: [PATCH 19/33] fix --- ext/include/opentelemetry/ext/http/client/http_client.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/ext/include/opentelemetry/ext/http/client/http_client.h b/ext/include/opentelemetry/ext/http/client/http_client.h index 3c5ce6cb52..28b3317a4c 100644 --- a/ext/include/opentelemetry/ext/http/client/http_client.h +++ b/ext/include/opentelemetry/ext/http/client/http_client.h @@ -213,8 +213,6 @@ class Session virtual void SendRequest(EventHandler &) noexcept = 0; - virtual std::unique_ptr SendRequestSync(SessionState &) noexcept = 0; - virtual bool IsSessionActive() noexcept = 0; virtual bool CancelSession() noexcept = 0; From 012575298f22e8bef1ad126b1f8ed7cf9190ba1d Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Wed, 27 Jan 2021 17:59:18 +0530 Subject: [PATCH 20/33] fix --- .../opentelemetry/ext/http/client/http_client_factory.h | 3 --- 1 file changed, 3 deletions(-) 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 080dee6242..9ae5b0dd1b 100644 --- a/ext/include/opentelemetry/ext/http/client/http_client_factory.h +++ b/ext/include/opentelemetry/ext/http/client/http_client_factory.h @@ -1,8 +1,5 @@ #pragma once #include "opentelemetry/ext/http/client/http_client.h" -#ifdef WITH_CURL -# include "opentelemetry/ext/http/client/curl/http_client_curl.h" -#endif OPENTELEMETRY_BEGIN_NAMESPACE namespace ext From ae0a1a0d8ad618be2de4bbdc0239f5cac68f660d Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Wed, 27 Jan 2021 19:46:57 +0530 Subject: [PATCH 21/33] fix --- ext/test/http/curl_http_test.cc | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/ext/test/http/curl_http_test.cc b/ext/test/http/curl_http_test.cc index f5f2738518..88be5fe535 100644 --- a/ext/test/http/curl_http_test.cc +++ b/ext/test/http/curl_http_test.cc @@ -273,7 +273,7 @@ TEST_F(BasicCurlHttpTests, SendGetRequestSync) curl::HttpClientSync http_client; http_client::Headers m1 = {}; - auto result = http_client.Get("http://127.0.0.1:19000/get/", m1); // (session_state); + auto result = http_client.Get("http://127.0.0.1:19000/get/", m1); EXPECT_EQ(result, true); EXPECT_EQ(result.GetSessionState(), http_client::SessionState::Response); } @@ -284,13 +284,24 @@ TEST_F(BasicCurlHttpTests, SendGetRequestSyncTimeout) curl::HttpClientSync http_client; http_client::Headers m1 = {}; - auto result = - http_client.Get("http://222.222.222.200:19000/get/", m1); // (session_state); + auto result = http_client.Get("http://222.222.222.200:19000/get/", m1); EXPECT_EQ(result, false); EXPECT_EQ(result.GetSessionState(), http_client::SessionState::ConnectFailed); } +TEST_F(BasicCurlHttpTests, SendPostRequestSync) +{ + received_requests_.clear(); + curl::HttpClientSync http_client; + + http_client::Headers m1 = {}; + http_client::Body body = {}; + auto result = http_client.Post("http://127.0.0.1:19000/post/", body, m1); + EXPECT_EQ(result, true); + EXPECT_EQ(result.GetSessionState(), http_client::SessionState::Response); +} + TEST_F(BasicCurlHttpTests, GetBaseUri) { curl::HttpClient session_manager; From 8c351c1d0adf4d00df1cfd847b65340a14a51ea6 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Fri, 29 Jan 2021 10:27:05 +0530 Subject: [PATCH 22/33] review fix --- exporters/CMakeLists.txt | 14 ++++++++++++++ exporters/zipkin/CMakeLists.txt | 4 ++-- .../opentelemetry/exporters/zipkin/recordable.h | 4 ++-- .../exporters/zipkin/zipkin_exporter.h | 8 ++++---- 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/exporters/CMakeLists.txt b/exporters/CMakeLists.txt index 305357a075..69cff59e89 100644 --- a/exporters/CMakeLists.txt +++ b/exporters/CMakeLists.txt @@ -1,3 +1,17 @@ +# Copyright 2021, OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + if(WITH_OTLP) add_subdirectory(otlp) endif() diff --git a/exporters/zipkin/CMakeLists.txt b/exporters/zipkin/CMakeLists.txt index cfe0a8f8e3..b9e8610d1d 100644 --- a/exporters/zipkin/CMakeLists.txt +++ b/exporters/zipkin/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright 2020, OpenTelemetry Authors +# Copyright 2021, OpenTelemetry Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -15,7 +15,7 @@ include_directories(include) find_package(CURL) if(CURL_FOUND) - add_compile_definitions(WITH_CURL) + add_definitions(-DWITH_CURL) endif() add_library(zipkin_trace_exporter src/zipkin_exporter.cc src/recordable.cc) if(BUILD_TESTING) diff --git a/exporters/zipkin/include/opentelemetry/exporters/zipkin/recordable.h b/exporters/zipkin/include/opentelemetry/exporters/zipkin/recordable.h index 3bce9b09dd..989248932e 100644 --- a/exporters/zipkin/include/opentelemetry/exporters/zipkin/recordable.h +++ b/exporters/zipkin/include/opentelemetry/exporters/zipkin/recordable.h @@ -13,8 +13,8 @@ using ZipkinSpan = nlohmann::json; enum class TransportFormat { - JSON, - PROTOBUF + kJson, + kProtobuf }; class Recordable final : public sdk::trace::Recordable diff --git a/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h b/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h index 3dd6305cdd..1a1a7561d5 100644 --- a/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h +++ b/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h @@ -14,7 +14,7 @@ namespace exporter namespace zipkin { -std::string ZIPKIN_ENDPOINT_DEFAULT = "http://localhost:9411/api/v2/spans"; +constexpr std::string kZipkinEndpointDefault = "http://localhost:9411/api/v2/spans"; /** * Struct to hold Zipkin exporter options. @@ -22,8 +22,8 @@ std::string ZIPKIN_ENDPOINT_DEFAULT = "http://localhost:9411/api/v2/spans"; struct ZipkinExporterOptions { // The endpoint to export to. By default the OpenTelemetry Collector's default endpoint. - std::string endpoint = ZIPKIN_ENDPOINT_DEFAULT; - TransportFormat format = TransportFormat::JSON; + std::string endpoint = kZipkinEndpointDefault; + TransportFormat format = TransportFormat::kJson; std::string service_name = "default-service"; std::string ipv4; std::string ipv6; @@ -69,7 +69,7 @@ class ZipkinExporter final : public trace_sdk::SpanExporter std::chrono::microseconds timeout = std::chrono::microseconds::max()) noexcept override { return true; - }; + } private: void InitializeLocalEndpoint(); From 7283a85a86ed9747e7cb67aae3397a39eb8427eb Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Fri, 12 Feb 2021 18:58:36 +0530 Subject: [PATCH 23/33] fix --- exporters/zipkin/src/recordable.cc | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/exporters/zipkin/src/recordable.cc b/exporters/zipkin/src/recordable.cc index 78d28b5207..663d461259 100644 --- a/exporters/zipkin/src/recordable.cc +++ b/exporters/zipkin/src/recordable.cc @@ -14,15 +14,15 @@ void Recordable::SetIds(trace::TraceId trace_id, trace::SpanId span_id, trace::SpanId parent_span_id) noexcept { - char traceid[trace::TraceId::kSize * 2] = {0}; - trace_id.ToLowerBase16(traceid); - char spanid[trace::SpanId::kSize * 2] = {0}; - span_id.ToLowerBase16(spanid); - char parentid[trace::SpanId::kSize * 2] = {0}; - parent_span_id.ToLowerBase16(parentid); - span_["id"] = std::string(spanid, 16); - span_["parentId"] = std::string(parentid, 16); - span_["traceId"] = std::string(traceid, 32); + char trace_id_lower_base16[trace::TraceId::kSize * 2] = {0}; + trace_id.ToLowerBase16(trace_id_lower_base16); + char span_id_lower_base16[trace::SpanId::kSize * 2] = {0}; + span_id.ToLowerBase16(span_id_lower_base16); + char parent_span_id_lower_base16[trace::SpanId::kSize * 2] = {0}; + parent_span_id.ToLowerBase16(parent_span_id_lower_base16); + span_["id"] = std::string(span_id_lower_base16, 16); + span_["parentId"] = std::string(parent_span_id_lower_base16, 16); + span_["traceId"] = std::string(trace_id_lower_base16, 32); } void PopulateAttribute(nlohmann::json &attribute, @@ -35,8 +35,6 @@ void PopulateAttribute(nlohmann::json &attribute, nostd::variant_size::value == kAttributeValueSize, "AttributeValue contains unknown type"); - // attribute->set_key(key.data(), key.size()); - if (nostd::holds_alternative(value)) { attribute[key.data()] = nostd::get(value); @@ -47,7 +45,6 @@ void PopulateAttribute(nlohmann::json &attribute, } else if (nostd::holds_alternative(value)) { - attribute[key.data()] = nostd::get(value); } else if (nostd::holds_alternative(value)) From 5764899298c39955665d059a9af13d627d6d441a Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Fri, 12 Feb 2021 20:17:46 +0530 Subject: [PATCH 24/33] fix --- ci/do_ci.sh | 1 + .../zipkin/include/opentelemetry/exporters/zipkin/recordable.h | 2 +- .../include/opentelemetry/exporters/zipkin/zipkin_exporter.h | 2 +- exporters/zipkin/src/recordable.cc | 2 +- exporters/zipkin/test/zipkin_recordable_test.cc | 2 +- 5 files changed, 5 insertions(+), 4 deletions(-) diff --git a/ci/do_ci.sh b/ci/do_ci.sh index 62723fb5d3..0fefb9ffb4 100755 --- a/ci/do_ci.sh +++ b/ci/do_ci.sh @@ -30,6 +30,7 @@ if [[ "$1" == "cmake.test" ]]; then rm -rf * cmake -DCMAKE_BUILD_TYPE=Debug \ -DWITH_PROMETHEUS=ON \ + -DWITH_ZIPKIN=ON \ -DCMAKE_CXX_FLAGS="-Werror" \ "${SRC_DIR}" make diff --git a/exporters/zipkin/include/opentelemetry/exporters/zipkin/recordable.h b/exporters/zipkin/include/opentelemetry/exporters/zipkin/recordable.h index 989248932e..780aaa5bdf 100644 --- a/exporters/zipkin/include/opentelemetry/exporters/zipkin/recordable.h +++ b/exporters/zipkin/include/opentelemetry/exporters/zipkin/recordable.h @@ -36,7 +36,7 @@ class Recordable final : public sdk::trace::Recordable void AddLink(const opentelemetry::trace::SpanContext &span_context, const common::KeyValueIterable &attributes) noexcept override; - void SetStatus(trace::CanonicalCode code, nostd::string_view description) noexcept override; + void SetStatus(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/zipkin_exporter.h b/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h index 1a1a7561d5..196e5fc614 100644 --- a/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h +++ b/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h @@ -14,7 +14,7 @@ namespace exporter namespace zipkin { -constexpr std::string kZipkinEndpointDefault = "http://localhost:9411/api/v2/spans"; +const std::string kZipkinEndpointDefault = "http://localhost:9411/api/v2/spans"; /** * Struct to hold Zipkin exporter options. diff --git a/exporters/zipkin/src/recordable.cc b/exporters/zipkin/src/recordable.cc index 663d461259..04ce8b06da 100644 --- a/exporters/zipkin/src/recordable.cc +++ b/exporters/zipkin/src/recordable.cc @@ -153,7 +153,7 @@ void Recordable::AddLink(const opentelemetry::trace::SpanContext &span_context, // https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/sdk_exporters/zipkin.md } -void Recordable::SetStatus(trace::CanonicalCode code, nostd::string_view description) noexcept +void Recordable::SetStatus(trace::StatusCode code, nostd::string_view description) noexcept { span_["tags"]["otel.status_code"] = code; if (description.size()) diff --git a/exporters/zipkin/test/zipkin_recordable_test.cc b/exporters/zipkin/test/zipkin_recordable_test.cc index 2fbcc265c0..a0a234ef59 100644 --- a/exporters/zipkin/test/zipkin_recordable_test.cc +++ b/exporters/zipkin/test/zipkin_recordable_test.cc @@ -78,7 +78,7 @@ TEST(ZipkinSpanRecordable, SetDuration) TEST(ZipkinSpanRecordable, SetStatus) { opentelemetry::exporter::zipkin::Recordable rec; - trace::CanonicalCode code(trace::CanonicalCode::OK); + trace::StatusCode code(trace::StatusCode::kOk); nostd::string_view description = "For test"; json j_span = {{"tags", {{"otel.status_code", code}, {"otel.status_description", description}}}}; rec.SetStatus(code, description); From 18390cf7d8338f82da69e9f0ccededbe7867d1f6 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Fri, 12 Feb 2021 20:28:55 +0530 Subject: [PATCH 25/33] fix --- ci/do_ci.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/ci/do_ci.sh b/ci/do_ci.sh index 0fefb9ffb4..62723fb5d3 100755 --- a/ci/do_ci.sh +++ b/ci/do_ci.sh @@ -30,7 +30,6 @@ if [[ "$1" == "cmake.test" ]]; then rm -rf * cmake -DCMAKE_BUILD_TYPE=Debug \ -DWITH_PROMETHEUS=ON \ - -DWITH_ZIPKIN=ON \ -DCMAKE_CXX_FLAGS="-Werror" \ "${SRC_DIR}" make From b54304d1fd1854a2a971cdf1b1816fb7add97bfb Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Mon, 15 Feb 2021 12:05:33 +0530 Subject: [PATCH 26/33] fix --- .../include/opentelemetry/exporters/zipkin/zipkin_exporter.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h b/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h index 196e5fc614..610774cabe 100644 --- a/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h +++ b/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h @@ -77,10 +77,10 @@ class ZipkinExporter final : public trace_sdk::SpanExporter private: // The configuration options associated with this exporter. bool isShutdown_ = false; + ZipkinExporterOptions options_; std::shared_ptr http_client_; opentelemetry::ext::http::common::UrlParser url_parser_; nlohmann::json local_end_point_; - ZipkinExporterOptions options_; }; } // namespace zipkin } // namespace exporter From 653d084c9320cbf1061388ddf2eb2b11a5413b50 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Fri, 26 Feb 2021 00:00:24 +0530 Subject: [PATCH 27/33] fix annotations as per specs --- exporters/zipkin/src/recordable.cc | 18 +++++++++++++----- .../zipkin/test/zipkin_recordable_test.cc | 9 +++++---- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/exporters/zipkin/src/recordable.cc b/exporters/zipkin/src/recordable.cc index 04ce8b06da..dd36433f45 100644 --- a/exporters/zipkin/src/recordable.cc +++ b/exporters/zipkin/src/recordable.cc @@ -136,14 +136,22 @@ void Recordable::AddEvent(nostd::string_view name, core::SystemTimestamp timestamp, const common::KeyValueIterable &attributes) noexcept { - nlohmann::json annotations = nlohmann::json::object(); // empty object + nlohmann::json attrs = nlohmann::json::object(); // empty object attributes.ForEachKeyValue([&](nostd::string_view key, common::AttributeValue value) noexcept { - PopulateAttribute(annotations, key, value); + PopulateAttribute(attrs, key, value); return true; }); - span_["annotations"][name.data()]["value"] = annotations; - span_["annotations"]["timestamp"] = - std::chrono::duration_cast(timestamp.time_since_epoch()).count(); + + nlohmann::json annotation = {{"value", nlohmann::json::object({{name.data(), attrs}}).dump()}, + {"timestamp", std::chrono::duration_cast( + timestamp.time_since_epoch()) + .count()}}; + + if (!span_.contains("annotations")) + { + span_["annotations"] = nlohmann::json::array(); + } + span_["annotations"].push_back(annotation); } void Recordable::AddLink(const opentelemetry::trace::SpanContext &span_context, diff --git a/exporters/zipkin/test/zipkin_recordable_test.cc b/exporters/zipkin/test/zipkin_recordable_test.cc index a0a234ef59..31d384ace0 100644 --- a/exporters/zipkin/test/zipkin_recordable_test.cc +++ b/exporters/zipkin/test/zipkin_recordable_test.cc @@ -98,8 +98,9 @@ TEST(ZipkinSpanRecordable, AddEventDefault) uint64_t unix_event_time = std::chrono::duration_cast(event_time.time_since_epoch()).count(); - json j_span = {{"annotations", - {{name, {{"value", nlohmann::json::object()}}}, {"timestamp", unix_event_time}}}}; + json j_span = { + {"annotations", + {{{"value", json({{name, json::object()}}).dump()}, {"timestamp", unix_event_time}}}}}; EXPECT_EQ(rec.span(), j_span); } @@ -124,8 +125,8 @@ TEST(ZipkinSpanRecordable, AddEventWithAttributes) nlohmann::json j_span = { {"annotations", - {{"Test Event", {{"value", {{"attr1", 4}, {"attr2", 7}, {"attr3", 23}}}}}, - {"timestamp", unix_event_time}}}}; + {{{"value", json({{"Test Event", {{"attr1", 4}, {"attr2", 7}, {"attr3", 23}}}}).dump()}, + {"timestamp", unix_event_time}}}}}; EXPECT_EQ(rec.span(), j_span); } From 46337125ba51286c0981738e5b8a5b45a0c0f5db Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Wed, 3 Mar 2021 17:49:00 +0530 Subject: [PATCH 28/33] Update exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h Co-authored-by: Reiley Yang --- .../include/opentelemetry/exporters/zipkin/zipkin_exporter.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h b/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h index 610774cabe..e4c9a68f1d 100644 --- a/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h +++ b/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h @@ -44,7 +44,7 @@ class ZipkinExporter final : public trace_sdk::SpanExporter ZipkinExporter(); /** - * Create an ZipkinExporter using the given options. + * Create a ZipkinExporter using the given options. */ explicit ZipkinExporter(const ZipkinExporterOptions &options); From 359a385bdfe9fd4a2720e8d34593e03a30c6bf11 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Wed, 3 Mar 2021 17:52:31 +0530 Subject: [PATCH 29/33] Update exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h Co-authored-by: Reiley Yang --- .../include/opentelemetry/exporters/zipkin/zipkin_exporter.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h b/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h index e4c9a68f1d..b00bae1079 100644 --- a/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h +++ b/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h @@ -39,7 +39,7 @@ class ZipkinExporter final : public trace_sdk::SpanExporter { public: /** - * Create an ZipkinExporter using all default options. + * Create a ZipkinExporter using all default options. */ ZipkinExporter(); From 051fccf6a784384a04d81ecb5b2cb9cdea34a284 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Wed, 3 Mar 2021 18:08:37 +0530 Subject: [PATCH 30/33] fix comments --- examples/CMakeLists.txt | 1 + .../opentelemetry/exporters/zipkin/recordable.h | 16 ++++++++++++++++ .../exporters/zipkin/zipkin_exporter.h | 16 ++++++++++++++++ exporters/zipkin/src/recordable.cc | 16 ++++++++++++++++ exporters/zipkin/src/zipkin_exporter.cc | 17 ++++++++++++++++- exporters/zipkin/test/zipkin_recordable_test.cc | 15 +++++++++++++++ 6 files changed, 80 insertions(+), 1 deletion(-) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 22f6b9e838..803c6a8d4b 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -3,6 +3,7 @@ if(WITH_OTLP) endif() add_subdirectory(plugin) add_subdirectory(simple) +add_subdirectory(simple_zipkin) add_subdirectory(batch) add_subdirectory(metrics_simple) add_subdirectory(multithreaded) diff --git a/exporters/zipkin/include/opentelemetry/exporters/zipkin/recordable.h b/exporters/zipkin/include/opentelemetry/exporters/zipkin/recordable.h index 780aaa5bdf..3672911f70 100644 --- a/exporters/zipkin/include/opentelemetry/exporters/zipkin/recordable.h +++ b/exporters/zipkin/include/opentelemetry/exporters/zipkin/recordable.h @@ -1,3 +1,19 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #pragma once #include "nlohmann/json.hpp" diff --git a/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h b/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h index b00bae1079..31f6244bdf 100644 --- a/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h +++ b/exporters/zipkin/include/opentelemetry/exporters/zipkin/zipkin_exporter.h @@ -1,3 +1,19 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #pragma once #include "opentelemetry/exporters/zipkin/recordable.h" diff --git a/exporters/zipkin/src/recordable.cc b/exporters/zipkin/src/recordable.cc index dd36433f45..eda23dcf89 100644 --- a/exporters/zipkin/src/recordable.cc +++ b/exporters/zipkin/src/recordable.cc @@ -1,3 +1,19 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #include "opentelemetry/exporters/zipkin/recordable.h" #include diff --git a/exporters/zipkin/src/zipkin_exporter.cc b/exporters/zipkin/src/zipkin_exporter.cc index 1929fab7ee..cae2cd2246 100644 --- a/exporters/zipkin/src/zipkin_exporter.cc +++ b/exporters/zipkin/src/zipkin_exporter.cc @@ -1,3 +1,18 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ #include "opentelemetry/exporters/zipkin/zipkin_exporter.h" #include "opentelemetry/exporters/zipkin/recordable.h" #include "opentelemetry/ext/http/client/http_client_factory.h" @@ -88,4 +103,4 @@ void ZipkinExporter::InitializeLocalEndpoint() } // namespace zipkin } // namespace exporter -OPENTELEMETRY_END_NAMESPACE \ No newline at end of file +OPENTELEMETRY_END_NAMESPACE diff --git a/exporters/zipkin/test/zipkin_recordable_test.cc b/exporters/zipkin/test/zipkin_recordable_test.cc index 31d384ace0..d3c482df5c 100644 --- a/exporters/zipkin/test/zipkin_recordable_test.cc +++ b/exporters/zipkin/test/zipkin_recordable_test.cc @@ -1,3 +1,18 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ #include "opentelemetry/sdk/trace/recordable.h" #include "opentelemetry/sdk/trace/simple_processor.h" #include "opentelemetry/sdk/trace/span_data.h" From acb104042ebf3388c6359c82fa7225293198877c Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Wed, 3 Mar 2021 18:13:05 +0530 Subject: [PATCH 31/33] add changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ba42e5b013..bebce4736d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,8 @@ Increment the: ## [Unreleased] + * [EXPORTER] Added Zipkin Exporter. ([#471](https://github.com/open-telemetry/opentelemetry-cpp/pull/471)) + ## [0.2.0] 2021-03-02 * [SDK] Added `ForceFlush` to `TracerProvider`. ([#588](https://github.com/open-telemetry/opentelemetry-cpp/pull/588)). From f97e6caf75147a1dbe90a33445899498848e25eb Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Wed, 3 Mar 2021 18:29:26 +0530 Subject: [PATCH 32/33] fix md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bebce4736d..54b6d0df48 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,7 @@ Increment the: ## [Unreleased] - * [EXPORTER] Added Zipkin Exporter. ([#471](https://github.com/open-telemetry/opentelemetry-cpp/pull/471)) +* [EXPORTER] Added Zipkin Exporter. ([#471](https://github.com/open-telemetry/opentelemetry-cpp/pull/471)) ## [0.2.0] 2021-03-02 From fa6826ade383ac3e0d96fe68d2a89e328736c845 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Wed, 3 Mar 2021 18:34:06 +0530 Subject: [PATCH 33/33] fix --- examples/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 803c6a8d4b..22f6b9e838 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -3,7 +3,6 @@ if(WITH_OTLP) endif() add_subdirectory(plugin) add_subdirectory(simple) -add_subdirectory(simple_zipkin) add_subdirectory(batch) add_subdirectory(metrics_simple) add_subdirectory(multithreaded)