tracing_gcloud_layer/lib.rs
1use derive_builder::Builder;
2use google_logger::{GoogleLogger, LogMapper, LoggerError};
3use tracing_subscriber::Registry;
4
5use self::default_mapper::DefaultLogMapper;
6use self::google_writer::GoogleWriter;
7
8mod config;
9mod default_mapper;
10mod gauth;
11pub mod google_logger;
12pub mod google_writer;
13mod log_entry;
14mod utils;
15
16pub use config::GoogleWriterConfig;
17pub use utils::{extract_trace_id, get_severity};
18
19pub type DefaultGCloudLayerConfig = GCloudLayerConfig<DefaultLogMapper>;
20pub type DefaultGCloudLayerConfigBuilder = GCloudLayerConfigBuilder<DefaultLogMapper>;
21
22/// Configuration for setting up Google Cloud logging with `tracing`.
23///
24/// `GCloudLayerConfig` holds everything needed to build a `tracing_stackdriver` layer
25/// that sends logs to Google Cloud Logging. It supports custom log mappers, batching,
26/// and uses service account credentials for authentication.
27///
28/// Use `.build_layer()` to produce a ready-to-use `tracing` layer.
29#[derive(Builder, Clone)]
30#[builder(pattern = "owned", setter(into, strip_option))]
31pub struct GCloudLayerConfig<M: LogMapper = DefaultLogMapper> {
32 /// The log name shown in Cloud Logging (e.g., `"stdout"` or `"my-service"`).
33 log_name: String,
34 /// Raw bytes of a Google service account JSON key.
35 logger_credential: Vec<u8>,
36 #[builder(default)]
37 config: GoogleWriterConfig,
38 #[builder(default)]
39 log_mapper: M,
40}
41
42impl<M: LogMapper> GCloudLayerConfig<M> {
43 /// Builds a `tracing_stackdriver` layer using this config.
44 ///
45 /// Creates a `GoogleLogger` from the provided log name and credentials,
46 /// then wraps it in a `GoogleWriter` for async batching. Returns a
47 /// `tracing_stackdriver` layer that can be added to a subscriber.
48 ///
49 /// # Example
50 /// ```no_run
51 /// use tracing_gcloud_layer::DefaultGCloudLayerConfigBuilder;
52 /// use tracing_subscriber::prelude::*;
53 ///
54 /// fn main() -> Result<(), Box<dyn std::error::Error>> {
55 /// let svc_account_bytes = std::fs::read("svc-account.json")?;
56 ///
57 /// let layer = DefaultGCloudLayerConfigBuilder::default()
58 /// .log_name("my-service")
59 /// .logger_credential(svc_account_bytes)
60 /// .build()?
61 /// .build_layer()?;
62 ///
63 /// tracing_subscriber::registry().with(layer).init();
64 /// Ok(())
65 /// }
66 /// ```
67 pub fn build_layer(
68 self,
69 ) -> Result<tracing_stackdriver::Layer<Registry, impl Fn() -> GoogleWriter<M>>, LoggerError>
70 {
71 let GCloudLayerConfig {
72 config,
73 log_mapper,
74 log_name,
75 logger_credential,
76 } = self;
77
78 let log_name = std::sync::Arc::from(log_name);
79 let logger = GoogleLogger::new(log_name, logger_credential, log_mapper)?;
80
81 Ok(tracing_stackdriver::layer()
82 .with_writer(move || GoogleWriter::new(logger.clone(), config.clone())))
83 }
84}