metrics_sqlite/
models.rs

1//! Diesel models of metrics sqlite storage
2use crate::schema::{metric_keys, metrics};
3use crate::{MetricsError, Result};
4use ::metrics::Unit;
5use diesel::prelude::*;
6use std::borrow::Cow;
7
8/// A new metric measurement for storing into sqlite database
9#[derive(Insertable, Debug)]
10#[diesel(table_name = metrics)]
11pub struct NewMetric {
12    /// Timestamp of sample
13    pub timestamp: f64,
14    /// Key/name of sample
15    pub metric_key_id: i64,
16    /// Value of sample
17    pub value: f64,
18}
19
20/// New metric key entry
21#[derive(Insertable, Debug)]
22#[diesel(table_name = metric_keys)]
23pub struct NewMetricKey<'a> {
24    /// Actual key
25    pub key: Cow<'a, str>,
26    /// Unit if any
27    pub unit: Cow<'a, str>,
28    /// Description of metric key if any
29    pub description: Cow<'a, str>,
30}
31
32/// Metric key
33#[derive(Queryable, Debug, Identifiable)]
34#[cfg_attr(feature = "serde", derive(serde::Serialize))]
35pub struct MetricKey<'a> {
36    /// primary key of metric key
37    pub id: i64,
38    /// Actual key
39    pub key: Cow<'a, str>,
40    /// Unit if any
41    pub unit: Cow<'a, str>,
42    /// Description of metric key if any
43    pub description: Cow<'a, str>,
44}
45impl<'a> MetricKey<'a> {
46    pub(crate) fn create_or_update(
47        key_name: &str,
48        unit: Option<Unit>,
49        description: Option<&'a str>,
50        db: &mut SqliteConnection,
51    ) -> Result<MetricKey<'a>> {
52        let key = Self::key_by_name(key_name, db)?;
53        let unit_value = unit
54            .map(|u| Cow::Owned(u.as_str().to_string()))
55            .unwrap_or(Cow::Borrowed(""));
56        let description = description.map(Cow::Borrowed).unwrap_or(Cow::Borrowed(""));
57        Self::update(key.id, unit_value, description, db)?;
58        Ok(key)
59    }
60    fn update(
61        id_value: i64,
62        unit_value: Cow<'a, str>,
63        description_value: Cow<'a, str>,
64        db: &mut SqliteConnection,
65    ) -> Result<()> {
66        use crate::schema::metric_keys::dsl::*;
67        diesel::update(metric_keys.filter(id.eq(id_value)))
68            .set((unit.eq(unit_value), description.eq(description_value)))
69            .execute(db)?;
70        Ok(())
71    }
72    pub(crate) fn key_by_name(key_name: &str, db: &mut SqliteConnection) -> Result<MetricKey<'a>> {
73        use crate::schema::metric_keys::dsl::metric_keys;
74        match Self::key_by_name_inner(key_name, db) {
75            Ok(key) => Ok(key),
76            Err(MetricsError::KeyNotFound(_)) => {
77                // not stored yet so create an entry
78                let new_key = NewMetricKey {
79                    key: Cow::Borrowed(key_name),
80                    unit: Cow::Borrowed(""),
81                    description: Cow::Borrowed(""),
82                };
83                new_key.insert_into(metric_keys).execute(db)?;
84                // fetch it back out to get the ID
85                Self::key_by_name_inner(key_name, db)
86            }
87            Err(e) => Err(e),
88        }
89    }
90    fn key_by_name_inner(key_name: &str, db: &mut SqliteConnection) -> Result<MetricKey<'a>> {
91        use crate::schema::metric_keys::dsl::*;
92        let query = metric_keys.filter(key.eq(key_name));
93        let keys = query.load::<MetricKey>(db)?;
94        keys.into_iter()
95            .next()
96            .ok_or_else(|| MetricsError::KeyNotFound(key_name.to_string()))
97    }
98}
99
100/// Metric model for existing entries in sqlite database
101#[derive(Queryable, Debug, Identifiable, Associations)]
102#[diesel(belongs_to(MetricKey<'_>))]
103#[cfg_attr(feature = "serde", derive(serde::Serialize))]
104pub struct Metric {
105    /// Unique ID of sample
106    pub id: i64,
107    /// Timestamp of sample
108    pub timestamp: f64,
109    /// Key/name of sample
110    pub metric_key_id: i64,
111    /// Value of sample
112    pub value: f64,
113}