Summary
For Microsoft.Monitor/slis@2025-03-01-preview, the ConditionOperator enum declared in the OpenAPI specification does not match what the ARM control plane actually accepts. As a result, every wire value declared in the spec is rejected with MalformedStructureError, while several undocumented values (e.g. EQ, In, NotIn, NotContains, NotStartsWith) are silently accepted. Numeric comparison operators (<, <=, >, >=) appear to have no working alias at all.
This makes the dimension-filter feature unusable for any non-portal authoring path (Bicep, Terraform AzAPI, raw REST, generated SDKs).
Spec reference
- Repo:
Azure/azure-rest-api-specs
- File:
specification/monitoringservice/resource-manager/Microsoft.Monitor/Slis/preview/2025-03-01-preview/openapi.json
- Commit verified:
0fa038c6da5afc7cde4bf7429ca10d0465a3cacd
The ConditionOperator schema declares:
"enum": ["==", "!=", "<", "<=", ">", ">=",
"@in", "!in",
"startswith", "!startswith",
"contains", "!contains"],
"x-ms-enum": {
"name": "ConditionOperator",
"modelAsString": true,
"values": [
{"name": "Equal", "value": "=="},
{"name": "NotEqual", "value": "!="},
{"name": "LessThan", "value": "<"},
{"name": "LessThanOrEqual", "value": "<="},
{"name": "GreaterThan", "value": ">"},
{"name": "GreaterThanOrEqual", "value": ">="},
{"name": "In", "value": "@in"},
{"name": "NotIn", "value": "!in"},
{"name": "StartsWith", "value": "startswith"},
{"name": "NotStartsWith", "value": "!startswith"},
{"name": "Contains", "value": "contains"},
{"name": "NotContains", "value": "!contains"}
]
}
These are also the values reflected in the auto-generated Bicep/ARM template reference and the generated Azure.ResourceManager.Monitor.Slis .NET SDK.
Reproduction
Region: japaneast. Identical resource template, only the operator value changes:
Observed behavior
Every value below was tested with az rest PUT against the same SLI ARM URI in the same subscription. MalformedStructureError is the response when ARM rejects the body before reaching the service.
| Operator value tried |
Source |
Result |
== |
spec wire value |
❌ MalformedStructureError |
!= |
spec wire value |
❌ MalformedStructureError |
< |
spec wire value |
❌ MalformedStructureError |
<= |
spec wire value |
❌ MalformedStructureError |
> |
spec wire value |
❌ MalformedStructureError |
>= |
spec wire value |
❌ MalformedStructureError |
@in |
spec wire value |
❌ MalformedStructureError |
!in |
spec wire value |
❌ MalformedStructureError |
!startswith |
spec wire value |
❌ MalformedStructureError |
!contains |
spec wire value |
❌ MalformedStructureError |
Equal |
x-ms-enum SDK name |
❌ MalformedStructureError |
LessThanOrEqual |
x-ms-enum SDK name |
❌ MalformedStructureError |
GreaterThan |
x-ms-enum SDK name |
❌ MalformedStructureError |
LT, LE, GT, GTE |
guessed |
❌ MalformedStructureError |
LessThan, LessThanOrEqualTo, Less, LessOrEqual |
guessed |
❌ MalformedStructureError |
EQ |
undocumented |
✅ accepted |
Eq |
undocumented |
✅ accepted |
In |
undocumented |
✅ accepted |
NotIn |
undocumented |
✅ accepted |
NotContains |
undocumented |
✅ accepted |
NotStartsWith |
undocumented |
✅ accepted |
contains (lowercase) |
matches spec wire value but not casing |
✅ accepted |
startswith (lowercase) |
matches spec wire value but not casing |
✅ accepted |
Two distinct problems:
- Spec/implementation mismatch. None of the spec-declared wire values work; instead an undocumented PascalCase set works. Generated clients and IaC users cannot reach this set.
- Numeric comparison operators have no working alias. No naming variant (
<=, LE, LessThanOrEqual, LessOrEqual, …) is accepted, so dimension filters such as le <= 1 (Prometheus histogram bucket selection) are simply not expressible through this API today.
Impact
For our scenario (a histogram le bucket SLI on Microsoft.Monitor/accounts Prometheus metrics), this means we cannot write dimensionName=le, operator=LessThanOrEqual, values=["1"]. We had to abandon the histogram pattern and emit N separate metric names (metric_le_0p1, metric_le_0p5, …) to encode the bucket boundary in the metric name instead of as a label. This is non-idiomatic versus Prometheus convention, multiplies metric cardinality, and only became necessary because the documented operator surface does not work.
A ==-equivalent for histograms also does not help our case in particular, but it would solve the general case for users who want to filter Prometheus-style le="1" buckets, if the working EQ/Eq value were documented.
Public documentation gap
For non-portal authoring (Bicep / Terraform AzAPI / REST / generated SDKs), the OpenAPI spec is effectively the only source of truth for the signalSources[].filters[] schema. The Azure Monitor SLI conceptual / how-to documentation (Create service level indicators in Azure Monitor (preview)) mentions filters only abstractly:
Add filters such as a status code or dimension value to limit the values used for the calculation. … filter the good signal to count only requests with a 200 status code…
It does not document the operator enum, the wire values, or the dimensionName/value schema. Combined with the spec/implementation mismatch above, there is currently no public source from which an SDK or IaC user can derive a correct operator string, even though the service does accept undocumented values like EQ, In, NotIn, NotContains, and NotStartsWith.
Sibling Azure Monitor APIs do not have this issue
Dimension-filter operator enums in adjacent Azure Monitor APIs (verified against the same azure-rest-api-specs commit):
| API |
Type |
Operator enum |
Status |
Microsoft.Insights/metricAlerts (MetricDimension) |
metric alert |
free string; Include / Exclude by convention |
works |
Microsoft.Insights/autoscalesettings (ScaleRuleMetricDimension) |
autoscale |
Equals, NotEquals |
works |
Microsoft.Insights/scheduledQueryRules (Dimension) |
log alert |
Include, Exclude |
works |
Microsoft.Monitor/slis (Condition) |
SLI |
12 values incl. ==, <=, @in, !contains |
spec/impl mismatch |
The SLI service is the only one in this family that declared a richer operator set than its peers, and is also the only one whose declared values do not match the implementation.
PromQL convention check
The destination metrics live in an Azure Monitor Workspace and are queried via PromQL. Note that PromQL itself does not have a <= label matcher — only =, !=, =~, !~. Histogram bucket selection in Prometheus is done by string equality on the le label (e.g. le="1" for the cumulative count of samples with duration ≤ 1s). So the rich numeric-comparison surface declared in the SLI spec is not actually required to express the canonical histogram pattern; an EQ-equivalent would suffice — provided one of the spec values worked, or the working value (EQ) were documented.
Expected behavior
Either:
- Fix the implementation to accept the spec-declared wire values (
==, <=, @in, etc.), so SDKs and IaC users can rely on the documented contract; or
- Fix the spec to declare the values that ARM actually accepts (
EQ, In, NotIn, NotContains, NotStartsWith, contains, startswith, …) and document precisely which dimension types each operator supports. If numeric comparison is not implemented, drop those values from the spec (and align with the simpler Include/Exclude style used by sibling Azure Monitor APIs).
In either case, please add an authoritative reference for the signalSources[].filters[] DSL — operator names, semantics, supported dimensionName / value shapes — to the Service level indicators conceptual docs so that non-portal users have something to read.
Environment
- API version:
2025-03-01-preview
- Region:
japaneast
- ARM endpoint:
management.azure.com
- Tested via:
az rest --method PUT and Bicep deployment, both reproduce identically.
- Tested: 2026-05-21
Summary
For
Microsoft.Monitor/slis@2025-03-01-preview, theConditionOperatorenum declared in the OpenAPI specification does not match what the ARM control plane actually accepts. As a result, every wire value declared in the spec is rejected withMalformedStructureError, while several undocumented values (e.g.EQ,In,NotIn,NotContains,NotStartsWith) are silently accepted. Numeric comparison operators (<,<=,>,>=) appear to have no working alias at all.This makes the dimension-filter feature unusable for any non-portal authoring path (Bicep, Terraform AzAPI, raw REST, generated SDKs).
Spec reference
Azure/azure-rest-api-specsspecification/monitoringservice/resource-manager/Microsoft.Monitor/Slis/preview/2025-03-01-preview/openapi.json0fa038c6da5afc7cde4bf7429ca10d0465a3cacdThe
ConditionOperatorschema declares:These are also the values reflected in the auto-generated Bicep/ARM template reference and the generated
Azure.ResourceManager.Monitor.Slis.NET SDK.Reproduction
Region:
japaneast. Identical resource template, only theoperatorvalue changes:{ "properties": { "displayName": "operator-probe", "sliProperties": { "evaluationMethod": "RequestBased", "destinationMetrics": { "azureMonitorWorkspaceResourceId": "<AMW resource id>" }, "compliancePeriodWindow": "P30D", "compliancePeriodAggregation": "Average", "spatialAggregation": "Average", "compliancePeriodWindowAggregation": "PT5M", "type": "Availability", "ratioBasedSli": { "goodSignals": [{ "signalSources": [{ "azureMonitorWorkspaceResourceId": "<AMW resource id>", "metricName": "<metric>", "temporalAggregation": "Total", "filters": [{ "dimensionName": "<dim>", "operator": "<value under test>", "values": ["x"] }] }], "formula": "S0" }], "totalSignals": [/* same shape, no filters */] } } } }Observed behavior
Every value below was tested with
az restPUT against the same SLI ARM URI in the same subscription.MalformedStructureErroris the response when ARM rejects the body before reaching the service.==MalformedStructureError!=MalformedStructureError<MalformedStructureError<=MalformedStructureError>MalformedStructureError>=MalformedStructureError@inMalformedStructureError!inMalformedStructureError!startswithMalformedStructureError!containsMalformedStructureErrorEqualMalformedStructureErrorLessThanOrEqualMalformedStructureErrorGreaterThanMalformedStructureErrorLT,LE,GT,GTEMalformedStructureErrorLessThan,LessThanOrEqualTo,Less,LessOrEqualMalformedStructureErrorEQEqInNotInNotContainsNotStartsWithcontains(lowercase)startswith(lowercase)Two distinct problems:
<=,LE,LessThanOrEqual,LessOrEqual, …) is accepted, so dimension filters such asle <= 1(Prometheus histogram bucket selection) are simply not expressible through this API today.Impact
For our scenario (a histogram
lebucket SLI onMicrosoft.Monitor/accountsPrometheus metrics), this means we cannot writedimensionName=le, operator=LessThanOrEqual, values=["1"]. We had to abandon the histogram pattern and emit N separate metric names (metric_le_0p1,metric_le_0p5, …) to encode the bucket boundary in the metric name instead of as a label. This is non-idiomatic versus Prometheus convention, multiplies metric cardinality, and only became necessary because the documented operator surface does not work.A
==-equivalent for histograms also does not help our case in particular, but it would solve the general case for users who want to filter Prometheus-stylele="1"buckets, if the workingEQ/Eqvalue were documented.Public documentation gap
For non-portal authoring (Bicep / Terraform AzAPI / REST / generated SDKs), the OpenAPI spec is effectively the only source of truth for the
signalSources[].filters[]schema. The Azure Monitor SLI conceptual / how-to documentation (Create service level indicators in Azure Monitor (preview)) mentions filters only abstractly:It does not document the
operatorenum, the wire values, or thedimensionName/valueschema. Combined with the spec/implementation mismatch above, there is currently no public source from which an SDK or IaC user can derive a correct operator string, even though the service does accept undocumented values likeEQ,In,NotIn,NotContains, andNotStartsWith.Sibling Azure Monitor APIs do not have this issue
Dimension-filter operator enums in adjacent Azure Monitor APIs (verified against the same
azure-rest-api-specscommit):Microsoft.Insights/metricAlerts(MetricDimension)Include/Excludeby conventionMicrosoft.Insights/autoscalesettings(ScaleRuleMetricDimension)Equals,NotEqualsMicrosoft.Insights/scheduledQueryRules(Dimension)Include,ExcludeMicrosoft.Monitor/slis(Condition)==,<=,@in,!containsThe SLI service is the only one in this family that declared a richer operator set than its peers, and is also the only one whose declared values do not match the implementation.
PromQL convention check
The destination metrics live in an Azure Monitor Workspace and are queried via PromQL. Note that PromQL itself does not have a
<=label matcher — only=,!=,=~,!~. Histogram bucket selection in Prometheus is done by string equality on thelelabel (e.g.le="1"for the cumulative count of samples with duration ≤ 1s). So the rich numeric-comparison surface declared in the SLI spec is not actually required to express the canonical histogram pattern; anEQ-equivalent would suffice — provided one of the spec values worked, or the working value (EQ) were documented.Expected behavior
Either:
==,<=,@in, etc.), so SDKs and IaC users can rely on the documented contract; orEQ,In,NotIn,NotContains,NotStartsWith,contains,startswith, …) and document precisely which dimension types each operator supports. If numeric comparison is not implemented, drop those values from the spec (and align with the simplerInclude/Excludestyle used by sibling Azure Monitor APIs).In either case, please add an authoritative reference for the
signalSources[].filters[]DSL — operator names, semantics, supporteddimensionName/valueshapes — to the Service level indicators conceptual docs so that non-portal users have something to read.Environment
2025-03-01-previewjapaneastmanagement.azure.comaz rest --method PUTand Bicep deployment, both reproduce identically.