Skip to content
Merged
Show file tree
Hide file tree
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 Dec 29, 2021
bfd6875
feature: new version without ranges
salvatore-campagna Dec 29, 2021
77373e9
fix: reuse method to extract the netmask from the prefix length
salvatore-campagna Jan 11, 2022
f0e4b8a
docs: add some javadoc
salvatore-campagna Jan 11, 2022
d344f25
fix: code format violations
salvatore-campagna Jan 11, 2022
3506bba
fix: check number of buckets to collect
salvatore-campagna Jan 11, 2022
3832cb5
fix: extract ther ipv6 address value
salvatore-campagna Jan 11, 2022
228c264
fix: add ip_prefix to the unsupported transform aggregations
salvatore-campagna Jan 11, 2022
48c9d03
test: include tests with incorrect is_ipv6 value
salvatore-campagna Jan 12, 2022
a2f0498
Merge branch 'master' into feature/ip-subnet-agg
elasticmachine Jan 13, 2022
b3403e9
fix: incorrect netmask
salvatore-campagna Jan 13, 2022
58297d5
fix: move IpPrefix aggregator to prefix package
salvatore-campagna Jan 13, 2022
563d337
fix: code format violations
salvatore-campagna Jan 13, 2022
c269c66
docs: include documentation for the ip prefix aggregation
salvatore-campagna Jan 13, 2022
90b5e95
docs: fix sentence using the actual aggregation name
salvatore-campagna Jan 13, 2022
3c68ec2
docs: reduce the number of documents used in the example
salvatore-campagna Jan 13, 2022
2ca2cb2
test: add integration tests for mixed IPv4/IPv6 field
salvatore-campagna Jan 14, 2022
4a1a9ce
Merge branch 'master' into feature/ip-subnet-agg
elasticmachine Jan 14, 2022
318a139
docs: improve the documentation
salvatore-campagna Jan 14, 2022
1aa223f
fix: use 1 as the min_doc_count minimum and default value
salvatore-campagna Jan 14, 2022
986f0d8
docs: include the field type
salvatore-campagna Jan 14, 2022
322e42f
docs: rephrase netmask description
salvatore-campagna Jan 14, 2022
ea66f68
Merge branch 'master' into feature/ip-subnet-agg
elasticmachine Jan 14, 2022
f70f3d8
Merge branch 'master' into feature/ip-subnet-agg
elasticmachine Jan 17, 2022
6359121
docs: reference documentation improvements
salvatore-campagna Jan 17, 2022
7859b89
Merge branch 'master' into feature/ip-subnet-agg
elasticmachine Jan 17, 2022
917389f
fix: use prefix_length instead of prefix_len
salvatore-campagna Jan 20, 2022
9d5956d
fix: improve exception error messages
salvatore-campagna Jan 20, 2022
cdfed61
fix: add some notes clarifying netmask setting
salvatore-campagna Jan 20, 2022
785eb6f
fix: use ValueSourceConfig instead of ValueSource and DocValueFormat
salvatore-campagna Jan 20, 2022
54547e4
fix: remove check of bucket limit
salvatore-campagna Jan 20, 2022
130cb9f
fix: use a NonCollectingAggregator when unmapped
salvatore-campagna Jan 20, 2022
ccab368
fix: improve performance of critical path removing Arrays.copyOfRange
salvatore-campagna Jan 20, 2022
df8ff71
fix: avoid re-allocation of BytesRef variables
salvatore-campagna Jan 20, 2022
6602d96
fix: code format violations
salvatore-campagna Jan 20, 2022
3e1d03e
Merge branch 'master' into feature/ip-subnet-agg
elasticmachine Jan 20, 2022
3a967cd
fix: error message for invalid prefix_length
salvatore-campagna Jan 20, 2022
83f12c4
fix: use the parent testCase method
salvatore-campagna Jan 20, 2022
3645a72
fix: code format violations
salvatore-campagna Jan 20, 2022
c4d20e6
fix: use the correct prefix length range depending on the isIpv6 rand…
salvatore-campagna Jan 20, 2022
da3eb73
Merge branch 'master' into feature/ip-subnet-agg
elasticmachine Jan 24, 2022
658a844
fix: re-use the subnet buffer instead of re-allocating byte arrays
salvatore-campagna Jan 26, 2022
e4517a2
Update docs/changelog/82410.yaml
salvatore-campagna Jan 26, 2022
6f446c2
Merge branch 'master' into feature/ip-subnet-agg
elasticmachine Jan 26, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/reference/aggregations/bucket.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ include::bucket/global-aggregation.asciidoc[]

include::bucket/histogram-aggregation.asciidoc[]

include::bucket/ipprefix-aggregation.asciidoc[]

include::bucket/iprange-aggregation.asciidoc[]

include::bucket/missing-aggregation.asciidoc[]
Expand Down
387 changes: 387 additions & 0 deletions docs/reference/aggregations/bucket/ipprefix-aggregation.asciidoc
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}}
{"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`.


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

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,/]

Loading