PromQL UTF-8 Syntax Guide

SigNoz Cloud - This page applies to SigNoz Cloud editions.
Self-Host - This page applies to self-hosted SigNoz editions.
PromQL Query editor in SigNoz Dashboards
PromQL Query editor in SigNoz Dashboards

What Changed and Why

SigNoz now supports UTF-8 characters in Prometheus metric and label names. This is needed for OpenTelemetry compatibility, since OpenTelemetry uses dots (.) in metric names (e.g., container.cpu.utilization) while traditional Prometheus only allowed letters, numbers, and underscores.

To support these characters, PromQL queries in SigNoz use a new quoted syntax. All pre-existing queries continue to work — this change is backward compatible.

New Syntax Rules

  1. Metric names with special characters (like dots) must be quoted with double quotes and placed inside curly braces as the first parameter
  2. Label names with special characters also need double quotes
  3. Traditional metric names (letters, numbers, underscores only) continue to work without quotes
  4. All pre-existing queries continue to work unchanged
# New syntax for metrics with dots
{"my.noncompliant.metric", "noncompliant.label"="value"}

Regex Label Matchers Are Fully Anchored

The regex matchers =~ and !~ are fully anchored, following standard Prometheus semantics. The pattern is wrapped and anchored as ^(?:...)$, so =~"foo" is evaluated as =~"^(?:foo)$" and must match the entire label value, not just a substring.

To perform a substring match, wrap the pattern with .* on both sides:

# Matches only label values that are exactly "Docman"
{"service.name"=~"Docman"}

# Matches any label value containing "Docman" (substring match)
{"service.name"=~".*Docman.*"}

This applies to alternation patterns as well. For example, env=~"prod|stag" matches values that are exactly prod or stag, not values that merely contain those strings.

Migration Examples

Container CPU Utilization

# Old format
sum(rate(container_cpu_utilization{k8s_namespace_name="ns"}[5m])) by (k8s_pod_name)

# New format
sum by ("k8s.pod.name") (rate({"container.cpu.utilization","k8s.namespace.name"="ns"}[5m]))

Histogram Quantile

# Old format
histogram_quantile(0.95, sum(rate(request_duration_bucket{job="api"}[5m])) by (le))

# New format
histogram_quantile(0.95, sum by (le) (rate({"request.duration.bucket",job="api"}[5m])))

Complex Query with Functions

# Old format
max_over_time(foo_bar_total{env=~"prod|stag"}[1h] offset 30m) / ignoring(instance) group_left sum(rate(other_metric[5m])) without (pod)

# New format
max_over_time({"foo.bar.total",env=~"prod|stag"}[1h] offset 30m) / ignoring ("instance") group_left () sum without ("pod") (rate({"other.metric"}[5m]))

Metrics Without Dots in the Name

For metrics and attributes that don't contain dots, both old and new formats work. We recommend using the new format for consistency.

# Old format
sum by (foo_attr) (
  rate(foo_bar_total{env=~"prod|stage"}[1h] offset 30m)
)

# New format
sum by ("foo_attr") (
    rate({"foo_bar_total", env =~"prod|stage"}[1h] offset 30m)
)

By Metric Type

Counter

# Old format
rate(http_requests_total{job="api",status!~"5.."}[5m])

# New format
rate({"http_requests_total", job="api", status!~"5.."})[5m])

Gauge

# Old format
avg_over_time(kube_pod_container_resource_requests_cpu_cores{namespace="prod"}[10m])

# New format
avg_over_time({"kube_pod_container_resource_requests_cpu_cores",namespace="prod"}[10m])

Histogram

# Old format
histogram_quantile(0.95, sum(rate(http_request_duration_seconds_bucket{job="api"}[5m])) by (le))

# New format
histogram_quantile(0.95, sum by (le) (rate({"http_request_duration_seconds.bucket",job="api"}[5m])))

Summary

# Old format
sum(rate(http_request_duration_seconds_sum[5m])) / sum(rate(http_request_duration_seconds_count[5m]))

# New format
sum(rate({"http_request_duration_seconds.sum"}[5m])) / sum(rate({"http_request_duration_seconds.count"}[5m]))

For Histogram metrics, the new format uses .min, .max, .count, .bucket, .sum suffixes instead of the previous _ suffixes. Same for Summary metrics: .count, .quantile, .sum suffixes.

Migration

Cloud Users

Your existing queries have already been migrated automatically — no action is required. Dashboards and alerts continue working as before.

Self-Hosted Users

  • Migration scripts are provided to convert existing PromQL queries in your dashboards and alerts automatically
  • The new syntax is introduced incrementally to minimize disruption
  • See the migration docs linked below for step-by-step instructions

Backward Compatibility

The new syntax is fully backward compatible:

  • Existing queries with traditional metric names (no dots or special characters) continue to work unchanged
  • Migration is non-breaking for existing workflows
  • Migration scripts are available for dashboards and alerts that will now contain previously-invalid characters post migration

Last updated: July 24, 2026

Edit on GitHub

Was this page helpful?

Your response helps us improve this page.