use tracing;
pub mod attributes {
pub const GRPC_METHOD: &str = "rpc.method";
pub const GRPC_SERVICE: &str = "rpc.service";
pub const RPC_SYSTEM: &str = "rpc.system";
pub const GRPC_STATUS_CODE: &str = "rpc.grpc.status_code";
pub const GRPC_REQUEST_SIZE: &str = "rpc.grpc.request.size";
pub const GRPC_RESPONSE_SIZE: &str = "rpc.grpc.response.size";
pub const GRPC_REQUEST_COUNT: &str = "rpc.grpc.request.count";
pub const GRPC_RESPONSE_COUNT: &str = "rpc.grpc.response.count";
}
pub fn parse_grpc_method(path: &str) -> Option<(&str, &str)> {
let path = path.strip_prefix('/')?;
let (service, method) = path.split_once('/')?;
if service.is_empty() || method.is_empty() {
return None;
}
Some((service, method))
}
pub fn record_grpc_attributes(method_path: &str) {
if let Some((service, method)) = parse_grpc_method(method_path) {
tracing::Span::current().record(attributes::RPC_SYSTEM, "grpc");
tracing::Span::current().record(attributes::GRPC_SERVICE, service);
tracing::Span::current().record(attributes::GRPC_METHOD, method);
}
}
pub fn record_grpc_status(status_code: i32) {
tracing::Span::current().record(attributes::GRPC_STATUS_CODE, status_code);
}
pub fn record_message_sizes(request_bytes: Option<u64>, response_bytes: Option<u64>) {
if let Some(req) = request_bytes {
tracing::Span::current().record(attributes::GRPC_REQUEST_SIZE, req);
}
if let Some(resp) = response_bytes {
tracing::Span::current().record(attributes::GRPC_RESPONSE_SIZE, resp);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_grpc_method() {
let result = parse_grpc_method("/mypackage.MyService/MyMethod");
assert_eq!(result, Some(("mypackage.MyService", "MyMethod")));
}
#[test]
fn test_parse_grpc_method_no_package() {
let result = parse_grpc_method("/MyService/MyMethod");
assert_eq!(result, Some(("MyService", "MyMethod")));
}
#[test]
fn test_parse_grpc_method_invalid() {
assert_eq!(parse_grpc_method(""), None);
assert_eq!(parse_grpc_method("/"), None);
assert_eq!(parse_grpc_method("no-leading-slash"), None);
assert_eq!(parse_grpc_method("//EmptyService"), None);
assert_eq!(parse_grpc_method("/Service/"), None);
}
}