blob: 7c490c6332a870db3fbb2c41870c90694224673c [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//! Tracer items.
use crate::{
reporter::{CollectItem, DynReport, Report},
trace::trace_context::TracingContext,
};
use std::sync::{Arc, Weak};
use tokio::sync::OnceCell;
static GLOBAL_TRACER: OnceCell<Tracer> = OnceCell::const_new();
/// Set the global tracer.
pub fn set_global_tracer(tracer: Tracer) {
if GLOBAL_TRACER.set(tracer).is_err() {
panic!("global tracer has set")
}
}
/// Get the global tracer.
pub fn global_tracer() -> &'static Tracer {
GLOBAL_TRACER.get().expect("global tracer haven't set")
}
/// Create trace context by global tracer.
pub fn create_trace_context() -> TracingContext {
global_tracer().create_trace_context()
}
struct Inner {
service_name: String,
instance_name: String,
reporter: Box<DynReport>,
}
/// Skywalking tracer.
#[derive(Clone)]
pub struct Tracer {
inner: Arc<Inner>,
}
impl Tracer {
/// New with service info and reporter.
pub fn new(
service_name: impl Into<String>,
instance_name: impl Into<String>,
reporter: impl Report + Send + Sync + 'static,
) -> Self {
Self {
inner: Arc::new(Inner {
service_name: service_name.into(),
instance_name: instance_name.into(),
reporter: Box::new(reporter),
}),
}
}
/// Get service name.
pub fn service_name(&self) -> &str {
&self.inner.service_name
}
/// Get instance name.
pub fn instance_name(&self) -> &str {
&self.inner.instance_name
}
/// Create trace context.
pub fn create_trace_context(&self) -> TracingContext {
TracingContext::new(
&self.inner.service_name,
&self.inner.instance_name,
self.downgrade(),
)
}
/// Finalize the trace context.
pub(crate) fn finalize_context(&self, context: &mut TracingContext) {
let segment_object = context.convert_to_segment_object();
self.inner
.reporter
.report(CollectItem::Trace(Box::new(segment_object)));
}
fn downgrade(&self) -> WeakTracer {
WeakTracer {
inner: Arc::downgrade(&self.inner),
}
}
}
#[derive(Clone)]
pub(crate) struct WeakTracer {
inner: Weak<Inner>,
}
impl WeakTracer {
pub(crate) fn upgrade(&self) -> Option<Tracer> {
Weak::upgrade(&self.inner).map(|inner| Tracer { inner })
}
}
#[cfg(test)]
mod tests {
use super::*;
trait AssertSend: Send {}
impl AssertSend for Tracer {}
}