1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
/*
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0
 */

//! Definitions of high level Telemetry Providers.

use std::sync::Arc;

use crate::{meter::ProvideMeter, noop::NoopMeterProvider};

/// A struct to hold the various types of telemetry providers.
#[non_exhaustive]
pub struct TelemetryProvider {
    meter_provider: Box<dyn ProvideMeter + Send + Sync>,
}

impl TelemetryProvider {
    /// Returns a builder struct for [TelemetryProvider]
    pub fn builder() -> TelemetryProviderBuilder {
        TelemetryProviderBuilder {
            meter_provider: Box::new(NoopMeterProvider),
        }
    }

    /// Returns a noop [TelemetryProvider]
    pub fn noop() -> TelemetryProvider {
        Self {
            meter_provider: Box::new(NoopMeterProvider),
        }
    }

    /// Get the set [ProvideMeter]
    pub fn meter_provider(&self) -> &(dyn ProvideMeter + Send + Sync) {
        self.meter_provider.as_ref()
    }
}

// If we choose to expand our Telemetry provider and make Logging and Tracing
// configurable at some point in the future we can do that by adding default
// logger_provider and tracer_providers based on `tracing` to maintain backwards
// compatibilty with what we have today.
impl Default for TelemetryProvider {
    fn default() -> Self {
        Self {
            meter_provider: Box::new(NoopMeterProvider),
        }
    }
}

/// A builder for [TelemetryProvider].
#[non_exhaustive]
pub struct TelemetryProviderBuilder {
    meter_provider: Box<dyn ProvideMeter + Send + Sync>,
}

impl TelemetryProviderBuilder {
    /// Set the [ProvideMeter].
    pub fn meter_provider(
        mut self,
        meter_provider: impl ProvideMeter + Send + Sync + 'static,
    ) -> Self {
        self.meter_provider = Box::new(meter_provider);
        self
    }

    /// Build the [TelemetryProvider].
    pub fn build(self) -> TelemetryProvider {
        TelemetryProvider {
            meter_provider: self.meter_provider,
        }
    }
}

/// Wrapper type to hold a implementer of TelemetryProvider in an Arc so that
/// it can be safely used across threads.
#[non_exhaustive]
pub(crate) struct GlobalTelemetryProvider {
    pub(crate) telemetry_provider: Arc<TelemetryProvider>,
}

impl GlobalTelemetryProvider {
    pub(crate) fn new(telemetry_provider: TelemetryProvider) -> Self {
        Self {
            telemetry_provider: Arc::new(telemetry_provider),
        }
    }

    pub(crate) fn telemetry_provider(&self) -> &Arc<TelemetryProvider> {
        &self.telemetry_provider
    }
}