github.com/yankunsam/loki/v2@v2.6.3-0.20220817130409-389df5235c27/docs/sources/logql/_index.md (about) 1 --- 2 title: LogQL 3 weight: 700 4 --- 5 # LogQL: Log query language 6 7 LogQL is Grafana Loki's PromQL-inspired query language. 8 Queries act as if they are a distributed `grep` to aggregate log sources. 9 LogQL uses labels and operators for filtering. 10 11 There are two types of LogQL queries: 12 13 - [Log queries](log_queries/) return the contents of log lines. 14 - [Metric queries](metric_queries/) extend log queries to calculate values 15 based on query results. 16 17 ## Binary operators 18 19 ### Arithmetic operators 20 21 The following binary arithmetic operators exist in Loki: 22 23 - `+` (addition) 24 - `-` (subtraction) 25 - `*` (multiplication) 26 - `/` (division) 27 - `%` (modulo) 28 - `^` (power/exponentiation) 29 30 Binary arithmetic operators are defined between two literals (scalars), a literal and a vector, and two vectors. 31 32 Between two literals, the behavior is obvious: 33 They evaluate to another literal that is the result of the operator applied to both scalar operands (`1 + 1 = 2`). 34 35 Between a vector and a literal, the operator is applied to the value of every data sample in the vector, e.g. if a time series vector is multiplied by 2, the result is another vector in which every sample value of the original vector is multiplied by 2. 36 37 Between two vectors, a binary arithmetic operator is applied to each entry in the left-hand side vector and its matching element in the right-hand vector. 38 The result is propagated into the result vector with the grouping labels becoming the output label set. Entries for which no matching entry in the right-hand vector can be found are not part of the result. 39 40 Pay special attention to [operator order](#order-of-operations) when chaining arithmetic operators. 41 42 #### Arithmetic Examples 43 44 Implement a health check with a simple query: 45 46 ```logql 47 1 + 1 48 ``` 49 50 Double the rate of a a log stream's entries: 51 52 ```logql 53 sum(rate({app="foo"}[1m])) * 2 54 ``` 55 56 Get proportion of warning logs to error logs for the `foo` app 57 58 ```logql 59 sum(rate({app="foo", level="warn"}[1m])) / sum(rate({app="foo", level="error"}[1m])) 60 ``` 61 62 ### Logical and set operators 63 64 These logical/set binary operators are only defined between two vectors: 65 66 - `and` (intersection) 67 - `or` (union) 68 - `unless` (complement) 69 70 `vector1 and vector2` results in a vector consisting of the elements of vector1 for which there are elements in vector2 with exactly matching label sets. 71 Other elements are dropped. 72 73 `vector1 or vector2` results in a vector that contains all original elements (label sets + values) of vector1 and additionally all elements of vector2 which do not have matching label sets in vector1. 74 75 `vector1 unless vector2` results in a vector consisting of the elements of vector1 for which there are no elements in vector2 with exactly matching label sets. 76 All matching elements in both vectors are dropped. 77 78 ##### Binary operators examples 79 80 This contrived query will return the intersection of these queries, effectively `rate({app="bar"})`: 81 82 ```logql 83 rate({app=~"foo|bar"}[1m]) and rate({app="bar"}[1m]) 84 ``` 85 86 ### Comparison operators 87 88 - `==` (equality) 89 - `!=` (inequality) 90 - `>` (greater than) 91 - `>=` (greater than or equal to) 92 - `<` (less than) 93 - `<=` (less than or equal to) 94 95 Comparison operators are defined between scalar/scalar, vector/scalar, and vector/vector value pairs. 96 By default they filter. 97 Their behavior can be modified by providing `bool` after the operator, which will return 0 or 1 for the value rather than filtering. 98 99 Between two scalars, these operators result in another scalar that is either 0 (false) or 1 (true), depending on the comparison result. 100 The `bool` modifier must **not** be provided. 101 102 `1 >= 1` is equivalent to `1` 103 104 Between a vector and a scalar, these operators are applied to the value of every data sample in the vector, and vector elements between which the comparison result is false get dropped from the result vector. 105 If the `bool` modifier is provided, vector elements that would be dropped instead have the value 0 and vector elements that would be kept have the value 1. 106 107 Filters the streams which logged at least 10 lines in the last minute: 108 109 ```logql 110 count_over_time({foo="bar"}[1m]) > 10 111 ``` 112 113 Attach the value(s) `0`/`1` to streams that logged less/more than 10 lines: 114 115 ```logql 116 count_over_time({foo="bar"}[1m]) > bool 10 117 ``` 118 119 Between two vectors, these operators behave as a filter by default, applied to matching entries. 120 Vector elements for which the expression is not true or which do not find a match on the other side of the expression get dropped from the result, while the others are propagated into a result vector. 121 If the `bool` modifier is provided, vector elements that would have been dropped instead have the value 0 and vector elements that would be kept have the value 1, with the grouping labels again becoming the output label set. 122 123 Return the streams matching `app=foo` without app labels that have higher counts within the last minute than their counterparts matching `app=bar` without app labels: 124 125 ```logql 126 sum without(app) (count_over_time({app="foo"}[1m])) > sum without(app) (count_over_time({app="bar"}[1m])) 127 ``` 128 129 Same as above, but vectors have their values set to `1` if they pass the comparison or `0` if they fail/would otherwise have been filtered out: 130 131 ```logql 132 sum without(app) (count_over_time({app="foo"}[1m])) > bool sum without(app) (count_over_time({app="bar"}[1m])) 133 ``` 134 135 ### Order of operations 136 137 When chaining or combining operators, you have to consider operator precedence: 138 Generally, you can assume regular [mathematical convention](https://en.wikipedia.org/wiki/Order_of_operations) with operators on the same precedence level being left-associative. 139 140 More details can be found in the [Golang language documentation](https://golang.org/ref/spec#Operator_precedence). 141 142 `1 + 2 / 3` is equal to `1 + ( 2 / 3 )`. 143 144 `2 * 3 % 2` is evaluated as `(2 * 3) % 2`. 145 146 ### Keywords on and ignoring 147 The `ignoring` keyword causes specified labels to be ignored during matching. 148 The syntax: 149 ```logql 150 <vector expr> <bin-op> ignoring(<labels>) <vector expr> 151 ``` 152 This example will return the machines which total count within the last minutes exceed average value for app `foo`. 153 ```logql 154 max by(machine) (count_over_time({app="foo"}[1m])) > bool ignoring(machine) avg(count_over_time({app="foo"}[1m])) 155 ``` 156 The on keyword reduces the set of considered labels to a specified list. 157 The syntax: 158 ```logql 159 <vector expr> <bin-op> on(<labels>) <vector expr> 160 ``` 161 This example will return every machine total count within the last minutes ratio in app `foo`: 162 ```logql 163 sum by(machine) (count_over_time({app="foo"}[1m])) / on() sum(count_over_time({app="foo"}[1m])) 164 ``` 165 166 ### Many-to-one and one-to-many vector matches 167 Many-to-one and one-to-many matchings occur when each vector element on the "one"-side can match with multiple elements on the "many"-side. You must explicitly request matching by using the group_left or group_right modifier, where left or right determines which vector has the higher cardinality. 168 The syntax: 169 ```logql 170 <vector expr> <bin-op> ignoring(<labels>) group_left(<labels>) <vector expr> 171 <vector expr> <bin-op> ignoring(<labels>) group_right(<labels>) <vector expr> 172 <vector expr> <bin-op> on(<labels>) group_left(<labels>) <vector expr> 173 <vector expr> <bin-op> on(<labels>) group_right(<labels>) <vector expr> 174 ``` 175 The label list provided with the group modifier contains additional labels from the "one"-side that are included in the result metrics. And a label should only appear in one of the lists specified by `on` and `group_x`. Every time series of the result vector must be uniquely identifiable. 176 Grouping modifiers can only be used for comparison and arithmetic. By default, the system matches `and`, `unless`, and `or` operations with all entries in the right vector. 177 178 The following example returns the rates requests partitioned by `app` and `status` as a percentage of total requests. 179 ```logql 180 sum by (app, status) ( 181 rate( 182 {job="http-server"} 183 | json 184 [5m] 185 ) 186 ) 187 / on (app) group_left 188 sum by (app) ( 189 rate( 190 {job="http-server"} 191 | json 192 [5m] 193 ) 194 ) 195 196 => 197 [ 198 {app="foo", status="200"} => 0.8 199 {app="foo", status="400"} => 0.1 200 {app="foo", status="500"} => 0.1 201 ] 202 ``` 203 This version uses `group_left(<labels>)` to include `<labels>` from the right hand side in the result and returns the cost of discarded events per user, organization, and namespace: 204 ```logql 205 sum by (user, namespace) ( 206 rate( 207 {job="events"} 208 | logfmt 209 | discarded="true" 210 [5m] 211 ) 212 ) 213 * on (user) group_left(organization) 214 max_over_time( 215 {job="cost-calculator"} 216 | logfmt 217 | unwrap cost 218 [5m] 219 ) by (user, organization) 220 221 => 222 [ 223 {user="foo", namespace="dev", organization="little-org"} => 10 224 {user="foo", namespace="prod", organization="little-org"} => 50 225 {user="bar", namespace="dev", organization="big-org"} => 70 226 {user="bar", namespace="prod", organization="big-org"} => 200 227 ] 228 ``` 229 230 ## Comments 231 232 LogQL queries can be commented using the `#` character: 233 234 ```logql 235 {app="foo"} # anything that comes after will not be interpreted in your query 236 ``` 237 238 With multi-line LogQL queries, the query parser can exclude whole or partial lines using `#`: 239 240 ```logql 241 {app="foo"} 242 | json 243 # this line will be ignored 244 | bar="baz" # this checks if bar = "baz" 245 ``` 246 247 ## Pipeline Errors 248 249 There are multiple reasons which cause pipeline processing errors, such as: 250 251 - A numeric label filter may fail to turn a label value into a number 252 - A metric conversion for a label may fail. 253 - A log line is not a valid json document. 254 - etc... 255 256 When those failures happen, Loki won't filter out those log lines. Instead they are passed into the next stage of the pipeline with a new system label named `__error__`. The only way to filter out errors is by using a label filter expressions. The `__error__` label can't be renamed via the language. 257 258 For example to remove json errors: 259 260 ```logql 261 {cluster="ops-tools1",container="ingress-nginx"} 262 | json 263 | __error__ != "JSONParserErr" 264 ``` 265 266 Alternatively you can remove all error using a catch all matcher such as `__error__ = ""` or even show only errors using `__error__ != ""`. 267 268 The filter should be placed after the stage that generated this error. This means if you need to remove errors from an unwrap expression it needs to be placed after the unwrap. 269 270 ```logql 271 quantile_over_time( 272 0.99, 273 {container="ingress-nginx",service="hosted-grafana"} 274 | json 275 | unwrap response_latency_seconds 276 | __error__=""[1m] 277 ) by (cluster) 278 ``` 279 280 >Metric queries cannot contain errors, in case errors are found during execution, Loki will return an error and appropriate status code. 281 282 ## Functions 283 284 Loki supports functions to operate on data. 285 286 ### label_replace() 287 288 For each timeseries in `v`, 289 290 ``` 291 label_replace(v instant-vector, 292 dst_label string, 293 replacement string, 294 src_label string, 295 regex string) 296 ``` 297 matches the regular expression `regex` against the label `src_label`. 298 If it matches, then the timeseries is returned with the label `dst_label` replaced by the expansion of `replacement`. 299 300 `$1` is replaced with the first matching subgroup, 301 `$2` with the second etc. 302 If the regular expression doesn't match, 303 then the timeseries is returned unchanged. 304 305 This example will return a vector with each time series having a `foo` label with the value `a` added to it: 306 307 ```logql 308 label_replace(rate({job="api-server",service="a:c"} |= "err" [1m]), "foo", "$1", 309 "service", "(.*):.*") 310 ```