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

Ip matcher for LogQL #3986

Merged
merged 24 commits into from
Jul 22, 2021
Merged

Ip matcher for LogQL #3986

merged 24 commits into from
Jul 22, 2021

Conversation

kavirajk
Copy link
Collaborator

@kavirajk kavirajk commented Jul 12, 2021

What this PR does / why we need it:

This PR adds buiilt-in IP matcher support for LogQL. It adds filter ip(pattern). It works with both IPv4 and IPv6 and can be used as both label_filter and line_filter

pattern can be one of the following.

  1. Single IP - e.g: 192.168.0.1, ::1
  2. IP Range - e.g: 192.168.0.1-192.189.10.12, 2001:db8::1-2001:db8::8
  3. CIDR - e.g: 192.168.4.5/16, 2001:db8::/32

Example queries:

  1. `{ foo = "bar" }|=ip("192.168.4.5/16")
  2. { foo = "bar" }|logfmt|addr=ip("192.168.4.5/16")
  3. { foo = "bar" }|logfmt|remote_addr=ip("2001:db8::1-2001:db8::8")|level="error"

Which issue(s) this PR fixes:
Fixes #2722

Special notes for your reviewer:
Based on the design doc

Checklist

  • Documentation added
  • Tests updated

@kavirajk kavirajk requested a review from a team July 13, 2021 07:51
pkg/logql/expr.y Outdated Show resolved Hide resolved
func (ipf *IPFilter) Process(line []byte, lbs *LabelsBuilder) ([]byte, bool) {

// make sure the pattern provided was valid, even before trying to match.
if ipf.patternError != nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

This can be spotted before and so should return an error during query parsing.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yea. thought about that actually. My previous implementation had thrown this error during constructor of NewIPFilter() but while writing grammar, there was no way to handle that error while creating the LabelFilter expression!. So I changed it to like this.

May be I'm missing something about handling this error during the parse stage?. Can you point me any example?

Copy link
Contributor

Choose a reason for hiding this comment

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

You can use the Stage() method of this expr, it can return an errors and will be considered as 400.

pkg/logql/log/ip.go Outdated Show resolved Hide resolved
pkg/logql/log/ip.go Outdated Show resolved Hide resolved
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.

Looking good ! I've left some comments.

@kavirajk
Copy link
Collaborator Author

@cyriltovena addressed your comments. can you take a look again? thanks

@kavirajk kavirajk changed the title Ip matcher label filter Ip matcher for LogQL Jul 14, 2021
Copy link
Contributor

@dannykopping dannykopping left a comment

Choose a reason for hiding this comment

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

Comment on lines 5 to 31
Consider the following logs,

```
3.180.71.3 - - [17/May/2015:08:05:32 +0000] "GET /downloads/product_1 HTTP/1.1" 304 0 "-" "Debian APT-HTTP/1.3 (0.8.16~exp12ubuntu10.21)"
80.91.33.133 - - [17/May/2015:08:05:14 +0000] "GET /downloads/product_1 HTTP/1.1" 304 0 "-" "Debian APT-HTTP/1.3 (0.8.16~exp12ubuntu10.16)"
46.4.66.76 - - [17/May/2015:08:05:45 +0000] "GET /downloads/product_1 HTTP/1.1" 404 318 "-" "Debian APT-HTTP/1.3 (1.0.1ubuntu2)"
93.180.71.3 - - [17/May/2015:08:05:26 +0000] "GET /downloads/product_1 HTTP/1.1" 404 324 "-" "Debian APT-HTTP/1.3 (0.8.16~exp12ubuntu10.21)"
```

How would you use LogQL to search for log lines with IP addresses?. Say single IP to start with? That's easy, we can use LogQL line filter (kinda like distributed grep)

```logql
{foo="bar"} |= "3.180.71.3"
```

will output following log lines.

```
3.180.71.3 - - [17/May/2015:08:05:32 +0000] "GET /downloads/product_1 HTTP/1.1" 304 0 "-" "Debian APT-HTTP/1.3 (0.8.16~exp12ubuntu10.21)"
93.180.71.3 - - [17/May/2015:08:05:26 +0000] "GET /downloads/product_1 HTTP/1.1" 404 324 "-" "Debian APT-HTTP/1.3 (0.8.16~exp12ubuntu10.21)"
```

but wait! what `93.180.71.3` is doing here?. Oh yea. it actually matches with what we queried for `3.180.71.3`. It can also match with other log lines which we don't actually want. The right option would be to use regexp to match the IP address(something like `|~"^3.180.71.3"`).

Now forget about single IP, what about range of IP addresses? What about IP subnet? Or even more interesting IPv6 addresses? (not easy to come up with regexp for all the use cases).

Luckily, LogQL comes with built-in support for IP matcher.
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think we need to present the need for the parser; I think that's relatively self-explanatory.

- Label Filter

```logql
{ foo = "bar" }|logfmt|remote_addr=ip("2001:db8::1-2001:db8::8")|level="error"
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's format these queries to make them more readable:

{ foo = "bar" }
  | logfmt
  | remote_addr=ip("2001:db8::1-2001:db8::8")
  | level="error"

@kavirajk kavirajk mentioned this pull request Jul 15, 2021
5 tasks
pkg/logql/expr.y Outdated Show resolved Hide resolved
pkg/logql/log/ip.go Outdated Show resolved Hide resolved
pkg/logql/log/ip.go Outdated Show resolved Hide resolved
pkg/logql/log/ip.go Outdated Show resolved Hide resolved
pkg/logql/log/ip.go Show resolved Hide resolved
pkg/logql/ast.go Outdated Show resolved Hide resolved
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

@cyriltovena
Copy link
Contributor

@dannykopping @KMiller-Grafana Are we good to go ?

@KMiller-Grafana
Copy link
Contributor

Looks good to me. I've added an extra task to my personal to-do list to correct the weights in the docs files associated with this PR after this PR is merged in.

@cyriltovena
Copy link
Contributor

@kavirajk can up resolve conflicts and regenerate the y.go files.

Signed-off-by: Kaviraj <kavirajkanagaraj@gmail.com>
1. ast tests
2. parse tests

Signed-off-by: Kaviraj <kavirajkanagaraj@gmail.com>
Signed-off-by: Kaviraj <kavirajkanagaraj@gmail.com>
Signed-off-by: Kaviraj <kavirajkanagaraj@gmail.com>
Signed-off-by: Kaviraj <kavirajkanagaraj@gmail.com>
Signed-off-by: Kaviraj <kavirajkanagaraj@gmail.com>
Signed-off-by: Kaviraj <kavirajkanagaraj@gmail.com>
Signed-off-by: Kaviraj <kavirajkanagaraj@gmail.com>
1. support NEQ
2. reduce allocation.
3. Minor tweaks

Signed-off-by: Kaviraj <kavirajkanagaraj@gmail.com>
1. Add necessary interface implementation
2. More tests for parser and ast

Signed-off-by: Kaviraj <kavirajkanagaraj@gmail.com>
Signed-off-by: Kaviraj <kavirajkanagaraj@gmail.com>
Its wierd bug. Not handing string() method breaks the parser :(

Signed-off-by: Kaviraj <kavirajkanagaraj@gmail.com>
It got out of hands to handle both in same struct.

Signed-off-by: Kaviraj <kavirajkanagaraj@gmail.com>
Signed-off-by: Kaviraj <kavirajkanagaraj@gmail.com>
1. Indendation fix
2. Remove string() interface for ip label filte
@kavirajk
Copy link
Collaborator Author

@cyriltovena conflicts resolved. Can you merge it?

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.

Ready-made matchers for IP addresses
4 participants