@@ -18,13 +18,6 @@ use crate::registry::Registry;
18
18
19
19
const REQWEST_TIMEOUT_SEC : Duration = Duration :: from_secs ( 10 ) ;
20
20
21
- lazy_static ! {
22
- static ref HTTP_CLIENT : Client = Client :: builder( )
23
- . timeout( REQWEST_TIMEOUT_SEC )
24
- . build( )
25
- . unwrap( ) ;
26
- }
27
-
28
21
/// `BasicAuthentication` holder for supporting `push` to Pushgateway endpoints
29
22
/// using Basic access authentication.
30
23
/// Can be passed to any `push_metrics` method.
@@ -60,6 +53,18 @@ pub fn push_metrics<S: BuildHasher>(
60
53
push ( job, grouping, url, mfs, "PUT" , basic_auth)
61
54
}
62
55
56
+ /// Functions just like `push_metrics`, except the metrics are pushed
57
+ /// asynchronously.
58
+ pub async fn push_metrics_async < S : BuildHasher > (
59
+ job : & str ,
60
+ grouping : HashMap < String , String , S > ,
61
+ url : & str ,
62
+ mfs : Vec < proto:: MetricFamily > ,
63
+ basic_auth : Option < BasicAuthentication > ,
64
+ ) -> Result < ( ) > {
65
+ push_async ( job, grouping, url, mfs, "PUT" , basic_auth) . await
66
+ }
67
+
63
68
/// `push_add_metrics` works like `push_metrics`, but only previously pushed
64
69
/// metrics with the same name (and the same job and other grouping labels) will
65
70
/// be replaced. (It uses HTTP method 'POST' to push to the Pushgateway.)
@@ -73,16 +78,25 @@ pub fn push_add_metrics<S: BuildHasher>(
73
78
push ( job, grouping, url, mfs, "POST" , basic_auth)
74
79
}
75
80
81
+ /// `push_add_metrics_async` works like `push_metrics`, but async.
82
+ pub async fn push_add_metrics_async < ' a , S : BuildHasher > (
83
+ job : & ' a str ,
84
+ grouping : HashMap < String , String , S > ,
85
+ url : & ' a str ,
86
+ mfs : Vec < proto:: MetricFamily > ,
87
+ basic_auth : Option < BasicAuthentication > ,
88
+ ) -> Result < ( ) > {
89
+ push ( job, grouping, url, mfs, "POST" , basic_auth)
90
+ }
91
+
76
92
const LABEL_NAME_JOB : & str = "job" ;
77
93
78
- fn push < S : BuildHasher > (
94
+ fn configure_push < S : BuildHasher > (
79
95
job : & str ,
80
96
grouping : HashMap < String , String , S > ,
81
97
url : & str ,
82
98
mfs : Vec < proto:: MetricFamily > ,
83
- method : & str ,
84
- basic_auth : Option < BasicAuthentication > ,
85
- ) -> Result < ( ) > {
99
+ ) -> Result < ( String , impl Encoder , Vec < u8 > ) > {
86
100
// Suppress clippy warning needless_pass_by_value.
87
101
let grouping = grouping;
88
102
@@ -145,7 +159,24 @@ fn push<S: BuildHasher>(
145
159
// Ignore error, `no metrics` and `no name`.
146
160
let _ = encoder. encode ( & [ mf] , & mut buf) ;
147
161
}
162
+ Ok ( ( push_url, encoder, buf) )
163
+ }
148
164
165
+ fn push < S : BuildHasher > (
166
+ job : & str ,
167
+ grouping : HashMap < String , String , S > ,
168
+ url : & str ,
169
+ mfs : Vec < proto:: MetricFamily > ,
170
+ method : & str ,
171
+ basic_auth : Option < BasicAuthentication > ,
172
+ ) -> Result < ( ) > {
173
+ let ( push_url, encoder, buf) = configure_push ( job, grouping, url, mfs) ?;
174
+ lazy_static ! {
175
+ static ref HTTP_CLIENT : Client = Client :: builder( )
176
+ . timeout( REQWEST_TIMEOUT_SEC )
177
+ . build( )
178
+ . unwrap( ) ;
179
+ }
149
180
let mut builder = HTTP_CLIENT
150
181
. request (
151
182
Method :: from_str ( method) . unwrap ( ) ,
@@ -159,14 +190,50 @@ fn push<S: BuildHasher>(
159
190
}
160
191
161
192
let response = builder. send ( ) . map_err ( |e| Error :: Msg ( format ! ( "{}" , e) ) ) ?;
193
+ handle_push_response ( response. status ( ) , push_url)
194
+ }
195
+
196
+ async fn push_async < S : BuildHasher > (
197
+ job : & str ,
198
+ grouping : HashMap < String , String , S > ,
199
+ url : & str ,
200
+ mfs : Vec < proto:: MetricFamily > ,
201
+ method : & str ,
202
+ basic_auth : Option < BasicAuthentication > ,
203
+ ) -> Result < ( ) > {
204
+ let ( push_url, encoder, buf) = configure_push ( job, grouping, url, mfs) ?;
205
+ lazy_static ! {
206
+ static ref ASYNC_HTTP_CLIENT : reqwest:: Client = reqwest:: Client :: builder( )
207
+ . timeout( REQWEST_TIMEOUT_SEC )
208
+ . build( )
209
+ . unwrap( ) ;
210
+ }
211
+ let mut builder = ASYNC_HTTP_CLIENT
212
+ . request (
213
+ Method :: from_str ( method) . unwrap ( ) ,
214
+ Url :: from_str ( & push_url) . unwrap ( ) ,
215
+ )
216
+ . header ( CONTENT_TYPE , encoder. format_type ( ) )
217
+ . body ( buf) ;
218
+
219
+ if let Some ( BasicAuthentication { username, password } ) = basic_auth {
220
+ builder = builder. basic_auth ( username, Some ( password) ) ;
221
+ }
162
222
163
- match response. status ( ) {
223
+ let response = builder
224
+ . send ( )
225
+ . await
226
+ . map_err ( |e| Error :: Msg ( format ! ( "{}" , e) ) ) ?;
227
+ handle_push_response ( response. status ( ) , push_url)
228
+ }
229
+
230
+ fn handle_push_response ( status : StatusCode , push_url : String ) -> Result < ( ) > {
231
+ match status {
164
232
StatusCode :: ACCEPTED => Ok ( ( ) ) ,
165
233
StatusCode :: OK => Ok ( ( ) ) ,
166
234
_ => Err ( Error :: Msg ( format ! (
167
235
"unexpected status code {} while pushing to {}" ,
168
- response. status( ) ,
169
- push_url
236
+ status, push_url
170
237
) ) ) ,
171
238
}
172
239
}
@@ -188,6 +255,23 @@ fn push_from_collector<S: BuildHasher>(
188
255
push ( job, grouping, url, mfs, method, basic_auth)
189
256
}
190
257
258
+ async fn push_from_collector_async < ' a , S : BuildHasher > (
259
+ job : & ' a str ,
260
+ grouping : HashMap < String , String , S > ,
261
+ url : & ' a str ,
262
+ collectors : Vec < Box < dyn Collector > > ,
263
+ method : & ' a str ,
264
+ basic_auth : Option < BasicAuthentication > ,
265
+ ) -> Result < ( ) > {
266
+ let registry = Registry :: new ( ) ;
267
+ for bc in collectors {
268
+ registry. register ( bc) ?;
269
+ }
270
+
271
+ let mfs = registry. gather ( ) ;
272
+ push_async ( job, grouping, url, mfs, method, basic_auth) . await
273
+ }
274
+
191
275
/// `push_collector` push metrics collected from the provided collectors. It is
192
276
/// a convenient way to push only a few metrics.
193
277
pub fn push_collector < S : BuildHasher > (
@@ -200,7 +284,20 @@ pub fn push_collector<S: BuildHasher>(
200
284
push_from_collector ( job, grouping, url, collectors, "PUT" , basic_auth)
201
285
}
202
286
203
- /// `push_add_collector` works like `push_add_metrics`, it collects from the
287
+ /// `push_collector_async` is just an async version of `push_collector`.
288
+ /// Pushes metrics collected from the provided collectors. It is
289
+ /// a convenient way to push only a few metrics.
290
+ pub async fn push_collector_async < ' a , S : BuildHasher > (
291
+ job : & ' a str ,
292
+ grouping : HashMap < String , String , S > ,
293
+ url : & ' a str ,
294
+ collectors : Vec < Box < dyn Collector > > ,
295
+ basic_auth : Option < BasicAuthentication > ,
296
+ ) -> Result < ( ) > {
297
+ push_from_collector_async ( job, grouping, url, collectors, "PUT" , basic_auth) . await
298
+ }
299
+
300
+ /// `push_add_collector` works like `push_add_collector`, it collects from the
204
301
/// provided collectors. It is a convenient way to push only a few metrics.
205
302
pub fn push_add_collector < S : BuildHasher > (
206
303
job : & str ,
@@ -212,6 +309,19 @@ pub fn push_add_collector<S: BuildHasher>(
212
309
push_from_collector ( job, grouping, url, collectors, "POST" , basic_auth)
213
310
}
214
311
312
+ /// `push_add_collector_async` works like `push_add_collector`, but async.
313
+ /// It collects from the provided collectors. It is a convenient way to push
314
+ /// only a few metrics.
315
+ pub async fn push_add_collector_async < ' a , S : BuildHasher > (
316
+ job : & ' a str ,
317
+ grouping : HashMap < String , String , S > ,
318
+ url : & ' a str ,
319
+ collectors : Vec < Box < dyn Collector > > ,
320
+ basic_auth : Option < BasicAuthentication > ,
321
+ ) -> Result < ( ) > {
322
+ push_from_collector_async ( job, grouping, url, collectors, "POST" , basic_auth) . await
323
+ }
324
+
215
325
const DEFAULT_GROUP_LABEL_PAIR : ( & str , & str ) = ( "instance" , "unknown" ) ;
216
326
217
327
/// `hostname_grouping_key` returns a label map with the only entry
0 commit comments