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.

771 lines
25KB

  1. //! Utilities to efficiently send data to influx
  2. //!
  3. use std::iter::FromIterator;
  4. use std::io::{Write, Read};
  5. use std::sync::mpsc::{Sender, Receiver, channel};
  6. use std::thread;
  7. use std::collections::HashMap;
  8. use std::fs::{self, OpenOptions};
  9. use std::time::Duration;
  10. use hyper::status::StatusCode;
  11. use hyper::client::response::Response;
  12. use hyper::Url;
  13. use hyper::client::Client;
  14. use influent::measurement::{Measurement, Value};
  15. use zmq;
  16. use chrono::{DateTime, Utc, TimeZone};
  17. use sloggers::types::Severity;
  18. use super::{nanos, file_logger};
  19. use warnings::Warning;
  20. const WRITER_ADDR: &'static str = "ipc:///tmp/mm/influx";
  21. //const WRITER_ADDR: &'static str = "tcp://127.0.0.1:17853";
  22. const DB_NAME: &'static str = "mm";
  23. const DB_HOST: &'static str = "http://washington.0ptimus.internal:8086/write";
  24. //const DB_HOST: &'static str = "http://harrison.0ptimus.internal:8086/write";
  25. const ZMQ_RCV_HWM: i32 = 0;
  26. const ZMQ_SND_HWM: i32 = 0;
  27. /// Provides flexible and ergonomic use of `Sender<OwnedMeasurement>`.
  28. ///
  29. /// The macro both creates an `OwnedMeasurement` from the supplied tags and
  30. /// values, as well as sends it with the `Sender`.
  31. ///
  32. /// Benchmarks show around 600ns for a small measurement and 1u for a medium-sized
  33. /// measurement (see `tests` mod).
  34. ///
  35. /// # Examples
  36. ///
  37. /// ```
  38. /// #[macro_use] extern crate logging;
  39. ///
  40. /// use std::sync::mpsc::channel;
  41. /// use logging::influx::*;
  42. ///
  43. /// fn main() {
  44. /// let (tx, rx) = channel();
  45. ///
  46. /// // "shorthand" syntax
  47. ///
  48. /// measure!(tx, test, tag[color;"red"], int[n;1]);
  49. ///
  50. /// let meas: OwnedMeasurement = rx.recv().unwrap();
  51. ///
  52. /// assert_eq!(meas.key, "test");
  53. /// assert_eq!(meas.tags.get("color"), Some(&"red"));
  54. /// assert_eq!(meas.fields.get("n"), Some(&OwnedValue::Integer(1)));
  55. ///
  56. /// // alternate syntax ...
  57. ///
  58. /// measure!(tx, test,
  59. /// tag [ one => "a" ],
  60. /// tag [ two => "b" ],
  61. /// int [ three => 2 ],
  62. /// float [ four => 1.2345 ],
  63. /// string [ five => String::from("d") ],
  64. /// bool [ six => true ],
  65. /// int [ seven => { 1 + 2 } ],
  66. /// time [ 1 ]
  67. /// );
  68. ///
  69. /// let meas: OwnedMeasurement = rx.recv().unwrap();
  70. ///
  71. /// assert_eq!(meas.key, "test");
  72. /// assert_eq!(meas.tags.get("one"), Some(&"a"));
  73. /// assert_eq!(meas.tags.get("two"), Some(&"b"));
  74. /// assert_eq!(meas.fields.get("three"), Some(&OwnedValue::Integer(2)));
  75. /// assert_eq!(meas.fields.get("seven"), Some(&OwnedValue::Integer(3)));
  76. /// assert_eq!(meas.timestamp, Some(1));
  77. /// }
  78. /// ```
  79. ///
  80. #[macro_export]
  81. macro_rules! measure {
  82. (@kv $t:tt, $meas:ident, $k:tt => $v:expr) => { measure!(@ea $t, $meas, stringify!($k), $v) };
  83. (@kv $t:tt, $meas:ident, $k:tt; $v:expr) => { measure!(@ea $t, $meas, stringify!($k), $v) };
  84. (@kv time, $meas:ident, $tm:expr) => { $meas = $meas.set_timestamp($tm as i64) };
  85. (@ea tag, $meas:ident, $k:expr, $v:expr) => { $meas = $meas.add_tag($k, $v); };
  86. (@ea int, $meas:ident, $k:expr, $v:expr) => { $meas = $meas.add_field($k, $crate::influx::OwnedValue::Integer($v)) };
  87. (@ea float, $meas:ident, $k:expr, $v:expr) => { $meas = $meas.add_field($k, $crate::influx::OwnedValue::Float($v)) };
  88. (@ea string, $meas:ident, $k:expr, $v:expr) => { $meas = $meas.add_field($k, $crate::influx::OwnedValue::String($v)) };
  89. (@ea bool, $meas:ident, $k:expr, $v:expr) => { $meas = $meas.add_field($k, $crate::influx::OwnedValue::Boolean($v)) };
  90. ($m:tt, $name:tt, $( $t:tt [ $($tail:tt)* ] ),+ $(,)*) => {{
  91. let mut meas = $crate::influx::OwnedMeasurement::new(stringify!($name));
  92. $(
  93. measure!(@kv $t, meas, $($tail)*);
  94. )*
  95. let _ = $m.send(meas);
  96. }};
  97. }
  98. #[test]
  99. fn it_checks_color_tag_error_in_non_doctest() {
  100. let (tx, rx) = channel();
  101. measure!(tx, test, tag[color;"red"], int[n;1]);
  102. let meas: OwnedMeasurement = rx.recv().unwrap();
  103. assert_eq!(meas.tags.get("color"), Some(&"red"), "meas = \n {:?} \n", meas);
  104. }
  105. #[test]
  106. fn it_uses_the_measure_macro() {
  107. let (tx, rx) = channel();
  108. measure!(tx, test_measurement,
  109. tag [ one => "a" ],
  110. tag [ two => "b" ],
  111. int [ three => 2 ],
  112. float [ four => 1.2345 ],
  113. string [ five => String::from("d") ],
  114. bool [ six => true ],
  115. int [ seven => { 1 + 2 } ],
  116. time [ 1 ]
  117. );
  118. thread::sleep_ms(10);
  119. let meas: OwnedMeasurement = rx.try_recv().unwrap();
  120. assert_eq!(meas.key, "test_measurement");
  121. assert_eq!(meas.tags.get("one"), Some(&"a"));
  122. assert_eq!(meas.tags.get("two"), Some(&"b"));
  123. assert_eq!(meas.fields.get("three"), Some(&OwnedValue::Integer(2)));
  124. assert_eq!(meas.fields.get("seven"), Some(&OwnedValue::Integer(3)));
  125. assert_eq!(meas.timestamp, Some(1));
  126. }
  127. #[test]
  128. fn it_uses_the_measure_macro_alt_syntax() {
  129. let (tx, rx) = channel();
  130. measure!(tx, test_measurement,
  131. tag[one; "a"],
  132. tag[two; "b"],
  133. int[three; 2],
  134. float[four; 1.2345],
  135. string[five; String::from("d")],
  136. bool [ six => true ],
  137. int[seven; { 1 + 2 }],
  138. time[1]
  139. );
  140. thread::sleep_ms(10);
  141. let meas: OwnedMeasurement = rx.try_recv().unwrap();
  142. assert_eq!(meas.key, "test_measurement");
  143. assert_eq!(meas.tags.get("one"), Some(&"a"));
  144. assert_eq!(meas.tags.get("two"), Some(&"b"));
  145. assert_eq!(meas.fields.get("three"), Some(&OwnedValue::Integer(2)));
  146. assert_eq!(meas.fields.get("seven"), Some(&OwnedValue::Integer(3)));
  147. assert_eq!(meas.timestamp, Some(1));
  148. }
  149. #[test]
  150. fn try_to_break_measure_macro() {
  151. let (tx, _) = channel();
  152. measure!(tx, one, tag[x=>"y"], int[n;1]);
  153. measure!(tx, one, tag[x;"y"], int[n;1],);
  154. }
  155. pub fn pull(ctx: &zmq::Context) -> Result<zmq::Socket, zmq::Error> {
  156. let socket = ctx.socket(zmq::PULL)?;
  157. socket.bind(WRITER_ADDR)?;
  158. socket.set_rcvhwm(ZMQ_RCV_HWM)?;
  159. Ok(socket)
  160. }
  161. pub fn push(ctx: &zmq::Context) -> Result<zmq::Socket, zmq::Error> {
  162. let socket = ctx.socket(zmq::PUSH)?;
  163. socket.connect(WRITER_ADDR)?;
  164. socket.set_sndhwm(ZMQ_SND_HWM)?;
  165. Ok(socket)
  166. }
  167. /// This removes offending things rather than escaping them.
  168. ///
  169. fn escape_tag(s: &str) -> String {
  170. s.replace(" ", "")
  171. .replace(",", "")
  172. .replace("\"", "")
  173. }
  174. fn escape(s: &str) -> String {
  175. s.replace(" ", "\\ ")
  176. .replace(",", "\\,")
  177. }
  178. fn as_string(s: &str) -> String {
  179. // the second replace removes double escapes
  180. //
  181. format!("\"{}\"", s.replace("\"", "\\\"")
  182. .replace(r#"\\""#, r#"\""#))
  183. }
  184. #[test]
  185. fn it_checks_as_string_does_not_double_escape() {
  186. let raw = "this is \\\"an escaped string\\\" so it's problematic";
  187. let escaped = as_string(&raw);
  188. assert_eq!(escaped, format!("\"{}\"", raw).as_ref());
  189. }
  190. fn as_integer(i: &i64) -> String {
  191. format!("{}i", i)
  192. }
  193. fn as_float(f: &f64) -> String {
  194. f.to_string()
  195. }
  196. fn as_boolean(b: &bool) -> &str {
  197. if *b { "t" } else { "f" }
  198. }
  199. pub fn now() -> i64 {
  200. nanos(Utc::now()) as i64
  201. }
  202. /// Serialize the measurement into influx line protocol
  203. /// and append to the buffer.
  204. ///
  205. /// # Examples
  206. ///
  207. /// ```
  208. /// extern crate influent;
  209. /// extern crate logging;
  210. ///
  211. /// use influent::measurement::{Measurement, Value};
  212. /// use std::string::String;
  213. /// use logging::influx::serialize;
  214. ///
  215. /// fn main() {
  216. /// let mut buf = String::new();
  217. /// let mut m = Measurement::new("test");
  218. /// m.add_field("x", Value::Integer(1));
  219. /// serialize(&m, &mut buf);
  220. /// }
  221. ///
  222. /// ```
  223. ///
  224. pub fn serialize(measurement: &Measurement, line: &mut String) {
  225. line.push_str(&escape(measurement.key));
  226. for (tag, value) in measurement.tags.iter() {
  227. line.push_str(",");
  228. line.push_str(&escape(tag));
  229. line.push_str("=");
  230. line.push_str(&escape(value));
  231. }
  232. let mut was_spaced = false;
  233. for (field, value) in measurement.fields.iter() {
  234. line.push_str({if !was_spaced { was_spaced = true; " " } else { "," }});
  235. line.push_str(&escape(field));
  236. line.push_str("=");
  237. match value {
  238. &Value::String(ref s) => line.push_str(&as_string(s)),
  239. &Value::Integer(ref i) => line.push_str(&as_integer(i)),
  240. &Value::Float(ref f) => line.push_str(&as_float(f)),
  241. &Value::Boolean(ref b) => line.push_str(as_boolean(b))
  242. };
  243. }
  244. match measurement.timestamp {
  245. Some(t) => {
  246. line.push_str(" ");
  247. line.push_str(&t.to_string());
  248. }
  249. _ => {}
  250. }
  251. }
  252. pub fn serialize_owned(measurement: &OwnedMeasurement, line: &mut String) {
  253. line.push_str(&escape_tag(measurement.key));
  254. let add_tag = |line: &mut String, key: &str, value: &str| {
  255. line.push_str(",");
  256. line.push_str(&escape_tag(key));
  257. line.push_str("=");
  258. line.push_str(&escape(value));
  259. };
  260. for (key, value) in measurement.tags.iter() {
  261. add_tag(line, key, value);
  262. }
  263. for (key, value) in measurement.string_tags.iter() {
  264. add_tag(line, key, value);
  265. }
  266. let mut fields = measurement.fields.iter();
  267. let add_field = |line: &mut String, key: &str, value: &OwnedValue| {
  268. line.push_str(" ");
  269. line.push_str(&escape_tag(key));
  270. line.push_str("=");
  271. match value {
  272. &OwnedValue::String(ref s) => line.push_str(&as_string(s)),
  273. &OwnedValue::Integer(ref i) => line.push_str(&format!("{}i", i)),
  274. &OwnedValue::Float(ref f) => line.push_str(&format!("{}", f)),
  275. &OwnedValue::Boolean(ref b) => line.push_str(as_boolean(b))
  276. };
  277. };
  278. let mut fields = measurement.fields.iter();
  279. // first time separate from tags with space
  280. //
  281. fields.next().map(|kv| {
  282. add_field(line, kv.0, kv.1);
  283. });
  284. // then seperate the rest w/ comma
  285. //
  286. for kv in fields {
  287. add_field(line, kv.0, kv.1);
  288. }
  289. if let Some(t) = measurement.timestamp {
  290. line.push_str(" ");
  291. line.push_str(&t.to_string());
  292. }
  293. }
  294. pub fn writer(warnings: Sender<Warning>) -> thread::JoinHandle<()> {
  295. thread::spawn(move || {
  296. let _ = fs::create_dir("/tmp/mm");
  297. let ctx = zmq::Context::new();
  298. let socket = pull(&ctx).expect("influx::writer failed to create pull socket");
  299. let url = Url::parse_with_params(DB_HOST, &[("db", DB_NAME), ("precision", "ns")]).expect("influx writer url should parse");
  300. let client = Client::new();
  301. let mut buf = String::with_capacity(4096);
  302. let mut server_resp = String::with_capacity(4096);
  303. let mut count = 0;
  304. loop {
  305. if let Ok(bytes) = socket.recv_bytes(0) {
  306. if let Ok(msg) = String::from_utf8(bytes) {
  307. count = match count {
  308. 0 => {
  309. buf.push_str(&msg);
  310. 1
  311. }
  312. n @ 1...40 => {
  313. buf.push_str("\n");
  314. buf.push_str(&msg);
  315. n + 1
  316. }
  317. _ => {
  318. buf.push_str("\n");
  319. buf.push_str(&msg);
  320. match client.post(url.clone())
  321. .body(&buf)
  322. .send() {
  323. Ok(Response { status, .. }) if status == StatusCode::NoContent => {}
  324. Ok(mut resp) => {
  325. resp.read_to_string(&mut server_resp); //.unwrap_or(0);
  326. let _ = warnings.send(
  327. Warning::Error(
  328. format!("Influx server: {}", server_resp)));
  329. server_resp.clear();
  330. }
  331. Err(why) => {
  332. let _ = warnings.send(
  333. Warning::Error(
  334. format!("Influx write error: {}", why)));
  335. }
  336. }
  337. buf.clear();
  338. 0
  339. }
  340. }
  341. }
  342. }
  343. }
  344. })
  345. }
  346. #[derive(Debug, Clone, PartialEq)]
  347. pub enum OwnedValue {
  348. String(String),
  349. Float(f64),
  350. Integer(i64),
  351. Boolean(bool)
  352. }
  353. #[derive(Clone, Debug)]
  354. pub struct OwnedMeasurement {
  355. pub key: &'static str,
  356. pub timestamp: Option<i64>,
  357. pub fields: HashMap<&'static str, OwnedValue>,
  358. pub tags: HashMap<&'static str, &'static str>,
  359. pub string_tags: HashMap<&'static str, String>
  360. }
  361. impl OwnedMeasurement {
  362. pub fn new(key: &'static str) -> Self {
  363. OwnedMeasurement {
  364. key,
  365. timestamp: None,
  366. fields: HashMap::new(),
  367. tags: HashMap::new(),
  368. string_tags: HashMap::new()
  369. }
  370. }
  371. pub fn add_tag(mut self, key: &'static str, value: &'static str) -> Self {
  372. self.tags.insert(key, value);
  373. self
  374. }
  375. pub fn add_string_tag(mut self, key: &'static str, value: String) -> Self {
  376. self.string_tags.insert(key, value);
  377. self
  378. }
  379. pub fn add_field(mut self, key: &'static str, value: OwnedValue) -> Self {
  380. self.fields.insert(key, value);
  381. self
  382. }
  383. pub fn set_timestamp(mut self, timestamp: i64) -> Self {
  384. self.timestamp = Some(timestamp);
  385. self
  386. }
  387. pub fn set_tag(mut self, key: &'static str, value: &'static str) -> Self {
  388. *self.tags.entry(key).or_insert(value) = value;
  389. self
  390. }
  391. }
  392. pub fn dur_nanos(d: ::std::time::Duration) -> i64 {
  393. (d.as_secs() * 1_000_000_000_u64 + (d.subsec_nanos() as u64)) as i64
  394. }
  395. //pub fn now() -> i64 { ::latency::dt_nanos(Utc::now()) }
  396. /// exactly like `writer`, but also returns a `Sender<Measurement>` and accepts
  397. /// incoming `Measurement`s that way *in addition* to the old socket/`String`
  398. /// method
  399. ///
  400. pub struct InfluxWriter {
  401. kill_switch: Sender<()>,
  402. thread: Option<thread::JoinHandle<()>>,
  403. }
  404. impl InfluxWriter {
  405. pub fn new(log_path: &str, warnings: Sender<Warning>) -> (Self, Sender<OwnedMeasurement>) {
  406. let (kill_switch, terminate) = channel();
  407. let (tx, rx) = channel();
  408. let logger = file_logger(log_path, Severity::Info);
  409. let thread = thread::spawn(move || {
  410. info!(logger, "initializing zmq");
  411. let _ = fs::create_dir("/tmp/mm");
  412. let ctx = zmq::Context::new();
  413. let socket = pull(&ctx).expect("influx::writer failed to create pull socket");
  414. info!(logger, "initializing url";
  415. "DB_HOST" => DB_HOST,
  416. "DB_NAME" => DB_NAME);
  417. let url = Url::parse_with_params(DB_HOST, &[("db", DB_NAME), ("precision", "ns")]).expect("influx writer url should parse");
  418. let client = Client::new();
  419. info!(logger, "initializing buffers");
  420. let mut meas_buf = String::with_capacity(4096);
  421. let mut buf = String::with_capacity(4096);
  422. let mut server_resp = String::with_capacity(4096);
  423. let mut count = 0;
  424. let next = |prev: u8, s: &str, buf: &mut String| -> u8 {
  425. debug!(logger, "appending serialized measurement to buffer";
  426. "prev" => prev,
  427. "buf.len()" => buf.len());
  428. match prev {
  429. 0 => {
  430. buf.push_str(s);
  431. 1
  432. }
  433. n @ 1...80 => {
  434. buf.push_str("\n");
  435. buf.push_str(s);
  436. n + 1
  437. }
  438. _ => {
  439. buf.push_str("\n");
  440. if s.len() > 0 {
  441. buf.push_str(s);
  442. }
  443. debug!(logger, "sending buffer to influx";
  444. "buf.len()" => buf.len());
  445. let resp = client.post(url.clone())
  446. .body(buf.as_str())
  447. .send();
  448. match resp {
  449. Ok(Response { status, .. }) if status == StatusCode::NoContent => {
  450. debug!(logger, "server responded ok: 204 NoContent");
  451. }
  452. Ok(mut resp) => {
  453. let mut server_resp = String::with_capacity(1024);
  454. //server_resp.push_str(&format!("sent at {}:\n", Utc::now()));
  455. //server_resp.push_str(&buf);
  456. //server_resp.push_str("\nreceived:\n");
  457. resp.read_to_string(&mut server_resp); //.unwrap_or(0);
  458. error!(logger, "influx server error";
  459. "status" => resp.status.to_string(),
  460. "body" => server_resp);
  461. }
  462. Err(why) => {
  463. error!(logger, "http request failed: {:?}", why);
  464. // warnings.send(
  465. // Warning::Error(
  466. // format!("Influx write error: {}", why)));
  467. }
  468. }
  469. buf.clear();
  470. 0
  471. }
  472. }
  473. };
  474. let mut rcvd_msg = false;
  475. loop {
  476. rcvd_msg = false;
  477. rx.try_recv()
  478. .map(|meas| {
  479. debug!(logger, "rcvd new OwnedMeasurement";
  480. "count" => count);
  481. serialize_owned(&meas, &mut meas_buf);
  482. count = next(count, &meas_buf, &mut buf);
  483. meas_buf.clear();
  484. rcvd_msg = true;
  485. });
  486. socket.recv_bytes(zmq::DONTWAIT).ok()
  487. .and_then(|bytes| {
  488. String::from_utf8(bytes).ok()
  489. }).map(|s| {
  490. debug!(logger, "rcvd new serialized";
  491. "count" => count);
  492. count = next(count, &s, &mut buf);
  493. rcvd_msg = true;
  494. });
  495. let end = terminate.try_recv()
  496. .map(|_| {
  497. let _ = next(::std::u8::MAX, "", &mut buf);
  498. true
  499. }).unwrap_or(false);
  500. if end { break }
  501. #[cfg(feature = "no-thrash")]
  502. {
  503. if !rcvd_msg {
  504. thread::sleep(Duration::new(0, 5000));
  505. }
  506. }
  507. }
  508. crit!(logger, "goodbye");
  509. });
  510. let writer = InfluxWriter {
  511. kill_switch,
  512. thread: Some(thread)
  513. };
  514. (writer, tx)
  515. }
  516. }
  517. impl Drop for InfluxWriter {
  518. fn drop(&mut self) {
  519. let _ = self.kill_switch.send(()).unwrap();
  520. if let Some(thread) = self.thread.take() {
  521. let _ = thread.join();
  522. }
  523. }
  524. }
  525. mod tests {
  526. use super::*;
  527. use test::{black_box, Bencher};
  528. #[bench]
  529. fn measure_macro_small(b: &mut Bencher) {
  530. let (tx, rx) = channel();
  531. let listener = thread::spawn(move || {
  532. loop { if rx.recv().is_err() { break } }
  533. });
  534. b.iter(|| {
  535. measure!(tx, test, tag[color; "red"], int[n; 1], time[now()]);
  536. });
  537. }
  538. #[bench]
  539. fn measure_macro_medium(b: &mut Bencher) {
  540. let (tx, rx) = channel();
  541. let listener = thread::spawn(move || {
  542. loop { if rx.recv().is_err() { break } }
  543. });
  544. b.iter(|| {
  545. measure!(tx, test,
  546. tag[color; "red"],
  547. tag[mood => "playful"],
  548. tag [ ticker => "xmr_btc" ],
  549. float[ price => 1.2345 ],
  550. float[ amount => 56.323],
  551. int[n; 1],
  552. time[now()]
  553. );
  554. });
  555. }
  556. #[test]
  557. #[ignore]
  558. fn it_spawns_a_writer_thread_and_sends_dummy_measurement_to_influxdb() {
  559. let ctx = zmq::Context::new();
  560. let socket = push(&ctx).unwrap();
  561. let (tx, rx) = channel();
  562. let w = writer(tx.clone());
  563. let mut buf = String::with_capacity(4096);
  564. let mut meas = Measurement::new("rust_test");
  565. meas.add_tag("a", "t");
  566. meas.add_field("c", Value::Float(1.23456));
  567. let now = now();
  568. meas.set_timestamp(now);
  569. serialize(&meas, &mut buf);
  570. socket.send_str(&buf, 0);
  571. drop(w);
  572. }
  573. #[test]
  574. fn it_serializes_a_measurement_in_place() {
  575. let mut buf = String::with_capacity(4096);
  576. let mut meas = Measurement::new("rust_test");
  577. meas.add_tag("a", "b");
  578. meas.add_field("c", Value::Float(1.0));
  579. let now = now();
  580. meas.set_timestamp(now);
  581. serialize(&meas, &mut buf);
  582. let ans = format!("rust_test,a=b c=1 {}", now);
  583. assert_eq!(buf, ans);
  584. }
  585. #[test]
  586. fn it_serializes_a_hard_to_serialize_message() {
  587. let raw = r#"error encountered trying to send krkn order: Other("Failed to send http request: Other("Resource temporarily unavailable (os error 11)")")"#;
  588. let mut buf = String::new();
  589. let mut server_resp = String::new();
  590. let mut m = Measurement::new("rust_test");
  591. m.add_field("s", Value::String(&raw));
  592. let now = now();
  593. m.set_timestamp(now);
  594. serialize(&m, &mut buf);
  595. println!("{}", buf);
  596. buf.push_str("\n");
  597. let buf_copy = buf.clone();
  598. buf.push_str(&buf_copy);
  599. println!("{}", buf);
  600. let url = Url::parse_with_params(DB_HOST, &[("db", DB_NAME), ("precision", "ns")]).expect("influx writer url should parse");
  601. let client = Client::new();
  602. match client.post(url.clone())
  603. .body(&buf)
  604. .send() {
  605. Ok(Response { status, .. }) if status == StatusCode::NoContent => {}
  606. Ok(mut resp) => {
  607. resp.read_to_string(&mut server_resp); //.unwrap_or(0);
  608. panic!("{}", server_resp);
  609. }
  610. Err(why) => {
  611. panic!(why)
  612. }
  613. }
  614. }
  615. #[bench]
  616. fn serialize_owned_longer(b: &mut Bencher) {
  617. let mut buf = String::with_capacity(1024);
  618. let m =
  619. OwnedMeasurement::new("test")
  620. .add_tag("one", "a")
  621. .add_tag("two", "b")
  622. .add_tag("ticker", "xmr_btc")
  623. .add_tag("exchange", "plnx")
  624. .add_tag("side", "bid")
  625. .add_field("three", OwnedValue::Float(1.2345))
  626. .add_field("four", OwnedValue::Integer(57))
  627. .add_field("five", OwnedValue::Boolean(true))
  628. .add_field("six", OwnedValue::String(String::from("abcdefghijklmnopqrstuvwxyz")))
  629. .set_timestamp(now());
  630. b.iter(|| {
  631. serialize_owned(&m, &mut buf);
  632. buf.clear()
  633. });
  634. }
  635. #[bench]
  636. fn serialize_owned_simple(b: &mut Bencher) {
  637. let mut buf = String::with_capacity(1024);
  638. let m =
  639. OwnedMeasurement::new("test")
  640. .add_tag("one", "a")
  641. .add_tag("two", "b")
  642. .add_field("three", OwnedValue::Float(1.2345))
  643. .add_field("four", OwnedValue::Integer(57))
  644. .set_timestamp(now());
  645. b.iter(|| {
  646. serialize_owned(&m, &mut buf);
  647. buf.clear()
  648. });
  649. }
  650. #[test]
  651. fn it_serializes_a_hard_to_serialize_message_from_owned() {
  652. let raw = r#"error encountered trying to send krkn order: Other("Failed to send http request: Other("Resource temporarily unavailable (os error 11)")")"#;
  653. let mut buf = String::new();
  654. let mut server_resp = String::new();
  655. let mut m = OwnedMeasurement::new("rust_test")
  656. .add_field("s", OwnedValue::String(raw.to_string()))
  657. .set_timestamp(now());
  658. serialize_owned(&m, &mut buf);
  659. println!("{}", buf);
  660. buf.push_str("\n");
  661. let buf_copy = buf.clone();
  662. buf.push_str(&buf_copy);
  663. println!("{}", buf);
  664. let url = Url::parse_with_params(DB_HOST, &[("db", DB_NAME), ("precision", "ns")]).expect("influx writer url should parse");
  665. let client = Client::new();
  666. match client.post(url.clone())
  667. .body(&buf)
  668. .send() {
  669. Ok(Response { status, .. }) if status == StatusCode::NoContent => {}
  670. Ok(mut resp) => {
  671. resp.read_to_string(&mut server_resp); //.unwrap_or(0);
  672. panic!("{}", server_resp);
  673. }
  674. Err(why) => {
  675. panic!(why)
  676. }
  677. }
  678. }
  679. }