-
Notifications
You must be signed in to change notification settings - Fork 417
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
32f10c7
commit 2fce994
Showing
11 changed files
with
787 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 $<TARGET_FILE:protobuf::protoc>) | ||
set(_GRPC_GRPCPP gRPC::grpc++) | ||
set(_GRPC_CPP_PLUGIN_EXECUTABLE $<TARGET_FILE:gRPC::grpc_cpp_plugin>) | ||
|
||
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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 : | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 <grpcpp/grpcpp.h> | ||
#include <iostream> | ||
#include <string> | ||
|
||
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> 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<Greeter::Stub> 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; | ||
} |
Oops, something went wrong.