1*cc02d7e2SAndroid Build Coastguard Worker //
2*cc02d7e2SAndroid Build Coastguard Worker //
3*cc02d7e2SAndroid Build Coastguard Worker // Copyright 2024 gRPC authors.
4*cc02d7e2SAndroid Build Coastguard Worker //
5*cc02d7e2SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
6*cc02d7e2SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
7*cc02d7e2SAndroid Build Coastguard Worker // You may obtain a copy of the License at
8*cc02d7e2SAndroid Build Coastguard Worker //
9*cc02d7e2SAndroid Build Coastguard Worker // http://www.apache.org/licenses/LICENSE-2.0
10*cc02d7e2SAndroid Build Coastguard Worker //
11*cc02d7e2SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
12*cc02d7e2SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
13*cc02d7e2SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*cc02d7e2SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
15*cc02d7e2SAndroid Build Coastguard Worker // limitations under the License.
16*cc02d7e2SAndroid Build Coastguard Worker //
17*cc02d7e2SAndroid Build Coastguard Worker //
18*cc02d7e2SAndroid Build Coastguard Worker
19*cc02d7e2SAndroid Build Coastguard Worker // Explicitly define HAVE_ABSEIL to avoid conflict with OTel's Abseil
20*cc02d7e2SAndroid Build Coastguard Worker // version. Refer
21*cc02d7e2SAndroid Build Coastguard Worker // https://github.com/open-telemetry/opentelemetry-cpp/issues/1042.
22*cc02d7e2SAndroid Build Coastguard Worker #ifndef HAVE_ABSEIL
23*cc02d7e2SAndroid Build Coastguard Worker #define HAVE_ABSEIL
24*cc02d7e2SAndroid Build Coastguard Worker #endif
25*cc02d7e2SAndroid Build Coastguard Worker
26*cc02d7e2SAndroid Build Coastguard Worker #include <condition_variable>
27*cc02d7e2SAndroid Build Coastguard Worker #include <mutex>
28*cc02d7e2SAndroid Build Coastguard Worker
29*cc02d7e2SAndroid Build Coastguard Worker #include "opentelemetry/sdk/metrics/view/instrument_selector_factory.h"
30*cc02d7e2SAndroid Build Coastguard Worker #include "opentelemetry/sdk/metrics/view/meter_selector_factory.h"
31*cc02d7e2SAndroid Build Coastguard Worker #include "opentelemetry/sdk/metrics/view/view_factory.h"
32*cc02d7e2SAndroid Build Coastguard Worker
33*cc02d7e2SAndroid Build Coastguard Worker #include <grpcpp/ext/proto_server_reflection_plugin.h>
34*cc02d7e2SAndroid Build Coastguard Worker #include <grpcpp/grpcpp.h>
35*cc02d7e2SAndroid Build Coastguard Worker #include <grpcpp/health_check_service_interface.h>
36*cc02d7e2SAndroid Build Coastguard Worker
37*cc02d7e2SAndroid Build Coastguard Worker #ifdef BAZEL_BUILD
38*cc02d7e2SAndroid Build Coastguard Worker #include "examples/cpp/otel/util.h"
39*cc02d7e2SAndroid Build Coastguard Worker #include "examples/protos/helloworld.grpc.pb.h"
40*cc02d7e2SAndroid Build Coastguard Worker #else
41*cc02d7e2SAndroid Build Coastguard Worker #include "helloworld.grpc.pb.h"
42*cc02d7e2SAndroid Build Coastguard Worker #include "util.h"
43*cc02d7e2SAndroid Build Coastguard Worker #endif
44*cc02d7e2SAndroid Build Coastguard Worker
45*cc02d7e2SAndroid Build Coastguard Worker using grpc::CallbackServerContext;
46*cc02d7e2SAndroid Build Coastguard Worker using grpc::Channel;
47*cc02d7e2SAndroid Build Coastguard Worker using grpc::ClientContext;
48*cc02d7e2SAndroid Build Coastguard Worker using grpc::Server;
49*cc02d7e2SAndroid Build Coastguard Worker using grpc::ServerBuilder;
50*cc02d7e2SAndroid Build Coastguard Worker using grpc::ServerUnaryReactor;
51*cc02d7e2SAndroid Build Coastguard Worker using grpc::Status;
52*cc02d7e2SAndroid Build Coastguard Worker using helloworld::Greeter;
53*cc02d7e2SAndroid Build Coastguard Worker using helloworld::HelloReply;
54*cc02d7e2SAndroid Build Coastguard Worker using helloworld::HelloRequest;
55*cc02d7e2SAndroid Build Coastguard Worker
AddLatencyView(opentelemetry::sdk::metrics::MeterProvider * provider,const std::string & name,const std::string & unit)56*cc02d7e2SAndroid Build Coastguard Worker void AddLatencyView(opentelemetry::sdk::metrics::MeterProvider* provider,
57*cc02d7e2SAndroid Build Coastguard Worker const std::string& name, const std::string& unit) {
58*cc02d7e2SAndroid Build Coastguard Worker auto histogram_config = std::make_shared<
59*cc02d7e2SAndroid Build Coastguard Worker opentelemetry::sdk::metrics::HistogramAggregationConfig>();
60*cc02d7e2SAndroid Build Coastguard Worker histogram_config->boundaries_ = {
61*cc02d7e2SAndroid Build Coastguard Worker 0, 0.00001, 0.00005, 0.0001, 0.0003, 0.0006, 0.0008, 0.001, 0.002,
62*cc02d7e2SAndroid Build Coastguard Worker 0.003, 0.004, 0.005, 0.006, 0.008, 0.01, 0.013, 0.016, 0.02,
63*cc02d7e2SAndroid Build Coastguard Worker 0.025, 0.03, 0.04, 0.05, 0.065, 0.08, 0.1, 0.13, 0.16,
64*cc02d7e2SAndroid Build Coastguard Worker 0.2, 0.25, 0.3, 0.4, 0.5, 0.65, 0.8, 1, 2,
65*cc02d7e2SAndroid Build Coastguard Worker 5, 10, 20, 50, 100};
66*cc02d7e2SAndroid Build Coastguard Worker provider->AddView(
67*cc02d7e2SAndroid Build Coastguard Worker opentelemetry::sdk::metrics::InstrumentSelectorFactory::Create(
68*cc02d7e2SAndroid Build Coastguard Worker opentelemetry::sdk::metrics::InstrumentType::kHistogram, name, unit),
69*cc02d7e2SAndroid Build Coastguard Worker opentelemetry::sdk::metrics::MeterSelectorFactory::Create(
70*cc02d7e2SAndroid Build Coastguard Worker "grpc-c++", grpc::Version(), ""),
71*cc02d7e2SAndroid Build Coastguard Worker opentelemetry::sdk::metrics::ViewFactory::Create(
72*cc02d7e2SAndroid Build Coastguard Worker name, "", unit,
73*cc02d7e2SAndroid Build Coastguard Worker opentelemetry::sdk::metrics::AggregationType::kHistogram,
74*cc02d7e2SAndroid Build Coastguard Worker std::move(histogram_config)));
75*cc02d7e2SAndroid Build Coastguard Worker }
76*cc02d7e2SAndroid Build Coastguard Worker
77*cc02d7e2SAndroid Build Coastguard Worker namespace {
78*cc02d7e2SAndroid Build Coastguard Worker
79*cc02d7e2SAndroid Build Coastguard Worker class GreeterClient {
80*cc02d7e2SAndroid Build Coastguard Worker public:
GreeterClient(std::shared_ptr<Channel> channel)81*cc02d7e2SAndroid Build Coastguard Worker GreeterClient(std::shared_ptr<Channel> channel)
82*cc02d7e2SAndroid Build Coastguard Worker : stub_(Greeter::NewStub(channel)) {}
83*cc02d7e2SAndroid Build Coastguard Worker
84*cc02d7e2SAndroid Build Coastguard Worker // Assembles the client's payload, sends it and presents the response back
85*cc02d7e2SAndroid Build Coastguard Worker // from the server.
SayHello(const std::string & user)86*cc02d7e2SAndroid Build Coastguard Worker std::string SayHello(const std::string& user) {
87*cc02d7e2SAndroid Build Coastguard Worker // Data we are sending to the server.
88*cc02d7e2SAndroid Build Coastguard Worker HelloRequest request;
89*cc02d7e2SAndroid Build Coastguard Worker request.set_name(user);
90*cc02d7e2SAndroid Build Coastguard Worker
91*cc02d7e2SAndroid Build Coastguard Worker // Container for the data we expect from the server.
92*cc02d7e2SAndroid Build Coastguard Worker HelloReply reply;
93*cc02d7e2SAndroid Build Coastguard Worker
94*cc02d7e2SAndroid Build Coastguard Worker // Context for the client. It could be used to convey extra information to
95*cc02d7e2SAndroid Build Coastguard Worker // the server and/or tweak certain RPC behaviors.
96*cc02d7e2SAndroid Build Coastguard Worker ClientContext context;
97*cc02d7e2SAndroid Build Coastguard Worker
98*cc02d7e2SAndroid Build Coastguard Worker // The actual RPC.
99*cc02d7e2SAndroid Build Coastguard Worker std::mutex mu;
100*cc02d7e2SAndroid Build Coastguard Worker std::condition_variable cv;
101*cc02d7e2SAndroid Build Coastguard Worker bool done = false;
102*cc02d7e2SAndroid Build Coastguard Worker Status status;
103*cc02d7e2SAndroid Build Coastguard Worker stub_->async()->SayHello(&context, &request, &reply,
104*cc02d7e2SAndroid Build Coastguard Worker [&mu, &cv, &done, &status](Status s) {
105*cc02d7e2SAndroid Build Coastguard Worker status = std::move(s);
106*cc02d7e2SAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(mu);
107*cc02d7e2SAndroid Build Coastguard Worker done = true;
108*cc02d7e2SAndroid Build Coastguard Worker cv.notify_one();
109*cc02d7e2SAndroid Build Coastguard Worker });
110*cc02d7e2SAndroid Build Coastguard Worker
111*cc02d7e2SAndroid Build Coastguard Worker std::unique_lock<std::mutex> lock(mu);
112*cc02d7e2SAndroid Build Coastguard Worker while (!done) {
113*cc02d7e2SAndroid Build Coastguard Worker cv.wait(lock);
114*cc02d7e2SAndroid Build Coastguard Worker }
115*cc02d7e2SAndroid Build Coastguard Worker
116*cc02d7e2SAndroid Build Coastguard Worker // Act upon its status.
117*cc02d7e2SAndroid Build Coastguard Worker if (status.ok()) {
118*cc02d7e2SAndroid Build Coastguard Worker return reply.message();
119*cc02d7e2SAndroid Build Coastguard Worker } else {
120*cc02d7e2SAndroid Build Coastguard Worker std::cout << status.error_code() << ": " << status.error_message()
121*cc02d7e2SAndroid Build Coastguard Worker << std::endl;
122*cc02d7e2SAndroid Build Coastguard Worker return "RPC failed";
123*cc02d7e2SAndroid Build Coastguard Worker }
124*cc02d7e2SAndroid Build Coastguard Worker }
125*cc02d7e2SAndroid Build Coastguard Worker
126*cc02d7e2SAndroid Build Coastguard Worker private:
127*cc02d7e2SAndroid Build Coastguard Worker std::unique_ptr<Greeter::Stub> stub_;
128*cc02d7e2SAndroid Build Coastguard Worker };
129*cc02d7e2SAndroid Build Coastguard Worker
130*cc02d7e2SAndroid Build Coastguard Worker // Logic and data behind the server's behavior.
131*cc02d7e2SAndroid Build Coastguard Worker class GreeterServiceImpl final : public Greeter::CallbackService {
SayHello(CallbackServerContext * context,const HelloRequest * request,HelloReply * reply)132*cc02d7e2SAndroid Build Coastguard Worker ServerUnaryReactor* SayHello(CallbackServerContext* context,
133*cc02d7e2SAndroid Build Coastguard Worker const HelloRequest* request,
134*cc02d7e2SAndroid Build Coastguard Worker HelloReply* reply) override {
135*cc02d7e2SAndroid Build Coastguard Worker std::string prefix("Hello ");
136*cc02d7e2SAndroid Build Coastguard Worker reply->set_message(prefix + request->name());
137*cc02d7e2SAndroid Build Coastguard Worker
138*cc02d7e2SAndroid Build Coastguard Worker ServerUnaryReactor* reactor = context->DefaultReactor();
139*cc02d7e2SAndroid Build Coastguard Worker reactor->Finish(Status::OK);
140*cc02d7e2SAndroid Build Coastguard Worker return reactor;
141*cc02d7e2SAndroid Build Coastguard Worker }
142*cc02d7e2SAndroid Build Coastguard Worker };
143*cc02d7e2SAndroid Build Coastguard Worker
144*cc02d7e2SAndroid Build Coastguard Worker } // namespace
145*cc02d7e2SAndroid Build Coastguard Worker
RunServer(uint16_t port)146*cc02d7e2SAndroid Build Coastguard Worker void RunServer(uint16_t port) {
147*cc02d7e2SAndroid Build Coastguard Worker std::string server_address = absl::StrFormat("0.0.0.0:%d", port);
148*cc02d7e2SAndroid Build Coastguard Worker GreeterServiceImpl service;
149*cc02d7e2SAndroid Build Coastguard Worker
150*cc02d7e2SAndroid Build Coastguard Worker grpc::EnableDefaultHealthCheckService(true);
151*cc02d7e2SAndroid Build Coastguard Worker grpc::reflection::InitProtoReflectionServerBuilderPlugin();
152*cc02d7e2SAndroid Build Coastguard Worker ServerBuilder builder;
153*cc02d7e2SAndroid Build Coastguard Worker // Listen on the given address without any authentication mechanism.
154*cc02d7e2SAndroid Build Coastguard Worker builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
155*cc02d7e2SAndroid Build Coastguard Worker // Register "service" as the instance through which we'll communicate with
156*cc02d7e2SAndroid Build Coastguard Worker // clients. In this case it corresponds to an *synchronous* service.
157*cc02d7e2SAndroid Build Coastguard Worker builder.RegisterService(&service);
158*cc02d7e2SAndroid Build Coastguard Worker // Finally assemble the server.
159*cc02d7e2SAndroid Build Coastguard Worker std::unique_ptr<Server> server(builder.BuildAndStart());
160*cc02d7e2SAndroid Build Coastguard Worker std::cout << "Server listening on " << server_address << std::endl;
161*cc02d7e2SAndroid Build Coastguard Worker
162*cc02d7e2SAndroid Build Coastguard Worker // Wait for the server to shutdown. Note that some other thread must be
163*cc02d7e2SAndroid Build Coastguard Worker // responsible for shutting down the server for this call to ever return.
164*cc02d7e2SAndroid Build Coastguard Worker server->Wait();
165*cc02d7e2SAndroid Build Coastguard Worker }
166*cc02d7e2SAndroid Build Coastguard Worker
RunClient(const std::string & target_str)167*cc02d7e2SAndroid Build Coastguard Worker void RunClient(const std::string& target_str) {
168*cc02d7e2SAndroid Build Coastguard Worker // Instantiate the client. It requires a channel, out of which the actual RPCs
169*cc02d7e2SAndroid Build Coastguard Worker // are created. This channel models a connection to an endpoint specified by
170*cc02d7e2SAndroid Build Coastguard Worker // the argument "--target=" which is the only expected argument.
171*cc02d7e2SAndroid Build Coastguard Worker grpc::ChannelArguments args;
172*cc02d7e2SAndroid Build Coastguard Worker // Continuously send RPCs every second.
173*cc02d7e2SAndroid Build Coastguard Worker while (true) {
174*cc02d7e2SAndroid Build Coastguard Worker GreeterClient greeter(grpc::CreateCustomChannel(
175*cc02d7e2SAndroid Build Coastguard Worker target_str, grpc::InsecureChannelCredentials(), args));
176*cc02d7e2SAndroid Build Coastguard Worker std::string user("world");
177*cc02d7e2SAndroid Build Coastguard Worker std::string reply = greeter.SayHello(user);
178*cc02d7e2SAndroid Build Coastguard Worker std::cout << "Greeter received: " << reply << std::endl;
179*cc02d7e2SAndroid Build Coastguard Worker std::this_thread::sleep_for(std::chrono::seconds(1));
180*cc02d7e2SAndroid Build Coastguard Worker }
181*cc02d7e2SAndroid Build Coastguard Worker }
182