1use actor::HealthCheckResponse;
2use log::{debug, error, info, trace, warn};
3use std::error::Error;
4use std::sync::{Arc, RwLock};
5use wasmcloud_actor_core as actor;
6use wasmcloud_actor_logging::{WriteLogArgs, OP_LOG};
7use wasmcloud_provider_core::{
8 capabilities::{CapabilityProvider, Dispatcher, NullDispatcher},
9 capability_provider,
10 core::{OP_BIND_ACTOR, OP_HEALTH_REQUEST, OP_REMOVE_ACTOR},
11 deserialize, serialize,
12};
13
14#[cfg(not(feature = "static_plugin"))]
15capability_provider!(LoggingProvider, LoggingProvider::new);
16
17#[allow(unused)]
18const CAPABILITY_ID: &str = "wasmcloud:logging";
19const SYSTEM_ACTOR: &str = "system";
20
21const ERROR: &str = "error";
22const WARN: &str = "warn";
23const INFO: &str = "info";
24const DEBUG: &str = "debug";
25const TRACE: &str = "trace";
26
27#[derive(Clone)]
29pub struct LoggingProvider {
30 dispatcher: Arc<RwLock<Box<dyn Dispatcher>>>,
31}
32
33impl Default for LoggingProvider {
34 fn default() -> Self {
35 if env_logger::try_init().is_err() {}
36
37 LoggingProvider {
38 dispatcher: Arc::new(RwLock::new(Box::new(NullDispatcher::new()))),
39 }
40 }
41}
42
43impl LoggingProvider {
44 pub fn new() -> Self {
46 Self::default()
47 }
48
49 fn write_log(
50 &self,
51 actor: &str,
52 log_msg: WriteLogArgs,
53 ) -> Result<Vec<u8>, Box<dyn Error + Sync + Send>> {
54 match &*log_msg.level {
55 ERROR => error!(target: &log_msg.target, "[{}] {}", actor, log_msg.text),
56 WARN => warn!(target: &log_msg.target, "[{}] {}", actor, log_msg.text),
57 INFO => info!(target: &log_msg.target, "[{}] {}", actor, log_msg.text),
58 DEBUG => debug!(target: &log_msg.target, "[{}] {}", actor, log_msg.text),
59 TRACE => trace!(target: &log_msg.target, "[{}] {}", actor, log_msg.text),
60 _ => error!("Unknown log level: {}", log_msg.level),
61 }
62 Ok(vec![])
63 }
64}
65
66impl CapabilityProvider for LoggingProvider {
67 fn configure_dispatch(
70 &self,
71 dispatcher: Box<dyn Dispatcher>,
72 ) -> Result<(), Box<dyn Error + Sync + Send>> {
73 info!("Dispatcher configured.");
74 let mut lock = self.dispatcher.write().unwrap();
75 *lock = dispatcher;
76
77 Ok(())
78 }
79
80 fn handle_call(
83 &self,
84 actor: &str,
85 op: &str,
86 msg: &[u8],
87 ) -> Result<Vec<u8>, Box<dyn Error + Sync + Send>> {
88 trace!("Handling operation `{}` from `{}`", op, actor);
89 match op {
90 OP_BIND_ACTOR if actor == SYSTEM_ACTOR => Ok(vec![]),
91 OP_REMOVE_ACTOR if actor == SYSTEM_ACTOR => Ok(vec![]),
92 OP_HEALTH_REQUEST if actor == SYSTEM_ACTOR => Ok(serialize(HealthCheckResponse {
93 healthy: true,
94 message: "".to_string(),
95 })?),
96 OP_LOG => self.write_log(actor, deserialize(msg)?),
97 _ => Err(format!("Unknown operation: {}", op).into()),
98 }
99 }
100
101 fn stop(&self) {}
103}