Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add InstrumentationLibrary for instrumentation library information #207

Merged
merged 4 commits into from
Sep 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions benches/trace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ fn trace_benchmark_group<F: Fn(&sdk::Tracer)>(c: &mut Criterion, name: &str, f:
..Default::default()
})
.build()
.get_tracer("always-sample");
.get_tracer("always-sample", None);

b.iter(|| f(&always_sample));
});
Expand All @@ -86,7 +86,7 @@ fn trace_benchmark_group<F: Fn(&sdk::Tracer)>(c: &mut Criterion, name: &str, f:
..Default::default()
})
.build()
.get_tracer("never-sample");
.get_tracer("never-sample", None);
b.iter(|| f(&never_sample));
});

Expand Down
2 changes: 1 addition & 1 deletion examples/stdout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,6 @@ fn main() {
global::set_provider(provider);

global::trace_provider()
.get_tracer("component-main")
.get_tracer("component-main", None)
.in_span("operation", |_cx| {});
}
2 changes: 1 addition & 1 deletion opentelemetry-jaeger/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ impl PipelineBuilder {
/// Install a Jaeger pipeline with the recommended defaults.
pub fn install(self) -> Result<sdk::Tracer, Box<dyn Error>> {
let trace_provider = self.build()?;
let tracer = trace_provider.get_tracer("opentelemetry-jaeger");
let tracer = trace_provider.get_tracer("opentelemetry-jaeger", None);

global::set_provider(trace_provider);

Expand Down
2 changes: 1 addition & 1 deletion src/api/context/propagation/composite_propagator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ use std::fmt::Debug;
/// let mut injector = HashMap::new();
///
/// // And a given span
/// let example_span = sdk::TracerProvider::default().get_tracer("example-component").start("span-name");
/// let example_span = sdk::TracerProvider::default().get_tracer("example-component", None).start("span-name");
///
/// // with the current context, call inject to add the headers
/// composite_propagator.inject_context(&Context::current_with_span(example_span)
Expand Down
2 changes: 1 addition & 1 deletion src/api/trace/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pub trait TraceContextExt {
/// // returns a reference to an empty span by default
/// assert_eq!(Context::current().span().span_context(), api::SpanContext::empty_context());
///
/// sdk::TracerProvider::default().get_tracer("my-component").in_span("my-span", |cx| {
/// sdk::TracerProvider::default().get_tracer("my-component", None).in_span("my-span", |cx| {
/// // Returns a reference to the current span if set
/// assert_ne!(cx.span().span_context(), api::SpanContext::empty_context());
/// });
Expand Down
2 changes: 1 addition & 1 deletion src/api/trace/noop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ impl api::TracerProvider for NoopProvider {
type Tracer = NoopTracer;

/// Returns a new `NoopTracer` instance.
fn get_tracer(&self, _name: &'static str) -> Self::Tracer {
fn get_tracer(&self, _name: &'static str, _version: Option<&'static str>) -> Self::Tracer {
NoopTracer {}
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/api/trace/provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
//! the SDK to suppress telemetry produced by this library.
//!
//! Implementations might require the user to specify configuration properties at
//! `TracerProvider` creation time, or rely on external configuration.
//! `TracerProvider` creation time, or rely on external configurations.
use crate::api;
use std::fmt;

Expand All @@ -29,5 +29,5 @@ pub trait TracerProvider: fmt::Debug + 'static {

/// Creates a named tracer instance of `Self::Tracer`.
/// If the name is an empty string then provider uses default name.
fn get_tracer(&self, name: &'static str) -> Self::Tracer;
fn get_tracer(&self, name: &'static str, version: Option<&'static str>) -> Self::Tracer;
}
9 changes: 6 additions & 3 deletions src/global/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,13 @@
//! // Then you can use the global provider to create a tracer via `tracer`.
//! let _span = global::tracer("my-component").start("span-name");
//!
//! // You can also get the tracer via name and version.
//! let _tracer = global::tracer_with_version("another-component", "1.1.1");
//!
//! // Or access the configured provider via `trace_provider`.
//! let provider = global::trace_provider();
//! let _tracer_a = provider.get_tracer("my-component-a");
//! let _tracer_b = provider.get_tracer("my-component-b");
//! let _tracer_a = provider.get_tracer("my-component-a", None);
//! let _tracer_b = provider.get_tracer("my-component-b", None);
//! }
//!
//! // in main or other app start
Expand Down Expand Up @@ -84,4 +87,4 @@ pub use metrics::{meter, meter_provider, set_meter_provider};
#[cfg(feature = "trace")]
pub use propagation::{get_text_map_propagator, set_text_map_propagator};
#[cfg(feature = "trace")]
pub use trace::{set_provider, trace_provider, tracer, GenericProvider};
pub use trace::{set_provider, trace_provider, tracer, tracer_with_version, GenericProvider};
34 changes: 27 additions & 7 deletions src/global/trace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use std::time::SystemTime;
/// [`Span`]: ../api/trace/span/trait.Span.html
#[derive(Debug)]
pub struct BoxedSpan(Box<DynSpan>);

type DynSpan = dyn api::Span + Send + Sync;

impl api::Span for BoxedSpan {
Expand Down Expand Up @@ -163,7 +164,11 @@ where
/// [`GlobalProvider`]: struct.GlobalProvider.html
pub trait GenericProvider: fmt::Debug + 'static {
/// Creates a named tracer instance that is a trait object through the underlying `TracerProvider`.
fn get_tracer_boxed(&self, name: &'static str) -> Box<dyn GenericTracer + Send + Sync>;
fn get_tracer_boxed(
&self,
name: &'static str,
version: Option<&'static str>,
) -> Box<dyn GenericTracer + Send + Sync>;
}

impl<S, T, P> GenericProvider for P
Expand All @@ -173,8 +178,12 @@ where
P: api::TracerProvider<Tracer = T>,
{
/// Return a boxed generic tracer
fn get_tracer_boxed(&self, name: &'static str) -> Box<dyn GenericTracer + Send + Sync> {
Box::new(self.get_tracer(name))
fn get_tracer_boxed(
&self,
name: &'static str,
version: Option<&'static str>,
) -> Box<dyn GenericTracer + Send + Sync> {
Box::new(self.get_tracer(name, version))
}
}

Expand Down Expand Up @@ -207,8 +216,8 @@ impl api::TracerProvider for GlobalProvider {
type Tracer = BoxedTracer;

/// Find or create a named tracer using the global provider.
fn get_tracer(&self, name: &'static str) -> Self::Tracer {
BoxedTracer(self.provider.get_tracer_boxed(name))
fn get_tracer(&self, name: &'static str, version: Option<&'static str>) -> Self::Tracer {
BoxedTracer(self.provider.get_tracer_boxed(name, version))
}
}

Expand All @@ -233,12 +242,23 @@ pub fn trace_provider() -> GlobalProvider {
///
/// If the name is an empty string, the provider will use a default name.
///
/// This is a more convenient way of expressing `global::trace_provider().get_tracer(name)`.
/// This is a more convenient way of expressing `global::trace_provider().get_tracer(name, None)`.
///
/// [`Tracer`]: ../api/trace/tracer/trait.Tracer.html
/// [`GlobalProvider`]: struct.GlobalProvider.html
pub fn tracer(name: &'static str) -> BoxedTracer {
trace_provider().get_tracer(name)
trace_provider().get_tracer(name, None)
}

/// Creates a named instance of [`Tracer`] with version info via the configured [`GlobalProvider`]
///
/// If the name is an empty string, the provider will use a default name.
/// If the version is an empty string, it will be used as part of instrumentation library information.
///
/// [`Tracer`]: ../api/trace/tracer/trait.Tracer.html
/// [`GlobalProvider`]: struct.GlobalProvider.html
pub fn tracer_with_version(name: &'static str, version: &'static str) -> BoxedTracer {
trace_provider().get_tracer(name, Some(version))
}

/// Sets the given [`TracerProvider`] instance as the current global provider.
Expand Down
25 changes: 25 additions & 0 deletions src/sdk/instrumentation.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//! Provides instrumentation information for both tracing and metric.
//! See `OTEPS-0083` for details.
//!
//! [OTEPS-0083](https://github.com/open-telemetry/oteps/blob/master/text/0083-component.md)

/// InstrumentationLibrary contains information about instrumentation library.
///
/// See `Instrumentation Libraries` for more information.
///
/// [`Instrumentation Libraries`](https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/overview.md#instrumentation-libraries)
#[derive(Debug, Default, Hash, Copy, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub struct InstrumentationLibrary {
/// instrumentation library name, cannot be empty
pub name: &'static str,
/// instrumentation library version, can be empty
pub version: Option<&'static str>,
}

impl InstrumentationLibrary {
/// Create an InstrumentationLibrary from name and version.
pub fn new(name: &'static str, version: Option<&'static str>) -> InstrumentationLibrary {
InstrumentationLibrary { name, version }
}
}
2 changes: 2 additions & 0 deletions src/sdk/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@
//! `Meter` creation.
pub mod env;
pub mod export;
pub mod instrumentation;
#[cfg(feature = "metrics")]
pub mod metrics;
pub mod resource;
#[cfg(feature = "trace")]
pub mod trace;

pub use env::EnvResourceDetector;
pub use instrumentation::InstrumentationLibrary;
pub use resource::Resource;
#[cfg(feature = "trace")]
pub use trace::{
Expand Down
12 changes: 7 additions & 5 deletions src/sdk/trace/provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const DEFAULT_COMPONENT_NAME: &str = "rust.opentelemetry.io/sdk/tracer";
/// TracerProvider inner type
#[derive(Debug)]
struct ProviderInner {
named_tracers: RwLock<HashMap<&'static str, sdk::Tracer>>,
named_tracers: RwLock<HashMap<sdk::InstrumentationLibrary, sdk::Tracer>>,
processors: Vec<Box<dyn api::SpanProcessor>>,
config: sdk::Config,
}
Expand Down Expand Up @@ -66,29 +66,31 @@ impl api::TracerProvider for TracerProvider {
type Tracer = sdk::Tracer;

/// Find or create `Tracer` instance by name.
fn get_tracer(&self, name: &'static str) -> Self::Tracer {
fn get_tracer(&self, name: &'static str, version: Option<&'static str>) -> Self::Tracer {
// Use default value if name is invalid empty string
let component_name = if name.is_empty() {
DEFAULT_COMPONENT_NAME
} else {
name
};

let instrumentation_lib = sdk::InstrumentationLibrary::new(component_name, version);

// Return named tracer if already initialized
if let Some(tracer) = self
.inner
.named_tracers
.read()
.expect("RwLock poisoned")
.get(&component_name)
.get(&instrumentation_lib)
{
return tracer.clone();
};

// Else construct new named tracer
let mut tracers = self.inner.named_tracers.write().expect("RwLock poisoned");
let new_tracer = sdk::Tracer::new(name, self.clone());
tracers.insert(component_name, new_tracer.clone());
let new_tracer = sdk::Tracer::new(instrumentation_lib, self.clone());
tracers.insert(instrumentation_lib, new_tracer.clone());

new_tracer
}
Expand Down
26 changes: 20 additions & 6 deletions src/sdk/trace/tracer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,29 +17,43 @@ use std::time::SystemTime;
/// `Tracer` implementation to create and manage spans
#[derive(Clone)]
pub struct Tracer {
name: &'static str,
instrumentation_lib: sdk::InstrumentationLibrary,
provider: sdk::TracerProvider,
}

impl fmt::Debug for Tracer {
/// Formats the `Tracer` using the given formatter.
/// Omitting `provider` here is necessary to avoid cycles.
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Tracer").field("name", &self.name).finish()
f.debug_struct("Tracer")
.field("name", &self.instrumentation_lib.name)
.field("version", &self.instrumentation_lib.version)
.finish()
}
}

impl Tracer {
/// Create a new tracer (used internally by `TracerProvider`s.
pub(crate) fn new(name: &'static str, provider: sdk::TracerProvider) -> Self {
Tracer { name, provider }
/// Create a new tracer (used internally by `TracerProvider`s).
pub(crate) fn new(
instrumentation_lib: sdk::InstrumentationLibrary,
provider: sdk::TracerProvider,
) -> Self {
Tracer {
instrumentation_lib,
provider,
}
}

/// TracerProvider associated with this tracer
/// TracerProvider associated with this tracer.
pub fn provider(&self) -> &sdk::TracerProvider {
&self.provider
}

/// instrumentation library information of this tracer.
pub fn instrumentation_library(&self) -> &sdk::InstrumentationLibrary {
&self.instrumentation_lib
}

/// Make a sampling decision using the provided sampler for the span and context.
#[allow(clippy::too_many_arguments)]
fn make_sampling_decision(
Expand Down