#![cfg_attr(docsrs, feature(doc_cfg))]
#[macro_use]
extern crate elfo_utils;
use std::sync::Arc;
use dashmap::DashMap;
use derive_more::Constructor;
use futures_intrusive::{buffer::GrowingHeapBuf, channel::GenericChannel};
use fxhash::FxBuildHasher;
use parking_lot::RawMutex;
use sharded_slab::Pool;
use tracing::{span::Id as SpanId, Metadata};
use tracing_subscriber::{prelude::*, registry::Registry};
use elfo_core::{tracing::TraceId, ActorMeta, Blueprint};
use elfo_utils::time::SystemTime;
use crate::actor::Logger;
pub use crate::{actor::ReopenLogFile, capture_layer::CaptureLayer, scope_filter::ScopeFilter};
pub mod config;
mod actor;
mod capture_layer;
mod formatters;
mod scope_filter;
mod stats;
mod theme;
mod line_buffer;
mod line_transaction;
const CHANNEL_CAPACITY: usize = 128 * 1024;
type StringId = usize;
struct Shared {
channel: GenericChannel<RawMutex, PreparedEvent, GrowingHeapBuf<PreparedEvent>>,
pool: Pool<String>,
spans: DashMap<SpanId, SpanData, FxBuildHasher>,
}
#[derive(Constructor)]
struct SpanData {
parent_id: Option<SpanId>,
payload_id: StringId,
}
struct PreparedEvent {
timestamp: SystemTime,
trace_id: Option<TraceId>,
metadata: &'static Metadata<'static>,
object: Option<Arc<ActorMeta>>,
span_id: Option<SpanId>,
payload_id: StringId,
}
pub fn new() -> (Blueprint, ScopeFilter, CaptureLayer) {
let shared = Shared {
channel: GenericChannel::with_capacity(CHANNEL_CAPACITY),
pool: Pool::default(),
spans: DashMap::default(),
};
let shared = Arc::new(shared);
let scope_filter = ScopeFilter::new();
let capture_layer = CaptureLayer::new(shared.clone());
let blueprint = Logger::blueprint(shared, scope_filter.clone());
(blueprint, scope_filter, capture_layer)
}
pub fn init() -> Blueprint {
let (blueprint, scope_filter, capture_layer) = new();
let subscriber = Registry::default().with(capture_layer).with(scope_filter);
#[cfg(feature = "env-filter")]
let subscriber = {
use tracing_subscriber::EnvFilter;
let env_filter = std::env::var(EnvFilter::DEFAULT_ENV)
.ok()
.map(|_| EnvFilter::try_from_default_env().expect("invalid env"));
subscriber.with(env_filter)
};
tracing::subscriber::set_global_default(subscriber).expect("cannot set global subscriber");
#[cfg(feature = "tracing-log")]
{
if let Err(e) = tracing_log::LogTracer::init() {
tracing::error!(
error = &*e.to_string(),
"can't integrate with log adapter, logs produced via `log` crate might be not available",
);
} else {
log::error!("initialized tracing_log adapter");
}
}
blueprint
}