From 2fce99434afcf282f8cc9b8510d70070efc32c6f Mon Sep 17 00:00:00 2001 From: Hablapatabla Date: Fri, 7 May 2021 21:41:32 -0400 Subject: [PATCH 01/16] Add simple gRPC example --- examples/CMakeLists.txt | 1 + examples/grpc/CMakeLists.txt | 62 ++++++ examples/grpc/README.md | 122 +++++++++++ examples/grpc/client.cc | 109 ++++++++++ .../grpc/experimental/greeter_interceptor.cc | 199 ++++++++++++++++++ examples/grpc/grpc_foo_lib/foo_split.cc | 53 +++++ examples/grpc/grpc_foo_lib/foo_split.h | 3 + examples/grpc/grpc_foo_lib/grpc_map_carrier.h | 28 +++ examples/grpc/protos/messages.proto | 15 ++ examples/grpc/server.cc | 122 +++++++++++ examples/grpc/tracer_common.h | 73 +++++++ 11 files changed, 787 insertions(+) create mode 100644 examples/grpc/CMakeLists.txt create mode 100644 examples/grpc/README.md create mode 100644 examples/grpc/client.cc create mode 100644 examples/grpc/experimental/greeter_interceptor.cc create mode 100644 examples/grpc/grpc_foo_lib/foo_split.cc create mode 100644 examples/grpc/grpc_foo_lib/foo_split.h create mode 100644 examples/grpc/grpc_foo_lib/grpc_map_carrier.h create mode 100644 examples/grpc/protos/messages.proto create mode 100644 examples/grpc/server.cc create mode 100644 examples/grpc/tracer_common.h diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 8aec6526a6..b1d7370178 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -8,3 +8,4 @@ add_subdirectory(metrics_simple) add_subdirectory(multithreaded) add_subdirectory(multi_processor) add_subdirectory(http) +add_subdirectory(grpc) diff --git a/examples/grpc/CMakeLists.txt b/examples/grpc/CMakeLists.txt new file mode 100644 index 0000000000..7f7688748b --- /dev/null +++ b/examples/grpc/CMakeLists.txt @@ -0,0 +1,62 @@ +find_package(gRPC) +find_package(Protobuf) + +if(NOT Protobuf_FOUND) + message(WARNING "Aborting grpc example build, protobuf not found.") +elseif(NOT gRPC_FOUND) + message(WARNING "Aborting grpc example build, grpc not found.") +else() + set(_PROTOBUF_PROTOC $) + set(_GRPC_GRPCPP gRPC::grpc++) + set(_GRPC_CPP_PLUGIN_EXECUTABLE $) + + include_directories( + ${CMAKE_SOURCE_DIR}/exporters/ostream/include + ${CMAKE_SOURCE_DIR}/ext/include ${CMAKE_SOURCE_DIR}/api/include/ + ${CMAKE_SOURCE_DIR/}) + + include_directories(${CMAKE_CURRENT_BINARY_DIR}/protos) + + get_filename_component( + hw_proto ${CMAKE_CURRENT_SOURCE_DIR}/protos/messages.proto ABSOLUTE) + get_filename_component(hw_proto_path "${hw_proto}" PATH) + + set(hw_proto_srcs "${CMAKE_CURRENT_BINARY_DIR}/messages.pb.cc") + set(hw_proto_hdrs "${CMAKE_CURRENT_BINARY_DIR}/messages.pb.h") + set(hw_grpc_srcs "${CMAKE_CURRENT_BINARY_DIR}/messages.grpc.pb.cc") + set(hw_grpc_hdrs "${CMAKE_CURRENT_BINARY_DIR}/messages.grpc.pb.h") + + add_custom_command( + OUTPUT "${hw_proto_srcs}" "${hw_proto_hdrs}" "${hw_grpc_srcs}" + "${hw_grpc_hdrs}" + COMMAND + ${_PROTOBUF_PROTOC} ARGS --grpc_out "${CMAKE_CURRENT_BINARY_DIR}" + --cpp_out "${CMAKE_CURRENT_BINARY_DIR}" -I "${hw_proto_path}" + --plugin=protoc-gen-grpc="${_GRPC_CPP_PLUGIN_EXECUTABLE}" "${hw_proto}" + DEPENDS "${hw_proto}") + + include_directories("${CMAKE_CURRENT_BINARY_DIR}") + + add_library(grpc_foo_library grpc_foo_lib/foo_split.cc) + + add_library(hw_grpc_proto ${hw_grpc_srcs} ${hw_grpc_hdrs} ${hw_proto_srcs} + ${hw_proto_hdrs}) + + target_link_libraries(hw_grpc_proto ${_REFLECTION} ${_GRPC_GRPCPP} + ${_PROTOBUF_LIBPROTOBUF}) + + foreach(_target client server) + add_executable(${_target} "${_target}.cc") + target_link_libraries( + ${_target} + hw_grpc_proto + grpc_foo_library + ${_REFLECTION} + ${_GRPC_GRPCPP} + ${_PROTOBUF_LIBPROTOBUF} + ${CMAKE_THREAD_LIBS_INIT} + ${CORE_RUNTIME_LIBS} + opentelemetry_trace + opentelemetry_exporter_ostream_span) + endforeach() +endif() diff --git a/examples/grpc/README.md b/examples/grpc/README.md new file mode 100644 index 0000000000..31541f576e --- /dev/null +++ b/examples/grpc/README.md @@ -0,0 +1,122 @@ +# OpenTelemetry C++ Example + +## gRPC + +This is a simple example that demonstrates tracing a gRPC request from client to server. The example shows several aspects of tracing such as: + +* Using the `TracerProvider` +* Implementing the TextMapCarrie +* Context injection/extraction +* Span Attributes +* Span Semantic Conventions +* Using the ostream exporte +* Nested spans +* W3c Trace Context Propagation (Very soon!) + +### Running the example + +1. The example uses gRPC C++ as well as Google's protocol buffers. Make sure you have +installed both of these packages on your system, in such a way that CMake would know +how to find them with this command: + +'''find_package(gRPC)''' + +If you install these with a package manager like '''brew''' or '''apt''', you should not need to do extra work. + +2. Build and Deploy the opentelementry-cpp as described in [INSTALL.md](../../INSTALL.md). Building the project will build all of the examples and create new folders containing their executables within the 'build' directory NOT the 'examples' directory. + +3. Start the server from your `build/examples/grpc` directory. Both the server and client are configured to use 8800 as the default port, but if you would like to use another port, you can specify that as an argument. + + ```console + $ ./server [port_num] + Server listening on port: 0.0.0.0:8800 + ``` + +4. In a separate terminal window, run the client to make a single request: + + ```console + $ ./client [port_num] + ``` + +5. You should see console exporter output for both the client and server sessions. + * Client console + + ```console + { + name : GreeterClient/Greet + trace_id : f898b8bca93936f112a56b710bb888eb + span_id : 8354bf34f7de06a0 + tracestate : + parent_span_id: 0000000000000000 + start : 1620434679192923000 + duration : 1571169 + description : + span kind : Client + status : Ok + attributes : + rpc.grpc.status_code: 0 + net.peer.port: 8800 + rpc.system: grpc + net.peer.ip: 0.0.0.0 + rpc.method: Greet + rpc.service: grpc-example.GreetService + events : + links : + } + ``` + + * Server console + + ```console + { + name : splitfunc + trace_id : 0836f1469dac75fddb57df13bcf33420 + span_id : 97b3f69fae5c0e15 + tracestate : + parent_span_id: 3d5fcaccc5617153 + start : 1620435268681957000 + duration : 38026 + description : + span kind : Internal + status : Unset + attributes : + events : + links : + } + + { + name : splitlib + trace_id : 0836f1469dac75fddb57df13bcf33420 + span_id : 3d5fcaccc5617153 + tracestate : + parent_span_id: a6aa48220c511354 + start : 1620435268681937000 + duration : 99145 + description : + span kind : Internal + status : Unset + attributes : + events : + links : + } + + { + name : GreeterService/Greet + trace_id : 0836f1469dac75fddb57df13bcf33420 + span_id : a6aa48220c511354 + tracestate : + parent_span_id: 0000000000000000 + start : 1620435268681893000 + duration : 178531 + description : + span kind : Serve + status : Ok + attributes : + rpc.grpc.status_code: 0 + rpc.method: Greet + rpc.service: GreeterService + rpc.system: grpc + events : + links : + } + ``` diff --git a/examples/grpc/client.cc b/examples/grpc/client.cc new file mode 100644 index 0000000000..9ca65de9ed --- /dev/null +++ b/examples/grpc/client.cc @@ -0,0 +1,109 @@ +#include "grpc_foo_lib/foo_split.h" +#include "grpc_foo_lib/grpc_map_carrier.h" +#include "messages.grpc.pb.h" +#include "tracer_common.h" + +#include +#include +#include + +using grpc::Channel; +using grpc::ClientContext; +using grpc::ClientReader; +using grpc::Status; + +using grpc_example::Greeter; +using grpc_example::GreetRequest; +using grpc_example::GreetResponse; + +namespace +{ +class GreeterClient +{ +public: + GreeterClient(std::shared_ptr channel) : stub_(Greeter::NewStub(channel)) {} + + std::string Greet(std::string ip, uint16_t port) + { + // Build gRPC Context objects and protobuf message containers + GreetRequest request; + GreetResponse response; + ClientContext context; + request.set_request("Nice to meet you!"); + // See tracer_common.h for this function + auto propagator = get_propagator(); + + opentelemetry::trace::StartSpanOptions options; + options.kind = opentelemetry::trace::SpanKind::kClient; + // Spans are only as useful as the information that you put in them. + // Even though this is a client service, it can still be useful to add + // as much data as possible. We add attributes for peer ip and port, both + // because it is required per OpenTelemetry's rpc semantic conventions, + // and because it could still be useful to a debugger in the future. + std::string span_name = "GreeterClient/Greet"; + auto span = get_tracer("grpc-client") + ->StartSpan(span_name, + {{"rpc.system", "grpc"}, + {"rpc.service", "grpc-example.GreetService"}, + {"rpc.method", "Greet"}, + {"net.peer.ip", ip}, + {"net.peer.port", port}, + {"rpc.grpc.status_code", 0}}, + options); + auto scope = get_tracer("grpc-client")->WithActiveSpan(span); + + gRPCMapCarrier carrier; + carrier.gRPCMapCarrier::Set("http.header.stub", "temporarily-stubbed"); + + opentelemetry::context::Context ctx1 = opentelemetry::context::Context{"current-span", span}; + opentelemetry::context::Context ctx2 = propagator->Extract(carrier, ctx1); + gRPCMapCarrier carrier2; + propagator->Inject(carrier2, ctx2); + + Status status = stub_->Greet(&context, request, &response); + if (status.ok()) + { + span->SetStatus(opentelemetry::trace::StatusCode::kOk); + // Make sure to end your spans! + span->End(); + return response.response(); + } + else + { + std::cout << status.error_code() << ": " << status.error_message() << std::endl; + span->SetStatus(opentelemetry::trace::StatusCode::kError); + // Make sure to end your spans! + span->End(); + return "RPC failed"; + } + } + +private: + std::unique_ptr stub_; +}; // GreeterClient class + +void RunClient(uint16_t port) +{ + GreeterClient greeter( + grpc::CreateChannel("0.0.0.0:" + std::to_string(port), grpc::InsecureChannelCredentials())); + std::string response = greeter.Greet("0.0.0.0", port); + std::cout << "grpc_server says: " << response << std::endl; +} +} // namespace + +int main(int argc, char **argv) +{ + initTracer(); + constexpr uint16_t default_port = 8800; + uint16_t port; + if (argc > 1) + { + port = atoi(argv[1]); + } + else + { + port = default_port; + } + RunClient(port); + return 0; +} diff --git a/examples/grpc/experimental/greeter_interceptor.cc b/examples/grpc/experimental/greeter_interceptor.cc new file mode 100644 index 0000000000..b72e8ef3fd --- /dev/null +++ b/examples/grpc/experimental/greeter_interceptor.cc @@ -0,0 +1,199 @@ +#include "messages.grpc.pb.h" +#include "tracer_common.h" + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +using grpc::Server; +using grpc::ServerBuilder; +using grpc::ServerContext; +using grpc::ServerWriter; +using grpc::Status; + +using grpc_example::Greeter; +using grpc_example::GreetRequest; +using grpc_example::GreetResponse; + +class GreeterInterceptor : public grpc::experimental::Intercepto +{ +public: + GreeterInterceptor(grpc::experimental::ServerRpcInfo *info) + { + info_ = info; + const char *method = info->method(); + grpc::experimental::ServerRpcInfo::Type type = info->type(); + } + + void Intercept(grpc::experimental::InterceptorBatchMethods *methods) override + { + if (methods->QueryInterceptionHookPoint( + grpc::experimental::InterceptionHookPoints::PRE_SEND_INITIAL_METADATA)) + { + auto *map = methods->GetSendInitialMetadata(); + std::cout << "PRE_SEND_INITIAL_METADATA SEND_INITIAL_METADATA ELEMENTS: " << std::endl; + + for (const auto &pair : *map) + std::cout << pair.first << " : " << pair.second << std::endl; + } + + if (methods->QueryInterceptionHookPoint( + grpc::experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) + { + GreetRequest req; + auto *buffer = methods->GetSerializedSendMessage(); + auto copied_buffer = *buffer; + size_t size = copied_buffer.Length(); + std::cout << "PRE_SEND_MESSAGE: Byte buffer size: " << size << std::endl; + } + + if (methods->QueryInterceptionHookPoint( + grpc::experimental::InterceptionHookPoints::PRE_SEND_STATUS)) + { + auto *map = methods->GetSendTrailingMetadata(); + std::cout << "PRE_SEND_STATUS SEND_TRAILING_METADATA ELEMENTS: " << std::endl; + + for (const auto &pair : *map) + std::cout << pair.first << " : " << pair.second << std::endl; + } + if (methods->QueryInterceptionHookPoint( + grpc::experimental::InterceptionHookPoints::POST_RECV_INITIAL_METADATA)) + { + auto *map = methods->GetRecvInitialMetadata(); + std::cout << "POST_RECV_INITIAL_METADATA RECV_INITIAL_METADATA ELEMENTS: " << std::endl; + + for (const auto &pair : *map) + std::cout << pair.first << " : " << pair.second << std::endl; + } + if (methods->QueryInterceptionHookPoint( + grpc::experimental::InterceptionHookPoints::POST_RECV_MESSAGE)) + { + GreetResponse *resp = static_cast(methods->GetRecvMessage()); + std::cout << "Response: " << resp->response() << std::endl; + } + if (methods->QueryInterceptionHookPoint( + grpc::experimental::InterceptionHookPoints::POST_RECV_STATUS)) + { + auto *map = methods->GetRecvTrailingMetadata(); + std::cout << "POST_RECV_STATUS RECV_TRAILING_METADATA ELEMENTS: " << std::endl; + + for (const auto &pair : *map) + std::cout << pair.first << " : " << pair.second << std::endl; + } + if (methods->QueryInterceptionHookPoint( + grpc::experimental::InterceptionHookPoints::POST_RECV_CLOSE)) + {} + methods->Proceed(); + } + +private: + grpc::experimental::ServerRpcInfo *info_; +}; + +class GreeterInterceptorFactory : public grpc::experimental::ServerInterceptorFactoryInterface +{ +public: + virtual grpc::experimental::Interceptor *CreateServerInterceptor( + grpc::experimental::ServerRpcInfo *info) override + { + return new GreeterInterceptor(info); + } +}; + +class GreeterServer final : public Greeter::Service +{ +public: + Status Greet(ServerContext *context, + const GreetRequest *request, + GreetResponse *response) override + { + opentelemetry::trace::StartSpanOptions options; + options.kind = opentelemetry::trace::SpanKind::kServer; + std::string peer_name = context->peer(); + std::string peer_name_copy = peer_name; + std::string delim = ":"; + std::vector peer_name_attributes{}; + std::cout << "peer name: " << peer_name << std::endl; + ; + size_t idx; + while ((idx = peer_name_copy.find(delim)) != std::string::npos) + { + peer_name_attributes.push_back(peer_name_copy.substr(0, idx)); + peer_name_copy.erase(0, idx + delim.length()); + } + for (std::string s : peer_name_attributes) + { + std::cout << s << std::endl; + } + + std::string span_name = "grpc server"; + auto span = get_tracer("grpc-server") + ->StartSpan(span_name, + {{"rpc.system", "grpc"}, + {"rpc.service", "grpc-example.GreetService"}, + {"rpc.method", "Greet"}, + {"net.peer.ip", peer_name_attributes.at(1)}, + {"net.peer.port", peer_name_attributes.at(2)}, + {"rpc.grpc.status_code", "0"}}, + options); + auto scope = get_tracer("grpc-server")->WithActiveSpan(span); + + std::string req = request->request(); + std::cout << "grpc_client says: " << req << std::endl; + std::string message = "The pleasure is mine."; + response->set_response(message); + + span->End(); + return Status::OK; + } +}; + +void RunServer(uint16_t port) +{ + std::string address("0.0.0.0:" + std::to_string(port)); + GreeterServer service; + ServerBuilder builder; + + builder.RegisterService(&service); + builder.AddListeningPort(address, grpc::InsecureServerCredentials()); + std::vector> creators; + creators.reserve(1); + creators.push_back(std::unique_ptr(new GreeterInterceptorFactory())); + builder.experimental().SetInterceptorCreators(std::move(creators)); + + std::unique_ptr server(builder.BuildAndStart()); + std::cout << "Server listening on port: " << address << std::endl; + server->Wait(); + server->Shutdown(); +} + +int main(int argc, char **argv) +{ + initTracer(); + constexpr uint16_t default_port = 8800; + uint16_t port; + if (argc > 1) + { + port = atoi(argv[1]); + } + else + { + port = default_port; + } + + RunServer(port); + return 0; +} diff --git a/examples/grpc/grpc_foo_lib/foo_split.cc b/examples/grpc/grpc_foo_lib/foo_split.cc new file mode 100644 index 0000000000..cd9ba8348d --- /dev/null +++ b/examples/grpc/grpc_foo_lib/foo_split.cc @@ -0,0 +1,53 @@ +#include +#include +#include "../tracer_common.h" +#include "grpc_map_carrier.h" +#include "opentelemetry/trace/provider.h" + +namespace +{ +std::vector mysplit(std::string s, char delim) +{ + auto propagator = get_propagator(); + + gRPCMapCarrier carrier; + carrier.gRPCMapCarrier::Set("http.header.stub", "temporarily-stubbed"); + auto span = get_tracer("grpc-lib")->StartSpan("splitfunc"); + auto scope = get_tracer("grpc-lib")->WithActiveSpan(span); + + std::vector token_container{}; + std::stringstream ss(s); + std::string token; + + while (std::getline(ss, token, delim)) + token_container.push_back(token); + + opentelemetry::context::Context ctx1 = opentelemetry::context::Context{"current-span", span}; + opentelemetry::context::Context ctx2 = propagator->Extract(carrier, ctx1); + gRPCMapCarrier carrier2; + propagator->Inject(carrier2, ctx2); + + span->End(); + return token_container; +} +} // namespace + +std::vector split(std::string s, char delim) +{ + auto propagator = get_propagator(); + + gRPCMapCarrier carrier; + carrier.gRPCMapCarrier::Set("http.header.stub", "temporarily-stubbed"); + + auto span = get_tracer("grpc-lib")->StartSpan("splitlib"); + auto scope = get_tracer("grpc-lib")->WithActiveSpan(span); + opentelemetry::context::Context ctx1 = opentelemetry::context::Context{"current-span", span}; + opentelemetry::context::Context ctx2 = propagator->Extract(carrier, ctx1); + gRPCMapCarrier carrier2; + propagator->Inject(carrier2, ctx2); + + std::vector v = mysplit(s, delim); + + span->End(); + return v; +} diff --git a/examples/grpc/grpc_foo_lib/foo_split.h b/examples/grpc/grpc_foo_lib/foo_split.h new file mode 100644 index 0000000000..fb2710dade --- /dev/null +++ b/examples/grpc/grpc_foo_lib/foo_split.h @@ -0,0 +1,3 @@ +#pragma once + +std::vector split(std::string s, char delim); diff --git a/examples/grpc/grpc_foo_lib/grpc_map_carrier.h b/examples/grpc/grpc_foo_lib/grpc_map_carrier.h new file mode 100644 index 0000000000..3a6a0b5230 --- /dev/null +++ b/examples/grpc/grpc_foo_lib/grpc_map_carrier.h @@ -0,0 +1,28 @@ +#pragma once +#include "opentelemetry/context/context.h" +#include "opentelemetry/context/propagation/text_map_propagator.h" +#include "opentelemetry/nostd/string_view.h" + +class gRPCMapCarrier : public opentelemetry::context::propagation::TextMapCarrie +{ +private: + std::map headers_; + +public: + virtual opentelemetry::nostd::string_view Get( + opentelemetry::nostd::string_view key) const noexcept override + { + auto it = headers_.find(std::string(key)); + if (it != headers_.end()) + { + return opentelemetry::nostd::string_view(it->second); + } + return ""; + } + + virtual void Set(opentelemetry::nostd::string_view key, + opentelemetry::nostd::string_view value) noexcept override + { + headers_[std::string(key)] = std::string(value); + } +}; diff --git a/examples/grpc/protos/messages.proto b/examples/grpc/protos/messages.proto new file mode 100644 index 0000000000..e0d69959bf --- /dev/null +++ b/examples/grpc/protos/messages.proto @@ -0,0 +1,15 @@ +syntax = "proto3"; + +package grpc_example; + +service Greeter { + rpc Greet(GreetRequest) returns (GreetResponse) {} +} + +message GreetRequest { + string request = 1; +} + +message GreetResponse { + string response = 1; +} diff --git a/examples/grpc/server.cc b/examples/grpc/server.cc new file mode 100644 index 0000000000..5c0d742f15 --- /dev/null +++ b/examples/grpc/server.cc @@ -0,0 +1,122 @@ +#include "grpc_foo_lib/foo_split.h" +#include "grpc_foo_lib/grpc_map_carrier.h" +#include "messages.grpc.pb.h" +#include "tracer_common.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +using grpc::Server; +using grpc::ServerBuilder; +using grpc::ServerContext; +using grpc::ServerWriter; +using grpc::Status; + +using grpc_example::Greeter; +using grpc_example::GreetRequest; +using grpc_example::GreetResponse; + +namespace +{ +class GreeterServer final : public Greeter::Service +{ +public: + Status Greet(ServerContext *context, + const GreetRequest *request, + GreetResponse *response) override + { + // Get global propagator to move spans across rpc boundaries + auto propagator = get_propagator(); + // Create a SpanOptions object and set the kind to Server to inform OpenTel. + opentelemetry::trace::StartSpanOptions options; + options.kind = opentelemetry::trace::SpanKind::kServer; + // Build a new span from a tracer, start, and activate it. When adding + // attributes to spans, be sure to follow the OpenTelemetry Semantic + // Conventions that are relevant to your project as closely as possible + // Some protocols/patterns that have specified conventions: + // RPC, HTTP, AWS Lambda, Database, Exceptions, etc. + std::string span_name = "GreeterService/Greet"; + auto span = get_tracer("grpc-server") + ->StartSpan(span_name, + {{"rpc.system", "grpc"}, + {"rpc.service", "GreeterService"}, + {"rpc.method", "Greet"}, + {"rpc.grpc.status_code", 0}}, + options); + auto scope = get_tracer("grpc-server")->WithActiveSpan(span); + + // Fetch and parse whatever HTTP headers we can from the gRPC request. + std::string peer_name = context->peer(); + std::vector peer_name_attributes = split(peer_name, ':'); + + // Create a text map carrier and fill it with other headers. gRPC runs on + // HTTP 2, so we add all the HTTP headers that we just extracted + gRPCMapCarrier carrier; + carrier.gRPCMapCarrier::Set("net.ip.version", peer_name_attributes.at(0)); + carrier.gRPCMapCarrier::Set("net.peer.ip", peer_name_attributes.at(1)); + carrier.gRPCMapCarrier::Set("net.peer.port", peer_name_attributes.at(2)); + + // Build a context and add a k-v pair for the current span, so OpenTelemetry + // can know the causal relationship between spans, and can infer the parent + // -> child hierarchy of spans + opentelemetry::context::Context ctx1 = opentelemetry::context::Context{"current-span", span}; + // Because contexts are immutable, we build another one and extract the contents + // of our carrier with extra header information, and ctx1 which has our current span + opentelemetry::context::Context ctx2 = propagator->Extract(carrier, ctx1); + // Build another carrier to hold the combination of all of our span data + gRPCMapCarrier carrier2; + propagator->Inject(carrier2, ctx2); + + std::string req = request->request(); + std::cout << std::endl << "grpc_client says: " << req << std::endl; + std::string message = "The pleasure is mine."; + response->set_response(message); + + span->SetStatus(opentelemetry::trace::StatusCode::kOk); + // Make sure to end your spans! + span->End(); + return Status::OK; + } +}; // GreeterServer class + +void RunServer(uint16_t port) +{ + std::string address("0.0.0.0:" + std::to_string(port)); + GreeterServer service; + ServerBuilder builder; + + builder.RegisterService(&service); + builder.AddListeningPort(address, grpc::InsecureServerCredentials()); + + std::unique_ptr server(builder.BuildAndStart()); + std::cout << "Server listening on port: " << address << std::endl; + server->Wait(); + server->Shutdown(); +} +} // namespace + +int main(int argc, char **argv) +{ + initTracer(); + constexpr uint16_t default_port = 8800; + uint16_t port; + if (argc > 1) + { + port = atoi(argv[1]); + } + else + { + port = default_port; + } + + RunServer(port); + return 0; +} diff --git a/examples/grpc/tracer_common.h b/examples/grpc/tracer_common.h new file mode 100644 index 0000000000..6f4b4c4856 --- /dev/null +++ b/examples/grpc/tracer_common.h @@ -0,0 +1,73 @@ +#pragma once +#include "opentelemetry/exporters/ostream/span_exporter.h" +#include "opentelemetry/sdk/trace/simple_processor.h" +#include "opentelemetry/sdk/trace/tracer_provider.h" +#include "opentelemetry/trace/provider.h" + +#include "opentelemetry/context/propagation/global_propagator.h" +#include "opentelemetry/context/propagation/text_map_propagator.h" +#include "opentelemetry/context/runtime_context.h" +#include "opentelemetry/trace/propagation/http_trace_context.h" +#include "opentelemetry/trace/scope.h" + +#include +#include +#include +#include "opentelemetry/ext/http/client/http_client.h" +#include "opentelemetry/nostd/shared_ptr.h" + +namespace +{ +inline nostd::shared_ptr GetSpanFromContext( + const opentelemetry::context::Context &context) +{ + opentelemetry::context::ContextValue span = context.GetValue(opentelemetry::trace::kSpanKey); + if (nostd::holds_alternative>(span)) + { + return nostd::get>(span); + } + static nostd::shared_ptr invalid_span{ + new opentelemetry::trace::DefaultSpan(opentelemetry::trace::SpanContext::GetInvalid())}; + return invalid_span; +} + +void initTracer() +{ + auto exporter = std::unique_ptr( + new opentelemetry::exporter::trace::OStreamSpanExporter); + auto processor = std::unique_ptr( + new sdktrace::SimpleSpanProcessor(std::move(exporter))); + std::vector> processors; + processors.push_back(std::move(processor)); + // Default is an always-on sampler. + auto context = std::make_shared(std::move(processors)); + auto provider = nostd::shared_ptr( + new sdktrace::TracerProvider(context)); + // Set the global trace provide + opentelemetry::trace::Provider::SetTracerProvider(provider); + + // set global propagato + opentelemetry::context::propagation::GlobalTextMapPropagator::SetGlobalPropagator( + nostd::shared_ptr( + new opentelemetry::trace::propagation::HttpTraceContext())); +} + +nostd::shared_ptr get_tracer(std::string tracer_name) +{ + auto provider = opentelemetry::trace::Provider::GetTracerProvider(); + return provider->GetTracer(tracer_name); +} + +// This function idempotently sets the global propagator and returns it to remove +// boilerplate from gRPC example services/library +nostd::shared_ptr get_propagator() +{ + opentelemetry::context::propagation::GlobalTextMapPropagator::SetGlobalPropagator( + opentelemetry::nostd::shared_ptr( + new opentelemetry::trace::propagation::HttpTraceContext())); + auto propagator = + opentelemetry::context::propagation::GlobalTextMapPropagator::GetGlobalPropagator(); + return propagator; +} + +} // namespace From 6ebb25a6b2472121df05c297f4150e2f9af907d5 Mon Sep 17 00:00:00 2001 From: Hablapatabla Date: Fri, 7 May 2021 22:17:57 -0400 Subject: [PATCH 02/16] Restore errors introduced by format.sh. Explicitly include header file in grpc_map_carrier --- examples/grpc/experimental/greeter_interceptor.cc | 2 +- examples/grpc/grpc_foo_lib/foo_split.cc | 1 + examples/grpc/grpc_foo_lib/grpc_map_carrier.h | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/grpc/experimental/greeter_interceptor.cc b/examples/grpc/experimental/greeter_interceptor.cc index b72e8ef3fd..9d5b98ecb0 100644 --- a/examples/grpc/experimental/greeter_interceptor.cc +++ b/examples/grpc/experimental/greeter_interceptor.cc @@ -28,7 +28,7 @@ using grpc_example::Greeter; using grpc_example::GreetRequest; using grpc_example::GreetResponse; -class GreeterInterceptor : public grpc::experimental::Intercepto +class GreeterInterceptor : public grpc::experimental::Interceptor { public: GreeterInterceptor(grpc::experimental::ServerRpcInfo *info) diff --git a/examples/grpc/grpc_foo_lib/foo_split.cc b/examples/grpc/grpc_foo_lib/foo_split.cc index cd9ba8348d..773d67c03a 100644 --- a/examples/grpc/grpc_foo_lib/foo_split.cc +++ b/examples/grpc/grpc_foo_lib/foo_split.cc @@ -3,6 +3,7 @@ #include "../tracer_common.h" #include "grpc_map_carrier.h" #include "opentelemetry/trace/provider.h" +#include "foo_split.h" namespace { diff --git a/examples/grpc/grpc_foo_lib/grpc_map_carrier.h b/examples/grpc/grpc_foo_lib/grpc_map_carrier.h index 3a6a0b5230..3d86dada2f 100644 --- a/examples/grpc/grpc_foo_lib/grpc_map_carrier.h +++ b/examples/grpc/grpc_foo_lib/grpc_map_carrier.h @@ -3,7 +3,7 @@ #include "opentelemetry/context/propagation/text_map_propagator.h" #include "opentelemetry/nostd/string_view.h" -class gRPCMapCarrier : public opentelemetry::context::propagation::TextMapCarrie +class gRPCMapCarrier : public opentelemetry::context::propagation::TextMapCarrier { private: std::map headers_; From c3d5bfa74daf18e5a4b2d42c3a371217f5d01453 Mon Sep 17 00:00:00 2001 From: Hablapatabla Date: Sat, 8 May 2021 16:39:51 -0400 Subject: [PATCH 03/16] Implement Lalit's proposed changes in PR #729. --- examples/grpc/README.md | 6 ++--- examples/grpc/client.cc | 27 +++++++++---------- .../grpc/experimental/greeter_interceptor.cc | 3 ++- examples/grpc/grpc_foo_lib/foo_split.cc | 26 ++++++++---------- examples/grpc/grpc_foo_lib/grpc_map_carrier.h | 1 + 5 files changed, 29 insertions(+), 34 deletions(-) diff --git a/examples/grpc/README.md b/examples/grpc/README.md index 31541f576e..bf83072456 100644 --- a/examples/grpc/README.md +++ b/examples/grpc/README.md @@ -2,14 +2,14 @@ ## gRPC -This is a simple example that demonstrates tracing a gRPC request from client to server. The example shows several aspects of tracing such as: +This is a simple example that demonstrates tracing a gRPC request from client to server. There is an experimental directory in this example - the code within has been commented out to prevent any conflicts. The example shows several aspects of tracing such as: * Using the `TracerProvider` -* Implementing the TextMapCarrie +* Implementing the TextMapCarrier * Context injection/extraction * Span Attributes * Span Semantic Conventions -* Using the ostream exporte +* Using the ostream exporter * Nested spans * W3c Trace Context Propagation (Very soon!) diff --git a/examples/grpc/client.cc b/examples/grpc/client.cc index 9ca65de9ed..bf977cb030 100644 --- a/examples/grpc/client.cc +++ b/examples/grpc/client.cc @@ -41,29 +41,25 @@ class GreeterClient // because it is required per OpenTelemetry's rpc semantic conventions, // and because it could still be useful to a debugger in the future. std::string span_name = "GreeterClient/Greet"; - auto span = get_tracer("grpc-client") - ->StartSpan(span_name, - {{"rpc.system", "grpc"}, - {"rpc.service", "grpc-example.GreetService"}, - {"rpc.method", "Greet"}, - {"net.peer.ip", ip}, - {"net.peer.port", port}, - {"rpc.grpc.status_code", 0}}, - options); - auto scope = get_tracer("grpc-client")->WithActiveSpan(span); + auto span = get_tracer("grpc")->StartSpan(span_name, + {{"rpc.system", "grpc"}, + {"rpc.service", "grpc-example.GreetService"}, + {"rpc.method", "Greet"}, + {"net.peer.ip", ip}, + {"net.peer.port", port}}, + options); + auto scope = get_tracer("grpc")->WithActiveSpan(span); gRPCMapCarrier carrier; carrier.gRPCMapCarrier::Set("http.header.stub", "temporarily-stubbed"); - - opentelemetry::context::Context ctx1 = opentelemetry::context::Context{"current-span", span}; - opentelemetry::context::Context ctx2 = propagator->Extract(carrier, ctx1); - gRPCMapCarrier carrier2; - propagator->Inject(carrier2, ctx2); + opentelemetry::context::Context ctx = opentelemetry::context::Context{"current-span", span}; + propagator->Inject(carrier, ctx); Status status = stub_->Greet(&context, request, &response); if (status.ok()) { span->SetStatus(opentelemetry::trace::StatusCode::kOk); + span->SetAttribute("rpc.grpc.status_code", status.error_code()); // Make sure to end your spans! span->End(); return response.response(); @@ -72,6 +68,7 @@ class GreeterClient { std::cout << status.error_code() << ": " << status.error_message() << std::endl; span->SetStatus(opentelemetry::trace::StatusCode::kError); + span->SetAttribute("rpc.grpc.status_code", status.error_code()); // Make sure to end your spans! span->End(); return "RPC failed"; diff --git a/examples/grpc/experimental/greeter_interceptor.cc b/examples/grpc/experimental/greeter_interceptor.cc index 9d5b98ecb0..94118137f3 100644 --- a/examples/grpc/experimental/greeter_interceptor.cc +++ b/examples/grpc/experimental/greeter_interceptor.cc @@ -1,4 +1,4 @@ -#include "messages.grpc.pb.h" +/*#include "messages.grpc.pb.h" #include "tracer_common.h" #include @@ -197,3 +197,4 @@ int main(int argc, char **argv) RunServer(port); return 0; } +*/ \ No newline at end of file diff --git a/examples/grpc/grpc_foo_lib/foo_split.cc b/examples/grpc/grpc_foo_lib/foo_split.cc index 773d67c03a..119b2544fe 100644 --- a/examples/grpc/grpc_foo_lib/foo_split.cc +++ b/examples/grpc/grpc_foo_lib/foo_split.cc @@ -1,8 +1,3 @@ -#include -#include -#include "../tracer_common.h" -#include "grpc_map_carrier.h" -#include "opentelemetry/trace/provider.h" #include "foo_split.h" namespace @@ -13,8 +8,8 @@ std::vector mysplit(std::string s, char delim) gRPCMapCarrier carrier; carrier.gRPCMapCarrier::Set("http.header.stub", "temporarily-stubbed"); - auto span = get_tracer("grpc-lib")->StartSpan("splitfunc"); - auto scope = get_tracer("grpc-lib")->WithActiveSpan(span); + auto span = get_tracer("grpc")->StartSpan("splitfunc"); + auto scope = get_tracer("grpc")->WithActiveSpan(span); std::vector token_container{}; std::stringstream ss(s); @@ -24,9 +19,9 @@ std::vector mysplit(std::string s, char delim) token_container.push_back(token); opentelemetry::context::Context ctx1 = opentelemetry::context::Context{"current-span", span}; - opentelemetry::context::Context ctx2 = propagator->Extract(carrier, ctx1); - gRPCMapCarrier carrier2; - propagator->Inject(carrier2, ctx2); + opentelemetry::context::Context ctx2 = opentelemetry::context::RuntimeContext::GetCurrent(); + propagator->Inject(carrier, ctx1); + propagator->Inject(carrier, ctx2); span->End(); return token_container; @@ -40,12 +35,13 @@ std::vector split(std::string s, char delim) gRPCMapCarrier carrier; carrier.gRPCMapCarrier::Set("http.header.stub", "temporarily-stubbed"); - auto span = get_tracer("grpc-lib")->StartSpan("splitlib"); - auto scope = get_tracer("grpc-lib")->WithActiveSpan(span); + auto span = get_tracer("grpc")->StartSpan("splitlib"); + auto scope = get_tracer("grpc")->WithActiveSpan(span); + opentelemetry::context::Context ctx1 = opentelemetry::context::Context{"current-span", span}; - opentelemetry::context::Context ctx2 = propagator->Extract(carrier, ctx1); - gRPCMapCarrier carrier2; - propagator->Inject(carrier2, ctx2); + opentelemetry::context::Context ctx2 = opentelemetry::context::RuntimeContext::GetCurrent(); + propagator->Inject(carrier, ctx1); + propagator->Inject(carrier, ctx2); std::vector v = mysplit(s, delim); diff --git a/examples/grpc/grpc_foo_lib/grpc_map_carrier.h b/examples/grpc/grpc_foo_lib/grpc_map_carrier.h index 3d86dada2f..1804a338b0 100644 --- a/examples/grpc/grpc_foo_lib/grpc_map_carrier.h +++ b/examples/grpc/grpc_foo_lib/grpc_map_carrier.h @@ -1,4 +1,5 @@ #pragma once +#include #include "opentelemetry/context/context.h" #include "opentelemetry/context/propagation/text_map_propagator.h" #include "opentelemetry/nostd/string_view.h" From bb178cdfcc510fb82c55094412eb26c09f069d4d Mon Sep 17 00:00:00 2001 From: Hablapatabla Date: Mon, 10 May 2021 15:29:32 -0400 Subject: [PATCH 04/16] Implement client-server propagation, except it doesn't work. Commit to pull changes and try again --- examples/grpc/client.cc | 11 +++++--- examples/grpc/grpc_foo_lib/foo_split.h | 6 +++++ examples/grpc/server.cc | 36 ++++++++++++++++---------- 3 files changed, 35 insertions(+), 18 deletions(-) diff --git a/examples/grpc/client.cc b/examples/grpc/client.cc index bf977cb030..0ea9168f41 100644 --- a/examples/grpc/client.cc +++ b/examples/grpc/client.cc @@ -49,12 +49,15 @@ class GreeterClient {"net.peer.port", port}}, options); auto scope = get_tracer("grpc")->WithActiveSpan(span); - + // Text map-style carrier for the propagator. Include other relevant information here. gRPCMapCarrier carrier; carrier.gRPCMapCarrier::Set("http.header.stub", "temporarily-stubbed"); - opentelemetry::context::Context ctx = opentelemetry::context::Context{"current-span", span}; - propagator->Inject(carrier, ctx); - + // The current runtime context has information about the currently active span. + // We need to add that to our carrier so that the server can extract it later, + // enabling the span hierarchy. + auto current_ctx = opentelemetry::context::RuntimeContext::GetCurrent(); + propagator->Inject(carrier, current_ctx); + // Send request to server Status status = stub_->Greet(&context, request, &response); if (status.ok()) { diff --git a/examples/grpc/grpc_foo_lib/foo_split.h b/examples/grpc/grpc_foo_lib/foo_split.h index fb2710dade..9a0be41dcb 100644 --- a/examples/grpc/grpc_foo_lib/foo_split.h +++ b/examples/grpc/grpc_foo_lib/foo_split.h @@ -1,3 +1,9 @@ #pragma once +#include +#include +#include +#include "../tracer_common.h" +#include "grpc_map_carrier.h" +#include "opentelemetry/trace/provider.h" std::vector split(std::string s, char delim); diff --git a/examples/grpc/server.cc b/examples/grpc/server.cc index 5c0d742f15..271fa4b05d 100644 --- a/examples/grpc/server.cc +++ b/examples/grpc/server.cc @@ -38,6 +38,23 @@ class GreeterServer final : public Greeter::Service // Create a SpanOptions object and set the kind to Server to inform OpenTel. opentelemetry::trace::StartSpanOptions options; options.kind = opentelemetry::trace::SpanKind::kServer; + // Create a text map carrier for our propagator. This carrier holds all of our + // information that needs to be propagated. We instantiate our carrier here as + // in your systems you will probably have information to fill it with before + // even starting your span, maybe your client's http headers. There is no way + // to get any carrier-relevant information at this point without doing work that + // we want to capture in a span, but we include the definition at this point to fit + // real-life scenarios + gRPCMapCarrier carrier; + // The current RuntimeContext should contain the currently active span, which is from + // the client side. To implement the span hierarchy, we need to fetch that span from + // the RuntimeContext so that we can set it as the parent of our new span + auto current_ctx = opentelemetry::context::RuntimeContext::GetCurrent(); + // We want a new context that will have the information that we 'could' have placed + // in the carrier already, as well as the RuntimeContext which has our parent-span + // information. Contexts are immutable, so we need to make a new one + auto new_ctx = propagator->Extract(carrier, current_ctx); + options.parent = GetSpanFromContext(new_ctx)->GetContext(); // Build a new span from a tracer, start, and activate it. When adding // attributes to spans, be sure to follow the OpenTelemetry Semantic // Conventions that are relevant to your project as closely as possible @@ -54,31 +71,22 @@ class GreeterServer final : public Greeter::Service auto scope = get_tracer("grpc-server")->WithActiveSpan(span); // Fetch and parse whatever HTTP headers we can from the gRPC request. + span->AddEvent("Processing client attributes"); std::string peer_name = context->peer(); std::vector peer_name_attributes = split(peer_name, ':'); - // Create a text map carrier and fill it with other headers. gRPC runs on - // HTTP 2, so we add all the HTTP headers that we just extracted - gRPCMapCarrier carrier; + // Fill the carrier with other headers. gRPC runs on HTTP 2, so we add all + // of the HTTP headers that we just extracted carrier.gRPCMapCarrier::Set("net.ip.version", peer_name_attributes.at(0)); carrier.gRPCMapCarrier::Set("net.peer.ip", peer_name_attributes.at(1)); carrier.gRPCMapCarrier::Set("net.peer.port", peer_name_attributes.at(2)); - // Build a context and add a k-v pair for the current span, so OpenTelemetry - // can know the causal relationship between spans, and can infer the parent - // -> child hierarchy of spans - opentelemetry::context::Context ctx1 = opentelemetry::context::Context{"current-span", span}; - // Because contexts are immutable, we build another one and extract the contents - // of our carrier with extra header information, and ctx1 which has our current span - opentelemetry::context::Context ctx2 = propagator->Extract(carrier, ctx1); - // Build another carrier to hold the combination of all of our span data - gRPCMapCarrier carrier2; - propagator->Inject(carrier2, ctx2); - std::string req = request->request(); std::cout << std::endl << "grpc_client says: " << req << std::endl; std::string message = "The pleasure is mine."; + // Send response to client response->set_response(message); + span->AddEvent("Response sent to client"); span->SetStatus(opentelemetry::trace::StatusCode::kOk); // Make sure to end your spans! From 139273b000e4763e9a493e38a0d69a723760f88d Mon Sep 17 00:00:00 2001 From: Hablapatabla Date: Mon, 10 May 2021 18:46:03 -0400 Subject: [PATCH 05/16] Saving files before refreshing line endings --- examples/grpc/client.cc | 18 ++++----- examples/grpc/grpc_foo_lib/foo_split.cc | 8 ++-- examples/grpc/grpc_foo_lib/foo_split.h | 2 +- examples/grpc/grpc_foo_lib/grpc_map_carrier.h | 37 ++++++++++++------ examples/grpc/server.cc | 39 +++++++++++-------- examples/grpc/tracer_common.h | 7 ++-- examples/http/server.cc | 6 +++ examples/http/tracer_common.h | 2 +- 8 files changed, 73 insertions(+), 46 deletions(-) diff --git a/examples/grpc/client.cc b/examples/grpc/client.cc index 0ea9168f41..3bf2f61783 100644 --- a/examples/grpc/client.cc +++ b/examples/grpc/client.cc @@ -30,8 +30,6 @@ class GreeterClient GreetResponse response; ClientContext context; request.set_request("Nice to meet you!"); - // See tracer_common.h for this function - auto propagator = get_propagator(); opentelemetry::trace::StartSpanOptions options; options.kind = opentelemetry::trace::SpanKind::kClient; @@ -49,14 +47,16 @@ class GreeterClient {"net.peer.port", port}}, options); auto scope = get_tracer("grpc")->WithActiveSpan(span); - // Text map-style carrier for the propagator. Include other relevant information here. - gRPCMapCarrier carrier; - carrier.gRPCMapCarrier::Set("http.header.stub", "temporarily-stubbed"); - // The current runtime context has information about the currently active span. - // We need to add that to our carrier so that the server can extract it later, - // enabling the span hierarchy. + opentelemetry::nostd::span sp = span->GetContext().span_id().Id(); + for(const uint8_t &e : sp) { + std::cout << unsigned(e) << ' '; + } + std::cout << '\n'; auto current_ctx = opentelemetry::context::RuntimeContext::GetCurrent(); - propagator->Inject(carrier, current_ctx); + const gRPCMapCarrier carrier; + auto prop = opentelemetry::context::propagation::GlobalTextMapPropagator::GetGlobalPropagator(); + prop->Inject(carrier, current_ctx); + // Send request to server Status status = stub_->Greet(&context, request, &response); if (status.ok()) diff --git a/examples/grpc/grpc_foo_lib/foo_split.cc b/examples/grpc/grpc_foo_lib/foo_split.cc index 119b2544fe..586d0d80a1 100644 --- a/examples/grpc/grpc_foo_lib/foo_split.cc +++ b/examples/grpc/grpc_foo_lib/foo_split.cc @@ -4,10 +4,10 @@ namespace { std::vector mysplit(std::string s, char delim) { + initTracer(); auto propagator = get_propagator(); - gRPCMapCarrier carrier; - carrier.gRPCMapCarrier::Set("http.header.stub", "temporarily-stubbed"); + gRPCMapCarrier carrier; auto span = get_tracer("grpc")->StartSpan("splitfunc"); auto scope = get_tracer("grpc")->WithActiveSpan(span); @@ -30,10 +30,10 @@ std::vector mysplit(std::string s, char delim) std::vector split(std::string s, char delim) { + initTracer(); auto propagator = get_propagator(); - gRPCMapCarrier carrier; - carrier.gRPCMapCarrier::Set("http.header.stub", "temporarily-stubbed"); + gRPCMapCarrier carrier; auto span = get_tracer("grpc")->StartSpan("splitlib"); auto scope = get_tracer("grpc")->WithActiveSpan(span); diff --git a/examples/grpc/grpc_foo_lib/foo_split.h b/examples/grpc/grpc_foo_lib/foo_split.h index 9a0be41dcb..630ba91cff 100644 --- a/examples/grpc/grpc_foo_lib/foo_split.h +++ b/examples/grpc/grpc_foo_lib/foo_split.h @@ -2,8 +2,8 @@ #include #include #include +#include #include "../tracer_common.h" #include "grpc_map_carrier.h" -#include "opentelemetry/trace/provider.h" std::vector split(std::string s, char delim); diff --git a/examples/grpc/grpc_foo_lib/grpc_map_carrier.h b/examples/grpc/grpc_foo_lib/grpc_map_carrier.h index 1804a338b0..853f07d625 100644 --- a/examples/grpc/grpc_foo_lib/grpc_map_carrier.h +++ b/examples/grpc/grpc_foo_lib/grpc_map_carrier.h @@ -1,29 +1,44 @@ #pragma once -#include +#include #include "opentelemetry/context/context.h" +#include "opentelemetry/context/propagation/global_propagator.h" #include "opentelemetry/context/propagation/text_map_propagator.h" #include "opentelemetry/nostd/string_view.h" +#include "opentelemetry/trace/provider.h" + +namespace { +template class gRPCMapCarrier : public opentelemetry::context::propagation::TextMapCarrier { -private: - std::map headers_; - public: - virtual opentelemetry::nostd::string_view Get( - opentelemetry::nostd::string_view key) const noexcept override + gRPCMapCarrier(T &headers) : headers_(headers) {} + gRPCMapCarrier() = default; + virtual nostd::string_view Get(nostd::string_view key) const noexcept override { - auto it = headers_.find(std::string(key)); + std::string key_to_compare = key.data(); + if (key == opentelemetry::trace::propagation::kTraceParent) + { + key_to_compare = "Traceparent"; + } + else if (key == opentelemetry::trace::propagation::kTraceState) + { + key_to_compare = "Tracestate"; + } + auto it = headers_.find(key_to_compare); if (it != headers_.end()) { - return opentelemetry::nostd::string_view(it->second); + return it->second; } return ""; } - virtual void Set(opentelemetry::nostd::string_view key, - opentelemetry::nostd::string_view value) noexcept override + virtual void Set(nostd::string_view key, nostd::string_view value) noexcept override { - headers_[std::string(key)] = std::string(value); + headers_.insert(std::pair(std::string(key), std::string(value))); } + + T headers_; }; + +} // namespace \ No newline at end of file diff --git a/examples/grpc/server.cc b/examples/grpc/server.cc index 271fa4b05d..96724bb6ad 100644 --- a/examples/grpc/server.cc +++ b/examples/grpc/server.cc @@ -2,6 +2,7 @@ #include "grpc_foo_lib/grpc_map_carrier.h" #include "messages.grpc.pb.h" #include "tracer_common.h" +#include "opentelemetry/trace/span_context_kv_iterable_view.h" #include #include @@ -13,6 +14,7 @@ #include #include #include +#include using grpc::Server; using grpc::ServerBuilder; @@ -24,6 +26,9 @@ using grpc_example::Greeter; using grpc_example::GreetRequest; using grpc_example::GreetResponse; +using Span = opentelemetry::trace::Span; +using SpanContext = opentelemetry::trace::SpanContext; + namespace { class GreeterServer final : public Greeter::Service @@ -33,8 +38,6 @@ class GreeterServer final : public Greeter::Service const GreetRequest *request, GreetResponse *response) override { - // Get global propagator to move spans across rpc boundaries - auto propagator = get_propagator(); // Create a SpanOptions object and set the kind to Server to inform OpenTel. opentelemetry::trace::StartSpanOptions options; options.kind = opentelemetry::trace::SpanKind::kServer; @@ -45,30 +48,34 @@ class GreeterServer final : public Greeter::Service // to get any carrier-relevant information at this point without doing work that // we want to capture in a span, but we include the definition at this point to fit // real-life scenarios - gRPCMapCarrier carrier; - // The current RuntimeContext should contain the currently active span, which is from - // the client side. To implement the span hierarchy, we need to fetch that span from - // the RuntimeContext so that we can set it as the parent of our new span + std::map m; + m.insert(std::pair("1", "2")); + const gRPCMapCarrier> carrier((std::map &) m); + auto prop = opentelemetry::context::propagation::GlobalTextMapPropagator::GetGlobalPropagator(); auto current_ctx = opentelemetry::context::RuntimeContext::GetCurrent(); - // We want a new context that will have the information that we 'could' have placed - // in the carrier already, as well as the RuntimeContext which has our parent-span - // information. Contexts are immutable, so we need to make a new one - auto new_ctx = propagator->Extract(carrier, current_ctx); - options.parent = GetSpanFromContext(new_ctx)->GetContext(); + auto new_context = prop->Extract(carrier, current_ctx); + auto s = GetSpanFromContext(new_context); + opentelemetry::nostd::span sp = s->GetContext().span_id().Id(); + for(const uint8_t &e : sp) { + std::cout << unsigned(e) << ' '; + } + std::cout << '\n'; + options.parent = s->GetContext(); + // Build a new span from a tracer, start, and activate it. When adding // attributes to spans, be sure to follow the OpenTelemetry Semantic // Conventions that are relevant to your project as closely as possible // Some protocols/patterns that have specified conventions: // RPC, HTTP, AWS Lambda, Database, Exceptions, etc. std::string span_name = "GreeterService/Greet"; - auto span = get_tracer("grpc-server") + auto span = get_tracer("grpc") ->StartSpan(span_name, {{"rpc.system", "grpc"}, {"rpc.service", "GreeterService"}, {"rpc.method", "Greet"}, {"rpc.grpc.status_code", 0}}, options); - auto scope = get_tracer("grpc-server")->WithActiveSpan(span); + auto scope = get_tracer("grpc")->WithActiveSpan(span); // Fetch and parse whatever HTTP headers we can from the gRPC request. span->AddEvent("Processing client attributes"); @@ -77,9 +84,9 @@ class GreeterServer final : public Greeter::Service // Fill the carrier with other headers. gRPC runs on HTTP 2, so we add all // of the HTTP headers that we just extracted - carrier.gRPCMapCarrier::Set("net.ip.version", peer_name_attributes.at(0)); - carrier.gRPCMapCarrier::Set("net.peer.ip", peer_name_attributes.at(1)); - carrier.gRPCMapCarrier::Set("net.peer.port", peer_name_attributes.at(2)); + /*carrier.Set("net.ip.version", peer_name_attributes.at(0)); + carrier.Set("net.peer.ip", peer_name_attributes.at(1)); + carrier.Set("net.peer.port", peer_name_attributes.at(2));*/ std::string req = request->request(); std::cout << std::endl << "grpc_client says: " << req << std::endl; diff --git a/examples/grpc/tracer_common.h b/examples/grpc/tracer_common.h index 6f4b4c4856..d6ca9b79ca 100644 --- a/examples/grpc/tracer_common.h +++ b/examples/grpc/tracer_common.h @@ -13,8 +13,8 @@ #include #include #include -#include "opentelemetry/ext/http/client/http_client.h" #include "opentelemetry/nostd/shared_ptr.h" +#include "opentelemetry/ext/http/client/http_client.h" namespace { @@ -24,10 +24,12 @@ inline nostd::shared_ptr GetSpanFromContext( opentelemetry::context::ContextValue span = context.GetValue(opentelemetry::trace::kSpanKey); if (nostd::holds_alternative>(span)) { + std::cout << "GETSPAN FROM CONTEXT YES\n"; return nostd::get>(span); } static nostd::shared_ptr invalid_span{ new opentelemetry::trace::DefaultSpan(opentelemetry::trace::SpanContext::GetInvalid())}; + std::cout << "GETSPANFROMCONTEXT no\n"; return invalid_span; } @@ -62,9 +64,6 @@ nostd::shared_ptr get_tracer(std::string tracer_na // boilerplate from gRPC example services/library nostd::shared_ptr get_propagator() { - opentelemetry::context::propagation::GlobalTextMapPropagator::SetGlobalPropagator( - opentelemetry::nostd::shared_ptr( - new opentelemetry::trace::propagation::HttpTraceContext())); auto propagator = opentelemetry::context::propagation::GlobalTextMapPropagator::GetGlobalPropagator(); return propagator; diff --git a/examples/http/server.cc b/examples/http/server.cc index a9f1a81e08..cb055d77bf 100644 --- a/examples/http/server.cc +++ b/examples/http/server.cc @@ -25,6 +25,12 @@ class RequestHandler : public HTTP_SERVER_NS::HttpRequestCallback auto prop = opentelemetry::context::propagation::GlobalTextMapPropagator::GetGlobalPropagator(); auto current_ctx = opentelemetry::context::RuntimeContext::GetCurrent(); auto new_context = prop->Extract(carrier, current_ctx); + opentelemetry::nostd::span sp = GetSpanFromContext(new_context)->GetContext().span_id().Id(); + for(const uint8_t &e : sp) { + std::cout << unsigned(e) << ' '; + } + std::cout << '\n'; + options.parent = GetSpanFromContext(new_context)->GetContext(); // start span with parent context extracted from http header diff --git a/examples/http/tracer_common.h b/examples/http/tracer_common.h index a618175b1d..2f517e5601 100644 --- a/examples/http/tracer_common.h +++ b/examples/http/tracer_common.h @@ -47,7 +47,7 @@ class HttpTextMapCarrier : public opentelemetry::context::propagation::TextMapCa } else if (key == opentelemetry::trace::propagation::kTraceState) { - key_to_compare == "Tracestate"; + key_to_compare = "Tracestate"; } auto it = headers_.find(key_to_compare); if (it != headers_.end()) From 9496c3f5c36b970852781052f9342aa8fe81da7a Mon Sep 17 00:00:00 2001 From: Hablapatabla Date: Mon, 10 May 2021 18:46:21 -0400 Subject: [PATCH 06/16] Normalize all the line endings --- tools/ports/benchmark/CONTROL | 8 +-- tools/ports/benchmark/portfile.cmake | 98 ++++++++++++++-------------- 2 files changed, 53 insertions(+), 53 deletions(-) diff --git a/tools/ports/benchmark/CONTROL b/tools/ports/benchmark/CONTROL index 62b80dffae..82e4b57e84 100644 --- a/tools/ports/benchmark/CONTROL +++ b/tools/ports/benchmark/CONTROL @@ -1,5 +1,5 @@ -Source: benchmark -Version: 1.5.1 -Homepage: https://github.com/google/benchmark -Description: A library to support the benchmarking of functions, similar to unit-tests. +Source: benchmark +Version: 1.5.1 +Homepage: https://github.com/google/benchmark +Description: A library to support the benchmarking of functions, similar to unit-tests. Supports: !uwp \ No newline at end of file diff --git a/tools/ports/benchmark/portfile.cmake b/tools/ports/benchmark/portfile.cmake index e89fafca6c..06ff36d148 100644 --- a/tools/ports/benchmark/portfile.cmake +++ b/tools/ports/benchmark/portfile.cmake @@ -1,49 +1,49 @@ -if(VCPKG_CMAKE_SYSTEM_NAME STREQUAL "WindowsStore") - message(FATAL_ERROR "${PORT} does not currently support UWP") -endif() - -if (VCPKG_PLATFORM_TOOLSET STREQUAL "v140") - # set(CMAKE_C_COMPILER_WORKS 1) - # set(CMAKE_CXX_COMPILER_WORKS 1) - set(CMAKE_C_COMPILER cl.exe) - set(CMAKE_CXX_COMPILER cl.exe) - set(MSVC_TOOLSET_VERSION 140) - # set(VCPKG_VISUAL_STUDIO_PATH "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0") - # set(VCPKG_PLATFORM_TOOLSET v140) -else() - # Make sure vs2019 compiled binaries are compat with vs2017 - set(VCPKG_CXX_FLAGS "/Zc:__cplusplus /d2FH4-") - set(VCPKG_C_FLAGS "/Zc:__cplusplus /d2FH4-") - set(PREFER PREFER_NINJA) -endif() - -include(vcpkg_common_functions) - -vcpkg_check_linkage(ONLY_STATIC_LIBRARY) - -vcpkg_from_github( - OUT_SOURCE_PATH SOURCE_PATH - REPO google/benchmark - HEAD_REF master -) - -vcpkg_configure_cmake( - SOURCE_PATH ${SOURCE_PATH} - ${PREFER} - OPTIONS - -DBENCHMARK_ENABLE_TESTING=OFF - -DCMAKE_DEBUG_POSTFIX=d -) - -vcpkg_install_cmake() - -vcpkg_copy_pdbs() - -vcpkg_fixup_cmake_targets(CONFIG_PATH lib/cmake/benchmark) - -file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/include) -file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/share) - -# Handle copyright -file(COPY ${SOURCE_PATH}/LICENSE DESTINATION ${CURRENT_PACKAGES_DIR}/share/benchmark) -file(RENAME ${CURRENT_PACKAGES_DIR}/share/benchmark/LICENSE ${CURRENT_PACKAGES_DIR}/share/benchmark/copyright) +if(VCPKG_CMAKE_SYSTEM_NAME STREQUAL "WindowsStore") + message(FATAL_ERROR "${PORT} does not currently support UWP") +endif() + +if (VCPKG_PLATFORM_TOOLSET STREQUAL "v140") + # set(CMAKE_C_COMPILER_WORKS 1) + # set(CMAKE_CXX_COMPILER_WORKS 1) + set(CMAKE_C_COMPILER cl.exe) + set(CMAKE_CXX_COMPILER cl.exe) + set(MSVC_TOOLSET_VERSION 140) + # set(VCPKG_VISUAL_STUDIO_PATH "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0") + # set(VCPKG_PLATFORM_TOOLSET v140) +else() + # Make sure vs2019 compiled binaries are compat with vs2017 + set(VCPKG_CXX_FLAGS "/Zc:__cplusplus /d2FH4-") + set(VCPKG_C_FLAGS "/Zc:__cplusplus /d2FH4-") + set(PREFER PREFER_NINJA) +endif() + +include(vcpkg_common_functions) + +vcpkg_check_linkage(ONLY_STATIC_LIBRARY) + +vcpkg_from_github( + OUT_SOURCE_PATH SOURCE_PATH + REPO google/benchmark + HEAD_REF master +) + +vcpkg_configure_cmake( + SOURCE_PATH ${SOURCE_PATH} + ${PREFER} + OPTIONS + -DBENCHMARK_ENABLE_TESTING=OFF + -DCMAKE_DEBUG_POSTFIX=d +) + +vcpkg_install_cmake() + +vcpkg_copy_pdbs() + +vcpkg_fixup_cmake_targets(CONFIG_PATH lib/cmake/benchmark) + +file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/include) +file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/share) + +# Handle copyright +file(COPY ${SOURCE_PATH}/LICENSE DESTINATION ${CURRENT_PACKAGES_DIR}/share/benchmark) +file(RENAME ${CURRENT_PACKAGES_DIR}/share/benchmark/LICENSE ${CURRENT_PACKAGES_DIR}/share/benchmark/copyright) From 1799f3210ff8c5f71257dee630872ee42f0aed2f Mon Sep 17 00:00:00 2001 From: Hablapatabla Date: Tue, 11 May 2021 17:19:29 -0400 Subject: [PATCH 07/16] Format and comment out debugging output from trying to implement span propagation from client to server --- examples/grpc/client.cc | 8 ++++++-- examples/grpc/server.cc | 12 ++++++++++-- examples/grpc/tracer_common.h | 4 ++-- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/examples/grpc/client.cc b/examples/grpc/client.cc index 3bf2f61783..07220fa02c 100644 --- a/examples/grpc/client.cc +++ b/examples/grpc/client.cc @@ -47,13 +47,17 @@ class GreeterClient {"net.peer.port", port}}, options); auto scope = get_tracer("grpc")->WithActiveSpan(span); + + /* + Commented out some debugging output, in case a reviewer finds it useful opentelemetry::nostd::span sp = span->GetContext().span_id().Id(); for(const uint8_t &e : sp) { std::cout << unsigned(e) << ' '; } - std::cout << '\n'; + std::cout << '\n';*/ auto current_ctx = opentelemetry::context::RuntimeContext::GetCurrent(); - const gRPCMapCarrier carrier; + // Experimented with opentelemetry::ext::http::client::Headers here too + gRPCMapCarrier> carrier; auto prop = opentelemetry::context::propagation::GlobalTextMapPropagator::GetGlobalPropagator(); prop->Inject(carrier, current_ctx); diff --git a/examples/grpc/server.cc b/examples/grpc/server.cc index 96724bb6ad..38075c0a21 100644 --- a/examples/grpc/server.cc +++ b/examples/grpc/server.cc @@ -49,17 +49,25 @@ class GreeterServer final : public Greeter::Service // we want to capture in a span, but we include the definition at this point to fit // real-life scenarios std::map m; - m.insert(std::pair("1", "2")); + // Try inserting data into the map + // m.insert(std::pair("1", "2")); + // Also tried without passing a map at all, like in grpc/client.cc const gRPCMapCarrier> carrier((std::map &) m); auto prop = opentelemetry::context::propagation::GlobalTextMapPropagator::GetGlobalPropagator(); + // GetSpanFromContext fails here auto current_ctx = opentelemetry::context::RuntimeContext::GetCurrent(); + // GetSpanFromContext for new_context actually returns a span, suggesting there should be + // a usable parent span in this context auto new_context = prop->Extract(carrier, current_ctx); auto s = GetSpanFromContext(new_context); + // Commented out debugging output. Only outputs '0 0 0 0 0 0' as the spanid, which + // I'm fairly sure indicates an inactive/invalid span + /* opentelemetry::nostd::span sp = s->GetContext().span_id().Id(); for(const uint8_t &e : sp) { std::cout << unsigned(e) << ' '; } - std::cout << '\n'; + std::cout << '\n';*/ options.parent = s->GetContext(); // Build a new span from a tracer, start, and activate it. When adding diff --git a/examples/grpc/tracer_common.h b/examples/grpc/tracer_common.h index d6ca9b79ca..2380784033 100644 --- a/examples/grpc/tracer_common.h +++ b/examples/grpc/tracer_common.h @@ -24,12 +24,12 @@ inline nostd::shared_ptr GetSpanFromContext( opentelemetry::context::ContextValue span = context.GetValue(opentelemetry::trace::kSpanKey); if (nostd::holds_alternative>(span)) { - std::cout << "GETSPAN FROM CONTEXT YES\n"; + //std::cout << "GETSPAN FROM CONTEXT YES\n"; return nostd::get>(span); } static nostd::shared_ptr invalid_span{ new opentelemetry::trace::DefaultSpan(opentelemetry::trace::SpanContext::GetInvalid())}; - std::cout << "GETSPANFROMCONTEXT no\n"; + //std::cout << "GETSPANFROMCONTEXT no\n"; return invalid_span; } From 25ff0093d5b22df285cfd99c04d6344cdb8c3e43 Mon Sep 17 00:00:00 2001 From: Hablapatabla Date: Tue, 11 May 2021 17:25:06 -0400 Subject: [PATCH 08/16] Fix code snippet markdown in README and try adding block around find_package statements to prevent errors when building otel with -DWITH_OTLP=YES --- examples/grpc/CMakeLists.txt | 6 ++++-- examples/grpc/README.md | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/examples/grpc/CMakeLists.txt b/examples/grpc/CMakeLists.txt index 7f7688748b..0ab380db94 100644 --- a/examples/grpc/CMakeLists.txt +++ b/examples/grpc/CMakeLists.txt @@ -1,6 +1,8 @@ -find_package(gRPC) -find_package(Protobuf) +if(NOT Protobuf_FOUND) + find_package(Protobuf) +elseif(NOT gRPC_FOUND) + find_package(gRPC) if(NOT Protobuf_FOUND) message(WARNING "Aborting grpc example build, protobuf not found.") elseif(NOT gRPC_FOUND) diff --git a/examples/grpc/README.md b/examples/grpc/README.md index bf83072456..e3ed1dfcee 100644 --- a/examples/grpc/README.md +++ b/examples/grpc/README.md @@ -19,7 +19,7 @@ This is a simple example that demonstrates tracing a gRPC request from client to installed both of these packages on your system, in such a way that CMake would know how to find them with this command: -'''find_package(gRPC)''' +```find_package(gRPC)``` If you install these with a package manager like '''brew''' or '''apt''', you should not need to do extra work. From d8569a20ecde220878e15a1a10b47f6a5f3a429c Mon Sep 17 00:00:00 2001 From: Hablapatabla Date: Tue, 11 May 2021 17:53:24 -0400 Subject: [PATCH 09/16] Revert CMakeLists so it works again after bad commit (oof). --- examples/grpc/CMakeLists.txt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/examples/grpc/CMakeLists.txt b/examples/grpc/CMakeLists.txt index 0ab380db94..7f7688748b 100644 --- a/examples/grpc/CMakeLists.txt +++ b/examples/grpc/CMakeLists.txt @@ -1,8 +1,6 @@ +find_package(gRPC) +find_package(Protobuf) -if(NOT Protobuf_FOUND) - find_package(Protobuf) -elseif(NOT gRPC_FOUND) - find_package(gRPC) if(NOT Protobuf_FOUND) message(WARNING "Aborting grpc example build, protobuf not found.") elseif(NOT gRPC_FOUND) From 2de0ea2bb1ce5d70fd295f7472af5b7b6bf1f5ae Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Wed, 2 Jun 2021 06:34:08 +0530 Subject: [PATCH 10/16] fix context propagation --- examples/grpc/CMakeLists.txt | 106 ++++------ examples/grpc/README.md | 2 +- examples/grpc/{client.cc => client.cpp} | 35 ++- .../grpc/experimental/greeter_interceptor.cc | 200 ------------------ examples/grpc/grpc_foo_lib/foo_split.cc | 50 ----- examples/grpc/grpc_foo_lib/foo_split.h | 9 - examples/grpc/grpc_foo_lib/grpc_map_carrier.h | 44 ---- examples/grpc/{server.cc => server.cpp} | 42 ++-- examples/grpc/tracer_common.h | 71 ++++--- examples/http/server.cc | 10 +- 10 files changed, 127 insertions(+), 442 deletions(-) rename examples/grpc/{client.cc => client.cpp} (79%) delete mode 100644 examples/grpc/experimental/greeter_interceptor.cc delete mode 100644 examples/grpc/grpc_foo_lib/foo_split.cc delete mode 100644 examples/grpc/grpc_foo_lib/foo_split.h delete mode 100644 examples/grpc/grpc_foo_lib/grpc_map_carrier.h rename examples/grpc/{server.cc => server.cpp} (68%) diff --git a/examples/grpc/CMakeLists.txt b/examples/grpc/CMakeLists.txt index 7f7688748b..2b43cf18f6 100644 --- a/examples/grpc/CMakeLists.txt +++ b/examples/grpc/CMakeLists.txt @@ -1,62 +1,48 @@ -find_package(gRPC) -find_package(Protobuf) - -if(NOT Protobuf_FOUND) - message(WARNING "Aborting grpc example build, protobuf not found.") -elseif(NOT gRPC_FOUND) - message(WARNING "Aborting grpc example build, grpc not found.") +# Proto file +get_filename_component(proto_file "./protos/messages.proto" ABSOLUTE) +get_filename_component(proto_file_path "${proto_file}" PATH) + +message("PATH:${proto_file_path}:${proto_file}") +# Generated sources +set(example_proto_srcs "${CMAKE_CURRENT_BINARY_DIR}/messages.pb.cc") +set(example_proto_hdrs "${CMAKE_CURRENT_BINARY_DIR}/messages.pb.h") +set(example_grpc_srcs "${CMAKE_CURRENT_BINARY_DIR}/messages.grpc.pb.cc") +set(example_grpc_hdrs "${CMAKE_CURRENT_BINARY_DIR}/messages.grpc.pb.h") + +add_custom_command( + OUTPUT "${example_proto_srcs}" "${example_proto_hdrs}" "${example_grpc_srcs}" + "${example_grpc_hdrs}" + COMMAND + ${PROTOBUF_PROTOC_EXECUTABLE} ARGS "--grpc_out=${CMAKE_CURRENT_BINARY_DIR}" + "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" "--proto_path=${proto_file_path}" + --plugin=protoc-gen-grpc="${gRPC_CPP_PLUGIN_EXECUTABLE}" "${proto_file}") +# DEPENDS "${proto_file}") + +# hw_grpc_proto +add_library(example_grpc_proto ${example_grpc_srcs} ${example_grpc_hdrs} + ${example_proto_srcs} ${example_proto_hdrs}) + +include_directories( + ${CMAKE_SOURCE_DIR}/exporters/ostream/include ${CMAKE_SOURCE_DIR}/ext/include + ${CMAKE_SOURCE_DIR}/api/include/ ${CMAKE_SOURCE_DIR/}) + +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +if(TARGET protobuf::libprotobuf) + target_link_libraries(example_grpc_proto gRPC::grpc++ protobuf::libprotobuf) else() - set(_PROTOBUF_PROTOC $) - set(_GRPC_GRPCPP gRPC::grpc++) - set(_GRPC_CPP_PLUGIN_EXECUTABLE $) - - include_directories( - ${CMAKE_SOURCE_DIR}/exporters/ostream/include - ${CMAKE_SOURCE_DIR}/ext/include ${CMAKE_SOURCE_DIR}/api/include/ - ${CMAKE_SOURCE_DIR/}) - - include_directories(${CMAKE_CURRENT_BINARY_DIR}/protos) - - get_filename_component( - hw_proto ${CMAKE_CURRENT_SOURCE_DIR}/protos/messages.proto ABSOLUTE) - get_filename_component(hw_proto_path "${hw_proto}" PATH) - - set(hw_proto_srcs "${CMAKE_CURRENT_BINARY_DIR}/messages.pb.cc") - set(hw_proto_hdrs "${CMAKE_CURRENT_BINARY_DIR}/messages.pb.h") - set(hw_grpc_srcs "${CMAKE_CURRENT_BINARY_DIR}/messages.grpc.pb.cc") - set(hw_grpc_hdrs "${CMAKE_CURRENT_BINARY_DIR}/messages.grpc.pb.h") - - add_custom_command( - OUTPUT "${hw_proto_srcs}" "${hw_proto_hdrs}" "${hw_grpc_srcs}" - "${hw_grpc_hdrs}" - COMMAND - ${_PROTOBUF_PROTOC} ARGS --grpc_out "${CMAKE_CURRENT_BINARY_DIR}" - --cpp_out "${CMAKE_CURRENT_BINARY_DIR}" -I "${hw_proto_path}" - --plugin=protoc-gen-grpc="${_GRPC_CPP_PLUGIN_EXECUTABLE}" "${hw_proto}" - DEPENDS "${hw_proto}") - - include_directories("${CMAKE_CURRENT_BINARY_DIR}") - - add_library(grpc_foo_library grpc_foo_lib/foo_split.cc) - - add_library(hw_grpc_proto ${hw_grpc_srcs} ${hw_grpc_hdrs} ${hw_proto_srcs} - ${hw_proto_hdrs}) - - target_link_libraries(hw_grpc_proto ${_REFLECTION} ${_GRPC_GRPCPP} - ${_PROTOBUF_LIBPROTOBUF}) - - foreach(_target client server) - add_executable(${_target} "${_target}.cc") - target_link_libraries( - ${_target} - hw_grpc_proto - grpc_foo_library - ${_REFLECTION} - ${_GRPC_GRPCPP} - ${_PROTOBUF_LIBPROTOBUF} - ${CMAKE_THREAD_LIBS_INIT} - ${CORE_RUNTIME_LIBS} - opentelemetry_trace - opentelemetry_exporter_ostream_span) - endforeach() + target_include_directories(example_grpc_proto ${Protobuf_INCLUDE_DIRS}) + target_link_libraries(example_grpc_proto ${Protobuf_LIBRARIES}) endif() + +foreach(_target client server) + add_executable(${_target} "${_target}.cpp") + target_link_libraries( + ${_target} + example_grpc_proto + protobuf::libprotobuf + gRPC::grpc++ + gRPC::grpc++_reflection + opentelemetry_trace + opentelemetry_exporter_ostream_span) +endforeach() diff --git a/examples/grpc/README.md b/examples/grpc/README.md index e3ed1dfcee..58cd17c8e2 100644 --- a/examples/grpc/README.md +++ b/examples/grpc/README.md @@ -116,7 +116,7 @@ If you install these with a package manager like '''brew''' or '''apt''', you sh rpc.method: Greet rpc.service: GreeterService rpc.system: grpc - events : + events : links : } ``` diff --git a/examples/grpc/client.cc b/examples/grpc/client.cpp similarity index 79% rename from examples/grpc/client.cc rename to examples/grpc/client.cpp index 07220fa02c..1a4e3c74aa 100644 --- a/examples/grpc/client.cc +++ b/examples/grpc/client.cpp @@ -1,12 +1,12 @@ -#include "grpc_foo_lib/foo_split.h" -#include "grpc_foo_lib/grpc_map_carrier.h" -#include "messages.grpc.pb.h" #include "tracer_common.h" - -#include #include +#include #include +#include + +#include "messages.grpc.pb.h" + using grpc::Channel; using grpc::ClientContext; using grpc::ClientReader; @@ -16,8 +16,10 @@ using grpc_example::Greeter; using grpc_example::GreetRequest; using grpc_example::GreetResponse; + namespace { + class GreeterClient { public: @@ -46,20 +48,13 @@ class GreeterClient {"net.peer.ip", ip}, {"net.peer.port", port}}, options); - auto scope = get_tracer("grpc")->WithActiveSpan(span); - /* - Commented out some debugging output, in case a reviewer finds it useful - opentelemetry::nostd::span sp = span->GetContext().span_id().Id(); - for(const uint8_t &e : sp) { - std::cout << unsigned(e) << ' '; - } - std::cout << '\n';*/ - auto current_ctx = opentelemetry::context::RuntimeContext::GetCurrent(); - // Experimented with opentelemetry::ext::http::client::Headers here too - gRPCMapCarrier> carrier; - auto prop = opentelemetry::context::propagation::GlobalTextMapPropagator::GetGlobalPropagator(); - prop->Inject(carrier, current_ctx); + auto scope = get_tracer("grpc-client")->WithActiveSpan(span); + + auto current_ctx = opentelemetry::context::RuntimeContext::GetCurrent(); + GrpcClientCarrier carrier(&context); + auto prop = opentelemetry::context::propagation::GlobalTextMapPropagator::GetGlobalPropagator(); + prop->Inject(carrier, current_ctx); // Send request to server Status status = stub_->Greet(&context, request, &response); @@ -98,6 +93,10 @@ void RunClient(uint16_t port) int main(int argc, char **argv) { initTracer(); + // set global propagator + opentelemetry::context::propagation::GlobalTextMapPropagator::SetGlobalPropagator( + nostd::shared_ptr( + new opentelemetry::trace::propagation::HttpTraceContext())); constexpr uint16_t default_port = 8800; uint16_t port; if (argc > 1) diff --git a/examples/grpc/experimental/greeter_interceptor.cc b/examples/grpc/experimental/greeter_interceptor.cc deleted file mode 100644 index 94118137f3..0000000000 --- a/examples/grpc/experimental/greeter_interceptor.cc +++ /dev/null @@ -1,200 +0,0 @@ -/*#include "messages.grpc.pb.h" -#include "tracer_common.h" - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -using grpc::Server; -using grpc::ServerBuilder; -using grpc::ServerContext; -using grpc::ServerWriter; -using grpc::Status; - -using grpc_example::Greeter; -using grpc_example::GreetRequest; -using grpc_example::GreetResponse; - -class GreeterInterceptor : public grpc::experimental::Interceptor -{ -public: - GreeterInterceptor(grpc::experimental::ServerRpcInfo *info) - { - info_ = info; - const char *method = info->method(); - grpc::experimental::ServerRpcInfo::Type type = info->type(); - } - - void Intercept(grpc::experimental::InterceptorBatchMethods *methods) override - { - if (methods->QueryInterceptionHookPoint( - grpc::experimental::InterceptionHookPoints::PRE_SEND_INITIAL_METADATA)) - { - auto *map = methods->GetSendInitialMetadata(); - std::cout << "PRE_SEND_INITIAL_METADATA SEND_INITIAL_METADATA ELEMENTS: " << std::endl; - - for (const auto &pair : *map) - std::cout << pair.first << " : " << pair.second << std::endl; - } - - if (methods->QueryInterceptionHookPoint( - grpc::experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) - { - GreetRequest req; - auto *buffer = methods->GetSerializedSendMessage(); - auto copied_buffer = *buffer; - size_t size = copied_buffer.Length(); - std::cout << "PRE_SEND_MESSAGE: Byte buffer size: " << size << std::endl; - } - - if (methods->QueryInterceptionHookPoint( - grpc::experimental::InterceptionHookPoints::PRE_SEND_STATUS)) - { - auto *map = methods->GetSendTrailingMetadata(); - std::cout << "PRE_SEND_STATUS SEND_TRAILING_METADATA ELEMENTS: " << std::endl; - - for (const auto &pair : *map) - std::cout << pair.first << " : " << pair.second << std::endl; - } - if (methods->QueryInterceptionHookPoint( - grpc::experimental::InterceptionHookPoints::POST_RECV_INITIAL_METADATA)) - { - auto *map = methods->GetRecvInitialMetadata(); - std::cout << "POST_RECV_INITIAL_METADATA RECV_INITIAL_METADATA ELEMENTS: " << std::endl; - - for (const auto &pair : *map) - std::cout << pair.first << " : " << pair.second << std::endl; - } - if (methods->QueryInterceptionHookPoint( - grpc::experimental::InterceptionHookPoints::POST_RECV_MESSAGE)) - { - GreetResponse *resp = static_cast(methods->GetRecvMessage()); - std::cout << "Response: " << resp->response() << std::endl; - } - if (methods->QueryInterceptionHookPoint( - grpc::experimental::InterceptionHookPoints::POST_RECV_STATUS)) - { - auto *map = methods->GetRecvTrailingMetadata(); - std::cout << "POST_RECV_STATUS RECV_TRAILING_METADATA ELEMENTS: " << std::endl; - - for (const auto &pair : *map) - std::cout << pair.first << " : " << pair.second << std::endl; - } - if (methods->QueryInterceptionHookPoint( - grpc::experimental::InterceptionHookPoints::POST_RECV_CLOSE)) - {} - methods->Proceed(); - } - -private: - grpc::experimental::ServerRpcInfo *info_; -}; - -class GreeterInterceptorFactory : public grpc::experimental::ServerInterceptorFactoryInterface -{ -public: - virtual grpc::experimental::Interceptor *CreateServerInterceptor( - grpc::experimental::ServerRpcInfo *info) override - { - return new GreeterInterceptor(info); - } -}; - -class GreeterServer final : public Greeter::Service -{ -public: - Status Greet(ServerContext *context, - const GreetRequest *request, - GreetResponse *response) override - { - opentelemetry::trace::StartSpanOptions options; - options.kind = opentelemetry::trace::SpanKind::kServer; - std::string peer_name = context->peer(); - std::string peer_name_copy = peer_name; - std::string delim = ":"; - std::vector peer_name_attributes{}; - std::cout << "peer name: " << peer_name << std::endl; - ; - size_t idx; - while ((idx = peer_name_copy.find(delim)) != std::string::npos) - { - peer_name_attributes.push_back(peer_name_copy.substr(0, idx)); - peer_name_copy.erase(0, idx + delim.length()); - } - for (std::string s : peer_name_attributes) - { - std::cout << s << std::endl; - } - - std::string span_name = "grpc server"; - auto span = get_tracer("grpc-server") - ->StartSpan(span_name, - {{"rpc.system", "grpc"}, - {"rpc.service", "grpc-example.GreetService"}, - {"rpc.method", "Greet"}, - {"net.peer.ip", peer_name_attributes.at(1)}, - {"net.peer.port", peer_name_attributes.at(2)}, - {"rpc.grpc.status_code", "0"}}, - options); - auto scope = get_tracer("grpc-server")->WithActiveSpan(span); - - std::string req = request->request(); - std::cout << "grpc_client says: " << req << std::endl; - std::string message = "The pleasure is mine."; - response->set_response(message); - - span->End(); - return Status::OK; - } -}; - -void RunServer(uint16_t port) -{ - std::string address("0.0.0.0:" + std::to_string(port)); - GreeterServer service; - ServerBuilder builder; - - builder.RegisterService(&service); - builder.AddListeningPort(address, grpc::InsecureServerCredentials()); - std::vector> creators; - creators.reserve(1); - creators.push_back(std::unique_ptr(new GreeterInterceptorFactory())); - builder.experimental().SetInterceptorCreators(std::move(creators)); - - std::unique_ptr server(builder.BuildAndStart()); - std::cout << "Server listening on port: " << address << std::endl; - server->Wait(); - server->Shutdown(); -} - -int main(int argc, char **argv) -{ - initTracer(); - constexpr uint16_t default_port = 8800; - uint16_t port; - if (argc > 1) - { - port = atoi(argv[1]); - } - else - { - port = default_port; - } - - RunServer(port); - return 0; -} -*/ \ No newline at end of file diff --git a/examples/grpc/grpc_foo_lib/foo_split.cc b/examples/grpc/grpc_foo_lib/foo_split.cc deleted file mode 100644 index 586d0d80a1..0000000000 --- a/examples/grpc/grpc_foo_lib/foo_split.cc +++ /dev/null @@ -1,50 +0,0 @@ -#include "foo_split.h" - -namespace -{ -std::vector mysplit(std::string s, char delim) -{ - initTracer(); - auto propagator = get_propagator(); - - gRPCMapCarrier carrier; - auto span = get_tracer("grpc")->StartSpan("splitfunc"); - auto scope = get_tracer("grpc")->WithActiveSpan(span); - - std::vector token_container{}; - std::stringstream ss(s); - std::string token; - - while (std::getline(ss, token, delim)) - token_container.push_back(token); - - opentelemetry::context::Context ctx1 = opentelemetry::context::Context{"current-span", span}; - opentelemetry::context::Context ctx2 = opentelemetry::context::RuntimeContext::GetCurrent(); - propagator->Inject(carrier, ctx1); - propagator->Inject(carrier, ctx2); - - span->End(); - return token_container; -} -} // namespace - -std::vector split(std::string s, char delim) -{ - initTracer(); - auto propagator = get_propagator(); - - gRPCMapCarrier carrier; - - auto span = get_tracer("grpc")->StartSpan("splitlib"); - auto scope = get_tracer("grpc")->WithActiveSpan(span); - - opentelemetry::context::Context ctx1 = opentelemetry::context::Context{"current-span", span}; - opentelemetry::context::Context ctx2 = opentelemetry::context::RuntimeContext::GetCurrent(); - propagator->Inject(carrier, ctx1); - propagator->Inject(carrier, ctx2); - - std::vector v = mysplit(s, delim); - - span->End(); - return v; -} diff --git a/examples/grpc/grpc_foo_lib/foo_split.h b/examples/grpc/grpc_foo_lib/foo_split.h deleted file mode 100644 index 630ba91cff..0000000000 --- a/examples/grpc/grpc_foo_lib/foo_split.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include "../tracer_common.h" -#include "grpc_map_carrier.h" - -std::vector split(std::string s, char delim); diff --git a/examples/grpc/grpc_foo_lib/grpc_map_carrier.h b/examples/grpc/grpc_foo_lib/grpc_map_carrier.h deleted file mode 100644 index 853f07d625..0000000000 --- a/examples/grpc/grpc_foo_lib/grpc_map_carrier.h +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once -#include -#include "opentelemetry/context/context.h" -#include "opentelemetry/context/propagation/global_propagator.h" -#include "opentelemetry/context/propagation/text_map_propagator.h" -#include "opentelemetry/nostd/string_view.h" -#include "opentelemetry/trace/provider.h" - - -namespace { -template -class gRPCMapCarrier : public opentelemetry::context::propagation::TextMapCarrier -{ -public: - gRPCMapCarrier(T &headers) : headers_(headers) {} - gRPCMapCarrier() = default; - virtual nostd::string_view Get(nostd::string_view key) const noexcept override - { - std::string key_to_compare = key.data(); - if (key == opentelemetry::trace::propagation::kTraceParent) - { - key_to_compare = "Traceparent"; - } - else if (key == opentelemetry::trace::propagation::kTraceState) - { - key_to_compare = "Tracestate"; - } - auto it = headers_.find(key_to_compare); - if (it != headers_.end()) - { - return it->second; - } - return ""; - } - - virtual void Set(nostd::string_view key, nostd::string_view value) noexcept override - { - headers_.insert(std::pair(std::string(key), std::string(value))); - } - - T headers_; -}; - -} // namespace \ No newline at end of file diff --git a/examples/grpc/server.cc b/examples/grpc/server.cpp similarity index 68% rename from examples/grpc/server.cc rename to examples/grpc/server.cpp index 38075c0a21..5be1707763 100644 --- a/examples/grpc/server.cc +++ b/examples/grpc/server.cpp @@ -1,5 +1,3 @@ -#include "grpc_foo_lib/foo_split.h" -#include "grpc_foo_lib/grpc_map_carrier.h" #include "messages.grpc.pb.h" #include "tracer_common.h" #include "opentelemetry/trace/span_context_kv_iterable_view.h" @@ -38,37 +36,21 @@ class GreeterServer final : public Greeter::Service const GreetRequest *request, GreetResponse *response) override { + for( auto elem: context->client_metadata()) { + std::cout << "ELEM: " << elem.first << " " << elem.second << "\n"; + } + // Create a SpanOptions object and set the kind to Server to inform OpenTel. opentelemetry::trace::StartSpanOptions options; options.kind = opentelemetry::trace::SpanKind::kServer; - // Create a text map carrier for our propagator. This carrier holds all of our - // information that needs to be propagated. We instantiate our carrier here as - // in your systems you will probably have information to fill it with before - // even starting your span, maybe your client's http headers. There is no way - // to get any carrier-relevant information at this point without doing work that - // we want to capture in a span, but we include the definition at this point to fit - // real-life scenarios - std::map m; - // Try inserting data into the map - // m.insert(std::pair("1", "2")); - // Also tried without passing a map at all, like in grpc/client.cc - const gRPCMapCarrier> carrier((std::map &) m); + + // extract context from http header + GrpcServerCarrier carrier(context); + auto prop = opentelemetry::context::propagation::GlobalTextMapPropagator::GetGlobalPropagator(); - // GetSpanFromContext fails here auto current_ctx = opentelemetry::context::RuntimeContext::GetCurrent(); - // GetSpanFromContext for new_context actually returns a span, suggesting there should be - // a usable parent span in this context auto new_context = prop->Extract(carrier, current_ctx); - auto s = GetSpanFromContext(new_context); - // Commented out debugging output. Only outputs '0 0 0 0 0 0' as the spanid, which - // I'm fairly sure indicates an inactive/invalid span - /* - opentelemetry::nostd::span sp = s->GetContext().span_id().Id(); - for(const uint8_t &e : sp) { - std::cout << unsigned(e) << ' '; - } - std::cout << '\n';*/ - options.parent = s->GetContext(); + options.parent = opentelemetry::trace::propagation::GetSpan(new_context)->GetContext(); // Build a new span from a tracer, start, and activate it. When adding // attributes to spans, be sure to follow the OpenTelemetry Semantic @@ -87,10 +69,10 @@ class GreeterServer final : public Greeter::Service // Fetch and parse whatever HTTP headers we can from the gRPC request. span->AddEvent("Processing client attributes"); - std::string peer_name = context->peer(); - std::vector peer_name_attributes = split(peer_name, ':'); + //std::string peer_name = context->peer(); + //std::vector peer_name_attributes = split(peer_name, ':'); - // Fill the carrier with other headers. gRPC runs on HTTP 2, so we add all + // Fill the carrier with other headers. gRPC runs on HTTP 2, so we add all // of the HTTP headers that we just extracted /*carrier.Set("net.ip.version", peer_name_attributes.at(0)); carrier.Set("net.peer.ip", peer_name_attributes.at(1)); diff --git a/examples/grpc/tracer_common.h b/examples/grpc/tracer_common.h index 2380784033..8d1df41ad4 100644 --- a/examples/grpc/tracer_common.h +++ b/examples/grpc/tracer_common.h @@ -1,3 +1,6 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + #pragma once #include "opentelemetry/exporters/ostream/span_exporter.h" #include "opentelemetry/sdk/trace/simple_processor.h" @@ -6,32 +9,57 @@ #include "opentelemetry/context/propagation/global_propagator.h" #include "opentelemetry/context/propagation/text_map_propagator.h" -#include "opentelemetry/context/runtime_context.h" +#include "opentelemetry/nostd/shared_ptr.h" #include "opentelemetry/trace/propagation/http_trace_context.h" -#include "opentelemetry/trace/scope.h" +#include #include #include #include -#include "opentelemetry/nostd/shared_ptr.h" -#include "opentelemetry/ext/http/client/http_client.h" + +using grpc::ClientContext; +using grpc::ServerContext; namespace { -inline nostd::shared_ptr GetSpanFromContext( - const opentelemetry::context::Context &context) +class GrpcClientCarrier : public opentelemetry::context::propagation::TextMapCarrier { - opentelemetry::context::ContextValue span = context.GetValue(opentelemetry::trace::kSpanKey); - if (nostd::holds_alternative>(span)) +public: + GrpcClientCarrier(ClientContext *context) : context_(context) {} + GrpcClientCarrier() = default; + virtual nostd::string_view Get(nostd::string_view key) const noexcept override { return ""; } + + virtual void Set(nostd::string_view key, nostd::string_view value) noexcept override { - //std::cout << "GETSPAN FROM CONTEXT YES\n"; - return nostd::get>(span); + std::cout << " Client ::: Adding " << key << " " << value << "\n"; + context_->AddMetadata(key.data(), value.data()); + } + + ClientContext *context_; +}; + +class GrpcServerCarrier : public opentelemetry::context::propagation::TextMapCarrier +{ +public: + GrpcServerCarrier(ServerContext *context) : context_(context) {} + GrpcServerCarrier() = default; + virtual nostd::string_view Get(nostd::string_view key) const noexcept override + { + auto it = context_->client_metadata().find(key.data()); + if (it != context_->client_metadata().end()) + { + return it->second.data(); + } + return ""; + } + + virtual void Set(nostd::string_view key, nostd::string_view value) noexcept override + { + // Not required for server } - static nostd::shared_ptr invalid_span{ - new opentelemetry::trace::DefaultSpan(opentelemetry::trace::SpanContext::GetInvalid())}; - //std::cout << "GETSPANFROMCONTEXT no\n"; - return invalid_span; -} + + ServerContext *context_; +}; void initTracer() { @@ -45,10 +73,10 @@ void initTracer() auto context = std::make_shared(std::move(processors)); auto provider = nostd::shared_ptr( new sdktrace::TracerProvider(context)); - // Set the global trace provide + // Set the global trace provider opentelemetry::trace::Provider::SetTracerProvider(provider); - // set global propagato + // set global propagator opentelemetry::context::propagation::GlobalTextMapPropagator::SetGlobalPropagator( nostd::shared_ptr( new opentelemetry::trace::propagation::HttpTraceContext())); @@ -60,13 +88,4 @@ nostd::shared_ptr get_tracer(std::string tracer_na return provider->GetTracer(tracer_name); } -// This function idempotently sets the global propagator and returns it to remove -// boilerplate from gRPC example services/library -nostd::shared_ptr get_propagator() -{ - auto propagator = - opentelemetry::context::propagation::GlobalTextMapPropagator::GetGlobalPropagator(); - return propagator; -} - } // namespace diff --git a/examples/http/server.cc b/examples/http/server.cc index cb055d77bf..48cf49216a 100644 --- a/examples/http/server.cc +++ b/examples/http/server.cc @@ -25,13 +25,15 @@ class RequestHandler : public HTTP_SERVER_NS::HttpRequestCallback auto prop = opentelemetry::context::propagation::GlobalTextMapPropagator::GetGlobalPropagator(); auto current_ctx = opentelemetry::context::RuntimeContext::GetCurrent(); auto new_context = prop->Extract(carrier, current_ctx); - opentelemetry::nostd::span sp = GetSpanFromContext(new_context)->GetContext().span_id().Id(); - for(const uint8_t &e : sp) { + opentelemetry::nostd::span sp = + GetSpanFromContext(new_context)->GetContext().span_id().Id(); + for (const uint8_t &e : sp) + { std::cout << unsigned(e) << ' '; } std::cout << '\n'; - - options.parent = GetSpanFromContext(new_context)->GetContext(); + + options.parent = GetSpanFromContext(new_context)->GetContext(); // start span with parent context extracted from http header auto span = get_tracer("http-server") From 464d52b8fd401f325fa2c26e8b48056c66917a62 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Wed, 2 Jun 2021 08:08:51 +0530 Subject: [PATCH 11/16] run only with WITH_OTLP --- examples/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index ea7550cae9..3112f3c85b 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,5 +1,6 @@ if(WITH_OTLP) add_subdirectory(otlp) + add_subdirectory(grpc) endif() if(WITH_JAEGER) add_subdirectory(jaeger) @@ -11,4 +12,3 @@ add_subdirectory(metrics_simple) add_subdirectory(multithreaded) add_subdirectory(multi_processor) add_subdirectory(http) -add_subdirectory(grpc) From 44dd7508be5269caccdd6aa099642bc5dce62a92 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Wed, 2 Jun 2021 08:13:31 +0530 Subject: [PATCH 12/16] revert --- tools/ports/benchmark/CONTROL | 10 +-- tools/ports/benchmark/portfile.cmake | 99 ++++++++++++++-------------- 2 files changed, 54 insertions(+), 55 deletions(-) diff --git a/tools/ports/benchmark/CONTROL b/tools/ports/benchmark/CONTROL index b55440df46..62b80dffae 100644 --- a/tools/ports/benchmark/CONTROL +++ b/tools/ports/benchmark/CONTROL @@ -1,5 +1,5 @@ -Source: benchmark -Version: 1.5.3 -Homepage: https://github.com/google/benchmark -Description: A library to support the benchmarking of functions, similar to unit-tests. -Supports: !(arm|uwp) +Source: benchmark +Version: 1.5.1 +Homepage: https://github.com/google/benchmark +Description: A library to support the benchmarking of functions, similar to unit-tests. +Supports: !uwp \ No newline at end of file diff --git a/tools/ports/benchmark/portfile.cmake b/tools/ports/benchmark/portfile.cmake index d946848b1e..e89fafca6c 100644 --- a/tools/ports/benchmark/portfile.cmake +++ b/tools/ports/benchmark/portfile.cmake @@ -1,50 +1,49 @@ -if (VCPKG_PLATFORM_TOOLSET STREQUAL "v140") - # set(CMAKE_C_COMPILER_WORKS 1) - # set(CMAKE_CXX_COMPILER_WORKS 1) - set(CMAKE_C_COMPILER cl.exe) - set(CMAKE_CXX_COMPILER cl.exe) - set(MSVC_TOOLSET_VERSION 140) - # set(VCPKG_VISUAL_STUDIO_PATH "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0") - # set(VCPKG_PLATFORM_TOOLSET v140) -else() - # Make sure vs2019 compiled binaries are compat with vs2017 - set(VCPKG_CXX_FLAGS "/Zc:__cplusplus /d2FH4-") - set(VCPKG_C_FLAGS "/Zc:__cplusplus /d2FH4-") - set(PREFER PREFER_NINJA) -endif() - -#https://github.com/google/benchmark/issues/661 -vcpkg_fail_port_install(ON_TARGET "uwp") - -vcpkg_check_linkage(ONLY_STATIC_LIBRARY) - -vcpkg_from_github( - OUT_SOURCE_PATH SOURCE_PATH - REPO google/benchmark - REF c05843a9f622db08ad59804c190f98879b76beba # v1.5.3 - SHA512 1 - HEAD_REF master - PATCHES "version.patch" -) - -vcpkg_configure_cmake( - SOURCE_PATH ${SOURCE_PATH} - ${PREFER} - OPTIONS - -DBENCHMARK_ENABLE_TESTING=OFF - -DCMAKE_DEBUG_POSTFIX=d -) - -vcpkg_install_cmake() - -vcpkg_copy_pdbs() - -vcpkg_fixup_cmake_targets(CONFIG_PATH lib/cmake/benchmark) - -vcpkg_fixup_pkgconfig(SYSTEM_LIBRARIES pthread) - -file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/include) -file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/share) - -# Handle copyright -file(INSTALL ${SOURCE_PATH}/LICENSE DESTINATION ${CURRENT_PACKAGES_DIR}/share/${PORT} RENAME copyright) +if(VCPKG_CMAKE_SYSTEM_NAME STREQUAL "WindowsStore") + message(FATAL_ERROR "${PORT} does not currently support UWP") +endif() + +if (VCPKG_PLATFORM_TOOLSET STREQUAL "v140") + # set(CMAKE_C_COMPILER_WORKS 1) + # set(CMAKE_CXX_COMPILER_WORKS 1) + set(CMAKE_C_COMPILER cl.exe) + set(CMAKE_CXX_COMPILER cl.exe) + set(MSVC_TOOLSET_VERSION 140) + # set(VCPKG_VISUAL_STUDIO_PATH "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0") + # set(VCPKG_PLATFORM_TOOLSET v140) +else() + # Make sure vs2019 compiled binaries are compat with vs2017 + set(VCPKG_CXX_FLAGS "/Zc:__cplusplus /d2FH4-") + set(VCPKG_C_FLAGS "/Zc:__cplusplus /d2FH4-") + set(PREFER PREFER_NINJA) +endif() + +include(vcpkg_common_functions) + +vcpkg_check_linkage(ONLY_STATIC_LIBRARY) + +vcpkg_from_github( + OUT_SOURCE_PATH SOURCE_PATH + REPO google/benchmark + HEAD_REF master +) + +vcpkg_configure_cmake( + SOURCE_PATH ${SOURCE_PATH} + ${PREFER} + OPTIONS + -DBENCHMARK_ENABLE_TESTING=OFF + -DCMAKE_DEBUG_POSTFIX=d +) + +vcpkg_install_cmake() + +vcpkg_copy_pdbs() + +vcpkg_fixup_cmake_targets(CONFIG_PATH lib/cmake/benchmark) + +file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/include) +file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/share) + +# Handle copyright +file(COPY ${SOURCE_PATH}/LICENSE DESTINATION ${CURRENT_PACKAGES_DIR}/share/benchmark) +file(RENAME ${CURRENT_PACKAGES_DIR}/share/benchmark/LICENSE ${CURRENT_PACKAGES_DIR}/share/benchmark/copyright) From bc4311fa812a29563baeefeb28f4fed521fdd234 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Wed, 2 Jun 2021 08:18:26 +0530 Subject: [PATCH 13/16] another revert try --- tools/ports/benchmark/CONTROL | 4 ++-- tools/ports/benchmark/portfile.cmake | 15 ++++++++------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/tools/ports/benchmark/CONTROL b/tools/ports/benchmark/CONTROL index 62b80dffae..4e522eb83d 100644 --- a/tools/ports/benchmark/CONTROL +++ b/tools/ports/benchmark/CONTROL @@ -1,5 +1,5 @@ Source: benchmark -Version: 1.5.1 +Version: 1.5.3 Homepage: https://github.com/google/benchmark Description: A library to support the benchmarking of functions, similar to unit-tests. -Supports: !uwp \ No newline at end of file +Supports: !(arm|uwp) diff --git a/tools/ports/benchmark/portfile.cmake b/tools/ports/benchmark/portfile.cmake index e89fafca6c..5a2779c493 100644 --- a/tools/ports/benchmark/portfile.cmake +++ b/tools/ports/benchmark/portfile.cmake @@ -1,7 +1,3 @@ -if(VCPKG_CMAKE_SYSTEM_NAME STREQUAL "WindowsStore") - message(FATAL_ERROR "${PORT} does not currently support UWP") -endif() - if (VCPKG_PLATFORM_TOOLSET STREQUAL "v140") # set(CMAKE_C_COMPILER_WORKS 1) # set(CMAKE_CXX_COMPILER_WORKS 1) @@ -17,14 +13,18 @@ else() set(PREFER PREFER_NINJA) endif() -include(vcpkg_common_functions) +#https://github.com/google/benchmark/issues/661 +vcpkg_fail_port_install(ON_TARGET "uwp") vcpkg_check_linkage(ONLY_STATIC_LIBRARY) vcpkg_from_github( OUT_SOURCE_PATH SOURCE_PATH REPO google/benchmark + REF c05843a9f622db08ad59804c190f98879b76beba # v1.5.3 + SHA512 1 HEAD_REF master + PATCHES "version.patch" ) vcpkg_configure_cmake( @@ -41,9 +41,10 @@ vcpkg_copy_pdbs() vcpkg_fixup_cmake_targets(CONFIG_PATH lib/cmake/benchmark) +vcpkg_fixup_pkgconfig(SYSTEM_LIBRARIES pthread) + file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/include) file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/share) # Handle copyright -file(COPY ${SOURCE_PATH}/LICENSE DESTINATION ${CURRENT_PACKAGES_DIR}/share/benchmark) -file(RENAME ${CURRENT_PACKAGES_DIR}/share/benchmark/LICENSE ${CURRENT_PACKAGES_DIR}/share/benchmark/copyright) +file(INSTALL ${SOURCE_PATH}/LICENSE DESTINATION ${CURRENT_PACKAGES_DIR}/share/${PORT} RENAME copyright) From 2fb974a64b35a2b35062c328f7dc882ea9a7b60f Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Wed, 2 Jun 2021 08:44:36 +0530 Subject: [PATCH 14/16] fix readme --- examples/grpc/README.md | 101 ++++++++++++++++----------------------- examples/grpc/client.cpp | 6 +-- examples/grpc/server.cpp | 13 ----- 3 files changed, 41 insertions(+), 79 deletions(-) diff --git a/examples/grpc/README.md b/examples/grpc/README.md index 58cd17c8e2..bc7e182294 100644 --- a/examples/grpc/README.md +++ b/examples/grpc/README.md @@ -15,53 +15,54 @@ This is a simple example that demonstrates tracing a gRPC request from client to ### Running the example -1. The example uses gRPC C++ as well as Google's protocol buffers. Make sure you have -installed both of these packages on your system, in such a way that CMake would know -how to find them with this command: +1. The example uses gRPC C++ as well as Google's protocol buffers. Make sure you have installed both + of these packages on your system, in such a way that CMake would know how to find them with this command: -```find_package(gRPC)``` + ``find_package(gRPC)`` If you install these with a package manager like '''brew''' or '''apt''', you should not need to do extra work. -2. Build and Deploy the opentelementry-cpp as described in [INSTALL.md](../../INSTALL.md). Building the project will build all of the examples and create new folders containing their executables within the 'build' directory NOT the 'examples' directory. +1. Build and Deploy the opentelementry-cpp as described in [INSTALL.md](../../INSTALL.md). Building the project will build all of the examples + and create new folders containing their executables within the 'build' directory NOT the 'examples' directory. -3. Start the server from your `build/examples/grpc` directory. Both the server and client are configured to use 8800 as the default port, but if you would like to use another port, you can specify that as an argument. +2. Start the server from your `build/examples/grpc` directory. Both the server and client are configured to use 8800 as the default port, + but if you would like to use another port, you can specify that as an argument. ```console $ ./server [port_num] Server listening on port: 0.0.0.0:8800 ``` -4. In a separate terminal window, run the client to make a single request: +3. In a separate terminal window, run the client to make a single request: ```console $ ./client [port_num] + ... ``` -5. You should see console exporter output for both the client and server sessions. +4. You should see console exporter output for both the client and server sessions. * Client console ```console { name : GreeterClient/Greet - trace_id : f898b8bca93936f112a56b710bb888eb - span_id : 8354bf34f7de06a0 + trace_id : f5d16f8399be0d2c6b39d992634ffdbb + span_id : 9c79a2dd744d7d2d tracestate : parent_span_id: 0000000000000000 - start : 1620434679192923000 - duration : 1571169 + start : 1622603339918985700 + duration : 4960500 description : span kind : Client status : Ok attributes : - rpc.grpc.status_code: 0 - net.peer.port: 8800 - rpc.system: grpc - net.peer.ip: 0.0.0.0 - rpc.method: Greet - rpc.service: grpc-example.GreetService + rpc.grpc.status_code: 0 + net.peer.port: 8080 + net.peer.ip: 0.0.0.0 + rpc.method: Greet + rpc.service: grpc-example.GreetService + rpc.system: grpc events : - links : } ``` @@ -69,54 +70,32 @@ If you install these with a package manager like '''brew''' or '''apt''', you sh ```console { - name : splitfunc - trace_id : 0836f1469dac75fddb57df13bcf33420 - span_id : 97b3f69fae5c0e15 - tracestate : - parent_span_id: 3d5fcaccc5617153 - start : 1620435268681957000 - duration : 38026 - description : - span kind : Internal - status : Unset - attributes : - events : - links : - } - - { - name : splitlib - trace_id : 0836f1469dac75fddb57df13bcf33420 - span_id : 3d5fcaccc5617153 - tracestate : - parent_span_id: a6aa48220c511354 - start : 1620435268681937000 - duration : 99145 - description : - span kind : Internal - status : Unset - attributes : - events : - links : - } - - { name : GreeterService/Greet - trace_id : 0836f1469dac75fddb57df13bcf33420 - span_id : a6aa48220c511354 + trace_id : f5d16f8399be0d2c6b39d992634ffdbb + span_id : 1e8a7d2d46e08573 tracestate : - parent_span_id: 0000000000000000 - start : 1620435268681893000 - duration : 178531 + parent_span_id: 9c79a2dd744d7d2d + start : 1622603339923163800 + duration : 76400 description : - span kind : Serve + span kind : Server status : Ok attributes : - rpc.grpc.status_code: 0 - rpc.method: Greet - rpc.service: GreeterService - rpc.system: grpc + rpc.grpc.status_code: 0 + rpc.method: Greet + rpc.service: GreeterService + rpc.system: grpc events : + { + name : Processing client attributes + timestamp : 1622603339923180800 + attributes : + } + { + name : Response sent to client + timestamp : 1622603339923233700 + attributes : + } links : } ``` diff --git a/examples/grpc/client.cpp b/examples/grpc/client.cpp index 1a4e3c74aa..dfd81c00cb 100644 --- a/examples/grpc/client.cpp +++ b/examples/grpc/client.cpp @@ -35,11 +35,7 @@ class GreeterClient opentelemetry::trace::StartSpanOptions options; options.kind = opentelemetry::trace::SpanKind::kClient; - // Spans are only as useful as the information that you put in them. - // Even though this is a client service, it can still be useful to add - // as much data as possible. We add attributes for peer ip and port, both - // because it is required per OpenTelemetry's rpc semantic conventions, - // and because it could still be useful to a debugger in the future. + std::string span_name = "GreeterClient/Greet"; auto span = get_tracer("grpc")->StartSpan(span_name, {{"rpc.system", "grpc"}, diff --git a/examples/grpc/server.cpp b/examples/grpc/server.cpp index 5be1707763..ed7482b26c 100644 --- a/examples/grpc/server.cpp +++ b/examples/grpc/server.cpp @@ -52,11 +52,6 @@ class GreeterServer final : public Greeter::Service auto new_context = prop->Extract(carrier, current_ctx); options.parent = opentelemetry::trace::propagation::GetSpan(new_context)->GetContext(); - // Build a new span from a tracer, start, and activate it. When adding - // attributes to spans, be sure to follow the OpenTelemetry Semantic - // Conventions that are relevant to your project as closely as possible - // Some protocols/patterns that have specified conventions: - // RPC, HTTP, AWS Lambda, Database, Exceptions, etc. std::string span_name = "GreeterService/Greet"; auto span = get_tracer("grpc") ->StartSpan(span_name, @@ -69,14 +64,6 @@ class GreeterServer final : public Greeter::Service // Fetch and parse whatever HTTP headers we can from the gRPC request. span->AddEvent("Processing client attributes"); - //std::string peer_name = context->peer(); - //std::vector peer_name_attributes = split(peer_name, ':'); - - // Fill the carrier with other headers. gRPC runs on HTTP 2, so we add all - // of the HTTP headers that we just extracted - /*carrier.Set("net.ip.version", peer_name_attributes.at(0)); - carrier.Set("net.peer.ip", peer_name_attributes.at(1)); - carrier.Set("net.peer.port", peer_name_attributes.at(2));*/ std::string req = request->request(); std::cout << std::endl << "grpc_client says: " << req << std::endl; From fadde9e37096ffc0d5d716abf70d433dd83c1b53 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Wed, 2 Jun 2021 08:47:17 +0530 Subject: [PATCH 15/16] fix readme --- examples/grpc/README.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/examples/grpc/README.md b/examples/grpc/README.md index bc7e182294..d964501aea 100644 --- a/examples/grpc/README.md +++ b/examples/grpc/README.md @@ -20,12 +20,10 @@ This is a simple example that demonstrates tracing a gRPC request from client to ``find_package(gRPC)`` -If you install these with a package manager like '''brew''' or '''apt''', you should not need to do extra work. - -1. Build and Deploy the opentelementry-cpp as described in [INSTALL.md](../../INSTALL.md). Building the project will build all of the examples +2. Build and Deploy the opentelementry-cpp as described in [INSTALL.md](../../INSTALL.md). Building the project will build all of the examples and create new folders containing their executables within the 'build' directory NOT the 'examples' directory. -2. Start the server from your `build/examples/grpc` directory. Both the server and client are configured to use 8800 as the default port, +3. Start the server from your `build/examples/grpc` directory. Both the server and client are configured to use 8800 as the default port, but if you would like to use another port, you can specify that as an argument. ```console @@ -33,14 +31,14 @@ If you install these with a package manager like '''brew''' or '''apt''', you sh Server listening on port: 0.0.0.0:8800 ``` -3. In a separate terminal window, run the client to make a single request: +4. In a separate terminal window, run the client to make a single request: ```console $ ./client [port_num] ... ``` -4. You should see console exporter output for both the client and server sessions. +5. You should see console exporter output for both the client and server sessions. * Client console ```console From 0e3c346cc290816865299dd24cc00c889e65498c Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Wed, 2 Jun 2021 09:09:42 +0530 Subject: [PATCH 16/16] format, and comments --- examples/grpc/client.cpp | 9 +++++---- examples/grpc/server.cpp | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/examples/grpc/client.cpp b/examples/grpc/client.cpp index dfd81c00cb..5ebdbf617d 100644 --- a/examples/grpc/client.cpp +++ b/examples/grpc/client.cpp @@ -47,10 +47,11 @@ class GreeterClient auto scope = get_tracer("grpc-client")->WithActiveSpan(span); - auto current_ctx = opentelemetry::context::RuntimeContext::GetCurrent(); - GrpcClientCarrier carrier(&context); - auto prop = opentelemetry::context::propagation::GlobalTextMapPropagator::GetGlobalPropagator(); - prop->Inject(carrier, current_ctx); + // inject current context to grpc metadata + auto current_ctx = opentelemetry::context::RuntimeContext::GetCurrent(); + GrpcClientCarrier carrier(&context); + auto prop = opentelemetry::context::propagation::GlobalTextMapPropagator::GetGlobalPropagator(); + prop->Inject(carrier, current_ctx); // Send request to server Status status = stub_->Greet(&context, request, &response); diff --git a/examples/grpc/server.cpp b/examples/grpc/server.cpp index ed7482b26c..167fc08966 100644 --- a/examples/grpc/server.cpp +++ b/examples/grpc/server.cpp @@ -44,7 +44,7 @@ class GreeterServer final : public Greeter::Service opentelemetry::trace::StartSpanOptions options; options.kind = opentelemetry::trace::SpanKind::kServer; - // extract context from http header + // extract context from grpc metadata GrpcServerCarrier carrier(context); auto prop = opentelemetry::context::propagation::GlobalTextMapPropagator::GetGlobalPropagator();