Repository: dbt-labs/dbt-core

Issue:
Error in serializing with wrong syntax for metric 'model' field
The correct syntax for the 'model' attribute in a metrics definition is "ref('my_model')". If all of the quotes are removed, we get an error in serializing: E   TypeError: can not serialize 'Undefined' object


Discussion:

Resolving patch:
diff --git a/core/dbt/context/providers.py b/core/dbt/context/providers.py
--- a/core/dbt/context/providers.py
+++ b/core/dbt/context/providers.py
@@ -38,6 +38,7 @@
 )
 from dbt.exceptions import (
     CompilationException,
+    ParsingException,
     InternalException,
     ValidationException,
     RuntimeException,
@@ -1388,11 +1389,24 @@ def generate_parse_exposure(
 
 class MetricRefResolver(BaseResolver):
     def __call__(self, *args) -> str:
-        if len(args) not in (1, 2):
+        package = None
+        if len(args) == 1:
+            name = args[0]
+        elif len(args) == 2:
+            package, name = args
+        else:
             ref_invalid_args(self.model, args)
+        self.validate_args(name, package)
         self.model.refs.append(list(args))
         return ''
 
+    def validate_args(self, name, package):
+        if not isinstance(name, str):
+            raise ParsingException(
+                f'In a metrics section in {self.model.original_file_path} '
+                f'the name argument to ref() must be a string'
+            )
+
 
 def generate_parse_metrics(
     metric: ParsedMetric,


Test patch:
diff --git a/test/integration/075_metrics_tests/invalid-models/people.sql b/test/integration/075_metrics_tests/invalid-models/people.sql
new file mode 100644
--- /dev/null
+++ b/test/integration/075_metrics_tests/invalid-models/people.sql
@@ -0,0 +1,3 @@
+select 1 as id, 'Drew' as first_name, 'Banin' as last_name, 'yellow' as favorite_color, true as loves_dbt, 5 as tenure, current_timestamp as created_at
+union all
+select 1 as id, 'Jeremy' as first_name, 'Cohen' as last_name, 'indigo' as favorite_color, true as loves_dbt, 4 as tenure, current_timestamp as created_at
diff --git a/test/integration/075_metrics_tests/invalid-models/people_metrics.yml b/test/integration/075_metrics_tests/invalid-models/people_metrics.yml
new file mode 100644
--- /dev/null
+++ b/test/integration/075_metrics_tests/invalid-models/people_metrics.yml
@@ -0,0 +1,30 @@
+version: 2
+
+metrics:
+
+  - model: "ref(people)"
+    name: number_of_people
+    description: Total count of people
+    label: "Number of people"
+    type: count
+    sql: "*"
+    timestamp: created_at
+    time_grains: [day, week, month]
+    dimensions:
+      - favorite_color
+      - loves_dbt
+    meta:
+        my_meta: 'testing'
+
+  - model: "ref(people)"
+    name: collective_tenure
+    description: Total number of years of team experience
+    label: "Collective tenure"
+    type: sum
+    sql: tenure
+    timestamp: created_at
+    time_grains: [day]
+    filters:
+      - field: loves_dbt
+        operator: is
+        value: 'true'
diff --git a/test/integration/075_metrics_tests/models/people.sql b/test/integration/075_metrics_tests/models/people.sql
new file mode 100644
--- /dev/null
+++ b/test/integration/075_metrics_tests/models/people.sql
@@ -0,0 +1,3 @@
+select 1 as id, 'Drew' as first_name, 'Banin' as last_name, 'yellow' as favorite_color, true as loves_dbt, 5 as tenure, current_timestamp as created_at
+union all
+select 1 as id, 'Jeremy' as first_name, 'Cohen' as last_name, 'indigo' as favorite_color, true as loves_dbt, 4 as tenure, current_timestamp as created_at
diff --git a/test/integration/075_metrics_tests/models/people_metrics.yml b/test/integration/075_metrics_tests/models/people_metrics.yml
new file mode 100644
--- /dev/null
+++ b/test/integration/075_metrics_tests/models/people_metrics.yml
@@ -0,0 +1,30 @@
+version: 2
+
+metrics:
+
+  - model: "ref('people')"
+    name: number_of_people
+    description: Total count of people
+    label: "Number of people"
+    type: count
+    sql: "*"
+    timestamp: created_at
+    time_grains: [day, week, month]
+    dimensions:
+      - favorite_color
+      - loves_dbt
+    meta:
+        my_meta: 'testing'
+
+  - model: "ref('people')"
+    name: collective_tenure
+    description: Total number of years of team experience
+    label: "Collective tenure"
+    type: sum
+    sql: tenure
+    timestamp: created_at
+    time_grains: [day]
+    filters:
+      - field: loves_dbt
+        operator: is
+        value: 'true'
diff --git a/test/integration/075_metrics_tests/test_metrics.py b/test/integration/075_metrics_tests/test_metrics.py
new file mode 100644
--- /dev/null
+++ b/test/integration/075_metrics_tests/test_metrics.py
@@ -0,0 +1,59 @@
+from test.integration.base import DBTIntegrationTest, use_profile, normalize, get_manifest
+from dbt.exceptions import ParsingException
+
+class BaseMetricTest(DBTIntegrationTest):
+
+    @property
+    def schema(self):
+        return "test_075"
+
+    @property
+    def models(self):
+        return "models"
+
+    @property
+    def project_config(self):
+        return {
+            'config-version': 2,
+            'seed-paths': ['seeds'],
+            'seeds': {
+                'quote_columns': False,
+            },
+        }
+
+    @use_profile('postgres')
+    def test_postgres_simple_metric(self):
+        # initial run
+        results = self.run_dbt(["run"])
+        self.assertEqual(len(results), 1)
+        manifest = get_manifest()
+        metric_ids = list(manifest.metrics.keys())
+        expected_metric_ids = ['metric.test.number_of_people', 'metric.test.collective_tenure']
+        self.assertEqual(metric_ids, expected_metric_ids)
+
+class InvalidRefMetricTest(DBTIntegrationTest):
+
+    @property
+    def schema(self):
+        return "test_075"
+
+    @property
+    def models(self):
+        return "invalid-models"
+
+    @property
+    def project_config(self):
+        return {
+            'config-version': 2,
+            'seed-paths': ['seeds'],
+            'seeds': {
+                'quote_columns': False,
+            },
+        }
+
+    @use_profile('postgres')
+    def test_postgres_simple_metric(self):
+        # initial run
+        with self.assertRaises(ParsingException):
+            results = self.run_dbt(["run"])
+