influxive_core/
lib.rs

1#![deny(missing_docs)]
2#![deny(warnings)]
3#![deny(unsafe_code)]
4//! Core types for influxive crates. The main point of this crate is to expose
5//! the [MetricWriter] trait to be used by downstream influxive crates.
6//!
7//! ## Example [Metric] type creation:
8//!
9//! ```
10//! let _metric = influxive_core::Metric::new(std::time::SystemTime::now(), "my.name")
11//!     .with_field("field.bool", true)
12//!     .with_field("field.float", 3.14)
13//!     .with_field("field.signed", -42)
14//!     .with_field("field.unsigned", 42)
15//!     .with_field("field.string", "string.value")
16//!     .with_tag("tag.bool", true)
17//!     .with_tag("tag.float", 3.14)
18//!     .with_tag("tag.signed", -42)
19//!     .with_tag("tag.unsigned", 42)
20//!     .with_tag("tag.string", "string.value");
21//! ```
22
23use std::borrow::Cow;
24use std::sync::Arc;
25
26/// Standin until std::io::Error::other is stablized.
27pub fn err_other<E>(error: E) -> std::io::Error
28where
29    E: Into<Box<dyn std::error::Error + Send + Sync>>,
30{
31    std::io::Error::other(error)
32}
33
34/// String type handling various string types usable by InfluxDB.
35#[derive(Debug, Clone)]
36pub enum StringType {
37    /// String value.
38    String(Cow<'static, str>),
39
40    /// String value.
41    ArcString(Arc<str>),
42}
43
44impl StringType {
45    /// Get an owned string out of this StringType.
46    pub fn into_string(self) -> String {
47        match self {
48            StringType::String(s) => s.into_owned(),
49            StringType::ArcString(s) => s.to_string(),
50        }
51    }
52}
53
54macro_rules! stringtype_from_impl {
55    ($($f:ty, $i:ident, $b:block,)*) => {$(
56        impl From<$f> for StringType {
57            fn from($i: $f) -> Self $b
58        }
59    )*};
60}
61
62stringtype_from_impl! {
63    String, f, { StringType::String(Cow::Owned(f)) },
64    &'static String, f, { StringType::String(Cow::Borrowed(f.as_str())) },
65    &'static str, f, { StringType::String(Cow::Borrowed(f)) },
66    Cow<'static, str>, f, { StringType::String(f) },
67    Arc<str>, f, { StringType::ArcString(f) },
68}
69
70/// Field-type enum for sending data to InfluxDB.
71#[derive(Debug, Clone)]
72pub enum DataType {
73    /// Bool value.
74    Bool(bool),
75
76    /// Float value.
77    F64(f64),
78
79    /// Signed integer value.
80    I64(i64),
81
82    /// Unsigned integer value.
83    U64(u64),
84
85    /// String value.
86    String(StringType),
87}
88
89macro_rules! datatype_from_impl {
90    ($($f:ty, $i:ident, $b:block,)*) => {$(
91        impl From<$f> for DataType {
92            fn from($i: $f) -> Self $b
93        }
94    )*};
95}
96
97datatype_from_impl! {
98    bool, f, { DataType::Bool(f) },
99    f64, f, { DataType::F64(f) },
100    f32, f, { DataType::F64(f as f64) },
101    i8, f, { DataType::I64(f as i64) },
102    i16, f, { DataType::I64(f as i64) },
103    i32, f, { DataType::I64(f as i64) },
104    i64, f, { DataType::I64(f as i64) },
105    u8, f, { DataType::U64(f as u64) },
106    u16, f, { DataType::U64(f as u64) },
107    u32, f, { DataType::U64(f as u64) },
108    u64, f, { DataType::U64(f as u64) },
109    String, f, { DataType::String(f.into()) },
110    &'static String, f, { DataType::String(f.into()) },
111    &'static str, f, { DataType::String(f.into()) },
112    Cow<'static, str>, f, { DataType::String(f.into()) },
113    Arc<str>, f, { DataType::String(f.into()) },
114}
115
116/// A metric to record in the influxdb instance.
117#[derive(Debug)]
118pub struct Metric {
119    /// The timestamp for this metric report.
120    pub timestamp: std::time::SystemTime,
121
122    /// The name of this metric report.
123    pub name: StringType,
124
125    /// The fields associated with this metric report.
126    pub fields: Vec<(StringType, DataType)>,
127
128    /// The tags associated with this metric report.
129    pub tags: Vec<(StringType, DataType)>,
130}
131
132impl Metric {
133    /// Construct a new metric report to be sent to InfluxDB.
134    pub fn new<N: Into<StringType>>(
135        timestamp: std::time::SystemTime,
136        name: N,
137    ) -> Metric {
138        Self {
139            timestamp,
140            name: name.into(),
141            fields: Vec::new(),
142            tags: Vec::new(),
143        }
144    }
145
146    /// Add a field to this metric report.
147    pub fn with_field<N, V>(mut self, name: N, value: V) -> Self
148    where
149        N: Into<StringType>,
150        V: Into<DataType>,
151    {
152        self.fields.push((name.into(), value.into()));
153        self
154    }
155
156    /// Add a tag to this metric report.
157    pub fn with_tag<N, V>(mut self, name: N, value: V) -> Self
158    where
159        N: Into<StringType>,
160        V: Into<DataType>,
161    {
162        self.tags.push((name.into(), value.into()));
163        self
164    }
165}
166
167/// Indicates a type that is capable of writing metrics to an InfluxDB instance.
168pub trait MetricWriter: 'static + Send + Sync {
169    /// Write a metric to an InfluxDB instance. Note, this should return
170    /// immediately, perhaps by adding the metric to a memory buffer for
171    /// a different process/task/thread to actually write the metric as
172    /// determined by the concrete implementation.
173    fn write_metric(&self, metric: Metric);
174}