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  ```