Repository: metrics-rs/metrics (Rust)

Issue:
Add macro test for dynamic keys + static labels.
As shown in #195, we had a bug where a dynamic name/static labels combination had compilation errors due to incorrect functionality in the procedural macros.  We need to add a test to stress this use case so that we don't miss it in tests in the future.


Discussion:

Patch:
diff --git a/metrics-macros/src/lib.rs b/metrics-macros/src/lib.rs
index cee262d9..bc8e1cd3 100644
--- a/metrics-macros/src/lib.rs
+++ b/metrics-macros/src/lib.rs
@@ -425,7 +425,7 @@ fn generate_metric_key(name: &Expr, labels: &Option<Labels>) -> TokenStream2 {
         // to figure out the correct key.
         if has_labels {
             quote! {
-                metrics::Key::Owned(metrics::KeyData::from_parts(#name, & METRIC_LABELS))
+                metrics::Key::Owned(metrics::KeyData::from_static_labels(#name, &METRIC_LABELS))
             }
         } else {
             quote! {
diff --git a/metrics/src/key.rs b/metrics/src/key.rs
index 434a334a..6392a4b6 100644
--- a/metrics/src/key.rs
+++ b/metrics/src/key.rs
@@ -125,6 +125,17 @@ impl KeyData {
         }
     }
 
+    /// Creates a [`KeyData`] from a non-static name and a static set of labels.
+    pub fn from_static_labels<N>(name: N, labels: &'static [Label]) -> Self
+    where
+        N: Into<NameParts>,
+    {
+        Self {
+            name_parts: name.into(),
+            labels: Cow::<[Label]>::const_slice(labels),
+        }
+    }
+
     /// Creates a [`KeyData`] from a static name.
     ///
     /// This function is `const`, so it can be used in a static context.


Test patch:
diff --git a/metrics-macros/src/tests.rs b/metrics-macros/src/tests.rs
index 2f3fdda9..2be96c25 100644
--- a/metrics-macros/src/tests.rs
+++ b/metrics-macros/src/tests.rs
@@ -227,7 +227,7 @@ fn test_get_expanded_callsite_owned_name_static_inline_labels() {
         "{ ",
         "static METRIC_LABELS : [metrics :: Label ; 1usize] = [metrics :: Label :: from_static_parts (\"key1\" , \"value1\")] ; ",
         "if let Some (recorder) = metrics :: try_recorder () { ",
-        "recorder . myop_mytype (metrics :: Key :: Owned (metrics :: KeyData :: from_parts (String :: from (\"owned\") , & METRIC_LABELS)) , 1) ; ",
+        "recorder . myop_mytype (metrics :: Key :: Owned (metrics :: KeyData :: from_static_labels (String :: from (\"owned\") , & METRIC_LABELS)) , 1) ; ",
         "} ",
         "}",
     );
diff --git a/metrics/tests/macros/01_basic.rs b/metrics/tests/macros/01_basic.rs
index a215ad61..291d8a5a 100644
--- a/metrics/tests/macros/01_basic.rs
+++ b/metrics/tests/macros/01_basic.rs
@@ -1,12 +1,28 @@
 use metrics::counter;
 
-fn static_key() {
+fn literal_key() {
     counter!("abcdef", 1);
 }
 
-fn dynamic_key() {
+fn literal_key_literal_labels() {
+    counter!("abcdef", 1, "uvw" => "xyz");
+}
+
+fn nonliteral_key() {
     let some_u16 = 0u16;
     counter!(format!("response_status_{}", some_u16), 1);
 }
 
+fn nonliteral_key_literal_labels() {
+    let some_u16 = 0u16;
+    counter!(format!("response_status_{}", some_u16), 1, "uvw" => "xyz");
+}
+
+fn nonliteral_key_nonliteral_labels() {
+    let some_u16 = 0u16;
+    let dynamic_val = "xyz";
+    let labels = [("uvw", format!("{}!", dynamic_val))];
+    counter!(format!("response_status_{}", some_u16), 12, &labels);
+}
+
 fn main() {}