Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Binary operators in LogQL #1662

Merged
merged 10 commits into from
Feb 11, 2020
Merged

Binary operators in LogQL #1662

merged 10 commits into from
Feb 11, 2020

Conversation

owen-d
Copy link
Member

@owen-d owen-d commented Feb 7, 2020

What this PR does / why we need it:
This feature introduces binary operators into LogQL. In addition to the benefits provided by binary operations, it also helps pave the way for future sharding work.

Arithmetic Binary Operators

Arithmetic binary operators
The following binary arithmetic operators exist in Loki:

  • + (addition)
  • - (subtraction)
  • * (multiplication)
  • / (division)
  • % (modulo)

Binary arithmetic operators are defined only between two vectors.

Between two instant 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. 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.

Examples

Get proportion of warning logs to error logs for the foo app

sum(rate({app="foo", level="warn"}[1m])) / sum(rate({app="foo", level="error"}[1m]))

Operators on the same precedence level are left-associative (queries substituted with numbers here for simplicity). For example, 2 * 3 % 2 is equivalent to (2 * 3) % 2. However, some operators have different priorities: 1 + 2 / 3 will still be 1 + ( 2 / 3 ). These function identically to mathematical conventions.

Logical/set binary operators

These logical/set binary operators are only defined between two vectors:

  • and (intersection)
  • or (union)
  • unless (complement)

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. Other elements are dropped.

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.

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. All matching elements in both vectors are dropped.

Examples

This contrived query will return the intersection of these queries, effectively rate({app="bar"})

rate({app=~"foo|bar"}[1m]) and rate({app="bar"}[1m])

@codecov-io
Copy link

codecov-io commented Feb 7, 2020

Codecov Report

Merging #1662 into master will increase coverage by 0.58%.
The diff coverage is 92.7%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1662      +/-   ##
==========================================
+ Coverage   61.73%   62.31%   +0.58%     
==========================================
  Files         109      109              
  Lines        8310     8446     +136     
==========================================
+ Hits         5130     5263     +133     
- Misses       2784     2786       +2     
- Partials      396      397       +1
Impacted Files Coverage Δ
pkg/logql/lex.go 100% <ø> (ø) ⬆️
pkg/logql/ast.go 88.6% <100%> (+1.39%) ⬆️
pkg/logql/engine.go 88.23% <100%> (ø) ⬆️
pkg/logql/evaluator.go 92.23% <91.3%> (+0.48%) ⬆️
pkg/promtail/targets/filetarget.go 70.55% <0%> (+1.84%) ⬆️
pkg/promtail/targets/tailer.go 75.86% <0%> (+2.29%) ⬆️

@cyriltovena cyriltovena self-assigned this Feb 8, 2020
{
// require left associativity
in: `
sum(count_over_time({foo="bar"}[5m])) by (foo) /
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to have more failure tests, specially around unexpected type like two logstreams ({app="foo"} + {app="fuzz"}) which you seem to support reading the yacc file. (I might be wrong).

This would also be nice for covering panic thrown in the ast.go

We should try to keep error message for those bad query useful for our users.

Copy link
Contributor

@cyriltovena cyriltovena left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, left few comments about ast error.

Copy link
Contributor

@cyriltovena cyriltovena left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@owen-d owen-d merged commit 6bbb61e into grafana:master Feb 11, 2020
@owen-d owen-d deleted the feature/arith-binops branch February 11, 2020 16:36
billimek added a commit to billimek/loki that referenced this pull request Feb 13, 2020
* 'extraPorts' of github.com:billimek/loki: (25 commits)
  Ensure status codes are set correctly in the frontend. (grafana#1684)
  --dry-run Promtail. (grafana#1652)
  Fix logcli --quiet parameter parsing issue (grafana#1682)
  This improves the log ouput for statistics in the logcli. (grafana#1644)
  Loki stack helm chart can deploy datasources without Grafana (grafana#1688)
  Automatically prune metrics from the /metrics output of the promtail metrics pipeline stage after an idle period.
  Allow a metric defined as a counter to match all lines, useful for creating line count metrics which include all your labels. Found a bug in the the test runner where it didn't fail if the actual error was nil but the test expected an error Added some tests to the counters to test valid configs
  maintainer links & usernames (grafana#1675)
  Binary operators in LogQL (grafana#1662)
  Pipe data to Promtail (grafana#1649)
  Add Owen to the maintainer team. (grafana#1673)
  Update tanka.md so that promtail.yml is in the correct format (grafana#1671)
  Correcte syntax of rate example (grafana#1641)
  Frontend & Querier query statistics instrumentation. (grafana#1661)
  loki-canary: fix indent of DaemonSet manifest written in .md file (grafana#1648)
  Query frontend service should be headless. (grafana#1665)
  Support custom prefix name in metrics stage (grafana#1664)
  pkg/promtail/positions: handle empty positions file (grafana#1660)
  Convert second(Integer class) to nanosecond precision (grafana#1656)
  Unite docs for fluentd plugin (grafana#1634)
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants