Prometheus Query Language
GreptimeDB implements PromQL in Rust and exposes it through the Prometheus HTTP API, the GreptimeDB HTTP API, and SQL. Grafana can connect through its Prometheus data source. See Limitations for supported features and known differences.
Prometheus' HTTP API
GreptimeDB has implemented a set of Prometheus compatible APIs under HTTP
context /v1/prometheus/:
- Instant queries
/api/v1/query - Range queries
/api/v1/query_range - Series
/api/v1/series - Label names
/api/v1/labels - Label values
/api/v1/label/<label_name>/values
These endpoints use Prometheus HTTP API request and response formats. In Grafana,
set the Prometheus data source URL to http://localhost:4000/v1/prometheus/.
Consult Prometheus documents for usage of these API.
You can use additional query parameter db to specify GreptimeDB database name.
For example, the following query will return the CPU usage of the process_cpu_seconds_total metric in the public database:
curl -X POST \
-H 'Authorization: Basic <base64-encoded-credentials>' \
--data-urlencode 'query=irate(process_cpu_seconds_total[1h])' \
--data-urlencode 'start=2024-11-24T00:00:00Z' \
--data-urlencode 'end=2024-11-25T00:00:00Z' \
--data-urlencode 'step=1h' \
'http://localhost:4000/v1/prometheus/api/v1/query_range?db=public'
If authentication is enabled in GreptimeDB, the authentication header is required. Refer to the authentication documentation for more details.
You need to either set it in the HTTP URL query param db like the example above, or set it using --header 'x-greptime-db-name: <database name>' as HTTP header.
The query string parameters for the API are identical to those of the original Prometheus API, with the exception of the additional db parameter, which specifies the GreptimeDB database name.
The output format is compatible with the Prometheus API:
{
"status": "success",
"data": {
"resultType": "matrix",
"result": [
{
"metric": {
"job": "node",
"instance": "node_exporter:9100",
"__name__": "process_cpu_seconds_total"
},
"values": [
[
1732618800,
"0.0022222222222222734"
],
[
1732622400,
"0.0009999999999999788"
],
[
1732626000,
"0.0029999999999997585"
],
[
1732629600,
"0.002222222222222175"
]
]
}
]
}
}
SQL
GreptimeDB also extends SQL grammar to support PromQL. You can start with the TQL (Time-series Query Language) keyword to write parameters and queries. The grammar looks like this:
TQL [EVAL|EVALUATE] (<START>, <END>, <STEP>) <QUERY>
<START> specifies the query start range and <END> specifies the end time. <STEP> identifies the query resolution step width. All of them can either be an unquoted number (represent UNIX timestamp for <START> and <END>, and duration in seconds for <STEP>), or a quoted string (represent an RFC3339 timestamp for <START> and <END>, and duration in string format for <STEP>).
For example:
TQL EVAL (1676738180, 1676738780, '10s') sum(some_metric)
You can write the above command in all places that support SQL, including the GreptimeDB HTTP API, SDK, PostgreSQL and MySQL client etc.
GreptimeDB's extensions to PromQL
Specifying value field
Based on the table model, GreptimeDB supports multiple fields in a single table(or metric, in the context of Prometheus). Queries will run on every fields by default. Or you can use the special filter __field__ to query a specific field(s):
metric{__field__="field1"}
Exclude or regex are also supported:
metric{__field__!="field1"}
metric{__field__=~"field_1|field_2"}
metric{__field__!~"field_1|field_2"}
Cross-database query
Greptime has its own database concept. In order to run cross-database query, you
can use __database__ matcher to specify the database name.
metric{__database__="mydatabase"}
Note that only = is supported for database matcher.
Limitations
PromQL queries support float samples and native histogram samples. Float metrics use a timestamp column, string labels, and Double values. Native histogram support and ingestion requirements are described in Native histograms.
v1.3.0 compatibility test results
The v1.3.0 release measurements use promql-compat revision 1203cd8 with Prometheus v3.15.0 as the reference. The target is GreptimeDB v1.3.0.
| Test suite | Cases counted | Cases excluded | Including __name__ | Ignoring only __name__ |
|---|---|---|---|---|
| Prometheus test corpus | 852 | 1391 | 53.52% (456/852) | 88.50% (754/852) |
| Prometheus compliance queries | 539 | 0 | 54.17% (292/539) | 94.81% (511/539) |
| Generated queries (seed 1) | 1999 | 1 | 63.83% (1276/1999) | 93.35% (1866/1999) |
Percentages are test-case pass rates, with excluded cases omitted from the denominators; the last column ignores differences only in __name__. See the promql-compat methodology.
Known differences in v1.3.0
| Query behavior | Example | Difference from Prometheus |
|---|---|---|
| Metric-name labels in function and aggregation results | rate(x[1m]), abs(x), sum(rate(x[1m])), sum(x > 0) | Functions retain __name__, and aggregations without grouping can retain it from their inputs, affecting Grafana legends and alert/recording-rule labels. In v1.3, filtering comparisons without bool can also restore a removed metric name. |
| Date functions with an argument | year(vector(1136239445)) | Uses the sample timestamp instead of the sample value. Affects year, month, day_of_month, day_of_week, day_of_year, days_in_month, hour, and minute. |
| Selectors without a metric name | {job="demo"} | Returns Expect a metric matcher, but not found. A metric name or an explicit __name__ matcher is required. |
vector(time()) | vector(time()) | Fails with Invalid function argument for unknown in both instant and range queries, including when used alone. |
absent_over_time | absent_over_time(nonexistent_metric[5m]) | Some queries return different series than Prometheus: expected series can be missing, or extra series can appear. This example returns no series; Prometheus returns a series with value 1. |
| Dynamic scalar parameters | topk(scalar(foo), x), quantile_over_time(scalar(foo), x[5m]) | Some uses of scalar() as a parameter fail planning. |
first_over_time | first_over_time(x[5m]) | Returns Unsupported expr type; the function is not implemented. |
| Validation differences | scalar_metric > on() dup_metric, clamp(x, 10, 1) | Duplicate label sets and duplicate matches can return results where Prometheus raises an error; reversed clamp bounds return an error where Prometheus returns an empty result; label_replace rejects UTF-8 destination labels accepted by Prometheus 3. |
Literal
Both string and float literals are supported, with the same rule as PromQL.
Selector
Instant and range selectors require a metric name or an explicit __name__ matcher. A selector with only ordinary labels, such as {job="demo"}, returns an error. Metric-name matching has the following restrictions:
- In
TQL, only equal-matching is supported, for example{__name__="request_count"}. - The Prometheus HTTP API also supports regex-matching and negative matching, for example
{__name__=~"request_.*"}or{__name__!="request_count", host="h1"}. These matchers only match tables created by the metric engine, such as tables written through Prometheus Remote Write.
Time duration, offset, and @ modifier (including @ start() and @ end()) are supported.
Subqueries support an explicit step; an omitted step defaults to one minute, independently of the outer query step. Use [range:step] for another interval. Instant queries can return range vectors; range queries reject a range-vector root expression.
When selecting non-existent columns, they will be treated as columns filled with empty string values (""). This behavior aligns with both Prometheus and VictoriaMetrics.
Timestamp precision
PromQL evaluation times and steps use millisecond precision. Sample selection preserves stored microsecond or nanosecond timestamps; timestamp() converts the selected sample timestamp to milliseconds, then returns floating-point seconds.
Binary
- Supported:
Operator +-*/%==!=><>=<=^atan2 and or unless
Vector matching supports on, ignoring, group_left, and group_right. Some duplicate matches and duplicate label sets are not rejected; see Known differences in v1.3.0 for examples.
Aggregators
- Supported:
Aggregator Example group group by (foo)(metric)sum sum by (foo)(metric)avg avg by (foo)(metric)min min by (foo)(metric)max max by (foo)(metric)stddev stddev by (foo)(metric)stdvar stdvar by (foo)(metric)topk topk(3, rate(instance_cpu_time_ns[5m]))bottomk bottomk(3, rate(instance_cpu_time_ns[5m]))count_values count_values("version", build_version)count count (metric)quantile quantile(0.9, cpu_usage)
Instant Functions
The following functions are implemented; behavior differences and argument limits are listed under Known differences in v1.3.0. histogram_count, histogram_sum, histogram_avg, histogram_stddev, and histogram_stdvar operate on native histogram samples.
- Supported:
Function Example round round(metric)vector vector(1)time time()year year()month month()day_of_month day_of_month()day_of_week day_of_week()day_of_year day_of_year()days_in_month days_in_month()hour hour()minute minute()abs abs(metric)ceil ceil(metric)exp exp(metric)ln ln(metric)log2 log2(metric)log10 log10(metric)sqrt sqrt(metric)acos acos(metric)asin asin(metric)atan atan(metric)sin sin(metric)cos cos(metric)tan tan(metric)acosh acosh(metric)asinh asinh(metric)atanh atanh(metric)sinh sinh(metric)cosh cosh(metric)scalar scalar(metric)tanh tanh(metric)timestamp timestamp(metric)sort sort(http_requests_total)sort_desc sort_desc(http_requests_total)histogram_fraction histogram_fraction(0, 1, request_duration)histogram_count histogram_count(request_duration)histogram_sum histogram_sum(request_duration)histogram_avg histogram_avg(request_duration)histogram_stddev histogram_stddev(request_duration)histogram_stdvar histogram_stdvar(request_duration)histogram_quantile histogram_quantile(phi, metric)predict_linear predict_linear(metric[5m], 120)absent absent(nonexistent{job="myjob"})sgn sgn(metric)pi pi()deg deg(metric)rad rad(metric)floor floor(metric)clamp clamp(metric, 0, 12)clamp_max clamp_max(metric, 12)clamp_min clamp_min(metric, 0)
Range Functions
See Known differences in v1.3.0 for absent_over_time behavior and the unimplemented first_over_time.
- Supported:
Function Example idelta idelta(metric[5m])avg_over_time avg_over_time(metric[5m])min_over_time min_over_time(metric[5m])max_over_time max_over_time(metric[5m])sum_over_time sum_over_time(metric[5m])count_over_time count_over_time(metric[5m])last_over_time last_over_time(metric[5m])present_over_time present_over_time(metric[5m])quantile_over_time quantile_over_time(0.9, metric[5m])stddev_over_time stddev_over_time(metric[5m])stdvar_over_time stdvar_over_time(metric[5m])changes changes(metric[5m])delta delta(metric[5m])rate rate(metric[5m])deriv deriv(metric[5m])increase increase(metric[5m])irate irate(metric[5m])resets resets(metric[5m])
Label & Other Functions
- Supported:
Function Example label_join label_join(up{job="api-server",src1="a",src2="b",src3="c"}, "foo", ",", "src1", "src2", "src3")label_replace label_replace(up{job="api-server",service="a:c"}, "foo", "$1", "service", "(.*):.*")sort_by_label sort_by_label(metric, "foo", "bar")sort_by_label_desc sort_by_label_desc(metric, "foo", "bar")