opentelemetry_gcloud_trace/
lib.rs

1//! # OpenTelemetry Google Cloud Trace Exporter
2//!
3//! OpenTelemetry exporter implementation for Google Cloud Trace
4//!
5//! ## Performance
6//!
7//! For optimal performance, a batch exporter is recommended as the simple exporter will export
8//! each span synchronously on drop. You can enable the [`rt-tokio`], [`rt-tokio-current-thread`]
9//! features and specify a runtime on the pipeline to have a batch exporter
10//! configured for you automatically.
11//!
12//! ```toml
13//! [dependencies]
14//! opentelemetry = { version = "*", features = ["rt-tokio"] }
15//! opentelemetry-gcloud-trace = "*"
16//! ```
17//!
18//! ```ignore
19//! let gcp_trace_exporter = GcpCloudTraceExporterBuilder::new(config_env_var("PROJECT_ID")?)
20//!
21//! let tracer_provider = gcp_trace_exporter.create_provider().await?;
22//! let tracer: opentelemetry_sdk::trace::Tracer = gcp_trace_exporter.install(&tracer_provider).await?;
23//!
24//! opentelemetry::global::set_tracer_provider(tracer_provider.clone());
25//!
26//! tracer.in_span("doing_work_parent", |cx| {
27//!   // ...
28//! });
29//!
30//! tracer_provider.shutdown()?;
31//! ```
32//! ## Configuration
33//!
34//! You can specify trace configuration using `create_provider_from_builder`:
35//!
36//! ```ignore
37//!    gcp_trace_exporter.create_provider_from_builder (
38//!       TracerProvider::builder()
39//!          .with_sampler(Sampler::AlwaysOn)
40//!          .with_id_generator(RandomIdGenerator::default())
41//!    )
42//! ```
43//!
44//! you can specify resource using `with_resource`:
45//! ```ignore
46//!    let resources = Resource::new(vec![KeyValue::new("service.name", "my-service")]);
47//!    GcpCloudTraceExporterBuilder::new(google_project_id).with_resource(resource).await?;
48//! ```
49//!
50//! Have a look at full examples in the `examples` directory.
51//!
52
53#![allow(unused_parens, clippy::new_without_default, clippy::needless_update)]
54
55pub mod errors;
56pub type TraceExportResult<E> = Result<E, crate::errors::GcloudTraceError>;
57
58mod google_trace_exporter_client;
59mod span_exporter;
60
61use crate::errors::GcloudTraceError;
62use opentelemetry::trace::TracerProvider;
63use opentelemetry::InstrumentationScope;
64use opentelemetry_sdk::error::OTelSdkError;
65use opentelemetry_sdk::trace::span_processor_with_async_runtime::BatchSpanProcessor;
66use opentelemetry_sdk::trace::{SdkTracerProvider, TracerProviderBuilder};
67use opentelemetry_sdk::{runtime, Resource};
68use rsb_derive::*;
69pub use span_exporter::GcpCloudTraceExporter;
70
71pub type SdkTracer = opentelemetry_sdk::trace::Tracer;
72
73#[derive(Debug, Builder)]
74pub struct GcpCloudTraceExporterBuilder {
75    pub google_project_id: String,
76    pub resource: Option<Resource>,
77}
78
79impl GcpCloudTraceExporterBuilder {
80    pub async fn for_default_project_id() -> TraceExportResult<Self> {
81        let detected_project_id = gcloud_sdk::GoogleEnvironment::detect_google_project_id().await.ok_or_else(||
82            crate::errors::GcloudTraceError::SystemError(
83                crate::errors::GcloudTraceSystemError::new(
84                    "No Google Project ID detected. Please specify it explicitly using env variable: PROJECT_ID or define it as default project for your service accounts".to_string()
85                )
86            )
87        )?;
88        Ok(Self::new(detected_project_id))
89    }
90
91    pub async fn create_provider(&self) -> Result<SdkTracerProvider, GcloudTraceError> {
92        self.create_provider_from_builder(SdkTracerProvider::builder())
93            .await
94    }
95
96    pub async fn create_provider_from_builder(
97        &self,
98        builder: TracerProviderBuilder,
99    ) -> Result<SdkTracerProvider, GcloudTraceError> {
100        let exporter = GcpCloudTraceExporter::new(
101            &self.google_project_id,
102            self.resource
103                .clone()
104                .unwrap_or_else(|| Resource::builder_empty().build()),
105        )
106        .await?;
107
108        let tracer_provider = builder
109            .with_span_processor(BatchSpanProcessor::builder(exporter, runtime::Tokio).build())
110            .build();
111
112        Ok(tracer_provider)
113    }
114
115    pub async fn install(
116        self,
117        provider: &SdkTracerProvider,
118    ) -> Result<opentelemetry_sdk::trace::Tracer, OTelSdkError> {
119        let scope = InstrumentationScope::builder("opentelemetry-gcloud")
120            .with_version(env!("CARGO_PKG_VERSION"))
121            .with_schema_url("https://opentelemetry.io/schemas/1.23.0")
122            .build();
123
124        let tracer = provider.tracer_with_scope(scope);
125        Ok(tracer)
126    }
127}