You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

585 lines
17KB

  1. //! An object to handle everyone's errors
  2. //!
  3. use std::thread::{self, JoinHandle};
  4. use std::sync::{Arc, Mutex, RwLock};
  5. use std::sync::mpsc::{Sender, channel};
  6. use std::collections::{BTreeMap, VecDeque};
  7. use std::fmt::{self, Display, Error as FmtError, Formatter};
  8. use std::io::{self, Write};
  9. use std::fs;
  10. use chrono::{DateTime, Utc};
  11. use termion::color::{self, Fg, Bg};
  12. use influent::measurement::{Measurement, Value as InfluentValue};
  13. use slog::{self, OwnedKVList, Drain, Key, KV, Level, Logger};
  14. use sloggers::types::Severity;
  15. use super::{nanos, file_logger};
  16. use influx;
  17. const N_WARNINGS: usize = 500;
  18. #[macro_export]
  19. macro_rules! confirmed {
  20. ($warnings:ident, $($args:tt)*) => (
  21. {
  22. let _ = warnings.send(Warning::Confirmed( ( format!($($args)*) ) ) ).unwrap();
  23. }
  24. )
  25. }
  26. /// logs a `Warning::Awesome` message to the `WarningsManager`
  27. #[macro_export]
  28. macro_rules! awesome {
  29. ($warnings:ident, $($args:tt)*) => (
  30. {
  31. let _ = $warnings.send(Warning::Awesome( ( format!($($args)*) ) ) ).unwrap();
  32. }
  33. )
  34. }
  35. #[macro_export]
  36. macro_rules! critical {
  37. ($warnings:ident, $($args:tt)*) => (
  38. {
  39. let _ = $warnings.send(Warning::Critical( ( format!($($args)*) ) ) ).unwrap();
  40. }
  41. )
  42. }
  43. #[macro_export]
  44. macro_rules! notice {
  45. ($warnings:ident, $($args:tt)*) => (
  46. {
  47. let _ = $warnings.send(Warning::Notice( ( format!($($args)*) ) ) ).unwrap();
  48. }
  49. )
  50. }
  51. #[macro_export]
  52. macro_rules! error_w {
  53. ($warnings:ident, $($args:tt)*) => (
  54. {
  55. $warnings.send(Warning::Error( ( format!($($args)*) ) ) ).unwrap();
  56. }
  57. )
  58. }
  59. /// represents a non-fatal error somewhere in
  60. /// the system to report either to the program interface
  61. /// or in logs.
  62. ///
  63. #[derive(Debug, Clone, PartialEq)]
  64. pub enum Warning {
  65. Notice(String),
  66. Error(String),
  67. DegradedService(String),
  68. Critical(String),
  69. Confirmed(String),
  70. Awesome(String),
  71. Log {
  72. level: Level,
  73. module: &'static str,
  74. function: &'static str,
  75. line: u32,
  76. msg: String,
  77. kv: MeasurementRecord,
  78. },
  79. Terminate
  80. }
  81. impl Warning {
  82. pub fn msg(&self) -> String {
  83. match *self {
  84. Warning::Notice(ref s) | Warning::Error(ref s) |
  85. Warning::DegradedService(ref s) | Warning::Critical(ref s) |
  86. Warning::Awesome(ref s) | Warning::Confirmed(ref s) |
  87. Warning::Log { msg: ref s, .. } =>
  88. s.clone(),
  89. Warning::Terminate => "".to_owned()
  90. }
  91. }
  92. pub fn msg_str(&self) -> &str {
  93. match *self {
  94. Warning::Notice(ref s) | Warning::Error(ref s) |
  95. Warning::DegradedService(ref s) | Warning::Critical(ref s) |
  96. Warning::Awesome(ref s) | Warning::Confirmed(ref s) |
  97. Warning::Log { msg: ref s, .. } =>
  98. s.as_ref(),
  99. Warning::Terminate => "Terminate"
  100. }
  101. }
  102. pub fn category_str(&self) -> &str {
  103. match self {
  104. &Warning::Notice(_) => "NOTC",
  105. &Warning::Error(_) => "ERRO",
  106. &Warning::Critical(_) => "CRIT",
  107. &Warning::DegradedService(_) => "DGRD",
  108. &Warning::Confirmed(_) => "CNFD",
  109. &Warning::Awesome(_) => "AWSM",
  110. &Warning::Log { ref level, .. } => level.as_short_str(),
  111. &Warning::Terminate => "TERM",
  112. }
  113. }
  114. pub fn category(&self, f: &mut Formatter) -> fmt::Result {
  115. match *self {
  116. Warning::Notice(_) => {
  117. write!(f, "[ Notice ]")
  118. }
  119. Warning::Error(_) => {
  120. write!(f, "{yellow}[{title}]{reset}",
  121. yellow = Fg(color::LightYellow),
  122. title = " Error--",
  123. reset = Fg(color::Reset))
  124. }
  125. Warning::Critical(_) => {
  126. write!(f, "{bg}{fg}{title}{resetbg}{resetfg}",
  127. bg = Bg(color::Red),
  128. fg = Fg(color::White),
  129. title = " CRITICAL ",
  130. resetbg = Bg(color::Reset),
  131. resetfg = Fg(color::Reset))
  132. }
  133. Warning::Awesome(_) => {
  134. write!(f, "{color}[{title}]{reset}",
  135. color = Fg(color::Green),
  136. title = "Awesome!",
  137. reset = Fg(color::Reset))
  138. }
  139. Warning::DegradedService(_) => {
  140. write!(f, "{color}[{title}] {reset}",
  141. color = Fg(color::Blue),
  142. title = "Degraded Service ",
  143. reset = Fg(color::Reset))
  144. }
  145. Warning::Confirmed(_) => {
  146. write!(f, "{bg}{fg}{title}{resetbg}{resetfg}",
  147. bg = Bg(color::Blue),
  148. fg = Fg(color::White),
  149. title = "Confirmed ",
  150. resetbg = Bg(color::Reset),
  151. resetfg = Fg(color::Reset))
  152. }
  153. _ => Ok(())
  154. }
  155. }
  156. }
  157. impl Display for Warning {
  158. fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
  159. self.category(f)?;
  160. write!(f, " {}", self.msg())
  161. }
  162. }
  163. #[derive(Debug, Clone)]
  164. pub struct Record {
  165. pub time: DateTime<Utc>,
  166. pub msg: Warning
  167. }
  168. impl Record {
  169. pub fn new(msg: Warning) -> Self {
  170. let time = Utc::now();
  171. Record { time, msg }
  172. }
  173. pub fn to_measurement(&self, name: &'static str) -> Measurement {
  174. let cat = self.msg.category_str();
  175. let body = self.msg.msg_str();
  176. let mut m = Measurement::new(name);
  177. m.add_tag("category", cat);
  178. m.add_field("msg", InfluentValue::String(body));
  179. m.set_timestamp(nanos(self.time) as i64);
  180. m
  181. }
  182. }
  183. impl Display for Record {
  184. fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
  185. write!(f, "{} | {}", self.time.format("%H:%M:%S"), self.msg)
  186. }
  187. }
  188. pub type SlogResult = Result<(), slog::Error>;
  189. #[derive(Debug, Clone, PartialEq)]
  190. pub enum Value {
  191. String(String),
  192. Float(f64),
  193. Integer(i64),
  194. Boolean(bool)
  195. }
  196. impl Value {
  197. pub fn to_influent<'a>(&'a self) -> InfluentValue<'a> {
  198. match self {
  199. &Value::String(ref s) => InfluentValue::String(s),
  200. &Value::Float(n) => InfluentValue::Float(n),
  201. &Value::Integer(i) => InfluentValue::Integer(i),
  202. &Value::Boolean(b) => InfluentValue::Boolean(b),
  203. }
  204. }
  205. }
  206. #[derive(Debug, Clone, PartialEq)]
  207. pub struct MeasurementRecord {
  208. fields: Vec<(Key, Value)>,
  209. tags: Vec<(Key, String)>,
  210. }
  211. impl MeasurementRecord {
  212. pub fn new() -> Self {
  213. MeasurementRecord {
  214. fields: Vec::new(),
  215. tags: Vec::new(),
  216. }
  217. }
  218. pub fn add_field(&mut self, key: Key, val: Value) -> SlogResult {
  219. self.fields.push((key, val));
  220. Ok(())
  221. }
  222. pub fn add_tag(&mut self, key: Key, val: String) -> SlogResult {
  223. match key {
  224. "exchange" | "thread" | "ticker" | "category" => {
  225. self.tags.push((key, val));
  226. }
  227. other => {
  228. self.add_field(other, Value::String(val)).unwrap();
  229. }
  230. }
  231. Ok(())
  232. }
  233. pub fn serialize_values(&mut self, record: &slog::Record, values: &OwnedKVList) {
  234. let mut builder = TagBuilder { mrec: self };
  235. let _ = values.serialize(record, &mut builder);
  236. }
  237. pub fn to_measurement<'a>(&'a self, name: &'a str) -> Measurement<'a> {
  238. let fields: BTreeMap<&'a str, InfluentValue<'a>> =
  239. self.fields.iter()
  240. .map(|&(k, ref v)| {
  241. (k, v.to_influent())
  242. }).collect();
  243. let tags: BTreeMap<&'a str, &'a str> =
  244. self.tags.iter()
  245. .map(|&(k, ref v)| {
  246. (k, v.as_ref())
  247. }).collect();
  248. Measurement {
  249. key: name,
  250. timestamp: Some(nanos(Utc::now()) as i64),
  251. fields,
  252. tags,
  253. }
  254. }
  255. }
  256. impl slog::Serializer for MeasurementRecord {
  257. fn emit_usize(&mut self, key: Key, val: usize) -> SlogResult { self.add_field(key, Value::Integer(val as i64)) }
  258. fn emit_isize(&mut self, key: Key, val: isize) -> SlogResult { self.add_field(key, Value::Integer(val as i64)) }
  259. fn emit_bool(&mut self, key: Key, val: bool) -> SlogResult { self.add_field(key, Value::Boolean(val)) }
  260. fn emit_u8(&mut self, key: Key, val: u8) -> SlogResult { self.add_field(key, Value::Integer(val as i64)) }
  261. fn emit_i8(&mut self, key: Key, val: i8) -> SlogResult { self.add_field(key, Value::Integer(val as i64)) }
  262. fn emit_u16(&mut self, key: Key, val: u16) -> SlogResult { self.add_field(key, Value::Integer(val as i64)) }
  263. fn emit_i16(&mut self, key: Key, val: i16) -> SlogResult { self.add_field(key, Value::Integer(val as i64)) }
  264. fn emit_u32(&mut self, key: Key, val: u32) -> SlogResult { self.add_field(key, Value::Integer(val as i64)) }
  265. fn emit_i32(&mut self, key: Key, val: i32) -> SlogResult { self.add_field(key, Value::Integer(val as i64)) }
  266. fn emit_f32(&mut self, key: Key, val: f32) -> SlogResult { self.add_field(key, Value::Float(val as f64)) }
  267. fn emit_u64(&mut self, key: Key, val: u64) -> SlogResult { self.add_field(key, Value::Integer(val as i64)) }
  268. fn emit_i64(&mut self, key: Key, val: i64) -> SlogResult { self.add_field(key, Value::Integer(val)) }
  269. fn emit_f64(&mut self, key: Key, val: f64) -> SlogResult { self.add_field(key, Value::Float(val)) }
  270. fn emit_str(&mut self, key: Key, val: &str) -> SlogResult { self.add_field(key, Value::String(val.to_string())) }
  271. fn emit_unit(&mut self, key: Key) -> SlogResult { self.add_field(key, Value::Boolean(true)) }
  272. fn emit_none(&mut self, _: Key) -> SlogResult { Ok(()) } //self.add_field(key, Value::String("none".into())) }
  273. fn emit_arguments(&mut self, key: Key, val: &fmt::Arguments) -> SlogResult { self.add_field(key, Value::String(val.to_string())) }
  274. }
  275. pub struct TagBuilder<'a> {
  276. mrec: &'a mut MeasurementRecord
  277. }
  278. impl<'a> slog::Serializer for TagBuilder<'a> {
  279. fn emit_str(&mut self, key: Key, val: &str) -> SlogResult {
  280. match key {
  281. "exchange" | "thread" | "ticker" | "category" => {
  282. self.mrec.add_tag(key, val.to_string())
  283. }
  284. other => {
  285. self.mrec.add_field(other, Value::String(val.to_string()))
  286. }
  287. }
  288. }
  289. fn emit_arguments(&mut self, key: Key, val: &fmt::Arguments) -> SlogResult {
  290. match key {
  291. "exchange" | "thread" | "ticker" | "category" => {
  292. self.mrec.add_tag(key, val.to_string())
  293. }
  294. other => {
  295. self.mrec.add_field(other, Value::String(val.to_string()))
  296. }
  297. }
  298. }
  299. }
  300. pub struct WarningsDrain<D: Drain> {
  301. level: Level,
  302. tx: Arc<Mutex<Sender<Warning>>>,
  303. drain: D,
  304. to_file: Logger,
  305. }
  306. impl<D> WarningsDrain<D>
  307. where D: Drain
  308. {
  309. pub fn new(tx: Sender<Warning>, level: Level, drain: D) -> Self {
  310. let tx = Arc::new(Mutex::new(tx));
  311. let to_file = file_logger("var/log/mm.log", Severity::Warning);
  312. WarningsDrain { tx, drain, level, to_file }
  313. }
  314. }
  315. impl From<Sender<Warning>> for WarningsDrain<slog::Fuse<slog::Discard>> {
  316. fn from(tx: Sender<Warning>) -> Self {
  317. WarningsDrain::new(tx, Level::Debug, slog::Discard.fuse())
  318. }
  319. }
  320. impl<D: Drain> Drain for WarningsDrain<D> {
  321. type Ok = ();
  322. type Err = D::Err;
  323. fn log(&self, record: &slog::Record, values: &OwnedKVList) -> Result<Self::Ok, Self::Err> {
  324. if record.level() <= self.level {
  325. let mut ser = MeasurementRecord::new();
  326. ser.serialize_values(record, values);
  327. let _ = record.kv().serialize(record, &mut ser);
  328. let msg = record.msg().to_string();
  329. if let Ok(lock) = self.tx.lock() {
  330. let _ = lock.send(Warning::Log {
  331. level: record.level(),
  332. module: record.module(),
  333. function: record.function(),
  334. line: record.line(),
  335. msg,
  336. kv: ser
  337. });
  338. }
  339. }
  340. if record.level() <= Level::Warning {
  341. let _ = self.to_file.log(record);
  342. }
  343. let _ = self.drain.log(record, values)?;
  344. Ok(())
  345. }
  346. }
  347. #[derive(Debug)]
  348. pub struct WarningsManager {
  349. pub tx: Sender<Warning>,
  350. pub warnings: Arc<RwLock<VecDeque<Record>>>,
  351. thread: Option<JoinHandle<()>>
  352. }
  353. impl Drop for WarningsManager {
  354. fn drop(&mut self) {
  355. let _ = self.tx.send(Warning::Terminate);
  356. if let Some(thread) = self.thread.take() {
  357. thread.join().unwrap();
  358. }
  359. }
  360. }
  361. const TIMESTAMP_FORMAT: &'static str = "%b %d %H:%M:%S%.3f";
  362. /// Serializes *only* KV pair with `key == "thread"`
  363. ///
  364. struct ThreadSer<'a>(&'a mut Vec<u8>);
  365. impl<'a> slog::ser::Serializer for ThreadSer<'a> {
  366. fn emit_arguments(&mut self, _: &str, _: &fmt::Arguments) -> slog::Result {
  367. Ok(())
  368. }
  369. fn emit_str(&mut self, key: &str, val: &str) -> slog::Result {
  370. if key == "thread" {
  371. write!(self.0, " {:<20}", val)?;
  372. }
  373. Ok(())
  374. }
  375. }
  376. /// Serializes KV pairs as ", k: v"
  377. ///
  378. struct KvSer<'a>(&'a mut Vec<u8>);
  379. macro_rules! s(
  380. ($s:expr, $k:expr, $v:expr) => {
  381. try!(write!($s.0, ", {}: {}", $k, $v));
  382. };
  383. );
  384. impl<'a> slog::ser::Serializer for KvSer<'a> {
  385. fn emit_none(&mut self, key: &str) -> slog::Result {
  386. s!(self, key, "None");
  387. Ok(())
  388. }
  389. fn emit_unit(&mut self, key: &str) -> slog::Result {
  390. s!(self, key, "()");
  391. Ok(())
  392. }
  393. fn emit_bool(&mut self, key: &str, val: bool) -> slog::Result {
  394. s!(self, key, val);
  395. Ok(())
  396. }
  397. fn emit_char(&mut self, key: &str, val: char) -> slog::Result {
  398. s!(self, key, val);
  399. Ok(())
  400. }
  401. fn emit_usize(&mut self, key: &str, val: usize) -> slog::Result {
  402. s!(self, key, val);
  403. Ok(())
  404. }
  405. fn emit_isize(&mut self, key: &str, val: isize) -> slog::Result {
  406. s!(self, key, val);
  407. Ok(())
  408. }
  409. fn emit_u8(&mut self, key: &str, val: u8) -> slog::Result {
  410. s!(self, key, val);
  411. Ok(())
  412. }
  413. fn emit_i8(&mut self, key: &str, val: i8) -> slog::Result {
  414. s!(self, key, val);
  415. Ok(())
  416. }
  417. fn emit_u16(&mut self, key: &str, val: u16) -> slog::Result {
  418. s!(self, key, val);
  419. Ok(())
  420. }
  421. fn emit_i16(&mut self, key: &str, val: i16) -> slog::Result {
  422. s!(self, key, val);
  423. Ok(())
  424. }
  425. fn emit_u32(&mut self, key: &str, val: u32) -> slog::Result {
  426. s!(self, key, val);
  427. Ok(())
  428. }
  429. fn emit_i32(&mut self, key: &str, val: i32) -> slog::Result {
  430. s!(self, key, val);
  431. Ok(())
  432. }
  433. fn emit_f32(&mut self, key: &str, val: f32) -> slog::Result {
  434. s!(self, key, val);
  435. Ok(())
  436. }
  437. fn emit_u64(&mut self, key: &str, val: u64) -> slog::Result {
  438. s!(self, key, val);
  439. Ok(())
  440. }
  441. fn emit_i64(&mut self, key: &str, val: i64) -> slog::Result {
  442. s!(self, key, val);
  443. Ok(())
  444. }
  445. fn emit_f64(&mut self, key: &str, val: f64) -> slog::Result {
  446. s!(self, key, val);
  447. Ok(())
  448. }
  449. fn emit_str(&mut self, key: &str, val: &str) -> slog::Result {
  450. s!(self, key, val);
  451. Ok(())
  452. }
  453. fn emit_arguments(
  454. &mut self,
  455. key: &str,
  456. val: &fmt::Arguments,
  457. ) -> slog::Result {
  458. s!(self, key, val);
  459. Ok(())
  460. }
  461. }
  462. #[allow(unused_variables, unused_imports)]
  463. #[cfg(test)]
  464. mod tests {
  465. use super::*;
  466. use test::{black_box, Bencher};
  467. #[test]
  468. #[ignore]
  469. fn it_creates_a_logger() {
  470. let wm = WarningsManager::new("rust-test");
  471. let im = influx::writer(wm.tx.clone());
  472. let drain =
  473. WarningsDrain {
  474. tx: Arc::new(Mutex::new(wm.tx.clone())),
  475. drain: slog::Discard,
  476. to_file: Logger::root(slog::Discard, o!()),
  477. level: Level::Trace,
  478. };
  479. let logger = slog::Logger::root(drain, o!());
  480. }
  481. #[bench]
  482. fn it_sends_integers_with_a_sender_behind_a_mutex(b: &mut Bencher) {
  483. let (tx, rx) = channel();
  484. enum Msg {
  485. Val(usize),
  486. Terminate
  487. }
  488. let worker = thread::spawn(move || {
  489. let mut xs = Vec::new();
  490. loop {
  491. match rx.recv().unwrap() {
  492. Msg::Val(x) => { xs.push(x); }
  493. Msg::Terminate => break,
  494. }
  495. }
  496. xs.len()
  497. });
  498. let tx = Arc::new(Mutex::new(tx));
  499. b.iter(|| {
  500. let lock = tx.lock().unwrap();
  501. let _ = lock.send(Msg::Val(1));
  502. });
  503. let _ = tx.lock().unwrap().send(Msg::Terminate);
  504. let len = worker.join().unwrap();
  505. //println!("{}", len);
  506. }
  507. }