-
Notifications
You must be signed in to change notification settings - Fork 384
/
server.rs
88 lines (73 loc) · 2.9 KB
/
server.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
use hello_world::greeter_server::{Greeter, GreeterServer};
use hello_world::{HelloReply, HelloRequest};
use opentelemetry::sdk::propagation::TraceContextPropagator;
use opentelemetry::{global, propagation::Extractor};
use tonic::{transport::Server, Request, Response, Status};
use tracing::*;
use tracing_opentelemetry::OpenTelemetrySpanExt;
use tracing_subscriber::prelude::*;
pub mod hello_world {
tonic::include_proto!("helloworld"); // The string specified here must match the proto package name
}
struct MetadataMap<'a>(&'a tonic::metadata::MetadataMap);
impl<'a> Extractor for MetadataMap<'a> {
/// Get a value for a key from the MetadataMap. If the value can't be converted to &str, returns None
fn get(&self, key: &str) -> Option<&str> {
self.0.get(key).and_then(|metadata| metadata.to_str().ok())
}
/// Collect all the keys from the MetadataMap.
fn keys(&self) -> Vec<&str> {
self.0
.keys()
.map(|key| match key {
tonic::metadata::KeyRef::Ascii(v) => v.as_str(),
tonic::metadata::KeyRef::Binary(v) => v.as_str(),
})
.collect::<Vec<_>>()
}
}
#[instrument]
fn expensive_fn(to_print: String) {
std::thread::sleep(std::time::Duration::from_millis(20));
info!("{}", to_print);
}
#[derive(Debug, Default)]
pub struct MyGreeter {}
#[tonic::async_trait]
impl Greeter for MyGreeter {
#[instrument]
async fn say_hello(
&self,
request: Request<HelloRequest>, // Accept request of type HelloRequest
) -> Result<Response<HelloReply>, Status> {
let parent_cx =
global::get_text_map_propagator(|prop| prop.extract(&MetadataMap(request.metadata())));
tracing::Span::current().set_parent(parent_cx);
let name = request.into_inner().name;
expensive_fn(format!("Got name: {:?}", name));
// Return an instance of type HelloReply
let reply = hello_world::HelloReply {
message: format!("Hello {}!", name), // We must use .into_inner() as the fields of gRPC requests and responses are private
};
Ok(Response::new(reply)) // Send back our formatted greeting
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
global::set_text_map_propagator(TraceContextPropagator::new());
let tracer = opentelemetry_jaeger::new_pipeline()
.with_service_name("grpc-server")
.install_batch(opentelemetry::runtime::Tokio)?;
tracing_subscriber::registry()
.with(tracing_subscriber::EnvFilter::new("INFO"))
.with(tracing_opentelemetry::layer().with_tracer(tracer))
.try_init()?;
let addr = "[::1]:50051".parse()?;
let greeter = MyGreeter::default();
Server::builder()
.add_service(GreeterServer::new(greeter))
.serve(addr)
.await?;
opentelemetry::global::shutdown_tracer_provider();
Ok(())
}