@@ -247,6 +247,23 @@ impl<S: Clone + std::hash::Hash + Eq, M, C: MetricConstructor<M>> Family<S, M, C
247
247
} )
248
248
}
249
249
250
+ /// Access a metric with the given label set, returning None if one
251
+ /// does not yet exist.
252
+ ///
253
+ /// ```
254
+ /// # use prometheus_client::metrics::counter::{Atomic, Counter};
255
+ /// # use prometheus_client::metrics::family::Family;
256
+ /// #
257
+ /// let family = Family::<Vec<(String, String)>, Counter>::default();
258
+ ///
259
+ /// if let Some(metric) = family.get(&vec![("method".to_owned(), "GET".to_owned())]) {
260
+ /// metric.inc();
261
+ /// };
262
+ /// ```
263
+ pub fn get ( & self , label_set : & S ) -> Option < MappedRwLockReadGuard < M > > {
264
+ RwLockReadGuard :: try_map ( self . metrics . read ( ) , |metrics| metrics. get ( label_set) ) . ok ( )
265
+ }
266
+
250
267
/// Remove a label set from the metric family.
251
268
///
252
269
/// Returns a bool indicating if a label set was removed or not.
@@ -452,4 +469,47 @@ mod tests {
452
469
. get( )
453
470
) ;
454
471
}
472
+
473
+ #[ test]
474
+ fn test_get ( ) {
475
+ let family = Family :: < Vec < ( String , String ) > , Counter > :: default ( ) ;
476
+
477
+ // Test getting a non-existent metric
478
+ let non_existent = family. get ( & vec ! [ ( "method" . to_string( ) , "GET" . to_string( ) ) ] ) ;
479
+ assert ! ( non_existent. is_none( ) ) ;
480
+
481
+ // Create a metric
482
+ family
483
+ . get_or_create ( & vec ! [ ( "method" . to_string( ) , "GET" . to_string( ) ) ] )
484
+ . inc ( ) ;
485
+
486
+ // Test getting an existing metric
487
+ let existing = family. get ( & vec ! [ ( "method" . to_string( ) , "GET" . to_string( ) ) ] ) ;
488
+ assert ! ( existing. is_some( ) ) ;
489
+ assert_eq ! ( existing. unwrap( ) . get( ) , 1 ) ;
490
+
491
+ // Test getting a different non-existent metric
492
+ let another_non_existent = family. get ( & vec ! [ ( "method" . to_string( ) , "POST" . to_string( ) ) ] ) ;
493
+ assert ! ( another_non_existent. is_none( ) ) ;
494
+
495
+ // Test modifying the metric through the returned reference
496
+ if let Some ( metric) = family. get ( & vec ! [ ( "method" . to_string( ) , "GET" . to_string( ) ) ] ) {
497
+ metric. inc ( ) ;
498
+ }
499
+
500
+ // Verify the modification
501
+ let modified = family. get ( & vec ! [ ( "method" . to_string( ) , "GET" . to_string( ) ) ] ) ;
502
+ assert_eq ! ( modified. unwrap( ) . get( ) , 2 ) ;
503
+
504
+ // Test with a different label set type
505
+ let string_family = Family :: < String , Counter > :: default ( ) ;
506
+ string_family. get_or_create ( & "test" . to_string ( ) ) . inc ( ) ;
507
+
508
+ let string_metric = string_family. get ( & "test" . to_string ( ) ) ;
509
+ assert ! ( string_metric. is_some( ) ) ;
510
+ assert_eq ! ( string_metric. unwrap( ) . get( ) , 1 ) ;
511
+
512
+ let non_existent_string = string_family. get ( & "non_existent" . to_string ( ) ) ;
513
+ assert ! ( non_existent_string. is_none( ) ) ;
514
+ }
455
515
}
0 commit comments