|
| 1 | +// Copyright 2023 The MathWorks, Inc. |
| 2 | + |
| 3 | +#include "opentelemetry/ext/http/client/http_client_factory.h" |
| 4 | +#include "opentelemetry/ext/http/common/url_parser.h" |
| 5 | +#include "opentelemetry/trace/semantic_conventions.h" |
| 6 | +#include "HttpTextMapCarrier.h" |
| 7 | + |
| 8 | +#include "opentelemetry/exporters/otlp/otlp_http_exporter_factory.h" |
| 9 | +#include "opentelemetry/sdk/trace/simple_processor_factory.h" |
| 10 | +#include "opentelemetry/sdk/trace/tracer_context.h" |
| 11 | +#include "opentelemetry/sdk/trace/tracer_context_factory.h" |
| 12 | +#include "opentelemetry/sdk/trace/tracer_provider_factory.h" |
| 13 | +#include "opentelemetry/trace/provider.h" |
| 14 | + |
| 15 | +#include "opentelemetry/context/propagation/global_propagator.h" |
| 16 | +#include "opentelemetry/context/propagation/text_map_propagator.h" |
| 17 | + |
| 18 | +#include <vector> |
| 19 | +#include "opentelemetry/ext/http/client/http_client.h" |
| 20 | +#include "opentelemetry/nostd/shared_ptr.h" |
| 21 | + |
| 22 | +namespace |
| 23 | +{ |
| 24 | + |
| 25 | +using namespace opentelemetry::trace; |
| 26 | +namespace http_client = opentelemetry::ext::http::client; |
| 27 | +namespace context = opentelemetry::context; |
| 28 | +namespace nostd = opentelemetry::nostd; |
| 29 | + |
| 30 | +void InitTracer() |
| 31 | +{ |
| 32 | + auto exporter = opentelemetry::exporter::otlp::OtlpHttpExporterFactory::Create(); |
| 33 | + auto processor = |
| 34 | + opentelemetry::sdk::trace::SimpleSpanProcessorFactory::Create(std::move(exporter)); |
| 35 | + std::vector<std::unique_ptr<opentelemetry::sdk::trace::SpanProcessor>> processors; |
| 36 | + processors.push_back(std::move(processor)); |
| 37 | + std::unique_ptr<opentelemetry::sdk::trace::TracerContext> context = |
| 38 | + opentelemetry::sdk::trace::TracerContextFactory::Create(std::move(processors)); |
| 39 | + std::shared_ptr<opentelemetry::trace::TracerProvider> provider = |
| 40 | + opentelemetry::sdk::trace::TracerProviderFactory::Create(std::move(context)); |
| 41 | + // Set the global trace provider |
| 42 | + opentelemetry::trace::Provider::SetTracerProvider(provider); |
| 43 | + |
| 44 | + // set global propagator |
| 45 | + opentelemetry::context::propagation::GlobalTextMapPropagator::SetGlobalPropagator( |
| 46 | + opentelemetry::nostd::shared_ptr<opentelemetry::context::propagation::TextMapPropagator>( |
| 47 | + new opentelemetry::trace::propagation::HttpTraceContext())); |
| 48 | +} |
| 49 | + |
| 50 | +opentelemetry::nostd::shared_ptr<opentelemetry::trace::Tracer> get_tracer(std::string tracer_name) |
| 51 | +{ |
| 52 | + auto provider = opentelemetry::trace::Provider::GetTracerProvider(); |
| 53 | + return provider->GetTracer(tracer_name); |
| 54 | +} |
| 55 | + |
| 56 | +void sendRequest(const std::string &url) |
| 57 | +{ |
| 58 | + auto http_client = http_client::HttpClientFactory::CreateSync(); |
| 59 | + // define input to post to destination |
| 60 | + std::vector<uint8_t> body; |
| 61 | + uint8_t magic_square_size = 3; // request 3x3 magic square |
| 62 | + body.push_back(magic_square_size); |
| 63 | + |
| 64 | + // start active span |
| 65 | + StartSpanOptions options; |
| 66 | + options.kind = SpanKind::kClient; // client |
| 67 | + opentelemetry::ext::http::common::UrlParser url_parser(url); |
| 68 | + |
| 69 | + std::string span_name = url_parser.path_; |
| 70 | + auto span = get_tracer("http-client") |
| 71 | + ->StartSpan(span_name, |
| 72 | + {{SemanticConventions::kUrlFull, url_parser.url_}, |
| 73 | + {SemanticConventions::kUrlScheme, url_parser.scheme_}, |
| 74 | + {SemanticConventions::kHttpRequestMethod, "POST"}}, |
| 75 | + options); |
| 76 | + auto scope = get_tracer("http-client")->WithActiveSpan(span); |
| 77 | + |
| 78 | + // inject current context into http header |
| 79 | + auto current_ctx = context::RuntimeContext::GetCurrent(); |
| 80 | + HttpTextMapCarrier<http_client::Headers> carrier; |
| 81 | + auto prop = context::propagation::GlobalTextMapPropagator::GetGlobalPropagator(); |
| 82 | + prop->Inject(carrier, current_ctx); |
| 83 | + |
| 84 | + // send http request |
| 85 | + http_client::Result result = http_client->Post(url, body, carrier.headers_); |
| 86 | + if (result) |
| 87 | + { |
| 88 | + // set span attributes |
| 89 | + auto status_code = result.GetResponse().GetStatusCode(); |
| 90 | + span->SetAttribute(SemanticConventions::kHttpResponseStatusCode, status_code); |
| 91 | + result.GetResponse().ForEachHeader( |
| 92 | + [&span](nostd::string_view header_name, nostd::string_view header_value) { |
| 93 | + span->SetAttribute("http.header." + std::string(header_name.data()), header_value); |
| 94 | + return true; |
| 95 | + }); |
| 96 | + |
| 97 | + if (status_code >= 400) |
| 98 | + { |
| 99 | + span->SetStatus(StatusCode::kError); |
| 100 | + } |
| 101 | + } |
| 102 | + else |
| 103 | + { |
| 104 | + span->SetStatus( |
| 105 | + StatusCode::kError, |
| 106 | + "Response Status :" + |
| 107 | + std::to_string( |
| 108 | + static_cast<typename std::underlying_type<http_client::SessionState>::type>( |
| 109 | + result.GetSessionState()))); |
| 110 | + } |
| 111 | + // end span and export data |
| 112 | + span->End(); |
| 113 | +} |
| 114 | + |
| 115 | +void CleanupTracer() |
| 116 | +{ |
| 117 | + std::shared_ptr<opentelemetry::trace::TracerProvider> none; |
| 118 | + opentelemetry::trace::Provider::SetTracerProvider(none); |
| 119 | +} |
| 120 | + |
| 121 | +} // namespace |
| 122 | + |
| 123 | +int main(int argc, char *argv[]) |
| 124 | +{ |
| 125 | + InitTracer(); |
| 126 | + constexpr char default_host[] = "localhost"; |
| 127 | + constexpr char default_path[] = "/mymagic/magic"; |
| 128 | + constexpr uint16_t default_port = 9910; |
| 129 | + uint16_t port; |
| 130 | + |
| 131 | + // The port the validation service listens to can be specified via the command line. |
| 132 | + if (argc > 1) |
| 133 | + { |
| 134 | + port = (uint16_t)(atoi(argv[1])); |
| 135 | + } |
| 136 | + else |
| 137 | + { |
| 138 | + port = default_port; |
| 139 | + } |
| 140 | + |
| 141 | + std::string url = "http://" + std::string(default_host) + ":" + std::to_string(port) + |
| 142 | + std::string(default_path); |
| 143 | + sendRequest(url); |
| 144 | + CleanupTracer(); |
| 145 | +} |
0 commit comments