-
Notifications
You must be signed in to change notification settings - Fork 25.6k
Add an aggregator for IPv4 and IPv6 subnets #82410
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
Merged
salvatore-campagna
merged 44 commits into
elastic:master
from
salvatore-campagna:feature/ip-subnet-agg
Jan 28, 2022
Merged
Changes from 41 commits
Commits
Show all changes
44 commits
Select commit
Hold shift + click to select a range
d63ae90
feature: ipv4 and ipv6 subnet aggregator
salvatore-campagna bfd6875
feature: new version without ranges
salvatore-campagna 77373e9
fix: reuse method to extract the netmask from the prefix length
salvatore-campagna f0e4b8a
docs: add some javadoc
salvatore-campagna d344f25
fix: code format violations
salvatore-campagna 3506bba
fix: check number of buckets to collect
salvatore-campagna 3832cb5
fix: extract ther ipv6 address value
salvatore-campagna 228c264
fix: add ip_prefix to the unsupported transform aggregations
salvatore-campagna 48c9d03
test: include tests with incorrect is_ipv6 value
salvatore-campagna a2f0498
Merge branch 'master' into feature/ip-subnet-agg
elasticmachine b3403e9
fix: incorrect netmask
salvatore-campagna 58297d5
fix: move IpPrefix aggregator to prefix package
salvatore-campagna 563d337
fix: code format violations
salvatore-campagna c269c66
docs: include documentation for the ip prefix aggregation
salvatore-campagna 90b5e95
docs: fix sentence using the actual aggregation name
salvatore-campagna 3c68ec2
docs: reduce the number of documents used in the example
salvatore-campagna 2ca2cb2
test: add integration tests for mixed IPv4/IPv6 field
salvatore-campagna 4a1a9ce
Merge branch 'master' into feature/ip-subnet-agg
elasticmachine 318a139
docs: improve the documentation
salvatore-campagna 1aa223f
fix: use 1 as the min_doc_count minimum and default value
salvatore-campagna 986f0d8
docs: include the field type
salvatore-campagna 322e42f
docs: rephrase netmask description
salvatore-campagna ea66f68
Merge branch 'master' into feature/ip-subnet-agg
elasticmachine f70f3d8
Merge branch 'master' into feature/ip-subnet-agg
elasticmachine 6359121
docs: reference documentation improvements
salvatore-campagna 7859b89
Merge branch 'master' into feature/ip-subnet-agg
elasticmachine 917389f
fix: use prefix_length instead of prefix_len
salvatore-campagna 9d5956d
fix: improve exception error messages
salvatore-campagna cdfed61
fix: add some notes clarifying netmask setting
salvatore-campagna 785eb6f
fix: use ValueSourceConfig instead of ValueSource and DocValueFormat
salvatore-campagna 54547e4
fix: remove check of bucket limit
salvatore-campagna 130cb9f
fix: use a NonCollectingAggregator when unmapped
salvatore-campagna ccab368
fix: improve performance of critical path removing Arrays.copyOfRange
salvatore-campagna df8ff71
fix: avoid re-allocation of BytesRef variables
salvatore-campagna 6602d96
fix: code format violations
salvatore-campagna 3e1d03e
Merge branch 'master' into feature/ip-subnet-agg
elasticmachine 3a967cd
fix: error message for invalid prefix_length
salvatore-campagna 83f12c4
fix: use the parent testCase method
salvatore-campagna 3645a72
fix: code format violations
salvatore-campagna c4d20e6
fix: use the correct prefix length range depending on the isIpv6 rand…
salvatore-campagna da3eb73
Merge branch 'master' into feature/ip-subnet-agg
elasticmachine 658a844
fix: re-use the subnet buffer instead of re-allocating byte arrays
salvatore-campagna e4517a2
Update docs/changelog/82410.yaml
salvatore-campagna 6f446c2
Merge branch 'master' into feature/ip-subnet-agg
elasticmachine File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
387 changes: 387 additions & 0 deletions
387
docs/reference/aggregations/bucket/ipprefix-aggregation.asciidoc
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,387 @@ | ||
| [[search-aggregations-bucket-ipprefix-aggregation]] | ||
| === IP prefix aggregation | ||
| ++++ | ||
| <titleabbrev>IP prefix</titleabbrev> | ||
| ++++ | ||
|
|
||
| A bucket aggregation that groups documents based on the network or sub-network of an IP address. An IP address consists of two groups of bits: the most significant bits which represent the network prefix, and the least significant bits which represent the host. | ||
|
|
||
| [[ipprefix-agg-ex]] | ||
| ==== Example | ||
|
|
||
| For example, consider the following index: | ||
| [source,console] | ||
| ---------------------------------------------- | ||
| PUT network-traffic | ||
| { | ||
| "mappings": { | ||
| "properties": { | ||
| "ipv4": { "type": "ip" }, | ||
| "ipv6": { "type": "ip" } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| POST /network-traffic/_bulk?refresh | ||
| {"index":{"_id":0}} | ||
salvatore-campagna marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| {"ipv4":"192.168.1.10","ipv6":"2001:db8:a4f8:112a:6001:0:12:7f10"} | ||
| {"index":{"_id":1}} | ||
| {"ipv4":"192.168.1.12","ipv6":"2001:db8:a4f8:112a:6001:0:12:7f12"} | ||
| {"index":{"_id":2}} | ||
| { "ipv4":"192.168.1.33","ipv6":"2001:db8:a4f8:112a:6001:0:12:7f33"} | ||
| {"index":{"_id":3}} | ||
| {"ipv4":"192.168.1.10","ipv6":"2001:db8:a4f8:112a:6001:0:12:7f10"} | ||
| {"index":{"_id":4}} | ||
| {"ipv4":"192.168.2.41","ipv6":"2001:db8:a4f8:112c:6001:0:12:7f41"} | ||
| {"index":{"_id":5}} | ||
| {"ipv4":"192.168.2.10","ipv6":"2001:db8:a4f8:112c:6001:0:12:7f10"} | ||
| {"index":{"_id":6}} | ||
| {"ipv4":"192.168.2.23","ipv6":"2001:db8:a4f8:112c:6001:0:12:7f23"} | ||
| {"index":{"_id":7}} | ||
| {"ipv4":"192.168.3.201","ipv6":"2001:db8:a4f8:114f:6001:0:12:7201"} | ||
| {"index":{"_id":8}} | ||
| {"ipv4":"192.168.3.107","ipv6":"2001:db8:a4f8:114f:6001:0:12:7307"} | ||
| ---------------------------------------------- | ||
| // TESTSETUP | ||
|
|
||
| The following aggregation groups documents into buckets. Each bucket identifies a different sub-network. The sub-network is calculated by applying a netmask with prefix length of `24` to each IP address in the `ipv4` field: | ||
|
|
||
| [source,console,id=ip-prefix-ipv4-example] | ||
| -------------------------------------------------- | ||
| GET /network-traffic/_search | ||
| { | ||
| "size": 0, | ||
| "aggs": { | ||
| "ipv4-subnets": { | ||
| "ip_prefix": { | ||
| "field": "ipv4", | ||
| "prefix_length": 24 | ||
| } | ||
| } | ||
| } | ||
| } | ||
| -------------------------------------------------- | ||
| // TEST | ||
|
|
||
| Response: | ||
|
|
||
| [source,console-result] | ||
| -------------------------------------------------- | ||
| { | ||
| ... | ||
|
|
||
| "aggregations": { | ||
| "ipv4-subnets": { | ||
| "buckets": [ | ||
| { | ||
| "key": "192.168.1.0", | ||
| "is_ipv6": false, | ||
| "doc_count": 4, | ||
| "prefix_length": 24, | ||
| "netmask": "255.255.255.0" | ||
| }, | ||
| { | ||
| "key": "192.168.2.0", | ||
| "is_ipv6": false, | ||
| "doc_count": 3, | ||
| "prefix_length": 24, | ||
| "netmask": "255.255.255.0" | ||
| }, | ||
| { | ||
| "key": "192.168.3.0", | ||
| "is_ipv6": false, | ||
| "doc_count": 2, | ||
| "prefix_length": 24, | ||
| "netmask": "255.255.255.0" | ||
| } | ||
| ] | ||
| } | ||
| } | ||
| } | ||
| -------------------------------------------------- | ||
| // TESTRESPONSE[s/\.\.\./"took": $body.took,"timed_out": false,"_shards": $body._shards,"hits": $body.hits,/] | ||
|
|
||
| To aggregate IPv6 addresses, set `is_ipv6` to `true`. | ||
|
|
||
| [source,console,id=ip-prefix-ipv6-example] | ||
| -------------------------------------------------- | ||
| GET /network-traffic/_search | ||
| { | ||
| "size": 0, | ||
| "aggs": { | ||
| "ipv6-subnets": { | ||
| "ip_prefix": { | ||
| "field": "ipv6", | ||
| "prefix_length": 64, | ||
| "is_ipv6": true | ||
| } | ||
| } | ||
| } | ||
| } | ||
| -------------------------------------------------- | ||
| // TEST | ||
|
|
||
| If `is_ipv6` is `true`, the response doesn't include a `netmask` for each bucket. | ||
|
|
||
| [source,console-result] | ||
| -------------------------------------------------- | ||
| { | ||
| ... | ||
|
|
||
| "aggregations": { | ||
| "ipv6-subnets": { | ||
| "buckets": [ | ||
| { | ||
| "key": "2001:db8:a4f8:112a::", | ||
| "is_ipv6": true, | ||
| "doc_count": 4, | ||
| "prefix_length": 64 | ||
| }, | ||
| { | ||
| "key": "2001:db8:a4f8:112c::", | ||
| "is_ipv6": true, | ||
| "doc_count": 3, | ||
| "prefix_length": 64 | ||
| }, | ||
| { | ||
| "key": "2001:db8:a4f8:114f::", | ||
| "is_ipv6": true, | ||
| "doc_count": 2, | ||
| "prefix_length": 64 | ||
| } | ||
| ] | ||
| } | ||
| } | ||
| } | ||
| -------------------------------------------------- | ||
| // TESTRESPONSE[s/\.\.\./"took": $body.took,"timed_out": false,"_shards": $body._shards,"hits": $body.hits,/] | ||
|
|
||
| [role="child_attributes"] | ||
| [[ip-prefix-agg-params]] | ||
| ==== Parameters | ||
|
|
||
| `field`:: | ||
| (Required, string) | ||
| The document IP address field to aggregate on. The field mapping type must be <<ip,`ip`>>. | ||
|
|
||
| `prefix_length`:: | ||
| (Required, integer) | ||
| Length of the network prefix. For IPv4 addresses, the accepted range is `[0, 32]`. For IPv6 addresses, the accepted range is `[0, 128]`. | ||
|
|
||
| `is_ipv6`:: | ||
| (Optional, boolean) | ||
| Defines whether the prefix applies to IPv6 addresses. Just specifying the `prefix_length` parameter is not enough to know if an IP prefix applies to IPv4 or IPv6 addresses. Defaults to `false`. | ||
|
|
||
| `append_prefix_length`:: | ||
| (Optional, boolean) | ||
| Defines whether the prefix length is appended to IP address keys in the response. Defaults to `false`. | ||
|
|
||
| `keyed`:: | ||
| (Optional, boolean) | ||
| Defines whether buckets are returned as a hash rather than an array in the response. Defaults to `false`. | ||
|
|
||
| `min_doc_count`:: | ||
| (Optional, integer) | ||
| Defines the minimum number of documents for buckets to be included in the response. Defaults to `1`. | ||
|
|
||
jrodewig marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| [[ipprefix-agg-response]] | ||
| ==== Response body | ||
|
|
||
| `key`:: | ||
| (string) | ||
| The IPv6 or IPv4 subnet. | ||
|
|
||
| `prefix_length`:: | ||
| (integer) | ||
| The length of the prefix used to aggregate the bucket. | ||
|
|
||
| `doc_count`:: | ||
| (integer) | ||
| Number of documents matching a specific IP prefix. | ||
|
|
||
| `is_ipv6`:: | ||
| (boolean) | ||
| Defines whether the netmask is an IPv6 netmask. | ||
|
|
||
| `netmask`:: | ||
| (string) | ||
| The IPv4 netmask. If `is_ipv6` is `true` in the request, this field is missing in the response. | ||
|
|
||
| [[ipprefix-agg-keyed-response]] | ||
| ==== Keyed Response | ||
jrodewig marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| Set the `keyed` flag of `true` to associate an unique IP address key with each bucket and return sub-networks as a hash rather than an array. | ||
|
|
||
| Example: | ||
|
|
||
| [source,console,id=ip-prefix-keyed-example] | ||
| -------------------------------------------------- | ||
| GET /network-traffic/_search | ||
| { | ||
| "size": 0, | ||
| "aggs": { | ||
| "ipv4-subnets": { | ||
| "ip_prefix": { | ||
| "field": "ipv4", | ||
| "prefix_length": 24, | ||
| "keyed": true | ||
| } | ||
| } | ||
| } | ||
| } | ||
| -------------------------------------------------- | ||
| // TEST | ||
|
|
||
| Response: | ||
|
|
||
| [source,console-result] | ||
| -------------------------------------------------- | ||
| { | ||
| ... | ||
|
|
||
| "aggregations": { | ||
| "ipv4-subnets": { | ||
| "buckets": { | ||
| "192.168.1.0": { | ||
| "is_ipv6": false, | ||
| "doc_count": 4, | ||
| "prefix_length": 24, | ||
| "netmask": "255.255.255.0" | ||
| }, | ||
| "192.168.2.0": { | ||
| "is_ipv6": false, | ||
| "doc_count": 3, | ||
| "prefix_length": 24, | ||
| "netmask": "255.255.255.0" | ||
| }, | ||
| "192.168.3.0": { | ||
| "is_ipv6": false, | ||
| "doc_count": 2, | ||
| "prefix_length": 24, | ||
| "netmask": "255.255.255.0" | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| -------------------------------------------------- | ||
| // TESTRESPONSE[s/\.\.\./"took": $body.took,"timed_out": false,"_shards": $body._shards,"hits": $body.hits,/] | ||
|
|
||
| [[ipprefix-agg-append-prefix-length]] | ||
| ==== Append the prefix length to the IP address key | ||
|
|
||
| Set the `append_prefix_length` flag to `true` to catenate IP address keys with the prefix length of the sub-network. | ||
|
|
||
| Example: | ||
|
|
||
| [source,console,id=ip-prefix-append-prefix-len-example] | ||
| -------------------------------------------------- | ||
| GET /network-traffic/_search | ||
| { | ||
| "size": 0, | ||
| "aggs": { | ||
| "ipv4-subnets": { | ||
| "ip_prefix": { | ||
| "field": "ipv4", | ||
| "prefix_length": 24, | ||
| "append_prefix_length": true | ||
| } | ||
| } | ||
| } | ||
| } | ||
| -------------------------------------------------- | ||
| // TEST | ||
|
|
||
| Response: | ||
|
|
||
| [source,console-result] | ||
| -------------------------------------------------- | ||
| { | ||
| ... | ||
|
|
||
| "aggregations": { | ||
| "ipv4-subnets": { | ||
| "buckets": [ | ||
| { | ||
| "key": "192.168.1.0/24", | ||
| "is_ipv6": false, | ||
| "doc_count": 4, | ||
| "prefix_length": 24, | ||
| "netmask": "255.255.255.0" | ||
| }, | ||
| { | ||
| "key": "192.168.2.0/24", | ||
| "is_ipv6": false, | ||
| "doc_count": 3, | ||
| "prefix_length": 24, | ||
| "netmask": "255.255.255.0" | ||
| }, | ||
| { | ||
| "key": "192.168.3.0/24", | ||
| "is_ipv6": false, | ||
| "doc_count": 2, | ||
| "prefix_length": 24, | ||
| "netmask": "255.255.255.0" | ||
| } | ||
| ] | ||
| } | ||
| } | ||
| } | ||
| -------------------------------------------------- | ||
| // TESTRESPONSE[s/\.\.\./"took": $body.took,"timed_out": false,"_shards": $body._shards,"hits": $body.hits,/] | ||
|
|
||
| [[ipprefix-agg-min-doc-count]] | ||
| ==== Minimum document count | ||
|
|
||
| Use the `min_doc_count` parameter to only return buckets with a minimum number of documents. | ||
|
|
||
| [source,console,id=ip-prefix-min-doc-count-example] | ||
| -------------------------------------------------- | ||
| GET /network-traffic/_search | ||
| { | ||
| "size": 0, | ||
| "aggs": { | ||
| "ipv4-subnets": { | ||
| "ip_prefix": { | ||
| "field": "ipv4", | ||
| "prefix_length": 24, | ||
| "min_doc_count": 3 | ||
| } | ||
| } | ||
| } | ||
| } | ||
| -------------------------------------------------- | ||
| // TEST | ||
|
|
||
| Response: | ||
|
|
||
| [source,console-result] | ||
| -------------------------------------------------- | ||
| { | ||
| ... | ||
|
|
||
| "aggregations": { | ||
| "ipv4-subnets": { | ||
| "buckets": [ | ||
| { | ||
| "key": "192.168.1.0", | ||
| "is_ipv6": false, | ||
| "doc_count": 4, | ||
| "prefix_length": 24, | ||
| "netmask": "255.255.255.0" | ||
| }, | ||
| { | ||
| "key": "192.168.2.0", | ||
| "is_ipv6": false, | ||
| "doc_count": 3, | ||
| "prefix_length": 24, | ||
| "netmask": "255.255.255.0" | ||
| } | ||
| ] | ||
| } | ||
| } | ||
| } | ||
| -------------------------------------------------- | ||
| // TESTRESPONSE[s/\.\.\./"took": $body.took,"timed_out": false,"_shards": $body._shards,"hits": $body.hits,/] | ||
|
|
||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.