1#[macro_use]
16extern crate wascc_codec as codec;
17
18use codec::capabilities::{
19 CapabilityDescriptor, CapabilityProvider, Dispatcher, NullDispatcher, OperationDirection,
20 OP_GET_CAPABILITY_DESCRIPTOR,
21};
22use codec::core::{OP_BIND_ACTOR, OP_REMOVE_ACTOR};
23use codec::{
24 deserialize,
25 logging::{WriteLogRequest, OP_LOG},
26 serialize,
27};
28
29#[macro_use]
30extern crate log;
31
32use std::error::Error;
33use std::sync::RwLock;
34
35#[cfg(not(feature = "static_plugin"))]
36capability_provider!(LoggingProvider, LoggingProvider::new);
37
38const CAPABILITY_ID: &str = "wascc:logging";
39const SYSTEM_ACTOR: &str = "system";
40const VERSION: &str = env!("CARGO_PKG_VERSION");
41const REVISION: u32 = 2; const ERROR: u32 = 1;
44const WARN: u32 = 2;
45const INFO: u32 = 3;
46const DEBUG: u32 = 4;
47const TRACE: u32 = 5;
48
49pub struct LoggingProvider {
51 dispatcher: RwLock<Box<dyn Dispatcher>>,
52}
53
54impl Default for LoggingProvider {
55 fn default() -> Self {
56 match env_logger::try_init() {
57 Ok(_) => {}
58 Err(_) => {}
59 }
60
61 LoggingProvider {
62 dispatcher: RwLock::new(Box::new(NullDispatcher::new())),
63 }
64 }
65}
66
67impl LoggingProvider {
68 pub fn new() -> Self {
70 Self::default()
71 }
72
73 fn get_descriptor(&self) -> Result<Vec<u8>, Box<dyn Error + Sync + Send>> {
74 Ok(serialize(
75 CapabilityDescriptor::builder()
76 .id(CAPABILITY_ID)
77 .name("waSCC Default Logging Provider (STDOUT)")
78 .long_description(
79 "A simple logging capability provider that supports levels from error to trace",
80 )
81 .version(VERSION)
82 .revision(REVISION)
83 .with_operation(
84 OP_LOG,
85 OperationDirection::ToProvider,
86 "Sends a log message to stdout",
87 )
88 .build(),
89 )?)
90 }
91
92 fn write_log(
93 &self,
94 actor: &str,
95 log_msg: WriteLogRequest,
96 ) -> Result<Vec<u8>, Box<dyn Error + Sync + Send>> {
97 match log_msg.level {
98 ERROR => error!("[{}] {}", actor, log_msg.body),
99 WARN => warn!("[{}] {}", actor, log_msg.body),
100 INFO => info!("[{}] {}", actor, log_msg.body),
101 DEBUG => debug!("[{}] {}", actor, log_msg.body),
102 TRACE => trace!("[{}] {}", actor, log_msg.body),
103 _ => error!("Unknown log level: {}", log_msg.level),
104 }
105 Ok(vec![])
106 }
107}
108
109impl CapabilityProvider for LoggingProvider {
110 fn configure_dispatch(
113 &self,
114 dispatcher: Box<dyn Dispatcher>,
115 ) -> Result<(), Box<dyn Error + Sync + Send>> {
116 let mut lock = self.dispatcher.write().unwrap();
117 *lock = dispatcher;
118
119 Ok(())
120 }
121
122 fn handle_call(
125 &self,
126 actor: &str,
127 op: &str,
128 msg: &[u8],
129 ) -> Result<Vec<u8>, Box<dyn Error + Sync + Send>> {
130 match op {
131 OP_BIND_ACTOR if actor == SYSTEM_ACTOR => Ok(vec![]),
132 OP_REMOVE_ACTOR if actor == SYSTEM_ACTOR => Ok(vec![]),
133 OP_GET_CAPABILITY_DESCRIPTOR if actor == SYSTEM_ACTOR => self.get_descriptor(),
134 OP_LOG => self.write_log(actor, deserialize(msg)?),
135 _ => Err(format!("Unknown operation: {}", op).into()),
136 }
137 }
138}