diff --git a/go.mod b/go.mod index 67c70b48090..2c472909518 100644 --- a/go.mod +++ b/go.mod @@ -51,9 +51,9 @@ require ( github.com/sony/gobreaker v0.5.0 github.com/spf13/afero v1.9.5 github.com/stretchr/testify v1.8.4 - github.com/thanos-io/objstore v0.0.0-20230721074820-89475d4508df - github.com/thanos-io/promql-engine v0.0.0-20230526105742-791d78b260ea - github.com/thanos-io/thanos v0.31.1-0.20230809185825-46339760e526 + github.com/thanos-io/objstore v0.0.0-20230804084840-c042a6a16c58 + github.com/thanos-io/promql-engine v0.0.0-20230816062837-c64fc7b373db + github.com/thanos-io/thanos v0.0.0-20230816172224-2b4f2a7061f9 github.com/uber/jaeger-client-go v2.30.0+incompatible github.com/weaveworks/common v0.0.0-20221201103051-7c2720a9024d go.etcd.io/etcd/api/v3 v3.5.9 @@ -117,6 +117,7 @@ require ( github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dennwc/varint v1.0.0 // indirect + github.com/dgryski/go-metro v0.0.0-20200812162917-85c65e2d0165 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/docker/go-units v0.5.0 // indirect github.com/edsrzf/mmap-go v1.1.0 // indirect @@ -187,6 +188,7 @@ require ( github.com/rs/cors v1.9.0 // indirect github.com/rs/xid v1.5.0 // indirect github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect + github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb // indirect github.com/sercand/kuberesolver v2.4.0+incompatible // indirect github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 // indirect github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546 // indirect @@ -209,8 +211,8 @@ require ( go.uber.org/goleak v1.2.1 // indirect go.uber.org/multierr v1.9.0 // indirect go.uber.org/zap v1.21.0 // indirect - go4.org/intern v0.0.0-20230205224052-192e9f60865c // indirect - go4.org/unsafe/assume-no-moving-gc v0.0.0-20230221090011-e4bae7ad2296 // indirect + go4.org/intern v0.0.0-20230525184215-6c62f75575cb // indirect + go4.org/unsafe/assume-no-moving-gc v0.0.0-20230525183740-e7c30c78aeb2 // indirect golang.org/x/crypto v0.11.0 // indirect golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect golang.org/x/mod v0.10.0 // indirect diff --git a/go.sum b/go.sum index b9cf44fb500..98ddc1df01f 100644 --- a/go.sum +++ b/go.sum @@ -549,6 +549,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dennwc/varint v1.0.0 h1:kGNFFSSw8ToIy3obO/kKr8U9GZYUAxQEVuix4zfDWzE= github.com/dennwc/varint v1.0.0/go.mod h1:hnItb35rvZvJrbTALZtY/iQfDs48JKRG1RPpgziApxA= +github.com/dgryski/go-metro v0.0.0-20200812162917-85c65e2d0165 h1:BS21ZUJ/B5X2UVUbczfmdWH7GapPWAhxcMsDnjJTU1E= +github.com/dgryski/go-metro v0.0.0-20200812162917-85c65e2d0165/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/dhui/dktest v0.3.16 h1:i6gq2YQEtcrjKbeJpBkWjE8MmLZPYllcjOFbTZuPDnw= @@ -1066,7 +1068,7 @@ github.com/opentracing-contrib/go-stdlib v1.0.0/go.mod h1:qtI1ogk+2JhVPIXVc6q+NH github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= -github.com/oracle/oci-go-sdk/v65 v65.13.0 h1:0+9ea5goYfhI3/MPfbIQU6yzHYWE6sCk6VuUepxk5Nk= +github.com/oracle/oci-go-sdk/v65 v65.41.1 h1:+lbosOyNiib3TGJDvLq1HwEAuFqkOjPJDIkyxM15WdQ= github.com/ovh/go-ovh v1.4.1 h1:VBGa5wMyQtTP7Zb+w97zRCh9sLtM/2YKRyy+MEJmWaM= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= @@ -1150,6 +1152,8 @@ github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUt github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/segmentio/fasthash v1.0.3 h1:EI9+KE1EwvMLBWwjpRDc+fEM+prwxDYbslddQGtrmhM= github.com/segmentio/fasthash v1.0.3/go.mod h1:waKX8l2N8yckOgmSsXJi7x1ZfdKZ4x7KRMzBtS3oedY= +github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb h1:XfLJSPIOUX+osiMraVgIrMR27uMXnRJWGm1+GL8/63U= +github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb/go.mod h1:bR6DqgcAl1zTcOX8/pE2Qkj9XO00eCNqmKb7lXP8EAg= github.com/sercand/kuberesolver/v4 v4.0.0 h1:frL7laPDG/lFm5n98ODmWnn+cvPpzlkf3LhzuPhcHP4= github.com/sercand/kuberesolver/v4 v4.0.0/go.mod h1:F4RGyuRmMAjeXHKL+w4P7AwUnPceEAPAhxUgXZjKgvM= github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 h1:bUGsEnyNbVPw06Bs80sCeARAlK8lhwqGyi6UT8ymuGk= @@ -1202,12 +1206,12 @@ github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNG github.com/tencentyun/cos-go-sdk-v5 v0.7.40 h1:W6vDGKCHe4wBACI1d2UgE6+50sJFhRWU4O8IB2ozzxM= github.com/thanos-community/galaxycache v0.0.0-20211122094458-3a32041a1f1e h1:f1Zsv7OAU9iQhZwigp50Yl38W10g/vd5NC8Rdk1Jzng= github.com/thanos-community/galaxycache v0.0.0-20211122094458-3a32041a1f1e/go.mod h1:jXcofnrSln/cLI6/dhlBxPQZEEQHVPCcFaH75M+nSzM= -github.com/thanos-io/objstore v0.0.0-20230721074820-89475d4508df h1:QEQsto338hS1gvB904Pr6gE0RRM7kIcvIu2YF8Dsqks= -github.com/thanos-io/objstore v0.0.0-20230721074820-89475d4508df/go.mod h1:IS7Z25+0KaknyU2P5PTP/5hwY6Yr/FzbInF88Yd5auU= -github.com/thanos-io/promql-engine v0.0.0-20230526105742-791d78b260ea h1:kzK8sBn2+mo3NAxP+XjAjAqr1hwfxxFUy5CybaBkjAI= -github.com/thanos-io/promql-engine v0.0.0-20230526105742-791d78b260ea/go.mod h1:eIgPaXWgOhNAv6CPPrgu09r0AtT7byBTZy+7WkX0D18= -github.com/thanos-io/thanos v0.31.1-0.20230809185825-46339760e526 h1:QpAdI+mFTgZ1UUviL7Wzxi+h45LZEoxErHQHdYFb+Z4= -github.com/thanos-io/thanos v0.31.1-0.20230809185825-46339760e526/go.mod h1:4MiWDaeClW8CSHiOR57bnuUOID3HDYQphMthOPwtpJY= +github.com/thanos-io/objstore v0.0.0-20230804084840-c042a6a16c58 h1:4cDXsvm3mb1NvW1B1qJ9/fy6h+OOYit0h8oVA957hLM= +github.com/thanos-io/objstore v0.0.0-20230804084840-c042a6a16c58/go.mod h1:oJ82xgcBDzGJrEgUsjlTj6n01+ZWUMMUR8BlZzX5xDE= +github.com/thanos-io/promql-engine v0.0.0-20230816062837-c64fc7b373db h1:05Tp4pfeTTJlRnwLtgvXCJvKYeZCRBoxwDFC+uYqGyM= +github.com/thanos-io/promql-engine v0.0.0-20230816062837-c64fc7b373db/go.mod h1:eIgPaXWgOhNAv6CPPrgu09r0AtT7byBTZy+7WkX0D18= +github.com/thanos-io/thanos v0.0.0-20230816172224-2b4f2a7061f9 h1:KuVECxBG1Q8WoYWlY8dk1wi3OtPSSxv+tWPV9S9qGFk= +github.com/thanos-io/thanos v0.0.0-20230816172224-2b4f2a7061f9/go.mod h1:zfpzKCtqaqCy1D9/6ksZfL+U+KKt8mkcX6v3btuDHgg= github.com/themihai/gomemcache v0.0.0-20180902122335-24332e2d58ab h1:7ZR3hmisBWw77ZpO1/o86g+JV3VKlk3d48jopJxzTjU= github.com/themihai/gomemcache v0.0.0-20180902122335-24332e2d58ab/go.mod h1:eheTFp954zcWZXCU8d0AT76ftsQOTo4DTqkN/h3k1MY= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= @@ -1312,11 +1316,10 @@ go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8= go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= -go4.org/intern v0.0.0-20230205224052-192e9f60865c h1:b8WZ7Ja8nKegYxfwDLLwT00ZKv4lXAQrw8LYPK+cHSI= -go4.org/intern v0.0.0-20230205224052-192e9f60865c/go.mod h1:RJ0SVrOMpxLhgb5noIV+09zI1RsRlMsbUcSxpWHqbrE= -go4.org/unsafe/assume-no-moving-gc v0.0.0-20230204201903-c31fa085b70e/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E= -go4.org/unsafe/assume-no-moving-gc v0.0.0-20230221090011-e4bae7ad2296 h1:QJ/xcIANMLApehfgPCHnfK1hZiaMmbaTVmPv7DAoTbo= -go4.org/unsafe/assume-no-moving-gc v0.0.0-20230221090011-e4bae7ad2296/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E= +go4.org/intern v0.0.0-20230525184215-6c62f75575cb h1:ae7kzL5Cfdmcecbh22ll7lYP3iuUdnfnhiPcSaDgH/8= +go4.org/intern v0.0.0-20230525184215-6c62f75575cb/go.mod h1:Ycrt6raEcnF5FTsLiLKkhBTO6DPX3RCUCUVnks3gFJU= +go4.org/unsafe/assume-no-moving-gc v0.0.0-20230525183740-e7c30c78aeb2 h1:WJhcL4p+YeDxmZWg141nRm7XC8IDmhz7lk5GpadO1Sg= +go4.org/unsafe/assume-no-moving-gc v0.0.0-20230525183740-e7c30c78aeb2/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= diff --git a/pkg/querier/tripperware/test_shard_by_query_utils.go b/pkg/querier/tripperware/test_shard_by_query_utils.go index 14907063596..657d7daa3a1 100644 --- a/pkg/querier/tripperware/test_shard_by_query_utils.go +++ b/pkg/querier/tripperware/test_shard_by_query_utils.go @@ -45,18 +45,6 @@ func TestQueryShardQuery(t *testing.T, instantQueryCodec Codec, shardedPrometheu name: "outer aggregation with without grouping", expression: "count(sum without (pod) (http_requests_total))", }, - { - name: "aggregate expression with label_replace", - expression: `sum by (pod) (label_replace(metric, "dst_label", "$1", "src_label", "re"))`, - }, - { - name: "aggregate without expression with label_replace", - expression: `sum without (pod) (label_replace(metric, "dst_label", "$1", "src_label", "re"))`, - }, - { - name: "binary expression", - expression: `http_requests_total{code="400"} / http_requests_total`, - }, { name: "binary expression with constant", expression: `http_requests_total{code="400"} / 4`, @@ -69,10 +57,6 @@ func TestQueryShardQuery(t *testing.T, instantQueryCodec Codec, shardedPrometheu name: "binary aggregation with different grouping labels", expression: `sum by (pod) (http_requests_total{code="400"}) / sum by (cluster) (http_requests_total)`, }, - { - name: "multiple binary expressions", - expression: `(http_requests_total{code="400"} + http_requests_total{code="500"}) / http_requests_total`, - }, { name: "multiple binary expressions with empty vector matchers", expression: ` @@ -193,6 +177,11 @@ sum by (container) ( expression: `sort_desc(avg(label_replace(label_replace(label_replace(count_over_time(container_memory_working_set_bytes{container!="", container!="POD", instance!="", }[1h] ), "node", "$1", "instance", "(.+)"), "container_name", "$1", "container", "(.+)"), "pod_name", "$1", "pod", "(.+)")*label_replace(label_replace(label_replace(avg_over_time(container_memory_working_set_bytes{container!="", container!="POD", instance!="", }[1h] ), "node", "$1", "instance", "(.+)"), "container_name", "$1", "container", "(.+)"), "pod_name", "$1", "pod", "(.+)")) by (namespace, container_name, pod_name, node, cluster_id))`, shardingLabels: []string{"namespace", "cluster_id"}, }, + { + name: "aggregate expression with label_replace", + expression: `sum by (pod) (label_replace(metric, "dst_label", "$1", "src_label", "re"))`, + shardingLabels: []string{"pod"}, + }, } // Shardable by labels instant queries with matrix response @@ -233,7 +222,7 @@ sum by (container) ( { name: "binary expression with outer without grouping", expression: `sum(http_requests_total{code="400"} * http_requests_total) without (pod)`, - shardingLabels: []string{"pod"}, + shardingLabels: []string{model.MetricNameLabel, "pod"}, }, { name: "binary expression with vector matching and outer without grouping", @@ -268,6 +257,26 @@ http_requests_total`, expression: `sum without (pod) (label_replace(metric, "dst_label", "$1", "src_label", "re"))`, shardingLabels: []string{"pod", "dst_label"}, }, + { + name: "binary expression", + expression: `http_requests_total{code="400"} / http_requests_total`, + shardingLabels: []string{model.MetricNameLabel}, + }, + { + name: "binary expression among vector and scalar", + expression: `aaaa - bbb > 1000`, + shardingLabels: []string{model.MetricNameLabel}, + }, + { + name: "binary expression with set operation", + expression: `aaaa and bbb`, + shardingLabels: []string{model.MetricNameLabel}, + }, + { + name: "multiple binary expressions", + expression: `(http_requests_total{code="400"} + http_requests_total{code="500"}) / http_requests_total`, + shardingLabels: []string{model.MetricNameLabel}, + }, } type testCase struct { @@ -324,6 +333,7 @@ http_requests_total`, name: fmt.Sprintf("non shardable query: %s", query.name), path: fmt.Sprintf(`/api/v1/query?time=120&query=%s`, url.QueryEscape(query.expression)), codec: instantQueryCodec, + shardSize: 2, isShardable: false, responses: []string{ `{"status":"success","data":{"resultType":"vector","result":[{"metric":{"__name__":"up","job":"foo"},"value":[1,"1"]}],"stats":{"samples":{"totalQueryableSamples":10,"totalQueryableSamplesPerStep":[[1,10]]}}}}`, @@ -334,6 +344,7 @@ http_requests_total`, name: fmt.Sprintf("non shardable query_range: %s", query.name), path: fmt.Sprintf(`/api/v1/query_range?start=1&end=2&step=1&query=%s`, url.QueryEscape(query.expression)), codec: shardedPrometheusCodec, + shardSize: 2, isShardable: false, responses: []string{ `{"status":"success","data":{"resultType":"matrix","result":[{"metric":{"__job__":"a","__name__":"metric"},"values":[[1,"1"],[2,"2"],[3,"3"]]}],"stats":{"samples":{"totalQueryableSamples":6,"totalQueryableSamplesPerStep":[[1,1],[2,2],[3,3]]}}}}`, diff --git a/vendor/github.com/dgryski/go-metro/LICENSE b/vendor/github.com/dgryski/go-metro/LICENSE new file mode 100644 index 00000000000..6243b617cfc --- /dev/null +++ b/vendor/github.com/dgryski/go-metro/LICENSE @@ -0,0 +1,24 @@ +This package is a mechanical translation of the reference C++ code for +MetroHash, available at https://github.com/jandrewrogers/MetroHash + +The MIT License (MIT) + +Copyright (c) 2016 Damian Gryski + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/dgryski/go-metro/README b/vendor/github.com/dgryski/go-metro/README new file mode 100644 index 00000000000..5ecebb3853f --- /dev/null +++ b/vendor/github.com/dgryski/go-metro/README @@ -0,0 +1,6 @@ +MetroHash + +This package is a mechanical translation of the reference C++ code for +MetroHash, available at https://github.com/jandrewrogers/MetroHash + +I claim no additional copyright over the original implementation. diff --git a/vendor/github.com/dgryski/go-metro/metro.py b/vendor/github.com/dgryski/go-metro/metro.py new file mode 100644 index 00000000000..8dd4d26e6ad --- /dev/null +++ b/vendor/github.com/dgryski/go-metro/metro.py @@ -0,0 +1,199 @@ +import peachpy.x86_64 + +k0 = 0xD6D018F5 +k1 = 0xA2AA033B +k2 = 0x62992FC1 +k3 = 0x30BC5B29 + +def advance(p,l,c): + ADD(p,c) + SUB(l,c) + +def imul(r,k): + t = GeneralPurposeRegister64() + MOV(t, k) + IMUL(r, t) + +def update32(v, p,idx, k, vadd): + r = GeneralPurposeRegister64() + MOV(r, [p + idx]) + imul(r, k) + ADD(v, r) + ROR(v, 29) + ADD(v, vadd) + +def final32(v, regs, keys): + r = GeneralPurposeRegister64() + MOV(r, v[regs[1]]) + ADD(r, v[regs[2]]) + imul(r, keys[0]) + ADD(r, v[regs[3]]) + ROR(r, 37) + imul(r, keys[1]) + XOR(v[regs[0]], r) + +seed = Argument(uint64_t) +buffer_base = Argument(ptr()) +buffer_len = Argument(int64_t) +buffer_cap = Argument(int64_t) + +def makeHash(name, args): + with Function(name, args, uint64_t) as function: + + reg_ptr = GeneralPurposeRegister64() + reg_ptr_len = GeneralPurposeRegister64() + reg_hash = GeneralPurposeRegister64() + + LOAD.ARGUMENT(reg_hash, seed) + LOAD.ARGUMENT(reg_ptr, buffer_base) + LOAD.ARGUMENT(reg_ptr_len, buffer_len) + + imul(reg_hash, k0) + r = GeneralPurposeRegister64() + MOV(r, k2*k0) + ADD(reg_hash, r) + + after32 = Label("after32") + + CMP(reg_ptr_len, 32) + JL(after32) + v = [GeneralPurposeRegister64() for _ in range(4)] + for i in range(4): + MOV(v[i], reg_hash) + + with Loop() as loop: + update32(v[0], reg_ptr, 0, k0, v[2]) + update32(v[1], reg_ptr, 8, k1, v[3]) + update32(v[2], reg_ptr, 16, k2, v[0]) + update32(v[3], reg_ptr, 24, k3, v[1]) + + ADD(reg_ptr, 32) + SUB(reg_ptr_len, 32) + CMP(reg_ptr_len, 32) + JGE(loop.begin) + + final32(v, [2,0,3,1], [k0, k1]) + final32(v, [3,1,2,0], [k1, k0]) + final32(v, [0,0,2,3], [k0, k1]) + final32(v, [1,1,3,2], [k1, k0]) + + XOR(v[0], v[1]) + ADD(reg_hash, v[0]) + + LABEL(after32) + + after16 = Label("after16") + CMP(reg_ptr_len, 16) + JL(after16) + + for i in range(2): + MOV(v[i], [reg_ptr]) + imul(v[i], k2) + ADD(v[i], reg_hash) + + advance(reg_ptr, reg_ptr_len, 8) + + ROR(v[i], 29) + imul(v[i], k3) + + r = GeneralPurposeRegister64() + MOV(r, v[0]) + imul(r, k0) + ROR(r, 21) + ADD(r, v[1]) + XOR(v[0], r) + + MOV(r, v[1]) + imul(r, k3) + ROR(r, 21) + ADD(r, v[0]) + XOR(v[1], r) + + ADD(reg_hash, v[1]) + + LABEL(after16) + + after8 = Label("after8") + CMP(reg_ptr_len, 8) + JL(after8) + + r = GeneralPurposeRegister64() + MOV(r, [reg_ptr]) + imul(r, k3) + ADD(reg_hash, r) + advance(reg_ptr, reg_ptr_len, 8) + + MOV(r, reg_hash) + ROR(r, 55) + imul(r, k1) + XOR(reg_hash, r) + + LABEL(after8) + + after4 = Label("after4") + CMP(reg_ptr_len, 4) + JL(after4) + + r = GeneralPurposeRegister64() + XOR(r, r) + MOV(r.as_dword, dword[reg_ptr]) + imul(r, k3) + ADD(reg_hash, r) + advance(reg_ptr, reg_ptr_len, 4) + + MOV(r, reg_hash) + ROR(r, 26) + imul(r, k1) + XOR(reg_hash, r) + + LABEL(after4) + + after2 = Label("after2") + CMP(reg_ptr_len, 2) + JL(after2) + + r = GeneralPurposeRegister64() + XOR(r,r) + MOV(r.as_word, word[reg_ptr]) + imul(r, k3) + ADD(reg_hash, r) + advance(reg_ptr, reg_ptr_len, 2) + + MOV(r, reg_hash) + ROR(r, 48) + imul(r, k1) + XOR(reg_hash, r) + + LABEL(after2) + + after1 = Label("after1") + CMP(reg_ptr_len, 1) + JL(after1) + + r = GeneralPurposeRegister64() + MOVZX(r, byte[reg_ptr]) + imul(r, k3) + ADD(reg_hash, r) + + MOV(r, reg_hash) + ROR(r, 37) + imul(r, k1) + XOR(reg_hash, r) + + LABEL(after1) + + r = GeneralPurposeRegister64() + MOV(r, reg_hash) + ROR(r, 28) + XOR(reg_hash, r) + + imul(reg_hash, k0) + + MOV(r, reg_hash) + ROR(r, 29) + XOR(reg_hash, r) + + RETURN(reg_hash) + +makeHash("Hash64", (buffer_base, buffer_len, buffer_cap, seed)) +makeHash("Hash64Str", (buffer_base, buffer_len, seed)) \ No newline at end of file diff --git a/vendor/github.com/dgryski/go-metro/metro128.go b/vendor/github.com/dgryski/go-metro/metro128.go new file mode 100644 index 00000000000..e8dd8ddbf54 --- /dev/null +++ b/vendor/github.com/dgryski/go-metro/metro128.go @@ -0,0 +1,94 @@ +package metro + +import "encoding/binary" + +func rotate_right(v uint64, k uint) uint64 { + return (v >> k) | (v << (64 - k)) +} + +func Hash128(buffer []byte, seed uint64) (uint64, uint64) { + + const ( + k0 = 0xC83A91E1 + k1 = 0x8648DBDB + k2 = 0x7BDEC03B + k3 = 0x2F5870A5 + ) + + ptr := buffer + + var v [4]uint64 + + v[0] = (seed - k0) * k3 + v[1] = (seed + k1) * k2 + + if len(ptr) >= 32 { + v[2] = (seed + k0) * k2 + v[3] = (seed - k1) * k3 + + for len(ptr) >= 32 { + v[0] += binary.LittleEndian.Uint64(ptr) * k0 + ptr = ptr[8:] + v[0] = rotate_right(v[0], 29) + v[2] + v[1] += binary.LittleEndian.Uint64(ptr) * k1 + ptr = ptr[8:] + v[1] = rotate_right(v[1], 29) + v[3] + v[2] += binary.LittleEndian.Uint64(ptr) * k2 + ptr = ptr[8:] + v[2] = rotate_right(v[2], 29) + v[0] + v[3] += binary.LittleEndian.Uint64(ptr) * k3 + ptr = ptr[8:] + v[3] = rotate_right(v[3], 29) + v[1] + } + + v[2] ^= rotate_right(((v[0]+v[3])*k0)+v[1], 21) * k1 + v[3] ^= rotate_right(((v[1]+v[2])*k1)+v[0], 21) * k0 + v[0] ^= rotate_right(((v[0]+v[2])*k0)+v[3], 21) * k1 + v[1] ^= rotate_right(((v[1]+v[3])*k1)+v[2], 21) * k0 + } + + if len(ptr) >= 16 { + v[0] += binary.LittleEndian.Uint64(ptr) * k2 + ptr = ptr[8:] + v[0] = rotate_right(v[0], 33) * k3 + v[1] += binary.LittleEndian.Uint64(ptr) * k2 + ptr = ptr[8:] + v[1] = rotate_right(v[1], 33) * k3 + v[0] ^= rotate_right((v[0]*k2)+v[1], 45) * k1 + v[1] ^= rotate_right((v[1]*k3)+v[0], 45) * k0 + } + + if len(ptr) >= 8 { + v[0] += binary.LittleEndian.Uint64(ptr) * k2 + ptr = ptr[8:] + v[0] = rotate_right(v[0], 33) * k3 + v[0] ^= rotate_right((v[0]*k2)+v[1], 27) * k1 + } + + if len(ptr) >= 4 { + v[1] += uint64(binary.LittleEndian.Uint32(ptr)) * k2 + ptr = ptr[4:] + v[1] = rotate_right(v[1], 33) * k3 + v[1] ^= rotate_right((v[1]*k3)+v[0], 46) * k0 + } + + if len(ptr) >= 2 { + v[0] += uint64(binary.LittleEndian.Uint16(ptr)) * k2 + ptr = ptr[2:] + v[0] = rotate_right(v[0], 33) * k3 + v[0] ^= rotate_right((v[0]*k2)+v[1], 22) * k1 + } + + if len(ptr) >= 1 { + v[1] += uint64(ptr[0]) * k2 + v[1] = rotate_right(v[1], 33) * k3 + v[1] ^= rotate_right((v[1]*k3)+v[0], 58) * k0 + } + + v[0] += rotate_right((v[0]*k0)+v[1], 13) + v[1] += rotate_right((v[1]*k1)+v[0], 37) + v[0] += rotate_right((v[0]*k2)+v[1], 13) + v[1] += rotate_right((v[1]*k3)+v[0], 37) + + return v[0], v[1] +} diff --git a/vendor/github.com/dgryski/go-metro/metro64.go b/vendor/github.com/dgryski/go-metro/metro64.go new file mode 100644 index 00000000000..1c04228a0bd --- /dev/null +++ b/vendor/github.com/dgryski/go-metro/metro64.go @@ -0,0 +1,88 @@ +// +build noasm !amd64 gccgo + +package metro + +import ( + "encoding/binary" + "math/bits" +) + +func Hash64(buffer []byte, seed uint64) uint64 { + + const ( + k0 = 0xD6D018F5 + k1 = 0xA2AA033B + k2 = 0x62992FC1 + k3 = 0x30BC5B29 + ) + + ptr := buffer + + hash := (seed + k2) * k0 + + if len(ptr) >= 32 { + v0, v1, v2, v3 := hash, hash, hash, hash + + for len(ptr) >= 32 { + v0 += binary.LittleEndian.Uint64(ptr[:8]) * k0 + v0 = bits.RotateLeft64(v0, -29) + v2 + v1 += binary.LittleEndian.Uint64(ptr[8:16]) * k1 + v1 = bits.RotateLeft64(v1, -29) + v3 + v2 += binary.LittleEndian.Uint64(ptr[16:24]) * k2 + v2 = bits.RotateLeft64(v2, -29) + v0 + v3 += binary.LittleEndian.Uint64(ptr[24:32]) * k3 + v3 = bits.RotateLeft64(v3, -29) + v1 + ptr = ptr[32:] + } + + v2 ^= bits.RotateLeft64(((v0+v3)*k0)+v1, -37) * k1 + v3 ^= bits.RotateLeft64(((v1+v2)*k1)+v0, -37) * k0 + v0 ^= bits.RotateLeft64(((v0+v2)*k0)+v3, -37) * k1 + v1 ^= bits.RotateLeft64(((v1+v3)*k1)+v2, -37) * k0 + hash += v0 ^ v1 + } + + if len(ptr) >= 16 { + v0 := hash + (binary.LittleEndian.Uint64(ptr[:8]) * k2) + v0 = bits.RotateLeft64(v0, -29) * k3 + v1 := hash + (binary.LittleEndian.Uint64(ptr[8:16]) * k2) + v1 = bits.RotateLeft64(v1, -29) * k3 + v0 ^= bits.RotateLeft64(v0*k0, -21) + v1 + v1 ^= bits.RotateLeft64(v1*k3, -21) + v0 + hash += v1 + ptr = ptr[16:] + } + + if len(ptr) >= 8 { + hash += binary.LittleEndian.Uint64(ptr[:8]) * k3 + ptr = ptr[8:] + hash ^= bits.RotateLeft64(hash, -55) * k1 + } + + if len(ptr) >= 4 { + hash += uint64(binary.LittleEndian.Uint32(ptr[:4])) * k3 + hash ^= bits.RotateLeft64(hash, -26) * k1 + ptr = ptr[4:] + } + + if len(ptr) >= 2 { + hash += uint64(binary.LittleEndian.Uint16(ptr[:2])) * k3 + ptr = ptr[2:] + hash ^= bits.RotateLeft64(hash, -48) * k1 + } + + if len(ptr) >= 1 { + hash += uint64(ptr[0]) * k3 + hash ^= bits.RotateLeft64(hash, -37) * k1 + } + + hash ^= bits.RotateLeft64(hash, -28) + hash *= k0 + hash ^= bits.RotateLeft64(hash, -29) + + return hash +} + +func Hash64Str(buffer string, seed uint64) uint64 { + return Hash64([]byte(buffer), seed) +} diff --git a/vendor/github.com/dgryski/go-metro/metro_amd64.s b/vendor/github.com/dgryski/go-metro/metro_amd64.s new file mode 100644 index 00000000000..7fa4730a487 --- /dev/null +++ b/vendor/github.com/dgryski/go-metro/metro_amd64.s @@ -0,0 +1,372 @@ +// +build !noasm +// +build !gccgo + +// Generated by PeachPy 0.2.0 from metro.py + +// func Hash64(buffer_base uintptr, buffer_len int64, buffer_cap int64, seed uint64) uint64 +TEXT ·Hash64(SB),4,$0-40 + MOVQ seed+24(FP), AX + MOVQ buffer_base+0(FP), BX + MOVQ buffer_len+8(FP), CX + MOVQ $3603962101, DX + IMULQ DX, AX + MOVQ $5961697176435608501, DX + ADDQ DX, AX + CMPQ CX, $32 + JLT after32 + MOVQ AX, DX + MOVQ AX, DI + MOVQ AX, SI + MOVQ AX, BP +loop_begin: + MOVQ 0(BX), R8 + MOVQ $3603962101, R9 + IMULQ R9, R8 + ADDQ R8, DX + RORQ $29, DX + ADDQ SI, DX + MOVQ 8(BX), R8 + MOVQ $2729050939, R9 + IMULQ R9, R8 + ADDQ R8, DI + RORQ $29, DI + ADDQ BP, DI + MOVQ 16(BX), R8 + MOVQ $1654206401, R9 + IMULQ R9, R8 + ADDQ R8, SI + RORQ $29, SI + ADDQ DX, SI + MOVQ 24(BX), R8 + MOVQ $817650473, R9 + IMULQ R9, R8 + ADDQ R8, BP + RORQ $29, BP + ADDQ DI, BP + ADDQ $32, BX + SUBQ $32, CX + CMPQ CX, $32 + JGE loop_begin + MOVQ DX, R8 + ADDQ BP, R8 + MOVQ $3603962101, R9 + IMULQ R9, R8 + ADDQ DI, R8 + RORQ $37, R8 + MOVQ $2729050939, R9 + IMULQ R9, R8 + XORQ R8, SI + MOVQ DI, R8 + ADDQ SI, R8 + MOVQ $2729050939, R9 + IMULQ R9, R8 + ADDQ DX, R8 + RORQ $37, R8 + MOVQ $3603962101, R9 + IMULQ R9, R8 + XORQ R8, BP + MOVQ DX, R8 + ADDQ SI, R8 + MOVQ $3603962101, R9 + IMULQ R9, R8 + ADDQ BP, R8 + RORQ $37, R8 + MOVQ $2729050939, R9 + IMULQ R9, R8 + XORQ R8, DX + MOVQ DI, R8 + ADDQ BP, R8 + MOVQ $2729050939, BP + IMULQ BP, R8 + ADDQ SI, R8 + RORQ $37, R8 + MOVQ $3603962101, SI + IMULQ SI, R8 + XORQ R8, DI + XORQ DI, DX + ADDQ DX, AX +after32: + CMPQ CX, $16 + JLT after16 + MOVQ 0(BX), DX + MOVQ $1654206401, DI + IMULQ DI, DX + ADDQ AX, DX + ADDQ $8, BX + SUBQ $8, CX + RORQ $29, DX + MOVQ $817650473, DI + IMULQ DI, DX + MOVQ 0(BX), DI + MOVQ $1654206401, SI + IMULQ SI, DI + ADDQ AX, DI + ADDQ $8, BX + SUBQ $8, CX + RORQ $29, DI + MOVQ $817650473, SI + IMULQ SI, DI + MOVQ DX, SI + MOVQ $3603962101, BP + IMULQ BP, SI + RORQ $21, SI + ADDQ DI, SI + XORQ SI, DX + MOVQ DI, SI + MOVQ $817650473, BP + IMULQ BP, SI + RORQ $21, SI + ADDQ DX, SI + XORQ SI, DI + ADDQ DI, AX +after16: + CMPQ CX, $8 + JLT after8 + MOVQ 0(BX), DX + MOVQ $817650473, DI + IMULQ DI, DX + ADDQ DX, AX + ADDQ $8, BX + SUBQ $8, CX + MOVQ AX, DX + RORQ $55, DX + MOVQ $2729050939, DI + IMULQ DI, DX + XORQ DX, AX +after8: + CMPQ CX, $4 + JLT after4 + XORQ DX, DX + MOVL 0(BX), DX + MOVQ $817650473, DI + IMULQ DI, DX + ADDQ DX, AX + ADDQ $4, BX + SUBQ $4, CX + MOVQ AX, DX + RORQ $26, DX + MOVQ $2729050939, DI + IMULQ DI, DX + XORQ DX, AX +after4: + CMPQ CX, $2 + JLT after2 + XORQ DX, DX + MOVW 0(BX), DX + MOVQ $817650473, DI + IMULQ DI, DX + ADDQ DX, AX + ADDQ $2, BX + SUBQ $2, CX + MOVQ AX, DX + RORQ $48, DX + MOVQ $2729050939, DI + IMULQ DI, DX + XORQ DX, AX +after2: + CMPQ CX, $1 + JLT after1 + MOVBQZX 0(BX), BX + MOVQ $817650473, CX + IMULQ CX, BX + ADDQ BX, AX + MOVQ AX, BX + RORQ $37, BX + MOVQ $2729050939, CX + IMULQ CX, BX + XORQ BX, AX +after1: + MOVQ AX, BX + RORQ $28, BX + XORQ BX, AX + MOVQ $3603962101, BX + IMULQ BX, AX + MOVQ AX, BX + RORQ $29, BX + XORQ BX, AX + MOVQ AX, ret+32(FP) + RET + +// func Hash64Str(buffer_base uintptr, buffer_len int64, seed uint64) uint64 +TEXT ·Hash64Str(SB),4,$0-32 + MOVQ seed+16(FP), AX + MOVQ buffer_base+0(FP), BX + MOVQ buffer_len+8(FP), CX + MOVQ $3603962101, DX + IMULQ DX, AX + MOVQ $5961697176435608501, DX + ADDQ DX, AX + CMPQ CX, $32 + JLT after32 + MOVQ AX, DX + MOVQ AX, DI + MOVQ AX, SI + MOVQ AX, BP +loop_begin: + MOVQ 0(BX), R8 + MOVQ $3603962101, R9 + IMULQ R9, R8 + ADDQ R8, DX + RORQ $29, DX + ADDQ SI, DX + MOVQ 8(BX), R8 + MOVQ $2729050939, R9 + IMULQ R9, R8 + ADDQ R8, DI + RORQ $29, DI + ADDQ BP, DI + MOVQ 16(BX), R8 + MOVQ $1654206401, R9 + IMULQ R9, R8 + ADDQ R8, SI + RORQ $29, SI + ADDQ DX, SI + MOVQ 24(BX), R8 + MOVQ $817650473, R9 + IMULQ R9, R8 + ADDQ R8, BP + RORQ $29, BP + ADDQ DI, BP + ADDQ $32, BX + SUBQ $32, CX + CMPQ CX, $32 + JGE loop_begin + MOVQ DX, R8 + ADDQ BP, R8 + MOVQ $3603962101, R9 + IMULQ R9, R8 + ADDQ DI, R8 + RORQ $37, R8 + MOVQ $2729050939, R9 + IMULQ R9, R8 + XORQ R8, SI + MOVQ DI, R8 + ADDQ SI, R8 + MOVQ $2729050939, R9 + IMULQ R9, R8 + ADDQ DX, R8 + RORQ $37, R8 + MOVQ $3603962101, R9 + IMULQ R9, R8 + XORQ R8, BP + MOVQ DX, R8 + ADDQ SI, R8 + MOVQ $3603962101, R9 + IMULQ R9, R8 + ADDQ BP, R8 + RORQ $37, R8 + MOVQ $2729050939, R9 + IMULQ R9, R8 + XORQ R8, DX + MOVQ DI, R8 + ADDQ BP, R8 + MOVQ $2729050939, BP + IMULQ BP, R8 + ADDQ SI, R8 + RORQ $37, R8 + MOVQ $3603962101, SI + IMULQ SI, R8 + XORQ R8, DI + XORQ DI, DX + ADDQ DX, AX +after32: + CMPQ CX, $16 + JLT after16 + MOVQ 0(BX), DX + MOVQ $1654206401, DI + IMULQ DI, DX + ADDQ AX, DX + ADDQ $8, BX + SUBQ $8, CX + RORQ $29, DX + MOVQ $817650473, DI + IMULQ DI, DX + MOVQ 0(BX), DI + MOVQ $1654206401, SI + IMULQ SI, DI + ADDQ AX, DI + ADDQ $8, BX + SUBQ $8, CX + RORQ $29, DI + MOVQ $817650473, SI + IMULQ SI, DI + MOVQ DX, SI + MOVQ $3603962101, BP + IMULQ BP, SI + RORQ $21, SI + ADDQ DI, SI + XORQ SI, DX + MOVQ DI, SI + MOVQ $817650473, BP + IMULQ BP, SI + RORQ $21, SI + ADDQ DX, SI + XORQ SI, DI + ADDQ DI, AX +after16: + CMPQ CX, $8 + JLT after8 + MOVQ 0(BX), DX + MOVQ $817650473, DI + IMULQ DI, DX + ADDQ DX, AX + ADDQ $8, BX + SUBQ $8, CX + MOVQ AX, DX + RORQ $55, DX + MOVQ $2729050939, DI + IMULQ DI, DX + XORQ DX, AX +after8: + CMPQ CX, $4 + JLT after4 + XORQ DX, DX + MOVL 0(BX), DX + MOVQ $817650473, DI + IMULQ DI, DX + ADDQ DX, AX + ADDQ $4, BX + SUBQ $4, CX + MOVQ AX, DX + RORQ $26, DX + MOVQ $2729050939, DI + IMULQ DI, DX + XORQ DX, AX +after4: + CMPQ CX, $2 + JLT after2 + XORQ DX, DX + MOVW 0(BX), DX + MOVQ $817650473, DI + IMULQ DI, DX + ADDQ DX, AX + ADDQ $2, BX + SUBQ $2, CX + MOVQ AX, DX + RORQ $48, DX + MOVQ $2729050939, DI + IMULQ DI, DX + XORQ DX, AX +after2: + CMPQ CX, $1 + JLT after1 + MOVBQZX 0(BX), BX + MOVQ $817650473, CX + IMULQ CX, BX + ADDQ BX, AX + MOVQ AX, BX + RORQ $37, BX + MOVQ $2729050939, CX + IMULQ CX, BX + XORQ BX, AX +after1: + MOVQ AX, BX + RORQ $28, BX + XORQ BX, AX + MOVQ $3603962101, BX + IMULQ BX, AX + MOVQ AX, BX + RORQ $29, BX + XORQ BX, AX + MOVQ AX, ret+24(FP) + RET diff --git a/vendor/github.com/dgryski/go-metro/metro_stub.go b/vendor/github.com/dgryski/go-metro/metro_stub.go new file mode 100644 index 00000000000..86ddcb47051 --- /dev/null +++ b/vendor/github.com/dgryski/go-metro/metro_stub.go @@ -0,0 +1,10 @@ +// +build !noasm,amd64 +// +build !gccgo + +package metro + +//go:generate python -m peachpy.x86_64 metro.py -S -o metro_amd64.s -mabi=goasm +//go:noescape + +func Hash64(buffer []byte, seed uint64) uint64 +func Hash64Str(buffer string, seed uint64) uint64 diff --git a/vendor/github.com/seiflotfy/cuckoofilter/.gitignore b/vendor/github.com/seiflotfy/cuckoofilter/.gitignore new file mode 100644 index 00000000000..11b90db8d96 --- /dev/null +++ b/vendor/github.com/seiflotfy/cuckoofilter/.gitignore @@ -0,0 +1,26 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof + +.idea diff --git a/vendor/github.com/seiflotfy/cuckoofilter/LICENSE b/vendor/github.com/seiflotfy/cuckoofilter/LICENSE new file mode 100644 index 00000000000..58393c98c1e --- /dev/null +++ b/vendor/github.com/seiflotfy/cuckoofilter/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 Seif Lotfy + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/vendor/github.com/seiflotfy/cuckoofilter/README.md b/vendor/github.com/seiflotfy/cuckoofilter/README.md new file mode 100644 index 00000000000..2a77fb393f4 --- /dev/null +++ b/vendor/github.com/seiflotfy/cuckoofilter/README.md @@ -0,0 +1,62 @@ +# Cuckoo Filter + +[![GoDoc](https://godoc.org/github.com/seiflotfy/cuckoofilter?status.svg)](https://godoc.org/github.com/seiflotfy/cuckoofilter) [![CodeHunt.io](https://img.shields.io/badge/vote-codehunt.io-02AFD1.svg)](http://codehunt.io/sub/cuckoo-filter/?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) + +Cuckoo filter is a Bloom filter replacement for approximated set-membership queries. While Bloom filters are well-known space-efficient data structures to serve queries like "if item x is in a set?", they do not support deletion. Their variances to enable deletion (like counting Bloom filters) usually require much more space. + +Cuckoo filters provide the flexibility to add and remove items dynamically. A cuckoo filter is based on cuckoo hashing (and therefore named as cuckoo filter). It is essentially a cuckoo hash table storing each key's fingerprint. Cuckoo hash tables can be highly compact, thus a cuckoo filter could use less space than conventional Bloom filters, for applications that require low false positive rates (< 3%). + +For details about the algorithm and citations please use this article for now + +["Cuckoo Filter: Better Than Bloom" by Bin Fan, Dave Andersen and Michael Kaminsky](https://www.cs.cmu.edu/~dga/papers/cuckoo-conext2014.pdf) + +## Implementation details + +The paper cited above leaves several parameters to choose. In this implementation + +1. Every element has 2 possible bucket indices +2. Buckets have a static size of 4 fingerprints +3. Fingerprints have a static size of 8 bits + +1 and 2 are suggested to be the optimum by the authors. The choice of 3 comes down to the desired false positive rate. Given a target false positive rate of `r` and a bucket size `b`, they suggest choosing the fingerprint size `f` using + + f >= log2(2b/r) bits + +With the 8 bit fingerprint size in this repository, you can expect `r ~= 0.03`. +[Other implementations](https://github.com/panmari/cuckoofilter) use 16 bit, which correspond to a false positive rate of `r ~= 0.0001`. + +## Example usage: +```go +package main + +import "fmt" +import cuckoo "github.com/seiflotfy/cuckoofilter" + +func main() { + cf := cuckoo.NewFilter(1000) + cf.InsertUnique([]byte("geeky ogre")) + + // Lookup a string (and it a miss) if it exists in the cuckoofilter + cf.Lookup([]byte("hello")) + + count := cf.Count() + fmt.Println(count) // count == 1 + + // Delete a string (and it a miss) + cf.Delete([]byte("hello")) + + count = cf.Count() + fmt.Println(count) // count == 1 + + // Delete a string (a hit) + cf.Delete([]byte("geeky ogre")) + + count = cf.Count() + fmt.Println(count) // count == 0 + + cf.Reset() // reset +} +``` + +## Documentation: +["Cuckoo Filter on GoDoc"](http://godoc.org/github.com/seiflotfy/cuckoofilter) diff --git a/vendor/github.com/seiflotfy/cuckoofilter/bucket.go b/vendor/github.com/seiflotfy/cuckoofilter/bucket.go new file mode 100644 index 00000000000..4a83fc50308 --- /dev/null +++ b/vendor/github.com/seiflotfy/cuckoofilter/bucket.go @@ -0,0 +1,45 @@ +package cuckoo + +type fingerprint byte + +type bucket [bucketSize]fingerprint + +const ( + nullFp = 0 + bucketSize = 4 +) + +func (b *bucket) insert(fp fingerprint) bool { + for i, tfp := range b { + if tfp == nullFp { + b[i] = fp + return true + } + } + return false +} + +func (b *bucket) delete(fp fingerprint) bool { + for i, tfp := range b { + if tfp == fp { + b[i] = nullFp + return true + } + } + return false +} + +func (b *bucket) getFingerprintIndex(fp fingerprint) int { + for i, tfp := range b { + if tfp == fp { + return i + } + } + return -1 +} + +func (b *bucket) reset() { + for i := range b { + b[i] = nullFp + } +} diff --git a/vendor/github.com/seiflotfy/cuckoofilter/cuckoofilter.go b/vendor/github.com/seiflotfy/cuckoofilter/cuckoofilter.go new file mode 100644 index 00000000000..ec0d246de28 --- /dev/null +++ b/vendor/github.com/seiflotfy/cuckoofilter/cuckoofilter.go @@ -0,0 +1,165 @@ +package cuckoo + +import ( + "fmt" + "math/bits" + "math/rand" +) + +const maxCuckooCount = 500 + +// Filter is a probabilistic counter +type Filter struct { + buckets []bucket + count uint + bucketPow uint +} + +// NewFilter returns a new cuckoofilter with a given capacity. +// A capacity of 1000000 is a normal default, which allocates +// about ~1MB on 64-bit machines. +func NewFilter(capacity uint) *Filter { + capacity = getNextPow2(uint64(capacity)) / bucketSize + if capacity == 0 { + capacity = 1 + } + buckets := make([]bucket, capacity) + return &Filter{ + buckets: buckets, + count: 0, + bucketPow: uint(bits.TrailingZeros(capacity)), + } +} + +// Lookup returns true if data is in the counter +func (cf *Filter) Lookup(data []byte) bool { + i1, fp := getIndexAndFingerprint(data, cf.bucketPow) + if cf.buckets[i1].getFingerprintIndex(fp) > -1 { + return true + } + i2 := getAltIndex(fp, i1, cf.bucketPow) + return cf.buckets[i2].getFingerprintIndex(fp) > -1 +} + +// Reset ... +func (cf *Filter) Reset() { + for i := range cf.buckets { + cf.buckets[i].reset() + } + cf.count = 0 +} + +func randi(i1, i2 uint) uint { + if rand.Intn(2) == 0 { + return i1 + } + return i2 +} + +// Insert inserts data into the counter and returns true upon success +func (cf *Filter) Insert(data []byte) bool { + i1, fp := getIndexAndFingerprint(data, cf.bucketPow) + if cf.insert(fp, i1) { + return true + } + i2 := getAltIndex(fp, i1, cf.bucketPow) + if cf.insert(fp, i2) { + return true + } + return cf.reinsert(fp, randi(i1, i2)) +} + +// InsertUnique inserts data into the counter if not exists and returns true upon success +func (cf *Filter) InsertUnique(data []byte) bool { + if cf.Lookup(data) { + return false + } + return cf.Insert(data) +} + +func (cf *Filter) insert(fp fingerprint, i uint) bool { + if cf.buckets[i].insert(fp) { + cf.count++ + return true + } + return false +} + +func (cf *Filter) reinsert(fp fingerprint, i uint) bool { + for k := 0; k < maxCuckooCount; k++ { + j := rand.Intn(bucketSize) + oldfp := fp + fp = cf.buckets[i][j] + cf.buckets[i][j] = oldfp + + // look in the alternate location for that random element + i = getAltIndex(fp, i, cf.bucketPow) + if cf.insert(fp, i) { + return true + } + } + return false +} + +// Delete data from counter if exists and return if deleted or not +func (cf *Filter) Delete(data []byte) bool { + i1, fp := getIndexAndFingerprint(data, cf.bucketPow) + if cf.delete(fp, i1) { + return true + } + i2 := getAltIndex(fp, i1, cf.bucketPow) + return cf.delete(fp, i2) +} + +func (cf *Filter) delete(fp fingerprint, i uint) bool { + if cf.buckets[i].delete(fp) { + if cf.count > 0 { + cf.count-- + } + return true + } + return false +} + +// Count returns the number of items in the counter +func (cf *Filter) Count() uint { + return cf.count +} + +// Encode returns a byte slice representing a Cuckoofilter +func (cf *Filter) Encode() []byte { + bytes := make([]byte, len(cf.buckets)*bucketSize) + for i, b := range cf.buckets { + for j, f := range b { + index := (i * len(b)) + j + bytes[index] = byte(f) + } + } + return bytes +} + +// Decode returns a Cuckoofilter from a byte slice +func Decode(bytes []byte) (*Filter, error) { + var count uint + if len(bytes)%bucketSize != 0 { + return nil, fmt.Errorf("expected bytes to be multiple of %d, got %d", bucketSize, len(bytes)) + } + if len(bytes) == 0 { + return nil, fmt.Errorf("bytes can not be empty") + } + buckets := make([]bucket, len(bytes)/4) + for i, b := range buckets { + for j := range b { + index := (i * len(b)) + j + if bytes[index] != 0 { + buckets[i][j] = fingerprint(bytes[index]) + count++ + } + } + } + return &Filter{ + buckets: buckets, + count: count, + bucketPow: uint(bits.TrailingZeros(uint(len(buckets)))), + }, nil +} diff --git a/vendor/github.com/seiflotfy/cuckoofilter/doc.go b/vendor/github.com/seiflotfy/cuckoofilter/doc.go new file mode 100644 index 00000000000..6f6cbf8281d --- /dev/null +++ b/vendor/github.com/seiflotfy/cuckoofilter/doc.go @@ -0,0 +1,35 @@ +/* +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +/* +Package cuckoo provides a Cuckoo Filter, a Bloom filter replacement for approximated set-membership queries. + +While Bloom filters are well-known space-efficient data structures to serve queries like "if item x is in a set?", they do not support deletion. Their variances to enable deletion (like counting Bloom filters) usually require much more space. + +Cuckoo filters provide the flexibility to add and remove items dynamically. A cuckoo filter is based on cuckoo hashing (and therefore named as cuckoo filter). It is essentially a cuckoo hash table storing each key's fingerprint. Cuckoo hash tables can be highly compact, thus a cuckoo filter could use less space than conventional Bloom filters, for applications that require low false positive rates (< 3%). + +For details about the algorithm and citations please use this article: + +"Cuckoo Filter: Better Than Bloom" by Bin Fan, Dave Andersen and Michael Kaminsky +(https://www.cs.cmu.edu/~dga/papers/cuckoo-conext2014.pdf) + +Note: +This implementation uses a a static bucket size of 4 fingerprints and a fingerprint size of 1 byte based on my understanding of an optimal bucket/fingerprint/size ratio from the aforementioned paper.*/ +package cuckoo diff --git a/vendor/github.com/seiflotfy/cuckoofilter/scalable_cuckoofilter.go b/vendor/github.com/seiflotfy/cuckoofilter/scalable_cuckoofilter.go new file mode 100644 index 00000000000..693184c9d41 --- /dev/null +++ b/vendor/github.com/seiflotfy/cuckoofilter/scalable_cuckoofilter.go @@ -0,0 +1,170 @@ +package cuckoo + +import ( + "bytes" + "encoding/gob" +) + +const ( + DefaultLoadFactor = 0.9 + DefaultCapacity = 10000 +) + +type ScalableCuckooFilter struct { + filters []*Filter + loadFactor float32 + //when scale(last filter size * loadFactor >= capacity) get new filter capacity + scaleFactor func(capacity uint) uint +} + +type option func(*ScalableCuckooFilter) + +type Store struct { + Bytes [][]byte + LoadFactor float32 +} + +/* + by default option the grow capacity is: + capacity , total + 4096 4096 + 8192 12288 +16384 28672 +32768 61440 +65536 126,976 +*/ +func NewScalableCuckooFilter(opts ...option) *ScalableCuckooFilter { + sfilter := new(ScalableCuckooFilter) + for _, opt := range opts { + opt(sfilter) + } + configure(sfilter) + return sfilter +} + +func (sf *ScalableCuckooFilter) Lookup(data []byte) bool { + for _, filter := range sf.filters { + if filter.Lookup(data) { + return true + } + } + return false +} + +func (sf *ScalableCuckooFilter) Reset() { + for _, filter := range sf.filters { + filter.Reset() + } +} + +func (sf *ScalableCuckooFilter) Insert(data []byte) bool { + needScale := false + lastFilter := sf.filters[len(sf.filters)-1] + if (float32(lastFilter.count) / float32(len(lastFilter.buckets))) > sf.loadFactor { + needScale = true + } else { + b := lastFilter.Insert(data) + needScale = !b + } + if !needScale { + return true + } + newFilter := NewFilter(sf.scaleFactor(uint(len(lastFilter.buckets)))) + sf.filters = append(sf.filters, newFilter) + return newFilter.Insert(data) +} + +func (sf *ScalableCuckooFilter) InsertUnique(data []byte) bool { + if sf.Lookup(data) { + return false + } + return sf.Insert(data) +} + +func (sf *ScalableCuckooFilter) Delete(data []byte) bool { + for _, filter := range sf.filters { + if filter.Delete(data) { + return true + } + } + return false +} + +func (sf *ScalableCuckooFilter) Count() uint { + var sum uint + for _, filter := range sf.filters { + sum += filter.count + } + return sum + +} + +func (sf *ScalableCuckooFilter) Encode() []byte { + slice := make([][]byte, len(sf.filters)) + for i, filter := range sf.filters { + encode := filter.Encode() + slice[i] = encode + } + store := &Store{ + Bytes: slice, + LoadFactor: sf.loadFactor, + } + buf := bytes.NewBuffer(nil) + enc := gob.NewEncoder(buf) + err := enc.Encode(store) + if err != nil { + return nil + } + return buf.Bytes() +} + +func (sf *ScalableCuckooFilter) DecodeWithParam(fBytes []byte, opts ...option) (*ScalableCuckooFilter, error) { + instance, err := DecodeScalableFilter(fBytes) + if err != nil { + return nil, err + } + for _, opt := range opts { + opt(instance) + } + return instance, nil +} + +func DecodeScalableFilter(fBytes []byte) (*ScalableCuckooFilter, error) { + buf := bytes.NewBuffer(fBytes) + dec := gob.NewDecoder(buf) + store := &Store{} + err := dec.Decode(store) + if err != nil { + return nil, err + } + filterSize := len(store.Bytes) + instance := NewScalableCuckooFilter(func(filter *ScalableCuckooFilter) { + filter.filters = make([]*Filter, filterSize) + }, func(filter *ScalableCuckooFilter) { + filter.loadFactor = store.LoadFactor + }) + for i, oneBytes := range store.Bytes { + filter, err := Decode(oneBytes) + if err != nil { + return nil, err + } + instance.filters[i] = filter + } + return instance, nil + +} + +func configure(sfilter *ScalableCuckooFilter) { + if sfilter.loadFactor == 0 { + sfilter.loadFactor = DefaultLoadFactor + } + if sfilter.scaleFactor == nil { + sfilter.scaleFactor = func(currentSize uint) uint { + return currentSize * bucketSize * 2 + } + } + if sfilter.filters == nil { + initFilter := NewFilter(DefaultCapacity) + sfilter.filters = []*Filter{initFilter} + } +} diff --git a/vendor/github.com/seiflotfy/cuckoofilter/util.go b/vendor/github.com/seiflotfy/cuckoofilter/util.go new file mode 100644 index 00000000000..2a0f65b1301 --- /dev/null +++ b/vendor/github.com/seiflotfy/cuckoofilter/util.go @@ -0,0 +1,52 @@ +package cuckoo + +import ( + metro "github.com/dgryski/go-metro" +) + +var ( + altHash = [256]uint{} + masks = [65]uint{} +) + +func init() { + for i := 0; i < 256; i++ { + altHash[i] = (uint(metro.Hash64([]byte{byte(i)}, 1337))) + } + for i := uint(0); i <= 64; i++ { + masks[i] = (1 << i) - 1 + } +} + +func getAltIndex(fp fingerprint, i uint, bucketPow uint) uint { + mask := masks[bucketPow] + hash := altHash[fp] & mask + return (i & mask) ^ hash +} + +func getFingerprint(hash uint64) byte { + // Use least significant bits for fingerprint. + fp := byte(hash%255 + 1) + return fp +} + +// getIndicesAndFingerprint returns the 2 bucket indices and fingerprint to be used +func getIndexAndFingerprint(data []byte, bucketPow uint) (uint, fingerprint) { + hash := metro.Hash64(data, 1337) + fp := getFingerprint(hash) + // Use most significant bits for deriving index. + i1 := uint(hash>>32) & masks[bucketPow] + return i1, fingerprint(fp) +} + +func getNextPow2(n uint64) uint { + n-- + n |= n >> 1 + n |= n >> 2 + n |= n >> 4 + n |= n >> 8 + n |= n >> 16 + n |= n >> 32 + n++ + return uint(n) +} diff --git a/vendor/github.com/thanos-io/objstore/CHANGELOG.md b/vendor/github.com/thanos-io/objstore/CHANGELOG.md index 564faa91860..84b2cccd270 100644 --- a/vendor/github.com/thanos-io/objstore/CHANGELOG.md +++ b/vendor/github.com/thanos-io/objstore/CHANGELOG.md @@ -27,11 +27,13 @@ We use *breaking :warning:* to mark changes that are not backward compatible (re - [#61](https://github.com/thanos-io/objstore/pull/61) Add OpenTelemetry TracingBucket. > This also changes the behaviour of `client.NewBucket`. Now it returns, uninstrumented and untraced bucket. You can combine `objstore.WrapWithMetrics` and `tracing/{opentelemetry,opentracing}.WrapWithTraces` to have old behavior. +- [#64](https://github.com/thanos-io/objstore/pull/64) OCI: OKE Workload Identity support. ### Changed - [#38](https://github.com/thanos-io/objstore/pull/38) *: Upgrade minio-go version to `v7.0.45`. - [#39](https://github.com/thanos-io/objstore/pull/39) COS: Upgrade cos sdk version to `v0.7.40`. - [#35](https://github.com/thanos-io/objstore/pull/35) Azure: Update Azure SDK and fix breaking changes. - [#65](https://github.com/thanos-io/objstore/pull/65) *: Upgrade minio-go version to `v7.0.61`. +- [#70](https://github.com/thanos-io/objstore/pull/70) GCS: Update cloud.google.com/go/storage version to `v1.27.0`. ### Removed diff --git a/vendor/github.com/thanos-io/objstore/README.md b/vendor/github.com/thanos-io/objstore/README.md index c738889478b..11b773a48a8 100644 --- a/vendor/github.com/thanos-io/objstore/README.md +++ b/vendor/github.com/thanos-io/objstore/README.md @@ -578,7 +578,7 @@ prefix: "" ### Oracle Cloud Infrastructure Object Storage -To configure Oracle Cloud Infrastructure (OCI) Object Storage as Thanos Object Store, you need to provide appropriate authentication credentials to your OCI tenancy. The OCI object storage client implementation for Thanos supports either the default keypair or instance principal authentication. +To configure Oracle Cloud Infrastructure (OCI) Object Storage as a Thanos Object Store, you need to provide appropriate authentication credentials to your OCI tenancy. The OCI object storage client implementation for Thanos supports default keypair, instance principal, and OKE workload identity authentication. #### API Signing Key @@ -642,6 +642,20 @@ config: You can also include any of the optional configuration just like the example in `Default Provider`. +#### OKE Workload Identity Provider + +For Example: + +```yaml +type: OCI +config: + provider: "oke-workload-identity" + bucket: "" + region: "" +``` + +The `bucket` and `region` fields are required. The `region` field identifies the bucket region. + ##### HuaweiCloud OBS To use HuaweiCloud OBS as an object store, you should apply for a HuaweiCloud Account to create an object storage bucket at first. More details: [HuaweiCloud OBS](https://support.huaweicloud.com/obs/index.html) diff --git a/vendor/github.com/thanos-io/objstore/objstore.go b/vendor/github.com/thanos-io/objstore/objstore.go index d7d04888465..61e3dfb4ff5 100644 --- a/vendor/github.com/thanos-io/objstore/objstore.go +++ b/vendor/github.com/thanos-io/objstore/objstore.go @@ -424,6 +424,13 @@ func WrapWithMetrics(b Bucket, reg prometheus.Registerer, name string) *metricBu ConstLabels: prometheus.Labels{"bucket": name}, }, []string{"operation"}), + opsTransferredBytes: promauto.With(reg).NewHistogramVec(prometheus.HistogramOpts{ + Name: "objstore_bucket_operation_transferred_bytes", + Help: "Number of bytes transferred from/to bucket per operation.", + ConstLabels: prometheus.Labels{"bucket": name}, + Buckets: prometheus.ExponentialBuckets(2<<14, 2, 16), // 32KiB, 64KiB, ... 1GiB + }, []string{"operation"}), + opsDuration: promauto.With(reg).NewHistogramVec(prometheus.HistogramOpts{ Name: "objstore_bucket_operation_duration_seconds", Help: "Duration of successful operations against the bucket", @@ -431,10 +438,11 @@ func WrapWithMetrics(b Bucket, reg prometheus.Registerer, name string) *metricBu Buckets: []float64{0.001, 0.01, 0.1, 0.3, 0.6, 1, 3, 6, 9, 20, 30, 60, 90, 120}, }, []string{"operation"}), - lastSuccessfulUploadTime: promauto.With(reg).NewGaugeVec(prometheus.GaugeOpts{ - Name: "objstore_bucket_last_successful_upload_time", - Help: "Second timestamp of the last successful upload to the bucket.", - }, []string{"bucket"}), + lastSuccessfulUploadTime: promauto.With(reg).NewGauge(prometheus.GaugeOpts{ + Name: "objstore_bucket_last_successful_upload_time", + Help: "Second timestamp of the last successful upload to the bucket.", + ConstLabels: prometheus.Labels{"bucket": name}, + }), } for _, op := range []string{ OpIter, @@ -450,7 +458,14 @@ func WrapWithMetrics(b Bucket, reg prometheus.Registerer, name string) *metricBu bkt.opsDuration.WithLabelValues(op) bkt.opsFetchedBytes.WithLabelValues(op) } - bkt.lastSuccessfulUploadTime.WithLabelValues(b.Name()) + // fetched bytes only relevant for get and getrange + for _, op := range []string{ + OpGet, + OpGetRange, + // TODO: Add uploads + } { + bkt.opsTransferredBytes.WithLabelValues(op) + } return bkt } @@ -461,10 +476,10 @@ type metricBucket struct { opsFailures *prometheus.CounterVec isOpFailureExpected IsOpFailureExpectedFunc - opsFetchedBytes *prometheus.CounterVec - + opsFetchedBytes *prometheus.CounterVec + opsTransferredBytes *prometheus.HistogramVec opsDuration *prometheus.HistogramVec - lastSuccessfulUploadTime *prometheus.GaugeVec + lastSuccessfulUploadTime prometheus.Gauge } func (b *metricBucket) WithExpectedErrs(fn IsOpFailureExpectedFunc) Bucket { @@ -473,6 +488,7 @@ func (b *metricBucket) WithExpectedErrs(fn IsOpFailureExpectedFunc) Bucket { ops: b.ops, opsFailures: b.opsFailures, opsFetchedBytes: b.opsFetchedBytes, + opsTransferredBytes: b.opsTransferredBytes, isOpFailureExpected: fn, opsDuration: b.opsDuration, lastSuccessfulUploadTime: b.lastSuccessfulUploadTime, @@ -530,6 +546,7 @@ func (b *metricBucket) Get(ctx context.Context, name string) (io.ReadCloser, err b.opsFailures, b.isOpFailureExpected, b.opsFetchedBytes, + b.opsTransferredBytes, ), nil } @@ -551,6 +568,7 @@ func (b *metricBucket) GetRange(ctx context.Context, name string, off, length in b.opsFailures, b.isOpFailureExpected, b.opsFetchedBytes, + b.opsTransferredBytes, ), nil } @@ -581,7 +599,7 @@ func (b *metricBucket) Upload(ctx context.Context, name string, r io.Reader) err } return err } - b.lastSuccessfulUploadTime.WithLabelValues(b.bkt.Name()).SetToCurrentTime() + b.lastSuccessfulUploadTime.SetToCurrentTime() b.opsDuration.WithLabelValues(op).Observe(time.Since(start).Seconds()) return nil } @@ -627,13 +645,15 @@ type timingReadCloser struct { start time.Time op string + readBytes int64 duration *prometheus.HistogramVec failed *prometheus.CounterVec isFailureExpected IsOpFailureExpectedFunc fetchedBytes *prometheus.CounterVec + transferredBytes *prometheus.HistogramVec } -func newTimingReadCloser(rc io.ReadCloser, op string, dur *prometheus.HistogramVec, failed *prometheus.CounterVec, isFailureExpected IsOpFailureExpectedFunc, fetchedBytes *prometheus.CounterVec) *timingReadCloser { +func newTimingReadCloser(rc io.ReadCloser, op string, dur *prometheus.HistogramVec, failed *prometheus.CounterVec, isFailureExpected IsOpFailureExpectedFunc, fetchedBytes *prometheus.CounterVec, transferredBytes *prometheus.HistogramVec) *timingReadCloser { // Initialize the metrics with 0. dur.WithLabelValues(op) failed.WithLabelValues(op) @@ -648,6 +668,8 @@ func newTimingReadCloser(rc io.ReadCloser, op string, dur *prometheus.HistogramV failed: failed, isFailureExpected: isFailureExpected, fetchedBytes: fetchedBytes, + transferredBytes: transferredBytes, + readBytes: 0, } } @@ -662,6 +684,7 @@ func (rc *timingReadCloser) Close() error { } if !rc.alreadyGotErr && err == nil { rc.duration.WithLabelValues(rc.op).Observe(time.Since(rc.start).Seconds()) + rc.transferredBytes.WithLabelValues(rc.op).Observe(float64(rc.readBytes)) rc.alreadyGotErr = true } return err @@ -670,6 +693,7 @@ func (rc *timingReadCloser) Close() error { func (rc *timingReadCloser) Read(b []byte) (n int, err error) { n, err = rc.ReadCloser.Read(b) rc.fetchedBytes.WithLabelValues(rc.op).Add(float64(n)) + rc.readBytes += int64(n) // Report metric just once. if !rc.alreadyGotErr && err != nil && err != io.EOF { if !rc.isFailureExpected(err) { diff --git a/vendor/github.com/thanos-io/promql-engine/engine/engine.go b/vendor/github.com/thanos-io/promql-engine/engine/engine.go index f8130ca4774..12858ba6635 100644 --- a/vendor/github.com/thanos-io/promql-engine/engine/engine.go +++ b/vendor/github.com/thanos-io/promql-engine/engine/engine.go @@ -5,10 +5,12 @@ package engine import ( "context" + "io" "math" "runtime" "sort" + "strconv" "time" "github.com/cespare/xxhash/v2" @@ -28,6 +30,7 @@ import ( "github.com/thanos-io/promql-engine/execution" "github.com/thanos-io/promql-engine/execution/model" "github.com/thanos-io/promql-engine/execution/parse" + "github.com/thanos-io/promql-engine/execution/warnings" "github.com/thanos-io/promql-engine/logicalplan" "github.com/thanos-io/promql-engine/parser" ) @@ -71,6 +74,9 @@ type Opts struct { // FallbackEngine Engine v1.QueryEngine + + // EnableAnalysis enables query analysis. + EnableAnalysis bool } func (o Opts) getLogicalOptimizers() []logicalplan.Optimizer { @@ -169,9 +175,9 @@ func New(opts Opts) *compatibilityEngine { } if opts.EnableXFunctions { - parser.Functions["xdelta"] = parse.Functions["xdelta"] - parser.Functions["xincrease"] = parse.Functions["xincrease"] - parser.Functions["xrate"] = parse.Functions["xrate"] + parser.Functions["xdelta"] = parse.XFunctions["xdelta"] + parser.Functions["xincrease"] = parse.XFunctions["xincrease"] + parser.Functions["xrate"] = parse.XFunctions["xrate"] } metrics := &engineMetrics{ @@ -211,6 +217,7 @@ func New(opts Opts) *compatibilityEngine { timeout: opts.Timeout, metrics: metrics, extLookbackDelta: opts.ExtLookbackDelta, + enableAnalysis: opts.EnableAnalysis, } } @@ -227,6 +234,7 @@ type compatibilityEngine struct { metrics *engineMetrics extLookbackDelta time.Duration + enableAnalysis bool } func (e *compatibilityEngine) SetQueryLogger(l promql.QueryLogger) { @@ -260,7 +268,7 @@ func (e *compatibilityEngine) NewInstantQuery(ctx context.Context, q storage.Que }) lplan = lplan.Optimize(e.logicalOptimizers) - exec, err := execution.New(ctx, lplan.Expr(), q, ts, ts, 0, opts.LookbackDelta, e.extLookbackDelta) + exec, err := execution.New(ctx, lplan.Expr(), q, ts, ts, 0, opts.LookbackDelta, e.extLookbackDelta, e.enableAnalysis) if e.triggerFallback(err) { e.metrics.queries.WithLabelValues("true").Inc() return e.prom.NewInstantQuery(ctx, q, opts, qs, ts) @@ -275,12 +283,13 @@ func (e *compatibilityEngine) NewInstantQuery(ctx context.Context, q storage.Que } return &compatibilityQuery{ - Query: &Query{exec: exec, opts: opts}, - engine: e, - expr: expr, - ts: ts, - t: InstantQuery, - resultSort: resultSort, + Query: &Query{exec: exec, opts: opts}, + engine: e, + expr: expr, + ts: ts, + t: InstantQuery, + resultSort: resultSort, + debugWriter: e.debugWriter, }, nil } @@ -311,7 +320,7 @@ func (e *compatibilityEngine) NewRangeQuery(ctx context.Context, q storage.Query }) lplan = lplan.Optimize(e.logicalOptimizers) - exec, err := execution.New(ctx, lplan.Expr(), q, start, end, step, opts.LookbackDelta, e.extLookbackDelta) + exec, err := execution.New(ctx, lplan.Expr(), q, start, end, step, opts.LookbackDelta, e.extLookbackDelta, e.enableAnalysis) if e.triggerFallback(err) { e.metrics.queries.WithLabelValues("true").Inc() return e.prom.NewRangeQuery(ctx, q, opts, qs, start, end, step) @@ -326,10 +335,11 @@ func (e *compatibilityEngine) NewRangeQuery(ctx context.Context, q storage.Query } return &compatibilityQuery{ - Query: &Query{exec: exec, opts: opts}, - engine: e, - expr: expr, - t: RangeQuery, + Query: &Query{exec: exec, opts: opts}, + engine: e, + expr: expr, + t: RangeQuery, + debugWriter: e.debugWriter, }, nil } @@ -337,7 +347,12 @@ type ExplainableQuery interface { promql.Query Explain() *ExplainOutputNode - Profile() + Analyze() *AnalyzeOutputNode +} + +type AnalyzeOutputNode struct { + OperatorTelemetry model.OperatorTelemetry `json:"telemetry,omitempty"` + Children []AnalyzeOutputNode `json:"children,omitempty"` } type ExplainOutputNode struct { @@ -358,8 +373,25 @@ func (q *Query) Explain() *ExplainOutputNode { return explainVector(q.exec) } -func (q *Query) Profile() { - // TODO(bwplotka): Return profile. +func (q *Query) Analyze() *AnalyzeOutputNode { + if observableRoot, ok := q.exec.(model.ObservableVectorOperator); ok { + return analyzeVector(observableRoot) + } + return nil +} + +func analyzeVector(obsv model.ObservableVectorOperator) *AnalyzeOutputNode { + telemetry, obsVectors := obsv.Analyze() + + var children []AnalyzeOutputNode + for _, vector := range obsVectors { + children = append(children, *analyzeVector(vector)) + } + + return &AnalyzeOutputNode{ + OperatorTelemetry: telemetry, + Children: children, + } } func explainVector(v model.VectorOperator) *ExplainOutputNode { @@ -479,12 +511,25 @@ type compatibilityQuery struct { resultSort resultSorter cancel context.CancelFunc + + debugWriter io.Writer } func (q *compatibilityQuery) Exec(ctx context.Context) (ret *promql.Result) { + ctx = warnings.NewContext(ctx) + defer func() { + warns := warnings.FromContext(ctx) + if len(warns) > 0 { + ret.Warnings = warns + } + }() + // Handle case with strings early on as this does not need us to process samples. switch e := q.expr.(type) { case *parser.StringLiteral: + if q.debugWriter != nil { + analyze(q.debugWriter, q.exec.(model.ObservableVectorOperator), " ", "") + } return &promql.Result{Value: promql.String{V: e.Val, T: q.ts.UnixMilli()}} } ret = &promql.Result{ @@ -567,6 +612,9 @@ loop: } sort.Sort(resultMatrix) ret.Value = resultMatrix + if q.debugWriter != nil { + analyze(q.debugWriter, q.exec.(model.ObservableVectorOperator), "", "") + } return ret } @@ -688,6 +736,26 @@ func recoverEngine(logger log.Logger, expr parser.Expr, errp *error) { } } +func analyze(w io.Writer, o model.ObservableVectorOperator, indent, indentNext string) { + telemetry, next := o.Analyze() + _, _ = w.Write([]byte(indent)) + _, _ = w.Write([]byte("Operator Time :")) + _, _ = w.Write([]byte(strconv.FormatInt(int64(telemetry.ExecutionTimeTaken()), 10))) + if len(next) == 0 { + _, _ = w.Write([]byte("\n")) + return + } + _, _ = w.Write([]byte(":\n")) + + for i, n := range next { + if i == len(next)-1 { + analyze(w, n, indentNext+"└──", indentNext+" ") + } else { + analyze(w, n, indentNext+"└──", indentNext+" ") + } + } +} + func explain(w io.Writer, o model.VectorOperator, indent, indentNext string) { me, next := o.Explain() _, _ = w.Write([]byte(indent)) diff --git a/vendor/github.com/thanos-io/promql-engine/execution/aggregate/hashaggregate.go b/vendor/github.com/thanos-io/promql-engine/execution/aggregate/hashaggregate.go index e0010839520..9d207dd7884 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/aggregate/hashaggregate.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/aggregate/hashaggregate.go @@ -8,6 +8,7 @@ import ( "fmt" "math" "sync" + "time" "github.com/efficientgo/core/errors" "github.com/prometheus/prometheus/model/labels" @@ -37,6 +38,7 @@ type aggregate struct { newAccumulator newAccumulatorFunc stepsBatch int workers worker.Group + model.OperatorTelemetry } func NewHashAggregate( @@ -68,18 +70,29 @@ func NewHashAggregate( newAccumulator: newAccumulator, } a.workers = worker.NewGroup(stepsBatch, a.workerTask) + a.OperatorTelemetry = &model.TrackedTelemetry{} return a, nil } +func (a *aggregate) Analyze() (model.OperatorTelemetry, []model.ObservableVectorOperator) { + a.SetName("[*aggregate]") + var ops []model.ObservableVectorOperator + if obsnextParamOp, ok := a.paramOp.(model.ObservableVectorOperator); ok { + ops = append(ops, obsnextParamOp) + } + if obsnext, ok := a.next.(model.ObservableVectorOperator); ok { + ops = append(ops, obsnext) + } + return a, ops +} + func (a *aggregate) Explain() (me string, next []model.VectorOperator) { var ops []model.VectorOperator - if a.paramOp != nil { ops = append(ops, a.paramOp) } ops = append(ops, a.next) - if a.by { return fmt.Sprintf("[*aggregate] %v by (%v)", a.aggregation.String(), a.labels), ops } @@ -106,7 +119,7 @@ func (a *aggregate) Next(ctx context.Context) ([]model.StepVector, error) { return nil, ctx.Err() default: } - + start := time.Now() in, err := a.next.Next(ctx) if err != nil { return nil, err @@ -151,7 +164,7 @@ func (a *aggregate) Next(ctx context.Context) ([]model.StepVector, error) { result = append(result, output) a.next.GetPool().PutStepVector(vector) } - + a.AddExecutionTimeTaken(time.Since(start)) return result, nil } @@ -172,6 +185,7 @@ func (a *aggregate) initializeTables(ctx context.Context) error { } a.tables = tables a.series = series + a.vectorPool.SetStepSize(len(a.series)) a.workers.Start(ctx) return nil @@ -201,13 +215,24 @@ func (a *aggregate) initializeScalarTables(ctx context.Context) ([]aggregateTabl if err != nil { return nil, nil, err } - - inputCache := make([]uint64, len(series)) - outputMap := make(map[uint64]*model.Series) - outputCache := make([]*model.Series, 0) - buf := make([]byte, 1024) + var ( + // inputCache is an index from input seriesID to output seriesID. + inputCache = make([]uint64, len(series)) + // outputMap is used to map from the hash of an input series to an output series. + outputMap = make(map[uint64]*model.Series) + // outputCache is an index from output seriesID to output series. + outputCache = make([]*model.Series, 0) + // hashingBuf is a reusable buffer for hashing input series. + hashingBuf = make([]byte, 1024) + // builder is a reusable labels builder for output series. + builder labels.ScratchBuilder + ) + labelsMap := make(map[string]struct{}) + for _, lblName := range a.labels { + labelsMap[lblName] = struct{}{} + } for i := 0; i < len(series); i++ { - hash, _, lbls := hashMetric(series[i], !a.by, a.labels, buf) + hash, _, lbls := hashMetric(builder, series[i], !a.by, a.labels, labelsMap, hashingBuf) output, ok := outputMap[hash] if !ok { output = &model.Series{ @@ -220,7 +245,6 @@ func (a *aggregate) initializeScalarTables(ctx context.Context) ([]aggregateTabl inputCache[i] = output.ID } - a.vectorPool.SetStepSize(len(outputCache)) tables := newScalarTables(a.stepsBatch, inputCache, outputCache, a.newAccumulator) series = make([]labels.Labels, len(outputCache)) diff --git a/vendor/github.com/thanos-io/promql-engine/execution/aggregate/khashaggregate.go b/vendor/github.com/thanos-io/promql-engine/execution/aggregate/khashaggregate.go index be7c19dba4e..d1bada91e78 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/aggregate/khashaggregate.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/aggregate/khashaggregate.go @@ -10,6 +10,7 @@ import ( "math" "sort" "sync" + "time" "github.com/efficientgo/core/errors" "github.com/prometheus/prometheus/model/labels" @@ -17,6 +18,7 @@ import ( "github.com/thanos-io/promql-engine/execution/model" "github.com/thanos-io/promql-engine/parser" + "github.com/thanos-io/promql-engine/query" ) type kAggregate struct { @@ -36,6 +38,7 @@ type kAggregate struct { inputToHeap []*samplesHeap heaps []*samplesHeap compare func(float64, float64) bool + model.OperatorTelemetry } func NewKHashAggregate( @@ -46,6 +49,7 @@ func NewKHashAggregate( by bool, labels []string, stepsBatch int, + opts *query.Options, ) (model.VectorOperator, error) { var compare func(float64, float64) bool @@ -72,7 +76,10 @@ func NewKHashAggregate( compare: compare, params: make([]float64, stepsBatch), } - + a.OperatorTelemetry = &model.NoopTelemetry{} + if opts.EnableAnalysis { + a.OperatorTelemetry = &model.TrackedTelemetry{} + } return a, nil } @@ -81,6 +88,7 @@ func (a *kAggregate) Next(ctx context.Context) ([]model.StepVector, error) { if err != nil { return nil, err } + start := time.Now() args, err := a.paramOp.Next(ctx) if err != nil { return nil, err @@ -120,6 +128,7 @@ func (a *kAggregate) Next(ctx context.Context) ([]model.StepVector, error) { a.next.GetPool().PutStepVector(vector) } a.next.GetPool().PutVectors(in) + a.AddExecutionTimeTaken(time.Since(start)) return result, nil } @@ -138,6 +147,18 @@ func (a *kAggregate) GetPool() *model.VectorPool { return a.vectorPool } +func (a *kAggregate) Analyze() (model.OperatorTelemetry, []model.ObservableVectorOperator) { + a.SetName("[*kaggregate]") + next := make([]model.ObservableVectorOperator, 0, 2) + if obsnextParamOp, ok := a.paramOp.(model.ObservableVectorOperator); ok { + next = append(next, obsnextParamOp) + } + if obsnext, ok := a.next.(model.ObservableVectorOperator); ok { + next = append(next, obsnext) + } + return a, next +} + func (a *kAggregate) Explain() (me string, next []model.VectorOperator) { if a.by { return fmt.Sprintf("[*kaggregate] %v by (%v)", a.aggregation.String(), a.labels), []model.VectorOperator{a.paramOp, a.next} @@ -150,14 +171,24 @@ func (a *kAggregate) init(ctx context.Context) error { if err != nil { return err } - hapsHash := make(map[uint64]*samplesHeap) - buf := make([]byte, 1024) + var ( + // heapsHash is a map of hash of the series to output samples heap for that series. + heapsHash = make(map[uint64]*samplesHeap) + // hashingBuf is a buffer used for metric hashing. + hashingBuf = make([]byte, 1024) + // builder is a scratch builder used for creating output series. + builder labels.ScratchBuilder + ) + labelsMap := make(map[string]struct{}) + for _, lblName := range a.labels { + labelsMap[lblName] = struct{}{} + } for i := 0; i < len(series); i++ { - hash, _, _ := hashMetric(series[i], !a.by, a.labels, buf) - h, ok := hapsHash[hash] + hash, _, _ := hashMetric(builder, series[i], !a.by, a.labels, labelsMap, hashingBuf) + h, ok := heapsHash[hash] if !ok { h = &samplesHeap{compare: a.compare} - hapsHash[hash] = h + heapsHash[hash] = h a.heaps = append(a.heaps, h) } a.inputToHeap = append(a.inputToHeap, h) @@ -170,7 +201,7 @@ func (a *kAggregate) init(ctx context.Context) error { func (a *kAggregate) aggregate(t int64, result *[]model.StepVector, k int, SampleIDs []uint64, samples []float64) { for i, sId := range SampleIDs { h := a.inputToHeap[sId] - if h.Len() < k || h.compare(h.entries[0].total, samples[i]) || math.IsNaN(h.entries[0].total) { + if h.Len() < k || h.compare(h.entries[0].total, samples[i]) || (math.IsNaN(h.entries[0].total) && !math.IsNaN(samples[i])) { if k == 1 && h.Len() == 1 { h.entries[0].sId = sId h.entries[0].total = samples[i] diff --git a/vendor/github.com/thanos-io/promql-engine/execution/aggregate/scalar_table.go b/vendor/github.com/thanos-io/promql-engine/execution/aggregate/scalar_table.go index 04d0ebc6fb5..cd6f09a11a2 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/aggregate/scalar_table.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/aggregate/scalar_table.go @@ -12,7 +12,6 @@ import ( "github.com/prometheus/prometheus/model/histogram" "github.com/prometheus/prometheus/model/labels" - "github.com/thanos-io/promql-engine/execution/function" "github.com/thanos-io/promql-engine/execution/model" "github.com/thanos-io/promql-engine/execution/parse" "github.com/thanos-io/promql-engine/parser" @@ -102,24 +101,43 @@ func (t *scalarTable) size() int { return len(t.outputs) } -func hashMetric(metric labels.Labels, without bool, grouping []string, buf []byte) (uint64, string, labels.Labels) { +func hashMetric( + builder labels.ScratchBuilder, + metric labels.Labels, + without bool, + grouping []string, + groupingSet map[string]struct{}, + buf []byte, +) (uint64, string, labels.Labels) { buf = buf[:0] + builder.Reset() + if without { - lb := labels.NewBuilder(metric) - lb.Del(grouping...) - lb.Del(labels.MetricName) + metric.Range(func(lbl labels.Label) { + if lbl.Name == labels.MetricName { + return + } + if _, ok := groupingSet[lbl.Name]; ok { + return + } + builder.Add(lbl.Name, lbl.Value) + }) key, bytes := metric.HashWithoutLabels(buf, grouping...) - return key, string(bytes), lb.Labels() + return key, string(bytes), builder.Labels() } if len(grouping) == 0 { return 0, "", labels.Labels{} } - lb := labels.NewBuilder(metric) - lb.Keep(grouping...) + metric.Range(func(lbl labels.Label) { + if _, ok := groupingSet[lbl.Name]; !ok { + return + } + builder.Add(lbl.Name, lbl.Value) + }) key, bytes := metric.HashForLabels(buf, grouping...) - return key, string(bytes), lb.Labels() + return key, string(bytes), builder.Labels() } type newAccumulatorFunc func() *accumulator @@ -279,45 +297,43 @@ func makeAccumulatorFunc(expr parser.ItemType) (newAccumulatorFunc, error) { case "stddev": return func() *accumulator { var count float64 - var mean, cMean float64 - var aux, cAux float64 + var mean float64 + var value float64 var hasValue bool return &accumulator{ AddFunc: func(v float64, _ *histogram.FloatHistogram) { hasValue = true count++ - delta := v - (mean + cMean) - mean, cMean = function.KahanSumInc(delta/count, mean, cMean) - aux, cAux = function.KahanSumInc(delta*(v-(mean+cMean)), aux, cAux) + delta := v - mean + mean += delta / count + value += delta * (v - mean) }, ValueFunc: func() (float64, *histogram.FloatHistogram) { if count == 1 { return 0, nil } - return math.Sqrt((aux + cAux) / count), nil + return math.Sqrt(value / count), nil }, HasValue: func() bool { return hasValue }, Reset: func(_ float64) { hasValue = false count = 0 mean = 0 - cMean = 0 - aux = 0 - cAux = 0 + value = 0 }, } }, nil case "stdvar": return func() *accumulator { var count float64 - var mean, cMean float64 + var mean float64 var value float64 var hasValue bool return &accumulator{ AddFunc: func(v float64, _ *histogram.FloatHistogram) { hasValue = true count++ - delta := v - (mean + cMean) + delta := v - mean mean += delta / count value = delta * (v - mean) }, @@ -332,7 +348,6 @@ func makeAccumulatorFunc(expr parser.ItemType) (newAccumulatorFunc, error) { hasValue = false count = 0 mean = 0 - cMean = 0 value = 0 }, } diff --git a/vendor/github.com/thanos-io/promql-engine/execution/binary/scalar.go b/vendor/github.com/thanos-io/promql-engine/execution/binary/scalar.go index 19faa406b4d..0c1ebe4d5f5 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/binary/scalar.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/binary/scalar.go @@ -8,12 +8,14 @@ import ( "fmt" "math" "sync" + "time" "github.com/prometheus/prometheus/model/labels" "github.com/thanos-io/promql-engine/execution/function" "github.com/thanos-io/promql-engine/execution/model" "github.com/thanos-io/promql-engine/parser" + "github.com/thanos-io/promql-engine/query" ) type ScalarSide int @@ -32,16 +34,18 @@ type scalarOperator struct { pool *model.VectorPool scalar model.VectorOperator next model.VectorOperator + opType parser.ItemType getOperands getOperandsFunc operandValIdx int - operation operation - opType parser.ItemType + floatOp operation + histOp histogramFloatOperation // If true then return the comparison result as 0/1. returnBool bool // Keep the result if both sides are scalars. bothScalars bool + model.OperatorTelemetry } func NewScalar( @@ -51,6 +55,7 @@ func NewScalar( op parser.ItemType, scalarSide ScalarSide, returnBool bool, + opts *query.Options, ) (*scalarOperator, error) { binaryOperation, err := newOperation(op, scalarSide != ScalarSideBoth) if err != nil { @@ -65,17 +70,36 @@ func NewScalar( operandValIdx = 1 } - return &scalarOperator{ + o := &scalarOperator{ pool: pool, next: next, scalar: scalar, - operation: binaryOperation, + floatOp: binaryOperation, + histOp: getHistogramFloatOperation(op, scalarSide), opType: op, getOperands: getOperands, operandValIdx: operandValIdx, returnBool: returnBool, bothScalars: scalarSide == ScalarSideBoth, - }, nil + } + o.OperatorTelemetry = &model.NoopTelemetry{} + if opts.EnableAnalysis { + o.OperatorTelemetry = &model.TrackedTelemetry{} + } + return o, nil + +} + +func (o *scalarOperator) Analyze() (model.OperatorTelemetry, []model.ObservableVectorOperator) { + o.SetName("[*scalarOperator]") + next := make([]model.ObservableVectorOperator, 0, 2) + if obsnext, ok := o.next.(model.ObservableVectorOperator); ok { + next = append(next, obsnext) + } + if obsnextScalar, ok := o.scalar.(model.ObservableVectorOperator); ok { + next = append(next, obsnextScalar) + } + return o, next } func (o *scalarOperator) Explain() (me string, next []model.VectorOperator) { @@ -97,6 +121,7 @@ func (o *scalarOperator) Next(ctx context.Context) ([]model.StepVector, error) { return nil, ctx.Err() default: } + start := time.Now() in, err := o.next.Next(ctx) if err != nil { @@ -118,14 +143,14 @@ func (o *scalarOperator) Next(ctx context.Context) ([]model.StepVector, error) { out := o.pool.GetVectorBatch() for v, vector := range in { step := o.pool.GetStepVector(vector.T) - for i := range vector.Samples { - scalarVal := math.NaN() - if len(scalarIn) > v && len(scalarIn[v].Samples) > 0 { - scalarVal = scalarIn[v].Samples[0] - } + scalarVal := math.NaN() + if len(scalarIn) > v && len(scalarIn[v].Samples) > 0 { + scalarVal = scalarIn[v].Samples[0] + } + for i := range vector.Samples { operands := o.getOperands(vector, i, scalarVal) - val, keep := o.operation(operands, o.operandValIdx) + val, keep := o.floatOp(operands, o.operandValIdx) if o.returnBool { if !o.bothScalars { val = 0.0 @@ -138,6 +163,14 @@ func (o *scalarOperator) Next(ctx context.Context) ([]model.StepVector, error) { } step.AppendSample(o.pool, vector.SampleIDs[i], val) } + + for i := range vector.HistogramIDs { + val := o.histOp(vector.Histograms[i], scalarVal) + if val != nil { + step.AppendHistogram(o.pool, vector.HistogramIDs[i], val) + } + } + out = append(out, step) o.next.GetPool().PutStepVector(vector) } @@ -148,6 +181,7 @@ func (o *scalarOperator) Next(ctx context.Context) ([]model.StepVector, error) { o.next.GetPool().PutVectors(in) o.scalar.GetPool().PutVectors(scalarIn) + o.AddExecutionTimeTaken(time.Since(start)) return out, nil } diff --git a/vendor/github.com/thanos-io/promql-engine/execution/binary/table.go b/vendor/github.com/thanos-io/promql-engine/execution/binary/table.go index 63f7a0697aa..b40c254ff7b 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/binary/table.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/binary/table.go @@ -6,6 +6,8 @@ package binary import ( "math" + "github.com/prometheus/prometheus/model/histogram" + "github.com/thanos-io/promql-engine/execution/model" "github.com/thanos-io/promql-engine/execution/parse" "github.com/thanos-io/promql-engine/parser" @@ -143,23 +145,19 @@ func (t *table) execBinaryOperation(lhs model.StepVector, rhs model.StepVector, type operation func(operands [2]float64, valueIdx int) (float64, bool) var operations = map[string]operation{ - "+": func(operands [2]float64, valueIdx int) (float64, bool) { return operands[0] + operands[1], true }, - "-": func(operands [2]float64, valueIdx int) (float64, bool) { return operands[0] - operands[1], true }, - "*": func(operands [2]float64, valueIdx int) (float64, bool) { return operands[0] * operands[1], true }, - "/": func(operands [2]float64, valueIdx int) (float64, bool) { return operands[0] / operands[1], true }, - "^": func(operands [2]float64, valueIdx int) (float64, bool) { - return math.Pow(operands[0], operands[1]), true - }, - "%": func(operands [2]float64, valueIdx int) (float64, bool) { - return math.Mod(operands[0], operands[1]), true - }, - "==": func(operands [2]float64, valueIdx int) (float64, bool) { return btof(operands[0] == operands[1]), true }, - "!=": func(operands [2]float64, valueIdx int) (float64, bool) { return btof(operands[0] != operands[1]), true }, - ">": func(operands [2]float64, valueIdx int) (float64, bool) { return btof(operands[0] > operands[1]), true }, - "<": func(operands [2]float64, valueIdx int) (float64, bool) { return btof(operands[0] < operands[1]), true }, - ">=": func(operands [2]float64, valueIdx int) (float64, bool) { return btof(operands[0] >= operands[1]), true }, - "<=": func(operands [2]float64, valueIdx int) (float64, bool) { return btof(operands[0] <= operands[1]), true }, - "atan2": func(operands [2]float64, valueIdx int) (float64, bool) { + "+": func(operands [2]float64, _ int) (float64, bool) { return operands[0] + operands[1], true }, + "-": func(operands [2]float64, _ int) (float64, bool) { return operands[0] - operands[1], true }, + "*": func(operands [2]float64, _ int) (float64, bool) { return operands[0] * operands[1], true }, + "/": func(operands [2]float64, _ int) (float64, bool) { return operands[0] / operands[1], true }, + "^": func(operands [2]float64, _ int) (float64, bool) { return math.Pow(operands[0], operands[1]), true }, + "%": func(operands [2]float64, _ int) (float64, bool) { return math.Mod(operands[0], operands[1]), true }, + "==": func(operands [2]float64, _ int) (float64, bool) { return btof(operands[0] == operands[1]), true }, + "!=": func(operands [2]float64, _ int) (float64, bool) { return btof(operands[0] != operands[1]), true }, + ">": func(operands [2]float64, _ int) (float64, bool) { return btof(operands[0] > operands[1]), true }, + "<": func(operands [2]float64, _ int) (float64, bool) { return btof(operands[0] < operands[1]), true }, + ">=": func(operands [2]float64, _ int) (float64, bool) { return btof(operands[0] >= operands[1]), true }, + "<=": func(operands [2]float64, _ int) (float64, bool) { return btof(operands[0] <= operands[1]), true }, + "atan2": func(operands [2]float64, _ int) (float64, bool) { return math.Atan2(operands[0], operands[1]), true }, } @@ -201,6 +199,42 @@ func newOperation(expr parser.ItemType, vectorBinOp bool) (operation, error) { return nil, parse.UnsupportedOperationErr(expr) } +// histogramFloatOperation is an operation defined one histogram and one float. +type histogramFloatOperation func(lhsHist *histogram.FloatHistogram, rhsFloat float64) *histogram.FloatHistogram + +func undefinedHistogramOp(_ *histogram.FloatHistogram, _ float64) *histogram.FloatHistogram { + return nil +} + +var lhsHistogramOperations = map[string]histogramFloatOperation{ + "*": func(hist *histogram.FloatHistogram, float float64) *histogram.FloatHistogram { + return hist.Copy().Mul(float) + }, + "/": func(hist *histogram.FloatHistogram, float float64) *histogram.FloatHistogram { + return hist.Copy().Div(float) + }, +} + +var rhsHistogramOperations = map[string]histogramFloatOperation{ + "*": func(hist *histogram.FloatHistogram, float float64) *histogram.FloatHistogram { + return hist.Copy().Mul(float) + }, +} + +func getHistogramFloatOperation(expr parser.ItemType, scalarSide ScalarSide) histogramFloatOperation { + t := parser.ItemTypeStr[expr] + var operation histogramFloatOperation + if scalarSide == ScalarSideLeft { + operation = rhsHistogramOperations[t] + } else { + operation = lhsHistogramOperations[t] + } + if operation != nil { + return operation + } + return undefinedHistogramOp +} + // btof returns 1 if b is true, 0 otherwise. func btof(b bool) float64 { if b { diff --git a/vendor/github.com/thanos-io/promql-engine/execution/binary/vector.go b/vendor/github.com/thanos-io/promql-engine/execution/binary/vector.go index 28dab1a8630..76b3441322f 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/binary/vector.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/binary/vector.go @@ -14,6 +14,7 @@ import ( "github.com/thanos-io/promql-engine/execution/model" "github.com/thanos-io/promql-engine/parser" + "github.com/thanos-io/promql-engine/query" ) // vectorOperator evaluates an expression between two step vectors. @@ -42,6 +43,7 @@ type vectorOperator struct { // If true then 1/0 needs to be returned instead of the value. returnBool bool + model.OperatorTelemetry } func NewVectorOperator( @@ -51,6 +53,7 @@ func NewVectorOperator( matching *parser.VectorMatching, operation parser.ItemType, returnBool bool, + opts *query.Options, ) (model.VectorOperator, error) { op, err := newOperation(operation, true) if err != nil { @@ -63,7 +66,7 @@ func NewVectorOperator( copy(groupings, matching.MatchingLabels) slices.Sort(groupings) - return &vectorOperator{ + o := &vectorOperator{ pool: pool, lhs: lhs, rhs: rhs, @@ -72,7 +75,24 @@ func NewVectorOperator( operation: op, opType: operation, returnBool: returnBool, - }, nil + } + o.OperatorTelemetry = &model.NoopTelemetry{} + if opts.EnableAnalysis { + o.OperatorTelemetry = &model.TrackedTelemetry{} + } + return o, nil +} + +func (o *vectorOperator) Analyze() (model.OperatorTelemetry, []model.ObservableVectorOperator) { + o.SetName("[*vectorOperator]") + next := make([]model.ObservableVectorOperator, 0, 2) + if obsnextParamOp, ok := o.lhs.(model.ObservableVectorOperator); ok { + next = append(next, obsnextParamOp) + } + if obsnext, ok := o.rhs.(model.ObservableVectorOperator); ok { + next = append(next, obsnext) + } + return o, next } func (o *vectorOperator) Explain() (me string, next []model.VectorOperator) { diff --git a/vendor/github.com/thanos-io/promql-engine/execution/exchange/coalesce.go b/vendor/github.com/thanos-io/promql-engine/execution/exchange/coalesce.go index 817051302d9..cc8ce8572af 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/exchange/coalesce.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/exchange/coalesce.go @@ -7,11 +7,13 @@ import ( "context" "sync" "sync/atomic" + "time" "github.com/efficientgo/core/errors" "github.com/prometheus/prometheus/model/labels" "github.com/thanos-io/promql-engine/execution/model" + "github.com/thanos-io/promql-engine/query" ) type errorChan chan error @@ -42,18 +44,36 @@ type coalesce struct { inVectors [][]model.StepVector // sampleOffsets holds per-operator offsets needed to map an input sample ID to an output sample ID. sampleOffsets []uint64 + model.OperatorTelemetry } -func NewCoalesce(pool *model.VectorPool, operators ...model.VectorOperator) model.VectorOperator { - return &coalesce{ +func NewCoalesce(pool *model.VectorPool, opts *query.Options, operators ...model.VectorOperator) model.VectorOperator { + c := &coalesce{ pool: pool, sampleOffsets: make([]uint64, len(operators)), operators: operators, inVectors: make([][]model.StepVector, len(operators)), } + c.OperatorTelemetry = &model.NoopTelemetry{} + if opts.EnableAnalysis { + c.OperatorTelemetry = &model.TrackedTelemetry{} + } + return c +} + +func (c *coalesce) Analyze() (model.OperatorTelemetry, []model.ObservableVectorOperator) { + c.SetName("[*coalesce]") + obsOperators := make([]model.ObservableVectorOperator, 0, len(c.operators)) + for _, operator := range c.operators { + if obsOperator, ok := operator.(model.ObservableVectorOperator); ok { + obsOperators = append(obsOperators, obsOperator) + } + } + return c, obsOperators } func (c *coalesce) Explain() (me string, next []model.VectorOperator) { + return "[*coalesce]", c.operators } @@ -76,7 +96,7 @@ func (c *coalesce) Next(ctx context.Context) ([]model.StepVector, error) { return nil, ctx.Err() default: } - + start := time.Now() var err error c.once.Do(func() { err = c.loadSeries(ctx) }) if err != nil { @@ -131,6 +151,7 @@ func (c *coalesce) Next(ctx context.Context) ([]model.StepVector, error) { c.inVectors[opIdx] = nil c.operators[opIdx].GetPool().PutVectors(vectors) } + c.AddExecutionTimeTaken(time.Since(start)) if out == nil { return nil, nil diff --git a/vendor/github.com/thanos-io/promql-engine/execution/exchange/concurrent.go b/vendor/github.com/thanos-io/promql-engine/execution/exchange/concurrent.go index e2f46fa75d9..35640582ef8 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/exchange/concurrent.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/exchange/concurrent.go @@ -7,6 +7,7 @@ import ( "context" "fmt" "sync" + "time" "github.com/thanos-io/promql-engine/execution/model" @@ -23,14 +24,26 @@ type concurrencyOperator struct { next model.VectorOperator buffer chan maybeStepVector bufferSize int + model.OperatorTelemetry } func NewConcurrent(next model.VectorOperator, bufferSize int) model.VectorOperator { - return &concurrencyOperator{ + c := &concurrencyOperator{ next: next, buffer: make(chan maybeStepVector, bufferSize), bufferSize: bufferSize, } + c.OperatorTelemetry = &model.TrackedTelemetry{} + return c +} + +func (c *concurrencyOperator) Analyze() (model.OperatorTelemetry, []model.ObservableVectorOperator) { + c.SetName(("[*concurrencyOperator]")) + next := make([]model.ObservableVectorOperator, 0, 1) + if obsnext, ok := c.next.(model.ObservableVectorOperator); ok { + next = append(next, obsnext) + } + return c, next } func (c *concurrencyOperator) Explain() (me string, next []model.VectorOperator) { @@ -52,6 +65,7 @@ func (c *concurrencyOperator) Next(ctx context.Context) ([]model.StepVector, err default: } + start := time.Now() c.once.Do(func() { go c.pull(ctx) go c.drainBufferOnCancel(ctx) @@ -64,6 +78,7 @@ func (c *concurrencyOperator) Next(ctx context.Context) ([]model.StepVector, err if r.err != nil { return nil, r.err } + c.AddExecutionTimeTaken(time.Since(start)) return r.stepVector, nil } diff --git a/vendor/github.com/thanos-io/promql-engine/execution/exchange/dedup.go b/vendor/github.com/thanos-io/promql-engine/execution/exchange/dedup.go index 86e428ab99e..7bcbdf37803 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/exchange/dedup.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/exchange/dedup.go @@ -6,6 +6,7 @@ package exchange import ( "context" "sync" + "time" "github.com/cespare/xxhash/v2" "github.com/prometheus/prometheus/model/histogram" @@ -37,13 +38,25 @@ type dedupOperator struct { // outputIndex is a slice that is used as an index from input sample ID to output sample ID. outputIndex []uint64 dedupCache dedupCache + model.OperatorTelemetry } func NewDedupOperator(pool *model.VectorPool, next model.VectorOperator) model.VectorOperator { - return &dedupOperator{ + d := &dedupOperator{ next: next, pool: pool, } + d.OperatorTelemetry = &model.TrackedTelemetry{} + return d +} + +func (d *dedupOperator) Analyze() (model.OperatorTelemetry, []model.ObservableVectorOperator) { + d.SetName("[*dedup]") + next := make([]model.ObservableVectorOperator, 0, 1) + if obsnext, ok := d.next.(model.ObservableVectorOperator); ok { + next = append(next, obsnext) + } + return d, next } func (d *dedupOperator) Next(ctx context.Context) ([]model.StepVector, error) { @@ -52,6 +65,7 @@ func (d *dedupOperator) Next(ctx context.Context) ([]model.StepVector, error) { if err != nil { return nil, err } + start := time.Now() in, err := d.next.Next(ctx) if err != nil { @@ -91,6 +105,7 @@ func (d *dedupOperator) Next(ctx context.Context) ([]model.StepVector, error) { } result = append(result, out) } + d.AddExecutionTimeTaken(time.Since(start)) return result, nil } diff --git a/vendor/github.com/thanos-io/promql-engine/execution/execution.go b/vendor/github.com/thanos-io/promql-engine/execution/execution.go index 58e2916d006..8dd84bfb4c9 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/execution.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/execution.go @@ -18,27 +18,24 @@ package execution import ( "context" + "runtime" "sort" "time" - "github.com/prometheus/prometheus/promql" - - "github.com/thanos-io/promql-engine/execution/noop" - "github.com/thanos-io/promql-engine/execution/remote" - "github.com/efficientgo/core/errors" - - "github.com/prometheus/prometheus/storage" - "github.com/prometheus/prometheus/model/labels" + "github.com/prometheus/prometheus/promql" + "github.com/prometheus/prometheus/storage" "github.com/thanos-io/promql-engine/execution/aggregate" "github.com/thanos-io/promql-engine/execution/binary" "github.com/thanos-io/promql-engine/execution/exchange" "github.com/thanos-io/promql-engine/execution/function" "github.com/thanos-io/promql-engine/execution/model" + "github.com/thanos-io/promql-engine/execution/noop" "github.com/thanos-io/promql-engine/execution/parse" + "github.com/thanos-io/promql-engine/execution/remote" "github.com/thanos-io/promql-engine/execution/scan" "github.com/thanos-io/promql-engine/execution/step_invariant" engstore "github.com/thanos-io/promql-engine/execution/storage" @@ -52,7 +49,7 @@ const stepsBatch = 10 // New creates new physical query execution for a given query expression which represents logical plan. // TODO(bwplotka): Add definition (could be parameters for each execution operator) we can optimize - it would represent physical plan. -func New(ctx context.Context, expr parser.Expr, queryable storage.Queryable, mint, maxt time.Time, step, lookbackDelta, extLookbackDelta time.Duration) (model.VectorOperator, error) { +func New(ctx context.Context, expr parser.Expr, queryable storage.Queryable, mint, maxt time.Time, step, lookbackDelta, extLookbackDelta time.Duration, enableAnalysis bool) (model.VectorOperator, error) { opts := &query.Options{ Context: ctx, Start: mint, @@ -61,6 +58,7 @@ func New(ctx context.Context, expr parser.Expr, queryable storage.Queryable, min LookbackDelta: lookbackDelta, StepsBatch: stepsBatch, ExtLookbackDelta: extLookbackDelta, + EnableAnalysis: enableAnalysis, } selectorPool := engstore.NewSelectorPool(queryable) hints := storage.SelectHints{ @@ -69,6 +67,7 @@ func New(ctx context.Context, expr parser.Expr, queryable storage.Queryable, min // TODO(fpetkovski): Adjust the step for sub-queries once they are supported. Step: step.Milliseconds(), } + return newOperator(expr, selectorPool, opts, hints) } @@ -95,85 +94,13 @@ func newOperator(expr parser.Expr, storage *engstore.SelectorPool, opts *query.O hints.Func = e.Func.Name hints.Grouping = nil hints.By = false - - if e.Func.Name == "histogram_quantile" { - nextOperators := make([]model.VectorOperator, len(e.Args)) - for i := range e.Args { - next, err := newOperator(e.Args[i], storage, opts, hints) - if err != nil { - return nil, err - } - nextOperators[i] = next - } - - return function.NewHistogramOperator(model.NewVectorPool(stepsBatch), e.Args, nextOperators, stepsBatch) - } - - // TODO(saswatamcode): Tracked in https://github.com/thanos-io/promql-engine/issues/23 - // Based on the category we can create an apt query plan. - call, err := function.NewFunctionCall(e.Func) - if err != nil { - return nil, err - } - - // TODO(saswatamcode): Range vector result might need new operator - // before it can be non-nested. https://github.com/thanos-io/promql-engine/issues/39 for i := range e.Args { switch t := e.Args[i].(type) { case *parser.MatrixSelector: - if call == nil { - return nil, parse.ErrNotImplemented - } - - vs, filters, err := unpackVectorSelector(t) - if err != nil { - return nil, err - } - - milliSecondRange := t.Range.Milliseconds() - if function.IsExtFunction(hints.Func) { - milliSecondRange += opts.ExtLookbackDelta.Milliseconds() - } - - start, end := getTimeRangesForVectorSelector(vs, opts, milliSecondRange) - hints.Start = start - hints.End = end - hints.Range = milliSecondRange - filter := storage.GetFilteredSelector(start, end, opts.Step.Milliseconds(), vs.LabelMatchers, filters, hints) - - numShards := runtime.GOMAXPROCS(0) / 2 - if numShards < 1 { - numShards = 1 - } - - operators := make([]model.VectorOperator, 0, numShards) - for i := 0; i < numShards; i++ { - operator := exchange.NewConcurrent( - scan.NewMatrixSelector(model.NewVectorPool(stepsBatch), filter, call, e, opts, t.Range, vs.Offset, i, numShards), - 2, - ) - operators = append(operators, operator) - } - - return exchange.NewCoalesce(model.NewVectorPool(stepsBatch), operators...), nil - } - } - - // Does not have matrix arg so create functionOperator normally. - nextOperators := make([]model.VectorOperator, 0, len(e.Args)) - for i := range e.Args { - // Strings don't need an operator - if e.Args[i].Type() == parser.ValueTypeString { - continue - } - next, err := newOperator(e.Args[i], storage, opts, hints) - if err != nil { - return nil, err + return newRangeVectorFunction(e, t, storage, opts, hints) } - nextOperators = append(nextOperators, next) } - - return function.NewFunctionOperator(e, call, nextOperators, stepsBatch, opts) + return newInstantVectorFunction(e, storage, opts, hints) case *parser.AggregateExpr: hints.Func = e.Op.String() @@ -194,7 +121,7 @@ func newOperator(expr parser.Expr, storage *engstore.SelectorPool, opts *query.O } if e.Op == parser.TOPK || e.Op == parser.BOTTOMK { - next, err = aggregate.NewKHashAggregate(model.NewVectorPool(stepsBatch), next, paramOp, e.Op, !e.Without, e.Grouping, stepsBatch) + next, err = aggregate.NewKHashAggregate(model.NewVectorPool(stepsBatch), next, paramOp, e.Op, !e.Without, e.Grouping, stepsBatch, opts) } else { next, err = aggregate.NewHashAggregate(model.NewVectorPool(stepsBatch), next, paramOp, e.Op, !e.Without, e.Grouping, stepsBatch) } @@ -240,7 +167,7 @@ func newOperator(expr parser.Expr, storage *engstore.SelectorPool, opts *query.O if err != nil { return nil, err } - return step_invariant.NewStepInvariantOperator(model.NewVectorPool(stepsBatch), next, e.Expr, opts, stepsBatch) + return step_invariant.NewStepInvariantOperator(model.NewVectorPoolWithSize(stepsBatch, 1), next, e.Expr, opts, stepsBatch) case logicalplan.Deduplicate: // The Deduplicate operator will deduplicate samples using a last-sample-wins strategy. @@ -259,7 +186,7 @@ func newOperator(expr parser.Expr, storage *engstore.SelectorPool, opts *query.O } operators[i] = operator } - coalesce := exchange.NewCoalesce(model.NewVectorPool(stepsBatch), operators...) + coalesce := exchange.NewCoalesce(model.NewVectorPool(stepsBatch), opts, operators...) dedup := exchange.NewDedupOperator(model.NewVectorPool(stepsBatch), coalesce) return exchange.NewConcurrent(dedup, 2), nil @@ -279,6 +206,8 @@ func newOperator(expr parser.Expr, storage *engstore.SelectorPool, opts *query.O return exchange.NewConcurrent(remoteExec, 2), nil case logicalplan.Noop: return noop.NewOperator(), nil + case logicalplan.UserDefinedExpr: + return e.MakeExecutionOperator(stepsBatch, model.NewVectorPool(stepsBatch), storage, opts, hints) default: return nil, errors.Wrapf(parse.ErrNotSupportedExpr, "got: %s", e) } @@ -295,6 +224,59 @@ func unpackVectorSelector(t *parser.MatrixSelector) (*parser.VectorSelector, []* } } +func newRangeVectorFunction(e *parser.Call, t *parser.MatrixSelector, storage *engstore.SelectorPool, opts *query.Options, hints storage.SelectHints) (model.VectorOperator, error) { + // TODO(saswatamcode): Range vector result might need new operator + // before it can be non-nested. https://github.com/thanos-io/promql-engine/issues/39 + vs, filters, err := unpackVectorSelector(t) + if err != nil { + return nil, err + } + + milliSecondRange := t.Range.Milliseconds() + if parse.IsExtFunction(e.Func.Name) { + milliSecondRange += opts.ExtLookbackDelta.Milliseconds() + } + + start, end := getTimeRangesForVectorSelector(vs, opts, milliSecondRange) + hints.Start = start + hints.End = end + hints.Range = milliSecondRange + filter := storage.GetFilteredSelector(start, end, opts.Step.Milliseconds(), vs.LabelMatchers, filters, hints) + + numShards := runtime.GOMAXPROCS(0) / 2 + if numShards < 1 { + numShards = 1 + } + + operators := make([]model.VectorOperator, 0, numShards) + for i := 0; i < numShards; i++ { + operator, err := scan.NewMatrixSelector(model.NewVectorPool(stepsBatch), filter, e, opts, t.Range, vs.Offset, i, numShards) + if err != nil { + return nil, err + } + operators = append(operators, exchange.NewConcurrent(operator, 2)) + } + + return exchange.NewCoalesce(model.NewVectorPool(stepsBatch), opts, operators...), nil +} + +func newInstantVectorFunction(e *parser.Call, storage *engstore.SelectorPool, opts *query.Options, hints storage.SelectHints) (model.VectorOperator, error) { + nextOperators := make([]model.VectorOperator, 0, len(e.Args)) + for i := range e.Args { + // Strings don't need an operator + if e.Args[i].Type() == parser.ValueTypeString { + continue + } + next, err := newOperator(e.Args[i], storage, opts, hints) + if err != nil { + return nil, err + } + nextOperators = append(nextOperators, next) + } + + return function.NewFunctionOperator(e, nextOperators, stepsBatch, opts) +} + func newShardedVectorSelector(selector engstore.SeriesSelector, opts *query.Options, offset time.Duration) (model.VectorOperator, error) { numShards := runtime.GOMAXPROCS(0) / 2 if numShards < 1 { @@ -308,7 +290,7 @@ func newShardedVectorSelector(selector engstore.SeriesSelector, opts *query.Opti operators = append(operators, operator) } - return exchange.NewCoalesce(model.NewVectorPool(stepsBatch), operators...), nil + return exchange.NewCoalesce(model.NewVectorPool(stepsBatch), opts, operators...), nil } func newVectorBinaryOperator(e *parser.BinaryExpr, selectorPool *engstore.SelectorPool, opts *query.Options, hints storage.SelectHints) (model.VectorOperator, error) { @@ -320,7 +302,7 @@ func newVectorBinaryOperator(e *parser.BinaryExpr, selectorPool *engstore.Select if err != nil { return nil, err } - return binary.NewVectorOperator(model.NewVectorPool(stepsBatch), leftOperator, rightOperator, e.VectorMatching, e.Op, e.ReturnBool) + return binary.NewVectorOperator(model.NewVectorPool(stepsBatch), leftOperator, rightOperator, e.VectorMatching, e.Op, e.ReturnBool, opts) } func newScalarBinaryOperator(e *parser.BinaryExpr, selectorPool *engstore.SelectorPool, opts *query.Options, hints storage.SelectHints) (model.VectorOperator, error) { @@ -341,7 +323,7 @@ func newScalarBinaryOperator(e *parser.BinaryExpr, selectorPool *engstore.Select scalarSide = binary.ScalarSideLeft } - return binary.NewScalar(model.NewVectorPool(stepsBatch), lhs, rhs, e.Op, scalarSide, e.ReturnBool) + return binary.NewScalar(model.NewVectorPoolWithSize(stepsBatch, 1), lhs, rhs, e.Op, scalarSide, e.ReturnBool, opts) } // Copy from https://github.com/prometheus/prometheus/blob/v2.39.1/promql/engine.go#L791. diff --git a/vendor/github.com/thanos-io/promql-engine/execution/function/absent.go b/vendor/github.com/thanos-io/promql-engine/execution/function/absent.go new file mode 100644 index 00000000000..59c55e72efb --- /dev/null +++ b/vendor/github.com/thanos-io/promql-engine/execution/function/absent.go @@ -0,0 +1,110 @@ +// Copyright (c) The Thanos Community Authors. +// Licensed under the Apache License 2.0. + +package function + +import ( + "context" + "sync" + "time" + + "github.com/prometheus/prometheus/model/labels" + + "github.com/thanos-io/promql-engine/execution/model" + "github.com/thanos-io/promql-engine/parser" +) + +type absentOperator struct { + once sync.Once + funcExpr *parser.Call + series []labels.Labels + pool *model.VectorPool + next model.VectorOperator + model.OperatorTelemetry +} + +func (o *absentOperator) Analyze() (model.OperatorTelemetry, []model.ObservableVectorOperator) { + o.SetName("[*absentOperator]") + next := make([]model.ObservableVectorOperator, 0, 1) + if obsnext, ok := o.next.(model.ObservableVectorOperator); ok { + next = append(next, obsnext) + } + return o, next +} + +func (o *absentOperator) Explain() (me string, next []model.VectorOperator) { + return "[*absentOperator]", []model.VectorOperator{} +} + +func (o *absentOperator) Series(_ context.Context) ([]labels.Labels, error) { + o.loadSeries() + return o.series, nil +} + +func (o *absentOperator) loadSeries() { + o.once.Do(func() { + o.pool.SetStepSize(1) + + // https://github.com/prometheus/prometheus/blob/main/promql/functions.go#L1385 + var lm []*labels.Matcher + switch n := o.funcExpr.Args[0].(type) { + case *parser.VectorSelector: + lm = n.LabelMatchers + case *parser.MatrixSelector: + lm = n.VectorSelector.(*parser.VectorSelector).LabelMatchers + default: + o.series = []labels.Labels{labels.EmptyLabels()} + return + } + + has := make(map[string]bool) + lmap := make(map[string]string) + for _, l := range lm { + if l.Name == labels.MetricName { + continue + } + if l.Type == labels.MatchEqual && !has[l.Name] { + lmap[l.Name] = l.Value + has[l.Name] = true + } else { + delete(lmap, l.Name) + } + } + o.series = []labels.Labels{labels.FromMap(lmap)} + }) +} + +func (o *absentOperator) GetPool() *model.VectorPool { + return o.pool +} + +func (o *absentOperator) Next(ctx context.Context) ([]model.StepVector, error) { + select { + case <-ctx.Done(): + return nil, ctx.Err() + default: + } + o.loadSeries() + start := time.Now() + + vectors, err := o.next.Next(ctx) + if err != nil { + return nil, err + } + if len(vectors) == 0 { + return nil, nil + } + + result := o.GetPool().GetVectorBatch() + for i := range vectors { + sv := o.GetPool().GetStepVector(vectors[i].T) + if len(vectors[i].Samples) == 0 && len(vectors[i].Histograms) == 0 { + sv.AppendSample(o.GetPool(), 0, 1) + } + result = append(result, sv) + o.next.GetPool().PutStepVector(vectors[i]) + } + o.next.GetPool().PutVectors(vectors) + o.AddExecutionTimeTaken(time.Since(start)) + return result, nil +} diff --git a/vendor/github.com/thanos-io/promql-engine/execution/function/functions.go b/vendor/github.com/thanos-io/promql-engine/execution/function/functions.go index c28b7343bb0..8f1c91ddf43 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/function/functions.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/function/functions.go @@ -4,63 +4,15 @@ package function import ( - "fmt" "math" "time" - "github.com/efficientgo/core/errors" "github.com/prometheus/prometheus/model/histogram" - "github.com/prometheus/prometheus/model/labels" - "github.com/prometheus/prometheus/promql" - - "github.com/thanos-io/promql-engine/execution/parse" - "github.com/thanos-io/promql-engine/parser" ) -var InvalidSample = promql.Sample{T: -1, F: 0} - -type FunctionArgs struct { - Labels labels.Labels - Samples []promql.Sample - StepTime int64 - SelectRange int64 - ScalarPoints []float64 - Offset int64 - MetricAppearedTs *int64 - LabelsBuilder labels.ScratchBuilder -} - -// FunctionCall represents functions as defined in https://prometheus.io/docs/prometheus/latest/querying/functions/ -type FunctionCall func(f FunctionArgs) promql.Sample +type functionCall func(f float64, h *histogram.FloatHistogram, vargs ...float64) (float64, bool) -func simpleFunc(f func(float64) float64) FunctionCall { - return func(fa FunctionArgs) promql.Sample { - if len(fa.Samples) == 0 { - return InvalidSample - } - return promql.Sample{ - Metric: fa.Labels, - T: fa.StepTime, - F: f(fa.Samples[0].F), - } - } - -} - -func filterFloatOnlySamples(samples []promql.Sample) []promql.Sample { - i := 0 - for _, sample := range samples { - if sample.H == nil { - samples[i] = sample - i++ - } - } - samples = samples[:i] - return samples -} - -// The engine handles sort and sort_desc when presenting the results. They are not needed here. -var Funcs = map[string]FunctionCall{ +var instantVectorFuncs = map[string]functionCall{ "abs": simpleFunc(math.Abs), "ceil": simpleFunc(math.Ceil), "exp": simpleFunc(math.Exp), @@ -99,854 +51,182 @@ var Funcs = map[string]FunctionCall{ } return sign }), - "round": func(f FunctionArgs) promql.Sample { - if len(f.Samples) != 1 || len(f.ScalarPoints) > 1 { - return InvalidSample + "round": func(f float64, h *histogram.FloatHistogram, vargs ...float64) (float64, bool) { + if len(vargs) > 1 { + return 0., false } toNearest := 1.0 - if len(f.ScalarPoints) > 0 { - toNearest = f.ScalarPoints[0] + if len(vargs) > 0 { + toNearest = vargs[0] } toNearestInverse := 1.0 / toNearest - return promql.Sample{ - T: f.StepTime, - F: math.Floor(f.Samples[0].F*toNearestInverse+0.5) / toNearestInverse, - } - }, - "pi": func(f FunctionArgs) promql.Sample { - return promql.Sample{ - T: f.StepTime, - F: math.Pi, - } - }, - "sum_over_time": func(f FunctionArgs) promql.Sample { - if len(f.Samples) == 0 { - return InvalidSample - } - return promql.Sample{ - Metric: f.Labels, - T: f.StepTime, - F: sumOverTime(f.Samples), - } - }, - "max_over_time": func(f FunctionArgs) promql.Sample { - if len(f.Samples) == 0 { - return InvalidSample - } - return promql.Sample{ - Metric: f.Labels, - T: f.StepTime, - F: maxOverTime(f.Samples), - } - }, - "min_over_time": func(f FunctionArgs) promql.Sample { - if len(f.Samples) == 0 { - return InvalidSample - } - return promql.Sample{ - Metric: f.Labels, - T: f.StepTime, - F: minOverTime(f.Samples), - } + return math.Floor(f*toNearestInverse+0.5) / toNearestInverse, true }, - "avg_over_time": func(f FunctionArgs) promql.Sample { - if len(f.Samples) == 0 { - return InvalidSample - } - return promql.Sample{ - Metric: f.Labels, - T: f.StepTime, - F: avgOverTime(f.Samples), - } + "pi": func(float64, *histogram.FloatHistogram, ...float64) (float64, bool) { + return math.Pi, true }, - "stddev_over_time": func(f FunctionArgs) promql.Sample { - if len(f.Samples) == 0 { - return InvalidSample - } - return promql.Sample{ - Metric: f.Labels, - T: f.StepTime, - F: stddevOverTime(f.Samples), - } + "vector": func(f float64, h *histogram.FloatHistogram, vargs ...float64) (float64, bool) { + return f, true }, - "stdvar_over_time": func(f FunctionArgs) promql.Sample { - if len(f.Samples) == 0 { - return InvalidSample - } - return promql.Sample{ - Metric: f.Labels, - T: f.StepTime, - F: stdvarOverTime(f.Samples), + "clamp": func(f float64, h *histogram.FloatHistogram, vargs ...float64) (float64, bool) { + if len(vargs) != 2 { + return 0., false } - }, - "count_over_time": func(f FunctionArgs) promql.Sample { - if len(f.Samples) == 0 { - return InvalidSample - } - return promql.Sample{ - Metric: f.Labels, - T: f.StepTime, - F: countOverTime(f.Samples), - } - }, - "last_over_time": func(f FunctionArgs) promql.Sample { - if len(f.Samples) == 0 { - return InvalidSample - } - return promql.Sample{ - Metric: f.Labels, - T: f.StepTime, - F: f.Samples[len(f.Samples)-1].F, - } - }, - "label_join": func(f FunctionArgs) promql.Sample { - // This is specifically handled by functionOperator Series() - return promql.Sample{} - }, - "present_over_time": func(f FunctionArgs) promql.Sample { - if len(f.Samples) == 0 { - return InvalidSample - } - return promql.Sample{ - Metric: f.Labels, - T: f.StepTime, - F: 1, - } - }, - "time": func(f FunctionArgs) promql.Sample { - return promql.Sample{ - T: f.StepTime, - F: float64(f.StepTime) / 1000, - } - }, - "changes": func(f FunctionArgs) promql.Sample { - if len(f.Samples) == 0 { - return InvalidSample - } - return promql.Sample{ - Metric: f.Labels, - T: f.StepTime, - F: changes(f.Samples), + + v := f + min := vargs[0] + max := vargs[1] + + if max < min { + return 0., false } + + return math.Max(min, math.Min(max, v)), true }, - "resets": func(f FunctionArgs) promql.Sample { - if len(f.Samples) == 0 { - return InvalidSample - } - return promql.Sample{ - Metric: f.Labels, - T: f.StepTime, - F: resets(f.Samples), + "clamp_min": func(f float64, h *histogram.FloatHistogram, vargs ...float64) (float64, bool) { + if len(vargs) != 1 { + return 0., false } + + v := f + min := vargs[0] + + return math.Max(min, v), true }, - "deriv": func(f FunctionArgs) promql.Sample { - if len(f.Samples) < 2 { - return InvalidSample - } - return promql.Sample{ - Metric: f.Labels, - T: f.StepTime, - F: deriv(f.Samples), + "clamp_max": func(f float64, h *histogram.FloatHistogram, vargs ...float64) (float64, bool) { + if len(vargs) != 1 { + return 0., false } + + v := f + max := vargs[0] + + return math.Min(max, v), true }, - "irate": func(f FunctionArgs) promql.Sample { - f.Samples = filterFloatOnlySamples(f.Samples) - if len(f.Samples) < 2 { - return InvalidSample - } - val, ok := instantValue(f.Samples, true) - if !ok { - return InvalidSample - } - return promql.Sample{ - Metric: f.Labels, - T: f.StepTime, - F: val, + "histogram_sum": func(f float64, h *histogram.FloatHistogram, vargs ...float64) (float64, bool) { + if h == nil { + return 0., false } + return h.Sum, true }, - "idelta": func(f FunctionArgs) promql.Sample { - f.Samples = filterFloatOnlySamples(f.Samples) - if len(f.Samples) < 2 { - return InvalidSample - } - val, ok := instantValue(f.Samples, false) - if !ok { - return InvalidSample - } - return promql.Sample{ - Metric: f.Labels, - T: f.StepTime, - F: val, + "histogram_count": func(f float64, h *histogram.FloatHistogram, vargs ...float64) (float64, bool) { + if h == nil { + return 0., false } + return h.Count, true }, - "vector": func(f FunctionArgs) promql.Sample { - if len(f.Samples) == 0 { - return InvalidSample - } - return promql.Sample{ - Metric: f.Labels, - T: f.StepTime, - F: f.Samples[0].F, + "histogram_fraction": func(f float64, h *histogram.FloatHistogram, vargs ...float64) (float64, bool) { + if h == nil || len(vargs) != 2 { + return 0., false } + return histogramFraction(vargs[0], vargs[1], h), true }, - "scalar": func(f FunctionArgs) promql.Sample { - // This is handled specially by operator. - return promql.Sample{} + // variants of date time functions with an argument + "days_in_month": func(f float64, h *histogram.FloatHistogram, vargs ...float64) (float64, bool) { + return daysInMonth(dateFromSampleValue(f)), true }, - "rate": func(f FunctionArgs) promql.Sample { - if len(f.Samples) < 2 { - return InvalidSample - } - v, h := extrapolatedRate(f.Samples, true, true, f.StepTime, f.SelectRange, f.Offset) - return promql.Sample{ - Metric: f.Labels, - T: f.StepTime, - F: v, - H: h, - } + "day_of_month": func(f float64, h *histogram.FloatHistogram, vargs ...float64) (float64, bool) { + return dayOfMonth(dateFromSampleValue(f)), true }, - "delta": func(f FunctionArgs) promql.Sample { - if len(f.Samples) < 2 { - return InvalidSample - } - v, h := extrapolatedRate(f.Samples, false, false, f.StepTime, f.SelectRange, f.Offset) - return promql.Sample{ - Metric: f.Labels, - T: f.StepTime, - F: v, - H: h, - } - }, - "increase": func(f FunctionArgs) promql.Sample { - if len(f.Samples) < 2 { - return InvalidSample - } - v, h := extrapolatedRate(f.Samples, true, false, f.StepTime, f.SelectRange, f.Offset) - return promql.Sample{ - Metric: f.Labels, - T: f.StepTime, - F: v, - H: h, - } + "day_of_week": func(f float64, h *histogram.FloatHistogram, vargs ...float64) (float64, bool) { + return dayOfWeek(dateFromSampleValue(f)), true }, - "xrate": func(f FunctionArgs) promql.Sample { - if len(f.Samples) == 0 { - return InvalidSample - } - if f.MetricAppearedTs == nil { - panic("BUG: we got some samples but metric still hasn't appeared") - } - v, h := extendedRate(f.Samples, true, true, f.StepTime, f.SelectRange, f.Offset, *f.MetricAppearedTs) - return promql.Sample{ - Metric: f.Labels, - T: f.StepTime, - F: v, - H: h, - } + "day_of_year": func(f float64, h *histogram.FloatHistogram, vargs ...float64) (float64, bool) { + return dayOfYear(dateFromSampleValue(f)), true }, - "xdelta": func(f FunctionArgs) promql.Sample { - if len(f.Samples) == 0 { - return InvalidSample - } - if f.MetricAppearedTs == nil { - panic("BUG: we got some samples but metric still hasn't appeared") - } - v, h := extendedRate(f.Samples, false, false, f.StepTime, f.SelectRange, f.Offset, *f.MetricAppearedTs) - return promql.Sample{ - Metric: f.Labels, - T: f.StepTime, - F: v, - H: h, - } + "hour": func(f float64, h *histogram.FloatHistogram, vargs ...float64) (float64, bool) { + return hour(dateFromSampleValue(f)), true }, - "xincrease": func(f FunctionArgs) promql.Sample { - if len(f.Samples) == 0 { - return InvalidSample - } - if f.MetricAppearedTs == nil { - panic("BUG: we got some samples but metric still hasn't appeared") - } - v, h := extendedRate(f.Samples, true, false, f.StepTime, f.SelectRange, f.Offset, *f.MetricAppearedTs) - return promql.Sample{ - Metric: f.Labels, - T: f.StepTime, - F: v, - H: h, - } + "minute": func(f float64, h *histogram.FloatHistogram, vargs ...float64) (float64, bool) { + return minute(dateFromSampleValue(f)), true }, - "clamp": func(f FunctionArgs) promql.Sample { - if len(f.Samples) == 0 || len(f.ScalarPoints) < 2 { - return InvalidSample - } - - v := f.Samples[0].F - min := f.ScalarPoints[0] - max := f.ScalarPoints[1] - - if max < min { - return InvalidSample - } - - return promql.Sample{ - Metric: f.Labels, - T: f.StepTime, - F: math.Max(min, math.Min(max, v)), - } + "month": func(f float64, h *histogram.FloatHistogram, vargs ...float64) (float64, bool) { + return month(dateFromSampleValue(f)), true }, - "clamp_min": func(f FunctionArgs) promql.Sample { - if len(f.Samples) == 0 || len(f.ScalarPoints) == 0 { - return InvalidSample - } - - v := f.Samples[0].F - min := f.ScalarPoints[0] - - return promql.Sample{ - Metric: f.Labels, - T: f.StepTime, - F: math.Max(min, v), - } + "year": func(f float64, h *histogram.FloatHistogram, vargs ...float64) (float64, bool) { + return year(dateFromSampleValue(f)), true }, - "clamp_max": func(f FunctionArgs) promql.Sample { - if len(f.Samples) == 0 || len(f.ScalarPoints) == 0 { - return InvalidSample - } +} - v := f.Samples[0].F - max := f.ScalarPoints[0] +type noArgFunctionCall func(t int64) float64 - return promql.Sample{ - Metric: f.Labels, - T: f.StepTime, - F: math.Min(max, v), - } - }, - "histogram_sum": func(f FunctionArgs) promql.Sample { - if len(f.Samples) == 0 || f.Samples[0].H == nil { - return InvalidSample - } - return promql.Sample{ - Metric: f.Labels, - T: f.StepTime, - F: f.Samples[0].H.Sum, - } - }, - "histogram_count": func(f FunctionArgs) promql.Sample { - if len(f.Samples) == 0 || f.Samples[0].H == nil { - return InvalidSample - } - return promql.Sample{ - Metric: f.Labels, - T: f.StepTime, - F: f.Samples[0].H.Count, - } +var noArgFuncs = map[string]noArgFunctionCall{ + "pi": func(_ int64) float64 { + return math.Pi }, - "histogram_fraction": func(f FunctionArgs) promql.Sample { - if len(f.Samples) == 0 || f.Samples[0].H == nil { - return InvalidSample - } - return promql.Sample{ - Metric: f.Labels, - T: f.StepTime, - F: histogramFraction(f.ScalarPoints[0], f.ScalarPoints[1], f.Samples[0].H), - } + "time": func(t int64) float64 { + return float64(t) / 1000 }, - "days_in_month": func(f FunctionArgs) promql.Sample { - return dateWrapper(f, func(t time.Time) float64 { - return float64(32 - time.Date(t.Year(), t.Month(), 32, 0, 0, 0, 0, time.UTC).Day()) - }) + // variants of date time functions with no argument + "days_in_month": func(t int64) float64 { + return daysInMonth(dateFromStepTime(t)) }, - "day_of_month": func(f FunctionArgs) promql.Sample { - return dateWrapper(f, func(t time.Time) float64 { - return float64(t.Day()) - }) + "day_of_month": func(t int64) float64 { + return dayOfMonth(dateFromStepTime(t)) }, - "day_of_week": func(f FunctionArgs) promql.Sample { - return dateWrapper(f, func(t time.Time) float64 { - return float64(t.Weekday()) - }) + "day_of_week": func(t int64) float64 { + return dayOfWeek(dateFromStepTime(t)) }, - "day_of_year": func(f FunctionArgs) promql.Sample { - return dateWrapper(f, func(t time.Time) float64 { - return float64(t.YearDay()) - }) + "day_of_year": func(t int64) float64 { + return dayOfYear(dateFromStepTime(t)) }, - "hour": func(f FunctionArgs) promql.Sample { - return dateWrapper(f, func(t time.Time) float64 { - return float64(t.Hour()) - }) + "hour": func(t int64) float64 { + return hour(dateFromStepTime(t)) }, - "minute": func(f FunctionArgs) promql.Sample { - return dateWrapper(f, func(t time.Time) float64 { - return float64(t.Minute()) - }) + "minute": func(t int64) float64 { + return minute(dateFromStepTime(t)) }, - "month": func(f FunctionArgs) promql.Sample { - return dateWrapper(f, func(t time.Time) float64 { - return float64(t.Month()) - }) + "month": func(t int64) float64 { + return month(dateFromStepTime(t)) }, - "year": func(f FunctionArgs) promql.Sample { - return dateWrapper(f, func(t time.Time) float64 { - return float64(t.Year()) - }) + "year": func(t int64) float64 { + return year(dateFromStepTime(t)) }, } -func NewFunctionCall(f *parser.Function) (FunctionCall, error) { - if call, ok := Funcs[f.Name]; ok { - return call, nil - } - - msg := fmt.Sprintf("unknown function: %s", f.Name) - if _, ok := parser.Functions[f.Name]; ok { - return nil, errors.Wrap(parse.ErrNotImplemented, msg) +func simpleFunc(f func(float64) float64) functionCall { + return func(v float64, h *histogram.FloatHistogram, vargs ...float64) (float64, bool) { + return f(v), true } - - return nil, errors.Wrap(parse.ErrNotSupportedExpr, msg) } -// extrapolatedRate is a utility function for rate/increase/delta. -// It calculates the rate (allowing for counter resets if isCounter is true), -// extrapolates if the first/last sample is close to the boundary, and returns -// the result as either per-second (if isRate is true) or overall. -func extrapolatedRate(samples []promql.Sample, isCounter, isRate bool, stepTime int64, selectRange int64, offset int64) (float64, *histogram.FloatHistogram) { - var ( - rangeStart = stepTime - (selectRange + offset) - rangeEnd = stepTime - offset - resultValue float64 - resultHistogram *histogram.FloatHistogram - ) - - if samples[0].H != nil { - resultHistogram = histogramRate(samples, isCounter) - } else { - resultValue = samples[len(samples)-1].F - samples[0].F - if isCounter { - var lastValue float64 - for _, sample := range samples { - if sample.F < lastValue { - resultValue += lastValue - } - lastValue = sample.F - } - } - } - - // Duration between first/last samples and boundary of range. - durationToStart := float64(samples[0].T-rangeStart) / 1000 - durationToEnd := float64(rangeEnd-samples[len(samples)-1].T) / 1000 - - sampledInterval := float64(samples[len(samples)-1].T-samples[0].T) / 1000 - averageDurationBetweenSamples := sampledInterval / float64(len(samples)-1) - - if isCounter && resultValue > 0 && samples[0].F >= 0 { - // Counters cannot be negative. If we have any slope at - // all (i.e. resultValue went up), we can extrapolate - // the zero point of the counter. If the duration to the - // zero point is shorter than the durationToStart, we - // take the zero point as the start of the series, - // thereby avoiding extrapolation to negative counter - // values. - durationToZero := sampledInterval * (samples[0].F / resultValue) - if durationToZero < durationToStart { - durationToStart = durationToZero - } - } - - // If the first/last samples are close to the boundaries of the range, - // extrapolate the result. This is as we expect that another sample - // will exist given the spacing between samples we've seen thus far, - // with an allowance for noise. - extrapolationThreshold := averageDurationBetweenSamples * 1.1 - extrapolateToInterval := sampledInterval - - if durationToStart < extrapolationThreshold { - extrapolateToInterval += durationToStart - } else { - extrapolateToInterval += averageDurationBetweenSamples / 2 - } - if durationToEnd < extrapolationThreshold { - extrapolateToInterval += durationToEnd - } else { - extrapolateToInterval += averageDurationBetweenSamples / 2 - } - factor := extrapolateToInterval / sampledInterval - if isRate { - factor /= float64(selectRange / 1000) - } - if resultHistogram == nil { - resultValue *= factor - } else { - resultHistogram.Mul(factor) - - } - - return resultValue, resultHistogram +func dateFromSampleValue(f float64) time.Time { + return time.Unix(int64(f), 0).UTC() } -// extendedRate is a utility function for xrate/xincrease/xdelta. -// It calculates the rate (allowing for counter resets if isCounter is true), -// taking into account the last sample before the range start, and returns -// the result as either per-second (if isRate is true) or overall. -func extendedRate(samples []promql.Sample, isCounter, isRate bool, stepTime int64, selectRange int64, offset int64, metricAppearedTs int64) (float64, *histogram.FloatHistogram) { - var ( - rangeStart = stepTime - (selectRange + offset) - rangeEnd = stepTime - offset - resultValue float64 - resultHistogram *histogram.FloatHistogram - ) - - if samples[0].H != nil { - // TODO - support extended rate for histograms - resultHistogram = histogramRate(samples, isCounter) - return resultValue, resultHistogram - } - - sameVals := true - for i := range samples { - if i > 0 && samples[i-1].F != samples[i].F { - sameVals = false - break - } - } - - // This effectively injects a "zero" series for xincrease if we only have one sample. - // Only do it for some time when the metric appears the first time. - until := selectRange + metricAppearedTs - if isCounter && !isRate && sameVals { - // Make sure we are not at the end of the range. - if stepTime-offset <= until { - return samples[0].F, nil - } - } - - sampledInterval := float64(samples[len(samples)-1].T - samples[0].T) - averageDurationBetweenSamples := sampledInterval / float64(len(samples)-1) - - firstPoint := 0 - // Only do this for not xincrease - if !(isCounter && !isRate) { - // If the point before the range is too far from rangeStart, drop it. - if float64(rangeStart-samples[0].T) > averageDurationBetweenSamples { - if len(samples) < 3 { - return resultValue, nil - } - firstPoint = 1 - sampledInterval = float64(samples[len(samples)-1].T - samples[1].T) - averageDurationBetweenSamples = sampledInterval / float64(len(samples)-2) - } - } - - var ( - counterCorrection float64 - lastValue float64 - ) - if isCounter { - for i := firstPoint; i < len(samples); i++ { - sample := samples[i] - if sample.F < lastValue { - counterCorrection += lastValue - } - lastValue = sample.F - } - } - resultValue = samples[len(samples)-1].F - samples[firstPoint].F + counterCorrection - - // Duration between last sample and boundary of range. - durationToEnd := float64(rangeEnd - samples[len(samples)-1].T) - // If the points cover the whole range (i.e. they start just before the - // range start and end just before the range end) adjust the value from - // the sampled range to the requested range. - // Only do this for not xincrease. - if !(isCounter && !isRate) { - if samples[firstPoint].T <= rangeStart && durationToEnd < averageDurationBetweenSamples { - adjustToRange := float64(selectRange / 1000) - resultValue = resultValue * (adjustToRange / (sampledInterval / 1000)) - } - } - - if isRate { - resultValue = resultValue / float64(selectRange/1000) - } - - return resultValue, nil +func dateFromStepTime(t int64) time.Time { + return time.Unix(t/1000, 0).UTC() } -// histogramRate is a helper function for extrapolatedRate. It requires -// points[0] to be a histogram. It returns nil if any other Point in points is -// not a histogram. -func histogramRate(points []promql.Sample, isCounter bool) *histogram.FloatHistogram { - prev := points[0].H // We already know that this is a histogram. - last := points[len(points)-1].H - if last == nil { - return nil // Range contains a mix of histograms and floats. - } - minSchema := prev.Schema - if last.Schema < minSchema { - minSchema = last.Schema - } - - // https://github.com/prometheus/prometheus/blob/ccea61c7bf1e6bce2196ba8189a209945a204c5b/promql/functions.go#L183 - // First iteration to find out two things: - // - What's the smallest relevant schema? - // - Are all data points histograms? - // []FloatPoint and a []HistogramPoint separately. - for _, currPoint := range points[1 : len(points)-1] { - curr := currPoint.H - if curr == nil { - return nil // Range contains a mix of histograms and floats. - } - if !isCounter { - continue - } - if curr.Schema < minSchema { - minSchema = curr.Schema - } - } - - h := last.CopyToSchema(minSchema) - h.Sub(prev) - - if isCounter { - // Second iteration to deal with counter resets. - for _, currPoint := range points[1:] { - curr := currPoint.H - if curr.DetectReset(prev) { - h.Add(prev) - } - prev = curr - } - } - h.CounterResetHint = histogram.GaugeType - return h.Compact(0) +func daysInMonth(t time.Time) float64 { + return float64(32 - time.Date(t.Year(), t.Month(), 32, 0, 0, 0, 0, time.UTC).Day()) } -func instantValue(samples []promql.Sample, isRate bool) (float64, bool) { - lastSample := samples[len(samples)-1] - previousSample := samples[len(samples)-2] - - var resultValue float64 - if isRate && lastSample.F < previousSample.F { - // Counter reset. - resultValue = lastSample.F - } else { - resultValue = lastSample.F - previousSample.F - } - - sampledInterval := lastSample.T - previousSample.T - if sampledInterval == 0 { - // Avoid dividing by 0. - return 0, false - } - - if isRate { - // Convert to per-second. - resultValue /= float64(sampledInterval) / 1000 - } - - return resultValue, true +func dayOfMonth(t time.Time) float64 { + return float64(t.Day()) } -func maxOverTime(points []promql.Sample) float64 { - max := points[0].F - for _, v := range points { - if v.F > max || math.IsNaN(max) { - max = v.F - } - } - return max +func dayOfWeek(t time.Time) float64 { + return float64(t.Weekday()) } -func minOverTime(points []promql.Sample) float64 { - min := points[0].F - for _, v := range points { - if v.F < min || math.IsNaN(min) { - min = v.F - } - } - return min +func dayOfYear(t time.Time) float64 { + return float64(t.YearDay()) } -func countOverTime(points []promql.Sample) float64 { - return float64(len(points)) +func hour(t time.Time) float64 { + return float64(t.Hour()) } -func avgOverTime(points []promql.Sample) float64 { - var mean, count, c float64 - for _, v := range points { - count++ - if math.IsInf(mean, 0) { - if math.IsInf(v.F, 0) && (mean > 0) == (v.F > 0) { - // The `mean` and `v.F` values are `Inf` of the same sign. They - // can't be subtracted, but the value of `mean` is correct - // already. - continue - } - if !math.IsInf(v.F, 0) && !math.IsNaN(v.F) { - // At this stage, the mean is an infinite. If the added - // value is neither an Inf or a Nan, we can keep that mean - // value. - // This is required because our calculation below removes - // the mean value, which would look like Inf += x - Inf and - // end up as a NaN. - continue - } - } - mean, c = KahanSumInc(v.F/count-mean/count, mean, c) - } - - if math.IsInf(mean, 0) { - return mean - } - return mean + c -} - -func sumOverTime(points []promql.Sample) float64 { - var sum, c float64 - for _, v := range points { - sum, c = KahanSumInc(v.F, sum, c) - } - if math.IsInf(sum, 0) { - return sum - } - return sum + c -} - -func stddevOverTime(points []promql.Sample) float64 { - var count float64 - var mean, cMean float64 - var aux, cAux float64 - for _, v := range points { - count++ - delta := v.F - (mean + cMean) - mean, cMean = KahanSumInc(delta/count, mean, cMean) - aux, cAux = KahanSumInc(delta*(v.F-(mean+cMean)), aux, cAux) - } - return math.Sqrt((aux + cAux) / count) -} - -func stdvarOverTime(points []promql.Sample) float64 { - var count float64 - var mean, cMean float64 - var aux, cAux float64 - for _, v := range points { - count++ - delta := v.F - (mean + cMean) - mean, cMean = KahanSumInc(delta/count, mean, cMean) - aux, cAux = KahanSumInc(delta*(v.F-(mean+cMean)), aux, cAux) - } - return (aux + cAux) / count +func minute(t time.Time) float64 { + return float64(t.Minute()) } -func changes(points []promql.Sample) float64 { - var count float64 - prev := points[0].F - count = 0 - for _, sample := range points[1:] { - current := sample.F - if current != prev && !(math.IsNaN(current) && math.IsNaN(prev)) { - count++ - } - prev = current - } - return count -} - -func deriv(points []promql.Sample) float64 { - // We pass in an arbitrary timestamp that is near the values in use - // to avoid floating point accuracy issues, see - // https://github.com/prometheus/prometheus/issues/2674 - slope, _ := linearRegression(points, points[0].T) - return slope -} - -func resets(points []promql.Sample) float64 { - count := 0 - prev := points[0].F - for _, sample := range points[1:] { - current := sample.F - if current < prev { - count++ - } - prev = current - } - - return float64(count) -} - -func linearRegression(samples []promql.Sample, interceptTime int64) (slope, intercept float64) { - var ( - n float64 - sumX, cX float64 - sumY, cY float64 - sumXY, cXY float64 - sumX2, cX2 float64 - initY float64 - constY bool - ) - initY = samples[0].F - constY = true - for i, sample := range samples { - // Set constY to false if any new y values are encountered. - if constY && i > 0 && sample.F != initY { - constY = false - } - n += 1.0 - x := float64(sample.T-interceptTime) / 1e3 - sumX, cX = KahanSumInc(x, sumX, cX) - sumY, cY = KahanSumInc(sample.F, sumY, cY) - sumXY, cXY = KahanSumInc(x*sample.F, sumXY, cXY) - sumX2, cX2 = KahanSumInc(x*x, sumX2, cX2) - } - if constY { - if math.IsInf(initY, 0) { - return math.NaN(), math.NaN() - } - return 0, initY - } - sumX = sumX + cX - sumY = sumY + cY - sumXY = sumXY + cXY - sumX2 = sumX2 + cX2 - - covXY := sumXY - sumX*sumY/n - varX := sumX2 - sumX*sumX/n - - slope = covXY / varX - intercept = sumY/n - slope*sumX/n - return slope, intercept -} - -func KahanSumInc(inc, sum, c float64) (newSum, newC float64) { - t := sum + inc - // Using Neumaier improvement, swap if next term larger than sum. - if math.Abs(sum) >= math.Abs(inc) { - c += (sum - t) + inc - } else { - c += (inc - t) + sum - } - return t, c -} - -// Common code for date related functions. -func dateWrapper(fa FunctionArgs, f func(time.Time) float64) promql.Sample { - if len(fa.Samples) == 0 { - return promql.Sample{ - Metric: labels.Labels{}, - F: f(time.Unix(fa.StepTime/1000, 0).UTC()), - } - } - t := time.Unix(int64(fa.Samples[0].F), 0).UTC() - lbls, _ := DropMetricName(fa.Labels, fa.LabelsBuilder) - return promql.Sample{ - Metric: lbls, - F: f(t), - } +func month(t time.Time) float64 { + return float64(t.Month()) } -// IsExtFunction is a convenience function to determine whether extended range calculations are required. -func IsExtFunction(functionName string) bool { - return functionName == "xincrease" || functionName == "xrate" || functionName == "xdelta" +func year(t time.Time) float64 { + return float64(t.Year()) } diff --git a/vendor/github.com/thanos-io/promql-engine/execution/function/histogram.go b/vendor/github.com/thanos-io/promql-engine/execution/function/histogram.go index 7e39bb15e49..bad31fd44ac 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/function/histogram.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/function/histogram.go @@ -9,6 +9,7 @@ import ( "math" "strconv" "sync" + "time" "github.com/cespare/xxhash/v2" "github.com/prometheus/prometheus/model/labels" @@ -44,17 +45,19 @@ type histogramOperator struct { // seriesBuckets are the buckets for each individual conventional histogram series. seriesBuckets []buckets + model.OperatorTelemetry } -func NewHistogramOperator(pool *model.VectorPool, args parser.Expressions, nextOps []model.VectorOperator, stepsBatch int) (model.VectorOperator, error) { - return &histogramOperator{ - pool: pool, - funcArgs: args, - once: sync.Once{}, - scalarOp: nextOps[0], - vectorOp: nextOps[1], - scalarPoints: make([]float64, stepsBatch), - }, nil +func (o *histogramOperator) Analyze() (model.OperatorTelemetry, []model.ObservableVectorOperator) { + o.SetName("[*functionOperator]") + next := make([]model.ObservableVectorOperator, 0, 2) + if obsScalarOp, ok := o.scalarOp.(model.ObservableVectorOperator); ok { + next = append(next, obsScalarOp) + } + if obsVectorOp, ok := o.vectorOp.(model.ObservableVectorOperator); ok { + next = append(next, obsVectorOp) + } + return o, next } func (o *histogramOperator) Explain() (me string, next []model.VectorOperator) { @@ -82,7 +85,7 @@ func (o *histogramOperator) Next(ctx context.Context) ([]model.StepVector, error return nil, ctx.Err() default: } - + start := time.Now() var err error o.once.Do(func() { err = o.loadSeries(ctx) }) if err != nil { @@ -111,6 +114,7 @@ func (o *histogramOperator) Next(ctx context.Context) ([]model.StepVector, error o.scalarOp.GetPool().PutStepVector(scalar) } o.scalarOp.GetPool().PutVectors(scalars) + o.AddExecutionTimeTaken(time.Since(start)) return o.processInputSeries(vectors) } diff --git a/vendor/github.com/thanos-io/promql-engine/execution/function/noarg.go b/vendor/github.com/thanos-io/promql-engine/execution/function/noarg.go new file mode 100644 index 00000000000..fef2813095b --- /dev/null +++ b/vendor/github.com/thanos-io/promql-engine/execution/function/noarg.go @@ -0,0 +1,65 @@ +// Copyright (c) The Thanos Community Authors. +// Licensed under the Apache License 2.0. + +package function + +import ( + "context" + "fmt" + "time" + + "github.com/prometheus/prometheus/model/labels" + + "github.com/thanos-io/promql-engine/execution/model" + "github.com/thanos-io/promql-engine/parser" +) + +type noArgFunctionOperator struct { + mint int64 + maxt int64 + step int64 + currentStep int64 + stepsBatch int + funcExpr *parser.Call + call noArgFunctionCall + vectorPool *model.VectorPool + series []labels.Labels + sampleIDs []uint64 + model.OperatorTelemetry +} + +func (o *noArgFunctionOperator) Analyze() (model.OperatorTelemetry, []model.ObservableVectorOperator) { + o.SetName("[*noArgFunctionOperator]") + return o, []model.ObservableVectorOperator{} +} + +func (o *noArgFunctionOperator) Explain() (me string, next []model.VectorOperator) { + + return fmt.Sprintf("[*noArgFunctionOperator] %v()", o.funcExpr.Func.Name), []model.VectorOperator{} +} + +func (o *noArgFunctionOperator) Series(_ context.Context) ([]labels.Labels, error) { + return o.series, nil +} + +func (o *noArgFunctionOperator) GetPool() *model.VectorPool { + return o.vectorPool +} + +func (o *noArgFunctionOperator) Next(_ context.Context) ([]model.StepVector, error) { + if o.currentStep > o.maxt { + return nil, nil + } + start := time.Now() + ret := o.vectorPool.GetVectorBatch() + for i := 0; i < o.stepsBatch && o.currentStep <= o.maxt; i++ { + sv := o.vectorPool.GetStepVector(o.currentStep) + sv.Samples = []float64{o.call(o.currentStep)} + sv.SampleIDs = o.sampleIDs + ret = append(ret, sv) + o.currentStep += o.step + } + o.AddExecutionTimeTaken(time.Since(start)) + + return ret, nil +} diff --git a/vendor/github.com/thanos-io/promql-engine/execution/function/operator.go b/vendor/github.com/thanos-io/promql-engine/execution/function/operator.go index e040d3ff298..7ccc254d3dd 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/function/operator.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/function/operator.go @@ -7,13 +7,11 @@ import ( "context" "fmt" "math" - "strings" "sync" + "time" "github.com/efficientgo/core/errors" - prommodel "github.com/prometheus/common/model" "github.com/prometheus/prometheus/model/labels" - "github.com/prometheus/prometheus/promql" "github.com/thanos-io/promql-engine/execution/model" "github.com/thanos-io/promql-engine/execution/parse" @@ -30,96 +28,108 @@ type functionOperator struct { vectorIndex int nextOps []model.VectorOperator - call FunctionCall + call functionCall scalarPoints [][]float64 - sampleBuf []promql.Sample + model.OperatorTelemetry } -type noArgFunctionOperator struct { - mint int64 - maxt int64 - step int64 - currentStep int64 - stepsBatch int - funcExpr *parser.Call - call FunctionCall - vectorPool *model.VectorPool - series []labels.Labels - sampleIDs []uint64 +func SetTelemetry(opts *query.Options) model.OperatorTelemetry { + if opts.EnableAnalysis { + return &model.TrackedTelemetry{} + } + return &model.NoopTelemetry{} } -func (o *noArgFunctionOperator) Explain() (me string, next []model.VectorOperator) { - return fmt.Sprintf("[*noArgFunctionOperator] %v()", o.funcExpr.Func.Name), []model.VectorOperator{} -} +func NewFunctionOperator(funcExpr *parser.Call, nextOps []model.VectorOperator, stepsBatch int, opts *query.Options) (model.VectorOperator, error) { + // Some functions need to be handled in special operators -func (o *noArgFunctionOperator) Series(_ context.Context) ([]labels.Labels, error) { - return o.series, nil -} + switch funcExpr.Func.Name { + case "scalar": + return &scalarFunctionOperator{ + next: nextOps[0], + pool: model.NewVectorPoolWithSize(stepsBatch, 1), + OperatorTelemetry: SetTelemetry(opts), + }, nil -func (o *noArgFunctionOperator) GetPool() *model.VectorPool { - return o.vectorPool -} + case "label_join", "label_replace": + return &relabelFunctionOperator{ + next: nextOps[0], + funcExpr: funcExpr, + OperatorTelemetry: SetTelemetry(opts), + }, nil -func (o *noArgFunctionOperator) Next(_ context.Context) ([]model.StepVector, error) { - if o.currentStep > o.maxt { - return nil, nil - } - fa := FunctionArgs{} - ret := o.vectorPool.GetVectorBatch() - for i := 0; i < o.stepsBatch && o.currentStep <= o.maxt; i++ { - sv := o.vectorPool.GetStepVector(o.currentStep) - fa.StepTime = o.currentStep - result := o.call(fa) - sv.Samples = []float64{result.F} - sv.SampleIDs = o.sampleIDs - - ret = append(ret, sv) - o.currentStep += o.step + case "absent": + return &absentOperator{ + next: nextOps[0], + pool: model.NewVectorPool(stepsBatch), + funcExpr: funcExpr, + OperatorTelemetry: SetTelemetry(opts), + }, nil + + case "histogram_quantile": + return &histogramOperator{ + pool: model.NewVectorPool(stepsBatch), + funcArgs: funcExpr.Args, + once: sync.Once{}, + scalarOp: nextOps[0], + vectorOp: nextOps[1], + scalarPoints: make([]float64, stepsBatch), + OperatorTelemetry: SetTelemetry(opts), + }, nil } - return ret, nil + // Short-circuit functions that take no args. Their only input is the step's timestamp. + if len(nextOps) == 0 { + return newNoArgsFunctionOperator(funcExpr, stepsBatch, opts) + } + // All remaining functions + return newInstantVectorFunctionOperator(funcExpr, nextOps, stepsBatch, opts) } -func NewFunctionOperator(funcExpr *parser.Call, call FunctionCall, nextOps []model.VectorOperator, stepsBatch int, opts *query.Options) (model.VectorOperator, error) { +func newNoArgsFunctionOperator(funcExpr *parser.Call, stepsBatch int, opts *query.Options) (model.VectorOperator, error) { + call, ok := noArgFuncs[funcExpr.Func.Name] + if !ok { + return nil, parse.UnknownFunctionError(funcExpr.Func) + } + interval := opts.Step.Milliseconds() // We set interval to be at least 1. if interval == 0 { interval = 1 } + op := &noArgFunctionOperator{ + currentStep: opts.Start.UnixMilli(), + mint: opts.Start.UnixMilli(), + maxt: opts.End.UnixMilli(), + step: interval, + stepsBatch: stepsBatch, + funcExpr: funcExpr, + call: call, + vectorPool: model.NewVectorPool(stepsBatch), + } switch funcExpr.Func.Name { - case "scalar": - return &scalarFunctionOperator{ - next: nextOps[0], - pool: model.NewVectorPool(stepsBatch), - }, nil + case "pi", "time": + op.sampleIDs = []uint64{0} + default: + // Other functions require non-nil labels. + op.series = []labels.Labels{{}} + op.sampleIDs = []uint64{0} + } + op.OperatorTelemetry = &model.NoopTelemetry{} + if opts.EnableAnalysis { + op.OperatorTelemetry = &model.TrackedTelemetry{} } - // Short-circuit functions that take no args. Their only input is the step's timestamp. - if len(nextOps) == 0 { - - op := &noArgFunctionOperator{ - currentStep: opts.Start.UnixMilli(), - mint: opts.Start.UnixMilli(), - maxt: opts.End.UnixMilli(), - step: interval, - stepsBatch: stepsBatch, - funcExpr: funcExpr, - call: call, - vectorPool: model.NewVectorPool(stepsBatch), - } - - switch funcExpr.Func.Name { - case "pi", "time": - op.sampleIDs = []uint64{0} - default: - // Other functions require non-nil labels. - op.series = []labels.Labels{{}} - op.sampleIDs = []uint64{0} - } + return op, nil +} - return op, nil +func newInstantVectorFunctionOperator(funcExpr *parser.Call, nextOps []model.VectorOperator, stepsBatch int, opts *query.Options) (model.VectorOperator, error) { + call, ok := instantVectorFuncs[funcExpr.Func.Name] + if !ok { + return nil, parse.UnknownFunctionError(funcExpr.Func) } + scalarPoints := make([][]float64, stepsBatch) for i := 0; i < stepsBatch; i++ { scalarPoints[i] = make([]float64, len(nextOps)-1) @@ -130,7 +140,6 @@ func NewFunctionOperator(funcExpr *parser.Call, call FunctionCall, nextOps []mod funcExpr: funcExpr, vectorIndex: 0, scalarPoints: scalarPoints, - sampleBuf: make([]promql.Sample, 1), } for i := range funcExpr.Args { @@ -139,9 +148,12 @@ func NewFunctionOperator(funcExpr *parser.Call, call FunctionCall, nextOps []mod break } } + f.OperatorTelemetry = &model.NoopTelemetry{} + if opts.EnableAnalysis { + f.OperatorTelemetry = &model.TrackedTelemetry{} + } // Check selector type. - // TODO(saswatamcode): Add support for matrix. switch funcExpr.Args[f.vectorIndex].Type() { case parser.ValueTypeVector, parser.ValueTypeScalar: return f, nil @@ -150,6 +162,17 @@ func NewFunctionOperator(funcExpr *parser.Call, call FunctionCall, nextOps []mod } } +func (o *functionOperator) Analyze() (model.OperatorTelemetry, []model.ObservableVectorOperator) { + o.SetName("[*functionOperator]") + obsOperators := make([]model.ObservableVectorOperator, 0, len(o.nextOps)) + for _, operator := range o.nextOps { + if obsOperator, ok := operator.(model.ObservableVectorOperator); ok { + obsOperators = append(obsOperators, obsOperator) + } + } + return o, obsOperators +} + func (o *functionOperator) Explain() (me string, next []model.VectorOperator) { return fmt.Sprintf("[*functionOperator] %v(%v)", o.funcExpr.Func.Name, o.funcExpr.Args), o.nextOps } @@ -176,7 +199,7 @@ func (o *functionOperator) Next(ctx context.Context) ([]model.StepVector, error) if err := o.loadSeries(ctx); err != nil { return nil, err } - + start := time.Now() // Process non-variadic single/multi-arg instant vector and scalar input functions. // Call next on vector input. vectors, err := o.nextOps[o.vectorIndex].Next(ctx) @@ -187,10 +210,6 @@ func (o *functionOperator) Next(ctx context.Context) ([]model.StepVector, error) if len(vectors) == 0 { return nil, nil } - if o.funcExpr.Func.Name == "label_join" { - return vectors, nil - } - scalarIndex := 0 for i := range o.nextOps { if i == o.vectorIndex { @@ -213,22 +232,11 @@ func (o *functionOperator) Next(ctx context.Context) ([]model.StepVector, error) o.nextOps[i].GetPool().PutVectors(scalarVectors) scalarIndex++ } - lblsBuilder := labels.ScratchBuilder{} for batchIndex, vector := range vectors { i := 0 - fa := FunctionArgs{} for i < len(vectors[batchIndex].Samples) { - o.sampleBuf[0].H = nil - o.sampleBuf[0].F = vector.Samples[i] - fa.Labels = o.series[0] - fa.Samples = o.sampleBuf - fa.StepTime = vector.T - fa.ScalarPoints = o.scalarPoints[batchIndex] - fa.LabelsBuilder = lblsBuilder - result := o.call(fa) - - if result.T != InvalidSample.T { - vector.Samples[i] = result.F + if v, ok := o.call(vector.Samples[i], nil, o.scalarPoints[batchIndex]...); ok { + vector.Samples[i] = v i++ } else { // This operator modifies samples directly in the input vector to avoid allocations. @@ -239,25 +247,20 @@ func (o *functionOperator) Next(ctx context.Context) ([]model.StepVector, error) i = 0 for i < len(vectors[batchIndex].Histograms) { - o.sampleBuf[0].H = vector.Histograms[i] - fa.Labels = o.series[0] - fa.Samples = o.sampleBuf - fa.StepTime = vector.T - fa.ScalarPoints = o.scalarPoints[batchIndex] - fa.LabelsBuilder = lblsBuilder - result := o.call(fa) - + v, ok := o.call(0., vector.Histograms[i], o.scalarPoints[batchIndex]...) // This operator modifies samples directly in the input vector to avoid allocations. // All current functions for histograms produce a float64 sample. It's therefore safe to // always remove the input histogram so that it does not propagate to the output. sampleID := vectors[batchIndex].HistogramIDs[i] vectors[batchIndex].RemoveHistogram(i) - if result.T != InvalidSample.T { - vectors[batchIndex].AppendSample(o.GetPool(), sampleID, result.F) + if ok { + vectors[batchIndex].AppendSample(o.GetPool(), sampleID, v) } } } + o.AddExecutionTimeTaken(time.Since(start)) + return vectors, nil } @@ -269,58 +272,16 @@ func (o *functionOperator) loadSeries(ctx context.Context) error { return } - if o.funcExpr.Func.Name == "scalar" { - o.series = []labels.Labels{} - return - } - series, loadErr := o.nextOps[o.vectorIndex].Series(ctx) if loadErr != nil { err = loadErr return } - o.series = make([]labels.Labels, len(series)) - var labelJoinDst string - var labelJoinSep string - var labelJoinSrcLabels []string - if o.funcExpr.Func.Name == "label_join" { - l := len(o.funcExpr.Args) - labelJoinDst = o.funcExpr.Args[1].(*parser.StringLiteral).Val - if !prommodel.LabelName(labelJoinDst).IsValid() { - err = errors.Newf("invalid destination label name in label_join: %s", labelJoinDst) - return - } - labelJoinSep = o.funcExpr.Args[2].(*parser.StringLiteral).Val - for j := 3; j < l; j++ { - labelJoinSrcLabels = append(labelJoinSrcLabels, o.funcExpr.Args[j].(*parser.StringLiteral).Val) - } - } b := labels.ScratchBuilder{} for i, s := range series { - lbls := s - switch o.funcExpr.Func.Name { - case "last_over_time": - case "label_join": - srcVals := make([]string, len(labelJoinSrcLabels)) - - for j, src := range labelJoinSrcLabels { - srcVals[j] = lbls.Get(src) - } - lb := labels.NewBuilder(lbls) - - strval := strings.Join(srcVals, labelJoinSep) - if strval == "" { - lb.Del(labelJoinDst) - } else { - lb.Set(labelJoinDst, strval) - } - - lbls = lb.Labels() - default: - lbls, _ = DropMetricName(s, b) - } + lbls, _ := DropMetricName(s, b) o.series[i] = lbls } }) diff --git a/vendor/github.com/thanos-io/promql-engine/execution/function/relabel.go b/vendor/github.com/thanos-io/promql-engine/execution/function/relabel.go new file mode 100644 index 00000000000..5b1600c4fbb --- /dev/null +++ b/vendor/github.com/thanos-io/promql-engine/execution/function/relabel.go @@ -0,0 +1,135 @@ +// Copyright (c) The Thanos Community Authors. +// Licensed under the Apache License 2.0. + +package function + +import ( + "context" + "regexp" + "strings" + "sync" + "time" + + "github.com/efficientgo/core/errors" + prommodel "github.com/prometheus/common/model" + "github.com/prometheus/prometheus/model/labels" + + "github.com/thanos-io/promql-engine/execution/model" + "github.com/thanos-io/promql-engine/parser" +) + +type relabelFunctionOperator struct { + next model.VectorOperator + funcExpr *parser.Call + once sync.Once + series []labels.Labels + model.OperatorTelemetry +} + +func (o *relabelFunctionOperator) Analyze() (model.OperatorTelemetry, []model.ObservableVectorOperator) { + o.SetName("[*relabelFunctionOperator]") + next := make([]model.ObservableVectorOperator, 0, 1) + if obsnext, ok := o.next.(model.ObservableVectorOperator); ok { + next = append(next, obsnext) + } + return o, next +} + +func (o *relabelFunctionOperator) Explain() (me string, next []model.VectorOperator) { + return "[*relabelFunctionOperator]", []model.VectorOperator{} +} + +func (o *relabelFunctionOperator) Series(ctx context.Context) ([]labels.Labels, error) { + var err error + o.once.Do(func() { err = o.loadSeries(ctx) }) + return o.series, err +} + +func (o *relabelFunctionOperator) GetPool() *model.VectorPool { + return o.next.GetPool() +} + +func (o *relabelFunctionOperator) Next(ctx context.Context) ([]model.StepVector, error) { + start := time.Now() + next, err := o.next.Next(ctx) + o.AddExecutionTimeTaken(time.Since(start)) + return next, err +} + +func (o *relabelFunctionOperator) loadSeries(ctx context.Context) (err error) { + series, err := o.next.Series(ctx) + if err != nil { + return err + } + o.series = make([]labels.Labels, len(series)) + + switch o.funcExpr.Func.Name { + case "label_join": + err = o.loadSeriesForLabelJoin(series) + case "label_replace": + err = o.loadSeriesForLabelReplace(series) + default: + err = errors.Newf("invalid function name for relabel operator: %s", o.funcExpr.Func.Name) + } + return err +} + +func (o *relabelFunctionOperator) loadSeriesForLabelJoin(series []labels.Labels) error { + labelJoinDst := o.funcExpr.Args[1].(*parser.StringLiteral).Val + if !prommodel.LabelName(labelJoinDst).IsValid() { + return errors.Newf("invalid destination label name in label_join: %s", labelJoinDst) + } + + var labelJoinSrcLabels []string + labelJoinSep := o.funcExpr.Args[2].(*parser.StringLiteral).Val + for j := 3; j < len(o.funcExpr.Args); j++ { + labelJoinSrcLabels = append(labelJoinSrcLabels, o.funcExpr.Args[j].(*parser.StringLiteral).Val) + } + for i, s := range series { + lbls := s + srcVals := make([]string, len(labelJoinSrcLabels)) + + for j, src := range labelJoinSrcLabels { + srcVals[j] = lbls.Get(src) + } + lb := labels.NewBuilder(lbls) + if strval := strings.Join(srcVals, labelJoinSep); strval == "" { + lb.Del(labelJoinDst) + } else { + lb.Set(labelJoinDst, strval) + } + o.series[i] = lb.Labels() + } + return nil +} +func (o *relabelFunctionOperator) loadSeriesForLabelReplace(series []labels.Labels) error { + labelReplaceDst := o.funcExpr.Args[1].(*parser.StringLiteral).Val + if !prommodel.LabelName(labelReplaceDst).IsValid() { + return errors.Newf("invalid destination label name in label_replace: %s", labelReplaceDst) + } + labelReplaceRepl := o.funcExpr.Args[2].(*parser.StringLiteral).Val + labelReplaceSrc := o.funcExpr.Args[3].(*parser.StringLiteral).Val + labelReplaceRegexVal := o.funcExpr.Args[4].(*parser.StringLiteral).Val + labelReplaceRegex, err := regexp.Compile("^(?:" + labelReplaceRegexVal + ")$") + if err != nil { + return errors.Newf("invalid regular expression in label_replace(): %s", labelReplaceRegexVal) + } + for i, s := range series { + lbls := s + + srcVal := lbls.Get(labelReplaceSrc) + matches := labelReplaceRegex.FindStringSubmatchIndex(srcVal) + if len(matches) == 0 { + o.series[i] = lbls + continue + } + res := labelReplaceRegex.ExpandString([]byte{}, labelReplaceRepl, srcVal, matches) + lb := labels.NewBuilder(lbls).Del(labelReplaceDst) + if len(res) > 0 { + lb.Set(labelReplaceDst, string(res)) + } + o.series[i] = lb.Labels() + } + + return nil +} diff --git a/vendor/github.com/thanos-io/promql-engine/execution/function/scalar.go b/vendor/github.com/thanos-io/promql-engine/execution/function/scalar.go index 4335b6fe149..9d6a8553170 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/function/scalar.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/function/scalar.go @@ -6,6 +6,7 @@ package function import ( "context" "math" + "time" "github.com/prometheus/prometheus/model/labels" @@ -15,6 +16,16 @@ import ( type scalarFunctionOperator struct { pool *model.VectorPool next model.VectorOperator + model.OperatorTelemetry +} + +func (o *scalarFunctionOperator) Analyze() (model.OperatorTelemetry, []model.ObservableVectorOperator) { + o.SetName("[*scalarFunctionOperator]") + next := make([]model.ObservableVectorOperator, 0, 1) + if obsnext, ok := o.next.(model.ObservableVectorOperator); ok { + next = append(next, obsnext) + } + return o, next } func (o *scalarFunctionOperator) Explain() (me string, next []model.VectorOperator) { @@ -35,6 +46,7 @@ func (o *scalarFunctionOperator) Next(ctx context.Context) ([]model.StepVector, return nil, ctx.Err() default: } + start := time.Now() in, err := o.next.Next(ctx) if err != nil { return nil, err @@ -55,5 +67,7 @@ func (o *scalarFunctionOperator) Next(ctx context.Context) ([]model.StepVector, o.next.GetPool().PutStepVector(vector) } o.next.GetPool().PutVectors(in) + o.AddExecutionTimeTaken(time.Since(start)) + return result, nil } diff --git a/vendor/github.com/thanos-io/promql-engine/execution/model/operator.go b/vendor/github.com/thanos-io/promql-engine/execution/model/operator.go index 40d04eb6717..021a36fe43a 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/model/operator.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/model/operator.go @@ -5,10 +5,59 @@ package model import ( "context" + "time" "github.com/prometheus/prometheus/model/labels" ) +type NoopTelemetry struct{} + +type TrackedTelemetry struct { + name string + ExecutionTime time.Duration +} + +func (ti *NoopTelemetry) AddExecutionTimeTaken(t time.Duration) {} + +func (ti *TrackedTelemetry) AddExecutionTimeTaken(t time.Duration) { + ti.ExecutionTime += t +} + +func (ti *TrackedTelemetry) Name() string { + return ti.name +} + +func (ti *TrackedTelemetry) SetName(operatorName string) { + ti.name = operatorName +} + +func (ti *NoopTelemetry) Name() string { + return "" +} + +func (ti *NoopTelemetry) SetName(operatorName string) {} + +type OperatorTelemetry interface { + AddExecutionTimeTaken(time.Duration) + ExecutionTimeTaken() time.Duration + SetName(string) + Name() string +} + +func (ti *NoopTelemetry) ExecutionTimeTaken() time.Duration { + return time.Duration(0) +} + +func (ti *TrackedTelemetry) ExecutionTimeTaken() time.Duration { + return ti.ExecutionTime +} + +type ObservableVectorOperator interface { + VectorOperator + OperatorTelemetry + Analyze() (OperatorTelemetry, []ObservableVectorOperator) +} + // VectorOperator performs operations on series in step by step fashion. type VectorOperator interface { // Next yields vectors of samples from all series for one or more execution steps. diff --git a/vendor/github.com/thanos-io/promql-engine/execution/model/pool.go b/vendor/github.com/thanos-io/promql-engine/execution/model/pool.go index d04b636bc7e..521be5ffe86 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/model/pool.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/model/pool.go @@ -18,6 +18,12 @@ type VectorPool struct { histograms sync.Pool } +func NewVectorPoolWithSize(stepsBatch, size int) *VectorPool { + pool := NewVectorPool(stepsBatch) + pool.SetStepSize(size) + return pool +} + func NewVectorPool(stepsBatch int) *VectorPool { pool := &VectorPool{} pool.vectors = sync.Pool{ @@ -40,7 +46,7 @@ func NewVectorPool(stepsBatch int) *VectorPool { } pool.histograms = sync.Pool{ New: func() any { - histograms := make([]*histogram.FloatHistogram, 0, pool.stepSize) + histograms := make([]*histogram.FloatHistogram, pool.stepSize)[:0] return &histograms }, } diff --git a/vendor/github.com/thanos-io/promql-engine/execution/parse/functions.go b/vendor/github.com/thanos-io/promql-engine/execution/parse/functions.go index 02d36c281f0..eb731ece248 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/parse/functions.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/parse/functions.go @@ -1,8 +1,14 @@ package parse -import "github.com/thanos-io/promql-engine/parser" +import ( + "fmt" -var Functions = map[string]*parser.Function{ + "github.com/efficientgo/core/errors" + + "github.com/thanos-io/promql-engine/parser" +) + +var XFunctions = map[string]*parser.Function{ "xdelta": { Name: "xdelta", ArgTypes: []parser.ValueType{parser.ValueTypeMatrix}, @@ -19,3 +25,18 @@ var Functions = map[string]*parser.Function{ ReturnType: parser.ValueTypeVector, }, } + +// IsExtFunction is a convenience function to determine whether extended range calculations are required. +func IsExtFunction(functionName string) bool { + _, ok := XFunctions[functionName] + return ok +} + +func UnknownFunctionError(f *parser.Function) error { + msg := fmt.Sprintf("unknown function: %s", f.Name) + if _, ok := parser.Functions[f.Name]; ok { + return errors.Wrap(ErrNotImplemented, msg) + } + + return errors.Wrap(ErrNotSupportedExpr, msg) +} diff --git a/vendor/github.com/thanos-io/promql-engine/execution/remote/operator.go b/vendor/github.com/thanos-io/promql-engine/execution/remote/operator.go index f9d0eb6aa6e..3e232fa2a2d 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/remote/operator.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/remote/operator.go @@ -24,17 +24,28 @@ type Execution struct { opts *query.Options queryRangeStart time.Time vectorSelector model.VectorOperator + model.OperatorTelemetry } func NewExecution(query promql.Query, pool *model.VectorPool, queryRangeStart time.Time, opts *query.Options) *Execution { storage := newStorageFromQuery(query, opts) - return &Execution{ + e := &Execution{ storage: storage, query: query, opts: opts, queryRangeStart: queryRangeStart, vectorSelector: scan.NewVectorSelector(pool, storage, opts, 0, 0, 1), } + e.OperatorTelemetry = &model.NoopTelemetry{} + if opts.EnableAnalysis { + e.OperatorTelemetry = &model.TrackedTelemetry{} + } + return e +} + +func (e *Execution) Analyze() (model.OperatorTelemetry, []model.ObservableVectorOperator) { + e.SetName("[*remoteExec]") + return e, nil } func (e *Execution) Series(ctx context.Context) ([]labels.Labels, error) { @@ -42,7 +53,9 @@ func (e *Execution) Series(ctx context.Context) ([]labels.Labels, error) { } func (e *Execution) Next(ctx context.Context) ([]model.StepVector, error) { + start := time.Now() next, err := e.vectorSelector.Next(ctx) + e.AddExecutionTimeTaken(time.Since(start)) if next == nil { // Closing the storage prematurely can lead to results from the query // engine to be recycled. Because of this, we close the storage only @@ -106,12 +119,15 @@ func (s *storageAdapter) executeQuery(ctx context.Context) { case promql.Vector: s.series = make([]engstore.SignedSeries, len(val)) for i, sample := range val { + series := promql.Series{Metric: sample.Metric} + if sample.H == nil { + series.Floats = []promql.FPoint{{T: sample.T, F: sample.F}} + } else { + series.Histograms = []promql.HPoint{{T: sample.T, H: sample.H}} + } s.series[i] = engstore.SignedSeries{ Signature: uint64(i), - Series: promql.NewStorageSeries(promql.Series{ - Metric: sample.Metric, - Floats: []promql.FPoint{{T: sample.T, F: sample.F}}, - }), + Series: promql.NewStorageSeries(series), } } } diff --git a/vendor/github.com/thanos-io/promql-engine/execution/scan/functions.go b/vendor/github.com/thanos-io/promql-engine/execution/scan/functions.go new file mode 100644 index 00000000000..3a9031a5ae2 --- /dev/null +++ b/vendor/github.com/thanos-io/promql-engine/execution/scan/functions.go @@ -0,0 +1,610 @@ +// Copyright (c) The Thanos Community Authors. +// Licensed under the Apache License 2.0. + +package scan + +import ( + "math" + + "github.com/prometheus/prometheus/model/histogram" +) + +type sample struct { + T int64 + F float64 + H *histogram.FloatHistogram +} + +type functionArgs struct { + Samples []sample + StepTime int64 + SelectRange int64 + ScalarPoints []float64 + Offset int64 + MetricAppearedTs *int64 +} + +type functionCall func(f functionArgs) (float64, *histogram.FloatHistogram, bool) + +func instantValue(samples []sample, isRate bool) (float64, bool) { + lastSample := samples[len(samples)-1] + previousSample := samples[len(samples)-2] + + var resultValue float64 + if isRate && lastSample.F < previousSample.F { + // Counter reset. + resultValue = lastSample.F + } else { + resultValue = lastSample.F - previousSample.F + } + + sampledInterval := lastSample.T - previousSample.T + if sampledInterval == 0 { + // Avoid dividing by 0. + return 0, false + } + + if isRate { + // Convert to per-second. + resultValue /= float64(sampledInterval) / 1000 + } + + return resultValue, true +} + +var rangeVectorFuncs = map[string]functionCall{ + "sum_over_time": func(f functionArgs) (float64, *histogram.FloatHistogram, bool) { + if len(f.Samples) == 0 { + return 0., nil, false + } + return sumOverTime(f.Samples), nil, true + }, + "max_over_time": func(f functionArgs) (float64, *histogram.FloatHistogram, bool) { + if len(f.Samples) == 0 { + return 0., nil, false + } + return maxOverTime(f.Samples), nil, true + }, + "min_over_time": func(f functionArgs) (float64, *histogram.FloatHistogram, bool) { + if len(f.Samples) == 0 { + return 0., nil, false + } + return minOverTime(f.Samples), nil, true + }, + "avg_over_time": func(f functionArgs) (float64, *histogram.FloatHistogram, bool) { + if len(f.Samples) == 0 { + return 0., nil, false + } + return avgOverTime(f.Samples), nil, true + }, + "stddev_over_time": func(f functionArgs) (float64, *histogram.FloatHistogram, bool) { + if len(f.Samples) == 0 { + return 0., nil, false + } + return stddevOverTime(f.Samples), nil, true + }, + "stdvar_over_time": func(f functionArgs) (float64, *histogram.FloatHistogram, bool) { + if len(f.Samples) == 0 { + return 0., nil, false + } + return stdvarOverTime(f.Samples), nil, true + }, + "count_over_time": func(f functionArgs) (float64, *histogram.FloatHistogram, bool) { + if len(f.Samples) == 0 { + return 0., nil, false + } + return countOverTime(f.Samples), nil, true + }, + "last_over_time": func(f functionArgs) (float64, *histogram.FloatHistogram, bool) { + if len(f.Samples) == 0 { + return 0., nil, false + } + return f.Samples[len(f.Samples)-1].F, nil, true + }, + "present_over_time": func(f functionArgs) (float64, *histogram.FloatHistogram, bool) { + if len(f.Samples) == 0 { + return 0., nil, false + } + return 1., nil, true + }, + "changes": func(f functionArgs) (float64, *histogram.FloatHistogram, bool) { + if len(f.Samples) == 0 { + return 0., nil, false + } + return changes(f.Samples), nil, true + }, + "resets": func(f functionArgs) (float64, *histogram.FloatHistogram, bool) { + if len(f.Samples) == 0 { + return 0., nil, false + } + return resets(f.Samples), nil, true + }, + "deriv": func(f functionArgs) (float64, *histogram.FloatHistogram, bool) { + if len(f.Samples) < 2 { + return 0., nil, false + } + return deriv(f.Samples), nil, true + }, + "irate": func(f functionArgs) (float64, *histogram.FloatHistogram, bool) { + f.Samples = filterFloatOnlySamples(f.Samples) + if len(f.Samples) < 2 { + return 0., nil, false + } + val, ok := instantValue(f.Samples, true) + if !ok { + return 0., nil, false + } + return val, nil, true + }, + "idelta": func(f functionArgs) (float64, *histogram.FloatHistogram, bool) { + f.Samples = filterFloatOnlySamples(f.Samples) + if len(f.Samples) < 2 { + return 0., nil, false + } + val, ok := instantValue(f.Samples, false) + if !ok { + return 0., nil, false + } + return val, nil, true + }, + "rate": func(f functionArgs) (float64, *histogram.FloatHistogram, bool) { + if len(f.Samples) < 2 { + return 0., nil, false + } + v, h := extrapolatedRate(f.Samples, true, true, f.StepTime, f.SelectRange, f.Offset) + return v, h, true + }, + "delta": func(f functionArgs) (float64, *histogram.FloatHistogram, bool) { + if len(f.Samples) < 2 { + return 0., nil, false + } + v, h := extrapolatedRate(f.Samples, false, false, f.StepTime, f.SelectRange, f.Offset) + return v, h, true + }, + "increase": func(f functionArgs) (float64, *histogram.FloatHistogram, bool) { + if len(f.Samples) < 2 { + return 0., nil, false + } + v, h := extrapolatedRate(f.Samples, true, false, f.StepTime, f.SelectRange, f.Offset) + return v, h, true + }, + "xrate": func(f functionArgs) (float64, *histogram.FloatHistogram, bool) { + if len(f.Samples) == 0 { + return 0., nil, false + } + if f.MetricAppearedTs == nil { + panic("BUG: we got some Samples but metric still hasn't appeared") + } + v, h := extendedRate(f.Samples, true, true, f.StepTime, f.SelectRange, f.Offset, *f.MetricAppearedTs) + return v, h, true + }, + "xdelta": func(f functionArgs) (float64, *histogram.FloatHistogram, bool) { + if len(f.Samples) == 0 { + return 0., nil, false + } + if f.MetricAppearedTs == nil { + panic("BUG: we got some Samples but metric still hasn't appeared") + } + v, h := extendedRate(f.Samples, false, false, f.StepTime, f.SelectRange, f.Offset, *f.MetricAppearedTs) + return v, h, true + }, + "xincrease": func(f functionArgs) (float64, *histogram.FloatHistogram, bool) { + if len(f.Samples) == 0 { + return 0., nil, false + } + if f.MetricAppearedTs == nil { + panic("BUG: we got some Samples but metric still hasn't appeared") + } + v, h := extendedRate(f.Samples, true, false, f.StepTime, f.SelectRange, f.Offset, *f.MetricAppearedTs) + return v, h, true + }, +} + +// extrapolatedRate is a utility function for rate/increase/delta. +// It calculates the rate (allowing for counter resets if isCounter is true), +// extrapolates if the first/last sample is close to the boundary, and returns +// the result as either per-second (if isRate is true) or overall. +func extrapolatedRate(samples []sample, isCounter, isRate bool, stepTime int64, selectRange int64, offset int64) (float64, *histogram.FloatHistogram) { + var ( + rangeStart = stepTime - (selectRange + offset) + rangeEnd = stepTime - offset + resultValue float64 + resultHistogram *histogram.FloatHistogram + ) + + if samples[0].H != nil { + resultHistogram = histogramRate(samples, isCounter) + } else { + resultValue = samples[len(samples)-1].F - samples[0].F + if isCounter { + var lastValue float64 + for _, sample := range samples { + if sample.F < lastValue { + resultValue += lastValue + } + lastValue = sample.F + } + } + } + + // Duration between first/last Samples and boundary of range. + durationToStart := float64(samples[0].T-rangeStart) / 1000 + durationToEnd := float64(rangeEnd-samples[len(samples)-1].T) / 1000 + + sampledInterval := float64(samples[len(samples)-1].T-samples[0].T) / 1000 + averageDurationBetweenSamples := sampledInterval / float64(len(samples)-1) + + if isCounter && resultValue > 0 && samples[0].F >= 0 { + // Counters cannot be negative. If we have any slope at + // all (i.e. resultValue went up), we can extrapolate + // the zero point of the counter. If the duration to the + // zero point is shorter than the durationToStart, we + // take the zero point as the start of the series, + // thereby avoiding extrapolation to negative counter + // values. + durationToZero := sampledInterval * (samples[0].F / resultValue) + if durationToZero < durationToStart { + durationToStart = durationToZero + } + } + + // If the first/last Samples are close to the boundaries of the range, + // extrapolate the result. This is as we expect that another sample + // will exist given the spacing between Samples we've seen thus far, + // with an allowance for noise. + extrapolationThreshold := averageDurationBetweenSamples * 1.1 + extrapolateToInterval := sampledInterval + + if durationToStart < extrapolationThreshold { + extrapolateToInterval += durationToStart + } else { + extrapolateToInterval += averageDurationBetweenSamples / 2 + } + if durationToEnd < extrapolationThreshold { + extrapolateToInterval += durationToEnd + } else { + extrapolateToInterval += averageDurationBetweenSamples / 2 + } + factor := extrapolateToInterval / sampledInterval + if isRate { + factor /= float64(selectRange / 1000) + } + if resultHistogram == nil { + resultValue *= factor + } else { + resultHistogram.Mul(factor) + + } + + return resultValue, resultHistogram +} + +// extendedRate is a utility function for xrate/xincrease/xdelta. +// It calculates the rate (allowing for counter resets if isCounter is true), +// taking into account the last sample before the range start, and returns +// the result as either per-second (if isRate is true) or overall. +func extendedRate(samples []sample, isCounter, isRate bool, stepTime int64, selectRange int64, offset int64, metricAppearedTs int64) (float64, *histogram.FloatHistogram) { + var ( + rangeStart = stepTime - (selectRange + offset) + rangeEnd = stepTime - offset + resultValue float64 + resultHistogram *histogram.FloatHistogram + ) + + if samples[0].H != nil { + // TODO - support extended rate for histograms + resultHistogram = histogramRate(samples, isCounter) + return resultValue, resultHistogram + } + + sameVals := true + for i := range samples { + if i > 0 && samples[i-1].F != samples[i].F { + sameVals = false + break + } + } + + // This effectively injects a "zero" series for xincrease if we only have one sample. + // Only do it for some time when the metric appears the first time. + until := selectRange + metricAppearedTs + if isCounter && !isRate && sameVals { + // Make sure we are not at the end of the range. + if stepTime-offset <= until { + return samples[0].F, nil + } + } + + sampledInterval := float64(samples[len(samples)-1].T - samples[0].T) + averageDurationBetweenSamples := sampledInterval / float64(len(samples)-1) + + firstPoint := 0 + // Only do this for not xincrease + if !(isCounter && !isRate) { + // If the point before the range is too far from rangeStart, drop it. + if float64(rangeStart-samples[0].T) > averageDurationBetweenSamples { + if len(samples) < 3 { + return resultValue, nil + } + firstPoint = 1 + sampledInterval = float64(samples[len(samples)-1].T - samples[1].T) + averageDurationBetweenSamples = sampledInterval / float64(len(samples)-2) + } + } + + var ( + counterCorrection float64 + lastValue float64 + ) + if isCounter { + for i := firstPoint; i < len(samples); i++ { + sample := samples[i] + if sample.F < lastValue { + counterCorrection += lastValue + } + lastValue = sample.F + } + } + resultValue = samples[len(samples)-1].F - samples[firstPoint].F + counterCorrection + + // Duration between last sample and boundary of range. + durationToEnd := float64(rangeEnd - samples[len(samples)-1].T) + // If the points cover the whole range (i.e. they start just before the + // range start and end just before the range end) adjust the value from + // the sampled range to the requested range. + // Only do this for not xincrease. + if !(isCounter && !isRate) { + if samples[firstPoint].T <= rangeStart && durationToEnd < averageDurationBetweenSamples { + adjustToRange := float64(selectRange / 1000) + resultValue = resultValue * (adjustToRange / (sampledInterval / 1000)) + } + } + + if isRate { + resultValue = resultValue / float64(selectRange/1000) + } + + return resultValue, nil +} + +// histogramRate is a helper function for extrapolatedRate. It requires +// points[0] to be a histogram. It returns nil if any other Point in points is +// not a histogram. +func histogramRate(points []sample, isCounter bool) *histogram.FloatHistogram { + prev := points[0].H // We already know that this is a histogram. + last := points[len(points)-1].H + if last == nil { + return nil // Range contains a mix of histograms and floats. + } + minSchema := prev.Schema + if last.Schema < minSchema { + minSchema = last.Schema + } + + // https://github.com/prometheus/prometheus/blob/ccea61c7bf1e6bce2196ba8189a209945a204c5b/promql/functions.go#L183 + // First iteration to find out two things: + // - What's the smallest relevant schema? + // - Are all data points histograms? + // []FloatPoint and a []HistogramPoint separately. + for _, currPoint := range points[1 : len(points)-1] { + curr := currPoint.H + if curr == nil { + return nil // Range contains a mix of histograms and floats. + } + if !isCounter { + continue + } + if curr.Schema < minSchema { + minSchema = curr.Schema + } + } + + h := last.CopyToSchema(minSchema) + h.Sub(prev) + + if isCounter { + // Second iteration to deal with counter resets. + for _, currPoint := range points[1:] { + curr := currPoint.H + if curr.DetectReset(prev) { + h.Add(prev) + } + prev = curr + } + } + h.CounterResetHint = histogram.GaugeType + return h.Compact(0) +} + +func maxOverTime(points []sample) float64 { + max := points[0].F + for _, v := range points { + if v.F > max || math.IsNaN(max) { + max = v.F + } + } + return max +} + +func minOverTime(points []sample) float64 { + min := points[0].F + for _, v := range points { + if v.F < min || math.IsNaN(min) { + min = v.F + } + } + return min +} + +func countOverTime(points []sample) float64 { + return float64(len(points)) +} + +func avgOverTime(points []sample) float64 { + var mean, count, c float64 + for _, v := range points { + count++ + if math.IsInf(mean, 0) { + if math.IsInf(v.F, 0) && (mean > 0) == (v.F > 0) { + // The `mean` and `v.F` values are `Inf` of the same sign. They + // can't be subtracted, but the value of `mean` is correct + // already. + continue + } + if !math.IsInf(v.F, 0) && !math.IsNaN(v.F) { + // At this stage, the mean is an infinite. If the added + // value is neither an Inf or a Nan, we can keep that mean + // value. + // This is required because our calculation below removes + // the mean value, which would look like Inf += x - Inf and + // end up as a NaN. + continue + } + } + mean, c = kahanSumInc(v.F/count-mean/count, mean, c) + } + + if math.IsInf(mean, 0) { + return mean + } + return mean + c +} + +func sumOverTime(points []sample) float64 { + var sum, c float64 + for _, v := range points { + sum, c = kahanSumInc(v.F, sum, c) + } + if math.IsInf(sum, 0) { + return sum + } + return sum + c +} + +func stddevOverTime(points []sample) float64 { + var count float64 + var mean, cMean float64 + var aux, cAux float64 + for _, v := range points { + count++ + delta := v.F - (mean + cMean) + mean, cMean = kahanSumInc(delta/count, mean, cMean) + aux, cAux = kahanSumInc(delta*(v.F-(mean+cMean)), aux, cAux) + } + return math.Sqrt((aux + cAux) / count) +} + +func stdvarOverTime(points []sample) float64 { + var count float64 + var mean, cMean float64 + var aux, cAux float64 + for _, v := range points { + count++ + delta := v.F - (mean + cMean) + mean, cMean = kahanSumInc(delta/count, mean, cMean) + aux, cAux = kahanSumInc(delta*(v.F-(mean+cMean)), aux, cAux) + } + return (aux + cAux) / count +} + +func changes(points []sample) float64 { + var count float64 + prev := points[0].F + count = 0 + for _, sample := range points[1:] { + current := sample.F + if current != prev && !(math.IsNaN(current) && math.IsNaN(prev)) { + count++ + } + prev = current + } + return count +} + +func deriv(points []sample) float64 { + // We pass in an arbitrary timestamp that is near the values in use + // to avoid floating point accuracy issues, see + // https://github.com/prometheus/prometheus/issues/2674 + slope, _ := linearRegression(points, points[0].T) + return slope +} + +func resets(points []sample) float64 { + count := 0 + prev := points[0].F + for _, sample := range points[1:] { + current := sample.F + if current < prev { + count++ + } + prev = current + } + + return float64(count) +} + +func linearRegression(Samples []sample, interceptTime int64) (slope, intercept float64) { + var ( + n float64 + sumX, cX float64 + sumY, cY float64 + sumXY, cXY float64 + sumX2, cX2 float64 + initY float64 + constY bool + ) + initY = Samples[0].F + constY = true + for i, sample := range Samples { + // Set constY to false if any new y values are encountered. + if constY && i > 0 && sample.F != initY { + constY = false + } + n += 1.0 + x := float64(sample.T-interceptTime) / 1e3 + sumX, cX = kahanSumInc(x, sumX, cX) + sumY, cY = kahanSumInc(sample.F, sumY, cY) + sumXY, cXY = kahanSumInc(x*sample.F, sumXY, cXY) + sumX2, cX2 = kahanSumInc(x*x, sumX2, cX2) + } + if constY { + if math.IsInf(initY, 0) { + return math.NaN(), math.NaN() + } + return 0, initY + } + sumX = sumX + cX + sumY = sumY + cY + sumXY = sumXY + cXY + sumX2 = sumX2 + cX2 + + covXY := sumXY - sumX*sumY/n + varX := sumX2 - sumX*sumX/n + + slope = covXY / varX + intercept = sumY/n - slope*sumX/n + return slope, intercept +} + +func filterFloatOnlySamples(samples []sample) []sample { + i := 0 + for _, sample := range samples { + if sample.H == nil { + samples[i] = sample + i++ + } + } + samples = samples[:i] + return samples +} + +func kahanSumInc(inc, sum, c float64) (newSum, newC float64) { + t := sum + inc + // Using Neumaier improvement, swap if next term larger than sum. + if math.Abs(sum) >= math.Abs(inc) { + c += (sum - t) + inc + } else { + c += (inc - t) + sum + } + return t, c +} diff --git a/vendor/github.com/thanos-io/promql-engine/execution/scan/literal_selector.go b/vendor/github.com/thanos-io/promql-engine/execution/scan/literal_selector.go index 802f067ac3b..c65192f14fe 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/scan/literal_selector.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/scan/literal_selector.go @@ -7,11 +7,12 @@ import ( "context" "fmt" "sync" + "time" + + "github.com/prometheus/prometheus/model/labels" "github.com/thanos-io/promql-engine/execution/model" "github.com/thanos-io/promql-engine/query" - - "github.com/prometheus/prometheus/model/labels" ) // numberLiteralSelector returns []model.StepVector with same sample value across time range. @@ -27,10 +28,11 @@ type numberLiteralSelector struct { once sync.Once val float64 + model.OperatorTelemetry } func NewNumberLiteralSelector(pool *model.VectorPool, opts *query.Options, val float64) *numberLiteralSelector { - return &numberLiteralSelector{ + op := &numberLiteralSelector{ vectorPool: pool, numSteps: opts.NumSteps(), mint: opts.Start.UnixMilli(), @@ -39,6 +41,18 @@ func NewNumberLiteralSelector(pool *model.VectorPool, opts *query.Options, val f currentStep: opts.Start.UnixMilli(), val: val, } + + op.OperatorTelemetry = &model.NoopTelemetry{} + if opts.EnableAnalysis { + op.OperatorTelemetry = &model.TrackedTelemetry{} + } + + return op +} + +func (o *numberLiteralSelector) Analyze() (model.OperatorTelemetry, []model.ObservableVectorOperator) { + o.SetName("[*numberLiteralSelector] ") + return o, nil } func (o *numberLiteralSelector) Explain() (me string, next []model.VectorOperator) { @@ -60,6 +74,7 @@ func (o *numberLiteralSelector) Next(ctx context.Context) ([]model.StepVector, e return nil, ctx.Err() default: } + start := time.Now() if o.currentStep > o.maxt { return nil, nil @@ -83,6 +98,7 @@ func (o *numberLiteralSelector) Next(ctx context.Context) ([]model.StepVector, e o.step = 1 } o.currentStep += o.step * int64(o.numSteps) + o.AddExecutionTimeTaken(time.Since(start)) return vectors, nil } diff --git a/vendor/github.com/thanos-io/promql-engine/execution/scan/matrix_selector.go b/vendor/github.com/thanos-io/promql-engine/execution/scan/matrix_selector.go index ea58ad7f265..5f7cdf714e5 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/scan/matrix_selector.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/scan/matrix_selector.go @@ -11,12 +11,12 @@ import ( "github.com/prometheus/prometheus/model/labels" "github.com/prometheus/prometheus/model/value" - "github.com/prometheus/prometheus/promql" "github.com/prometheus/prometheus/storage" "github.com/prometheus/prometheus/tsdb/chunkenc" "github.com/thanos-io/promql-engine/execution/function" "github.com/thanos-io/promql-engine/execution/model" + "github.com/thanos-io/promql-engine/execution/parse" engstore "github.com/thanos-io/promql-engine/execution/storage" "github.com/thanos-io/promql-engine/parser" "github.com/thanos-io/promql-engine/query" @@ -25,15 +25,16 @@ import ( type matrixScanner struct { labels labels.Labels signature uint64 - previousSamples []promql.Sample + previousSamples []sample samples *storage.BufferedSeriesIterator metricAppearedTs *int64 + deltaReduced bool } type matrixSelector struct { funcExpr *parser.Call storage engstore.SeriesSelector - call function.FunctionCall + call functionCall scanners []matrixScanner series []labels.Labels once sync.Once @@ -48,34 +49,42 @@ type matrixSelector struct { offset int64 currentStep int64 + isExtFunction bool + shard int numShards int // Lookback delta for extended range functions. extLookbackDelta int64 + model.OperatorTelemetry } // NewMatrixSelector creates operator which selects vector of series over time. func NewMatrixSelector( pool *model.VectorPool, selector engstore.SeriesSelector, - call function.FunctionCall, funcExpr *parser.Call, opts *query.Options, selectRange, offset time.Duration, shard, numShard int, -) model.VectorOperator { - // TODO(fpetkovski): Add offset parameter. - return &matrixSelector{ + +) (model.VectorOperator, error) { + call, ok := rangeVectorFuncs[funcExpr.Func.Name] + if !ok { + return nil, parse.UnknownFunctionError(funcExpr.Func) + } + isExtFunction := parse.IsExtFunction(funcExpr.Func.Name) + m := &matrixSelector{ storage: selector, call: call, funcExpr: funcExpr, vectorPool: pool, - numSteps: opts.NumSteps(), - mint: opts.Start.UnixMilli(), - maxt: opts.End.UnixMilli(), - step: opts.Step.Milliseconds(), + numSteps: opts.NumSteps(), + mint: opts.Start.UnixMilli(), + maxt: opts.End.UnixMilli(), + step: opts.Step.Milliseconds(), + isExtFunction: isExtFunction, selectRange: selectRange.Milliseconds(), offset: offset.Milliseconds(), @@ -86,6 +95,17 @@ func NewMatrixSelector( extLookbackDelta: opts.ExtLookbackDelta.Milliseconds(), } + m.OperatorTelemetry = &model.NoopTelemetry{} + if opts.EnableAnalysis { + m.OperatorTelemetry = &model.TrackedTelemetry{} + } + + return m, nil +} + +func (o *matrixSelector) Analyze() (model.OperatorTelemetry, []model.ObservableVectorOperator) { + o.SetName("[*matrixSelector]") + return o, nil } func (o *matrixSelector) Explain() (me string, next []model.VectorOperator) { @@ -113,6 +133,7 @@ func (o *matrixSelector) Next(ctx context.Context) ([]model.StepVector, error) { return nil, ctx.Err() default: } + start := time.Now() if o.currentStep > o.maxt { return nil, nil @@ -131,10 +152,9 @@ func (o *matrixSelector) Next(ctx context.Context) ([]model.StepVector, error) { // Reset the current timestamp. ts = o.currentStep - lblBuilder := labels.ScratchBuilder{} for i := 0; i < len(o.scanners); i++ { var ( - series = o.scanners[i] + series = &o.scanners[i] seriesTs = ts ) @@ -142,13 +162,13 @@ func (o *matrixSelector) Next(ctx context.Context) ([]model.StepVector, error) { maxt := seriesTs - o.offset mint := maxt - o.selectRange - var rangeSamples []promql.Sample + var rangeSamples []sample var err error - if function.IsExtFunction(o.funcExpr.Func.Name) { - rangeSamples, err = selectExtPoints(series.samples, mint, maxt, o.scanners[i].previousSamples, o.extLookbackDelta, &o.scanners[i].metricAppearedTs) - } else { + if !o.isExtFunction { rangeSamples, err = selectPoints(series.samples, mint, maxt, o.scanners[i].previousSamples) + } else { + rangeSamples, err = selectExtPoints(series.samples, mint, maxt, o.scanners[i].previousSamples, o.extLookbackDelta, &o.scanners[i].metricAppearedTs) } if err != nil { @@ -159,22 +179,20 @@ func (o *matrixSelector) Next(ctx context.Context) ([]model.StepVector, error) { // Also, allow operator to exist independently without being nested // under parser.Call by implementing new data model. // https://github.com/thanos-io/promql-engine/issues/39 - result := o.call(function.FunctionArgs{ - Labels: series.labels, + f, h, ok := o.call(functionArgs{ Samples: rangeSamples, StepTime: seriesTs, SelectRange: o.selectRange, Offset: o.offset, MetricAppearedTs: o.scanners[i].metricAppearedTs, - LabelsBuilder: lblBuilder, }) - if result.T != function.InvalidSample.T { - vectors[currStep].T = result.T - if result.H != nil { - vectors[currStep].AppendHistogram(o.vectorPool, series.signature, result.H) + if ok { + vectors[currStep].T = seriesTs + if h != nil { + vectors[currStep].AppendHistogram(o.vectorPool, series.signature, h) } else { - vectors[currStep].AppendSample(o.vectorPool, series.signature, result.F) + vectors[currStep].AppendSample(o.vectorPool, series.signature, f) } } @@ -185,8 +203,9 @@ func (o *matrixSelector) Next(ctx context.Context) ([]model.StepVector, error) { if stepRange > o.step { stepRange = o.step } - if !function.IsExtFunction(o.funcExpr.Func.Name) { + if !series.deltaReduced { series.samples.ReduceDelta(stepRange) + series.deltaReduced = true } seriesTs += o.step @@ -198,7 +217,7 @@ func (o *matrixSelector) Next(ctx context.Context) ([]model.StepVector, error) { o.step = 1 } o.currentStep += o.step * int64(o.numSteps) - + o.AddExecutionTimeTaken(time.Since(start)) return vectors, nil } @@ -227,14 +246,15 @@ func (o *matrixSelector) loadSeries(ctx context.Context) error { // If we are dealing with an extended range function we need to search further in the past for valid series. var selectRange = o.selectRange - if function.IsExtFunction(o.funcExpr.Func.Name) { + if o.isExtFunction { selectRange += o.extLookbackDelta } o.scanners[i] = matrixScanner{ - labels: lbls, - signature: s.Signature, - samples: storage.NewBufferIterator(s.Iterator(nil), selectRange), + labels: lbls, + signature: s.Signature, + samples: storage.NewBufferIterator(s.Iterator(nil), selectRange), + deltaReduced: o.isExtFunction, } o.series[i] = lbls } @@ -252,7 +272,7 @@ func (o *matrixSelector) loadSeries(ctx context.Context) error { // into the [mint, maxt] range are retained; only points with later timestamps // are populated from the iterator. // TODO(fpetkovski): Add max samples limit. -func selectPoints(it *storage.BufferedSeriesIterator, mint, maxt int64, out []promql.Sample) ([]promql.Sample, error) { +func selectPoints(it *storage.BufferedSeriesIterator, mint, maxt int64, out []sample) ([]sample, error) { if len(out) > 0 && out[len(out)-1].T >= mint { // There is an overlap between previous and current ranges, retain common // points. In most such cases: @@ -289,7 +309,7 @@ loop: continue loop } if t >= mint { - out = append(out, promql.Sample{T: t, H: fh}) + out = append(out, sample{T: t, H: fh}) } case chunkenc.ValFloat: t, v := buf.At() @@ -298,7 +318,7 @@ loop: } // Values in the buffer are guaranteed to be smaller than maxt. if t >= mint { - out = append(out, promql.Sample{T: t, F: v}) + out = append(out, sample{T: t, F: v}) } } } @@ -308,12 +328,12 @@ loop: case chunkenc.ValHistogram, chunkenc.ValFloatHistogram: t, fh := it.AtFloatHistogram() if t == maxt && !value.IsStaleNaN(fh.Sum) { - out = append(out, promql.Sample{T: t, H: fh}) + out = append(out, sample{T: t, H: fh}) } case chunkenc.ValFloat: t, v := it.At() if t == maxt && !value.IsStaleNaN(v) { - out = append(out, promql.Sample{T: t, F: v}) + out = append(out, sample{T: t, F: v}) } } @@ -329,7 +349,7 @@ loop: // into the [mint, maxt] range are retained; only points with later timestamps // are populated from the iterator. // TODO(fpetkovski): Add max samples limit. -func selectExtPoints(it *storage.BufferedSeriesIterator, mint, maxt int64, out []promql.Sample, extLookbackDelta int64, metricAppearedTs **int64) ([]promql.Sample, error) { +func selectExtPoints(it *storage.BufferedSeriesIterator, mint, maxt int64, out []sample, extLookbackDelta int64, metricAppearedTs **int64) ([]sample, error) { extMint := mint - extLookbackDelta if len(out) > 0 && out[len(out)-1].T >= mint { @@ -382,7 +402,7 @@ loop: *metricAppearedTs = &t } if t >= mint { - out = append(out, promql.Sample{T: t, H: fh}) + out = append(out, sample{T: t, H: fh}) } case chunkenc.ValFloat: t, v := buf.At() @@ -397,10 +417,10 @@ loop: // exists at or before range start, add it and then keep replacing // it with later points while not yet (strictly) inside the range. if t >= mint || !appendedPointBeforeMint { - out = append(out, promql.Sample{T: t, F: v}) + out = append(out, sample{T: t, F: v}) appendedPointBeforeMint = true } else { - out[len(out)-1] = promql.Sample{T: t, F: v} + out[len(out)-1] = sample{T: t, F: v} } } @@ -414,7 +434,7 @@ loop: if *metricAppearedTs == nil { *metricAppearedTs = &t } - out = append(out, promql.Sample{T: t, H: fh}) + out = append(out, sample{T: t, H: fh}) } case chunkenc.ValFloat: t, v := it.At() @@ -422,7 +442,7 @@ loop: if *metricAppearedTs == nil { *metricAppearedTs = &t } - out = append(out, promql.Sample{T: t, F: v}) + out = append(out, sample{T: t, F: v}) } } diff --git a/vendor/github.com/thanos-io/promql-engine/execution/scan/vector_selector.go b/vendor/github.com/thanos-io/promql-engine/execution/scan/vector_selector.go index ddfe802c21b..4b2c4dd86b6 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/scan/vector_selector.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/scan/vector_selector.go @@ -47,6 +47,7 @@ type vectorSelector struct { shard int numShards int + model.OperatorTelemetry } // NewVectorSelector creates operator which selects vector of series. @@ -57,7 +58,7 @@ func NewVectorSelector( offset time.Duration, shard, numShards int, ) model.VectorOperator { - return &vectorSelector{ + o := &vectorSelector{ storage: selector, vectorPool: pool, @@ -72,6 +73,16 @@ func NewVectorSelector( shard: shard, numShards: numShards, } + o.OperatorTelemetry = &model.NoopTelemetry{} + if queryOpts.EnableAnalysis { + o.OperatorTelemetry = &model.TrackedTelemetry{} + } + return o +} + +func (o *vectorSelector) Analyze() (model.OperatorTelemetry, []model.ObservableVectorOperator) { + o.SetName("[*vectorSelector]") + return o, nil } func (o *vectorSelector) Explain() (me string, next []model.VectorOperator) { @@ -95,7 +106,7 @@ func (o *vectorSelector) Next(ctx context.Context) ([]model.StepVector, error) { return nil, ctx.Err() default: } - + start := time.Now() if o.currentStep > o.maxt { return nil, nil } @@ -140,6 +151,7 @@ func (o *vectorSelector) Next(ctx context.Context) ([]model.StepVector, error) { o.step = 1 } o.currentStep += o.step * int64(o.numSteps) + o.AddExecutionTimeTaken(time.Since(start)) return vectors, nil } diff --git a/vendor/github.com/thanos-io/promql-engine/execution/step_invariant/step_invariant.go b/vendor/github.com/thanos-io/promql-engine/execution/step_invariant/step_invariant.go index 207530c175e..33a2566f371 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/step_invariant/step_invariant.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/step_invariant/step_invariant.go @@ -6,6 +6,7 @@ package step_invariant import ( "context" "sync" + "time" "github.com/efficientgo/core/errors" "github.com/prometheus/prometheus/model/labels" @@ -30,6 +31,16 @@ type stepInvariantOperator struct { step int64 currentStep int64 stepsBatch int + model.OperatorTelemetry +} + +func (u *stepInvariantOperator) Analyze() (model.OperatorTelemetry, []model.ObservableVectorOperator) { + u.SetName("[*stepInvariantOperator]") + next := make([]model.ObservableVectorOperator, 0, 1) + if obsnext, ok := u.next.(model.ObservableVectorOperator); ok { + next = append(next, obsnext) + } + return u, next } func (u *stepInvariantOperator) Explain() (me string, next []model.VectorOperator) { @@ -64,6 +75,10 @@ func NewStepInvariantOperator( case *parser.MatrixSelector, *parser.SubqueryExpr: u.cacheResult = false } + u.OperatorTelemetry = &model.NoopTelemetry{} + if opts.EnableAnalysis { + u.OperatorTelemetry = &model.TrackedTelemetry{} + } return u, nil } @@ -72,6 +87,7 @@ func (u *stepInvariantOperator) Series(ctx context.Context) ([]labels.Labels, er var err error u.seriesOnce.Do(func() { u.series, err = u.next.Series(ctx) + u.vectorPool.SetStepSize(len(u.series)) }) if err != nil { return nil, err @@ -87,6 +103,7 @@ func (u *stepInvariantOperator) Next(ctx context.Context) ([]model.StepVector, e if u.currentStep > u.maxt { return nil, nil } + start := time.Now() select { case <-ctx.Done(): @@ -102,10 +119,6 @@ func (u *stepInvariantOperator) Next(ctx context.Context) ([]model.StepVector, e return nil, err } - if len(u.cachedVector.Samples) == 0 { - return nil, nil - } - result := u.vectorPool.GetVectorBatch() for i := 0; i < u.stepsBatch && u.currentStep <= u.maxt; i++ { outVector := u.vectorPool.GetStepVector(u.currentStep) @@ -114,6 +127,7 @@ func (u *stepInvariantOperator) Next(ctx context.Context) ([]model.StepVector, e result = append(result, outVector) u.currentStep += u.step } + u.AddExecutionTimeTaken(time.Since(start)) return result, nil } diff --git a/vendor/github.com/thanos-io/promql-engine/execution/storage/series_selector.go b/vendor/github.com/thanos-io/promql-engine/execution/storage/series_selector.go index e9f0cf2791b..433fe6a1922 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/storage/series_selector.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/storage/series_selector.go @@ -9,6 +9,8 @@ import ( "github.com/prometheus/prometheus/model/labels" "github.com/prometheus/prometheus/storage" + + "github.com/thanos-io/promql-engine/execution/warnings" ) type SeriesSelector interface { @@ -76,6 +78,7 @@ func (o *seriesSelector) loadSeries(ctx context.Context) error { i++ } + warnings.AddToContext(seriesSet.Warnings(), ctx) return seriesSet.Err() } diff --git a/vendor/github.com/thanos-io/promql-engine/execution/unary/unary.go b/vendor/github.com/thanos-io/promql-engine/execution/unary/unary.go index 46b11b4793c..e1a0a18aa2e 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/unary/unary.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/unary/unary.go @@ -6,6 +6,7 @@ package unary import ( "context" "sync" + "time" "github.com/prometheus/prometheus/model/labels" "gonum.org/v1/gonum/floats" @@ -18,6 +19,7 @@ type unaryNegation struct { once sync.Once series []labels.Labels + model.OperatorTelemetry } func (u *unaryNegation) Explain() (me string, next []model.VectorOperator) { @@ -29,10 +31,20 @@ func NewUnaryNegation( stepsBatch int, ) (model.VectorOperator, error) { u := &unaryNegation{ - next: next, + next: next, + OperatorTelemetry: &model.TrackedTelemetry{}, } + return u, nil } +func (u *unaryNegation) Analyze() (model.OperatorTelemetry, []model.ObservableVectorOperator) { + u.SetName("[*unaryNegation]") + next := make([]model.ObservableVectorOperator, 0, 1) + if obsnext, ok := u.next.(model.ObservableVectorOperator); ok { + next = append(next, obsnext) + } + return u, next +} func (u *unaryNegation) Series(ctx context.Context) ([]labels.Labels, error) { if err := u.loadSeries(ctx); err != nil { @@ -68,7 +80,7 @@ func (u *unaryNegation) Next(ctx context.Context) ([]model.StepVector, error) { return nil, ctx.Err() default: } - + start := time.Now() in, err := u.next.Next(ctx) if err != nil { return nil, err @@ -79,5 +91,6 @@ func (u *unaryNegation) Next(ctx context.Context) ([]model.StepVector, error) { for i := range in { floats.Scale(-1, in[i].Samples) } + u.AddExecutionTimeTaken(time.Since(start)) return in, nil } diff --git a/vendor/github.com/thanos-io/promql-engine/execution/warnings/context.go b/vendor/github.com/thanos-io/promql-engine/execution/warnings/context.go new file mode 100644 index 00000000000..85482247c6d --- /dev/null +++ b/vendor/github.com/thanos-io/promql-engine/execution/warnings/context.go @@ -0,0 +1,54 @@ +package warnings + +import ( + "context" + "sync" + + "github.com/prometheus/prometheus/storage" +) + +type warningKey string + +const key warningKey = "promql-warnings" + +type warnings struct { + mu sync.Mutex + warns storage.Warnings +} + +func newWarnings() *warnings { + return &warnings{ + warns: make(storage.Warnings, 0), + } +} + +func (w *warnings) add(warns storage.Warnings) { + w.mu.Lock() + defer w.mu.Unlock() + w.warns = append(w.warns, warns...) +} + +func (w *warnings) get() storage.Warnings { + w.mu.Lock() + defer w.mu.Unlock() + return w.warns +} + +func NewContext(ctx context.Context) context.Context { + return context.WithValue(ctx, key, newWarnings()) +} + +func AddToContext(warns storage.Warnings, ctx context.Context) { + if len(warns) == 0 { + return + } + w, ok := ctx.Value(key).(*warnings) + if !ok { + return + } + w.add(warns) +} + +func FromContext(ctx context.Context) storage.Warnings { + return ctx.Value(key).(*warnings).get() +} diff --git a/vendor/github.com/thanos-io/promql-engine/logicalplan/distribute.go b/vendor/github.com/thanos-io/promql-engine/logicalplan/distribute.go index 576af424752..bc3a3b36240 100644 --- a/vendor/github.com/thanos-io/promql-engine/logicalplan/distribute.go +++ b/vendor/github.com/thanos-io/promql-engine/logicalplan/distribute.go @@ -156,7 +156,7 @@ func (m DistributedExecutionOptimizer) Optimize(plan parser.Expr, opts *Opts) pa } minEngineOverlap := labelRanges.minOverlap() - traverseBottomUp(nil, &plan, func(parent, current *parser.Expr) (stop bool) { + TraverseBottomUp(nil, &plan, func(parent, current *parser.Expr) (stop bool) { // If the current operation is not distributive, stop the traversal. if !isDistributive(current) { return true diff --git a/vendor/github.com/thanos-io/promql-engine/logicalplan/plan.go b/vendor/github.com/thanos-io/promql-engine/logicalplan/plan.go index 1ad2a69aa28..ad324ed93a1 100644 --- a/vendor/github.com/thanos-io/promql-engine/logicalplan/plan.go +++ b/vendor/github.com/thanos-io/promql-engine/logicalplan/plan.go @@ -98,41 +98,41 @@ func traverse(expr *parser.Expr, transform func(*parser.Expr)) { } } -func traverseBottomUp(parent *parser.Expr, current *parser.Expr, transform func(parent *parser.Expr, node *parser.Expr) bool) bool { +func TraverseBottomUp(parent *parser.Expr, current *parser.Expr, transform func(parent *parser.Expr, node *parser.Expr) bool) bool { switch node := (*current).(type) { case *parser.NumberLiteral: return false case *parser.StepInvariantExpr: - return traverseBottomUp(current, &node.Expr, transform) + return TraverseBottomUp(current, &node.Expr, transform) case *parser.VectorSelector: return transform(parent, current) case *parser.MatrixSelector: return transform(current, &node.VectorSelector) case *parser.AggregateExpr: - if stop := traverseBottomUp(current, &node.Expr, transform); stop { + if stop := TraverseBottomUp(current, &node.Expr, transform); stop { return stop } return transform(parent, current) case *parser.Call: for i := range node.Args { - if stop := traverseBottomUp(current, &node.Args[i], transform); stop { + if stop := TraverseBottomUp(current, &node.Args[i], transform); stop { return stop } } return transform(parent, current) case *parser.BinaryExpr: - lstop := traverseBottomUp(current, &node.LHS, transform) - rstop := traverseBottomUp(current, &node.RHS, transform) + lstop := TraverseBottomUp(current, &node.LHS, transform) + rstop := TraverseBottomUp(current, &node.RHS, transform) if lstop || rstop { return true } return transform(parent, current) case *parser.UnaryExpr: - return traverseBottomUp(current, &node.Expr, transform) + return TraverseBottomUp(current, &node.Expr, transform) case *parser.ParenExpr: - return traverseBottomUp(current, &node.Expr, transform) + return TraverseBottomUp(current, &node.Expr, transform) case *parser.SubqueryExpr: - return traverseBottomUp(current, &node.Expr, transform) + return TraverseBottomUp(current, &node.Expr, transform) } return true diff --git a/vendor/github.com/thanos-io/promql-engine/logicalplan/trim_sorts.go b/vendor/github.com/thanos-io/promql-engine/logicalplan/trim_sorts.go index 6815682e5df..73646510bd4 100644 --- a/vendor/github.com/thanos-io/promql-engine/logicalplan/trim_sorts.go +++ b/vendor/github.com/thanos-io/promql-engine/logicalplan/trim_sorts.go @@ -15,7 +15,7 @@ type TrimSortFunctions struct { } func (TrimSortFunctions) Optimize(expr parser.Expr, _ *Opts) parser.Expr { - traverseBottomUp(nil, &expr, func(parent, current *parser.Expr) bool { + TraverseBottomUp(nil, &expr, func(parent, current *parser.Expr) bool { if current == nil || parent == nil { return true } diff --git a/vendor/github.com/thanos-io/promql-engine/logicalplan/user_defined.go b/vendor/github.com/thanos-io/promql-engine/logicalplan/user_defined.go new file mode 100644 index 00000000000..259b4ea6c3b --- /dev/null +++ b/vendor/github.com/thanos-io/promql-engine/logicalplan/user_defined.go @@ -0,0 +1,22 @@ +package logicalplan + +import ( + "github.com/prometheus/prometheus/storage" + + "github.com/thanos-io/promql-engine/execution/model" + engstore "github.com/thanos-io/promql-engine/execution/storage" + "github.com/thanos-io/promql-engine/parser" + "github.com/thanos-io/promql-engine/query" +) + +// UserDefinedExpr is an extension point which allows users to define their execution operators. +type UserDefinedExpr interface { + parser.Expr + MakeExecutionOperator( + stepsBatch int, + vectors *model.VectorPool, + selectors *engstore.SelectorPool, + opts *query.Options, + hints storage.SelectHints, + ) (model.VectorOperator, error) +} diff --git a/vendor/github.com/thanos-io/promql-engine/query/options.go b/vendor/github.com/thanos-io/promql-engine/query/options.go index 0143eea9f7c..fed4fa2658d 100644 --- a/vendor/github.com/thanos-io/promql-engine/query/options.go +++ b/vendor/github.com/thanos-io/promql-engine/query/options.go @@ -16,7 +16,8 @@ type Options struct { LookbackDelta time.Duration ExtLookbackDelta time.Duration - StepsBatch int64 + StepsBatch int64 + EnableAnalysis bool } func (o *Options) NumSteps() int { diff --git a/vendor/github.com/thanos-io/thanos/pkg/cache/caching_bucket_config.go b/vendor/github.com/thanos-io/thanos/pkg/cache/caching_bucket_config.go index 3422783d6b3..e17b2f27b1c 100644 --- a/vendor/github.com/thanos-io/thanos/pkg/cache/caching_bucket_config.go +++ b/vendor/github.com/thanos-io/thanos/pkg/cache/caching_bucket_config.go @@ -38,30 +38,20 @@ func NewCachingBucketConfig() *CachingBucketConfig { // SetCacheImplementation sets the value of Cache for all configurations. func (cfg *CachingBucketConfig) SetCacheImplementation(c Cache) { - if cfg.get != nil { - for k := range cfg.get { - cfg.get[k].Cache = c - } + for k := range cfg.get { + cfg.get[k].Cache = c } - if cfg.iter != nil { - for k := range cfg.iter { - cfg.iter[k].Cache = c - } + for k := range cfg.iter { + cfg.iter[k].Cache = c } - if cfg.exists != nil { - for k := range cfg.exists { - cfg.exists[k].Cache = c - } + for k := range cfg.exists { + cfg.exists[k].Cache = c } - if cfg.getRange != nil { - for k := range cfg.getRange { - cfg.getRange[k].Cache = c - } + for k := range cfg.getRange { + cfg.getRange[k].Cache = c } - if cfg.attributes != nil { - for k := range cfg.attributes { - cfg.attributes[k].Cache = c - } + for k := range cfg.attributes { + cfg.attributes[k].Cache = c } } diff --git a/vendor/github.com/thanos-io/thanos/pkg/querysharding/analyzer.go b/vendor/github.com/thanos-io/thanos/pkg/querysharding/analyzer.go index 12cb1b9a1a0..5dcfdb07fe1 100644 --- a/vendor/github.com/thanos-io/thanos/pkg/querysharding/analyzer.go +++ b/vendor/github.com/thanos-io/thanos/pkg/querysharding/analyzer.go @@ -113,7 +113,7 @@ func (a *QueryAnalyzer) Analyze(query string) (QueryAnalysis, error) { case *parser.BinaryExpr: if n.VectorMatching != nil { shardingLabels := without(n.VectorMatching.MatchingLabels, []string{"le"}) - if !n.VectorMatching.On && len(shardingLabels) > 0 { + if !n.VectorMatching.On { shardingLabels = append(shardingLabels, model.MetricNameLabel) } analysis = analysis.scopeToLabels(shardingLabels, n.VectorMatching.On) diff --git a/vendor/github.com/thanos-io/thanos/pkg/store/6545postingsrepro b/vendor/github.com/thanos-io/thanos/pkg/store/6545postingsrepro new file mode 100644 index 00000000000..eb59461a1c7 --- /dev/null +++ b/vendor/github.com/thanos-io/thanos/pkg/store/6545postingsrepro @@ -0,0 +1,7 @@ +�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ǻ��8�������8��*��F��F������F���F�*�����*���8�*�T���8�8�����*������*���*�8������F������*����F����*���*�*��F��8���*��*����8��8���8������������*�����������������������*��������������������������*������������������������������*���������������������*��T���T���~������������������*��*��������������������������������������*�����*�*���8��*�*������������*������������������������������*�*���*�8��������*������*���*��8���������������������������������F�T��*���*�*�8����������*������*�����������������������������������F����*�����������������*����������������������������������*����������8�*�*���8��������������������������*�����*���*�����8����F��*��������������������������*����������*������*��������������������������������� ����8�8�����������*��*���*���������������������������������F�����������*��*���������*��*������������������������*�*�������*��*�����������*��*�������������������������*֡�*�*��*������*�����*�*�����������������������������*���*������8�������*������*���������������������������p��*��*�����������*�8������������������������������8�� +��8�*�F��*����8��8���������������������������������8�����*�����*��8�T�*���8�*�����������������������������8��*�����*��*�*���*�������������������������8�*�����*��������*������F��������������������������������������8�����*�����*�8������������������������������8�*�*�*�����*�*����F�����������������������������*�8���*�*������*����8�����*������������������������F�8������������p���*����*������������������������������*����������������*�*�������������������������������*���������������F��*��*���������������������������������*�������8�8�����*�������������������������*���*�F����*�����������*���������������������������*�������8��*����*�����8���������������������������*�8��������������*�*������*����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������~�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������b/@�5�*+P%���"���Z:?%�A-�42�+:�2��*��;&�B�5����D�w��Z^��ga"�2�1�+��#�?1+$�1���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������b�L�&�@\'*��%��"��:�??�G�0���P�:�9�2��Z*�&B�5��K�A�U��Ib�^Z]�g��'"2�!�1�+/�#�?1+ $2#���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������&�/�@��-�*�2���Z�:���0����2��+:*�B�,�R�59�kKA��b��L����a�"��!�$��?�+�$����2������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������?��&��\�'5*%��"��:�?�%�0A��2�P�:H���Z�*��B�R�kK�A�U��bZ���Z�A��a��!+����?�1���$2������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������?�����@-��P��(��Z:��%��4�2�P��+:�:�H�H�2�Z*%�;&�,�R��9k�w���A�]�ga�K��"�2��1��$#��1��������1�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������?�b�\��-�*���"�Z��??G%�A��2P�<�+:�:�9H���*�;�&�B������ADI�^�Z�A��"�!��+���?��2#1������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������L���5�+�P�2(�Z�?�G�%�0�2�<��:���H�2���Z�*��;��B��59�A�bZ�^�LZ�ga�K��'"�!��+�/�$�#�+� �:��#�1�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$����������������������������������������������$������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$���������������������������������������$$�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$������������������������������������������$$$$�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$$����������������������������������������������$$�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$������������������������������������������������������%%�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$���������������������������������������������������������$$����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$$$�����������������������������������������������$$$�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$���������������������������������������������������$������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$$$�������������������������������������������������$$������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$$$���������������������������������������������������$$�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$�����������������������������������������������������$$$$������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$�����������������������������������������$$$$������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$$������������������������������������������������������$$$$$�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$��������������������������������������������������������$$$�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$���������������������������������������������$$$$�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$�������������������������������������������������$$$$������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$�����������������������������������������������$$$$������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$������������������������������������������������$$$$��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$�������������������������������������������������$������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$$�����������������������������������������������������������$$$��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$������������������������������������������������$$$���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$���������������������������������������������������$$�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$���������������������������������������������������$$������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$$����������������������������������������������$$����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$$�����������������������������������������������$$$���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$$���������������������������������������������������$$$�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$$����������������������������������������������$������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$$��������������������������������������������������%%%%��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$$�������������������������������������$$$$����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$$��������������������������������������������������������$$��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$����������������������������������������������������$���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$�������������������������������������������������$$$�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$��������������������������������������������$$$�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$$����������������������������������������������%�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$$$��������������������������������������������$$����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$�������������������������������������������������$������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$�������������������������������������������$�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$$$���������������������������������������������������������������$$$����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$���������������������������������������������$$�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$$���������������������������������������������$$������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$����������������������������������������������������$$�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$$�����������������������������������������������$$����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$��������������������������������������������$���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$$$���������������������������������������������$$$�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$�����������������������������������������������������$$���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$$�������������������������������������������������$��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$$$��������������������������������������������������$$�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$$������������������������������������������������$$$��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$$������������������������������������������������������$$$���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$����������������������������������������������������$$$������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$$$�����������������������������������������������������$$$�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$�������������������������������������������$$$�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$$$�����������������������������������������������������$$$$������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$��������������������������������������������������������$$����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$���������������������������������������������������������$$$��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$$$�������������������������������������������������$$$���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$������������������������������������������������������$$$�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$�����������������������������������������������$$$$$���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$$����������������������������������������$$����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������%%%�������������������������������������������������$$������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$���������������������������������������������������$$$���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$��������������������������������������������������������$$$$����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$�������������������������������������������������������$$$$���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$�������������������������������������������������%%��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$����������������������������������������������������$$�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$�����������������������������������������������$�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$���������������������������������������������������%���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$�����������������������������������������������$$$��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$����������������������������������������$$$���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$$�������������������������������������������$$$�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$���������������������������������������$��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$$����������������������������������������������������%%����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$$��������������������������������������������������������$����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$�������������������������������������������$$$$������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$$$����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$������������������������������������������������������$����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$����������������������������������������������������������$���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$$���������������������������������������������������������$$$���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$$���������������������������������������������������������$$�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$$�������������������������������������������$$$���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$����������������������������������������������$$$����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$���������������������������������������������������%%%������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$�������������������������������������������������$$���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$$����������������������������������������������������$$�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$����������������������������������������������������$$�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$������������������������������������������������$$$$����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$��������������������������������������������������������$$������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$$��������������������������������������������$���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$$$����������������������������������������������������%%���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� ����$���� ����������$�����)��'���$����� ���"�)��������$���$���� +���������������������$���������#�������$�����������������$������#���� �������������������������� +���������� +����������#��������������������� ��������������������������� ��� + ��� �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������8�F����*��������������������*�*�� �*�F����8���*����*����*���������������������� �����������*����*��������������������������������F��� ���8�*�8�*�*�*�����*������������������������������ �*�8����8�*�������*�����*����������������������8�� +�8��������������T��F����������������������������������F�8�*��������T�*�������*�����������������������&��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������F����*���*����8������������������������� �����*��*�����F������������������������������������� ��*��*�*�*�8�������8���*���������������������������*�� ����F�����������*��F�*���*��������������������������������*�8����������*���F���T����������������������������������*�� \ No newline at end of file diff --git a/vendor/github.com/thanos-io/thanos/pkg/store/bucket.go b/vendor/github.com/thanos-io/thanos/pkg/store/bucket.go index 09bfba32068..f5b71b434ab 100644 --- a/vendor/github.com/thanos-io/thanos/pkg/store/bucket.go +++ b/vendor/github.com/thanos-io/thanos/pkg/store/bucket.go @@ -43,6 +43,7 @@ import ( "google.golang.org/grpc/status" "github.com/thanos-io/objstore" + "github.com/thanos-io/thanos/pkg/block" "github.com/thanos-io/thanos/pkg/block/indexheader" "github.com/thanos-io/thanos/pkg/block/metadata" @@ -58,6 +59,7 @@ import ( "github.com/thanos-io/thanos/pkg/store/hintspb" "github.com/thanos-io/thanos/pkg/store/labelpb" "github.com/thanos-io/thanos/pkg/store/storepb" + "github.com/thanos-io/thanos/pkg/stringset" "github.com/thanos-io/thanos/pkg/strutil" "github.com/thanos-io/thanos/pkg/tenancy" "github.com/thanos-io/thanos/pkg/tracing" @@ -364,6 +366,9 @@ type BucketStore struct { enableChunkHashCalculation bool + bmtx sync.Mutex + labelNamesSet stringset.Set + blockEstimatedMaxSeriesFunc BlockEstimator blockEstimatedMaxChunkFunc BlockEstimator } @@ -510,6 +515,7 @@ func NewBucketStore( enableSeriesResponseHints: enableSeriesResponseHints, enableChunkHashCalculation: enableChunkHashCalculation, seriesBatchSize: SeriesBatchSize, + labelNamesSet: stringset.AllStrings(), } for _, option := range options { @@ -879,9 +885,10 @@ type seriesEntry struct { // single TSDB block in object storage. type blockSeriesClient struct { grpc.ClientStream - ctx context.Context - logger log.Logger - extLset labels.Labels + ctx context.Context + logger log.Logger + extLset labels.Labels + extLsetToRemove map[string]struct{} mint int64 maxt int64 @@ -931,9 +938,11 @@ func newBlockSeriesClient( } return &blockSeriesClient{ - ctx: ctx, - logger: logger, - extLset: extLset, + ctx: ctx, + logger: logger, + extLset: extLset, + extLsetToRemove: extLsetToRemove, + mint: req.MinTime, maxt: req.MaxTime, indexr: b.indexReader(), @@ -1072,6 +1081,10 @@ func (b *blockSeriesClient) nextBatch() error { } completeLabelset := labelpb.ExtendSortedLabels(b.lset, b.extLset) + if b.extLsetToRemove != nil { + completeLabelset = rmLabels(completeLabelset, b.extLsetToRemove) + } + if !b.shardMatcher.MatchesLabels(completeLabelset) { continue } @@ -1240,7 +1253,9 @@ func debugFoundBlockSetOverview(logger log.Logger, mint, maxt, maxResolutionMill } // Series implements the storepb.StoreServer interface. -func (s *BucketStore) Series(req *storepb.SeriesRequest, srv storepb.Store_SeriesServer) (err error) { +func (s *BucketStore) Series(req *storepb.SeriesRequest, seriesSrv storepb.Store_SeriesServer) (err error) { + srv := newFlushableServer(seriesSrv, s.LabelNamesSet(), req.WithoutReplicaLabels) + if s.queryGate != nil { tracing.DoInSpan(srv.Context(), "store_query_gate_ismyturn", func(ctx context.Context) { err = s.queryGate.Start(srv.Context()) @@ -1489,7 +1504,10 @@ func (s *BucketStore) Series(req *storepb.SeriesRequest, srv storepb.Store_Serie } } - return err + if err != nil { + return err + } + return srv.Flush() } func chunksSize(chks []storepb.AggrChunk) (size int) { @@ -1674,6 +1692,35 @@ func (s *BucketStore) LabelNames(ctx context.Context, req *storepb.LabelNamesReq }, nil } +func (s *BucketStore) UpdateLabelNames() { + newSet := stringset.New() + for _, b := range s.blocks { + labelNames, err := b.indexHeaderReader.LabelNames() + if err != nil { + level.Warn(s.logger).Log("msg", "error getting label names", "block", b.meta.ULID, "err", err.Error()) + s.updateLabelNamesSet(stringset.AllStrings()) + return + } + for _, l := range labelNames { + newSet.Insert(l) + } + } + s.updateLabelNamesSet(newSet) +} + +func (s *BucketStore) updateLabelNamesSet(newSet stringset.Set) { + s.bmtx.Lock() + s.labelNamesSet = newSet + s.bmtx.Unlock() +} + +func (b *BucketStore) LabelNamesSet() stringset.Set { + b.bmtx.Lock() + defer b.bmtx.Unlock() + + return b.labelNamesSet +} + func (b *bucketBlock) FilterExtLabelsMatchers(matchers []*labels.Matcher) ([]*labels.Matcher, bool) { // We filter external labels from matchers so we won't try to match series on them. var result []*labels.Matcher @@ -3160,6 +3207,10 @@ type bucketChunkReader struct { mtx sync.Mutex stats *queryStats chunkBytes []*[]byte // Byte slice to return to the chunk pool on close. + + loadingChunksMtx sync.Mutex + loadingChunks bool + finishLoadingChks chan struct{} } func newBucketChunkReader(block *bucketBlock) *bucketChunkReader { @@ -3174,9 +3225,22 @@ func (r *bucketChunkReader) reset() { for i := range r.toLoad { r.toLoad[i] = r.toLoad[i][:0] } + r.loadingChunksMtx.Lock() + r.loadingChunks = false + r.finishLoadingChks = make(chan struct{}) + r.loadingChunksMtx.Unlock() } func (r *bucketChunkReader) Close() error { + // NOTE(GiedriusS): we need to wait until loading chunks because loading + // chunks modifies r.block.chunkPool. + r.loadingChunksMtx.Lock() + loadingChks := r.loadingChunks + r.loadingChunksMtx.Unlock() + + if loadingChks { + <-r.finishLoadingChks + } r.block.pendingReaders.Done() for _, b := range r.chunkBytes { @@ -3201,6 +3265,18 @@ func (r *bucketChunkReader) addLoad(id chunks.ChunkRef, seriesEntry, chunk int) // load loads all added chunks and saves resulting aggrs to refs. func (r *bucketChunkReader) load(ctx context.Context, res []seriesEntry, aggrs []storepb.Aggr, calculateChunkChecksum bool, bytesLimiter BytesLimiter) error { + r.loadingChunksMtx.Lock() + r.loadingChunks = true + r.loadingChunksMtx.Unlock() + + defer func() { + r.loadingChunksMtx.Lock() + r.loadingChunks = false + r.loadingChunksMtx.Unlock() + + close(r.finishLoadingChks) + }() + g, ctx := errgroup.WithContext(ctx) for seq, pIdxs := range r.toLoad { diff --git a/vendor/github.com/thanos-io/thanos/pkg/store/flushable.go b/vendor/github.com/thanos-io/thanos/pkg/store/flushable.go new file mode 100644 index 00000000000..c41b67d152c --- /dev/null +++ b/vendor/github.com/thanos-io/thanos/pkg/store/flushable.go @@ -0,0 +1,72 @@ +// Copyright (c) The Thanos Authors. +// Licensed under the Apache License 2.0. + +package store + +import ( + "github.com/prometheus/prometheus/model/labels" + "golang.org/x/exp/slices" + + "github.com/thanos-io/thanos/pkg/store/labelpb" + "github.com/thanos-io/thanos/pkg/store/storepb" + "github.com/thanos-io/thanos/pkg/stringset" +) + +// flushableServer is an extension of storepb.Store_SeriesServer with a Flush method. +type flushableServer interface { + storepb.Store_SeriesServer + Flush() error +} + +func newFlushableServer( + upstream storepb.Store_SeriesServer, + labelNames stringset.Set, + replicaLabels []string, +) flushableServer { + if labelNames.HasAny(replicaLabels) { + return &resortingServer{Store_SeriesServer: upstream} + } + return &passthroughServer{Store_SeriesServer: upstream} +} + +// passthroughServer is a flushableServer that forwards all data to +// an upstream server without additional processing. +type passthroughServer struct { + storepb.Store_SeriesServer +} + +func (p *passthroughServer) Flush() error { return nil } + +// resortingServer is a flushableServer that resorts all series by their labels. +// This is required if replica labels are stored internally in a TSDB. +// Data is resorted and sent to an upstream server upon calling Flush. +type resortingServer struct { + storepb.Store_SeriesServer + series []*storepb.Series +} + +func (r *resortingServer) Send(response *storepb.SeriesResponse) error { + if response.GetSeries() == nil { + return r.Store_SeriesServer.Send(response) + } + + series := response.GetSeries() + labelpb.ReAllocZLabelsStrings(&series.Labels, false) + r.series = append(r.series, series) + return nil +} + +func (r *resortingServer) Flush() error { + slices.SortFunc(r.series, func(a, b *storepb.Series) bool { + return labels.Compare( + labelpb.ZLabelsToPromLabels(a.Labels), + labelpb.ZLabelsToPromLabels(b.Labels), + ) < 0 + }) + for _, response := range r.series { + if err := r.Store_SeriesServer.Send(storepb.NewSeriesResponse(response)); err != nil { + return err + } + } + return nil +} diff --git a/vendor/github.com/thanos-io/thanos/pkg/store/postings_codec.go b/vendor/github.com/thanos-io/thanos/pkg/store/postings_codec.go index 811871cc13f..f1f89fbd44b 100644 --- a/vendor/github.com/thanos-io/thanos/pkg/store/postings_codec.go +++ b/vendor/github.com/thanos-io/thanos/pkg/store/postings_codec.go @@ -227,10 +227,7 @@ func (it *streamedDiffVarintPostings) At() storage.SeriesRef { return it.curSeries } -func (it *streamedDiffVarintPostings) readNextChunk() bool { - if len(it.db.B) > 0 { - return true - } +func (it *streamedDiffVarintPostings) readNextChunk(remainder []byte) bool { // Normal EOF. if len(it.input) == 0 { return false @@ -255,13 +252,13 @@ func (it *streamedDiffVarintPostings) readNextChunk() bool { it.err = fmt.Errorf("corrupted identifier") return false } - if string(it.input[:6]) != magicBody { + if string(it.input[:len(magicBody)]) != magicBody { it.err = fmt.Errorf("got bad identifier %s", string(it.input[:6])) return false } it.input = it.input[6:] it.readSnappyIdentifier = true - return it.readNextChunk() + return it.readNextChunk(nil) case chunkTypeCompressedData: if !it.readSnappyIdentifier { it.err = fmt.Errorf("missing magic snappy marker") @@ -276,7 +273,6 @@ func (it *streamedDiffVarintPostings) readNextChunk() bool { it.err = io.ErrUnexpectedEOF return false } - encodedBuf := it.input[:chunkLen] if it.buf == nil { if it.disablePooling { @@ -291,6 +287,15 @@ func (it *streamedDiffVarintPostings) readNextChunk() bool { } } + encodedBuf := it.input[:chunkLen] + + // NOTE(GiedriusS): we can probably optimize this better but this should be rare enough + // and not cause any problems. + if len(remainder) > 0 { + remainderCopy := make([]byte, 0, len(remainder)) + remainderCopy = append(remainderCopy, remainder...) + remainder = remainderCopy + } decoded, err := s2.Decode(it.buf, encodedBuf[checksumSize:]) if err != nil { it.err = err @@ -300,7 +305,11 @@ func (it *streamedDiffVarintPostings) readNextChunk() bool { it.err = fmt.Errorf("mismatched checksum (got %v, expected %v)", crc(decoded), checksum) return false } - it.db.B = decoded + if len(remainder) > 0 { + it.db.B = append(remainder, decoded...) + } else { + it.db.B = decoded + } case chunkTypeUncompressedData: if !it.readSnappyIdentifier { it.err = fmt.Errorf("missing magic snappy marker") @@ -315,11 +324,25 @@ func (it *streamedDiffVarintPostings) readNextChunk() bool { it.err = io.ErrUnexpectedEOF return false } - it.db.B = it.input[checksumSize:chunkLen] - if crc(it.db.B) != checksum { - it.err = fmt.Errorf("mismatched checksum (got %v, expected %v)", crc(it.db.B), checksum) + uncompressedData := it.input[checksumSize:chunkLen] + if crc(uncompressedData) != checksum { + it.err = fmt.Errorf("mismatched checksum (got %v, expected %v)", crc(uncompressedData), checksum) return false } + + // NOTE(GiedriusS): we can probably optimize this better but this should be rare enough + // and not cause any problems. + if len(remainder) > 0 { + remainderCopy := make([]byte, 0, len(remainder)) + remainderCopy = append(remainderCopy, remainder...) + remainder = remainderCopy + } + + if len(remainder) > 0 { + it.db.B = append(remainder, uncompressedData...) + } else { + it.db.B = uncompressedData + } default: if chunkType <= 0x7f { it.err = fmt.Errorf("unsupported chunk type %v", chunkType) @@ -336,19 +359,21 @@ func (it *streamedDiffVarintPostings) readNextChunk() bool { } func (it *streamedDiffVarintPostings) Next() bool { - if !it.readNextChunk() { - return false - } - val := it.db.Uvarint() - if it.db.Err() != nil { - if it.db.Err() != io.EOF { - it.err = it.db.Err() + // Continue reading next chunks until there is at least binary.MaxVarintLen64. + // If we cannot add any more chunks then return false. + for { + val := it.db.Uvarint64() + if it.db.Err() != nil { + if !it.readNextChunk(it.db.B) { + return false + } + it.db.E = nil + continue } - return false - } - it.curSeries = it.curSeries + storage.SeriesRef(val) - return true + it.curSeries = it.curSeries + storage.SeriesRef(val) + return true + } } func (it *streamedDiffVarintPostings) Err() error { @@ -534,7 +559,6 @@ func snappyStreamedEncode(postingsLength int, diffVarintPostings []byte) ([]byte if err != nil { return nil, fmt.Errorf("creating snappy compressor: %w", err) } - _, err = sw.Write(diffVarintPostings) if err != nil { return nil, err diff --git a/vendor/github.com/thanos-io/thanos/pkg/store/prometheus.go b/vendor/github.com/thanos-io/thanos/pkg/store/prometheus.go index 388fd0033e1..18e90ccc216 100644 --- a/vendor/github.com/thanos-io/thanos/pkg/store/prometheus.go +++ b/vendor/github.com/thanos-io/thanos/pkg/store/prometheus.go @@ -42,6 +42,7 @@ import ( "github.com/thanos-io/thanos/pkg/store/labelpb" "github.com/thanos-io/thanos/pkg/store/storepb" "github.com/thanos-io/thanos/pkg/store/storepb/prompb" + "github.com/thanos-io/thanos/pkg/stringset" "github.com/thanos-io/thanos/pkg/tracing" ) @@ -53,8 +54,10 @@ type PrometheusStore struct { buffers sync.Pool component component.StoreAPI externalLabelsFn func() labels.Labels - promVersion func() string - timestamps func() (mint int64, maxt int64) + labelNamesSet func() stringset.Set + + promVersion func() string + timestamps func() (mint int64, maxt int64) remoteReadAcceptableResponses []prompb.ReadRequest_ResponseType @@ -78,6 +81,7 @@ func NewPrometheusStore( component component.StoreAPI, externalLabelsFn func() labels.Labels, timestamps func() (mint int64, maxt int64), + labelNamesSet func() stringset.Set, promVersion func() string, ) (*PrometheusStore, error) { if logger == nil { @@ -91,6 +95,7 @@ func NewPrometheusStore( externalLabelsFn: externalLabelsFn, promVersion: promVersion, timestamps: timestamps, + labelNamesSet: labelNamesSet, remoteReadAcceptableResponses: []prompb.ReadRequest_ResponseType{prompb.ReadRequest_STREAMED_XOR_CHUNKS, prompb.ReadRequest_SAMPLES}, buffers: sync.Pool{New: func() interface{} { b := make([]byte, 0, initialBufSize) @@ -143,7 +148,8 @@ func (p *PrometheusStore) putBuffer(b *[]byte) { } // Series returns all series for a requested time range and label matcher. -func (p *PrometheusStore) Series(r *storepb.SeriesRequest, s storepb.Store_SeriesServer) error { +func (p *PrometheusStore) Series(r *storepb.SeriesRequest, seriesSrv storepb.Store_SeriesServer) error { + s := newFlushableServer(seriesSrv, p.labelNamesSet(), r.WithoutReplicaLabels) extLset := p.externalLabelsFn() match, matchers, err := matchesExternalLabels(r.Matchers, extLset) @@ -200,7 +206,7 @@ func (p *PrometheusStore) Series(r *storepb.SeriesRequest, s storepb.Store_Serie return err } } - return nil + return s.Flush() } shardMatcher := r.ShardInfo.Matcher(&p.buffers) @@ -323,7 +329,7 @@ func (p *PrometheusStore) queryPrometheus( } func (p *PrometheusStore) handleSampledPrometheusResponse( - s storepb.Store_SeriesServer, + s flushableServer, httpResp *http.Response, querySpan tracing.Span, extLset labels.Labels, @@ -373,11 +379,11 @@ func (p *PrometheusStore) handleSampledPrometheusResponse( } } level.Debug(p.logger).Log("msg", "handled ReadRequest_SAMPLED request.", "series", len(resp.Results[0].Timeseries)) - return nil + return s.Flush() } func (p *PrometheusStore) handleStreamedPrometheusResponse( - s storepb.Store_SeriesServer, + s flushableServer, shardMatcher *storepb.ShardMatcher, httpResp *http.Response, querySpan tracing.Span, @@ -455,9 +461,7 @@ func (p *PrometheusStore) handleStreamedPrometheusResponse( } r := storepb.NewSeriesResponse(&storepb.Series{ - Labels: labelpb.ZLabelsFromPromLabels( - completeLabelset, - ), + Labels: labelpb.ZLabelsFromPromLabels(completeLabelset), Chunks: thanosChks, }) if err := s.Send(r); err != nil { @@ -472,7 +476,7 @@ func (p *PrometheusStore) handleStreamedPrometheusResponse( querySpan.SetTag("processed.bytes", bodySizer.BytesCount()) level.Debug(p.logger).Log("msg", "handled ReadRequest_STREAMED_XOR_CHUNKS request.", "frames", framesNum) - return nil + return s.Flush() } type BytesCounter struct { diff --git a/vendor/github.com/thanos-io/thanos/pkg/store/tsdb.go b/vendor/github.com/thanos-io/thanos/pkg/store/tsdb.go index 5bbb469e98e..73604b92365 100644 --- a/vendor/github.com/thanos-io/thanos/pkg/store/tsdb.go +++ b/vendor/github.com/thanos-io/thanos/pkg/store/tsdb.go @@ -13,6 +13,7 @@ import ( "sync" "github.com/go-kit/log" + "github.com/go-kit/log/level" "github.com/pkg/errors" "github.com/prometheus/prometheus/model/labels" "github.com/prometheus/prometheus/storage" @@ -25,6 +26,7 @@ import ( "github.com/thanos-io/thanos/pkg/runutil" "github.com/thanos-io/thanos/pkg/store/labelpb" "github.com/thanos-io/thanos/pkg/store/storepb" + "github.com/thanos-io/thanos/pkg/stringset" ) const RemoteReadFrameLimit = 1048576 @@ -44,6 +46,9 @@ type TSDBStore struct { buffers sync.Pool maxBytesPerFrame int + lmx sync.RWMutex + labelNamesSet stringset.Set + extLset labels.Labels mtx sync.RWMutex } @@ -72,6 +77,7 @@ func NewTSDBStore(logger log.Logger, db TSDBReader, component component.StoreAPI component: component, extLset: extLset, maxBytesPerFrame: RemoteReadFrameLimit, + labelNamesSet: stringset.AllStrings(), buffers: sync.Pool{New: func() interface{} { b := make([]byte, 0, initialBufSize) return &b @@ -168,7 +174,9 @@ type CloseDelegator interface { // Series returns all series for a requested time range and label matcher. The returned data may // exceed the requested time bounds. -func (s *TSDBStore) Series(r *storepb.SeriesRequest, srv storepb.Store_SeriesServer) error { +func (s *TSDBStore) Series(r *storepb.SeriesRequest, seriesSrv storepb.Store_SeriesServer) error { + srv := newFlushableServer(seriesSrv, s.LabelNamesSet(), r.WithoutReplicaLabels) + match, matchers, err := matchesExternalLabels(r.Matchers, s.getExtLset()) if err != nil { return status.Error(codes.InvalidArgument, err.Error()) @@ -204,8 +212,8 @@ func (s *TSDBStore) Series(r *storepb.SeriesRequest, srv storepb.Store_SeriesSer for _, lbl := range r.WithoutReplicaLabels { extLsetToRemove[lbl] = struct{}{} } - finalExtLset := rmLabels(s.extLset.Copy(), extLsetToRemove) + // Stream at most one series per frame; series may be split over multiple frames according to maxBytesInFrame. for set.Next() { series := set.At() @@ -279,7 +287,7 @@ func (s *TSDBStore) Series(r *storepb.SeriesRequest, srv storepb.Store_SeriesSer return status.Error(codes.Aborted, err.Error()) } } - return nil + return srv.Flush() } // LabelNames returns all known label names constrained with the given matchers. @@ -368,3 +376,38 @@ func (s *TSDBStore) LabelValues(ctx context.Context, r *storepb.LabelValuesReque return &storepb.LabelValuesResponse{Values: values}, nil } + +func (s *TSDBStore) UpdateLabelNames(ctx context.Context) { + newSet := stringset.New() + q, err := s.db.ChunkQuerier(ctx, math.MinInt64, math.MaxInt64) + if err != nil { + level.Warn(s.logger).Log("msg", "error creating tsdb querier", "err", err.Error()) + s.setLabelNamesSet(stringset.AllStrings()) + return + } + defer runutil.CloseWithLogOnErr(s.logger, q, "close tsdb querier label names") + + res, _, err := q.LabelNames() + if err != nil { + level.Warn(s.logger).Log("msg", "error getting label names", "err", err.Error()) + s.setLabelNamesSet(stringset.AllStrings()) + return + } + for _, l := range res { + newSet.Insert(l) + } + s.setLabelNamesSet(newSet) +} + +func (s *TSDBStore) setLabelNamesSet(newSet stringset.Set) { + s.lmx.Lock() + s.labelNamesSet = newSet + s.lmx.Unlock() +} + +func (b *TSDBStore) LabelNamesSet() stringset.Set { + b.lmx.RLock() + defer b.lmx.RUnlock() + + return b.labelNamesSet +} diff --git a/vendor/github.com/thanos-io/thanos/pkg/stringset/set.go b/vendor/github.com/thanos-io/thanos/pkg/stringset/set.go new file mode 100644 index 00000000000..defe6993531 --- /dev/null +++ b/vendor/github.com/thanos-io/thanos/pkg/stringset/set.go @@ -0,0 +1,85 @@ +// Copyright (c) The Thanos Authors. +// Licensed under the Apache License 2.0. + +package stringset + +import ( + cuckoo "github.com/seiflotfy/cuckoofilter" +) + +type Set interface { + Has(string) bool + HasAny([]string) bool +} + +type fixedSet struct { + cuckoo *cuckoo.Filter +} + +func (f fixedSet) HasAny(strings []string) bool { + for _, s := range strings { + if f.Has(s) { + return true + } + } + return false +} + +func NewFromStrings(items ...string) Set { + f := cuckoo.NewFilter(uint(len(items))) + for _, label := range items { + f.InsertUnique([]byte(label)) + } + + return &fixedSet{cuckoo: f} +} + +func (f fixedSet) Has(s string) bool { + return f.cuckoo.Lookup([]byte(s)) +} + +type mutableSet struct { + cuckoo *cuckoo.ScalableCuckooFilter +} + +type MutableSet interface { + Set + Insert(string) +} + +func New() MutableSet { + return &mutableSet{ + cuckoo: cuckoo.NewScalableCuckooFilter(), + } +} + +func (e mutableSet) Insert(s string) { + e.cuckoo.Insert([]byte(s)) +} + +func (e mutableSet) Has(s string) bool { + return e.cuckoo.Lookup([]byte(s)) +} + +func (e mutableSet) HasAny(strings []string) bool { + for _, s := range strings { + if e.Has(s) { + return true + } + } + return false +} + +type allStringsSet struct{} + +func (e allStringsSet) HasAny(_ []string) bool { + return true +} + +func AllStrings() *allStringsSet { + return &allStringsSet{} +} + +func (e allStringsSet) Has(_ string) bool { + return true +} diff --git a/vendor/go4.org/unsafe/assume-no-moving-gc/assume-no-moving-gc.go b/vendor/go4.org/unsafe/assume-no-moving-gc/assume-no-moving-gc.go index 72b009a9668..60561d05d4f 100644 --- a/vendor/go4.org/unsafe/assume-no-moving-gc/assume-no-moving-gc.go +++ b/vendor/go4.org/unsafe/assume-no-moving-gc/assume-no-moving-gc.go @@ -10,9 +10,10 @@ // analysis keeps on the stack. Ensuring things aren't stack-allocated // is the caller's responsibility. // -// This package is then updated for new Go versions when that -// is still the case and explodes at runtime with a failure -// otherwise, unless an environment variable overrides it. +// This package is then updated as needed for new Go versions when +// that is still the case and explodes at runtime with a failure +// otherwise, with the idea that it's better to not start at all than +// to silently corrupt your data at runtime. // // To use: // @@ -20,15 +21,12 @@ // // There is no API. // -// It is intentional that this package will break code that's not updated -// regularly to double check its assumptions about the world and new Go -// versions. If you play stupid games with unsafe pointers, the stupid prize -// is this maintenance cost. (The alternative would be memory corruption if -// some unmaintained, unsafe library were built with a future version of Go -// that worked very differently than when the unsafe library was built.) -// Ideally you shouldn't write unsafe code, though. +// As of Go 1.21, this package asks the Go runtime whether it can move +// heap objects around. If you get an error on versions prior to that, +// go get go4.org/unsafe/assume-no-moving-gc@latest and things will +// work. // // The GitHub repo is at https://github.com/go4org/unsafe-assume-no-moving-gc package assume_no_moving_gc -const env = "ASSUME_NO_MOVING_GC_UNSAFE_RISK_IT_WITH" +const env = "ASSUME_NO_MOVING_GC_UNSAFE" diff --git a/vendor/go4.org/unsafe/assume-no-moving-gc/check.go b/vendor/go4.org/unsafe/assume-no-moving-gc/check.go new file mode 100644 index 00000000000..a2fbf465077 --- /dev/null +++ b/vendor/go4.org/unsafe/assume-no-moving-gc/check.go @@ -0,0 +1,36 @@ +// Copyright 2020 Brad Fitzpatrick. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build go1.21 +// +build go1.21 + +package assume_no_moving_gc + +import ( + "os" + _ "unsafe" +) + +//go:linkname heapObjectsCanMove runtime.heapObjectsCanMove +func heapObjectsCanMove() bool + +func init() { + if !heapObjectsCanMove() { + // The unsafe assumptions made by the package + // importing this package still hold. All's good. (at + // least unless they made other assumption this + // package doesn't concern itself with) + return + } + if os.Getenv(env) == "play-with-fire" { + return + } + panic(` +Something in this program imports go4.org/unsafe/assume-no-moving-gc to +declare that it assumes a non-moving garbage collector, but the version +of Go you're using declares that its heap objects can now move around. +This program is no longer safe. You should update your packages which import +go4.org/unsafe/assume-no-moving-gc. To risk it and bypass this check, set +ASSUME_NO_MOVING_GC_UNSAFE=play-with-fire and cross your fingers.`) +} diff --git a/vendor/go4.org/unsafe/assume-no-moving-gc/untested.go b/vendor/go4.org/unsafe/assume-no-moving-gc/untested.go deleted file mode 100644 index dbb169045ad..00000000000 --- a/vendor/go4.org/unsafe/assume-no-moving-gc/untested.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2020 Brad Fitzpatrick. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.21 -// +build go1.21 - -package assume_no_moving_gc - -import ( - "os" - "runtime" - "strings" -) - -func init() { - dots := strings.SplitN(runtime.Version(), ".", 3) - v := runtime.Version() - if len(dots) >= 2 { - v = dots[0] + "." + dots[1] - } - if os.Getenv(env) == v { - return - } - panic("Something in this program imports go4.org/unsafe/assume-no-moving-gc to declare that it assumes a non-moving garbage collector, but your version of go4.org/unsafe/assume-no-moving-gc hasn't been updated to assert that it's safe against the " + v + " runtime. If you want to risk it, run with environment variable " + env + "=\"" + v + "\" set. Notably, if " + v + " adds a moving garbage collector, this program is unsafe to use.") -} diff --git a/vendor/modules.txt b/vendor/modules.txt index cb2f9ad8765..ea29fb2bc5f 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -279,6 +279,9 @@ github.com/davecgh/go-spew/spew # github.com/dennwc/varint v1.0.0 ## explicit; go 1.12 github.com/dennwc/varint +# github.com/dgryski/go-metro v0.0.0-20200812162917-85c65e2d0165 +## explicit +github.com/dgryski/go-metro # github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f ## explicit github.com/dgryski/go-rendezvous @@ -805,6 +808,9 @@ github.com/sean-/seed # github.com/segmentio/fasthash v1.0.3 ## explicit; go 1.11 github.com/segmentio/fasthash/fnv1a +# github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb +## explicit; go 1.15 +github.com/seiflotfy/cuckoofilter # github.com/sercand/kuberesolver v2.4.0+incompatible => github.com/sercand/kuberesolver/v4 v4.0.0 ## explicit; go 1.14 github.com/sercand/kuberesolver @@ -835,7 +841,7 @@ github.com/stretchr/objx github.com/stretchr/testify/assert github.com/stretchr/testify/mock github.com/stretchr/testify/require -# github.com/thanos-io/objstore v0.0.0-20230721074820-89475d4508df +# github.com/thanos-io/objstore v0.0.0-20230804084840-c042a6a16c58 ## explicit; go 1.18 github.com/thanos-io/objstore github.com/thanos-io/objstore/exthttp @@ -845,7 +851,7 @@ github.com/thanos-io/objstore/providers/gcs github.com/thanos-io/objstore/providers/s3 github.com/thanos-io/objstore/providers/swift github.com/thanos-io/objstore/tracing/opentracing -# github.com/thanos-io/promql-engine v0.0.0-20230526105742-791d78b260ea +# github.com/thanos-io/promql-engine v0.0.0-20230816062837-c64fc7b373db ## explicit; go 1.19 github.com/thanos-io/promql-engine/api github.com/thanos-io/promql-engine/engine @@ -862,11 +868,12 @@ github.com/thanos-io/promql-engine/execution/scan github.com/thanos-io/promql-engine/execution/step_invariant github.com/thanos-io/promql-engine/execution/storage github.com/thanos-io/promql-engine/execution/unary +github.com/thanos-io/promql-engine/execution/warnings github.com/thanos-io/promql-engine/logicalplan github.com/thanos-io/promql-engine/parser github.com/thanos-io/promql-engine/query github.com/thanos-io/promql-engine/worker -# github.com/thanos-io/thanos v0.31.1-0.20230809185825-46339760e526 +# github.com/thanos-io/thanos v0.0.0-20230816172224-2b4f2a7061f9 ## explicit; go 1.18 github.com/thanos-io/thanos/pkg/block github.com/thanos-io/thanos/pkg/block/indexheader @@ -906,6 +913,7 @@ github.com/thanos-io/thanos/pkg/store/hintspb github.com/thanos-io/thanos/pkg/store/labelpb github.com/thanos-io/thanos/pkg/store/storepb github.com/thanos-io/thanos/pkg/store/storepb/prompb +github.com/thanos-io/thanos/pkg/stringset github.com/thanos-io/thanos/pkg/strutil github.com/thanos-io/thanos/pkg/targets/targetspb github.com/thanos-io/thanos/pkg/tenancy @@ -1108,10 +1116,10 @@ go.uber.org/zap/internal/color go.uber.org/zap/internal/exit go.uber.org/zap/zapcore go.uber.org/zap/zapgrpc -# go4.org/intern v0.0.0-20230205224052-192e9f60865c +# go4.org/intern v0.0.0-20230525184215-6c62f75575cb ## explicit; go 1.13 go4.org/intern -# go4.org/unsafe/assume-no-moving-gc v0.0.0-20230221090011-e4bae7ad2296 +# go4.org/unsafe/assume-no-moving-gc v0.0.0-20230525183740-e7c30c78aeb2 ## explicit; go 1.11 go4.org/unsafe/assume-no-moving-gc # golang.org/x/crypto v0.11.0