minco_plugin_observability/
lib.rs1#![forbid(unsafe_code)]
3
4use minco_core::{
5 CapabilityProvision, Plugin, PluginContext, PluginDescriptor, PluginError, PluginId,
6};
7use semver::Version;
8use serde::{Deserialize, Serialize};
9use std::sync::Arc;
10use tracing_subscriber::EnvFilter;
11
12#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
13pub struct ObservabilityConfig {
14 pub service_name: String,
15 pub json: bool,
16 pub default_filter: String,
17}
18
19#[derive(Debug, thiserror::Error)]
20pub enum ObservabilityError {
21 #[error("failed to initialize tracing subscriber: {0}")]
22 Initialization(String),
23}
24
25impl Default for ObservabilityConfig {
26 fn default() -> Self {
27 Self {
28 service_name: "minco-app".into(),
29 json: true,
30 default_filter: "info,tower_http=info".into(),
31 }
32 }
33}
34
35impl ObservabilityConfig {
36 pub fn init(&self) -> Result<(), ObservabilityError> {
37 let filter = EnvFilter::try_from_default_env()
38 .unwrap_or_else(|_| EnvFilter::new(&self.default_filter));
39 let result = if self.json {
40 tracing_subscriber::fmt()
41 .with_env_filter(filter)
42 .json()
43 .try_init()
44 } else {
45 tracing_subscriber::fmt().with_env_filter(filter).try_init()
46 };
47 result.map_err(|error| ObservabilityError::Initialization(error.to_string()))
48 }
49}
50
51#[derive(Debug, Clone)]
52pub struct ObservabilityPlugin {
53 config: ObservabilityConfig,
54}
55impl ObservabilityPlugin {
56 pub const fn new(config: ObservabilityConfig) -> Self {
57 Self { config }
58 }
59}
60impl Default for ObservabilityPlugin {
61 fn default() -> Self {
62 Self::new(ObservabilityConfig::default())
63 }
64}
65
66impl Plugin for ObservabilityPlugin {
67 fn descriptor(&self) -> PluginDescriptor {
68 let mut descriptor = PluginDescriptor::new(
69 PluginId::new("observability").expect("static id"),
70 Version::new(1, 0, 0),
71 "Structured tracing and CloudWatch-compatible JSON logging",
72 );
73 descriptor.default_enabled = true;
74 descriptor.provides.push(CapabilityProvision {
75 name: "observability.tracing".into(),
76 version: Version::new(1, 0, 0),
77 });
78 descriptor
79 }
80 fn install(&self, context: &mut PluginContext<'_>) -> Result<(), PluginError> {
81 context.services().insert(Arc::new(self.config.clone()))?;
82 Ok(())
83 }
84}