Repository: Azure/azure-cli-extensions

Issue:
Scheduled-query create example throws BadRequest error
I tried playing around the scheduled-query cli commands and kept running into issues parsing the LogAnalytics query we were attempting to use in the condition. So, I simply tried using the condition provided in the examples and it had similar issues.

```
C:\Users\XXXXX>az monitor scheduled-query create -g <RG> -n Another-Alert --scopes <RESOUCE ID> --description "This is a description" --condition "count 'union Event, Syslog | where TimeGenerated > ago(1h) | where EventLevelName=="Error" or SeverityLevel=="err"' > 360 resource id _ResourceID at least 1 violations out of 5 aggregated points"
BadRequest: {
  "error": {
    "message": "The request had some invalid properties",
    "code": "BadArgumentError",
    "correlationId": "fb91e6e3-85e8-4a34-a2c3-c5c76468f26a",
    "innererror": {
      "code": "SemanticError",
      "message": "A semantic error occurred.",
      "innererror": {
        "code": "SEM0100",
        "message": "'where' operator: Failed to resolve column or scalar expression named 'Error'"
      }
    }
  }
```

Any help or guidance would be greatly appreciated...

---
#### Document Details

⚠ *Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking.*

* ID: 445d2458-1e27-7cf4-8a04-95ec798ebdc1
* Version Independent ID: 3f80ed4a-d3c4-d15c-3e5d-50a48e0eb72c
* Content: [az monitor scheduled-query](https://docs.microsoft.com/en-us/cli/azure/ext/scheduled-query/monitor/scheduled-query?view=azure-cli-latest)
* Content Source: [latest/docs-ref-autogen/ext/scheduled-query/monitor/scheduled-query.yml](https://github.com/MicrosoftDocs/azure-docs-cli/blob/master/latest/docs-ref-autogen/ext/scheduled-query/monitor/scheduled-query.yml)
* GitHub Login: @rloutlaw
* Microsoft Alias: **routlaw**


Discussion:

Resolving patch:
diff --git a/src/scheduled-query/azext_scheduled_query/_help.py b/src/scheduled-query/azext_scheduled_query/_help.py
--- a/src/scheduled-query/azext_scheduled_query/_help.py
+++ b/src/scheduled-query/azext_scheduled_query/_help.py
@@ -35,9 +35,9 @@
         Dimensions can be queried by adding the 'where' keyword and multiple dimensions can be queried by combining them with the 'and' keyword.
 examples:
   - name: Create a scheduled query for a VM.
-    text: az monitor scheduled-query create -g {rg} -n {name1} --scopes {vm_id} --condition "count 'union Event, Syslog | where TimeGenerated > ago(1h) | where EventLevelName==\"Error\" or SeverityLevel==\"err\"' > 360 resource id _ResourceID at least 1 violations out of 5 aggregated points" --description "Test rule"
+    text: az monitor scheduled-query create -g {rg} -n {name1} --scopes {vm_id} --condition "count 'union Event, Syslog | where TimeGenerated > ago(1h) | where EventLevelName==\\'Error\\' or SeverityLevel==\\'err\\'' > 360 resource id _ResourceID at least 1 violations out of 5 aggregated points" --description "Test rule"
   - name: Create a scheduled query for VMs in a resource group.
-    text: az monitor scheduled-query create -g {rg} -n {name1} --scopes {rg_id} --condition "count 'union Event, Syslog | where TimeGenerated > ago(1h) | where EventLevelName==\"Error\" or SeverityLevel==\"err\"' > 360 resource id _ResourceID at least 1 violations out of 5 aggregated points" --description "Test rule"
+    text: az monitor scheduled-query create -g {rg} -n {name1} --scopes {rg_id} --condition "count 'union Event, Syslog | where TimeGenerated > ago(1h) | where EventLevelName==\\'Error\\' or SeverityLevel==\\'err\\'' > 360 resource id _ResourceID at least 1 violations out of 5 aggregated points" --description "Test rule"
 """
 
 helps['monitor scheduled-query update'] = """
diff --git a/src/scheduled-query/azext_scheduled_query/grammar/scheduled_query/ScheduleQueryConditionValidator.py b/src/scheduled-query/azext_scheduled_query/grammar/scheduled_query/ScheduleQueryConditionValidator.py
--- a/src/scheduled-query/azext_scheduled_query/grammar/scheduled_query/ScheduleQueryConditionValidator.py
+++ b/src/scheduled-query/azext_scheduled_query/grammar/scheduled_query/ScheduleQueryConditionValidator.py
@@ -57,7 +57,10 @@ def exitThreshold(self, ctx):
 
     # Exit a parse tree produced by MetricAlertConditionParser#threshold.
     def exitQuery(self, ctx):
-        self.parameters['query'] = ctx.getText().strip()
+        query = ctx.getText().strip()
+        query = query.replace("\\\"", "\"")
+        query = query.replace("\\\'", "\'")
+        self.parameters['query'] = query
 
     # Exit a parse tree produced by MetricAlertConditionParser#threshold.
     def exitResource_id(self, ctx):
diff --git a/src/scheduled-query/setup.py b/src/scheduled-query/setup.py
--- a/src/scheduled-query/setup.py
+++ b/src/scheduled-query/setup.py
@@ -16,7 +16,7 @@
 
 # TODO: Confirm this is the right version number you want and it matches your
 # HISTORY.rst entry.
-VERSION = '0.2.1'
+VERSION = '0.2.2'
 
 # The full list of classifiers is available at
 # https://pypi.python.org/pypi?%3Aaction=list_classifiers


Test patch:
diff --git a/src/scheduled-query/azext_scheduled_query/tests/latest/test_scheduled_query_scenario.py b/src/scheduled-query/azext_scheduled_query/tests/latest/test_scheduled_query_scenario.py
--- a/src/scheduled-query/azext_scheduled_query/tests/latest/test_scheduled_query_scenario.py
+++ b/src/scheduled-query/azext_scheduled_query/tests/latest/test_scheduled_query_scenario.py
@@ -125,19 +125,19 @@ def test_monitor_scheduled_query_condition_action(self):
 
         ns = self._build_namespace()
         self.call_condition(ns, 'avg "% Processor Time" from "Perf | where ObjectName == \\\"Processor\\\"" > 70 resource id resourceId')
-        self.check_condition(ns, 'Average', 'Perf | where ObjectName == \\\"Processor\\\"', 'GreaterThan', '70', '% Processor Time', 'resourceId')
+        self.check_condition(ns, 'Average', 'Perf | where ObjectName == \"Processor\"', 'GreaterThan', '70', '% Processor Time', 'resourceId')
 
         ns = self._build_namespace()
         self.call_condition(ns, 'count "diagnostics | where Category == \\\"A\\\"| where SubscriptionId contains \\\"111\\\" | summarize count() by bin(TimeGenerated, 1m)" > 1')
-        self.check_condition(ns, 'Count', 'diagnostics | where Category == \\\"A\\\"| where SubscriptionId contains \\\"111\\\" | summarize count() by bin(TimeGenerated, 1m)', 'GreaterThan', '1')
+        self.check_condition(ns, 'Count', 'diagnostics | where Category == \"A\"| where SubscriptionId contains \"111\" | summarize count() by bin(TimeGenerated, 1m)', 'GreaterThan', '1')
 
         ns = self._build_namespace()
         self.call_condition(ns, 'count "diagnostics | where Time > ago(3h) | where Category == \\\"manager\\\" | where not (log_s hasprefix \\\"I11\\\") | where log_s contains \\\"Code=1\\\" | summarize count(log_s) by bin(TimeGenerated, 1m)" > 10')
-        self.check_condition(ns, 'Count', 'diagnostics | where Time > ago(3h) | where Category == \\\"manager\\\" | where not (log_s hasprefix \\\"I11\\\") | where log_s contains \\\"Code=1\\\" | summarize count(log_s) by bin(TimeGenerated, 1m)', 'GreaterThan', '10')
+        self.check_condition(ns, 'Count', 'diagnostics | where Time > ago(3h) | where Category == \"manager\" | where not (log_s hasprefix \"I11\") | where log_s contains \"Code=1\" | summarize count(log_s) by bin(TimeGenerated, 1m)', 'GreaterThan', '10')
 
         ns = self._build_namespace()
         self.call_condition(ns, 'avg "% Processor Time" from "Perf | where ObjectName == \\\"Processor\\\" and C>=D && E<<F" > 70 resource id resourceId where ApiName includes GetBlob or PutBlob and DpiName excludes CCC at least 1.1 violations out of 10.1 aggregated points')
-        self.check_condition(ns, 'Average', 'Perf | where ObjectName == \\\"Processor\\\" and C>=D && E<<F', 'GreaterThan', '70', '% Processor Time', 'resourceId')
+        self.check_condition(ns, 'Average', 'Perf | where ObjectName == \"Processor\" and C>=D && E<<F', 'GreaterThan', '70', '% Processor Time', 'resourceId')
         self.check_dimension(ns, 0, 'ApiName', 'Include', ['GetBlob', 'PutBlob'])
         self.check_dimension(ns, 1, 'DpiName', 'Exclude', ['CCC'])
         self.check_falling_period(ns, 1, 10)