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.

758 lines
22KB

  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::{self, Sender, Receiver, channel};
  6. use std::collections::{BTreeMap, VecDeque};
  7. use std::fmt::{self, Display, Error as FmtError, Formatter};
  8. use std::io::{self, Read, Write};
  9. use std::fs;
  10. use zmq;
  11. use chrono::{DateTime, Utc, TimeZone};
  12. use termion::color::{self, Fg, Bg};
  13. use influent::measurement::{Measurement, Value as InfluentValue};
  14. use slog::{self, OwnedKVList, Drain, Key, KV, Level};
  15. use sloggers::types::Severity;
  16. use super::{nanos, file_logger};
  17. use influx;
  18. const N_WARNINGS: usize = 500;
  19. #[macro_export]
  20. macro_rules! confirmed {
  21. ($warnings:ident, $($args:tt)*) => (
  22. {
  23. $warnings.send(Warning::Confirmed( ( format!($($args)*) ) ) ).unwrap();
  24. }
  25. )
  26. }
  27. /// logs a `Warning::Awesome` message to the `WarningsManager`
  28. #[macro_export]
  29. macro_rules! awesome {
  30. ($warnings:ident, $($args:tt)*) => (
  31. {
  32. $warnings.send(Warning::Awesome( ( format!($($args)*) ) ) ).unwrap();
  33. }
  34. )
  35. }
  36. #[macro_export]
  37. macro_rules! critical {
  38. ($warnings:ident, $($args:tt)*) => (
  39. {
  40. $warnings.send(Warning::Critical( ( format!($($args)*) ) ) ).unwrap();
  41. }
  42. )
  43. }
  44. #[macro_export]
  45. macro_rules! notice {
  46. ($warnings:ident, $($args:tt)*) => (
  47. {
  48. $warnings.send(Warning::Notice( ( format!($($args)*) ) ) ).unwrap();
  49. }
  50. )
  51. }
  52. #[macro_export]
  53. macro_rules! error {
  54. ($warnings:ident, $($args:tt)*) => (
  55. {
  56. $warnings.send(Warning::Error( ( format!($($args)*) ) ) ).unwrap();
  57. }
  58. )
  59. }
  60. /// represents a non-fatal error somewhere in
  61. /// the system to report either to the program interface
  62. /// or in logs.
  63. ///
  64. #[derive(Debug, Clone, PartialEq)]
  65. pub enum Warning {
  66. Notice(String),
  67. Error(String),
  68. DegradedService(String),
  69. Critical(String),
  70. Confirmed(String),
  71. Awesome(String),
  72. Log {
  73. level: Level,
  74. module: &'static str,
  75. function: &'static str,
  76. line: u32,
  77. msg: String,
  78. kv: MeasurementRecord,
  79. },
  80. Terminate
  81. }
  82. impl Warning {
  83. pub fn msg(&self) -> String {
  84. match *self {
  85. Warning::Notice(ref s) | Warning::Error(ref s) |
  86. Warning::DegradedService(ref s) | Warning::Critical(ref s) |
  87. Warning::Awesome(ref s) | Warning::Confirmed(ref s) |
  88. Warning::Log { msg: ref s, .. } =>
  89. s.clone(),
  90. Warning::Terminate => "".to_owned()
  91. }
  92. }
  93. pub fn msg_str(&self) -> &str {
  94. match *self {
  95. Warning::Notice(ref s) | Warning::Error(ref s) |
  96. Warning::DegradedService(ref s) | Warning::Critical(ref s) |
  97. Warning::Awesome(ref s) | Warning::Confirmed(ref s) |
  98. Warning::Log { msg: ref s, .. } =>
  99. s.as_ref(),
  100. Warning::Terminate => "Terminate"
  101. }
  102. }
  103. pub fn category_str(&self) -> &str {
  104. match self {
  105. &Warning::Notice(_) => "NOTC",
  106. &Warning::Error(_) => "ERRO",
  107. &Warning::Critical(_) => "CRIT",
  108. &Warning::DegradedService(_) => "DGRD",
  109. &Warning::Confirmed(_) => "CNFD",
  110. &Warning::Awesome(_) => "AWSM",
  111. &Warning::Log { ref level, .. } => level.as_short_str(),
  112. &Warning::Terminate => "TERM",
  113. }
  114. }
  115. pub fn category(&self, f: &mut Formatter) {
  116. match self {
  117. &Warning::Notice(_) => {
  118. write!(f, "[ Notice ]");
  119. }
  120. &Warning::Error(_) => {
  121. write!(f, "{yellow}[{title}]{reset}",
  122. yellow = Fg(color::LightYellow),
  123. title = " Error--",
  124. reset = Fg(color::Reset));
  125. }
  126. &Warning::Critical(_) => {
  127. write!(f, "{bg}{fg}{title}{resetbg}{resetfg}",
  128. bg = Bg(color::Red),
  129. fg = Fg(color::White),
  130. title = " CRITICAL ",
  131. resetbg = Bg(color::Reset),
  132. resetfg = Fg(color::Reset));
  133. }
  134. &Warning::Awesome(_) => {
  135. write!(f, "{color}[{title}]{reset}",
  136. color = Fg(color::Green),
  137. title = "Awesome!",
  138. reset = Fg(color::Reset));
  139. }
  140. &Warning::DegradedService(_) => {
  141. write!(f, "{color}[{title}] {reset}",
  142. color = Fg(color::Blue),
  143. title = "Degraded Service ",
  144. reset = Fg(color::Reset));
  145. }
  146. &Warning::Confirmed(_) => {
  147. write!(f, "{bg}{fg}{title}{resetbg}{resetfg}",
  148. bg = Bg(color::Blue),
  149. fg = Fg(color::White),
  150. title = "Confirmed ",
  151. resetbg = Bg(color::Reset),
  152. resetfg = Fg(color::Reset));
  153. }
  154. _ => {}
  155. }
  156. }
  157. }
  158. impl Display for Warning {
  159. fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
  160. self.category(f);
  161. write!(f, " {}", self.msg())
  162. }
  163. }
  164. // impl Message for Warning {
  165. // fn kill_switch() -> Self {
  166. // Warning::Terminate
  167. // }
  168. // }
  169. #[derive(Debug, Clone)]
  170. pub struct Record {
  171. pub time: DateTime<Utc>,
  172. pub msg: Warning
  173. }
  174. impl Record {
  175. pub fn new(msg: Warning) -> Self {
  176. let time = Utc::now();
  177. Record { time, msg }
  178. }
  179. pub fn to_measurement(&self, name: &'static str) -> Measurement {
  180. let cat = self.msg.category_str();
  181. let body = self.msg.msg_str();
  182. let mut m = Measurement::new(name);
  183. m.add_tag("category", cat);
  184. m.add_field("msg", InfluentValue::String(body));
  185. m.set_timestamp(nanos(self.time) as i64);
  186. m
  187. }
  188. }
  189. impl Display for Record {
  190. fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
  191. write!(f, "{} | {}", self.time.format("%H:%M:%S"), self.msg)
  192. }
  193. }
  194. pub type SlogResult = Result<(), slog::Error>;
  195. #[derive(Debug, Clone, PartialEq)]
  196. pub enum Value {
  197. String(String),
  198. Float(f64),
  199. Integer(i64),
  200. Boolean(bool)
  201. }
  202. impl Value {
  203. pub fn to_influent<'a>(&'a self) -> InfluentValue<'a> {
  204. match self {
  205. &Value::String(ref s) => InfluentValue::String(s),
  206. &Value::Float(n) => InfluentValue::Float(n),
  207. &Value::Integer(i) => InfluentValue::Integer(i),
  208. &Value::Boolean(b) => InfluentValue::Boolean(b),
  209. }
  210. }
  211. }
  212. #[derive(Debug, Clone, PartialEq)]
  213. pub struct MeasurementRecord {
  214. fields: Vec<(Key, Value)>,
  215. //measurement: &'a mut Measurement<'a>,
  216. tags: Vec<(Key, String)>,
  217. }
  218. impl MeasurementRecord {
  219. pub fn new() -> Self {
  220. MeasurementRecord {
  221. fields: Vec::new(),
  222. tags: Vec::new(),
  223. }
  224. }
  225. pub fn add_field(&mut self, key: Key, val: Value) -> SlogResult {
  226. self.fields.push((key, val));
  227. Ok(())
  228. }
  229. pub fn add_tag(&mut self, key: Key, val: String) -> SlogResult {
  230. match key {
  231. "exchange" | "thread" | "ticker" | "category" => {
  232. self.tags.push((key, val));
  233. }
  234. other => {
  235. self.add_field(key, Value::String(val));
  236. }
  237. }
  238. Ok(())
  239. }
  240. pub fn serialize_values(&mut self, record: &slog::Record, values: &OwnedKVList) {
  241. let mut builder = TagBuilder { mrec: self };
  242. values.serialize(record, &mut builder);
  243. }
  244. pub fn to_measurement<'a>(&'a self, name: &'a str) -> Measurement<'a> {
  245. let fields: BTreeMap<&'a str, InfluentValue<'a>> =
  246. self.fields.iter()
  247. .map(|&(k, ref v)| {
  248. (k, v.to_influent())
  249. }).collect();
  250. let tags: BTreeMap<&'a str, &'a str> =
  251. self.tags.iter()
  252. .map(|&(k, ref v)| {
  253. (k, v.as_ref())
  254. }).collect();
  255. Measurement {
  256. key: name,
  257. timestamp: Some(nanos(Utc::now()) as i64),
  258. fields,
  259. tags,
  260. }
  261. }
  262. }
  263. impl slog::Serializer for MeasurementRecord {
  264. fn emit_usize(&mut self, key: Key, val: usize) -> SlogResult { self.add_field(key, Value::Integer(val as i64)) }
  265. fn emit_isize(&mut self, key: Key, val: isize) -> SlogResult { self.add_field(key, Value::Integer(val as i64)) }
  266. fn emit_bool(&mut self, key: Key, val: bool) -> SlogResult { self.add_field(key, Value::Boolean(val)); Ok(()) }
  267. fn emit_u8(&mut self, key: Key, val: u8) -> SlogResult { self.add_field(key, Value::Integer(val as i64)) }
  268. fn emit_i8(&mut self, key: Key, val: i8) -> SlogResult { self.add_field(key, Value::Integer(val as i64)) }
  269. fn emit_u16(&mut self, key: Key, val: u16) -> SlogResult { self.add_field(key, Value::Integer(val as i64)) }
  270. fn emit_i16(&mut self, key: Key, val: i16) -> SlogResult { self.add_field(key, Value::Integer(val as i64)) }
  271. fn emit_u32(&mut self, key: Key, val: u32) -> SlogResult { self.add_field(key, Value::Integer(val as i64)) }
  272. fn emit_i32(&mut self, key: Key, val: i32) -> SlogResult { self.add_field(key, Value::Integer(val as i64)) }
  273. fn emit_f32(&mut self, key: Key, val: f32) -> SlogResult { self.add_field(key, Value::Float(val as f64)) }
  274. fn emit_u64(&mut self, key: Key, val: u64) -> SlogResult { self.add_field(key, Value::Integer(val as i64)) }
  275. fn emit_i64(&mut self, key: Key, val: i64) -> SlogResult { self.add_field(key, Value::Integer(val)) }
  276. fn emit_f64(&mut self, key: Key, val: f64) -> SlogResult { self.add_field(key, Value::Float(val)) }
  277. fn emit_str(&mut self, key: Key, val: &str) -> SlogResult { self.add_field(key, Value::String(val.to_string())) }
  278. fn emit_unit(&mut self, key: Key) -> SlogResult { self.add_field(key, Value::Boolean(true)) }
  279. fn emit_none(&mut self, key: Key) -> SlogResult { Ok(()) } //self.add_field(key, Value::String("none".into())) }
  280. fn emit_arguments(&mut self, key: Key, val: &fmt::Arguments) -> SlogResult { self.add_field(key, Value::String(val.to_string())) }
  281. }
  282. pub struct TagBuilder<'a> {
  283. mrec: &'a mut MeasurementRecord
  284. }
  285. impl<'a> slog::Serializer for TagBuilder<'a> {
  286. fn emit_str(&mut self, key: Key, val: &str) -> SlogResult {
  287. match key {
  288. "exchange" | "thread" | "ticker" | "category" => {
  289. self.mrec.add_tag(key, val.to_string())
  290. }
  291. other => {
  292. self.mrec.add_field(key, Value::String(val.to_string()))
  293. }
  294. }
  295. }
  296. fn emit_arguments(&mut self, key: Key, val: &fmt::Arguments) -> SlogResult {
  297. match key {
  298. "exchange" | "thread" | "ticker" | "category" => {
  299. self.mrec.add_tag(key, val.to_string())
  300. }
  301. other => {
  302. self.mrec.add_field(key, Value::String(val.to_string()))
  303. }
  304. }
  305. }
  306. }
  307. pub struct WarningsDrain<D: Drain> {
  308. level: Level,
  309. tx: Arc<Mutex<Sender<Warning>>>,
  310. drain: D
  311. }
  312. impl<D> WarningsDrain<D>
  313. where D: Drain
  314. {
  315. pub fn new(tx: Sender<Warning>, level: Level, drain: D) -> Self {
  316. let tx = Arc::new(Mutex::new(tx));
  317. WarningsDrain { tx, drain, level }
  318. }
  319. }
  320. impl From<Sender<Warning>> for WarningsDrain<slog::Fuse<slog::Discard>> {
  321. fn from(tx: Sender<Warning>) -> Self {
  322. WarningsDrain::new(tx, Level::Debug, slog::Discard.fuse())
  323. }
  324. }
  325. impl<D: Drain> Drain for WarningsDrain<D> {
  326. type Ok = ();
  327. type Err = D::Err;
  328. fn log(&self, record: &slog::Record, values: &OwnedKVList) -> Result<Self::Ok, Self::Err> {
  329. if record.level() <= self.level {
  330. let mut ser = MeasurementRecord::new();
  331. ser.serialize_values(record, values);
  332. record.kv().serialize(record, &mut ser);
  333. let msg = record.msg().to_string();
  334. if let Ok(lock) = self.tx.lock() {
  335. lock.send(Warning::Log {
  336. level: record.level(),
  337. module: record.module(),
  338. function: record.function(),
  339. line: record.line(),
  340. msg,
  341. kv: ser
  342. });
  343. }
  344. }
  345. let _ = self.drain.log(record, values)?;
  346. Ok(())
  347. }
  348. }
  349. #[derive(Debug)]
  350. pub struct WarningsManager {
  351. pub tx: Sender<Warning>,
  352. pub warnings: Arc<RwLock<VecDeque<Record>>>,
  353. thread: Option<JoinHandle<()>>
  354. }
  355. impl WarningsManager {
  356. /// `measurement_name` is the name of the influxdb measurement
  357. /// we will save log entries to.
  358. ///
  359. pub fn new(measurement_name: &'static str) -> Self {
  360. let warnings = Arc::new(RwLock::new(VecDeque::new()));
  361. let warnings_copy = warnings.clone();
  362. let (tx, rx) = channel();
  363. let mut buf = String::with_capacity(4096);
  364. let ctx = zmq::Context::new();
  365. let socket = influx::push(&ctx).unwrap();
  366. let thread = thread::spawn(move || {
  367. let path = format!("var/log/warnings-manager-{}.log", measurement_name);
  368. let logger = file_logger(&path, Severity::Info);
  369. info!(logger, "entering loop");
  370. loop {
  371. if let Ok(msg) = rx.recv() {
  372. match msg {
  373. Warning::Terminate => {
  374. crit!(logger, "terminating");
  375. break;
  376. }
  377. Warning::Log { level, module, function, line, msg, kv } => {
  378. debug!(logger, "new Warning::Debug arrived";
  379. "msg" => &msg);
  380. let mut meas = kv.to_measurement(measurement_name);
  381. meas.add_field("msg", InfluentValue::String(msg.as_ref()));
  382. meas.add_tag("category", level.as_short_str());
  383. influx::serialize(&meas, &mut buf);
  384. socket.send_str(&buf, 0);
  385. buf.clear();
  386. // and don't push to warnings
  387. // bc it's debug
  388. }
  389. other => {
  390. debug!(logger, "new {} arrived", other.category_str();
  391. "msg" => other.category_str());
  392. let rec = Record::new(other);
  393. {
  394. let m = rec.to_measurement(measurement_name);
  395. influx::serialize(&m, &mut buf);
  396. socket.send_str(&buf, 0);
  397. buf.clear();
  398. }
  399. if let Ok(mut lock) = warnings.write() {
  400. lock.push_front(rec);
  401. lock.truncate(N_WARNINGS);
  402. }
  403. }
  404. }
  405. }
  406. }
  407. });
  408. WarningsManager {
  409. warnings: warnings_copy,
  410. thread: Some(thread),
  411. tx
  412. }
  413. }
  414. }
  415. impl Drop for WarningsManager {
  416. fn drop(&mut self) {
  417. self.tx.send(Warning::Terminate);
  418. if let Some(thread) = self.thread.take() {
  419. thread.join();
  420. }
  421. }
  422. }
  423. pub struct ZmqDrain<D>
  424. where D: Drain,
  425. {
  426. drain: D,
  427. ctx: zmq::Context,
  428. socket: zmq::Socket,
  429. buf: Arc<Mutex<Vec<u8>>>
  430. }
  431. impl<D> ZmqDrain<D>
  432. where D: Drain,
  433. {
  434. pub fn new(drain: D) -> Self {
  435. let _ = fs::create_dir("/tmp/mm");
  436. let ctx = zmq::Context::new();
  437. let socket = ctx.socket(zmq::PUB).unwrap();
  438. socket.bind("ipc:///tmp/mm/log").expect("zmq publisher bind failed");
  439. let buf = Arc::new(Mutex::new(Vec::with_capacity(4096)));
  440. ZmqDrain {
  441. drain,
  442. ctx,
  443. socket,
  444. buf
  445. }
  446. }
  447. }
  448. const TIMESTAMP_FORMAT: &'static str = "%b %d %H:%M:%S%.3f";
  449. impl<D> Drain for ZmqDrain<D>
  450. where D: Drain
  451. {
  452. type Ok = D::Ok;
  453. type Err = D::Err;
  454. fn log(&self, record: &slog::Record, values: &OwnedKVList) -> Result<Self::Ok, Self::Err> {
  455. {
  456. let mut buf = self.buf.lock().unwrap();
  457. write!(buf, "{time} {level}",
  458. time = Utc::now().format(TIMESTAMP_FORMAT),
  459. level = record.level().as_short_str());
  460. {
  461. let mut thread_ser = ThreadSer(&mut buf);
  462. record.kv().serialize(record, &mut thread_ser);
  463. values.serialize(record, &mut thread_ser);
  464. }
  465. write!(buf, " {file:<20} {line:<5} {msg}",
  466. file = record.file(),
  467. line = record.line(),
  468. msg = record.msg());
  469. {
  470. let mut kv_ser = KvSer(&mut buf);
  471. record.kv().serialize(record, &mut kv_ser);
  472. values.serialize(record, &mut kv_ser);
  473. }
  474. self.socket.send(&buf, 0);
  475. buf.clear();
  476. }
  477. self.drain.log(record, values)
  478. }
  479. }
  480. /// Can be used as a `Write` with `slog_term` and
  481. /// other libraries.
  482. ///
  483. pub struct ZmqIo {
  484. ctx: zmq::Context,
  485. socket: zmq::Socket,
  486. buf: Vec<u8>
  487. }
  488. impl ZmqIo {
  489. pub fn new(addr: &str) -> Self {
  490. let _ = fs::create_dir("/tmp/mm");
  491. let ctx = zmq::Context::new();
  492. let socket = ctx.socket(zmq::PUB).unwrap();
  493. let addr = format!("ipc:///tmp/mm/{}", addr);
  494. socket.bind(&addr).expect("zmq publisher bind failed");
  495. let buf = Vec::with_capacity(4096);
  496. ZmqIo { ctx, socket, buf }
  497. }
  498. }
  499. impl Write for ZmqIo {
  500. fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
  501. self.buf.write(buf)
  502. }
  503. fn flush(&mut self) -> io::Result<()> {
  504. match self.buf.pop() {
  505. Some(b'\n') => {
  506. self.socket.send(&self.buf, 0);
  507. }
  508. Some(other) => {
  509. self.buf.push(other);
  510. self.socket.send(&self.buf, 0);
  511. }
  512. None => {
  513. return Ok(());
  514. }
  515. }
  516. self.buf.clear();
  517. Ok(())
  518. }
  519. }
  520. /// Serializes *only* KV pair with `key == "thread"`
  521. ///
  522. struct ThreadSer<'a>(&'a mut Vec<u8>);
  523. impl<'a> slog::ser::Serializer for ThreadSer<'a> {
  524. fn emit_arguments(&mut self, key: &str, val: &fmt::Arguments) -> slog::Result {
  525. Ok(())
  526. }
  527. fn emit_str(&mut self, key: &str, val: &str) -> slog::Result {
  528. if key == "thread" {
  529. write!(self.0, " {:<20}", val);
  530. }
  531. Ok(())
  532. }
  533. }
  534. /// Serializes KV pairs as ", k: v"
  535. ///
  536. struct KvSer<'a>(&'a mut Vec<u8>);
  537. macro_rules! s(
  538. ($s:expr, $k:expr, $v:expr) => {
  539. try!(write!($s.0, ", {}: {}", $k, $v));
  540. };
  541. );
  542. impl<'a> slog::ser::Serializer for KvSer<'a> {
  543. fn emit_none(&mut self, key: &str) -> slog::Result {
  544. s!(self, key, "None");
  545. Ok(())
  546. }
  547. fn emit_unit(&mut self, key: &str) -> slog::Result {
  548. s!(self, key, "()");
  549. Ok(())
  550. }
  551. fn emit_bool(&mut self, key: &str, val: bool) -> slog::Result {
  552. s!(self, key, val);
  553. Ok(())
  554. }
  555. fn emit_char(&mut self, key: &str, val: char) -> slog::Result {
  556. s!(self, key, val);
  557. Ok(())
  558. }
  559. fn emit_usize(&mut self, key: &str, val: usize) -> slog::Result {
  560. s!(self, key, val);
  561. Ok(())
  562. }
  563. fn emit_isize(&mut self, key: &str, val: isize) -> slog::Result {
  564. s!(self, key, val);
  565. Ok(())
  566. }
  567. fn emit_u8(&mut self, key: &str, val: u8) -> slog::Result {
  568. s!(self, key, val);
  569. Ok(())
  570. }
  571. fn emit_i8(&mut self, key: &str, val: i8) -> slog::Result {
  572. s!(self, key, val);
  573. Ok(())
  574. }
  575. fn emit_u16(&mut self, key: &str, val: u16) -> slog::Result {
  576. s!(self, key, val);
  577. Ok(())
  578. }
  579. fn emit_i16(&mut self, key: &str, val: i16) -> slog::Result {
  580. s!(self, key, val);
  581. Ok(())
  582. }
  583. fn emit_u32(&mut self, key: &str, val: u32) -> slog::Result {
  584. s!(self, key, val);
  585. Ok(())
  586. }
  587. fn emit_i32(&mut self, key: &str, val: i32) -> slog::Result {
  588. s!(self, key, val);
  589. Ok(())
  590. }
  591. fn emit_f32(&mut self, key: &str, val: f32) -> slog::Result {
  592. s!(self, key, val);
  593. Ok(())
  594. }
  595. fn emit_u64(&mut self, key: &str, val: u64) -> slog::Result {
  596. s!(self, key, val);
  597. Ok(())
  598. }
  599. fn emit_i64(&mut self, key: &str, val: i64) -> slog::Result {
  600. s!(self, key, val);
  601. Ok(())
  602. }
  603. fn emit_f64(&mut self, key: &str, val: f64) -> slog::Result {
  604. s!(self, key, val);
  605. Ok(())
  606. }
  607. fn emit_str(&mut self, key: &str, val: &str) -> slog::Result {
  608. s!(self, key, val);
  609. Ok(())
  610. }
  611. fn emit_arguments(
  612. &mut self,
  613. key: &str,
  614. val: &fmt::Arguments,
  615. ) -> slog::Result {
  616. s!(self, key, val);
  617. Ok(())
  618. }
  619. }
  620. #[cfg(test)]
  621. mod tests {
  622. use super::*;
  623. use test::{black_box, Bencher};
  624. #[test]
  625. fn it_creates_a_logger() {
  626. let wm = WarningsManager::new("rust-test");
  627. let im = influx::writer(wm.tx.clone());
  628. let drain = WarningsDrain { tx: Arc::new(Mutex::new(wm.tx.clone())), drain: slog::Discard };
  629. let logger = slog::Logger::root(drain, o!());
  630. //for _ in 0..60 {
  631. // debug!(logger, "test 123"; "exchange" => "plnx");
  632. //}
  633. }
  634. #[bench]
  635. fn it_sends_integers_with_a_sender_behind_a_mutex(b: &mut Bencher) {
  636. let (tx, rx) = channel();
  637. enum Msg {
  638. Val(usize),
  639. Terminate
  640. }
  641. let worker = thread::spawn(move || {
  642. let mut xs = Vec::new();
  643. loop {
  644. match rx.recv().unwrap() {
  645. Msg::Val(x) => { xs.push(x); }
  646. Msg::Terminate => break,
  647. }
  648. }
  649. xs.len()
  650. });
  651. let tx = Arc::new(Mutex::new(tx));
  652. b.iter(|| {
  653. let lock = tx.lock().unwrap();
  654. lock.send(Msg::Val(1));
  655. });
  656. tx.lock().unwrap().send(Msg::Terminate);
  657. let len = worker.join().unwrap();
  658. println!("{}", len);
  659. }
  660. }