Repository: dbt-labs/dbt-core

Issue:
[CT-2696] Compilation error when rendering filter in metrics
### Is this a new bug in dbt-core?

- [X] I believe this is a new bug in dbt-core
- [X] I have searched the existing issues, and I could not find an existing issue for this bug

### Current Behavior

I have a metric with a filter defined: 
```
metrics:
  - name: "east_coast_order_amount"
    description: "Sum of orders from the east coast."
    type: simple
    label: "test"
    type_params:
      measures:
        - orders
    filter: |
      {{dimension('location_name')}} in ('Philadelphia')"
```

When I execute `dbt run` I get the following error:
```
Compilation Error
  Could not render {{dimension('location_name')}} in ('Philadelphia')
  : 'dimension' is undefined
```

This is likely due to the parser trying to render jinja when it encounters the double curlies, which it shouldn't be doing. If i escape the curlies dbt run succeeds. i.e 
```
metrics:
  - name: "east_coast_order_amount"
    description: "Sum of orders from the east coast."
    type: simple
    label: "test"
    type_params:
      measures:
        - orders
    filter: |
      \{\{dimension('location_name')\}\} in ('Philadelphia')"
```

### Expected Behavior

dbt should parse the filter correctly.

### Steps To Reproduce

Define a filter in a semantic model and run `dbt run`.

### Relevant log output

_No response_

### Environment

```markdown
- OS:
- Python:
- dbt:
```


### Which database adapter are you using with dbt?

_No response_

### Additional Context

_No response_


Discussion:
cc @QMalcolm 

Resolving patch:
diff --git a/core/dbt/parser/schema_renderer.py b/core/dbt/parser/schema_renderer.py
--- a/core/dbt/parser/schema_renderer.py
+++ b/core/dbt/parser/schema_renderer.py
@@ -67,8 +67,8 @@ def should_render_keypath(self, keypath: Keypath) -> bool:
             elif self._is_norender_key(keypath[0:]):
                 return False
         elif self.key == "metrics":
-            # back compat: "expression" is new name, "sql" is old name
-            if keypath[0] in ("expression", "sql"):
+            # This ensures all key paths that end in 'filter' for a metric are skipped
+            if keypath[-1] == "filter":
                 return False
             elif self._is_norender_key(keypath[0:]):
                 return False


Test patch:
diff --git a/tests/functional/duplicates/test_duplicate_metric.py b/tests/functional/duplicates/test_duplicate_metric.py
--- a/tests/functional/duplicates/test_duplicate_metric.py
+++ b/tests/functional/duplicates/test_duplicate_metric.py
@@ -25,7 +25,7 @@
     type_params:
       measure:
         name: "years_tenure"
-        filter: "loves_dbt is true"
+        filter: "{{dimension('loves_dbt')}} is true"
 """
 
 
diff --git a/tests/functional/metrics/fixtures.py b/tests/functional/metrics/fixtures.py
--- a/tests/functional/metrics/fixtures.py
+++ b/tests/functional/metrics/fixtures.py
@@ -43,7 +43,7 @@
     type_params:
       measure:
         name: "years_tenure"
-        filter: "loves_dbt is true"
+        filter: "{{dimension('loves_dbt')}} is true"
 
   - name: average_tenure
     label: "Average tenure"
@@ -86,7 +86,7 @@
     type_params:
       measure:
         name: years_tenure
-        filter: "loves_dbt is true"
+        filter: "{{dimension('loves_dbt')}} is true"
 
   - name: collective_window
     label: "Collective window"
@@ -95,7 +95,7 @@
     type_params:
       measure:
         name: years_tenure
-        filter: "loves_dbt is true"
+        filter: "{{dimension('loves_dbt')}} is true"
       window: 14 days
 
 """
@@ -377,7 +377,7 @@
     type_params:
       measure:
         name: years_tenure
-        filter: "loves_dbt is true"
+        filter: "{{dimension('loves_dbt')}} is true"
 
 """
 
@@ -404,7 +404,7 @@
     type_params:
       measure:
         name: years_tenure
-        filter: "loves_dbt is true"
+        filter: "{{dimension('loves_dbt')}} is true"
 
 """
 
diff --git a/tests/functional/partial_parsing/fixtures.py b/tests/functional/partial_parsing/fixtures.py
--- a/tests/functional/partial_parsing/fixtures.py
+++ b/tests/functional/partial_parsing/fixtures.py
@@ -353,7 +353,7 @@
     type_params:
       measure:
         name: customers
-        filter: "loves_dbt is true"
+        filter: "{{dimension('loves_dbt')}} is true"
     +meta:
         is_okr: True
     tags:
@@ -441,7 +441,7 @@
     type_params:
       measure:
         name: years_tenure
-        filter: "loves_dbt is true"
+        filter: "{{dimension('loves_dbt')}} is true"
 
 """
 
@@ -588,7 +588,7 @@
     type_params:
       measure:
         name: years_tenure
-        filter: "loves_dbt is true"
+        filter: "{{dimension('loves_dbt')}} is true"
 
 """
 
@@ -977,7 +977,7 @@
     type_params:
       measure:
         name: years_tenure
-        filter: "loves_dbt is true"
+        filter: "{{dimension('loves_dbt')}} is true"
 
 """
 
diff --git a/tests/unit/test_yaml_renderer.py b/tests/unit/test_yaml_renderer.py
--- a/tests/unit/test_yaml_renderer.py
+++ b/tests/unit/test_yaml_renderer.py
@@ -99,22 +99,20 @@ def test__macros(self):
         self.assertEqual(dct, expected)
 
     def test__metrics(self):
-        context = {"my_time_grains": "[day]"}
+        context = {"metric_name_end": "_metric"}
         renderer = SchemaYamlRenderer(context, "metrics")
 
         dct = {
-            "name": "my_source",
+            "name": "test{{ metric_name_end }}",
             "description": "{{ docs('my_doc') }}",
-            "expression": "select {{ var('my_var') }} from my_table",
-            "time_grains": "{{ my_time_grains }}",
+            "filter": "{{ dimension('my_dim') }} = false",
         }
         # We expect the expression and description will not be rendered, but
         # other fields will be
         expected = {
-            "name": "my_source",
+            "name": "test_metric",
             "description": "{{ docs('my_doc') }}",
-            "expression": "select {{ var('my_var') }} from my_table",
-            "time_grains": "[day]",
+            "filter": "{{ dimension('my_dim') }} = false",
         }
         dct = renderer.render_data(dct)
         self.assertEqual(dct, expected)