11use crate :: exporters:: * ;
22use crate :: sensors:: { Sensor , Topology } ;
3- use datadog_client :: client :: { Client , Config } ;
4- use datadog_client :: metrics :: { Point , Serie , Type } ;
3+ use serde :: ser :: SerializeSeq ;
4+ use serde :: { Serialize , Serializer } ;
55use std:: collections:: HashMap ;
66use std:: thread;
77use std:: time:: { Duration , Instant } ;
88
9+ #[ derive( Clone , Debug ) ]
10+ pub enum Type {
11+ Count ,
12+ Gauge ,
13+ Rate ,
14+ }
15+
16+ impl Type {
17+ pub fn as_str ( & self ) -> & str {
18+ match self {
19+ Self :: Count => "count" ,
20+ Self :: Gauge => "gauge" ,
21+ Self :: Rate => "rate" ,
22+ }
23+ }
24+ }
25+
26+ impl Serialize for Type {
27+ fn serialize < S > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error >
28+ where
29+ S : Serializer ,
30+ {
31+ serializer. serialize_str ( self . as_str ( ) )
32+ }
33+ }
34+
35+ #[ derive( Clone , Debug ) ]
36+ pub struct Point {
37+ timestamp : u64 ,
38+ value : f64 ,
39+ }
40+
41+ impl Point {
42+ pub fn new ( timestamp : u64 , value : f64 ) -> Self {
43+ Self { timestamp, value }
44+ }
45+ }
46+
47+ impl Serialize for Point {
48+ fn serialize < S > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error >
49+ where
50+ S : Serializer ,
51+ {
52+ let mut seq = serializer. serialize_seq ( Some ( 2 ) ) ?;
53+ seq. serialize_element ( & self . timestamp ) ?;
54+ seq. serialize_element ( & self . value ) ?;
55+ seq. end ( )
56+ }
57+ }
58+
59+ /// # Examples
60+ ///
61+ /// ```
62+ /// use datadog_client::metrics::{Point, Serie, Type};
63+ ///
64+ /// let serie = Serie::new("cpu.usage", Type::Gauge)
65+ /// .set_host("raspberrypi")
66+ /// .set_interval(42)
67+ /// .set_points(vec![])
68+ /// .add_point(Point::new(123456, 12.34))
69+ /// .set_tags(vec![])
70+ /// .add_tag(String::from("whatever:tag"));
71+ /// ```
72+ #[ derive( Debug , Clone , Serialize ) ]
73+ pub struct Serie {
74+ // The name of the host that produced the metric.
75+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
76+ host : Option < String > ,
77+ // If the type of the metric is rate or count, define the corresponding interval.
78+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
79+ interval : Option < i64 > ,
80+ // The name of the timeseries.
81+ metric : String ,
82+ // Points relating to a metric. All points must be tuples with timestamp and a scalar value (cannot be a string).
83+ // Timestamps should be in POSIX time in seconds, and cannot be more than ten minutes in the future or more than one hour in the past.
84+ points : Vec < Point > ,
85+ // A list of tags associated with the metric.
86+ tags : Vec < String > ,
87+ // The type of the metric either count, gauge, or rate.
88+ #[ serde( rename = "type" ) ]
89+ dtype : Type ,
90+ }
91+
92+ impl Serie {
93+ pub fn new ( metric : & str , dtype : Type ) -> Self {
94+ Self {
95+ host : None ,
96+ interval : None ,
97+ metric : metric. to_string ( ) ,
98+ points : Vec :: new ( ) ,
99+ tags : Vec :: new ( ) ,
100+ dtype,
101+ }
102+ }
103+ }
104+
105+ impl Serie {
106+ pub fn set_host ( mut self , host : & str ) -> Self {
107+ self . host = Some ( host. to_string ( ) ) ;
108+ self
109+ }
110+
111+ pub fn set_interval ( mut self , interval : i64 ) -> Self {
112+ self . interval = Some ( interval) ;
113+ self
114+ }
115+
116+ pub fn set_points ( mut self , points : Vec < Point > ) -> Self {
117+ self . points = points;
118+ self
119+ }
120+
121+ pub fn add_point ( mut self , point : Point ) -> Self {
122+ self . points . push ( point) ;
123+ self
124+ }
125+ }
126+
127+ impl Serie {
128+ pub fn set_tags ( mut self , tags : Vec < String > ) -> Self {
129+ self . tags = tags;
130+ self
131+ }
132+
133+ pub fn add_tag ( mut self , tag : String ) -> Self {
134+ self . tags . push ( tag) ;
135+ self
136+ }
137+ }
138+
139+ struct Client {
140+ host : String ,
141+ api_key : String ,
142+ }
143+
144+ impl Client {
145+ pub fn new ( parameters : & ArgMatches ) -> Self {
146+ Self {
147+ host : parameters. value_of ( "host" ) . unwrap ( ) . to_string ( ) ,
148+ api_key : parameters. value_of ( "api_key" ) . unwrap ( ) . to_string ( ) ,
149+ }
150+ }
151+
152+ pub fn send ( & self , series : & [ Serie ] ) {
153+ let url = format ! ( "{}/api/v1/series" , self . host) ;
154+ let request = ureq:: post ( url. as_str ( ) )
155+ . set ( "DD-API-KEY" , self . api_key . as_str ( ) )
156+ . send_json ( serde_json:: json!( { "series" : series } ) ) ;
157+ match request {
158+ Ok ( response) => {
159+ if response. status ( ) >= 400 {
160+ log:: warn!(
161+ "couldn't send metrics to datadog: status {}" ,
162+ response. status_text( )
163+ ) ;
164+ if let Ok ( body) = response. into_string ( ) {
165+ log:: warn!( "response from server: {}" , body) ;
166+ }
167+ } else {
168+ log:: info!( "metrics sent with success" ) ;
169+ }
170+ }
171+ Err ( err) => log:: warn!( "error while sending metrics: {}" , err) ,
172+ } ;
173+ }
174+ }
175+
9176fn merge < A > ( first : Vec < A > , second : Vec < A > ) -> Vec < A > {
10177 second. into_iter ( ) . fold ( first, |mut res, item| {
11178 res. push ( item) ;
@@ -79,15 +246,8 @@ impl DatadogExporter {
79246 }
80247 }
81248
82- fn build_client ( parameters : & ArgMatches ) -> Client {
83- let config = Config :: new (
84- parameters. value_of ( "host" ) . unwrap ( ) . to_string ( ) ,
85- parameters. value_of ( "api_key" ) . unwrap ( ) . to_string ( ) ,
86- ) ;
87- Client :: new ( config)
88- }
89-
90- fn runner ( & mut self , parameters : & ArgMatches ) {
249+ fn runner ( & mut self , parameters : & ArgMatches < ' _ > ) {
250+ let client = Client :: new ( parameters) ;
91251 if let Some ( timeout) = parameters. value_of ( "timeout" ) {
92252 let now = Instant :: now ( ) ;
93253 let timeout = timeout
@@ -110,18 +270,18 @@ impl DatadogExporter {
110270 info ! ( "Measurement step is: {}s" , step_duration) ;
111271
112272 while now. elapsed ( ) . as_secs ( ) <= timeout {
113- self . iterate ( parameters ) ;
273+ self . iterate ( & client ) ;
114274 thread:: sleep ( Duration :: new ( step_duration, step_duration_nano) ) ;
115275 }
116276 } else {
117- self . iterate ( parameters ) ;
277+ self . iterate ( & client ) ;
118278 }
119279 }
120280
121- fn iterate ( & mut self , parameters : & ArgMatches ) {
281+ fn iterate ( & mut self , client : & Client ) {
122282 self . topology . refresh ( ) ;
123- let _series = self . collect_series ( ) ;
124- let _client = Self :: build_client ( parameters ) ;
283+ let series = self . collect_series ( ) ;
284+ client . send ( & series ) ;
125285 }
126286
127287 fn create_consumption_serie ( & self ) -> Serie {
0 commit comments