1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
use async_graphql::{Enum, Object};
use chrono::{DateTime, Utc};
use serde_json::Value;
use vector_lib::encode_logfmt;
use vector_lib::event;
use vector_lib::tap::topology::TapOutput;

use super::EventEncodingType;

#[derive(Debug, Clone)]
pub struct Metric {
    output: TapOutput,
    event: event::Metric,
}

impl Metric {
    pub const fn new(output: TapOutput, event: event::Metric) -> Self {
        Self { output, event }
    }
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, Enum)]
enum MetricKind {
    /// Incremental metrics update previous values
    Incremental,
    /// Absolute metrics set the reference value for future updates
    Absolute,
}

impl From<event::MetricKind> for MetricKind {
    fn from(kind: event::MetricKind) -> Self {
        match kind {
            event::MetricKind::Incremental => Self::Incremental,
            event::MetricKind::Absolute => Self::Absolute,
        }
    }
}

struct MetricTag {
    key: String,
    value: String,
}

#[Object]
impl MetricTag {
    /// Metric tag key
    async fn key(&self) -> &str {
        self.key.as_ref()
    }

    /// Metric tag value
    async fn value(&self) -> &str {
        self.value.as_ref()
    }
}

#[Object]
/// Metric event with fields for querying metric data
impl Metric {
    /// Id of the component associated with the metric event
    async fn component_id(&self) -> &str {
        self.output.output_id.component.id()
    }

    /// Type of component associated with the metric event
    async fn component_type(&self) -> &str {
        self.output.component_type.as_ref()
    }

    /// Kind of component associated with the metric event
    async fn component_kind(&self) -> &str {
        self.output.component_kind
    }

    /// Metric timestamp
    async fn timestamp(&self) -> Option<&DateTime<Utc>> {
        self.event.data().timestamp()
    }

    /// Metric name
    async fn name(&self) -> &str {
        self.event.name()
    }

    /// Metric namespace
    async fn namespace(&self) -> Option<&str> {
        self.event.namespace()
    }

    /// Metric kind
    async fn kind(&self) -> MetricKind {
        self.event.kind().into()
    }

    /// Metric type
    async fn value_type(&self) -> &str {
        self.event.value().as_name()
    }

    /// Metric value in human readable form
    async fn value(&self) -> String {
        self.event.value().to_string()
    }

    /// Metric tags
    async fn tags(&self) -> Option<Vec<MetricTag>> {
        self.event.tags().map(|tags| {
            tags.iter_single()
                .map(|(key, value)| MetricTag {
                    key: key.to_owned(),
                    value: value.to_owned(),
                })
                .collect()
        })
    }

    /// Metric event as an encoded string format
    async fn string(&self, encoding: EventEncodingType) -> String {
        match encoding {
            EventEncodingType::Json => serde_json::to_string(&self.event)
                .expect("JSON serialization of metric event failed. Please report."),
            EventEncodingType::Yaml => serde_yaml::to_string(&self.event)
                .expect("YAML serialization of metric event failed. Please report."),
            EventEncodingType::Logfmt => {
                let json = serde_json::to_value(&self.event)
                    .expect("logfmt serialization of metric event failed: conversion to serde Value failed. Please report.");
                match json {
                    Value::Object(map) => encode_logfmt::encode_map(
                        &map.into_iter().map(|(k,v)| (event::KeyString::from(k), v)).collect(),
                    )
                    .expect("logfmt serialization of metric event failed. Please report."),
                    _ => panic!("logfmt serialization of metric event failed: metric converted to unexpected serde Value. Please report."),
                }
            }
        }
    }
}