From 7d4b9d9e784988bc70c026473aa6a22f5fb6e807 Mon Sep 17 00:00:00 2001 From: Ty Bekiares <107002404+ty-elastic@users.noreply.github.com> Date: Mon, 21 Nov 2022 10:23:42 -0600 Subject: [PATCH] [shippingservice] add grpc conventions (#597) Co-authored-by: Austin Parker --- docs/services/shippingservice.md | 22 ++++++++++------- src/shippingservice/Cargo.lock | 10 ++++++++ src/shippingservice/Cargo.toml | 1 + src/shippingservice/src/shipping_service.rs | 26 +++++++++++++++------ 4 files changed, 44 insertions(+), 15 deletions(-) diff --git a/docs/services/shippingservice.md b/docs/services/shippingservice.md index ada111b862..2b6e538e60 100644 --- a/docs/services/shippingservice.md +++ b/docs/services/shippingservice.md @@ -65,15 +65,17 @@ The root span is started and passed down as reference in the same thread to another closure where we call `quoteservice`. ```rust - let tracer = global::tracer("shippingservice/get-quote"); - let mut span = tracer.start_with_context("get-quote", &parent_cx); + let tracer = global::tracer("shippingservice"); + let mut span = tracer.span_builder("hipstershop.ShippingService/GetQuote").with_kind(SpanKind::Server).start_with_context(&tracer, &parent_cx); + span.set_attribute(semcov::trace::RPC_SYSTEM.string(RPC_SYSTEM_GRPC)); span.add_event("Processing get quote request".to_string(), vec![]); + let cx = Context::current_with_span(span); let q = match create_quote_from_count(itemct) - .with_context(Context::current_with_span(span)) + .with_context(cx.clone()) .await -//...create_quote_from_count... +//-> create_quote_from_count()... let f = match request_quote(count).await { Ok(float) => float, Err(err) => { @@ -92,10 +94,13 @@ to another closure where we call `quoteservice`. span.set_attribute(KeyValue::new("app.shipping.cost.total", format!("{}", q))); q })) +//<- create_quote_from_count()... + cx.span().set_attribute(semcov::trace::RPC_GRPC_STATUS_CODE.i64(RPC_GRPC_STATUS_CODE_OK)); ``` -Note that the span cannot be used after calling an async method in the -originating function. +Note that we create a context around the root span and send a clone to the +async function create_quote_from_count(). After create_quote_from_count() +completes, we can add additional attributes to the root span as appropriate. You may also notice the `attributes` set on the span in this example, and `events` propogated similarly. With any valid `span` pointer (attached to @@ -119,8 +124,9 @@ This is appropriate in our case of a sync runtime. global::get_text_map_propagator(|prop| prop.extract(&MetadataMap(request.metadata()))); // in this case, generating a tracking ID is trivial // we'll create a span and associated events all in this function. - let mut span = global::tracer("shippingservice/ship-order") - .start_with_context("ship-order", &parent_cx); + let tracer = global::tracer("shippingservice"); + let mut span = tracer + .span_builder("hipstershop.ShippingService/ShipOrder").with_kind(SpanKind::Server).start_with_context(&tracer, &parent_cx); ``` You must add attributes to a span in context with `set_attribute`, followed by a diff --git a/src/shippingservice/Cargo.lock b/src/shippingservice/Cargo.lock index 5328ab2f28..5cb67153a9 100644 --- a/src/shippingservice/Cargo.lock +++ b/src/shippingservice/Cargo.lock @@ -618,6 +618,15 @@ dependencies = [ "tonic-build", ] +[[package]] +name = "opentelemetry-semantic-conventions" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b02e0230abb0ab6636d18e2ba8fa02903ea63772281340ccac18e0af3ec9eeb" +dependencies = [ + "opentelemetry", +] + [[package]] name = "opentelemetry_api" version = "0.18.0" @@ -952,6 +961,7 @@ dependencies = [ "opentelemetry", "opentelemetry-http", "opentelemetry-otlp", + "opentelemetry-semantic-conventions", "opentelemetry_api", "prost", "prost-types", diff --git a/src/shippingservice/Cargo.toml b/src/shippingservice/Cargo.toml index 97def98776..f1d59601fd 100644 --- a/src/shippingservice/Cargo.toml +++ b/src/shippingservice/Cargo.toml @@ -18,6 +18,7 @@ prost = "0.11" prost-types = "0.11" tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] } opentelemetry = { version = "0.18", features = ["rt-tokio", "trace"] } +opentelemetry-semantic-conventions = "0.10.0" opentelemetry_api = { version = "0.18" } opentelemetry-http = "0.7.0" opentelemetry-otlp = "0.11.0" diff --git a/src/shippingservice/src/shipping_service.rs b/src/shippingservice/src/shipping_service.rs index 38142f25e2..67c3481494 100644 --- a/src/shippingservice/src/shipping_service.rs +++ b/src/shippingservice/src/shipping_service.rs @@ -1,5 +1,6 @@ use opentelemetry::{global, propagation::Extractor, trace::Span, Context, KeyValue}; -use opentelemetry_api::trace::{FutureExt, TraceContextExt, Tracer}; +use opentelemetry_api::trace::{FutureExt, TraceContextExt, SpanKind, Tracer}; +use opentelemetry_semantic_conventions as semcov; use shop::shipping_service_server::ShippingService; use shop::{GetQuoteRequest, GetQuoteResponse, Money, ShipOrderRequest, ShipOrderResponse}; use tonic::{Request, Response, Status}; @@ -14,6 +15,10 @@ use tracking::create_tracking_id; const NANOS_MULTIPLE: i32 = 10000000i32; +const RPC_SYSTEM_GRPC: &'static str = "grpc"; +const RPC_GRPC_STATUS_CODE_OK: i64 = 0; +const RPC_GRPC_STATUS_CODE_UNKNOWN: i64 = 2; + pub mod shop { tonic::include_proto!("hipstershop"); // The string specified here must match the proto package name } @@ -61,17 +66,20 @@ impl ShippingService for ShippingServer { // We may want to ask another service for product pricing / info // (although now everything is assumed to be the same price) // check out the create_quote_from_count method to see how we use the span created here - let tracer = global::tracer("shippingservice/get-quote"); - let mut span = tracer.start_with_context("get-quote", &parent_cx); + let tracer = global::tracer("shippingservice"); + let mut span = tracer.span_builder("hipstershop.ShippingService/GetQuote").with_kind(SpanKind::Server).start_with_context(&tracer, &parent_cx); + span.set_attribute(semcov::trace::RPC_SYSTEM.string(RPC_SYSTEM_GRPC)); + span.add_event("Processing get quote request".to_string(), vec![]); span.set_attribute(KeyValue::new("app.shipping.zip_code", request_message.address.unwrap().zip_code)); + let cx = Context::current_with_span(span); let q = match create_quote_from_count(itemct) - .with_context(Context::current_with_span(span)) + .with_context(cx.clone()) .await { Ok(quote) => quote, - Err(status) => return Err(status), + Err(status) => {cx.span().set_attribute(semcov::trace::RPC_GRPC_STATUS_CODE.i64(RPC_GRPC_STATUS_CODE_UNKNOWN)); return Err(status)}, }; let reply = GetQuoteResponse { @@ -83,6 +91,7 @@ impl ShippingService for ShippingServer { }; info!("Sending Quote: {}", q); + cx.span().set_attribute(semcov::trace::RPC_GRPC_STATUS_CODE.i64(RPC_GRPC_STATUS_CODE_OK)); Ok(Response::new(reply)) } async fn ship_order( @@ -95,8 +104,10 @@ impl ShippingService for ShippingServer { global::get_text_map_propagator(|prop| prop.extract(&MetadataMap(request.metadata()))); // in this case, generating a tracking ID is trivial // we'll create a span and associated events all in this function. - let mut span = global::tracer("shippingservice/ship-order") - .start_with_context("ship-order", &parent_cx); + let tracer = global::tracer("shippingservice"); + let mut span = tracer + .span_builder("hipstershop.ShippingService/ShipOrder").with_kind(SpanKind::Server).start_with_context(&tracer, &parent_cx); + span.set_attribute(semcov::trace::RPC_SYSTEM.string(RPC_SYSTEM_GRPC)); span.add_event("Processing shipping order request".to_string(), vec![]); @@ -109,6 +120,7 @@ impl ShippingService for ShippingServer { vec![], ); + span.set_attribute(semcov::trace::RPC_GRPC_STATUS_CODE.i64(RPC_GRPC_STATUS_CODE_OK)); Ok(Response::new(ShipOrderResponse { tracking_id: tid })) } }