tracing_datadog_macros/
lib.rs

1//! Collection of tracing macros
2//!
3//! # Example
4//!
5//! ```rust
6//! use tracing_datadog_macros::instrument_web;
7//!
8//! #[instrument_web(skip(self))]
9//! async fn process_data(&self, data: Data) {
10//!     // ...
11//! }
12//! ```
13
14#![warn(clippy::pedantic)]
15#![warn(clippy::nursery)]
16#![warn(clippy::cargo)]
17
18mod attr;
19
20use proc_macro::TokenStream;
21use quote::quote;
22
23const HTTP: &str = r#"span.type = "http""#;
24const QUEUE_CONSUMER: &str = r#"span.type = "queue", span.kind = "consumer", messaging.system = "pgmq""#;
25const QUEUE_PRODUCER: &str = r#"span.type = "queue", span.kind = "producer", messaging.system = "pgmq""#;
26const SQL: &str = r#"span.type = "sql", service.name = "database", db.system = "postgresql""#;
27const WEB: &str = r#"span.type = "web""#;
28
29#[proc_macro_attribute]
30pub fn instrument_custom(attr: TokenStream, item: TokenStream) -> TokenStream {
31    generate_instrumented_method(attr, item, "", Some(vec!["service_name"])).into()
32}
33
34#[proc_macro_attribute]
35pub fn instrument_http(attr: TokenStream, item: TokenStream) -> TokenStream {
36    generate_instrumented_method(attr, item, HTTP, Some(vec!["service_name"])).into()
37}
38
39#[proc_macro_attribute]
40pub fn instrument_queue_consumer(attr: TokenStream, item: TokenStream) -> TokenStream {
41    generate_instrumented_method(attr, item, QUEUE_CONSUMER, Some(vec!["service_name"])).into()
42}
43
44#[proc_macro_attribute]
45pub fn instrument_queue_producer(attr: TokenStream, item: TokenStream) -> TokenStream {
46    generate_instrumented_method(attr, item, QUEUE_PRODUCER, Some(vec!["service_name"])).into()
47}
48
49#[proc_macro_attribute]
50pub fn instrument_sql(attr: TokenStream, item: TokenStream) -> TokenStream {
51    generate_instrumented_method(attr, item, SQL, None).into()
52}
53
54#[proc_macro_attribute]
55pub fn instrument_web(attr: TokenStream, item: TokenStream) -> TokenStream {
56    generate_instrumented_method(attr, item, WEB, None).into()
57}
58
59#[allow(clippy::needless_pass_by_value)]
60fn generate_instrumented_method(
61    attr: TokenStream,
62    item: TokenStream,
63    extra_fields: &str,
64    required_attrs: Option<Vec<&str>>,
65) -> proc_macro2::TokenStream {
66    let attr: proc_macro2::TokenStream = attr.into();
67    let item: proc_macro2::TokenStream = item.into();
68    let extended_attr: proc_macro2::TokenStream =
69        attr::extend_fields(attr.to_string().as_str(), extra_fields, required_attrs)
70            .parse()
71            .unwrap();
72
73    quote!(
74        #[tracing::instrument(#extended_attr)]
75        #item
76    )
77}