From 03dcb5327e4ec814db6dca50dd2735574540846f Mon Sep 17 00:00:00 2001 From: Tetrergeru Date: Mon, 12 Aug 2024 11:49:29 +0200 Subject: [PATCH 01/19] Some tests pass --- go.mod | 53 ++- go.sum | 596 +++--------------------------- metric_source/local/eval.go | 238 ++++++------ metric_source/local/local.go | 4 +- metric_source/local/local_test.go | 179 ++++----- metric_source/local/timer.go | 16 +- 6 files changed, 308 insertions(+), 778 deletions(-) diff --git a/go.mod b/go.mod index af4fb7c7e..92e1277b9 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.21 require ( github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible github.com/PagerDuty/go-pagerduty v1.5.1 - github.com/ansel1/merry v1.6.2 + github.com/ansel1/merry v1.8.0 github.com/aws/aws-sdk-go v1.44.293 github.com/blevesearch/bleve/v2 v2.3.8 github.com/bwmarrin/discordgo v0.25.0 @@ -15,7 +15,7 @@ require ( github.com/dustin/go-humanize v1.0.1 github.com/go-chi/chi v4.1.2+incompatible github.com/go-chi/render v1.0.1 - github.com/go-graphite/carbonapi v0.16.0 + github.com/go-graphite/carbonapi v0.16.2-0.20240530091606-c2229eabd094 github.com/go-graphite/protocol v1.0.0 github.com/go-redis/redis/v8 v8.11.5 github.com/go-redsync/redsync/v4 v4.4.4 @@ -56,13 +56,11 @@ require ( ) require ( - bitbucket.org/tebeka/strftime v0.0.0-20140926081919-2194253a23c0 // indirect github.com/JaderDias/movingmedian v0.0.0-20220813210630-d8c6b6de8835 // indirect github.com/Masterminds/sprig/v3 v3.2.3 github.com/RoaringBitmap/roaring v1.3.0 // indirect github.com/aclements/go-moremath v0.0.0-20210112150236-f10218a38794 // indirect - github.com/ansel1/merry/v2 v2.1.1 // indirect - github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df // indirect + github.com/ansel1/merry/v2 v2.2.1 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bits-and-blooms/bitset v1.8.0 // indirect github.com/blend/go-sdk v2.0.0+incompatible // indirect @@ -81,21 +79,19 @@ require ( github.com/blevesearch/zapx/v13 v13.3.8 // indirect github.com/blevesearch/zapx/v14 v14.3.8 // indirect github.com/blevesearch/zapx/v15 v15.3.11 // indirect - github.com/bradfitz/gomemcache v0.0.0-20221031212613-62deef7fc822 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/dgryski/go-expirecache v0.0.0-20170314133854-743ef98b2adb // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/dgryski/go-onlinestats v0.0.0-20170612111826-1c7d19468768 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/disintegration/imaging v1.6.2 // indirect github.com/evmar/gocairo v0.0.0-20160222165215-ddd30f837497 // indirect github.com/francoispqt/gojay v1.2.13 // indirect - github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/geo v0.0.0-20230421003525-6adc56603217 // indirect - github.com/golang/protobuf v1.5.3 // indirect + github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.4 // indirect - github.com/gomodule/redigo v1.8.9 // indirect + github.com/gomodule/redigo v1.9.2 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/uuid v1.6.0 github.com/gopherjs/gopherjs v1.17.2 // indirect @@ -114,7 +110,7 @@ require ( github.com/lomik/og-rek v0.0.0-20170411191824-628eefeb8d80 // indirect github.com/lomik/zapwriter v0.0.0-20210624082824-c1161d1eb463 // indirect github.com/magiconair/properties v1.8.7 // indirect - github.com/maruel/natural v1.1.0 // indirect + github.com/maruel/natural v1.1.1 // indirect github.com/mattermost/go-i18n v1.11.1-0.20211013152124-5c415071e404 // indirect github.com/mattermost/ldap v0.0.0-20231116144001-0f480c025956 // indirect github.com/mattermost/logr/v2 v2.0.21 // indirect @@ -124,28 +120,26 @@ require ( github.com/mjibson/go-dsp v0.0.0-20180508042940-11479a337f12 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/msaf1980/go-stringutils v0.1.4 // indirect + github.com/msaf1980/go-stringutils v0.1.6 // indirect github.com/mschoch/smat v0.2.0 // indirect github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect - github.com/natefinch/atomic v1.0.1 // indirect github.com/pborman/uuid v1.2.1 // indirect github.com/pelletier/go-toml v1.9.5 // indirect - github.com/pelletier/go-toml/v2 v2.0.8 // indirect + github.com/pelletier/go-toml/v2 v2.2.1 // indirect github.com/philhofer/fwd v1.1.2 // indirect github.com/pkg/errors v0.9.1 - github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/client_model v0.3.0 // indirect github.com/prometheus/procfs v0.8.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartystreets/assertions v1.2.0 // indirect - github.com/spf13/afero v1.9.5 // indirect - github.com/spf13/cast v1.5.1 // indirect - github.com/spf13/jwalterweatherman v1.1.0 // indirect + github.com/spf13/afero v1.11.0 // indirect + github.com/spf13/cast v1.6.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/spf13/viper v1.16.0 // indirect - github.com/stretchr/objx v0.5.1 // indirect - github.com/stretchr/testify v1.8.4 - github.com/subosito/gotenv v1.4.2 // indirect + github.com/spf13/viper v1.18.2 // indirect + github.com/stretchr/objx v0.5.2 // indirect + github.com/stretchr/testify v1.9.0 + github.com/subosito/gotenv v1.6.0 // indirect github.com/tinylib/msgp v1.1.9 // indirect github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect @@ -153,17 +147,16 @@ require ( github.com/wiggin77/merror v1.0.5 // indirect github.com/wiggin77/srslog v1.0.1 // indirect go.etcd.io/bbolt v1.3.7 // indirect - go.uber.org/atomic v1.11.0 // indirect - go.uber.org/multierr v1.8.0 // indirect - go.uber.org/zap v1.24.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + go.uber.org/zap v1.27.0 // indirect golang.org/x/crypto v0.24.0 // indirect golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 // indirect - golang.org/x/image v0.13.0 // indirect + golang.org/x/image v0.14.0 // indirect golang.org/x/net v0.26.0 // indirect golang.org/x/oauth2 v0.17.0 // indirect golang.org/x/sys v0.21.0 // indirect golang.org/x/text v0.16.0 // indirect - gonum.org/v1/gonum v0.12.0 // indirect + gonum.org/v1/gonum v0.15.0 // indirect google.golang.org/appengine v1.6.8 // indirect google.golang.org/protobuf v1.33.0 // indirect gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect @@ -195,9 +188,13 @@ require ( github.com/mitchellh/reflectwalk v1.0.0 // indirect github.com/oklog/run v1.1.0 // indirect github.com/rogpeppe/go-internal v1.10.0 // indirect + github.com/sagikazarmark/locafero v0.4.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/shopspring/decimal v1.2.0 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect github.com/swaggo/files v1.0.1 // indirect github.com/swaggo/swag v1.8.12 // indirect + github.com/tebeka/strftime v0.1.5 // indirect golang.org/x/tools v0.22.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect google.golang.org/grpc v1.62.0 // indirect diff --git a/go.sum b/go.sum index acccd9382..d51642d6f 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,3 @@ -bitbucket.org/tebeka/strftime v0.0.0-20140926081919-2194253a23c0 h1:800dI8vRxVMgss6UcZY8gxk8PvYw7Qo1ZI3TrUkTKjc= -bitbucket.org/tebeka/strftime v0.0.0-20140926081919-2194253a23c0/go.mod h1:9BKpS/J2txC7Ql3QUhesesiV3HsIsA7zl7VK6cQVg5M= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= @@ -32,368 +30,31 @@ cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+Y cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= -cloud.google.com/go v0.100.1/go.mod h1:fs4QogzfH5n2pBXBP9vRiU+eCny7lD2vmFZy79Iuw1U= cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= -cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc= -cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU= -cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA= -cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM= -cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX2I= -cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4= -cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw= -cloud.google.com/go/accesscontextmanager v1.3.0/go.mod h1:TgCBehyr5gNMz7ZaH9xubp+CE8dkrszb4oK9CWyvD4o= -cloud.google.com/go/accesscontextmanager v1.4.0/go.mod h1:/Kjh7BBu/Gh83sv+K60vN9QE5NJcd80sU33vIe2IFPE= -cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw= -cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY= -cloud.google.com/go/aiplatform v1.27.0/go.mod h1:Bvxqtl40l0WImSb04d0hXFU7gDOiq9jQmorivIiWcKg= -cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI= -cloud.google.com/go/analytics v0.12.0/go.mod h1:gkfj9h6XRf9+TS4bmuhPEShsh3hH8PAZzm/41OOhQd4= -cloud.google.com/go/apigateway v1.3.0/go.mod h1:89Z8Bhpmxu6AmUxuVRg/ECRGReEdiP3vQtk4Z1J9rJk= -cloud.google.com/go/apigateway v1.4.0/go.mod h1:pHVY9MKGaH9PQ3pJ4YLzoj6U5FUDeDFBllIz7WmzJoc= -cloud.google.com/go/apigeeconnect v1.3.0/go.mod h1:G/AwXFAKo0gIXkPTVfZDd2qA1TxBXJ3MgMRBQkIi9jc= -cloud.google.com/go/apigeeconnect v1.4.0/go.mod h1:kV4NwOKqjvt2JYR0AoIWo2QGfoRtn/pkS3QlHp0Ni04= -cloud.google.com/go/apigeeregistry v0.4.0/go.mod h1:EUG4PGcsZvxOXAdyEghIdXwAEi/4MEaoqLMLDMIwKXY= -cloud.google.com/go/apikeys v0.4.0/go.mod h1:XATS/yqZbaBK0HOssf+ALHp8jAlNHUgyfprvNcBIszU= -cloud.google.com/go/appengine v1.4.0/go.mod h1:CS2NhuBuDXM9f+qscZ6V86m1MIIqPj3WC/UoEuR1Sno= -cloud.google.com/go/appengine v1.5.0/go.mod h1:TfasSozdkFI0zeoxW3PTBLiNqRmzraodCWatWI9Dmak= -cloud.google.com/go/area120 v0.5.0/go.mod h1:DE/n4mp+iqVyvxHN41Vf1CR602GiHQjFPusMFW6bGR4= -cloud.google.com/go/area120 v0.6.0/go.mod h1:39yFJqWVgm0UZqWTOdqkLhjoC7uFfgXRC8g/ZegeAh0= -cloud.google.com/go/artifactregistry v1.6.0/go.mod h1:IYt0oBPSAGYj/kprzsBjZ/4LnG/zOcHyFHjWPCi6SAQ= -cloud.google.com/go/artifactregistry v1.7.0/go.mod h1:mqTOFOnGZx8EtSqK/ZWcsm/4U8B77rbcLP6ruDU2Ixk= -cloud.google.com/go/artifactregistry v1.8.0/go.mod h1:w3GQXkJX8hiKN0v+at4b0qotwijQbYUqF2GWkZzAhC0= -cloud.google.com/go/artifactregistry v1.9.0/go.mod h1:2K2RqvA2CYvAeARHRkLDhMDJ3OXy26h3XW+3/Jh2uYc= -cloud.google.com/go/asset v1.5.0/go.mod h1:5mfs8UvcM5wHhqtSv8J1CtxxaQq3AdBxxQi2jGW/K4o= -cloud.google.com/go/asset v1.7.0/go.mod h1:YbENsRK4+xTiL+Ofoj5Ckf+O17kJtgp3Y3nn4uzZz5s= -cloud.google.com/go/asset v1.8.0/go.mod h1:mUNGKhiqIdbr8X7KNayoYvyc4HbbFO9URsjbytpUaW0= -cloud.google.com/go/asset v1.9.0/go.mod h1:83MOE6jEJBMqFKadM9NLRcs80Gdw76qGuHn8m3h8oHQ= -cloud.google.com/go/asset v1.10.0/go.mod h1:pLz7uokL80qKhzKr4xXGvBQXnzHn5evJAEAtZiIb0wY= -cloud.google.com/go/assuredworkloads v1.5.0/go.mod h1:n8HOZ6pff6re5KYfBXcFvSViQjDwxFkAkmUFffJRbbY= -cloud.google.com/go/assuredworkloads v1.6.0/go.mod h1:yo2YOk37Yc89Rsd5QMVECvjaMKymF9OP+QXWlKXUkXw= -cloud.google.com/go/assuredworkloads v1.7.0/go.mod h1:z/736/oNmtGAyU47reJgGN+KVoYoxeLBoj4XkKYscNI= -cloud.google.com/go/assuredworkloads v1.8.0/go.mod h1:AsX2cqyNCOvEQC8RMPnoc0yEarXQk6WEKkxYfL6kGIo= -cloud.google.com/go/assuredworkloads v1.9.0/go.mod h1:kFuI1P78bplYtT77Tb1hi0FMxM0vVpRC7VVoJC3ZoT0= -cloud.google.com/go/automl v1.5.0/go.mod h1:34EjfoFGMZ5sgJ9EoLsRtdPSNZLcfflJR39VbVNS2M0= -cloud.google.com/go/automl v1.6.0/go.mod h1:ugf8a6Fx+zP0D59WLhqgTDsQI9w07o64uf/Is3Nh5p8= -cloud.google.com/go/automl v1.7.0/go.mod h1:RL9MYCCsJEOmt0Wf3z9uzG0a7adTT1fe+aObgSpkCt8= -cloud.google.com/go/automl v1.8.0/go.mod h1:xWx7G/aPEe/NP+qzYXktoBSDfjO+vnKMGgsApGJJquM= -cloud.google.com/go/baremetalsolution v0.3.0/go.mod h1:XOrocE+pvK1xFfleEnShBlNAXf+j5blPPxrhjKgnIFc= -cloud.google.com/go/baremetalsolution v0.4.0/go.mod h1:BymplhAadOO/eBa7KewQ0Ppg4A4Wplbn+PsFKRLo0uI= -cloud.google.com/go/batch v0.3.0/go.mod h1:TR18ZoAekj1GuirsUsR1ZTKN3FC/4UDnScjT8NXImFE= -cloud.google.com/go/batch v0.4.0/go.mod h1:WZkHnP43R/QCGQsZ+0JyG4i79ranE2u8xvjq/9+STPE= -cloud.google.com/go/beyondcorp v0.2.0/go.mod h1:TB7Bd+EEtcw9PCPQhCJtJGjk/7TC6ckmnSFS+xwTfm4= -cloud.google.com/go/beyondcorp v0.3.0/go.mod h1:E5U5lcrcXMsCuoDNyGrpyTm/hn7ne941Jz2vmksAxW8= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/bigquery v1.42.0/go.mod h1:8dRTJxhtG+vwBKzE5OseQn/hiydoQN3EedCaOdYmxRA= -cloud.google.com/go/bigquery v1.43.0/go.mod h1:ZMQcXHsl+xmU1z36G2jNGZmKp9zNY5BUua5wDgmNCfw= -cloud.google.com/go/bigquery v1.44.0/go.mod h1:0Y33VqXTEsbamHJvJHdFmtqHvMIY28aK1+dFsvaChGc= -cloud.google.com/go/billing v1.4.0/go.mod h1:g9IdKBEFlItS8bTtlrZdVLWSSdSyFUZKXNS02zKMOZY= -cloud.google.com/go/billing v1.5.0/go.mod h1:mztb1tBc3QekhjSgmpf/CV4LzWXLzCArwpLmP2Gm88s= -cloud.google.com/go/billing v1.6.0/go.mod h1:WoXzguj+BeHXPbKfNWkqVtDdzORazmCjraY+vrxcyvI= -cloud.google.com/go/billing v1.7.0/go.mod h1:q457N3Hbj9lYwwRbnlD7vUpyjq6u5U1RAOArInEiD5Y= -cloud.google.com/go/binaryauthorization v1.1.0/go.mod h1:xwnoWu3Y84jbuHa0zd526MJYmtnVXn0syOjaJgy4+dM= -cloud.google.com/go/binaryauthorization v1.2.0/go.mod h1:86WKkJHtRcv5ViNABtYMhhNWRrD1Vpi//uKEy7aYEfI= -cloud.google.com/go/binaryauthorization v1.3.0/go.mod h1:lRZbKgjDIIQvzYQS1p99A7/U1JqvqeZg0wiI5tp6tg0= -cloud.google.com/go/binaryauthorization v1.4.0/go.mod h1:tsSPQrBd77VLplV70GUhBf/Zm3FsKmgSqgm4UmiDItk= -cloud.google.com/go/certificatemanager v1.3.0/go.mod h1:n6twGDvcUBFu9uBgt4eYvvf3sQ6My8jADcOVwHmzadg= -cloud.google.com/go/certificatemanager v1.4.0/go.mod h1:vowpercVFyqs8ABSmrdV+GiFf2H/ch3KyudYQEMM590= -cloud.google.com/go/channel v1.8.0/go.mod h1:W5SwCXDJsq/rg3tn3oG0LOxpAo6IMxNa09ngphpSlnk= -cloud.google.com/go/channel v1.9.0/go.mod h1:jcu05W0my9Vx4mt3/rEHpfxc9eKi9XwsdDL8yBMbKUk= -cloud.google.com/go/cloudbuild v1.3.0/go.mod h1:WequR4ULxlqvMsjDEEEFnOG5ZSRSgWOywXYDb1vPE6U= -cloud.google.com/go/cloudbuild v1.4.0/go.mod h1:5Qwa40LHiOXmz3386FrjrYM93rM/hdRr7b53sySrTqA= -cloud.google.com/go/clouddms v1.3.0/go.mod h1:oK6XsCDdW4Ib3jCCBugx+gVjevp2TMXFtgxvPSee3OM= -cloud.google.com/go/clouddms v1.4.0/go.mod h1:Eh7sUGCC+aKry14O1NRljhjyrr0NFC0G2cjwX0cByRk= -cloud.google.com/go/cloudtasks v1.5.0/go.mod h1:fD92REy1x5woxkKEkLdvavGnPJGEn8Uic9nWuLzqCpY= -cloud.google.com/go/cloudtasks v1.6.0/go.mod h1:C6Io+sxuke9/KNRkbQpihnW93SWDU3uXt92nu85HkYI= -cloud.google.com/go/cloudtasks v1.7.0/go.mod h1:ImsfdYWwlWNJbdgPIIGJWC+gemEGTBK/SunNQQNCAb4= -cloud.google.com/go/cloudtasks v1.8.0/go.mod h1:gQXUIwCSOI4yPVK7DgTVFiiP0ZW/eQkydWzwVMdHxrI= cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s= cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= -cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= -cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU= -cloud.google.com/go/compute v1.12.0/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= -cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= -cloud.google.com/go/compute v1.13.0/go.mod h1:5aPTS0cUNMIc1CE546K+Th6weJUNQErARyZtRXDJ8GE= -cloud.google.com/go/compute v1.14.0/go.mod h1:YfLtxrj9sU4Yxv+sXzZkyPjEyPBZfXHUvjxega5vAdo= -cloud.google.com/go/compute v1.15.1/go.mod h1:bjjoF/NtFUrkD/urWfdHaKuOPDR5nWIs63rR+SXhcpA= -cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs= -cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU= -cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= -cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= -cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= -cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY= -cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck= -cloud.google.com/go/container v1.6.0/go.mod h1:Xazp7GjJSeUYo688S+6J5V+n/t+G5sKBTFkKNudGRxg= -cloud.google.com/go/container v1.7.0/go.mod h1:Dp5AHtmothHGX3DwwIHPgq45Y8KmNsgN3amoYfxVkLo= -cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I= -cloud.google.com/go/containeranalysis v0.6.0/go.mod h1:HEJoiEIu+lEXM+k7+qLCci0h33lX3ZqoYFdmPcoO7s4= -cloud.google.com/go/datacatalog v1.3.0/go.mod h1:g9svFY6tuR+j+hrTw3J2dNcmI0dzmSiyOzm8kpLq0a0= -cloud.google.com/go/datacatalog v1.5.0/go.mod h1:M7GPLNQeLfWqeIm3iuiruhPzkt65+Bx8dAKvScX8jvs= -cloud.google.com/go/datacatalog v1.6.0/go.mod h1:+aEyF8JKg+uXcIdAmmaMUmZ3q1b/lKLtXCmXdnc0lbc= -cloud.google.com/go/datacatalog v1.7.0/go.mod h1:9mEl4AuDYWw81UGc41HonIHH7/sn52H0/tc8f8ZbZIE= -cloud.google.com/go/datacatalog v1.8.0/go.mod h1:KYuoVOv9BM8EYz/4eMFxrr4DUKhGIOXxZoKYF5wdISM= -cloud.google.com/go/dataflow v0.6.0/go.mod h1:9QwV89cGoxjjSR9/r7eFDqqjtvbKxAK2BaYU6PVk9UM= -cloud.google.com/go/dataflow v0.7.0/go.mod h1:PX526vb4ijFMesO1o202EaUmouZKBpjHsTlCtB4parQ= -cloud.google.com/go/dataform v0.3.0/go.mod h1:cj8uNliRlHpa6L3yVhDOBrUXH+BPAO1+KFMQQNSThKo= -cloud.google.com/go/dataform v0.4.0/go.mod h1:fwV6Y4Ty2yIFL89huYlEkwUPtS7YZinZbzzj5S9FzCE= -cloud.google.com/go/dataform v0.5.0/go.mod h1:GFUYRe8IBa2hcomWplodVmUx/iTL0FrsauObOM3Ipr0= -cloud.google.com/go/datafusion v1.4.0/go.mod h1:1Zb6VN+W6ALo85cXnM1IKiPw+yQMKMhB9TsTSRDo/38= -cloud.google.com/go/datafusion v1.5.0/go.mod h1:Kz+l1FGHB0J+4XF2fud96WMmRiq/wj8N9u007vyXZ2w= -cloud.google.com/go/datalabeling v0.5.0/go.mod h1:TGcJ0G2NzcsXSE/97yWjIZO0bXj0KbVlINXMG9ud42I= -cloud.google.com/go/datalabeling v0.6.0/go.mod h1:WqdISuk/+WIGeMkpw/1q7bK/tFEZxsrFJOJdY2bXvTQ= -cloud.google.com/go/dataplex v1.3.0/go.mod h1:hQuRtDg+fCiFgC8j0zV222HvzFQdRd+SVX8gdmFcZzA= -cloud.google.com/go/dataplex v1.4.0/go.mod h1:X51GfLXEMVJ6UN47ESVqvlsRplbLhcsAt0kZCCKsU0A= -cloud.google.com/go/dataproc v1.7.0/go.mod h1:CKAlMjII9H90RXaMpSxQ8EU6dQx6iAYNPcYPOkSbi8s= -cloud.google.com/go/dataproc v1.8.0/go.mod h1:5OW+zNAH0pMpw14JVrPONsxMQYMBqJuzORhIBfBn9uI= -cloud.google.com/go/dataqna v0.5.0/go.mod h1:90Hyk596ft3zUQ8NkFfvICSIfHFh1Bc7C4cK3vbhkeo= -cloud.google.com/go/dataqna v0.6.0/go.mod h1:1lqNpM7rqNLVgWBJyk5NF6Uen2PHym0jtVJonplVsDA= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/datastore v1.10.0/go.mod h1:PC5UzAmDEkAmkfaknstTYbNpgE49HAgW2J1gcgUfmdM= -cloud.google.com/go/datastream v1.2.0/go.mod h1:i/uTP8/fZwgATHS/XFu0TcNUhuA0twZxxQ3EyCUQMwo= -cloud.google.com/go/datastream v1.3.0/go.mod h1:cqlOX8xlyYF/uxhiKn6Hbv6WjwPPuI9W2M9SAXwaLLQ= -cloud.google.com/go/datastream v1.4.0/go.mod h1:h9dpzScPhDTs5noEMQVWP8Wx8AFBRyS0s8KWPx/9r0g= -cloud.google.com/go/datastream v1.5.0/go.mod h1:6TZMMNPwjUqZHBKPQ1wwXpb0d5VDVPl2/XoS5yi88q4= -cloud.google.com/go/deploy v1.4.0/go.mod h1:5Xghikd4VrmMLNaF6FiRFDlHb59VM59YoDQnOUdsH/c= -cloud.google.com/go/deploy v1.5.0/go.mod h1:ffgdD0B89tToyW/U/D2eL0jN2+IEV/3EMuXHA0l4r+s= -cloud.google.com/go/dialogflow v1.15.0/go.mod h1:HbHDWs33WOGJgn6rfzBW1Kv807BE3O1+xGbn59zZWI4= -cloud.google.com/go/dialogflow v1.16.1/go.mod h1:po6LlzGfK+smoSmTBnbkIZY2w8ffjz/RcGSS+sh1el0= -cloud.google.com/go/dialogflow v1.17.0/go.mod h1:YNP09C/kXA1aZdBgC/VtXX74G/TKn7XVCcVumTflA+8= -cloud.google.com/go/dialogflow v1.18.0/go.mod h1:trO7Zu5YdyEuR+BhSNOqJezyFQ3aUzz0njv7sMx/iek= -cloud.google.com/go/dialogflow v1.19.0/go.mod h1:JVmlG1TwykZDtxtTXujec4tQ+D8SBFMoosgy+6Gn0s0= -cloud.google.com/go/dialogflow v1.29.0/go.mod h1:b+2bzMe+k1s9V+F2jbJwpHPzrnIyHihAdRFMtn2WXuM= -cloud.google.com/go/dlp v1.6.0/go.mod h1:9eyB2xIhpU0sVwUixfBubDoRwP+GjeUoxxeueZmqvmM= -cloud.google.com/go/dlp v1.7.0/go.mod h1:68ak9vCiMBjbasxeVD17hVPxDEck+ExiHavX8kiHG+Q= -cloud.google.com/go/documentai v1.7.0/go.mod h1:lJvftZB5NRiFSX4moiye1SMxHx0Bc3x1+p9e/RfXYiU= -cloud.google.com/go/documentai v1.8.0/go.mod h1:xGHNEB7CtsnySCNrCFdCyyMz44RhFEEX2Q7UD0c5IhU= -cloud.google.com/go/documentai v1.9.0/go.mod h1:FS5485S8R00U10GhgBC0aNGrJxBP8ZVpEeJ7PQDZd6k= -cloud.google.com/go/documentai v1.10.0/go.mod h1:vod47hKQIPeCfN2QS/jULIvQTugbmdc0ZvxxfQY1bg4= -cloud.google.com/go/domains v0.6.0/go.mod h1:T9Rz3GasrpYk6mEGHh4rymIhjlnIuB4ofT1wTxDeT4Y= -cloud.google.com/go/domains v0.7.0/go.mod h1:PtZeqS1xjnXuRPKE/88Iru/LdfoRyEHYA9nFQf4UKpg= -cloud.google.com/go/edgecontainer v0.1.0/go.mod h1:WgkZ9tp10bFxqO8BLPqv2LlfmQF1X8lZqwW4r1BTajk= -cloud.google.com/go/edgecontainer v0.2.0/go.mod h1:RTmLijy+lGpQ7BXuTDa4C4ssxyXT34NIuHIgKuP4s5w= -cloud.google.com/go/errorreporting v0.3.0/go.mod h1:xsP2yaAp+OAW4OIm60An2bbLpqIhKXdWR/tawvl7QzU= -cloud.google.com/go/essentialcontacts v1.3.0/go.mod h1:r+OnHa5jfj90qIfZDO/VztSFqbQan7HV75p8sA+mdGI= -cloud.google.com/go/essentialcontacts v1.4.0/go.mod h1:8tRldvHYsmnBCHdFpvU+GL75oWiBKl80BiqlFh9tp+8= -cloud.google.com/go/eventarc v1.7.0/go.mod h1:6ctpF3zTnaQCxUjHUdcfgcA1A2T309+omHZth7gDfmc= -cloud.google.com/go/eventarc v1.8.0/go.mod h1:imbzxkyAU4ubfsaKYdQg04WS1NvncblHEup4kvF+4gw= -cloud.google.com/go/filestore v1.3.0/go.mod h1:+qbvHGvXU1HaKX2nD0WEPo92TP/8AQuCVEBXNY9z0+w= -cloud.google.com/go/filestore v1.4.0/go.mod h1:PaG5oDfo9r224f8OYXURtAsY+Fbyq/bLYoINEK8XQAI= cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY= -cloud.google.com/go/firestore v1.9.0/go.mod h1:HMkjKHNTtRyZNiMzu7YAsLr9K3X2udY2AMwDaMEQiiE= -cloud.google.com/go/functions v1.6.0/go.mod h1:3H1UA3qiIPRWD7PeZKLvHZ9SaQhR26XIJcC0A5GbvAk= -cloud.google.com/go/functions v1.7.0/go.mod h1:+d+QBcWM+RsrgZfV9xo6KfA1GlzJfxcfZcRPEhDDfzg= -cloud.google.com/go/functions v1.8.0/go.mod h1:RTZ4/HsQjIqIYP9a9YPbU+QFoQsAlYgrwOXJWHn1POY= -cloud.google.com/go/functions v1.9.0/go.mod h1:Y+Dz8yGguzO3PpIjhLTbnqV1CWmgQ5UwtlpzoyquQ08= -cloud.google.com/go/gaming v1.5.0/go.mod h1:ol7rGcxP/qHTRQE/RO4bxkXq+Fix0j6D4LFPzYTIrDM= -cloud.google.com/go/gaming v1.6.0/go.mod h1:YMU1GEvA39Qt3zWGyAVA9bpYz/yAhTvaQ1t2sK4KPUA= -cloud.google.com/go/gaming v1.7.0/go.mod h1:LrB8U7MHdGgFG851iHAfqUdLcKBdQ55hzXy9xBJz0+w= -cloud.google.com/go/gaming v1.8.0/go.mod h1:xAqjS8b7jAVW0KFYeRUxngo9My3f33kFmua++Pi+ggM= -cloud.google.com/go/gkebackup v0.2.0/go.mod h1:XKvv/4LfG829/B8B7xRkk8zRrOEbKtEam6yNfuQNH60= -cloud.google.com/go/gkebackup v0.3.0/go.mod h1:n/E671i1aOQvUxT541aTkCwExO/bTer2HDlj4TsBRAo= -cloud.google.com/go/gkeconnect v0.5.0/go.mod h1:c5lsNAg5EwAy7fkqX/+goqFsU1Da/jQFqArp+wGNr/o= -cloud.google.com/go/gkeconnect v0.6.0/go.mod h1:Mln67KyU/sHJEBY8kFZ0xTeyPtzbq9StAVvEULYK16A= -cloud.google.com/go/gkehub v0.9.0/go.mod h1:WYHN6WG8w9bXU0hqNxt8rm5uxnk8IH+lPY9J2TV7BK0= -cloud.google.com/go/gkehub v0.10.0/go.mod h1:UIPwxI0DsrpsVoWpLB0stwKCP+WFVG9+y977wO+hBH0= -cloud.google.com/go/gkemulticloud v0.3.0/go.mod h1:7orzy7O0S+5kq95e4Hpn7RysVA7dPs8W/GgfUtsPbrA= -cloud.google.com/go/gkemulticloud v0.4.0/go.mod h1:E9gxVBnseLWCk24ch+P9+B2CoDFJZTyIgLKSalC7tuI= -cloud.google.com/go/grafeas v0.2.0/go.mod h1:KhxgtF2hb0P191HlY5besjYm6MqTSTj3LSI+M+ByZHc= -cloud.google.com/go/gsuiteaddons v1.3.0/go.mod h1:EUNK/J1lZEZO8yPtykKxLXI6JSVN2rg9bN8SXOa0bgM= -cloud.google.com/go/gsuiteaddons v1.4.0/go.mod h1:rZK5I8hht7u7HxFQcFei0+AtfS9uSushomRlg+3ua1o= -cloud.google.com/go/iam v0.1.0/go.mod h1:vcUNEa0pEm0qRVpmWepWaFMIAI8/hjB9mO8rNCJtF6c= -cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= -cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc= -cloud.google.com/go/iam v0.6.0/go.mod h1:+1AH33ueBne5MzYccyMHtEKqLE4/kJOibtffMHDMFMc= -cloud.google.com/go/iam v0.7.0/go.mod h1:H5Br8wRaDGNc8XP3keLc4unfUUZeyH3Sfl9XpQEYOeg= -cloud.google.com/go/iam v0.8.0/go.mod h1:lga0/y3iH6CX7sYqypWJ33hf7kkfXJag67naqGESjkE= -cloud.google.com/go/iam v0.11.0/go.mod h1:9PiLDanza5D+oWFZiH1uG+RnRCfEGKoyl6yo4cgWZGY= -cloud.google.com/go/iap v1.4.0/go.mod h1:RGFwRJdihTINIe4wZ2iCP0zF/qu18ZwyKxrhMhygBEc= -cloud.google.com/go/iap v1.5.0/go.mod h1:UH/CGgKd4KyohZL5Pt0jSKE4m3FR51qg6FKQ/z/Ix9A= -cloud.google.com/go/ids v1.1.0/go.mod h1:WIuwCaYVOzHIj2OhN9HAwvW+DBdmUAdcWlFxRl+KubM= -cloud.google.com/go/ids v1.2.0/go.mod h1:5WXvp4n25S0rA/mQWAg1YEEBBq6/s+7ml1RDCW1IrcY= -cloud.google.com/go/iot v1.3.0/go.mod h1:r7RGh2B61+B8oz0AGE+J72AhA0G7tdXItODWsaA2oLs= -cloud.google.com/go/iot v1.4.0/go.mod h1:dIDxPOn0UvNDUMD8Ger7FIaTuvMkj+aGk94RPP0iV+g= -cloud.google.com/go/kms v1.4.0/go.mod h1:fajBHndQ+6ubNw6Ss2sSd+SWvjL26RNo/dr7uxsnnOA= -cloud.google.com/go/kms v1.5.0/go.mod h1:QJS2YY0eJGBg3mnDfuaCyLauWwBJiHRboYxJ++1xJNg= -cloud.google.com/go/kms v1.6.0/go.mod h1:Jjy850yySiasBUDi6KFUwUv2n1+o7QZFyuUJg6OgjA0= -cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic= -cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI= -cloud.google.com/go/language v1.7.0/go.mod h1:DJ6dYN/W+SQOjF8e1hLQXMF21AkH2w9wiPzPCJa2MIE= -cloud.google.com/go/language v1.8.0/go.mod h1:qYPVHf7SPoNNiCL2Dr0FfEFNil1qi3pQEyygwpgVKB8= -cloud.google.com/go/lifesciences v0.5.0/go.mod h1:3oIKy8ycWGPUyZDR/8RNnTOYevhaMLqh5vLUXs9zvT8= -cloud.google.com/go/lifesciences v0.6.0/go.mod h1:ddj6tSX/7BOnhxCSd3ZcETvtNr8NZ6t/iPhY2Tyfu08= -cloud.google.com/go/logging v1.6.1/go.mod h1:5ZO0mHHbvm8gEmeEUHrmDlTDSu5imF6MUP9OfilNXBw= -cloud.google.com/go/longrunning v0.1.1/go.mod h1:UUFxuDWkv22EuY93jjmDMFT5GPQKeFVJBIF6QlTqdsE= -cloud.google.com/go/longrunning v0.3.0/go.mod h1:qth9Y41RRSUE69rDcOn6DdK3HfQfsUI0YSmW3iIlLJc= -cloud.google.com/go/managedidentities v1.3.0/go.mod h1:UzlW3cBOiPrzucO5qWkNkh0w33KFtBJU281hacNvsdE= -cloud.google.com/go/managedidentities v1.4.0/go.mod h1:NWSBYbEMgqmbZsLIyKvxrYbtqOsxY1ZrGM+9RgDqInM= -cloud.google.com/go/maps v0.1.0/go.mod h1:BQM97WGyfw9FWEmQMpZ5T6cpovXXSd1cGmFma94eubI= -cloud.google.com/go/mediatranslation v0.5.0/go.mod h1:jGPUhGTybqsPQn91pNXw0xVHfuJ3leR1wj37oU3y1f4= -cloud.google.com/go/mediatranslation v0.6.0/go.mod h1:hHdBCTYNigsBxshbznuIMFNe5QXEowAuNmmC7h8pu5w= -cloud.google.com/go/memcache v1.4.0/go.mod h1:rTOfiGZtJX1AaFUrOgsMHX5kAzaTQ8azHiuDoTPzNsE= -cloud.google.com/go/memcache v1.5.0/go.mod h1:dk3fCK7dVo0cUU2c36jKb4VqKPS22BTkf81Xq617aWM= -cloud.google.com/go/memcache v1.6.0/go.mod h1:XS5xB0eQZdHtTuTF9Hf8eJkKtR3pVRCcvJwtm68T3rA= -cloud.google.com/go/memcache v1.7.0/go.mod h1:ywMKfjWhNtkQTxrWxCkCFkoPjLHPW6A7WOTVI8xy3LY= -cloud.google.com/go/metastore v1.5.0/go.mod h1:2ZNrDcQwghfdtCwJ33nM0+GrBGlVuh8rakL3vdPY3XY= -cloud.google.com/go/metastore v1.6.0/go.mod h1:6cyQTls8CWXzk45G55x57DVQ9gWg7RiH65+YgPsNh9s= -cloud.google.com/go/metastore v1.7.0/go.mod h1:s45D0B4IlsINu87/AsWiEVYbLaIMeUSoxlKKDqBGFS8= -cloud.google.com/go/metastore v1.8.0/go.mod h1:zHiMc4ZUpBiM7twCIFQmJ9JMEkDSyZS9U12uf7wHqSI= -cloud.google.com/go/monitoring v1.7.0/go.mod h1:HpYse6kkGo//7p6sT0wsIC6IBDET0RhIsnmlA53dvEk= -cloud.google.com/go/monitoring v1.8.0/go.mod h1:E7PtoMJ1kQXWxPjB6mv2fhC5/15jInuulFdYYtlcvT4= -cloud.google.com/go/networkconnectivity v1.4.0/go.mod h1:nOl7YL8odKyAOtzNX73/M5/mGZgqqMeryi6UPZTk/rA= -cloud.google.com/go/networkconnectivity v1.5.0/go.mod h1:3GzqJx7uhtlM3kln0+x5wyFvuVH1pIBJjhCpjzSt75o= -cloud.google.com/go/networkconnectivity v1.6.0/go.mod h1:OJOoEXW+0LAxHh89nXd64uGG+FbQoeH8DtxCHVOMlaM= -cloud.google.com/go/networkconnectivity v1.7.0/go.mod h1:RMuSbkdbPwNMQjB5HBWD5MpTBnNm39iAVpC3TmsExt8= -cloud.google.com/go/networkmanagement v1.4.0/go.mod h1:Q9mdLLRn60AsOrPc8rs8iNV6OHXaGcDdsIQe1ohekq8= -cloud.google.com/go/networkmanagement v1.5.0/go.mod h1:ZnOeZ/evzUdUsnvRt792H0uYEnHQEMaz+REhhzJRcf4= -cloud.google.com/go/networksecurity v0.5.0/go.mod h1:xS6fOCoqpVC5zx15Z/MqkfDwH4+m/61A3ODiDV1xmiQ= -cloud.google.com/go/networksecurity v0.6.0/go.mod h1:Q5fjhTr9WMI5mbpRYEbiexTzROf7ZbDzvzCrNl14nyU= -cloud.google.com/go/notebooks v1.2.0/go.mod h1:9+wtppMfVPUeJ8fIWPOq1UnATHISkGXGqTkxeieQ6UY= -cloud.google.com/go/notebooks v1.3.0/go.mod h1:bFR5lj07DtCPC7YAAJ//vHskFBxA5JzYlH68kXVdk34= -cloud.google.com/go/notebooks v1.4.0/go.mod h1:4QPMngcwmgb6uw7Po99B2xv5ufVoIQ7nOGDyL4P8AgA= -cloud.google.com/go/notebooks v1.5.0/go.mod h1:q8mwhnP9aR8Hpfnrc5iN5IBhrXUy8S2vuYs+kBJ/gu0= -cloud.google.com/go/optimization v1.1.0/go.mod h1:5po+wfvX5AQlPznyVEZjGJTMr4+CAkJf2XSTQOOl9l4= -cloud.google.com/go/optimization v1.2.0/go.mod h1:Lr7SOHdRDENsh+WXVmQhQTrzdu9ybg0NecjHidBq6xs= -cloud.google.com/go/orchestration v1.3.0/go.mod h1:Sj5tq/JpWiB//X/q3Ngwdl5K7B7Y0KZ7bfv0wL6fqVA= -cloud.google.com/go/orchestration v1.4.0/go.mod h1:6W5NLFWs2TlniBphAViZEVhrXRSMgUGDfW7vrWKvsBk= -cloud.google.com/go/orgpolicy v1.4.0/go.mod h1:xrSLIV4RePWmP9P3tBl8S93lTmlAxjm06NSm2UTmKvE= -cloud.google.com/go/orgpolicy v1.5.0/go.mod h1:hZEc5q3wzwXJaKrsx5+Ewg0u1LxJ51nNFlext7Tanwc= -cloud.google.com/go/osconfig v1.7.0/go.mod h1:oVHeCeZELfJP7XLxcBGTMBvRO+1nQ5tFG9VQTmYS2Fs= -cloud.google.com/go/osconfig v1.8.0/go.mod h1:EQqZLu5w5XA7eKizepumcvWx+m8mJUhEwiPqWiZeEdg= -cloud.google.com/go/osconfig v1.9.0/go.mod h1:Yx+IeIZJ3bdWmzbQU4fxNl8xsZ4amB+dygAwFPlvnNo= -cloud.google.com/go/osconfig v1.10.0/go.mod h1:uMhCzqC5I8zfD9zDEAfvgVhDS8oIjySWh+l4WK6GnWw= -cloud.google.com/go/oslogin v1.4.0/go.mod h1:YdgMXWRaElXz/lDk1Na6Fh5orF7gvmJ0FGLIs9LId4E= -cloud.google.com/go/oslogin v1.5.0/go.mod h1:D260Qj11W2qx/HVF29zBg+0fd6YCSjSqLUkY/qEenQU= -cloud.google.com/go/oslogin v1.6.0/go.mod h1:zOJ1O3+dTU8WPlGEkFSh7qeHPPSoxrcMbbK1Nm2iX70= -cloud.google.com/go/oslogin v1.7.0/go.mod h1:e04SN0xO1UNJ1M5GP0vzVBFicIe4O53FOfcixIqTyXo= -cloud.google.com/go/phishingprotection v0.5.0/go.mod h1:Y3HZknsK9bc9dMi+oE8Bim0lczMU6hrX0UpADuMefr0= -cloud.google.com/go/phishingprotection v0.6.0/go.mod h1:9Y3LBLgy0kDTcYET8ZH3bq/7qni15yVUoAxiFxnlSUA= -cloud.google.com/go/policytroubleshooter v1.3.0/go.mod h1:qy0+VwANja+kKrjlQuOzmlvscn4RNsAc0e15GGqfMxg= -cloud.google.com/go/policytroubleshooter v1.4.0/go.mod h1:DZT4BcRw3QoO8ota9xw/LKtPa8lKeCByYeKTIf/vxdE= -cloud.google.com/go/privatecatalog v0.5.0/go.mod h1:XgosMUvvPyxDjAVNDYxJ7wBW8//hLDDYmnsNcMGq1K0= -cloud.google.com/go/privatecatalog v0.6.0/go.mod h1:i/fbkZR0hLN29eEWiiwue8Pb+GforiEIBnV9yrRUOKI= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/pubsub v1.26.0/go.mod h1:QgBH3U/jdJy/ftjPhTkyXNj543Tin1pRYcdcPRnFIRI= -cloud.google.com/go/pubsub v1.27.1/go.mod h1:hQN39ymbV9geqBnfQq6Xf63yNhUAhv9CZhzp5O6qsW0= -cloud.google.com/go/pubsublite v1.5.0/go.mod h1:xapqNQ1CuLfGi23Yda/9l4bBCKz/wC3KIJ5gKcxveZg= -cloud.google.com/go/recaptchaenterprise v1.3.1/go.mod h1:OdD+q+y4XGeAlxRaMn1Y7/GveP6zmq76byL6tjPE7d4= -cloud.google.com/go/recaptchaenterprise/v2 v2.1.0/go.mod h1:w9yVqajwroDNTfGuhmOjPDN//rZGySaf6PtFVcSCa7o= -cloud.google.com/go/recaptchaenterprise/v2 v2.2.0/go.mod h1:/Zu5jisWGeERrd5HnlS3EUGb/D335f9k51B/FVil0jk= -cloud.google.com/go/recaptchaenterprise/v2 v2.3.0/go.mod h1:O9LwGCjrhGHBQET5CA7dd5NwwNQUErSgEDit1DLNTdo= -cloud.google.com/go/recaptchaenterprise/v2 v2.4.0/go.mod h1:Am3LHfOuBstrLrNCBrlI5sbwx9LBg3te2N6hGvHn2mE= -cloud.google.com/go/recaptchaenterprise/v2 v2.5.0/go.mod h1:O8LzcHXN3rz0j+LBC91jrwI3R+1ZSZEWrfL7XHgNo9U= -cloud.google.com/go/recommendationengine v0.5.0/go.mod h1:E5756pJcVFeVgaQv3WNpImkFP8a+RptV6dDLGPILjvg= -cloud.google.com/go/recommendationengine v0.6.0/go.mod h1:08mq2umu9oIqc7tDy8sx+MNJdLG0fUi3vaSVbztHgJ4= -cloud.google.com/go/recommender v1.5.0/go.mod h1:jdoeiBIVrJe9gQjwd759ecLJbxCDED4A6p+mqoqDvTg= -cloud.google.com/go/recommender v1.6.0/go.mod h1:+yETpm25mcoiECKh9DEScGzIRyDKpZ0cEhWGo+8bo+c= -cloud.google.com/go/recommender v1.7.0/go.mod h1:XLHs/W+T8olwlGOgfQenXBTbIseGclClff6lhFVe9Bs= -cloud.google.com/go/recommender v1.8.0/go.mod h1:PkjXrTT05BFKwxaUxQmtIlrtj0kph108r02ZZQ5FE70= -cloud.google.com/go/redis v1.7.0/go.mod h1:V3x5Jq1jzUcg+UNsRvdmsfuFnit1cfe3Z/PGyq/lm4Y= -cloud.google.com/go/redis v1.8.0/go.mod h1:Fm2szCDavWzBk2cDKxrkmWBqoCiL1+Ctwq7EyqBCA/A= -cloud.google.com/go/redis v1.9.0/go.mod h1:HMYQuajvb2D0LvMgZmLDZW8V5aOC/WxstZHiy4g8OiA= -cloud.google.com/go/redis v1.10.0/go.mod h1:ThJf3mMBQtW18JzGgh41/Wld6vnDDc/F/F35UolRZPM= -cloud.google.com/go/resourcemanager v1.3.0/go.mod h1:bAtrTjZQFJkiWTPDb1WBjzvc6/kifjj4QBYuKCCoqKA= -cloud.google.com/go/resourcemanager v1.4.0/go.mod h1:MwxuzkumyTX7/a3n37gmsT3py7LIXwrShilPh3P1tR0= -cloud.google.com/go/resourcesettings v1.3.0/go.mod h1:lzew8VfESA5DQ8gdlHwMrqZs1S9V87v3oCnKCWoOuQU= -cloud.google.com/go/resourcesettings v1.4.0/go.mod h1:ldiH9IJpcrlC3VSuCGvjR5of/ezRrOxFtpJoJo5SmXg= -cloud.google.com/go/retail v1.8.0/go.mod h1:QblKS8waDmNUhghY2TI9O3JLlFk8jybHeV4BF19FrE4= -cloud.google.com/go/retail v1.9.0/go.mod h1:g6jb6mKuCS1QKnH/dpu7isX253absFl6iE92nHwlBUY= -cloud.google.com/go/retail v1.10.0/go.mod h1:2gDk9HsL4HMS4oZwz6daui2/jmKvqShXKQuB2RZ+cCc= -cloud.google.com/go/retail v1.11.0/go.mod h1:MBLk1NaWPmh6iVFSz9MeKG/Psyd7TAgm6y/9L2B4x9Y= -cloud.google.com/go/run v0.2.0/go.mod h1:CNtKsTA1sDcnqqIFR3Pb5Tq0usWxJJvsWOCPldRU3Do= -cloud.google.com/go/run v0.3.0/go.mod h1:TuyY1+taHxTjrD0ZFk2iAR+xyOXEA0ztb7U3UNA0zBo= -cloud.google.com/go/scheduler v1.4.0/go.mod h1:drcJBmxF3aqZJRhmkHQ9b3uSSpQoltBPGPxGAWROx6s= -cloud.google.com/go/scheduler v1.5.0/go.mod h1:ri073ym49NW3AfT6DZi21vLZrG07GXr5p3H1KxN5QlI= -cloud.google.com/go/scheduler v1.6.0/go.mod h1:SgeKVM7MIwPn3BqtcBntpLyrIJftQISRrYB5ZtT+KOk= -cloud.google.com/go/scheduler v1.7.0/go.mod h1:jyCiBqWW956uBjjPMMuX09n3x37mtyPJegEWKxRsn44= -cloud.google.com/go/secretmanager v1.6.0/go.mod h1:awVa/OXF6IiyaU1wQ34inzQNc4ISIDIrId8qE5QGgKA= -cloud.google.com/go/secretmanager v1.8.0/go.mod h1:hnVgi/bN5MYHd3Gt0SPuTPPp5ENina1/LxM+2W9U9J4= -cloud.google.com/go/secretmanager v1.9.0/go.mod h1:b71qH2l1yHmWQHt9LC80akm86mX8AL6X1MA01dW8ht4= -cloud.google.com/go/security v1.5.0/go.mod h1:lgxGdyOKKjHL4YG3/YwIL2zLqMFCKs0UbQwgyZmfJl4= -cloud.google.com/go/security v1.7.0/go.mod h1:mZklORHl6Bg7CNnnjLH//0UlAlaXqiG7Lb9PsPXLfD0= -cloud.google.com/go/security v1.8.0/go.mod h1:hAQOwgmaHhztFhiQ41CjDODdWP0+AE1B3sX4OFlq+GU= -cloud.google.com/go/security v1.9.0/go.mod h1:6Ta1bO8LXI89nZnmnsZGp9lVoVWXqsVbIq/t9dzI+2Q= -cloud.google.com/go/security v1.10.0/go.mod h1:QtOMZByJVlibUT2h9afNDWRZ1G96gVywH8T5GUSb9IA= -cloud.google.com/go/securitycenter v1.13.0/go.mod h1:cv5qNAqjY84FCN6Y9z28WlkKXyWsgLO832YiWwkCWcU= -cloud.google.com/go/securitycenter v1.14.0/go.mod h1:gZLAhtyKv85n52XYWt6RmeBdydyxfPeTrpToDPw4Auc= -cloud.google.com/go/securitycenter v1.15.0/go.mod h1:PeKJ0t8MoFmmXLXWm41JidyzI3PJjd8sXWaVqg43WWk= -cloud.google.com/go/securitycenter v1.16.0/go.mod h1:Q9GMaLQFUD+5ZTabrbujNWLtSLZIZF7SAR0wWECrjdk= -cloud.google.com/go/servicecontrol v1.4.0/go.mod h1:o0hUSJ1TXJAmi/7fLJAedOovnujSEvjKCAFNXPQ1RaU= -cloud.google.com/go/servicecontrol v1.5.0/go.mod h1:qM0CnXHhyqKVuiZnGKrIurvVImCs8gmqWsDoqe9sU1s= -cloud.google.com/go/servicedirectory v1.4.0/go.mod h1:gH1MUaZCgtP7qQiI+F+A+OpeKF/HQWgtAddhTbhL2bs= -cloud.google.com/go/servicedirectory v1.5.0/go.mod h1:QMKFL0NUySbpZJ1UZs3oFAmdvVxhhxB6eJ/Vlp73dfg= -cloud.google.com/go/servicedirectory v1.6.0/go.mod h1:pUlbnWsLH9c13yGkxCmfumWEPjsRs1RlmJ4pqiNjVL4= -cloud.google.com/go/servicedirectory v1.7.0/go.mod h1:5p/U5oyvgYGYejufvxhgwjL8UVXjkuw7q5XcG10wx1U= -cloud.google.com/go/servicemanagement v1.4.0/go.mod h1:d8t8MDbezI7Z2R1O/wu8oTggo3BI2GKYbdG4y/SJTco= -cloud.google.com/go/servicemanagement v1.5.0/go.mod h1:XGaCRe57kfqu4+lRxaFEAuqmjzF0r+gWHjWqKqBvKFo= -cloud.google.com/go/serviceusage v1.3.0/go.mod h1:Hya1cozXM4SeSKTAgGXgj97GlqUvF5JaoXacR1JTP/E= -cloud.google.com/go/serviceusage v1.4.0/go.mod h1:SB4yxXSaYVuUBYUml6qklyONXNLt83U0Rb+CXyhjEeU= -cloud.google.com/go/shell v1.3.0/go.mod h1:VZ9HmRjZBsjLGXusm7K5Q5lzzByZmJHf1d0IWHEN5X4= -cloud.google.com/go/shell v1.4.0/go.mod h1:HDxPzZf3GkDdhExzD/gs8Grqk+dmYcEjGShZgYa9URw= -cloud.google.com/go/spanner v1.41.0/go.mod h1:MLYDBJR/dY4Wt7ZaMIQ7rXOTLjYrmxLE/5ve9vFfWos= -cloud.google.com/go/speech v1.6.0/go.mod h1:79tcr4FHCimOp56lwC01xnt/WPJZc4v3gzyT7FoBkCM= -cloud.google.com/go/speech v1.7.0/go.mod h1:KptqL+BAQIhMsj1kOP2la5DSEEerPDuOP/2mmkhHhZQ= -cloud.google.com/go/speech v1.8.0/go.mod h1:9bYIl1/tjsAnMgKGHKmBZzXKEkGgtU+MpdDPTE9f7y0= -cloud.google.com/go/speech v1.9.0/go.mod h1:xQ0jTcmnRFFM2RfX/U+rk6FQNUF6DQlydUSyoooSpco= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= -cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= -cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc= -cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= -cloud.google.com/go/storagetransfer v1.5.0/go.mod h1:dxNzUopWy7RQevYFHewchb29POFv3/AaBgnhqzqiK0w= -cloud.google.com/go/storagetransfer v1.6.0/go.mod h1:y77xm4CQV/ZhFZH75PLEXY0ROiS7Gh6pSKrM8dJyg6I= -cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw= -cloud.google.com/go/talent v1.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g= -cloud.google.com/go/talent v1.3.0/go.mod h1:CmcxwJ/PKfRgd1pBjQgU6W3YBwiewmUzQYH5HHmSCmM= -cloud.google.com/go/talent v1.4.0/go.mod h1:ezFtAgVuRf8jRsvyE6EwmbTK5LKciD4KVnHuDEFmOOA= -cloud.google.com/go/texttospeech v1.4.0/go.mod h1:FX8HQHA6sEpJ7rCMSfXuzBcysDAuWusNNNvN9FELDd8= -cloud.google.com/go/texttospeech v1.5.0/go.mod h1:oKPLhR4n4ZdQqWKURdwxMy0uiTS1xU161C8W57Wkea4= -cloud.google.com/go/tpu v1.3.0/go.mod h1:aJIManG0o20tfDQlRIej44FcwGGl/cD0oiRyMKG19IQ= -cloud.google.com/go/tpu v1.4.0/go.mod h1:mjZaX8p0VBgllCzF6wcU2ovUXN9TONFLd7iz227X2Xg= -cloud.google.com/go/trace v1.3.0/go.mod h1:FFUE83d9Ca57C+K8rDl/Ih8LwOzWIV1krKgxg6N0G28= -cloud.google.com/go/trace v1.4.0/go.mod h1:UG0v8UBqzusp+z63o7FK74SdFE+AXpCLdFb1rshXG+Y= -cloud.google.com/go/translate v1.3.0/go.mod h1:gzMUwRjvOqj5i69y/LYLd8RrNQk+hOmIXTi9+nb3Djs= -cloud.google.com/go/translate v1.4.0/go.mod h1:06Dn/ppvLD6WvA5Rhdp029IX2Mi3Mn7fpMRLPvXT5Wg= -cloud.google.com/go/video v1.8.0/go.mod h1:sTzKFc0bUSByE8Yoh8X0mn8bMymItVGPfTuUBUyRgxk= -cloud.google.com/go/video v1.9.0/go.mod h1:0RhNKFRF5v92f8dQt0yhaHrEuH95m068JYOvLZYnJSw= -cloud.google.com/go/videointelligence v1.6.0/go.mod h1:w0DIDlVRKtwPCn/C4iwZIJdvC69yInhW0cfi+p546uU= -cloud.google.com/go/videointelligence v1.7.0/go.mod h1:k8pI/1wAhjznARtVT9U1llUaFNPh7muw8QyOUpavru4= -cloud.google.com/go/videointelligence v1.8.0/go.mod h1:dIcCn4gVDdS7yte/w+koiXn5dWVplOZkE+xwG9FgK+M= -cloud.google.com/go/videointelligence v1.9.0/go.mod h1:29lVRMPDYHikk3v8EdPSaL8Ku+eMzDljjuvRs105XoU= -cloud.google.com/go/vision v1.2.0/go.mod h1:SmNwgObm5DpFBme2xpyOyasvBc1aPdjvMk2bBk0tKD0= -cloud.google.com/go/vision/v2 v2.2.0/go.mod h1:uCdV4PpN1S0jyCyq8sIM42v2Y6zOLkZs+4R9LrGYwFo= -cloud.google.com/go/vision/v2 v2.3.0/go.mod h1:UO61abBx9QRMFkNBbf1D8B1LXdS2cGiiCRx0vSpZoUo= -cloud.google.com/go/vision/v2 v2.4.0/go.mod h1:VtI579ll9RpVTrdKdkMzckdnwMyX2JILb+MhPqRbPsY= -cloud.google.com/go/vision/v2 v2.5.0/go.mod h1:MmaezXOOE+IWa+cS7OhRRLK2cNv1ZL98zhqFFZaaH2E= -cloud.google.com/go/vmmigration v1.2.0/go.mod h1:IRf0o7myyWFSmVR1ItrBSFLFD/rJkfDCUTO4vLlJvsE= -cloud.google.com/go/vmmigration v1.3.0/go.mod h1:oGJ6ZgGPQOFdjHuocGcLqX4lc98YQ7Ygq8YQwHh9A7g= -cloud.google.com/go/vmwareengine v0.1.0/go.mod h1:RsdNEf/8UDvKllXhMz5J40XxDrNJNN4sagiox+OI208= -cloud.google.com/go/vpcaccess v1.4.0/go.mod h1:aQHVbTWDYUR1EbTApSVvMq1EnT57ppDmQzZ3imqIk4w= -cloud.google.com/go/vpcaccess v1.5.0/go.mod h1:drmg4HLk9NkZpGfCmZ3Tz0Bwnm2+DKqViEpeEpOq0m8= -cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xXZmFiHmGE= -cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= -cloud.google.com/go/webrisk v1.6.0/go.mod h1:65sW9V9rOosnc9ZY7A7jsy1zoHS5W9IAXv6dGqhMQMc= -cloud.google.com/go/webrisk v1.7.0/go.mod h1:mVMHgEYH0r337nmt1JyLthzMr6YxwN1aAIEc2fTcq7A= -cloud.google.com/go/websecurityscanner v1.3.0/go.mod h1:uImdKm2wyeXQevQJXeh8Uun/Ym1VqworNDlBXQevGMo= -cloud.google.com/go/websecurityscanner v1.4.0/go.mod h1:ebit/Fp0a+FWu5j4JOmJEV8S8CzdTkAS77oDsiSqYWQ= -cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= -cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= -cloud.google.com/go/workflows v1.8.0/go.mod h1:ysGhmEajwZxGn1OhGOGKsTXc5PyxOc0vfKf5Af+to4M= -cloud.google.com/go/workflows v1.9.0/go.mod h1:ZGkj1aFIOd9c8Gerkjjq7OW7I5+l6cSvT3ujaO/WwSA= dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU= @@ -435,14 +96,10 @@ github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a/go.mod h1:SGn github.com/alicebob/miniredis/v2 v2.22.0 h1:lIHHiSkEyS1MkKHCHzN+0mWrA4YdbGdimE5iZ2sHSzo= github.com/alicebob/miniredis/v2 v2.22.0/go.mod h1:XNqvJdQJv5mSuVMc0ynneafpnL/zv52acZ6kqeS0t88= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= -github.com/ansel1/merry v1.5.0/go.mod h1:wUy/yW0JX0ix9GYvUbciq+bi3jW/vlKPlbpI7qdZpOw= -github.com/ansel1/merry v1.5.1/go.mod h1:wUy/yW0JX0ix9GYvUbciq+bi3jW/vlKPlbpI7qdZpOw= -github.com/ansel1/merry v1.6.2 h1:0xr40haRrfVzmOH/JVOu7KOKGEI1c/7q5EmgTEbn+Ng= -github.com/ansel1/merry v1.6.2/go.mod h1:pAcMW+2uxIgpzEON021vMtFsrymREY6faJWiiz1QGVQ= -github.com/ansel1/merry/v2 v2.0.1/go.mod h1:dD5OhpiPrVkvgseRYd+xgYlx7s6ytU3v9BTTJlDA7FM= -github.com/ansel1/merry/v2 v2.1.1 h1:Ax0gQh7Z/GfimoVg2EDBAU6CJIieWwVvhtBKJdkCE1M= -github.com/ansel1/merry/v2 v2.1.1/go.mod h1:4p/FFyQbCgqlDbseWOVQaL5USpgkE9sr5xh4V6Ry0JU= -github.com/ansel1/vespucci/v4 v4.1.1/go.mod h1:zzdrO4IgBfgcGMbGTk/qNGL8JPslmW3nPpcBHKReFYY= +github.com/ansel1/merry v1.8.0 h1:3RddCV1ubXegKphsodbkmZ4QuROep/ZaPCuwlKuCfFg= +github.com/ansel1/merry v1.8.0/go.mod h1:wJVu1mHEtEUWq5zTTX9RiWjcE+xL8y7BGYl2VTYdP7M= +github.com/ansel1/merry/v2 v2.2.1 h1:PJpynLFvIpJkn8ZGgNHLq332zIyBc/wTqp3o42ZpWdU= +github.com/ansel1/merry/v2 v2.2.1/go.mod h1:K9lCkM6tJ8s7LQVQ0ZmZ0WrB3BCyr+ZDzoqotzzoxpI= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= @@ -451,10 +108,6 @@ github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/aws/aws-sdk-go v1.44.293 h1:oBPrQqsyMYe61Sl/xKVvQFflXjPwYH11aKi8QR3Nhts= github.com/aws/aws-sdk-go v1.44.293/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= -github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df h1:GSoSVRLoBaFpOOds6QyY1L8AX7uoY+Ln3BHc22W40X0= -github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df/go.mod h1:hiVxq5OP2bUGBRNS3Z/bt/reCLFNbdcST6gISi1fiOM= -github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -500,8 +153,6 @@ github.com/blevesearch/zapx/v14 v14.3.8/go.mod h1:vS6exLagv0vXmgpUbNRZC6UuEV0xwT github.com/blevesearch/zapx/v15 v15.3.11 h1:dstyZki9s10FNLsW4LpEvPQ+fmM3nX15h4wKfcBwnEg= github.com/blevesearch/zapx/v15 v15.3.11/go.mod h1:hiYbBDf5/Ud/Eji0faUmMTOyeOjcl8q1vWGgRe7+bIQ= github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= -github.com/bradfitz/gomemcache v0.0.0-20221031212613-62deef7fc822 h1:hjXJeBcAMS1WGENGqDpzvmgS43oECTx8UXq31UBu0Jw= -github.com/bradfitz/gomemcache v0.0.0-20221031212613-62deef7fc822/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA= github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= @@ -510,8 +161,6 @@ github.com/bwmarrin/discordgo v0.25.0/go.mod h1:NJZpH+1AfhIcyQsPeuBKsUtYrRnjkyu0 github.com/carlosdp/twiliogo v0.0.0-20161027183705-b26045ebb9d1 h1:hXakhQtPnXH839q1pBl/GqfTSchqE+R5Fqn98Iu7UQM= github.com/carlosdp/twiliogo v0.0.0-20161027183705-b26045ebb9d1/go.mod h1:pAxCBpjl/0JxYZlWGP/Dyi8f/LQSCQD2WAsG/iNzqQ8= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -527,14 +176,11 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20220314180256-7f1daf1720fc/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20230105202645-06c439db220b/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= @@ -543,10 +189,9 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 github.com/cyberdelia/go-metrics-graphite v0.0.0-20161219230853-39f87cc3b432 h1:M5QgkYacWj0Xs8MhpIK/5uwU02icXpEoSo9sM2aRCps= github.com/cyberdelia/go-metrics-graphite v0.0.0-20161219230853-39f87cc3b432/go.mod h1:xwIwAxMvYnVrGJPe2FKx5prTrnAjGOD8zvDOnxnrrkM= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -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/dgryski/go-expirecache v0.0.0-20170314133854-743ef98b2adb h1:X9MwMz6mVZEWcbhsri5TwaCm/Q4USFdAAmy1T7RCGjw= -github.com/dgryski/go-expirecache v0.0.0-20170314133854-743ef98b2adb/go.mod h1:pD/+9DfmmQ+xvOI1fxUltHV69BxC1aeTILPQg9Kw1hE= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgryski/go-onlinestats v0.0.0-20170612111826-1c7d19468768 h1:Xzl7CSuSnGsyU+9xmSU2h8w3d7Tnis66xeoNN207tLo= github.com/dgryski/go-onlinestats v0.0.0-20170612111826-1c7d19468768/go.mod h1:alfmlCqcg4uw9jaoIU1nOp9RFdJLMuu8P07BCEgpgoo= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= @@ -571,10 +216,7 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.m github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= -github.com/envoyproxy/go-control-plane v0.10.3/go.mod h1:fJJn/j26vwOu972OllsvAgJJM//w9BV6Fxbg2LuVd34= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J6romD608Ba7Hij42vrOBCo= -github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w= github.com/evmar/gocairo v0.0.0-20160222165215-ddd30f837497 h1:DIQ8EvZ8OjuPNfcV4NgsyBeZho7WsTD0JEkDM5napMI= github.com/evmar/gocairo v0.0.0-20160222165215-ddd30f837497/go.mod h1:YXKUYPSqs+jDG8mvexHN2uTik4PKwg2B0WK9itQ0VrE= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= @@ -589,13 +231,13 @@ github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJn github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= -github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= -github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/go-asn1-ber/asn1-ber v1.5.5 h1:MNHlNMBDgEKD4TcKr36vQN68BA00aDfjIt3/bD50WnA= @@ -610,8 +252,8 @@ github.com/go-errors/errors v1.1.1/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWE github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-graphite/carbonapi v0.16.0 h1:HvPjAKYChiwdHtNpFu33hLRpPCYA7gyyeFWpPR2XvXs= -github.com/go-graphite/carbonapi v0.16.0/go.mod h1:RQpis4h2a1kxn1s/R5LQXbumFj+kR2bRz+BebPN1Z1Q= +github.com/go-graphite/carbonapi v0.16.2-0.20240530091606-c2229eabd094 h1:1obdNCH61kxvX5LLS0Pq4EP4U0GEHOutbVMgkH5yDwM= +github.com/go-graphite/carbonapi v0.16.2-0.20240530091606-c2229eabd094/go.mod h1:EwQ1MJBzP8BBozLkgwTZdePM/5SqPSxhtY0uDdER2LQ= github.com/go-graphite/protocol v1.0.0 h1:Fqb0mkVVtfMrn6vw6Ntm3raf3gVVZCOVdZu4JosW5qE= github.com/go-graphite/protocol v1.0.0/go.mod h1:eonkg/0UGhJUYu+PshOg1NzWSUcXskr/yHeQXJHJr8Y= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= @@ -666,7 +308,6 @@ github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGw github.com/golang/geo v0.0.0-20230421003525-6adc56603217 h1:HKlyj6in2JV6wVkmQ4XmG/EIm+SCYlPZ+V4GWit7Z+I= github.com/golang/geo v0.0.0-20230421003525-6adc56603217/go.mod h1:8wI0hitZ3a1IxZfeH3/5I97CI8i5cLGsYe7xNhQGs9U= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -698,14 +339,14 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/gomodule/redigo v1.8.2/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0= -github.com/gomodule/redigo v1.8.9 h1:Sl3u+2BI/kk+VEatbj0scLdrFhjPmbxOc1myhDP41ws= -github.com/gomodule/redigo v1.8.9/go.mod h1:7ArFNvsTjH8GMMzB4uy1snslv2BwmginuMs06a1uzZE= +github.com/gomodule/redigo v1.9.2 h1:HrutZBLhSIU8abiSfW8pj8mPhOyMYjZT/wcA4/L9L9s= +github.com/gomodule/redigo v1.9.2/go.mod h1:KsU3hiK/Ay8U42qpaJk+kuNa3C+spxapWpM+ywhcgtw= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -722,7 +363,6 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= @@ -753,14 +393,8 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4 github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= -github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= -github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= -github.com/googleapis/enterprise-certificate-proxy v0.2.1/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= -github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= @@ -770,10 +404,6 @@ github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0 github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM= github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM= github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= -github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo= -github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= -github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= -github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25dO0g= @@ -791,8 +421,6 @@ github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:Fecb github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w= github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw= github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI= github.com/hashicorp/consul/api v1.12.0/go.mod h1:6pVBMo0ebnYdt2S3H87XhekM/HHrUoTD2XXb/VrZVy0= @@ -844,7 +472,6 @@ github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbg github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4= github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= -github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA= @@ -878,8 +505,6 @@ github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7 github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= -github.com/k0kubun/pp v2.3.0+incompatible/go.mod h1:GWse8YhT0p8pT4ir3ZgBbfZild3tgzSScAn6HmfYukg= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.12.2/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= @@ -906,8 +531,6 @@ github.com/lomik/og-rek v0.0.0-20170411191824-628eefeb8d80/go.mod h1:T7SQVaLtK7m github.com/lomik/zapwriter v0.0.0-20210624082824-c1161d1eb463 h1:SN/0TEkyYpp8tit79JPUnecebCGZsXiYYPxN8i3I6Rk= github.com/lomik/zapwriter v0.0.0-20210624082824-c1161d1eb463/go.mod h1:rWIJAUD2hPOAyOzc3jBShAhN4CAZeLAyzUA/n8tE8ak= github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= -github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= -github.com/lyft/protoc-gen-star v0.6.1/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= @@ -917,8 +540,8 @@ github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/maruel/natural v1.1.0 h1:2z1NgP/Vae+gYrtC0VuvrTJ6U35OuyUqDdfluLqMWuQ= -github.com/maruel/natural v1.1.0/go.mod h1:eFVhYCcUOfZFxXoDZam8Ktya72wa79fNC3lc/leA0DQ= +github.com/maruel/natural v1.1.1 h1:Hja7XhhmvEFhcByqDoHz9QZbkWey+COd9xWfCfn1ioo= +github.com/maruel/natural v1.1.1/go.mod h1:v+Rfd79xlw1AgVBjbO0BEQmptqb5HvL/k9GRHB7ZKEg= github.com/mattermost/go-i18n v1.11.1-0.20211013152124-5c415071e404 h1:Khvh6waxG1cHc4Cz5ef9n3XVCxRWpAKUtqg9PJl5+y8= github.com/mattermost/go-i18n v1.11.1-0.20211013152124-5c415071e404/go.mod h1:RyS7FDNQlzF1PsjbJWHRI35exqaKGSO9qD4iv8QjE34= github.com/mattermost/ldap v0.0.0-20231116144001-0f480c025956 h1:Y1Tu/swM31pVwwb2BTCsOdamENjjWCI6qmfHLbk6OZI= @@ -936,7 +559,6 @@ github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= @@ -979,15 +601,13 @@ github.com/moira-alert/blackfriday-slack v0.1.2 h1:W6VbDlHDBxoB7X+OJ+3xZZuzMcQ0q github.com/moira-alert/blackfriday-slack v0.1.2/go.mod h1:tYMK3laTzU1wgxeOpUPdw36KHD3eTyQNDfxtg1nXLWI= github.com/moira-alert/go-chart v0.0.0-20231107064049-444c44a558ef h1:hSEQ/9B23MTYQCxx+GTRW5P1eWaqtgEMEqOxXs/YNKE= github.com/moira-alert/go-chart v0.0.0-20231107064049-444c44a558ef/go.mod h1:ktrkvZGboMQfYyBXAV05imlVxGIvVdeCn5vz91Fw1vE= -github.com/msaf1980/go-stringutils v0.1.4 h1:UwsIT0hplHVucqbknk3CoNqKkmIuSHhsbBldXxyld5U= -github.com/msaf1980/go-stringutils v0.1.4/go.mod h1:AxmV/6JuQUAtZJg5XmYATB5ZwCWgtpruVHY03dswRf8= +github.com/msaf1980/go-stringutils v0.1.6 h1:qri8o+4XLJCJYemHcvJY6xJhrGTmllUoPwayKEj4NSg= +github.com/msaf1980/go-stringutils v0.1.6/go.mod h1:xpicaTIpLAVzL0gUQkciB1zjypDGKsOCI25cKQbRQYA= github.com/mschoch/smat v0.2.0 h1:8imxQsjDm8yFEAVBe7azKmKSgzSkZXDuKkSq9374khM= github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOlotKw= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/natefinch/atomic v1.0.1 h1:ZPYKxkqQOx3KZ+RsbnP/YsgvxWQPGxjC0oBt2AhwV0A= -github.com/natefinch/atomic v1.0.1/go.mod h1:N/D/ELrljoqDyT3rZrsUmtsuzvHkeB/wWjHV22AZRbM= github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32 h1:W6apQkHrMkS0Muv8G/TipAy/FJl/rCYT0+EuS8+Z0z4= github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms= github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= @@ -1023,8 +643,8 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9 github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas= -github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= -github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= +github.com/pelletier/go-toml/v2 v2.2.1 h1:9TA9+T8+8CUCO2+WYnDLCgrYi9+omqKXyjDtosvtEhg= +github.com/pelletier/go-toml/v2 v2.2.1/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/philhofer/fwd v1.1.2 h1:bnDivRJ1EWPjUIRXV5KfORO897HTbpFAQddBdE8t7Gw= github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0= github.com/pierrec/lz4 v2.6.0+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= @@ -1032,10 +652,10 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= @@ -1091,6 +711,10 @@ github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sagikazarmark/crypt v0.6.0/go.mod h1:U8+INwJo3nBv1m6A/8OBXAq7Jnpspk5AxSgDyEQcea8= +github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= +github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= +github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= @@ -1130,31 +754,29 @@ github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYl github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hgR6gDIPg= github.com/smartystreets/goconvey v1.7.2/go.mod h1:Vw0tHAZW6lzCRk3xgdin6fKYcG+G3Pg9vgXWeJpQFMM= github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= -github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo= -github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= -github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= -github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= -github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= -github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= -github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= +github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= +github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.13.0/go.mod h1:Icm2xNL3/8uyh/wFuB1jI7TiTNKp8632Nwegu+zgdYw= -github.com/spf13/viper v1.16.0 h1:rGGH0XDZhdUOryiDWjmIvUSWpbNqisK8Wk0Vyefw8hc= -github.com/spf13/viper v1.16.0/go.mod h1:yg78JgCJcbrQOvV9YLXgkLaZqUidkY9K+Dd1FofRzQg= +github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= +github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/objx v0.5.1 h1:4VhoImhV/Bm0ToFkXFi8hXNXwpDRZ/ynw3amt82mzq0= -github.com/stretchr/objx v0.5.1/go.mod h1:/iHQpkQwBD6DLUmQ4pE+s1TXdob1mORJ4/UFdrifcy0= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -1166,15 +788,14 @@ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1F github.com/stretchr/testify v1.7.5/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203 h1:QVqDTf3h2WHt08YuiTGPZLls0Wq99X9bWd0Q5ZSBesM= github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203/go.mod h1:oqN97ltKNihBbwlX8dLpwxCl3+HnXKV/R0e+sRLd9C8= github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= -github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= -github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/swaggo/files v1.0.1 h1:J1bVJ4XHZNq0I46UU90611i9/YzdrF7x92oX1ig5IdE= github.com/swaggo/files v1.0.1/go.mod h1:0qXmMNH6sXNf+73t65aKeB+ApmgxdnkQzVTAj2uaMUg= github.com/swaggo/http-swagger v1.3.4 h1:q7t/XLx0n15H1Q9/tk3Y9L4n210XzJF5WtnDX64a5ww= @@ -1182,6 +803,8 @@ github.com/swaggo/http-swagger v1.3.4/go.mod h1:9dAh0unqMBAlbp1uE2Uc2mQTxNMU/ha4 github.com/swaggo/swag v1.8.12 h1:pctzkNPu0AlQP2royqX3apjKCQonAnf7KGoxeO4y64w= github.com/swaggo/swag v1.8.12/go.mod h1:lNfm6Gg+oAq3zRJQNEMBE66LIJKM44mxFqhEEgy2its= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= +github.com/tebeka/strftime v0.1.5 h1:1NQKN1NiQgkqd/2moD6ySP/5CoZQsKa1d3ZhJ44Jpmg= +github.com/tebeka/strftime v0.1.5/go.mod h1:29/OidkoWHdEKZqzyDLUyC+LmgDgdHo4WAFCDT7D/Ig= github.com/tinylib/msgp v1.1.9 h1:SHf3yoO2sGA0veCJeCBYLHuttAVFHGm2RHgNodW7wQU= github.com/tinylib/msgp v1.1.9/go.mod h1:BCXGB54lDD8qUEPmiG0cQQUANC4IUQyB2ItS2UDlO/k= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= @@ -1225,24 +848,20 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= -go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/automaxprocs v1.5.1 h1:e1YG66Lrk73dn4qhg8WFSvhF0JuFQF0ERIp4rpuV8Qk= go.uber.org/automaxprocs v1.5.1/go.mod h1:BF4eumQw0P9GtnuxxovUd06vwm1o18oMzFtK66vU6XU= -go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= -go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8= -go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= -go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= -go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -1251,7 +870,6 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -1260,7 +878,6 @@ golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= @@ -1279,8 +896,8 @@ golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXy golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.13.0 h1:3cge/F/QTkNLauhf2QoE9zp+7sr+ZcL4HnoZmdwg9sg= -golang.org/x/image v0.13.0/go.mod h1:6mmbMOeV28HuMTgA6OSRkdXKYw/t5W9Uwn2Yv1r3Yxk= +golang.org/x/image v0.14.0 h1:tNgSxAFe3jC4uYqvZdTr84SZoM1KfwdC9SKIFrLjFn4= +golang.org/x/image v0.14.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -1305,9 +922,7 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1359,7 +974,6 @@ golang.org/x/net v0.0.0-20210427231257-85d9c07bbe3a/go.mod h1:OJAsFXCWl8Ukc7SiCT golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= @@ -1367,17 +981,9 @@ golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220617184016-355a448f1bc9/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.0.0-20221012135044-0b7e1fb9d458/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= @@ -1403,14 +1009,6 @@ golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= -golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= -golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.0.0-20221006150949-b44042a4b9c1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec= -golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= golang.org/x/oauth2 v0.17.0 h1:6m3ZPmLEFdVxKKWnKq4VqZ60gutO35zm+zrAHVmHyDQ= golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5HA= golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= @@ -1426,10 +1024,7 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220513210516-0976fa681c29/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1504,7 +1099,6 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1521,17 +1115,11 @@ golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= @@ -1540,7 +1128,6 @@ golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9sn golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= -golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1553,8 +1140,6 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= @@ -1562,8 +1147,6 @@ golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1624,20 +1207,16 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA= golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= -golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -gonum.org/v1/gonum v0.12.0 h1:xKuo6hzt+gMav00meVPUlXwSdoEJP46BR+wdxQEFK2o= -gonum.org/v1/gonum v0.12.0/go.mod h1:73TDxJfAAHeA8Mk9mf8NlIppyhQNo5GLTcYeqgo2lvY= +gonum.org/v1/gonum v0.15.0 h1:2lYxjRbTYyxkJxlhC+LvJIx3SsANPdRybu1tGj9/OrQ= +gonum.org/v1/gonum v0.15.0/go.mod h1:xzZVBJBtS+Mz4q0Yl2LJTk+OxOg4jiXZ7qBoM0uISGo= google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y= @@ -1678,24 +1257,8 @@ google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/S google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8= google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs= google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= -google.golang.org/api v0.77.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw= -google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg= google.golang.org/api v0.81.0/go.mod h1:FA6Mb/bZxj706H2j+j2d6mHEEaHBmbbWnkfvmorOCko= -google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o= -google.golang.org/api v0.85.0/go.mod h1:AqZf8Ep9uZ2pyTvgL+x0D3Zt0eoT9b5E8fmzfu6FO2g= -google.golang.org/api v0.90.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= -google.golang.org/api v0.93.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= -google.golang.org/api v0.95.0/go.mod h1:eADj+UBuxkh5zlrSntJghuNeg8HwQ1w5lTKkuqaETEI= -google.golang.org/api v0.96.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= -google.golang.org/api v0.97.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= -google.golang.org/api v0.98.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= -google.golang.org/api v0.99.0/go.mod h1:1YOf74vkVndF7pG6hIHuINsM7eWwpVTAfNMNiL91A08= -google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70= -google.golang.org/api v0.102.0/go.mod h1:3VFl6/fzoA+qNuS1N1/VfXY4LjoXN/wzeIp7TweWwGo= -google.golang.org/api v0.103.0/go.mod h1:hGtW6nK1AC+d9si/UBhw8Xli+QMOf6xyNAyJw4qU9w0= -google.golang.org/api v0.108.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= -google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1752,7 +1315,6 @@ google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= @@ -1778,59 +1340,18 @@ google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ6 google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220208230804-65c12eb4c068/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= -google.golang.org/genproto v0.0.0-20220329172620-7be39ac1afc7/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220628213854-d9e0b6570c03/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220722212130-b98a9ff5e252/go.mod h1:GkXuJDJ6aQ7lnJcRF+SJVgFdQhypqgl3LB1C9vabdRE= -google.golang.org/genproto v0.0.0-20220801145646-83ce21fca29f/go.mod h1:iHe1svFLAZg9VWz891+QbRMwUv9O/1Ww+/mngYeThbc= -google.golang.org/genproto v0.0.0-20220815135757-37a418bb8959/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220817144833-d7fd3f11b9b1/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220822174746-9e6da59bd2fc/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220829144015-23454907ede3/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220829175752-36a9c930ecbf/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220913154956-18f8339a66a5/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220914142337-ca0e39ece12f/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220915135415-7fd63a7952de/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220916172020-2692e8806bfa/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220919141832-68c03719ef51/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220920201722-2b89144ce006/go.mod h1:ht8XFiar2npT/g4vkk7O0WYS1sHOHbdujxbEp7CJWbw= -google.golang.org/genproto v0.0.0-20220926165614-551eb538f295/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= -google.golang.org/genproto v0.0.0-20220926220553-6981cbe3cfce/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= -google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e/go.mod h1:3526vdqwhZAwq4wsRUaVG555sVgsNmIjRtO7t/JH29U= -google.golang.org/genproto v0.0.0-20221014173430-6e2ab493f96b/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= -google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= -google.golang.org/genproto v0.0.0-20221024153911-1573dae28c9c/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= -google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= -google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c/go.mod h1:CGI5F/G+E5bKwmfYo09AXuVN4dD894kIKUFmVbP2/Fo= -google.golang.org/genproto v0.0.0-20221114212237-e4508ebdbee1/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221117204609-8f9c96812029/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221202195650-67e5cbc046fd/go.mod h1:cTsE614GARnxrLsqKREzmNYJACSWWpAWdNMwnD7c2BE= -google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230124163310-31e0e69b6fc2/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230216225411-c8e22ba71e44/go.mod h1:8B0gmkoRebU8ukX6HP+4wrVQUY1+6PkQ44BSyIlflHA= google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de h1:cZGRis4/ot9uVm639a+rHCUaG0JJHEsdyzSQTMX+suY= google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= @@ -1862,18 +1383,10 @@ google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnD google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= -google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= @@ -1891,7 +1404,6 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= diff --git a/metric_source/local/eval.go b/metric_source/local/eval.go index 3d36c9e2a..56fbb2984 100644 --- a/metric_source/local/eval.go +++ b/metric_source/local/eval.go @@ -3,9 +3,9 @@ package local import ( "context" "errors" - "fmt" "runtime/debug" + "github.com/ansel1/merry" "github.com/go-graphite/carbonapi/expr" "github.com/go-graphite/carbonapi/expr/helper" "github.com/go-graphite/carbonapi/expr/types" @@ -14,75 +14,128 @@ import ( metricSource "github.com/moira-alert/moira/metric_source" ) -type evalCtx struct { - from int64 - until int64 +type evaluator struct { + database moira.Database + metrics []string } -func (ctx *evalCtx) fetchAndEval(database moira.Database, target string, result *FetchResult) error { - exp, err := ctx.parse(target) - if err != nil { - return err - } +func (eval *evaluator) fetchAndEval(target string, from, until int64, result *FetchResult) (err error) { + defer func() { + if r := recover(); r != nil { + err = ErrEvaluateTargetFailedWithPanic{ + target: target, + recoverMessage: r, + stackRecord: debug.Stack(), + } + } + }() - fetchedMetrics, err := ctx.getMetricsData(database, exp) + exp, err := eval.parse(target) if err != nil { return err } - commonStep := fetchedMetrics.calculateCommonStep() - ctx.scaleToCommonStep(commonStep, fetchedMetrics) + values := make(map[parser.MetricRequest][]*types.MetricData) - rewritten, newTargets, err := ctx.rewriteExpr(exp, fetchedMetrics) + fetchedMetrics, err := expr.FetchAndEvalExp(context.Background(), eval, exp, from, until, values) if err != nil { - return err + return merry.Unwrap(err) } - if rewritten { - for _, newTarget := range newTargets { - err = ctx.fetchAndEvalNoRewrite(database, newTarget, result) - if err != nil { - return err - } + eval.writeResult(exp, fetchedMetrics, result) + + return nil +} + +// It returns a map of only the data requested in the current invocation, scaled to a common step. +func (eval *evaluator) Fetch( + ctx context.Context, + exprs []parser.Expr, + from, until int64, + values map[parser.MetricRequest][]*types.MetricData, +) (map[parser.MetricRequest][]*types.MetricData, error) { + fetch := NewFetchCtx(0, 0) + + for _, exp := range exprs { + ms := exp.Metrics(from, until) + if err := fetch.getMetricsData(eval.database, ms); err != nil { + return nil, err } - return nil } - metricsData, err := ctx.eval(target, exp, fetchedMetrics) - if err != nil { - return err - } + fetch.scaleToCommonStep() - ctx.writeResult(exp, fetchedMetrics, metricsData, result) + eval.metrics = append(eval.metrics, fetch.fetchedMetrics.metrics...) - return nil + return fetch.fetchedMetrics.metricsMap, nil } -func (ctx *evalCtx) fetchAndEvalNoRewrite(database moira.Database, target string, result *FetchResult) error { - exp, err := ctx.parse(target) +// Eval uses the raw data within the values map being passed into it to in order to evaluate the input expression. +func (eval *evaluator) Eval( + ctx context.Context, + exp parser.Expr, + from, until int64, + values map[parser.MetricRequest][]*types.MetricData, +) (results []*types.MetricData, err error) { + rewritten, newTargets, err := expr.RewriteExpr(ctx, eval, exp, from, until, values) if err != nil { - return err + return nil, err } - fetchedMetrics, err := ctx.getMetricsData(database, exp) - if err != nil { - return err + if rewritten { + for _, target := range newTargets { + exp, _, err = parser.ParseExpr(target) + if err != nil { + return nil, err + } + + targetValues, err := eval.Fetch(ctx, []parser.Expr{exp}, from, until, values) + if err != nil { + return nil, err + } + + result, err := eval.Eval(ctx, exp, from, until, targetValues) + if err != nil { + return nil, err + } + + results = append(results, result...) + } + + return results, nil } - commonStep := fetchedMetrics.calculateCommonStep() - ctx.scaleToCommonStep(commonStep, fetchedMetrics) + results, err = expr.EvalExpr(ctx, eval, exp, from, until, values) - metricsData, err := ctx.eval(target, exp, fetchedMetrics) if err != nil { - return err + if errors.Is(err, parser.ErrMissingTimeseries) { + err = nil + } else if isErrUnknownFunction(err) { + err = ErrorUnknownFunction(err) + } else { + err = ErrEvalExpr{ + target: exp.StringValue(), + internalError: err, + } + } } - ctx.writeResult(exp, fetchedMetrics, metricsData, result) + return results, err +} + +func (eval *evaluator) writeResult(exp parser.Expr, metricsData []*types.MetricData, result *FetchResult) { + for _, metricData := range metricsData { + md := newMetricDataFromGraphit(metricData, len(metricsData) > 0) + result.MetricsData = append(result.MetricsData, md) + } - return nil + result.Metrics = append(result.Metrics, eval.metrics...) + for _, mr := range exp.Metrics(0, 0) { + result.Patterns = append(result.Patterns, mr.Metric) + } } -func (ctx *evalCtx) parse(target string) (parser.Expr, error) { +func (eval *evaluator) parse(target string) (parser.Expr, error) { parsedExpr, _, err := parser.ParseExpr(target) if err != nil { return nil, ErrParseExpr{ @@ -93,12 +146,24 @@ func (ctx *evalCtx) parse(target string) (parser.Expr, error) { return parsedExpr, nil } -func (ctx *evalCtx) getMetricsData(database moira.Database, parsedExpr parser.Expr) (*fetchedMetrics, error) { - metricRequests := parsedExpr.Metrics() +type fetchCtx struct { + from int64 + until int64 + fetchedMetrics *fetchedMetrics +} - metrics := make([]string, 0) - metricsMap := make(map[parser.MetricRequest][]*types.MetricData) +func NewFetchCtx(from, until int64) *fetchCtx { + return &fetchCtx{ + from, + until, + &fetchedMetrics{ + metricsMap: make(map[parser.MetricRequest][]*types.MetricData), + metrics: make([]string, 0), + }, + } +} +func (ctx *fetchCtx) getMetricsData(database moira.Database, metricRequests []parser.MetricRequest) error { fetchData := fetchData{database} for _, mr := range metricRequests { @@ -107,92 +172,37 @@ func (ctx *evalCtx) getMetricsData(database moira.Database, parsedExpr parser.Ex metricNames, err := fetchData.fetchMetricNames(mr.Metric) if err != nil { - return nil, err + return err } timer := NewTimerRoundingTimestamps(from, until, metricNames.retention) metricsData, err := fetchData.fetchMetricValues(mr.Metric, metricNames, timer) if err != nil { - return nil, err + return err } - metricsMap[mr] = metricsData - metrics = append(metrics, metricNames.metrics...) + ctx.fetchedMetrics.metricsMap[mr] = metricsData + ctx.fetchedMetrics.metrics = append(ctx.fetchedMetrics.metrics, metricNames.metrics...) } - return &fetchedMetrics{metricsMap, metrics}, nil + return nil } -func (ctx *evalCtx) scaleToCommonStep(retention int64, fetchedMetrics *fetchedMetrics) { - from, until := RoundTimestamps(ctx.from, ctx.until, retention) - ctx.from, ctx.until = from, until +func (ctx *fetchCtx) scaleToCommonStep() { + retention := ctx.fetchedMetrics.calculateCommonStep() + + // from, until := RoundTimestamps(ctx.from, ctx.until, retention) metricMap := make(map[parser.MetricRequest][]*types.MetricData) - for metricRequest, metricData := range fetchedMetrics.metricsMap { - metricRequest.From += from - metricRequest.Until += until + for metricRequest, metricData := range ctx.fetchedMetrics.metricsMap { + metricRequest.From += ctx.from + metricRequest.Until += ctx.until metricData = helper.ScaleToCommonStep(metricData, retention) metricMap[metricRequest] = metricData } - fetchedMetrics.metricsMap = metricMap -} - -func (ctx *evalCtx) rewriteExpr(parsedExpr parser.Expr, metrics *fetchedMetrics) (bool, []string, error) { - rewritten, newTargets, err := expr.RewriteExpr( - context.Background(), - parsedExpr, - ctx.from, - ctx.until, - metrics.metricsMap, - ) - - if err != nil && !errors.Is(err, parser.ErrMissingTimeseries) { - return false, nil, fmt.Errorf("failed RewriteExpr: %s", err.Error()) - } - return rewritten, newTargets, nil -} - -func (ctx *evalCtx) eval(target string, parsedExpr parser.Expr, metrics *fetchedMetrics) (result []*types.MetricData, err error) { - defer func() { - if r := recover(); r != nil { - result = nil - err = ErrEvaluateTargetFailedWithPanic{ - target: target, - recoverMessage: r, - stackRecord: debug.Stack(), - } - } - }() - - result, err = expr.EvalExpr(context.Background(), parsedExpr, ctx.from, ctx.until, metrics.metricsMap) - if err != nil { - if errors.Is(err, parser.ErrMissingTimeseries) { - err = nil - } else if isErrUnknownFunction(err) { - err = ErrorUnknownFunction(err) - } else { - err = ErrEvalExpr{ - target: target, - internalError: err, - } - } - } - - return result, err -} - -func (ctx *evalCtx) writeResult(exp parser.Expr, metrics *fetchedMetrics, metricsData []*types.MetricData, result *FetchResult) { - for _, metricData := range metricsData { - md := newMetricDataFromGraphit(metricData, metrics.hasWildcard()) - result.MetricsData = append(result.MetricsData, md) - } - - result.Metrics = append(result.Metrics, metrics.metrics...) - for _, mr := range exp.Metrics() { - result.Patterns = append(result.Patterns, mr.Metric) - } + ctx.fetchedMetrics.metricsMap = metricMap } func newMetricDataFromGraphit(md *types.MetricData, wildcard bool) metricSource.MetricData { @@ -211,10 +221,6 @@ type fetchedMetrics struct { metrics []string } -func (m *fetchedMetrics) hasWildcard() bool { - return len(m.metrics) == 0 -} - func (m *fetchedMetrics) calculateCommonStep() int64 { commonStep := int64(1) for _, metricsData := range m.metricsMap { diff --git a/metric_source/local/local.go b/metric_source/local/local.go index 6183200bf..ac5b45c7e 100644 --- a/metric_source/local/local.go +++ b/metric_source/local/local.go @@ -45,9 +45,9 @@ func (local *Local) Fetch(target string, from int64, until int64, allowRealTimeA from = moira.MaxInt64(from, until-local.database.GetMetricsTTLSeconds()) result := CreateEmptyFetchResult() - ctx := evalCtx{from, until} + eval := evaluator{local.database, make([]string, 0)} - err := ctx.fetchAndEval(local.database, target, result) + err := eval.fetchAndEval(target, from, until, result) if err != nil { return nil, err } diff --git a/metric_source/local/local_test.go b/metric_source/local/local_test.go index 6f0feb8a9..02affd94b 100644 --- a/metric_source/local/local_test.go +++ b/metric_source/local/local_test.go @@ -5,7 +5,6 @@ import ( "math" "strings" "testing" - "time" "github.com/go-graphite/carbonapi/expr/functions" "github.com/go-graphite/carbonapi/expr/types" @@ -88,14 +87,16 @@ func TestLocalSourceFetchErrors(t *testing.T) { }) Convey("Panic while evaluate target", t, func() { - database.EXPECT().GetPatternMetrics(pattern1).Return([]string{metric1}, nil) - database.EXPECT().GetMetricRetention(metric1).Return(retention, nil) + database.EXPECT().GetPatternMetrics(pattern1).Return([]string{metric1}, nil).Times(2) + database.EXPECT().GetMetricRetention(metric1).Return(retention, nil).Times(2) database.EXPECT().GetMetricsValues([]string{metric1}, retentionFrom, retentionUntil-1).Return(dataList, nil) + database.EXPECT().GetMetricsValues([]string{metric1}, int64(30), retentionUntil-1).Return(dataList, nil) database.EXPECT().GetMetricsTTLSeconds().Return(metricsTTL) result, err := localSource.Fetch("movingAverage(super.puper.pattern, -1)", from, until, true) expectedErrSubstring := strings.Split(ErrEvaluateTargetFailedWithPanic{target: "movingAverage(super.puper.pattern, -1)"}.Error(), ":")[0] + So(err, ShouldNotBeNil) So(err.Error(), ShouldStartWith, expectedErrSubstring) So(result, ShouldBeNil) }) @@ -108,7 +109,7 @@ func TestLocalSourceFetchNoMetrics(t *testing.T) { defer mockCtrl.Finish() pattern := pattern1 - pattern2 := pattern2 + // pattern2 := pattern2 var metricsTTL int64 = 3600 @@ -116,12 +117,12 @@ func TestLocalSourceFetchNoMetrics(t *testing.T) { database.EXPECT().GetPatternMetrics(pattern).Return([]string{}, nil) database.EXPECT().GetMetricsTTLSeconds().Return(metricsTTL) - result, err := localSource.Fetch("aliasByNode(super.puper.pattern, 2)", 17, 17, false) + result, err := localSource.Fetch("super.puper.pattern", 17, 17, false) So(err, ShouldBeNil) So(result, shouldEqualIfNaNsEqual, &FetchResult{ MetricsData: []metricSource.MetricData{{ - Name: "pattern", + Name: "super.puper.pattern", StartTime: 60, StopTime: 60, StepTime: 60, @@ -153,46 +154,46 @@ func TestLocalSourceFetchNoMetrics(t *testing.T) { }) }) - Convey("Single pattern, from 7 until 57", t, func() { - database.EXPECT().GetPatternMetrics(pattern).Return([]string{}, nil) - database.EXPECT().GetPatternMetrics(pattern2).Return([]string{}, nil) - database.EXPECT().GetMetricsTTLSeconds().Return(metricsTTL) - - result, err := localSource.Fetch("aliasByNode(super.puper.pattern, 2)", 7, 57, true) - - So(err, ShouldBeNil) - So(result, shouldEqualIfNaNsEqual, &FetchResult{ - MetricsData: []metricSource.MetricData{{ - Name: "pattern", - StartTime: 60, - StopTime: 60, - StepTime: 60, Values: []float64{}, - Wildcard: true, - }}, - Metrics: []string{}, - Patterns: []string{pattern}, - }) - }) - - Convey("Two patterns, from 17 until 67", t, func() { - database.EXPECT().GetPatternMetrics(pattern).Return([]string{}, nil) - database.EXPECT().GetMetricsTTLSeconds().Return(metricsTTL) - - result, err := localSource.Fetch("alias(sum(super.puper.pattern, super.duper.pattern), 'pattern')", 17, 67, true) - - So(err, ShouldBeNil) - So(result, shouldEqualIfNaNsEqual, &FetchResult{ - MetricsData: []metricSource.MetricData{{ - Name: "pattern", - StartTime: 60, - StopTime: 120, - StepTime: 60, Values: []float64{math.NaN()}, - Wildcard: true, - }}, - Metrics: []string{}, - Patterns: []string{pattern, pattern2}, - }) - }) + // Convey("Single pattern, from 7 until 57", t, func() { + // database.EXPECT().GetPatternMetrics(pattern).Return([]string{}, nil) + // database.EXPECT().GetPatternMetrics(pattern2).Return([]string{}, nil) + // database.EXPECT().GetMetricsTTLSeconds().Return(metricsTTL) + + // result, err := localSource.Fetch("aliasByNode(super.puper.pattern, 2)", 7, 57, true) + + // So(err, ShouldBeNil) + // So(result, shouldEqualIfNaNsEqual, &FetchResult{ + // MetricsData: []metricSource.MetricData{{ + // Name: "pattern", + // StartTime: 60, + // StopTime: 60, + // StepTime: 60, Values: []float64{}, + // Wildcard: true, + // }}, + // Metrics: []string{}, + // Patterns: []string{pattern}, + // }) + // }) + + // Convey("Two patterns, from 17 until 67", t, func() { + // database.EXPECT().GetPatternMetrics(pattern).Return([]string{}, nil) + // database.EXPECT().GetMetricsTTLSeconds().Return(metricsTTL) + + // result, err := localSource.Fetch("alias(sum(super.puper.pattern, super.duper.pattern), 'pattern')", 17, 67, true) + + // So(err, ShouldBeNil) + // So(result, shouldEqualIfNaNsEqual, &FetchResult{ + // MetricsData: []metricSource.MetricData{{ + // Name: "pattern", + // StartTime: 60, + // StopTime: 120, + // StepTime: 60, Values: []float64{math.NaN()}, + // Wildcard: true, + // }}, + // Metrics: []string{}, + // Patterns: []string{pattern, pattern2}, + // }) + // }) } func TestLocalSourceFetchMultipleMetrics(t *testing.T) { @@ -494,49 +495,49 @@ func TestLocalMetricsTTL(t *testing.T) { }) } -func TestLocal_evalExpr(t *testing.T) { - Convey("When everything is correct, we don't return any error", t, func() { - ctx := evalCtx{from: time.Now().Add(-1 * time.Hour).Unix(), until: time.Now().Unix()} - target := `seriesByTag('name=k8s.dev-cl1.kube_pod_status_ready', 'condition!=true', 'namespace=default', 'pod=~*')` - - expression, err := ctx.parse(target) - So(err, ShouldBeNil) - res, err := ctx.eval("target", expression, &fetchedMetrics{metricsMap: nil}) - So(err, ShouldBeNil) - So(res, ShouldBeNil) - }) - - Convey("When get panic, it should return error", t, func() { - ctx := evalCtx{from: 0, until: 0} - - expression, _ := ctx.parse(`;fg`) - res, err := ctx.eval("target", expression, &fetchedMetrics{metricsMap: nil}) - So(err.Error(), ShouldContainSubstring, "panic while evaluate target target: message: 'runtime error: invalid memory address or nil pointer dereference") - So(res, ShouldBeNil) - }) - - Convey("When no metrics, should not return error", t, func() { - ctx := evalCtx{from: time.Now().Add(-1 * time.Hour).Unix(), until: time.Now().Unix()} - target := `alias( divideSeries( alias( sumSeries( exclude( groupByNode( OFD.Production.{ofd-api,ofd-front}.*.fns-service-client.v120.*.GetCashboxRegistrationInformationAsync.ResponseCode.*.Meter.Rate-15-min-Requests-per-s, 9, "sum" ), "Ok" ) ), "bad" ), alias( sumSeries( OFD.Production.{ofd-api,ofd-front}.*.fns-service-client.v120.*.GetCashboxRegistrationInformationAsync.ResponseCode.*.Meter.Rate-15-min-Requests-per-s ), "total" ) ), "Result" )` - - expression, err := ctx.parse(target) - So(err, ShouldBeNil) - res, err := ctx.eval("target", expression, &fetchedMetrics{metricsMap: make(map[parser.MetricRequest][]*types.MetricData)}) - So(err, ShouldBeNil) - So(res, ShouldBeEmpty) - }) - - Convey("When got unknown func, should return error", t, func() { - ctx := evalCtx{from: time.Now().Add(-1 * time.Hour).Unix(), until: time.Now().Unix()} - target := `vf('name=k8s.dev-cl1.kube_pod_status_ready', 'condition!=true', 'namespace=default', 'pod=~*')` - - expression, _ := ctx.parse(target) - res, err := ctx.eval("target", expression, &fetchedMetrics{metricsMap: nil}) - So(err, ShouldBeError) - So(err.Error(), ShouldResemble, `Unknown graphite function: "vf"`) - So(res, ShouldBeNil) - }) -} +// func TestLocal_evalExpr(t *testing.T) { +// Convey("When everything is correct, we don't return any error", t, func() { +// ctx := fetchCtx{from: time.Now().Add(-1 * time.Hour).Unix(), until: time.Now().Unix()} +// target := `seriesByTag('name=k8s.dev-cl1.kube_pod_status_ready', 'condition!=true', 'namespace=default', 'pod=~*')` + +// expression, err := ctx.parse(target) +// So(err, ShouldBeNil) +// res, err := ctx.eval("target", expression, &fetchedMetrics{metricsMap: nil}) +// So(err, ShouldBeNil) +// So(res, ShouldBeNil) +// }) + +// Convey("When get panic, it should return error", t, func() { +// ctx := fetchCtx{from: 0, until: 0} + +// expression, _ := ctx.parse(`;fg`) +// res, err := ctx.eval("target", expression, &fetchedMetrics{metricsMap: nil}) +// So(err.Error(), ShouldContainSubstring, "panic while evaluate target target: message: 'runtime error: invalid memory address or nil pointer dereference") +// So(res, ShouldBeNil) +// }) + +// Convey("When no metrics, should not return error", t, func() { +// ctx := fetchCtx{from: time.Now().Add(-1 * time.Hour).Unix(), until: time.Now().Unix()} +// target := `alias( divideSeries( alias( sumSeries( exclude( groupByNode( OFD.Production.{ofd-api,ofd-front}.*.fns-service-client.v120.*.GetCashboxRegistrationInformationAsync.ResponseCode.*.Meter.Rate-15-min-Requests-per-s, 9, "sum" ), "Ok" ) ), "bad" ), alias( sumSeries( OFD.Production.{ofd-api,ofd-front}.*.fns-service-client.v120.*.GetCashboxRegistrationInformationAsync.ResponseCode.*.Meter.Rate-15-min-Requests-per-s ), "total" ) ), "Result" )` + +// expression, err := ctx.parse(target) +// So(err, ShouldBeNil) +// res, err := ctx.eval("target", expression, &fetchedMetrics{metricsMap: make(map[parser.MetricRequest][]*types.MetricData)}) +// So(err, ShouldBeNil) +// So(res, ShouldBeEmpty) +// }) + +// Convey("When got unknown func, should return error", t, func() { +// ctx := fetchCtx{from: time.Now().Add(-1 * time.Hour).Unix(), until: time.Now().Unix()} +// target := `vf('name=k8s.dev-cl1.kube_pod_status_ready', 'condition!=true', 'namespace=default', 'pod=~*')` + +// expression, _ := ctx.parse(target) +// res, err := ctx.eval("target", expression, &fetchedMetrics{metricsMap: nil}) +// So(err, ShouldBeError) +// So(err.Error(), ShouldResemble, `Unknown graphite function: "vf"`) +// So(res, ShouldBeNil) +// }) +// } func shouldEqualIfNaNsEqual(actual interface{}, expected ...interface{}) string { allowUnexportedOption := cmp.AllowUnexported(types.MetricData{}) diff --git a/metric_source/local/timer.go b/metric_source/local/timer.go index 224977bc7..9b557f421 100644 --- a/metric_source/local/timer.go +++ b/metric_source/local/timer.go @@ -9,7 +9,21 @@ type Timer struct { // Rounds start and stop time in a specific manner requered by carbonapi. func RoundTimestamps(startTime, stopTime, retention int64) (roundedStart, roundedStop int64) { - return ceilToMultiplier(startTime, retention), floorToMultiplier(stopTime, retention) + retention + // var until int64 + // if stopTime%retention == 0 { + // until = stopTime + // } else { + until := floorToMultiplier(stopTime, retention) + retention + // } + + // var from int64 + // if startTime%retention == 0 { + // from = startTime + // } else { + from := ceilToMultiplier(startTime, retention) + // } + + return from, until } // Creates new timer rounding start and stop time in a specific manner requered by carbonapi. From 79ca38a364413d903cd8e53de5c235bfbf6ba970 Mon Sep 17 00:00:00 2001 From: Tetrergeru Date: Mon, 12 Aug 2024 16:24:17 +0200 Subject: [PATCH 02/19] All old tests working --- metric_source/local/eval.go | 10 ++-- metric_source/local/local_test.go | 96 ++++++++++++++++--------------- metric_source/metric_data.go | 1 + 3 files changed, 55 insertions(+), 52 deletions(-) diff --git a/metric_source/local/eval.go b/metric_source/local/eval.go index 56fbb2984..1b08d9eba 100644 --- a/metric_source/local/eval.go +++ b/metric_source/local/eval.go @@ -124,15 +124,15 @@ func (eval *evaluator) Eval( } func (eval *evaluator) writeResult(exp parser.Expr, metricsData []*types.MetricData, result *FetchResult) { - for _, metricData := range metricsData { - md := newMetricDataFromGraphit(metricData, len(metricsData) > 0) - result.MetricsData = append(result.MetricsData, md) - } - result.Metrics = append(result.Metrics, eval.metrics...) for _, mr := range exp.Metrics(0, 0) { result.Patterns = append(result.Patterns, mr.Metric) } + + for _, metricData := range metricsData { + md := newMetricDataFromGraphit(metricData, len(result.Metrics) != len(result.Patterns)) + result.MetricsData = append(result.MetricsData, md) + } } func (eval *evaluator) parse(target string) (parser.Expr, error) { diff --git a/metric_source/local/local_test.go b/metric_source/local/local_test.go index 02affd94b..4efbbb28f 100644 --- a/metric_source/local/local_test.go +++ b/metric_source/local/local_test.go @@ -87,6 +87,7 @@ func TestLocalSourceFetchErrors(t *testing.T) { }) Convey("Panic while evaluate target", t, func() { + // TODO(Tetrergeru) It mustn't require two database requests database.EXPECT().GetPatternMetrics(pattern1).Return([]string{metric1}, nil).Times(2) database.EXPECT().GetMetricRetention(metric1).Return(retention, nil).Times(2) database.EXPECT().GetMetricsValues([]string{metric1}, retentionFrom, retentionUntil-1).Return(dataList, nil) @@ -109,7 +110,6 @@ func TestLocalSourceFetchNoMetrics(t *testing.T) { defer mockCtrl.Finish() pattern := pattern1 - // pattern2 := pattern2 var metricsTTL int64 = 3600 @@ -154,46 +154,46 @@ func TestLocalSourceFetchNoMetrics(t *testing.T) { }) }) - // Convey("Single pattern, from 7 until 57", t, func() { - // database.EXPECT().GetPatternMetrics(pattern).Return([]string{}, nil) - // database.EXPECT().GetPatternMetrics(pattern2).Return([]string{}, nil) - // database.EXPECT().GetMetricsTTLSeconds().Return(metricsTTL) - - // result, err := localSource.Fetch("aliasByNode(super.puper.pattern, 2)", 7, 57, true) - - // So(err, ShouldBeNil) - // So(result, shouldEqualIfNaNsEqual, &FetchResult{ - // MetricsData: []metricSource.MetricData{{ - // Name: "pattern", - // StartTime: 60, - // StopTime: 60, - // StepTime: 60, Values: []float64{}, - // Wildcard: true, - // }}, - // Metrics: []string{}, - // Patterns: []string{pattern}, - // }) - // }) - - // Convey("Two patterns, from 17 until 67", t, func() { - // database.EXPECT().GetPatternMetrics(pattern).Return([]string{}, nil) - // database.EXPECT().GetMetricsTTLSeconds().Return(metricsTTL) - - // result, err := localSource.Fetch("alias(sum(super.puper.pattern, super.duper.pattern), 'pattern')", 17, 67, true) - - // So(err, ShouldBeNil) - // So(result, shouldEqualIfNaNsEqual, &FetchResult{ - // MetricsData: []metricSource.MetricData{{ - // Name: "pattern", - // StartTime: 60, - // StopTime: 120, - // StepTime: 60, Values: []float64{math.NaN()}, - // Wildcard: true, - // }}, - // Metrics: []string{}, - // Patterns: []string{pattern, pattern2}, - // }) - // }) + Convey("Single pattern, from 7 until 57", t, func() { + database.EXPECT().GetPatternMetrics(pattern).Return([]string{}, nil) + database.EXPECT().GetMetricsTTLSeconds().Return(metricsTTL) + + result, err := localSource.Fetch("aliasByNode(super.puper.pattern, 2)", 7, 57, true) + + So(err, ShouldBeNil) + So(result, shouldEqualIfNaNsEqual, &FetchResult{ + MetricsData: []metricSource.MetricData{{ + Name: "pattern", + StartTime: 60, + StopTime: 60, + StepTime: 60, Values: []float64{}, + Wildcard: true, + }}, + Metrics: []string{}, + Patterns: []string{pattern}, + }) + }) + + Convey("Two patterns, from 17 until 67", t, func() { + database.EXPECT().GetPatternMetrics(pattern).Return([]string{}, nil) + database.EXPECT().GetPatternMetrics(pattern2).Return([]string{}, nil) + database.EXPECT().GetMetricsTTLSeconds().Return(metricsTTL) + + result, err := localSource.Fetch("alias(sum(super.puper.pattern, super.duper.pattern), 'pattern')", 17, 67, true) + + So(err, ShouldBeNil) + So(result, shouldEqualIfNaNsEqual, &FetchResult{ + MetricsData: []metricSource.MetricData{{ + Name: "pattern", + StartTime: 60, + StopTime: 120, + StepTime: 60, Values: []float64{math.NaN()}, + Wildcard: true, + }}, + Metrics: []string{}, + Patterns: []string{pattern, pattern2}, + }) + }) } func TestLocalSourceFetchMultipleMetrics(t *testing.T) { @@ -255,6 +255,7 @@ func TestLocalSourceFetchMultipleMetrics(t *testing.T) { StopTime: retentionUntil, StepTime: retention, Values: []float64{2, 2, 2, 2, 2}, + Wildcard: true, }, }, Metrics: metrics, @@ -495,6 +496,7 @@ func TestLocalMetricsTTL(t *testing.T) { }) } +// TODO(Tetrergeru) rewrite this test // func TestLocal_evalExpr(t *testing.T) { // Convey("When everything is correct, we don't return any error", t, func() { // ctx := fetchCtx{from: time.Now().Add(-1 * time.Hour).Unix(), until: time.Now().Unix()} @@ -531,12 +533,12 @@ func TestLocalMetricsTTL(t *testing.T) { // ctx := fetchCtx{from: time.Now().Add(-1 * time.Hour).Unix(), until: time.Now().Unix()} // target := `vf('name=k8s.dev-cl1.kube_pod_status_ready', 'condition!=true', 'namespace=default', 'pod=~*')` -// expression, _ := ctx.parse(target) -// res, err := ctx.eval("target", expression, &fetchedMetrics{metricsMap: nil}) -// So(err, ShouldBeError) -// So(err.Error(), ShouldResemble, `Unknown graphite function: "vf"`) -// So(res, ShouldBeNil) -// }) +// expression, _ := ctx.parse(target) +// res, err := ctx.eval("target", expression, &fetchedMetrics{metricsMap: nil}) +// So(err, ShouldBeError) +// So(err.Error(), ShouldResemble, `Unknown graphite function: "vf"`) +// So(res, ShouldBeNil) +// }) // } func shouldEqualIfNaNsEqual(actual interface{}, expected ...interface{}) string { diff --git a/metric_source/metric_data.go b/metric_source/metric_data.go index ceca26eb6..6b48f160e 100644 --- a/metric_source/metric_data.go +++ b/metric_source/metric_data.go @@ -12,6 +12,7 @@ type MetricData struct { StopTime int64 StepTime int64 Values []float64 + // TODO(Tetrergeru) Wtf is a wildcard in this context Wildcard bool } From a3ac31de007738fc358e3f54f038e29cf17ce48b Mon Sep 17 00:00:00 2001 From: Tetrergeru Date: Wed, 14 Aug 2024 12:05:14 +0200 Subject: [PATCH 03/19] Additional tests --- metric_source/local/local_test.go | 137 ++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) diff --git a/metric_source/local/local_test.go b/metric_source/local/local_test.go index 4efbbb28f..8f5f4c9ce 100644 --- a/metric_source/local/local_test.go +++ b/metric_source/local/local_test.go @@ -264,6 +264,143 @@ func TestLocalSourceFetchMultipleMetrics(t *testing.T) { }) } +func TestLocalSourceMovingFunctions(t *testing.T) { + mockCtrl := gomock.NewController(t) + database := mock_moira_alert.NewMockDatabase(mockCtrl) + localSource := Create(database) + defer mockCtrl.Finish() + + var from int64 = 17 + var until int64 = 67 + var retentionFrom int64 = 20 + var retentionUntil int64 = 70 + var retention int64 = 10 + var metricsTTL int64 = 3600 + + Convey("Test success evaluate multiple metrics with pow function", t, func() { + metrics := []string{ + "apps.server1.process.cpu.usage", + } + + metricList := make(map[string][]*moira.MetricValue) + metricList["apps.server1.process.cpu.usage"] = []*moira.MetricValue{ + {RetentionTimestamp: 20, Timestamp: 23, Value: 0.5}, + {RetentionTimestamp: 30, Timestamp: 33, Value: 0.4}, + {RetentionTimestamp: 40, Timestamp: 43, Value: 0.5}, + {RetentionTimestamp: 50, Timestamp: 53, Value: 0.5}, + {RetentionTimestamp: 60, Timestamp: 63, Value: 0.5}, + } + + metricList2 := make(map[string][]*moira.MetricValue) + metricList2["apps.server1.process.cpu.usage"] = []*moira.MetricValue{ + {RetentionTimestamp: 0, Timestamp: 3, Value: 0.5}, + {RetentionTimestamp: 10, Timestamp: 13, Value: 0.4}, + {RetentionTimestamp: 20, Timestamp: 23, Value: 0.5}, + {RetentionTimestamp: 30, Timestamp: 33, Value: 0.4}, + {RetentionTimestamp: 40, Timestamp: 43, Value: 0.5}, + {RetentionTimestamp: 50, Timestamp: 53, Value: 0.5}, + {RetentionTimestamp: 60, Timestamp: 63, Value: 0.5}, + } + + database.EXPECT().GetPatternMetrics("apps.*.process.cpu.usage").Return(metrics, nil) + database.EXPECT().GetMetricRetention(metrics[0]).Return(retention, nil) + // database.EXPECT().GetMetricsValues(metrics, retentionFrom, retentionUntil-1).Return(metricList, nil) + database.EXPECT().GetMetricsValues(metrics, int64(0), retentionUntil-1).Return(metricList, nil) + database.EXPECT().GetMetricsTTLSeconds().Return(metricsTTL) + + result, err := localSource.Fetch("alias(movingMin(apps.*.process.cpu.usage, '20s'), 'min')", from, until, true) + + So(err, ShouldBeNil) + So(result, shouldEqualIfNaNsEqual, &FetchResult{ + MetricsData: []metricSource.MetricData{ + { + Name: "min", + StartTime: retentionFrom, + StopTime: retentionUntil, + StepTime: retention, + Values: []float64{0.5, 0.4, 0.4, 0.5, 0.5}, + Wildcard: false, + }, + }, + Metrics: metrics, + Patterns: []string{"apps.*.process.cpu.usage"}, + }) + }) +} + +func TestLocalSourceApplyByNode(t *testing.T) { + mockCtrl := gomock.NewController(t) + database := mock_moira_alert.NewMockDatabase(mockCtrl) + localSource := Create(database) + defer mockCtrl.Finish() + + var from int64 = 17 + var until int64 = 67 + var retentionFrom int64 = 20 + var retentionUntil int64 = 70 + var retention int64 = 10 + var metricsTTL int64 = 3600 + + Convey("Test success evaluate multiple metrics with pow function", t, func() { + metrics := []string{ + "my.pattern.foo", + } + + metricList := make(map[string][]*moira.MetricValue) + metricList["my.pattern.foo"] = []*moira.MetricValue{ + {RetentionTimestamp: 20, Timestamp: 23, Value: 0.5}, + {RetentionTimestamp: 30, Timestamp: 33, Value: 0.4}, + {RetentionTimestamp: 40, Timestamp: 43, Value: 0.5}, + {RetentionTimestamp: 50, Timestamp: 53, Value: 0.5}, + {RetentionTimestamp: 60, Timestamp: 63, Value: 0.5}, + } + + metrics2 := []string{ + "your.my.pattern.foo", + } + + metricList2 := make(map[string][]*moira.MetricValue) + metricList2["your.my.pattern.foo"] = []*moira.MetricValue{ + {RetentionTimestamp: 20, Timestamp: 23, Value: 1}, + {RetentionTimestamp: 30, Timestamp: 33, Value: 2}, + {RetentionTimestamp: 40, Timestamp: 43, Value: 3}, + {RetentionTimestamp: 50, Timestamp: 53, Value: 4}, + {RetentionTimestamp: 60, Timestamp: 63, Value: 5}, + } + + database.EXPECT().GetPatternMetrics("my.pattern.*").Return(metrics, nil) + database.EXPECT().GetMetricRetention(metrics[0]).Return(retention, nil) + database.EXPECT().GetMetricsValues(metrics, retentionFrom, retentionUntil-1).Return(metricList, nil) + + database.EXPECT().GetPatternMetrics("your.my.pattern.foo").Return(metrics2, nil).AnyTimes() + database.EXPECT().GetMetricRetention(metrics2[0]).Return(retention, nil).AnyTimes() + database.EXPECT().GetMetricsValues(metrics2, retentionFrom, retentionUntil-1).Return(metricList2, nil) + + database.EXPECT().GetMetricsTTLSeconds().Return(metricsTTL) + + result, err := localSource.Fetch(`alias(applyByNode(my.pattern.*, 2, "your.%"), 'min')`, from, until, true) + + So(err, ShouldBeNil) + So(result, shouldEqualIfNaNsEqual, &FetchResult{ + MetricsData: []metricSource.MetricData{ + { + Name: "min", + StartTime: retentionFrom, + StopTime: retentionUntil, + StepTime: retention, + Values: []float64{1, 2, 3, 4, 5}, + Wildcard: true, + }, + }, + Metrics: []string{ + "my.pattern.foo", + "your.my.pattern.foo", + }, + Patterns: []string{"my.pattern.*"}, + }) + }) +} + func TestLocalSourceFetch(t *testing.T) { mockCtrl := gomock.NewController(t) database := mock_moira_alert.NewMockDatabase(mockCtrl) From 873fdd9c441622ea01b84ca1eb031973a98dfd04 Mon Sep 17 00:00:00 2001 From: Tetrergeru Date: Thu, 22 Aug 2024 10:59:47 +0200 Subject: [PATCH 04/19] Rewrite some old tests --- metric_source/local/local_test.go | 90 +++++++++++++++---------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/metric_source/local/local_test.go b/metric_source/local/local_test.go index 8f5f4c9ce..b9c92af5e 100644 --- a/metric_source/local/local_test.go +++ b/metric_source/local/local_test.go @@ -5,6 +5,7 @@ import ( "math" "strings" "testing" + "time" "github.com/go-graphite/carbonapi/expr/functions" "github.com/go-graphite/carbonapi/expr/types" @@ -87,7 +88,7 @@ func TestLocalSourceFetchErrors(t *testing.T) { }) Convey("Panic while evaluate target", t, func() { - // TODO(Tetrergeru) It mustn't require two database requests + // moving* functions with an integer second parameter require two metric fetches database.EXPECT().GetPatternMetrics(pattern1).Return([]string{metric1}, nil).Times(2) database.EXPECT().GetMetricRetention(metric1).Return(retention, nil).Times(2) database.EXPECT().GetMetricsValues([]string{metric1}, retentionFrom, retentionUntil-1).Return(dataList, nil) @@ -633,50 +634,49 @@ func TestLocalMetricsTTL(t *testing.T) { }) } -// TODO(Tetrergeru) rewrite this test -// func TestLocal_evalExpr(t *testing.T) { -// Convey("When everything is correct, we don't return any error", t, func() { -// ctx := fetchCtx{from: time.Now().Add(-1 * time.Hour).Unix(), until: time.Now().Unix()} -// target := `seriesByTag('name=k8s.dev-cl1.kube_pod_status_ready', 'condition!=true', 'namespace=default', 'pod=~*')` - -// expression, err := ctx.parse(target) -// So(err, ShouldBeNil) -// res, err := ctx.eval("target", expression, &fetchedMetrics{metricsMap: nil}) -// So(err, ShouldBeNil) -// So(res, ShouldBeNil) -// }) - -// Convey("When get panic, it should return error", t, func() { -// ctx := fetchCtx{from: 0, until: 0} - -// expression, _ := ctx.parse(`;fg`) -// res, err := ctx.eval("target", expression, &fetchedMetrics{metricsMap: nil}) -// So(err.Error(), ShouldContainSubstring, "panic while evaluate target target: message: 'runtime error: invalid memory address or nil pointer dereference") -// So(res, ShouldBeNil) -// }) - -// Convey("When no metrics, should not return error", t, func() { -// ctx := fetchCtx{from: time.Now().Add(-1 * time.Hour).Unix(), until: time.Now().Unix()} -// target := `alias( divideSeries( alias( sumSeries( exclude( groupByNode( OFD.Production.{ofd-api,ofd-front}.*.fns-service-client.v120.*.GetCashboxRegistrationInformationAsync.ResponseCode.*.Meter.Rate-15-min-Requests-per-s, 9, "sum" ), "Ok" ) ), "bad" ), alias( sumSeries( OFD.Production.{ofd-api,ofd-front}.*.fns-service-client.v120.*.GetCashboxRegistrationInformationAsync.ResponseCode.*.Meter.Rate-15-min-Requests-per-s ), "total" ) ), "Result" )` - -// expression, err := ctx.parse(target) -// So(err, ShouldBeNil) -// res, err := ctx.eval("target", expression, &fetchedMetrics{metricsMap: make(map[parser.MetricRequest][]*types.MetricData)}) -// So(err, ShouldBeNil) -// So(res, ShouldBeEmpty) -// }) - -// Convey("When got unknown func, should return error", t, func() { -// ctx := fetchCtx{from: time.Now().Add(-1 * time.Hour).Unix(), until: time.Now().Unix()} -// target := `vf('name=k8s.dev-cl1.kube_pod_status_ready', 'condition!=true', 'namespace=default', 'pod=~*')` - -// expression, _ := ctx.parse(target) -// res, err := ctx.eval("target", expression, &fetchedMetrics{metricsMap: nil}) -// So(err, ShouldBeError) -// So(err.Error(), ShouldResemble, `Unknown graphite function: "vf"`) -// So(res, ShouldBeNil) -// }) -// } +func TestLocal_evalExpr(t *testing.T) { + mockCtrl := gomock.NewController(t) + + Convey("When everything is correct, we don't return any error", t, func() { + target := `seriesByTag('name=k8s.dev-cl1.kube_pod_status_ready', 'condition!=true', 'namespace=default', 'pod=~*')` + + _, err := evalWithNoMetricsHelper(mockCtrl, target, time.Now().Add(-1*time.Hour).Unix(), time.Now().Unix()) + So(err, ShouldBeNil) + }) + + Convey("When get panic, it should return error", t, func() { + res, err := evalWithNoMetricsHelper(mockCtrl, `;fg`, 0, 0) + So(err.Error(), ShouldContainSubstring, "failed to parse target") + So(res.Metrics, ShouldBeEmpty) + }) + + Convey("When no metrics, should not return error", t, func() { + target := `alias( divideSeries( alias( sumSeries( exclude( groupByNode( OFD.Production.{ofd-api,ofd-front}.*.fns-service-client.v120.*.GetCashboxRegistrationInformationAsync.ResponseCode.*.Meter.Rate-15-min-Requests-per-s, 9, "sum" ), "Ok" ) ), "bad" ), alias( sumSeries( OFD.Production.{ofd-api,ofd-front}.*.fns-service-client.v120.*.GetCashboxRegistrationInformationAsync.ResponseCode.*.Meter.Rate-15-min-Requests-per-s ), "total" ) ), "Result" )` + + res, err := evalWithNoMetricsHelper(mockCtrl, target, time.Now().Add(-1*time.Hour).Unix(), time.Now().Unix()) + So(err, ShouldBeNil) + So(res.Metrics, ShouldBeEmpty) + }) + + Convey("When got unknown func, should return error", t, func() { + target := `vf('name=k8s.dev-cl1.kube_pod_status_ready', 'condition!=true', 'namespace=default', 'pod=~*')` + + res, err := evalWithNoMetricsHelper(mockCtrl, target, time.Now().Add(-1*time.Hour).Unix(), time.Now().Unix()) + So(err.Error(), ShouldResemble, `Unknown graphite function: "vf"`) + So(res.Metrics, ShouldBeEmpty) + }) +} + +func evalWithNoMetricsHelper(mockCtrl *gomock.Controller, target string, from, until int64) (*FetchResult, error) { + database := mock_moira_alert.NewMockDatabase(mockCtrl) + database.EXPECT().GetPatternMetrics(gomock.Any()).Return([]string{}, nil).AnyTimes() + eval := evaluator{database, make([]string, 0)} + + result := CreateEmptyFetchResult() + err := eval.fetchAndEval(target, from, until, result) + + return result, err +} func shouldEqualIfNaNsEqual(actual interface{}, expected ...interface{}) string { allowUnexportedOption := cmp.AllowUnexported(types.MetricData{}) From 8d1fbf7bbc6abffd612a12e6eb9eb11f40873c03 Mon Sep 17 00:00:00 2001 From: Tetrergeru Date: Tue, 10 Sep 2024 14:24:59 +0200 Subject: [PATCH 05/19] Fix error handling in evaluation --- metric_source/local/eval.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/metric_source/local/eval.go b/metric_source/local/eval.go index 1b08d9eba..ac3c2bf93 100644 --- a/metric_source/local/eval.go +++ b/metric_source/local/eval.go @@ -38,6 +38,7 @@ func (eval *evaluator) fetchAndEval(target string, from, until int64, result *Fe values := make(map[parser.MetricRequest][]*types.MetricData) fetchedMetrics, err := expr.FetchAndEvalExp(context.Background(), eval, exp, from, until, values) + if err != nil { return merry.Unwrap(err) } @@ -114,7 +115,7 @@ func (eval *evaluator) Eval( err = ErrorUnknownFunction(err) } else { err = ErrEvalExpr{ - target: exp.StringValue(), + target: exp.ToString(), internalError: err, } } From 6e80929aad747471785b499009a7c63fe66ad31f Mon Sep 17 00:00:00 2001 From: Tetrergeru Date: Tue, 10 Sep 2024 16:53:57 +0200 Subject: [PATCH 06/19] Fix lints --- metric_source/local/eval.go | 2 -- metric_source/metric_data.go | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/metric_source/local/eval.go b/metric_source/local/eval.go index ac3c2bf93..0e4c8d7f1 100644 --- a/metric_source/local/eval.go +++ b/metric_source/local/eval.go @@ -38,7 +38,6 @@ func (eval *evaluator) fetchAndEval(target string, from, until int64, result *Fe values := make(map[parser.MetricRequest][]*types.MetricData) fetchedMetrics, err := expr.FetchAndEvalExp(context.Background(), eval, exp, from, until, values) - if err != nil { return merry.Unwrap(err) } @@ -107,7 +106,6 @@ func (eval *evaluator) Eval( } results, err = expr.EvalExpr(ctx, eval, exp, from, until, values) - if err != nil { if errors.Is(err, parser.ErrMissingTimeseries) { err = nil diff --git a/metric_source/metric_data.go b/metric_source/metric_data.go index 6b48f160e..ce8dea377 100644 --- a/metric_source/metric_data.go +++ b/metric_source/metric_data.go @@ -13,7 +13,7 @@ type MetricData struct { StepTime int64 Values []float64 // TODO(Tetrergeru) Wtf is a wildcard in this context - Wildcard bool + Wildcard bool } // MakeMetricData creates new metrics data with given metric timeseries. From 2e1a3e6283b688e959a4bd5e836e6b375a9beb00 Mon Sep 17 00:00:00 2001 From: Tetrergeru Date: Tue, 10 Sep 2024 17:04:07 +0200 Subject: [PATCH 07/19] Move evaluation of rewritten into separate function --- metric_source/local/eval.go | 50 ++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/metric_source/local/eval.go b/metric_source/local/eval.go index 0e4c8d7f1..03e5f8af7 100644 --- a/metric_source/local/eval.go +++ b/metric_source/local/eval.go @@ -83,26 +83,7 @@ func (eval *evaluator) Eval( } if rewritten { - for _, target := range newTargets { - exp, _, err = parser.ParseExpr(target) - if err != nil { - return nil, err - } - - targetValues, err := eval.Fetch(ctx, []parser.Expr{exp}, from, until, values) - if err != nil { - return nil, err - } - - result, err := eval.Eval(ctx, exp, from, until, targetValues) - if err != nil { - return nil, err - } - - results = append(results, result...) - } - - return results, nil + return eval.evalRewritten(ctx, newTargets, from, until, values) } results, err = expr.EvalExpr(ctx, eval, exp, from, until, values) @@ -122,6 +103,35 @@ func (eval *evaluator) Eval( return results, err } +func (eval *evaluator) evalRewritten( + ctx context.Context, + newTargets []string, + from, until int64, + values map[parser.MetricRequest][]*types.MetricData, +) (results []*types.MetricData, err error) { + for _, target := range newTargets { + exp, _, err := parser.ParseExpr(target) + if err != nil { + return nil, err + } + + var targetValues map[parser.MetricRequest][]*types.MetricData + targetValues, err = eval.Fetch(ctx, []parser.Expr{exp}, from, until, values) + if err != nil { + return nil, err + } + + result, err := eval.Eval(ctx, exp, from, until, targetValues) + if err != nil { + return nil, err + } + + results = append(results, result...) + } + + return results, nil +} + func (eval *evaluator) writeResult(exp parser.Expr, metricsData []*types.MetricData, result *FetchResult) { result.Metrics = append(result.Metrics, eval.metrics...) for _, mr := range exp.Metrics(0, 0) { From e8642df4fd677a3e63bc17bb696e17b4a5a0f29a Mon Sep 17 00:00:00 2001 From: Tetrergeru Date: Wed, 2 Oct 2024 10:58:27 +0200 Subject: [PATCH 08/19] Fix some review --- metric_source/local/eval.go | 18 +++---- metric_source/local/fetchdata.go | 14 ++--- metric_source/local/fetchdata_test.go | 74 +++++++++++++-------------- metric_source/local/local.go | 2 +- metric_source/local/timer.go | 33 +++--------- metric_source/local/timer_test.go | 16 +++--- metric_source/metric_data.go | 3 +- 7 files changed, 71 insertions(+), 89 deletions(-) diff --git a/metric_source/local/eval.go b/metric_source/local/eval.go index 03e5f8af7..0b0235b74 100644 --- a/metric_source/local/eval.go +++ b/metric_source/local/eval.go @@ -47,14 +47,15 @@ func (eval *evaluator) fetchAndEval(target string, from, until int64, result *Fe return nil } -// It returns a map of only the data requested in the current invocation, scaled to a common step. +// Fetch is an implementation of Evaluator interface from carbonapi. +// It returns a map the metrics requested in the current invocation, scaled to a common step. func (eval *evaluator) Fetch( ctx context.Context, exprs []parser.Expr, from, until int64, values map[parser.MetricRequest][]*types.MetricData, ) (map[parser.MetricRequest][]*types.MetricData, error) { - fetch := NewFetchCtx(0, 0) + fetch := newFetchCtx(0, 0) for _, exp := range exprs { ms := exp.Metrics(from, until) @@ -70,7 +71,8 @@ func (eval *evaluator) Fetch( return fetch.fetchedMetrics.metricsMap, nil } -// Eval uses the raw data within the values map being passed into it to in order to evaluate the input expression. +// Eval is an implementation of Evaluator interface from carbonapi. +// It uses the raw data within the values map being passed into it to in order to evaluate the input expression. func (eval *evaluator) Eval( ctx context.Context, exp parser.Expr, @@ -139,7 +141,7 @@ func (eval *evaluator) writeResult(exp parser.Expr, metricsData []*types.MetricD } for _, metricData := range metricsData { - md := newMetricDataFromGraphit(metricData, len(result.Metrics) != len(result.Patterns)) + md := newMetricDataFromGraphite(metricData, len(result.Metrics) != len(result.Patterns)) result.MetricsData = append(result.MetricsData, md) } } @@ -161,7 +163,7 @@ type fetchCtx struct { fetchedMetrics *fetchedMetrics } -func NewFetchCtx(from, until int64) *fetchCtx { +func newFetchCtx(from, until int64) *fetchCtx { return &fetchCtx{ from, until, @@ -184,7 +186,7 @@ func (ctx *fetchCtx) getMetricsData(database moira.Database, metricRequests []pa return err } - timer := NewTimerRoundingTimestamps(from, until, metricNames.retention) + timer := newTimerRoundingTimestamps(from, until, metricNames.retention) metricsData, err := fetchData.fetchMetricValues(mr.Metric, metricNames, timer) if err != nil { @@ -200,8 +202,6 @@ func (ctx *fetchCtx) getMetricsData(database moira.Database, metricRequests []pa func (ctx *fetchCtx) scaleToCommonStep() { retention := ctx.fetchedMetrics.calculateCommonStep() - // from, until := RoundTimestamps(ctx.from, ctx.until, retention) - metricMap := make(map[parser.MetricRequest][]*types.MetricData) for metricRequest, metricData := range ctx.fetchedMetrics.metricsMap { metricRequest.From += ctx.from @@ -214,7 +214,7 @@ func (ctx *fetchCtx) scaleToCommonStep() { ctx.fetchedMetrics.metricsMap = metricMap } -func newMetricDataFromGraphit(md *types.MetricData, wildcard bool) metricSource.MetricData { +func newMetricDataFromGraphite(md *types.MetricData, wildcard bool) metricSource.MetricData { return metricSource.MetricData{ Name: md.Name, StartTime: md.StartTime, diff --git a/metric_source/local/fetchdata.go b/metric_source/local/fetchdata.go index e2a7a4a6d..880e46432 100644 --- a/metric_source/local/fetchdata.go +++ b/metric_source/local/fetchdata.go @@ -38,7 +38,7 @@ func (fd *fetchData) fetchMetricNames(pattern string) (*metricsWithRetention, er return &metricsWithRetention{retention, metrics}, nil } -func (fd *fetchData) fetchMetricValues(pattern string, metrics *metricsWithRetention, timer Timer) ([]*types.MetricData, error) { +func (fd *fetchData) fetchMetricValues(pattern string, metrics *metricsWithRetention, timer timer) ([]*types.MetricData, error) { if len(metrics.metrics) == 0 { return fetchDataNoMetrics(timer, pattern), nil } @@ -58,7 +58,7 @@ func (fd *fetchData) fetchMetricValues(pattern string, metrics *metricsWithReten return metricsData, nil } -func fetchDataNoMetrics(timer Timer, pattern string) []*types.MetricData { +func fetchDataNoMetrics(timer timer, pattern string) []*types.MetricData { dataList := map[string][]*moira.MetricValue{pattern: make([]*moira.MetricValue, 0)} valuesMap := unpackMetricsValues(dataList, timer) metricsData := createMetricData(pattern, timer, valuesMap[pattern]) @@ -66,7 +66,7 @@ func fetchDataNoMetrics(timer Timer, pattern string) []*types.MetricData { return []*types.MetricData{metricsData} } -func createMetricData(metric string, timer Timer, values []float64) *types.MetricData { +func createMetricData(metric string, timer timer, values []float64) *types.MetricData { fetchResponse := pb.FetchResponse{ Name: metric, StartTime: timer.startTime, @@ -77,7 +77,7 @@ func createMetricData(metric string, timer Timer, values []float64) *types.Metri return &types.MetricData{FetchResponse: fetchResponse, Tags: tags.ExtractTags(metric)} } -func unpackMetricsValues(metricsData map[string][]*moira.MetricValue, timer Timer) map[string][]float64 { +func unpackMetricsValues(metricsData map[string][]*moira.MetricValue, timer timer) map[string][]float64 { valuesMap := make(map[string][]float64, len(metricsData)) for metric, metricData := range metricsData { valuesMap[metric] = unpackMetricValues(metricData, timer) @@ -85,13 +85,13 @@ func unpackMetricsValues(metricsData map[string][]*moira.MetricValue, timer Time return valuesMap } -func unpackMetricValues(metricData []*moira.MetricValue, timer Timer) []float64 { +func unpackMetricValues(metricData []*moira.MetricValue, timer timer) []float64 { points := make(map[int]*moira.MetricValue, len(metricData)) for _, metricValue := range metricData { - points[timer.GetTimeSlot(metricValue.RetentionTimestamp)] = metricValue + points[timer.getTimeSlot(metricValue.RetentionTimestamp)] = metricValue } - numberOfTimeSlots := timer.NumberOfTimeSlots() + numberOfTimeSlots := timer.numberOfTimeSlots() values := make([]float64, 0, numberOfTimeSlots) diff --git a/metric_source/local/fetchdata_test.go b/metric_source/local/fetchdata_test.go index c55142ab3..c5b4a0aae 100644 --- a/metric_source/local/fetchdata_test.go +++ b/metric_source/local/fetchdata_test.go @@ -18,7 +18,7 @@ func BenchmarkUnpackMetricsValues(b *testing.B) { var until int64 = 1317 var retention int64 = 10 - timer := NewTimerRoundingTimestamps(from, until, retention) + timer := newTimerRoundingTimestamps(from, until, retention) metricsCount := 7300 @@ -47,7 +47,7 @@ func BenchmarkUnpackMetricValues(b *testing.B) { var until int64 = 317 var retention int64 = 10 - timer := NewTimerRoundingTimestamps(from, until, retention) + timer := newTimerRoundingTimestamps(from, until, retention) metricsValues := make([]*moira.MetricValue, 0) @@ -75,7 +75,7 @@ func TestFetchDataErrors(t *testing.T) { pattern := "super-puper-pattern" metric := "super-puper-metric" - timer := NewTimerRoundingTimestamps(17, 67, 10) + timer := newTimerRoundingTimestamps(17, 67, 10) retentionErr := fmt.Errorf("Ooops, retention error") patternErr := fmt.Errorf("Ooops, pattern error") @@ -145,7 +145,7 @@ func TestFetchData(t *testing.T) { var from int64 = 17 var until int64 = 67 var retention int64 = 10 - timer := NewTimerRoundingTimestamps(from, until, retention) + timer := newTimerRoundingTimestamps(from, until, retention) Convey("Test no metrics", t, func() { dataBase.EXPECT().GetPatternMetrics(pattern).Return([]string{}, nil) @@ -153,7 +153,7 @@ func TestFetchData(t *testing.T) { metrics, err := fetchedData.fetchMetricNames(pattern) So(err, ShouldBeNil) - timerNoMetrics := NewTimerRoundingTimestamps(from, until, metrics.retention) + timerNoMetrics := newTimerRoundingTimestamps(from, until, metrics.retention) metricValues, err := fetchedData.fetchMetricValues(pattern, metrics, timerNoMetrics) So(metricValues[0], shouldEqualIfNaNsEqual, &types.MetricData{ @@ -235,28 +235,28 @@ func TestUnpackMetricValuesNoData(t *testing.T) { metricData := map[string][]*moira.MetricValue{"metric": make([]*moira.MetricValue, 0)} Convey("From 1 until 1", t, func() { - timer := NewTimerRoundingTimestamps(1, 1, retention) + timer := newTimerRoundingTimestamps(1, 1, retention) val := unpackMetricsValues(metricData, timer) expected := []float64{} So(val["metric"], shouldEqualIfNaNsEqual, expected) }) Convey("From 0 until 0", t, func() { - timer := NewTimerRoundingTimestamps(0, 0, retention) + timer := newTimerRoundingTimestamps(0, 0, retention) val := unpackMetricsValues(metricData, timer) expected := []float64{math.NaN()} So(val["metric"], shouldEqualIfNaNsEqual, expected) }) Convey("From 0 until 10", t, func() { - timer := NewTimerRoundingTimestamps(0, 10, retention) + timer := newTimerRoundingTimestamps(0, 10, retention) val := unpackMetricsValues(metricData, timer) expected := []float64{math.NaN(), math.NaN()} So(val["metric"], shouldEqualIfNaNsEqual, expected) }) Convey("From 1 until 11", t, func() { - timer := NewTimerRoundingTimestamps(1, 11, retention) + timer := newTimerRoundingTimestamps(1, 11, retention) val := unpackMetricsValues(metricData, timer) expected := []float64{math.NaN()} So(val["metric"], shouldEqualIfNaNsEqual, expected) @@ -273,49 +273,49 @@ func TestUnpackMetricValues(t *testing.T) { }} Convey("From 1 until 1", t, func() { - timer := NewTimerRoundingTimestamps(1, 1, retention) + timer := newTimerRoundingTimestamps(1, 1, retention) val := unpackMetricsValues(metricData, timer) So(val["metric"], shouldEqualIfNaNsEqual, []float64{}) }) Convey("From 0 until 0", t, func() { - timer := NewTimerRoundingTimestamps(0, 0, retention) + timer := newTimerRoundingTimestamps(0, 0, retention) val := unpackMetricsValues(metricData, timer) So(val["metric"], shouldEqualIfNaNsEqual, []float64{100.0}) }) Convey("From 1 until 11", t, func() { - timer := NewTimerRoundingTimestamps(1, 11, retention) + timer := newTimerRoundingTimestamps(1, 11, retention) val := unpackMetricsValues(metricData, timer) So(val["metric"], shouldEqualIfNaNsEqual, []float64{200.0}) }) Convey("From 0 until 10", t, func() { - timer := NewTimerRoundingTimestamps(0, 10, retention) + timer := newTimerRoundingTimestamps(0, 10, retention) val := unpackMetricsValues(metricData, timer) So(val["metric"], shouldEqualIfNaNsEqual, []float64{100.00, 200.0}) }) Convey("From 0 until 11", t, func() { - timer := NewTimerRoundingTimestamps(0, 11, retention) + timer := newTimerRoundingTimestamps(0, 11, retention) val := unpackMetricsValues(metricData, timer) So(val["metric"], shouldEqualIfNaNsEqual, []float64{100.00, 200.00}) }) Convey("From 0 until 19", t, func() { - timer := NewTimerRoundingTimestamps(0, 19, retention) + timer := newTimerRoundingTimestamps(0, 19, retention) val := unpackMetricsValues(metricData, timer) So(val["metric"], shouldEqualIfNaNsEqual, []float64{100.00, 200.00}) }) Convey("From 1 until 30", t, func() { - timer := NewTimerRoundingTimestamps(1, 30, retention) + timer := newTimerRoundingTimestamps(1, 30, retention) val := unpackMetricsValues(metricData, timer) So(val["metric"], shouldEqualIfNaNsEqual, []float64{200.00, 300.00, math.NaN()}) @@ -330,7 +330,7 @@ func TestMultipleSeriesNoData(t *testing.T) { } Convey("From 1 until 1", t, func() { - timer := NewTimerRoundingTimestamps(1, 1, retention) + timer := newTimerRoundingTimestamps(1, 1, retention) val := unpackMetricsValues(metricData, timer) So(val["metric1"], shouldEqualIfNaNsEqual, []float64{}) @@ -338,7 +338,7 @@ func TestMultipleSeriesNoData(t *testing.T) { }) Convey("From 0 until 0", t, func() { - timer := NewTimerRoundingTimestamps(0, 0, retention) + timer := newTimerRoundingTimestamps(0, 0, retention) val := unpackMetricsValues(metricData, timer) So(val["metric1"], shouldEqualIfNaNsEqual, []float64{math.NaN()}) @@ -346,7 +346,7 @@ func TestMultipleSeriesNoData(t *testing.T) { }) Convey("From 1 until 5", t, func() { - timer := NewTimerRoundingTimestamps(1, 5, retention) + timer := newTimerRoundingTimestamps(1, 5, retention) val1 := unpackMetricsValues(metricData, timer) So(val1["metric1"], shouldEqualIfNaNsEqual, []float64{}) @@ -354,7 +354,7 @@ func TestMultipleSeriesNoData(t *testing.T) { }) Convey("From 0 until 5", t, func() { - timer := NewTimerRoundingTimestamps(0, 5, retention) + timer := newTimerRoundingTimestamps(0, 5, retention) val1 := unpackMetricsValues(metricData, timer) So(val1["metric1"], shouldEqualIfNaNsEqual, []float64{math.NaN()}) @@ -362,7 +362,7 @@ func TestMultipleSeriesNoData(t *testing.T) { }) Convey("From 5 until 30", t, func() { - timer := NewTimerRoundingTimestamps(5, 30, retention) + timer := newTimerRoundingTimestamps(5, 30, retention) val1 := unpackMetricsValues(metricData, timer) So(val1["metric1"], shouldEqualIfNaNsEqual, []float64{math.NaN(), math.NaN(), math.NaN()}) @@ -387,7 +387,7 @@ func TestMultipleSeries(t *testing.T) { } Convey("From 1 until 1", t, func() { - timer := NewTimerRoundingTimestamps(1, 1, retention) + timer := newTimerRoundingTimestamps(1, 1, retention) val := unpackMetricsValues(metricData, timer) So(val["metric1"], shouldEqualIfNaNsEqual, []float64{}) @@ -395,7 +395,7 @@ func TestMultipleSeries(t *testing.T) { }) Convey("From 0 until 0", t, func() { - timer := NewTimerRoundingTimestamps(0, 0, retention) + timer := newTimerRoundingTimestamps(0, 0, retention) val := unpackMetricsValues(metricData, timer) So(val["metric1"], shouldEqualIfNaNsEqual, []float64{100.0}) @@ -403,7 +403,7 @@ func TestMultipleSeries(t *testing.T) { }) Convey("From 1 until 5", t, func() { - timer := NewTimerRoundingTimestamps(1, 5, retention) + timer := newTimerRoundingTimestamps(1, 5, retention) val1 := unpackMetricsValues(metricData, timer) So(val1["metric1"], shouldEqualIfNaNsEqual, []float64{}) @@ -411,7 +411,7 @@ func TestMultipleSeries(t *testing.T) { }) Convey("From 0 until 5", t, func() { - timer := NewTimerRoundingTimestamps(0, 5, retention) + timer := newTimerRoundingTimestamps(0, 5, retention) val1 := unpackMetricsValues(metricData, timer) So(val1["metric1"], shouldEqualIfNaNsEqual, []float64{100.0}) @@ -419,7 +419,7 @@ func TestMultipleSeries(t *testing.T) { }) Convey("From 0 until 9", t, func() { - timer := NewTimerRoundingTimestamps(0, 9, retention) + timer := newTimerRoundingTimestamps(0, 9, retention) val1 := unpackMetricsValues(metricData, timer) So(val1["metric1"], shouldEqualIfNaNsEqual, []float64{100.00}) @@ -427,7 +427,7 @@ func TestMultipleSeries(t *testing.T) { }) Convey("From 0 until 10", t, func() { - timer := NewTimerRoundingTimestamps(0, 10, retention) + timer := newTimerRoundingTimestamps(0, 10, retention) val1 := unpackMetricsValues(metricData, timer) So(val1["metric1"], shouldEqualIfNaNsEqual, []float64{100.00, 200.00}) @@ -435,7 +435,7 @@ func TestMultipleSeries(t *testing.T) { }) Convey("From 1 until 11", t, func() { - timer := NewTimerRoundingTimestamps(1, 11, retention) + timer := newTimerRoundingTimestamps(1, 11, retention) val1 := unpackMetricsValues(metricData, timer) So(val1["metric1"], shouldEqualIfNaNsEqual, []float64{200.00}) @@ -443,7 +443,7 @@ func TestMultipleSeries(t *testing.T) { }) Convey("From 0 until 30", t, func() { - timer := NewTimerRoundingTimestamps(0, 30, retention) + timer := newTimerRoundingTimestamps(0, 30, retention) val1 := unpackMetricsValues(metricData, timer) So(val1["metric1"], shouldEqualIfNaNsEqual, []float64{100.00, 200.00, 300.00, math.NaN()}) @@ -451,7 +451,7 @@ func TestMultipleSeries(t *testing.T) { }) Convey("From 5 until 30", t, func() { - timer := NewTimerRoundingTimestamps(5, 30, retention) + timer := newTimerRoundingTimestamps(5, 30, retention) val1 := unpackMetricsValues(metricData, timer) So(val1["metric1"], shouldEqualIfNaNsEqual, []float64{200.00, 300.00, math.NaN()}) @@ -468,49 +468,49 @@ func TestShiftedSeries(t *testing.T) { }} Convey("From 1 until 1", t, func() { - timer := NewTimerRoundingTimestamps(1, 1, retention) + timer := newTimerRoundingTimestamps(1, 1, retention) val := unpackMetricsValues(metricData, timer) So(val["metric"], shouldEqualIfNaNsEqual, []float64{}) }) Convey("From 0 until 0", t, func() { - timer := NewTimerRoundingTimestamps(0, 0, retention) + timer := newTimerRoundingTimestamps(0, 0, retention) val := unpackMetricsValues(metricData, timer) So(val["metric"], shouldEqualIfNaNsEqual, []float64{100.0}) }) Convey("From 1 until 11", t, func() { - timer := NewTimerRoundingTimestamps(1, 11, retention) + timer := newTimerRoundingTimestamps(1, 11, retention) val := unpackMetricsValues(metricData, timer) So(val["metric"], shouldEqualIfNaNsEqual, []float64{200.0}) }) Convey("From 0 until 10", t, func() { - timer := NewTimerRoundingTimestamps(0, 10, retention) + timer := newTimerRoundingTimestamps(0, 10, retention) val := unpackMetricsValues(metricData, timer) So(val["metric"], shouldEqualIfNaNsEqual, []float64{100.00, 200.0}) }) Convey("From 0 until 11", t, func() { - timer := NewTimerRoundingTimestamps(0, 11, retention) + timer := newTimerRoundingTimestamps(0, 11, retention) val := unpackMetricsValues(metricData, timer) So(val["metric"], shouldEqualIfNaNsEqual, []float64{100.00, 200.00}) }) Convey("From 0 until 19", t, func() { - timer := NewTimerRoundingTimestamps(0, 19, retention) + timer := newTimerRoundingTimestamps(0, 19, retention) val := unpackMetricsValues(metricData, timer) So(val["metric"], shouldEqualIfNaNsEqual, []float64{100.00, 200.00}) }) Convey("From 1 until 30", t, func() { - timer := NewTimerRoundingTimestamps(1, 30, retention) + timer := newTimerRoundingTimestamps(1, 30, retention) val := unpackMetricsValues(metricData, timer) So(val["metric"], shouldEqualIfNaNsEqual, []float64{200.00, 300.00, math.NaN()}) diff --git a/metric_source/local/local.go b/metric_source/local/local.go index ac5b45c7e..f844f79aa 100644 --- a/metric_source/local/local.go +++ b/metric_source/local/local.go @@ -33,7 +33,7 @@ func (local *Local) IsConfigured() (bool, error) { return true, nil } -// IsConfigured always returns true. It easy to configure local source =). +// IsAvailable always returns true. It easy to configure local source =). func (local *Local) IsAvailable() (bool, error) { return true, nil } diff --git a/metric_source/local/timer.go b/metric_source/local/timer.go index 9b557f421..98f57bce4 100644 --- a/metric_source/local/timer.go +++ b/metric_source/local/timer.go @@ -1,49 +1,32 @@ package local -// Timer is responsible for managing time ranges and metrics' timeslots. -type Timer struct { +type timer struct { startTime int64 stopTime int64 stepTime int64 } -// Rounds start and stop time in a specific manner requered by carbonapi. -func RoundTimestamps(startTime, stopTime, retention int64) (roundedStart, roundedStop int64) { - // var until int64 - // if stopTime%retention == 0 { - // until = stopTime - // } else { +func roundTimestamps(startTime, stopTime, retention int64) (roundedStart, roundedStop int64) { until := floorToMultiplier(stopTime, retention) + retention - // } - - // var from int64 - // if startTime%retention == 0 { - // from = startTime - // } else { from := ceilToMultiplier(startTime, retention) - // } return from, until } -// Creates new timer rounding start and stop time in a specific manner requered by carbonapi. -// Timers should be created only with this function. -func NewTimerRoundingTimestamps(startTime int64, stopTime int64, retention int64) Timer { - startTime, stopTime = RoundTimestamps(startTime, stopTime, retention) - return Timer{ +func newTimerRoundingTimestamps(startTime int64, stopTime int64, retention int64) timer { + startTime, stopTime = roundTimestamps(startTime, stopTime, retention) + return timer{ startTime: startTime, stopTime: stopTime, stepTime: retention, } } -// Returns the number of timeslots from this timer's startTime until its stopTime with it's retention. -func (t Timer) NumberOfTimeSlots() int { - return t.GetTimeSlot(t.stopTime) +func (t timer) numberOfTimeSlots() int { + return t.getTimeSlot(t.stopTime) } -// Returns the index of given timestamp (rounded by timestamp) in this timer's time range. -func (t Timer) GetTimeSlot(timestamp int64) int { +func (t timer) getTimeSlot(timestamp int64) int { timeSlot := floorToMultiplier(timestamp-t.startTime, t.stepTime) / t.stepTime return int(timeSlot) } diff --git a/metric_source/local/timer_test.go b/metric_source/local/timer_test.go index cf25214e6..29563ca4a 100644 --- a/metric_source/local/timer_test.go +++ b/metric_source/local/timer_test.go @@ -14,26 +14,26 @@ func TestTimerNumberOfTimeSlots(t *testing.T) { Convey("Given `from` is divisible by retention", t, func() { for _, from := range []int64{0, retention} { until := from + retention*steps - timer := NewTimerRoundingTimestamps(from, until, retention) + timer := newTimerRoundingTimestamps(from, until, retention) - So(timer.NumberOfTimeSlots(), ShouldEqual, steps+1) + So(timer.numberOfTimeSlots(), ShouldEqual, steps+1) } }) Convey("Given `from` is divisible by retention", t, func() { from := int64(0) until := int64(0) - timer := NewTimerRoundingTimestamps(from, until, retention) + timer := newTimerRoundingTimestamps(from, until, retention) - So(timer.NumberOfTimeSlots(), ShouldEqual, 1) + So(timer.numberOfTimeSlots(), ShouldEqual, 1) }) Convey("Given `from` is not divisible by retention", t, func() { for from := int64(1); from < retention; from++ { until := from + retention*steps - timer := NewTimerRoundingTimestamps(from, until, retention) + timer := newTimerRoundingTimestamps(from, until, retention) - So(timer.NumberOfTimeSlots(), ShouldEqual, steps) + So(timer.numberOfTimeSlots(), ShouldEqual, steps) } }) } @@ -43,7 +43,7 @@ func TestTimerGetTimeSlot(t *testing.T) { retention := int64(10) from := int64(10) until := int64(60) - timer := NewTimerRoundingTimestamps(from, until, retention) + timer := newTimerRoundingTimestamps(from, until, retention) testCases := []struct { timestamp int64 @@ -61,7 +61,7 @@ func TestTimerGetTimeSlot(t *testing.T) { } for _, testCase := range testCases { - actual := timer.GetTimeSlot(testCase.timestamp) + actual := timer.getTimeSlot(testCase.timestamp) So(actual, ShouldEqual, testCase.timeSlot) } }) diff --git a/metric_source/metric_data.go b/metric_source/metric_data.go index ce8dea377..ceca26eb6 100644 --- a/metric_source/metric_data.go +++ b/metric_source/metric_data.go @@ -12,8 +12,7 @@ type MetricData struct { StopTime int64 StepTime int64 Values []float64 - // TODO(Tetrergeru) Wtf is a wildcard in this context - Wildcard bool + Wildcard bool } // MakeMetricData creates new metrics data with given metric timeseries. From ec1da1e3832383b24f7b8691b86efdf45ebb6e58 Mon Sep 17 00:00:00 2001 From: Tetrergeru Date: Wed, 2 Oct 2024 15:26:08 +0200 Subject: [PATCH 09/19] Add tests with database --- database/redis/database.go | 11 +- database/redis/notification.go | 17 +- database/redis/notification_test.go | 31 ++- docker-compose.yml | 208 ++++++++-------- metric_source/local/database_test.go | 344 +++++++++++++++++++++++++++ metric_source/local/local_test.go | 65 +---- 6 files changed, 480 insertions(+), 196 deletions(-) create mode 100644 metric_source/local/database_test.go diff --git a/database/redis/database.go b/database/redis/database.go index 5e3497080..03cf0cd56 100644 --- a/database/redis/database.go +++ b/database/redis/database.go @@ -91,9 +91,11 @@ func NewDatabase(logger moira.Logger, config DatabaseConfig, nh NotificationHist // NewTestDatabase use it only for tests. func NewTestDatabase(logger moira.Logger) *DbConnector { - return NewDatabase(logger, DatabaseConfig{ - Addrs: []string{"0.0.0.0:6379"}, - }, + return NewDatabase( + logger, DatabaseConfig{ + Addrs: []string{"0.0.0.0:6379"}, + MetricsTTL: time.Hour, + }, NotificationHistoryConfig{ NotificationHistoryTTL: time.Hour * 48, }, @@ -104,7 +106,8 @@ func NewTestDatabase(logger moira.Logger) *DbConnector { TransactionHeuristicLimit: 10000, ResaveTime: 30 * time.Second, }, - testSource) + testSource, + ) } // NewTestDatabaseWithIncorrectConfig use it only for tests. diff --git a/database/redis/notification.go b/database/redis/notification.go index a8f9c3f3c..21d1177de 100644 --- a/database/redis/notification.go +++ b/database/redis/notification.go @@ -8,14 +8,15 @@ import ( "strings" "time" - "github.com/moira-alert/moira/notifier" - "github.com/go-redis/redis/v8" "github.com/moira-alert/moira" "github.com/moira-alert/moira/database/redis/reply" ) +// Separate const to prevent cyclic dependencies +const NotificationsLimitUnlimited = int64(-1) + type notificationTypes struct { Valid, ToRemove, ToResaveNew, ToResaveOld []*moira.ScheduledNotification } @@ -294,8 +295,8 @@ func (connector *DbConnector) FetchNotifications(to int64, limit int64) ([]*moir } // No limit - if limit == notifier.NotificationsLimitUnlimited { - return connector.fetchNotifications(to, notifier.NotificationsLimitUnlimited) + if limit == NotificationsLimitUnlimited { + return connector.fetchNotifications(to, NotificationsLimitUnlimited) } count, err := connector.notificationsCount(to) @@ -305,7 +306,7 @@ func (connector *DbConnector) FetchNotifications(to int64, limit int64) ([]*moir // Hope count will be not greater then limit when we call fetchNotificationsNoLimit if limit > connector.notification.TransactionHeuristicLimit && count < limit/2 { - return connector.fetchNotifications(to, notifier.NotificationsLimitUnlimited) + return connector.fetchNotifications(to, NotificationsLimitUnlimited) } return connector.fetchNotifications(to, limit) @@ -354,7 +355,7 @@ func (connector *DbConnector) fetchNotifications(to int64, limit int64) ([]*moir // sorted by timestamp in one transaction with or without limit, depending on whether limit is nil. func getNotificationsInTxWithLimit(ctx context.Context, tx *redis.Tx, to int64, limit int64) ([]*moira.ScheduledNotification, error) { var rng *redis.ZRangeBy - if limit != notifier.NotificationsLimitUnlimited { + if limit != NotificationsLimitUnlimited { rng = &redis.ZRangeBy{Min: "-inf", Max: strconv.FormatInt(to, 10), Offset: 0, Count: limit} } else { rng = &redis.ZRangeBy{Min: "-inf", Max: strconv.FormatInt(to, 10)} @@ -393,7 +394,7 @@ func getLimitedNotifications( limitedNotifications := notifications - if limit != notifier.NotificationsLimitUnlimited { + if limit != NotificationsLimitUnlimited { limitedNotifications = limitNotifications(notifications) lastTs := limitedNotifications[len(limitedNotifications)-1].Timestamp @@ -401,7 +402,7 @@ func getLimitedNotifications( // this means that all notifications have same timestamp, // we hope that all notifications with same timestamp should fit our memory var err error - limitedNotifications, err = getNotificationsInTxWithLimit(ctx, tx, lastTs, notifier.NotificationsLimitUnlimited) + limitedNotifications, err = getNotificationsInTxWithLimit(ctx, tx, lastTs, NotificationsLimitUnlimited) if err != nil { return nil, fmt.Errorf("failed to get notification without limit in transaction: %w", err) } diff --git a/database/redis/notification_test.go b/database/redis/notification_test.go index d0a25ce56..d25832f63 100644 --- a/database/redis/notification_test.go +++ b/database/redis/notification_test.go @@ -10,7 +10,6 @@ import ( "github.com/moira-alert/moira" "github.com/moira-alert/moira/clock" logging "github.com/moira-alert/moira/logging/zerolog_adapter" - "github.com/moira-alert/moira/notifier" "github.com/stretchr/testify/assert" . "github.com/smartystreets/goconvey/convey" @@ -59,7 +58,7 @@ func TestScheduledNotification(t *testing.T) { }) Convey("Test fetch notifications", func() { - actual, err := database.FetchNotifications(now-database.getDelayedTimeInSeconds(), notifier.NotificationsLimitUnlimited) //nolint + actual, err := database.FetchNotifications(now-database.getDelayedTimeInSeconds(), NotificationsLimitUnlimited) //nolint So(err, ShouldBeNil) So(actual, ShouldResemble, []*moira.ScheduledNotification{¬ificationOld}) @@ -68,7 +67,7 @@ func TestScheduledNotification(t *testing.T) { So(total, ShouldEqual, 2) So(actual, ShouldResemble, []*moira.ScheduledNotification{¬ification, ¬ificationNew}) - actual, err = database.FetchNotifications(now+database.getDelayedTimeInSeconds(), notifier.NotificationsLimitUnlimited) //nolint + actual, err = database.FetchNotifications(now+database.getDelayedTimeInSeconds(), NotificationsLimitUnlimited) //nolint So(err, ShouldBeNil) So(actual, ShouldResemble, []*moira.ScheduledNotification{¬ification, ¬ificationNew}) @@ -128,7 +127,7 @@ func TestScheduledNotification(t *testing.T) { So(total, ShouldEqual, 0) So(actual, ShouldResemble, []*moira.ScheduledNotification{}) - actual, err = database.FetchNotifications(now+database.getDelayedTimeInSeconds(), notifier.NotificationsLimitUnlimited) //nolint + actual, err = database.FetchNotifications(now+database.getDelayedTimeInSeconds(), NotificationsLimitUnlimited) //nolint So(err, ShouldBeNil) So(actual, ShouldResemble, []*moira.ScheduledNotification{}) }) @@ -167,7 +166,7 @@ func TestScheduledNotification(t *testing.T) { So(total, ShouldEqual, 0) So(actual, ShouldResemble, []*moira.ScheduledNotification{}) - actual, err = database.FetchNotifications(now+database.getDelayedTimeInSeconds(), notifier.NotificationsLimitUnlimited) //nolint + actual, err = database.FetchNotifications(now+database.getDelayedTimeInSeconds(), NotificationsLimitUnlimited) //nolint So(err, ShouldBeNil) So(actual, ShouldResemble, []*moira.ScheduledNotification{}) }) @@ -197,7 +196,7 @@ func TestScheduledNotificationErrorConnection(t *testing.T) { So(err, ShouldNotBeNil) So(total, ShouldEqual, 0) - actual2, err := database.FetchNotifications(0, notifier.NotificationsLimitUnlimited) + actual2, err := database.FetchNotifications(0, NotificationsLimitUnlimited) So(err, ShouldNotBeNil) So(actual2, ShouldBeNil) @@ -284,7 +283,7 @@ func TestFetchNotifications(t *testing.T) { Convey("Test fetch notifications without limit", func() { addNotifications(database, []moira.ScheduledNotification{notification, notificationNew, notificationOld}) - actual, err := database.FetchNotifications(now+database.getDelayedTimeInSeconds(), notifier.NotificationsLimitUnlimited) //nolint + actual, err := database.FetchNotifications(now+database.getDelayedTimeInSeconds(), NotificationsLimitUnlimited) //nolint So(err, ShouldBeNil) So(actual, ShouldResemble, []*moira.ScheduledNotification{¬ificationOld, ¬ification, ¬ificationNew}) @@ -330,7 +329,7 @@ func TestGetNotificationsInTxWithLimit(t *testing.T) { Convey("Test with zero notifications without limit", func() { addNotifications(database, []moira.ScheduledNotification{}) err := client.Watch(ctx, func(tx *redis.Tx) error { - actual, err := getNotificationsInTxWithLimit(ctx, tx, now+database.getDelayedTimeInSeconds()*2, notifier.NotificationsLimitUnlimited) + actual, err := getNotificationsInTxWithLimit(ctx, tx, now+database.getDelayedTimeInSeconds()*2, NotificationsLimitUnlimited) So(err, ShouldBeNil) So(actual, ShouldResemble, []*moira.ScheduledNotification{}) return nil @@ -344,7 +343,7 @@ func TestGetNotificationsInTxWithLimit(t *testing.T) { Convey("Test all notifications without limit", func() { addNotifications(database, []moira.ScheduledNotification{notification, notificationNew, notificationOld}) err := client.Watch(ctx, func(tx *redis.Tx) error { - actual, err := getNotificationsInTxWithLimit(ctx, tx, now+database.getDelayedTimeInSeconds()*2, notifier.NotificationsLimitUnlimited) + actual, err := getNotificationsInTxWithLimit(ctx, tx, now+database.getDelayedTimeInSeconds()*2, NotificationsLimitUnlimited) So(err, ShouldBeNil) So(actual, ShouldResemble, []*moira.ScheduledNotification{¬ificationOld, ¬ification, ¬ificationNew}) return nil @@ -418,7 +417,7 @@ func TestGetLimitedNotifications(t *testing.T) { Convey("Test all notifications with different timestamps without limit", func() { notifications := []*moira.ScheduledNotification{¬ificationOld, ¬ification, ¬ificationNew} err := client.Watch(ctx, func(tx *redis.Tx) error { - actual, err := getLimitedNotifications(ctx, tx, notifier.NotificationsLimitUnlimited, notifications) + actual, err := getLimitedNotifications(ctx, tx, NotificationsLimitUnlimited, notifications) So(err, ShouldBeNil) So(actual, ShouldResemble, []*moira.ScheduledNotification{¬ificationOld, ¬ification, ¬ificationNew}) return nil @@ -913,7 +912,7 @@ func TestFetchNotificationsDo(t *testing.T) { Convey("Without limit", func() { addNotifications(database, []moira.ScheduledNotification{notification, notificationNew, notificationOld}) - actual, err := database.fetchNotificationsDo(now+database.getDelayedTimeInSeconds(), notifier.NotificationsLimitUnlimited) + actual, err := database.fetchNotificationsDo(now+database.getDelayedTimeInSeconds(), NotificationsLimitUnlimited) So(err, ShouldBeNil) So(actual, ShouldResemble, []*moira.ScheduledNotification{¬ificationOld, ¬ification, ¬ificationNew}) @@ -936,7 +935,7 @@ func TestFetchNotificationsDo(t *testing.T) { Convey("Without limit", func() { addNotifications(database, []moira.ScheduledNotification{}) - actual, err := database.fetchNotificationsDo(now+database.getDelayedTimeInSeconds(), notifier.NotificationsLimitUnlimited) + actual, err := database.fetchNotificationsDo(now+database.getDelayedTimeInSeconds(), NotificationsLimitUnlimited) So(err, ShouldBeNil) So(actual, ShouldResemble, []*moira.ScheduledNotification{}) @@ -947,7 +946,7 @@ func TestFetchNotificationsDo(t *testing.T) { Convey("Test all notification with ts and without limit in db", func() { addNotifications(database, []moira.ScheduledNotification{notification, notificationNew, notificationOld, notification4}) - actual, err := database.fetchNotificationsDo(now+database.getDelayedTimeInSeconds(), notifier.NotificationsLimitUnlimited) + actual, err := database.fetchNotificationsDo(now+database.getDelayedTimeInSeconds(), NotificationsLimitUnlimited) So(err, ShouldBeNil) So(actual, ShouldResemble, []*moira.ScheduledNotification{¬ificationOld, ¬ification4, ¬ification, ¬ificationNew}) @@ -1016,7 +1015,7 @@ func TestFetchNotificationsDo(t *testing.T) { Convey("Without limit", func() { addNotifications(database, []moira.ScheduledNotification{notificationOld, notificationOld2, notification, notificationNew, notificationNew2, notificationNew3}) - actual, err := database.fetchNotificationsDo(now+database.getDelayedTimeInSeconds()+3, notifier.NotificationsLimitUnlimited) + actual, err := database.fetchNotificationsDo(now+database.getDelayedTimeInSeconds()+3, NotificationsLimitUnlimited) So(err, ShouldBeNil) So(actual, ShouldResemble, []*moira.ScheduledNotification{¬ificationOld, ¬ificationOld2, ¬ification, ¬ificationNew, ¬ificationNew3}) @@ -1052,7 +1051,7 @@ func TestFetchNotificationsDo(t *testing.T) { Convey("Without limit", func() { addNotifications(database, []moira.ScheduledNotification{notificationOld, notificationOld2, notification, notificationNew, notificationNew2, notificationNew3}) - actual, err := database.fetchNotificationsDo(now+database.getDelayedTimeInSeconds()+3, notifier.NotificationsLimitUnlimited) + actual, err := database.fetchNotificationsDo(now+database.getDelayedTimeInSeconds()+3, NotificationsLimitUnlimited) So(err, ShouldBeNil) So(actual, ShouldResemble, []*moira.ScheduledNotification{¬ificationOld, ¬ificationOld2, ¬ification, ¬ificationNew, ¬ificationNew2}) @@ -1092,7 +1091,7 @@ func TestFetchNotificationsDo(t *testing.T) { Convey("without limit", func() { addNotifications(database, []moira.ScheduledNotification{notificationOld, notificationOld2, notification, notificationNew, notificationNew2, notificationNew3}) - actual, err := database.fetchNotificationsDo(now+database.getDelayedTimeInSeconds()+3, notifier.NotificationsLimitUnlimited) + actual, err := database.fetchNotificationsDo(now+database.getDelayedTimeInSeconds()+3, NotificationsLimitUnlimited) So(err, ShouldBeNil) So(actual, ShouldResemble, []*moira.ScheduledNotification{¬ificationOld, ¬ificationOld2, ¬ification, ¬ificationNew, ¬ificationNew3}) diff --git a/docker-compose.yml b/docker-compose.yml index 488244e01..143cec4b6 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,117 +9,117 @@ services: - "6379:6379" restart: always - graphite: - image: graphiteapp/graphite-statsd - ports: - - "7080:80" - restart: always + # graphite: + # image: graphiteapp/graphite-statsd + # ports: + # - "7080:80" + # restart: always - prometheus: - image: prom/prometheus - volumes: - - ./local/prometheus.yml:/etc/prometheus/prometheus.yml - command: "--config.file=/etc/prometheus/prometheus.yml --storage.tsdb.path=/prometheus" - ports: - - "9080:9090" - restart: always +# prometheus: +# image: prom/prometheus +# volumes: +# - ./local/prometheus.yml:/etc/prometheus/prometheus.yml +# command: "--config.file=/etc/prometheus/prometheus.yml --storage.tsdb.path=/prometheus" +# ports: +# - "9080:9090" +# restart: always - prometheus_2: - image: prom/prometheus - volumes: - - ./local/prometheus.yml:/etc/prometheus/prometheus.yml - command: "--config.file=/etc/prometheus/prometheus.yml --storage.tsdb.path=/prometheus" - ports: - - "9081:9090" - restart: always +# prometheus_2: +# image: prom/prometheus +# volumes: +# - ./local/prometheus.yml:/etc/prometheus/prometheus.yml +# command: "--config.file=/etc/prometheus/prometheus.yml --storage.tsdb.path=/prometheus" +# ports: +# - "9081:9090" +# restart: always - filter: - build: - context: . - dockerfile: Dockerfile.filter - volumes: - - ./local/filter.yml:/etc/moira/filter.yml - depends_on: - - redis - - relay - ports: - - "8094:8094" - restart: always +# filter: +# build: +# context: . +# dockerfile: Dockerfile.filter +# volumes: +# - ./local/filter.yml:/etc/moira/filter.yml +# depends_on: +# - redis +# - relay +# ports: +# - "8094:8094" +# restart: always - checker: - build: - context: . - dockerfile: Dockerfile.checker - volumes: - - ./local/checker.yml:/etc/moira/checker.yml - depends_on: - - redis - - filter - - graphite - - relay - ports: - - "8092:8092" - restart: always +# checker: +# build: +# context: . +# dockerfile: Dockerfile.checker +# volumes: +# - ./local/checker.yml:/etc/moira/checker.yml +# depends_on: +# - redis +# - filter +# - graphite +# - relay +# ports: +# - "8092:8092" +# restart: always - notifier: - build: - context: . - dockerfile: Dockerfile.notifier - volumes: - - ./local/notifier.yml:/etc/moira/notifier.yml - depends_on: - - redis - - checker - - relay - ports: - - "8093:8093" - restart: always +# notifier: +# build: +# context: . +# dockerfile: Dockerfile.notifier +# volumes: +# - ./local/notifier.yml:/etc/moira/notifier.yml +# depends_on: +# - redis +# - checker +# - relay +# ports: +# - "8093:8093" +# restart: always - api: - build: - context: . - dockerfile: Dockerfile.api - volumes: - - ./local/api.yml:/etc/moira/api.yml - depends_on: - - redis - - checker - - relay - networks: - - default - - balancer - ports: - - "8091:8091" - web: - image: moira/web2 - networks: - - balancer - restart: always +# api: +# build: +# context: . +# dockerfile: Dockerfile.api +# volumes: +# - ./local/api.yml:/etc/moira/api.yml +# depends_on: +# - redis +# - checker +# - relay +# networks: +# - default +# - balancer +# ports: +# - "8091:8091" +# web: +# image: moira/web2 +# networks: +# - balancer +# restart: always - balancer: - image: nginx:alpine - ports: - - "8080:8080" - depends_on: - - web - - api - networks: - - balancer - volumes: - - ./local/nginx.conf:/etc/nginx/conf.d/moira.conf - restart: always +# balancer: +# image: nginx:alpine +# ports: +# - "8080:8080" +# depends_on: +# - web +# - api +# networks: +# - balancer +# volumes: +# - ./local/nginx.conf:/etc/nginx/conf.d/moira.conf +# restart: always - relay: - image: openitcockpit/carbon-c-relay - ports: - - "2003:2003" - depends_on: - - graphite - volumes: - - ./local/relay.conf:/opt/carbon-c-relay/relay.conf - command: /opt/carbon-c-relay/bin/relay -E -s -f /opt/carbon-c-relay/relay.conf - restart: always -networks: - balancer: +# relay: +# image: openitcockpit/carbon-c-relay +# ports: +# - "2003:2003" +# depends_on: +# - graphite +# volumes: +# - ./local/relay.conf:/opt/carbon-c-relay/relay.conf +# command: /opt/carbon-c-relay/bin/relay -E -s -f /opt/carbon-c-relay/relay.conf +# restart: always +# networks: + # balancer: volumes: data: diff --git a/metric_source/local/database_test.go b/metric_source/local/database_test.go new file mode 100644 index 000000000..c4f18327b --- /dev/null +++ b/metric_source/local/database_test.go @@ -0,0 +1,344 @@ +package local + +import ( + "math" + "testing" + "time" + + "github.com/moira-alert/moira" + + "github.com/moira-alert/moira/database/redis" + + logging "github.com/moira-alert/moira/logging/zerolog_adapter" + + . "github.com/smartystreets/goconvey/convey" +) + +type metricMock struct { + values []float64 + patterns []string +} + +type testCase struct { + metrics map[string]metricMock + from int64 + retention int64 + target string + expected map[string][]float64 +} + +func saveMetrics(database moira.Database, metrics map[string]metricMock, now, retention int64) error { + maxValues := 0 + for _, m := range metrics { + if len(m.values) > maxValues { + maxValues = len(m.values) + } + } + + timeStart := now - retention*int64(maxValues-1) + for i := range maxValues { + time := timeStart + int64(i)*retention + + metricsMap := make(map[string]*moira.MatchedMetric, len(metrics)) + for name, metric := range metrics { + if len(metric.values) < i { + continue + } + + metricsMap[name] = &moira.MatchedMetric{ + Metric: name, + Patterns: metric.patterns, + Value: metric.values[i], + Timestamp: time, + RetentionTimestamp: time, + Retention: int(retention), + } + } + + err := database.SaveMetrics(metricsMap) + if err != nil { + return err + } + } + return nil +} + +func TestLocalSourceWithDatabase(t *testing.T) { + logger, _ := logging.ConfigureLog("stdout", "info", "test", true) // nolint: govet + database := redis.NewTestDatabase(logger) + localSource := Create(database) + + defer database.Flush() + + retention := int64(60) + now := floorToMultiplier(time.Now().Unix(), retention) + nan := math.NaN() + + testCases := []testCase{ + { + metrics: map[string]metricMock{ + "metric1": metricMock{ + values: []float64{1.0, 2.0, 3.0, 4.0, 5.0}, + patterns: []string{"pattern"}, + }, + "metric2": metricMock{ + values: []float64{5.0, 4.0, 3.0, 2.0, 1.0}, + patterns: []string{"pattern"}, + }, + }, + from: now - retention*4, + retention: retention, + target: "pattern", + expected: map[string][]float64{ + "metric1": []float64{1.0, 2.0, 3.0, 4.0, 5.0}, + "metric2": []float64{5.0, 4.0, 3.0, 2.0, 1.0}, + }, + }, + { + metrics: map[string]metricMock{ + "metric1": metricMock{ + values: []float64{1.0, 3.0, 1.0, 3.0, 1.0, 3.0}, + patterns: []string{"pattern"}, + }, + }, + from: now - retention*4, + retention: retention, + target: "movingAverage(pattern, 2)", + expected: map[string][]float64{ + "movingAverage(metric1,2)": []float64{2.0, 2.0, 2.0, 2.0, 2.0}, + }, + }, + { + metrics: map[string]metricMock{ + "metric1": metricMock{ + values: []float64{1.0, nan, 2.0, nan, nan}, + patterns: []string{"pattern"}, + }, + }, + from: now - retention*4, + retention: retention, + target: "keepLastValue(pattern, 1)", + expected: map[string][]float64{ + "keepLastValue(metric1,1)": []float64{1.0, 1.0, 2.0, 2.0, nan}, + }, + }, + { + metrics: map[string]metricMock{ + "metric.1.foo": metricMock{ + values: []float64{1.0, 2.0, 1.0, 2.0, 1.0}, + patterns: []string{"metric.*.*", "metric.1.foo"}, + }, + "metric.1.bar": metricMock{ + values: []float64{-1.0, -2.0, -3.0, -4.0, -5.0}, + patterns: []string{"metric.*.*", "metric.1.bar"}, + }, + "metric.2.foo": metricMock{ + values: []float64{3.0, 2.0, 3.0, 2.0, 3.0}, + patterns: []string{"metric.*.*", "metric.2.foo"}, + }, + "metric.2.bar": metricMock{ + values: []float64{-1.0, -2.0, -3.0, -4.0, -5.0}, + patterns: []string{"metric.*.*", "metric.2.bar"}, + }, + }, + from: now - retention*4, + retention: retention, + target: `applyByNode(metric.*.*, 1, "movingMax(%.foo, '2m')")`, + expected: map[string][]float64{ + "movingMax(metric.1.foo,'2m')": []float64{1.0, 2.0, 2.0, 2.0, 2.0}, + "movingMax(metric.2.foo,'2m')": []float64{3.0, 3.0, 3.0, 3.0, 3.0}, + }, + }, + { + metrics: map[string]metricMock{ + "metric.foo": metricMock{ + values: []float64{1.0, 2.0, 3.0, 4.0, 5.0}, + patterns: []string{"metric.*"}, + }, + }, + from: now - retention*4, + retention: retention, + target: "aliasByNode(metric.*, 1)", + expected: map[string][]float64{ + "foo": []float64{1.0, 2.0, 3.0, 4.0, 5.0}, + }, + }, + { + metrics: map[string]metricMock{ + "metric.foo": metricMock{ + values: []float64{1.0, 2.0, 3.0, 4.0, 5.0}, + patterns: []string{"metric.*"}, + }, + }, + from: now - retention*4, + retention: retention, + target: "aliasByNode(metric.*, 2)", + expected: map[string][]float64{ + "": []float64{1.0, 2.0, 3.0, 4.0, 5.0}, + }, + }, + { + metrics: map[string]metricMock{ + "metric.1": metricMock{ + values: []float64{1.0, 2.0, 3.0, 4.0, 5.0}, + patterns: []string{"metric.*"}, + }, + "metric.2": metricMock{ + values: []float64{-1.0, 2.0, 3.0, 4.0, 5.0}, + patterns: []string{"metric.*"}, + }, + "metric.3": metricMock{ + values: []float64{-1.0, -2.0, -3.0, -4.0, -5.0}, + patterns: []string{"metric.*"}, + }, + }, + from: now - retention*4, + retention: retention, + target: "minimumBelow(metric.*, 0)", + expected: map[string][]float64{ + "metric.2": []float64{-1.0, 2.0, 3.0, 4.0, 5.0}, + "metric.3": []float64{-1.0, -2.0, -3.0, -4.0, -5.0}, + }, + }, + { + metrics: map[string]metricMock{ + "metric.foo": metricMock{ + values: []float64{1.0, 2.0, 3.0, 4.0, 5.0}, + patterns: []string{"metric.*"}, + }, + }, + from: now - retention*4, + retention: retention, + target: "exponentialMovingAverage(metric.*, 2)", + expected: map[string][]float64{ + // TODO(Tetrergeru): It mustn't work that way + // "exponentialMovingAverage(metric.foo, 2)": []float64{1.0, 2.0, 3.0, 4.0, 5.0}, + }, + }, + { + metrics: map[string]metricMock{ + "metric.foo.1": metricMock{ + values: []float64{1.0, 2.0, 3.0, 4.0, 5.0}, + patterns: []string{"metric.*.*"}, + }, + "metric.foo.2": metricMock{ + values: []float64{1.5, 2.5, 3.5, 4.5, 5.5}, + patterns: []string{"metric.*.*"}, + }, + }, + from: now - retention*4, + retention: retention, + target: "groupByNode(metric.*.*, 1, 'sumSeries')", + expected: map[string][]float64{ + "foo": []float64{2.5, 4.5, 6.5, 8.5, 10.5}, + }, + }, + { + metrics: map[string]metricMock{ + "metric.foo.1": metricMock{ + values: []float64{1.5, 2.5, 3.5, 4.5, 5.5}, + patterns: []string{"metric.*.*"}, + }, + "metric.foo.2": metricMock{ + values: []float64{1.0, 2.0, 3.0, 4.0, 5.0}, + patterns: []string{"metric.*.*"}, + }, + }, + from: now - retention*4, + retention: retention, + target: "groupByNode(metric.*.*, 1, 'unique')", + expected: map[string][]float64{ + "foo": []float64{1.5, 2.5, 3.5, 4.5, 5.5}, + }, + }, + { + metrics: map[string]metricMock{ + "metric.foo": metricMock{ + values: []float64{0, 1, 2, 3, 4, 5}, + patterns: []string{"metric.*"}, + }, + }, + from: now - retention*5, + retention: retention, + target: "hitcount(metric.*, '2m')", + expected: map[string][]float64{ + "hitcount(metric.foo,'2m')": []float64{60, 300, 540}, + }, + }, + { + metrics: map[string]metricMock{ + "metric.foo": metricMock{ + values: []float64{1, nan, 3, nan, nan, 6}, + patterns: []string{"metric.*"}, + }, + }, + from: now - retention*5, + retention: retention, + target: "interpolate(metric.*, 1)", + expected: map[string][]float64{ + "interpolate(metric.foo)": []float64{1, 2, 3, nan, nan, 6}, + }, + }, + { + metrics: map[string]metricMock{ + "metric.foo": metricMock{ + values: []float64{1, nan, 3, nan, nan, 6}, + patterns: []string{"metric.*"}, + }, + }, + from: now - retention*5, + retention: retention, + target: "interpolate(metric.*)", + expected: map[string][]float64{ + "interpolate(metric.foo)": []float64{1, 2, 3, 4, 5, 6}, + }, + }, + { + metrics: map[string]metricMock{ + "metric.foo": metricMock{ + values: []float64{1, 2, 3, 4, 5, 6}, + patterns: []string{"metric.*"}, + }, + }, + from: now - retention*5, + retention: retention, + target: "smartSummarize(metric.*, '2m', 'average')", + expected: map[string][]float64{ + "smartSummarize(metric.foo,'2m','average')": []float64{1.5, 3.5, 5.5}, + }, + }, + { + metrics: map[string]metricMock{ + "metric.foo": metricMock{ + values: []float64{1.5, 2, 3, 4, 5, 6.5}, + patterns: []string{"metric.*"}, + }, + }, + from: now - retention*5, + retention: retention, + target: "smartSummarize(metric.*, '3m', 'median')", + expected: map[string][]float64{ + "smartSummarize(metric.foo,'3m','median')": []float64{2, 5}, + }, + }, + } + + Convey("Run test cases", t, func() { + for _, testCase := range testCases { + database.Flush() + err := saveMetrics(database, testCase.metrics, now, testCase.retention) + So(err, ShouldBeNil) + + result, err := localSource.Fetch(testCase.target, testCase.from, now, true) + So(err, ShouldBeNil) + + resultData := result.GetMetricsData() + resultMap := map[string][]float64{} + for _, data := range resultData { + resultMap[data.Name] = data.Values + } + + So(resultMap, shouldEqualIfNaNsEqual, testCase.expected) + } + }) +} diff --git a/metric_source/local/local_test.go b/metric_source/local/local_test.go index b9c92af5e..716f0040e 100644 --- a/metric_source/local/local_test.go +++ b/metric_source/local/local_test.go @@ -12,6 +12,7 @@ import ( "github.com/go-graphite/carbonapi/pkg/parser" "github.com/google/go-cmp/cmp" "github.com/moira-alert/moira" + metricSource "github.com/moira-alert/moira/metric_source" mock_moira_alert "github.com/moira-alert/moira/mock/moira-alert" . "github.com/smartystreets/goconvey/convey" @@ -265,70 +266,6 @@ func TestLocalSourceFetchMultipleMetrics(t *testing.T) { }) } -func TestLocalSourceMovingFunctions(t *testing.T) { - mockCtrl := gomock.NewController(t) - database := mock_moira_alert.NewMockDatabase(mockCtrl) - localSource := Create(database) - defer mockCtrl.Finish() - - var from int64 = 17 - var until int64 = 67 - var retentionFrom int64 = 20 - var retentionUntil int64 = 70 - var retention int64 = 10 - var metricsTTL int64 = 3600 - - Convey("Test success evaluate multiple metrics with pow function", t, func() { - metrics := []string{ - "apps.server1.process.cpu.usage", - } - - metricList := make(map[string][]*moira.MetricValue) - metricList["apps.server1.process.cpu.usage"] = []*moira.MetricValue{ - {RetentionTimestamp: 20, Timestamp: 23, Value: 0.5}, - {RetentionTimestamp: 30, Timestamp: 33, Value: 0.4}, - {RetentionTimestamp: 40, Timestamp: 43, Value: 0.5}, - {RetentionTimestamp: 50, Timestamp: 53, Value: 0.5}, - {RetentionTimestamp: 60, Timestamp: 63, Value: 0.5}, - } - - metricList2 := make(map[string][]*moira.MetricValue) - metricList2["apps.server1.process.cpu.usage"] = []*moira.MetricValue{ - {RetentionTimestamp: 0, Timestamp: 3, Value: 0.5}, - {RetentionTimestamp: 10, Timestamp: 13, Value: 0.4}, - {RetentionTimestamp: 20, Timestamp: 23, Value: 0.5}, - {RetentionTimestamp: 30, Timestamp: 33, Value: 0.4}, - {RetentionTimestamp: 40, Timestamp: 43, Value: 0.5}, - {RetentionTimestamp: 50, Timestamp: 53, Value: 0.5}, - {RetentionTimestamp: 60, Timestamp: 63, Value: 0.5}, - } - - database.EXPECT().GetPatternMetrics("apps.*.process.cpu.usage").Return(metrics, nil) - database.EXPECT().GetMetricRetention(metrics[0]).Return(retention, nil) - // database.EXPECT().GetMetricsValues(metrics, retentionFrom, retentionUntil-1).Return(metricList, nil) - database.EXPECT().GetMetricsValues(metrics, int64(0), retentionUntil-1).Return(metricList, nil) - database.EXPECT().GetMetricsTTLSeconds().Return(metricsTTL) - - result, err := localSource.Fetch("alias(movingMin(apps.*.process.cpu.usage, '20s'), 'min')", from, until, true) - - So(err, ShouldBeNil) - So(result, shouldEqualIfNaNsEqual, &FetchResult{ - MetricsData: []metricSource.MetricData{ - { - Name: "min", - StartTime: retentionFrom, - StopTime: retentionUntil, - StepTime: retention, - Values: []float64{0.5, 0.4, 0.4, 0.5, 0.5}, - Wildcard: false, - }, - }, - Metrics: metrics, - Patterns: []string{"apps.*.process.cpu.usage"}, - }) - }) -} - func TestLocalSourceApplyByNode(t *testing.T) { mockCtrl := gomock.NewController(t) database := mock_moira_alert.NewMockDatabase(mockCtrl) From bd712c3e34a35d6ac5326dd0f305da355c69444a Mon Sep 17 00:00:00 2001 From: Tetrergeru Date: Wed, 2 Oct 2024 15:32:30 +0200 Subject: [PATCH 10/19] Fix lint --- database/redis/notification.go | 2 +- metric_source/local/database_test.go | 80 ++++++++++++++-------------- 2 files changed, 41 insertions(+), 41 deletions(-) diff --git a/database/redis/notification.go b/database/redis/notification.go index 21d1177de..e72b2053b 100644 --- a/database/redis/notification.go +++ b/database/redis/notification.go @@ -14,7 +14,7 @@ import ( "github.com/moira-alert/moira/database/redis/reply" ) -// Separate const to prevent cyclic dependencies +// Separate const to prevent cyclic dependencies. const NotificationsLimitUnlimited = int64(-1) type notificationTypes struct { diff --git a/metric_source/local/database_test.go b/metric_source/local/database_test.go index c4f18327b..3a06a19e6 100644 --- a/metric_source/local/database_test.go +++ b/metric_source/local/database_test.go @@ -77,11 +77,11 @@ func TestLocalSourceWithDatabase(t *testing.T) { testCases := []testCase{ { metrics: map[string]metricMock{ - "metric1": metricMock{ + "metric1": { values: []float64{1.0, 2.0, 3.0, 4.0, 5.0}, patterns: []string{"pattern"}, }, - "metric2": metricMock{ + "metric2": { values: []float64{5.0, 4.0, 3.0, 2.0, 1.0}, patterns: []string{"pattern"}, }, @@ -90,13 +90,13 @@ func TestLocalSourceWithDatabase(t *testing.T) { retention: retention, target: "pattern", expected: map[string][]float64{ - "metric1": []float64{1.0, 2.0, 3.0, 4.0, 5.0}, - "metric2": []float64{5.0, 4.0, 3.0, 2.0, 1.0}, + "metric1": {1.0, 2.0, 3.0, 4.0, 5.0}, + "metric2": {5.0, 4.0, 3.0, 2.0, 1.0}, }, }, { metrics: map[string]metricMock{ - "metric1": metricMock{ + "metric1": { values: []float64{1.0, 3.0, 1.0, 3.0, 1.0, 3.0}, patterns: []string{"pattern"}, }, @@ -105,12 +105,12 @@ func TestLocalSourceWithDatabase(t *testing.T) { retention: retention, target: "movingAverage(pattern, 2)", expected: map[string][]float64{ - "movingAverage(metric1,2)": []float64{2.0, 2.0, 2.0, 2.0, 2.0}, + "movingAverage(metric1,2)": {2.0, 2.0, 2.0, 2.0, 2.0}, }, }, { metrics: map[string]metricMock{ - "metric1": metricMock{ + "metric1": { values: []float64{1.0, nan, 2.0, nan, nan}, patterns: []string{"pattern"}, }, @@ -119,24 +119,24 @@ func TestLocalSourceWithDatabase(t *testing.T) { retention: retention, target: "keepLastValue(pattern, 1)", expected: map[string][]float64{ - "keepLastValue(metric1,1)": []float64{1.0, 1.0, 2.0, 2.0, nan}, + "keepLastValue(metric1,1)": {1.0, 1.0, 2.0, 2.0, nan}, }, }, { metrics: map[string]metricMock{ - "metric.1.foo": metricMock{ + "metric.1.foo": { values: []float64{1.0, 2.0, 1.0, 2.0, 1.0}, patterns: []string{"metric.*.*", "metric.1.foo"}, }, - "metric.1.bar": metricMock{ + "metric.1.bar": { values: []float64{-1.0, -2.0, -3.0, -4.0, -5.0}, patterns: []string{"metric.*.*", "metric.1.bar"}, }, - "metric.2.foo": metricMock{ + "metric.2.foo": { values: []float64{3.0, 2.0, 3.0, 2.0, 3.0}, patterns: []string{"metric.*.*", "metric.2.foo"}, }, - "metric.2.bar": metricMock{ + "metric.2.bar": { values: []float64{-1.0, -2.0, -3.0, -4.0, -5.0}, patterns: []string{"metric.*.*", "metric.2.bar"}, }, @@ -145,13 +145,13 @@ func TestLocalSourceWithDatabase(t *testing.T) { retention: retention, target: `applyByNode(metric.*.*, 1, "movingMax(%.foo, '2m')")`, expected: map[string][]float64{ - "movingMax(metric.1.foo,'2m')": []float64{1.0, 2.0, 2.0, 2.0, 2.0}, - "movingMax(metric.2.foo,'2m')": []float64{3.0, 3.0, 3.0, 3.0, 3.0}, + "movingMax(metric.1.foo,'2m')": {1.0, 2.0, 2.0, 2.0, 2.0}, + "movingMax(metric.2.foo,'2m')": {3.0, 3.0, 3.0, 3.0, 3.0}, }, }, { metrics: map[string]metricMock{ - "metric.foo": metricMock{ + "metric.foo": { values: []float64{1.0, 2.0, 3.0, 4.0, 5.0}, patterns: []string{"metric.*"}, }, @@ -160,12 +160,12 @@ func TestLocalSourceWithDatabase(t *testing.T) { retention: retention, target: "aliasByNode(metric.*, 1)", expected: map[string][]float64{ - "foo": []float64{1.0, 2.0, 3.0, 4.0, 5.0}, + "foo": {1.0, 2.0, 3.0, 4.0, 5.0}, }, }, { metrics: map[string]metricMock{ - "metric.foo": metricMock{ + "metric.foo": { values: []float64{1.0, 2.0, 3.0, 4.0, 5.0}, patterns: []string{"metric.*"}, }, @@ -174,20 +174,20 @@ func TestLocalSourceWithDatabase(t *testing.T) { retention: retention, target: "aliasByNode(metric.*, 2)", expected: map[string][]float64{ - "": []float64{1.0, 2.0, 3.0, 4.0, 5.0}, + "": {1.0, 2.0, 3.0, 4.0, 5.0}, }, }, { metrics: map[string]metricMock{ - "metric.1": metricMock{ + "metric.1": { values: []float64{1.0, 2.0, 3.0, 4.0, 5.0}, patterns: []string{"metric.*"}, }, - "metric.2": metricMock{ + "metric.2": { values: []float64{-1.0, 2.0, 3.0, 4.0, 5.0}, patterns: []string{"metric.*"}, }, - "metric.3": metricMock{ + "metric.3": { values: []float64{-1.0, -2.0, -3.0, -4.0, -5.0}, patterns: []string{"metric.*"}, }, @@ -196,13 +196,13 @@ func TestLocalSourceWithDatabase(t *testing.T) { retention: retention, target: "minimumBelow(metric.*, 0)", expected: map[string][]float64{ - "metric.2": []float64{-1.0, 2.0, 3.0, 4.0, 5.0}, - "metric.3": []float64{-1.0, -2.0, -3.0, -4.0, -5.0}, + "metric.2": {-1.0, 2.0, 3.0, 4.0, 5.0}, + "metric.3": {-1.0, -2.0, -3.0, -4.0, -5.0}, }, }, { metrics: map[string]metricMock{ - "metric.foo": metricMock{ + "metric.foo": { values: []float64{1.0, 2.0, 3.0, 4.0, 5.0}, patterns: []string{"metric.*"}, }, @@ -217,11 +217,11 @@ func TestLocalSourceWithDatabase(t *testing.T) { }, { metrics: map[string]metricMock{ - "metric.foo.1": metricMock{ + "metric.foo.1": { values: []float64{1.0, 2.0, 3.0, 4.0, 5.0}, patterns: []string{"metric.*.*"}, }, - "metric.foo.2": metricMock{ + "metric.foo.2": { values: []float64{1.5, 2.5, 3.5, 4.5, 5.5}, patterns: []string{"metric.*.*"}, }, @@ -230,16 +230,16 @@ func TestLocalSourceWithDatabase(t *testing.T) { retention: retention, target: "groupByNode(metric.*.*, 1, 'sumSeries')", expected: map[string][]float64{ - "foo": []float64{2.5, 4.5, 6.5, 8.5, 10.5}, + "foo": {2.5, 4.5, 6.5, 8.5, 10.5}, }, }, { metrics: map[string]metricMock{ - "metric.foo.1": metricMock{ + "metric.foo.1": { values: []float64{1.5, 2.5, 3.5, 4.5, 5.5}, patterns: []string{"metric.*.*"}, }, - "metric.foo.2": metricMock{ + "metric.foo.2": { values: []float64{1.0, 2.0, 3.0, 4.0, 5.0}, patterns: []string{"metric.*.*"}, }, @@ -248,12 +248,12 @@ func TestLocalSourceWithDatabase(t *testing.T) { retention: retention, target: "groupByNode(metric.*.*, 1, 'unique')", expected: map[string][]float64{ - "foo": []float64{1.5, 2.5, 3.5, 4.5, 5.5}, + "foo": {1.5, 2.5, 3.5, 4.5, 5.5}, }, }, { metrics: map[string]metricMock{ - "metric.foo": metricMock{ + "metric.foo": { values: []float64{0, 1, 2, 3, 4, 5}, patterns: []string{"metric.*"}, }, @@ -262,12 +262,12 @@ func TestLocalSourceWithDatabase(t *testing.T) { retention: retention, target: "hitcount(metric.*, '2m')", expected: map[string][]float64{ - "hitcount(metric.foo,'2m')": []float64{60, 300, 540}, + "hitcount(metric.foo,'2m')": {60, 300, 540}, }, }, { metrics: map[string]metricMock{ - "metric.foo": metricMock{ + "metric.foo": { values: []float64{1, nan, 3, nan, nan, 6}, patterns: []string{"metric.*"}, }, @@ -276,12 +276,12 @@ func TestLocalSourceWithDatabase(t *testing.T) { retention: retention, target: "interpolate(metric.*, 1)", expected: map[string][]float64{ - "interpolate(metric.foo)": []float64{1, 2, 3, nan, nan, 6}, + "interpolate(metric.foo)": {1, 2, 3, nan, nan, 6}, }, }, { metrics: map[string]metricMock{ - "metric.foo": metricMock{ + "metric.foo": { values: []float64{1, nan, 3, nan, nan, 6}, patterns: []string{"metric.*"}, }, @@ -290,12 +290,12 @@ func TestLocalSourceWithDatabase(t *testing.T) { retention: retention, target: "interpolate(metric.*)", expected: map[string][]float64{ - "interpolate(metric.foo)": []float64{1, 2, 3, 4, 5, 6}, + "interpolate(metric.foo)": {1, 2, 3, 4, 5, 6}, }, }, { metrics: map[string]metricMock{ - "metric.foo": metricMock{ + "metric.foo": { values: []float64{1, 2, 3, 4, 5, 6}, patterns: []string{"metric.*"}, }, @@ -304,12 +304,12 @@ func TestLocalSourceWithDatabase(t *testing.T) { retention: retention, target: "smartSummarize(metric.*, '2m', 'average')", expected: map[string][]float64{ - "smartSummarize(metric.foo,'2m','average')": []float64{1.5, 3.5, 5.5}, + "smartSummarize(metric.foo,'2m','average')": {1.5, 3.5, 5.5}, }, }, { metrics: map[string]metricMock{ - "metric.foo": metricMock{ + "metric.foo": { values: []float64{1.5, 2, 3, 4, 5, 6.5}, patterns: []string{"metric.*"}, }, @@ -318,7 +318,7 @@ func TestLocalSourceWithDatabase(t *testing.T) { retention: retention, target: "smartSummarize(metric.*, '3m', 'median')", expected: map[string][]float64{ - "smartSummarize(metric.foo,'3m','median')": []float64{2, 5}, + "smartSummarize(metric.foo,'3m','median')": {2, 5}, }, }, } From 7a944b70e6c0e430fd737a7e4fccc3f1b447421c Mon Sep 17 00:00:00 2001 From: Tetrergeru Date: Wed, 2 Oct 2024 15:50:56 +0200 Subject: [PATCH 11/19] Fix tests --- metric_source/local/database_test.go | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/metric_source/local/database_test.go b/metric_source/local/database_test.go index 3a06a19e6..af7bf0724 100644 --- a/metric_source/local/database_test.go +++ b/metric_source/local/database_test.go @@ -1,6 +1,7 @@ package local import ( + "fmt" "math" "testing" "time" @@ -240,7 +241,7 @@ func TestLocalSourceWithDatabase(t *testing.T) { patterns: []string{"metric.*.*"}, }, "metric.foo.2": { - values: []float64{1.0, 2.0, 3.0, 4.0, 5.0}, + values: []float64{1.5, 2.5, 3.5, 4.5, 5.5}, patterns: []string{"metric.*.*"}, }, }, @@ -325,20 +326,23 @@ func TestLocalSourceWithDatabase(t *testing.T) { Convey("Run test cases", t, func() { for _, testCase := range testCases { - database.Flush() - err := saveMetrics(database, testCase.metrics, now, testCase.retention) - So(err, ShouldBeNil) + Convey(fmt.Sprintf("Target '%s'", testCase.target), t, func() { + database.Flush() - result, err := localSource.Fetch(testCase.target, testCase.from, now, true) - So(err, ShouldBeNil) + err := saveMetrics(database, testCase.metrics, now, testCase.retention) + So(err, ShouldBeNil) - resultData := result.GetMetricsData() - resultMap := map[string][]float64{} - for _, data := range resultData { - resultMap[data.Name] = data.Values - } + result, err := localSource.Fetch(testCase.target, testCase.from, now, true) + So(err, ShouldBeNil) + + resultData := result.GetMetricsData() + resultMap := map[string][]float64{} + for _, data := range resultData { + resultMap[data.Name] = data.Values + } - So(resultMap, shouldEqualIfNaNsEqual, testCase.expected) + So(resultMap, shouldEqualIfNaNsEqual, testCase.expected) + }) } }) } From 4d07dd3a29307f2be71a191747bf8ccebba2cf4e Mon Sep 17 00:00:00 2001 From: Tetrergeru Date: Wed, 2 Oct 2024 15:52:04 +0200 Subject: [PATCH 12/19] Revert changes in compose --- docker-compose.yml | 208 ++++++++++++++++++++++----------------------- 1 file changed, 104 insertions(+), 104 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 143cec4b6..488244e01 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,117 +9,117 @@ services: - "6379:6379" restart: always - # graphite: - # image: graphiteapp/graphite-statsd - # ports: - # - "7080:80" - # restart: always + graphite: + image: graphiteapp/graphite-statsd + ports: + - "7080:80" + restart: always -# prometheus: -# image: prom/prometheus -# volumes: -# - ./local/prometheus.yml:/etc/prometheus/prometheus.yml -# command: "--config.file=/etc/prometheus/prometheus.yml --storage.tsdb.path=/prometheus" -# ports: -# - "9080:9090" -# restart: always + prometheus: + image: prom/prometheus + volumes: + - ./local/prometheus.yml:/etc/prometheus/prometheus.yml + command: "--config.file=/etc/prometheus/prometheus.yml --storage.tsdb.path=/prometheus" + ports: + - "9080:9090" + restart: always -# prometheus_2: -# image: prom/prometheus -# volumes: -# - ./local/prometheus.yml:/etc/prometheus/prometheus.yml -# command: "--config.file=/etc/prometheus/prometheus.yml --storage.tsdb.path=/prometheus" -# ports: -# - "9081:9090" -# restart: always + prometheus_2: + image: prom/prometheus + volumes: + - ./local/prometheus.yml:/etc/prometheus/prometheus.yml + command: "--config.file=/etc/prometheus/prometheus.yml --storage.tsdb.path=/prometheus" + ports: + - "9081:9090" + restart: always -# filter: -# build: -# context: . -# dockerfile: Dockerfile.filter -# volumes: -# - ./local/filter.yml:/etc/moira/filter.yml -# depends_on: -# - redis -# - relay -# ports: -# - "8094:8094" -# restart: always + filter: + build: + context: . + dockerfile: Dockerfile.filter + volumes: + - ./local/filter.yml:/etc/moira/filter.yml + depends_on: + - redis + - relay + ports: + - "8094:8094" + restart: always -# checker: -# build: -# context: . -# dockerfile: Dockerfile.checker -# volumes: -# - ./local/checker.yml:/etc/moira/checker.yml -# depends_on: -# - redis -# - filter -# - graphite -# - relay -# ports: -# - "8092:8092" -# restart: always + checker: + build: + context: . + dockerfile: Dockerfile.checker + volumes: + - ./local/checker.yml:/etc/moira/checker.yml + depends_on: + - redis + - filter + - graphite + - relay + ports: + - "8092:8092" + restart: always -# notifier: -# build: -# context: . -# dockerfile: Dockerfile.notifier -# volumes: -# - ./local/notifier.yml:/etc/moira/notifier.yml -# depends_on: -# - redis -# - checker -# - relay -# ports: -# - "8093:8093" -# restart: always + notifier: + build: + context: . + dockerfile: Dockerfile.notifier + volumes: + - ./local/notifier.yml:/etc/moira/notifier.yml + depends_on: + - redis + - checker + - relay + ports: + - "8093:8093" + restart: always -# api: -# build: -# context: . -# dockerfile: Dockerfile.api -# volumes: -# - ./local/api.yml:/etc/moira/api.yml -# depends_on: -# - redis -# - checker -# - relay -# networks: -# - default -# - balancer -# ports: -# - "8091:8091" -# web: -# image: moira/web2 -# networks: -# - balancer -# restart: always + api: + build: + context: . + dockerfile: Dockerfile.api + volumes: + - ./local/api.yml:/etc/moira/api.yml + depends_on: + - redis + - checker + - relay + networks: + - default + - balancer + ports: + - "8091:8091" + web: + image: moira/web2 + networks: + - balancer + restart: always -# balancer: -# image: nginx:alpine -# ports: -# - "8080:8080" -# depends_on: -# - web -# - api -# networks: -# - balancer -# volumes: -# - ./local/nginx.conf:/etc/nginx/conf.d/moira.conf -# restart: always + balancer: + image: nginx:alpine + ports: + - "8080:8080" + depends_on: + - web + - api + networks: + - balancer + volumes: + - ./local/nginx.conf:/etc/nginx/conf.d/moira.conf + restart: always -# relay: -# image: openitcockpit/carbon-c-relay -# ports: -# - "2003:2003" -# depends_on: -# - graphite -# volumes: -# - ./local/relay.conf:/opt/carbon-c-relay/relay.conf -# command: /opt/carbon-c-relay/bin/relay -E -s -f /opt/carbon-c-relay/relay.conf -# restart: always -# networks: - # balancer: + relay: + image: openitcockpit/carbon-c-relay + ports: + - "2003:2003" + depends_on: + - graphite + volumes: + - ./local/relay.conf:/opt/carbon-c-relay/relay.conf + command: /opt/carbon-c-relay/bin/relay -E -s -f /opt/carbon-c-relay/relay.conf + restart: always +networks: + balancer: volumes: data: From 8f9e172a491b0b00aa03ccccded9379eca107d12 Mon Sep 17 00:00:00 2001 From: Tetrergeru Date: Wed, 2 Oct 2024 16:12:09 +0200 Subject: [PATCH 13/19] Fix tests --- metric_source/local/database_test.go | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/metric_source/local/database_test.go b/metric_source/local/database_test.go index af7bf0724..a1a75e70f 100644 --- a/metric_source/local/database_test.go +++ b/metric_source/local/database_test.go @@ -201,21 +201,6 @@ func TestLocalSourceWithDatabase(t *testing.T) { "metric.3": {-1.0, -2.0, -3.0, -4.0, -5.0}, }, }, - { - metrics: map[string]metricMock{ - "metric.foo": { - values: []float64{1.0, 2.0, 3.0, 4.0, 5.0}, - patterns: []string{"metric.*"}, - }, - }, - from: now - retention*4, - retention: retention, - target: "exponentialMovingAverage(metric.*, 2)", - expected: map[string][]float64{ - // TODO(Tetrergeru): It mustn't work that way - // "exponentialMovingAverage(metric.foo, 2)": []float64{1.0, 2.0, 3.0, 4.0, 5.0}, - }, - }, { metrics: map[string]metricMock{ "metric.foo.1": { @@ -326,7 +311,7 @@ func TestLocalSourceWithDatabase(t *testing.T) { Convey("Run test cases", t, func() { for _, testCase := range testCases { - Convey(fmt.Sprintf("Target '%s'", testCase.target), t, func() { + Convey(fmt.Sprintf("Target '%s'", testCase.target), func() { database.Flush() err := saveMetrics(database, testCase.metrics, now, testCase.retention) From db544e2e8f778d5302cd5d1b8cbc6aebb92463e0 Mon Sep 17 00:00:00 2001 From: Tetrergeru Date: Thu, 3 Oct 2024 10:40:21 +0200 Subject: [PATCH 14/19] Make variable NotificationsLimitUnlimited private in redis --- database/redis/notification.go | 14 +++++++------- database/redis/notification_test.go | 30 ++++++++++++++--------------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/database/redis/notification.go b/database/redis/notification.go index e72b2053b..8d0485e6c 100644 --- a/database/redis/notification.go +++ b/database/redis/notification.go @@ -15,7 +15,7 @@ import ( ) // Separate const to prevent cyclic dependencies. -const NotificationsLimitUnlimited = int64(-1) +const notificationsLimitUnlimited = int64(-1) type notificationTypes struct { Valid, ToRemove, ToResaveNew, ToResaveOld []*moira.ScheduledNotification @@ -295,8 +295,8 @@ func (connector *DbConnector) FetchNotifications(to int64, limit int64) ([]*moir } // No limit - if limit == NotificationsLimitUnlimited { - return connector.fetchNotifications(to, NotificationsLimitUnlimited) + if limit == notificationsLimitUnlimited { + return connector.fetchNotifications(to, notificationsLimitUnlimited) } count, err := connector.notificationsCount(to) @@ -306,7 +306,7 @@ func (connector *DbConnector) FetchNotifications(to int64, limit int64) ([]*moir // Hope count will be not greater then limit when we call fetchNotificationsNoLimit if limit > connector.notification.TransactionHeuristicLimit && count < limit/2 { - return connector.fetchNotifications(to, NotificationsLimitUnlimited) + return connector.fetchNotifications(to, notificationsLimitUnlimited) } return connector.fetchNotifications(to, limit) @@ -355,7 +355,7 @@ func (connector *DbConnector) fetchNotifications(to int64, limit int64) ([]*moir // sorted by timestamp in one transaction with or without limit, depending on whether limit is nil. func getNotificationsInTxWithLimit(ctx context.Context, tx *redis.Tx, to int64, limit int64) ([]*moira.ScheduledNotification, error) { var rng *redis.ZRangeBy - if limit != NotificationsLimitUnlimited { + if limit != notificationsLimitUnlimited { rng = &redis.ZRangeBy{Min: "-inf", Max: strconv.FormatInt(to, 10), Offset: 0, Count: limit} } else { rng = &redis.ZRangeBy{Min: "-inf", Max: strconv.FormatInt(to, 10)} @@ -394,7 +394,7 @@ func getLimitedNotifications( limitedNotifications := notifications - if limit != NotificationsLimitUnlimited { + if limit != notificationsLimitUnlimited { limitedNotifications = limitNotifications(notifications) lastTs := limitedNotifications[len(limitedNotifications)-1].Timestamp @@ -402,7 +402,7 @@ func getLimitedNotifications( // this means that all notifications have same timestamp, // we hope that all notifications with same timestamp should fit our memory var err error - limitedNotifications, err = getNotificationsInTxWithLimit(ctx, tx, lastTs, NotificationsLimitUnlimited) + limitedNotifications, err = getNotificationsInTxWithLimit(ctx, tx, lastTs, notificationsLimitUnlimited) if err != nil { return nil, fmt.Errorf("failed to get notification without limit in transaction: %w", err) } diff --git a/database/redis/notification_test.go b/database/redis/notification_test.go index d25832f63..c287f78d5 100644 --- a/database/redis/notification_test.go +++ b/database/redis/notification_test.go @@ -58,7 +58,7 @@ func TestScheduledNotification(t *testing.T) { }) Convey("Test fetch notifications", func() { - actual, err := database.FetchNotifications(now-database.getDelayedTimeInSeconds(), NotificationsLimitUnlimited) //nolint + actual, err := database.FetchNotifications(now-database.getDelayedTimeInSeconds(), notificationsLimitUnlimited) //nolint So(err, ShouldBeNil) So(actual, ShouldResemble, []*moira.ScheduledNotification{¬ificationOld}) @@ -67,7 +67,7 @@ func TestScheduledNotification(t *testing.T) { So(total, ShouldEqual, 2) So(actual, ShouldResemble, []*moira.ScheduledNotification{¬ification, ¬ificationNew}) - actual, err = database.FetchNotifications(now+database.getDelayedTimeInSeconds(), NotificationsLimitUnlimited) //nolint + actual, err = database.FetchNotifications(now+database.getDelayedTimeInSeconds(), notificationsLimitUnlimited) //nolint So(err, ShouldBeNil) So(actual, ShouldResemble, []*moira.ScheduledNotification{¬ification, ¬ificationNew}) @@ -127,7 +127,7 @@ func TestScheduledNotification(t *testing.T) { So(total, ShouldEqual, 0) So(actual, ShouldResemble, []*moira.ScheduledNotification{}) - actual, err = database.FetchNotifications(now+database.getDelayedTimeInSeconds(), NotificationsLimitUnlimited) //nolint + actual, err = database.FetchNotifications(now+database.getDelayedTimeInSeconds(), notificationsLimitUnlimited) //nolint So(err, ShouldBeNil) So(actual, ShouldResemble, []*moira.ScheduledNotification{}) }) @@ -166,7 +166,7 @@ func TestScheduledNotification(t *testing.T) { So(total, ShouldEqual, 0) So(actual, ShouldResemble, []*moira.ScheduledNotification{}) - actual, err = database.FetchNotifications(now+database.getDelayedTimeInSeconds(), NotificationsLimitUnlimited) //nolint + actual, err = database.FetchNotifications(now+database.getDelayedTimeInSeconds(), notificationsLimitUnlimited) //nolint So(err, ShouldBeNil) So(actual, ShouldResemble, []*moira.ScheduledNotification{}) }) @@ -196,7 +196,7 @@ func TestScheduledNotificationErrorConnection(t *testing.T) { So(err, ShouldNotBeNil) So(total, ShouldEqual, 0) - actual2, err := database.FetchNotifications(0, NotificationsLimitUnlimited) + actual2, err := database.FetchNotifications(0, notificationsLimitUnlimited) So(err, ShouldNotBeNil) So(actual2, ShouldBeNil) @@ -283,7 +283,7 @@ func TestFetchNotifications(t *testing.T) { Convey("Test fetch notifications without limit", func() { addNotifications(database, []moira.ScheduledNotification{notification, notificationNew, notificationOld}) - actual, err := database.FetchNotifications(now+database.getDelayedTimeInSeconds(), NotificationsLimitUnlimited) //nolint + actual, err := database.FetchNotifications(now+database.getDelayedTimeInSeconds(), notificationsLimitUnlimited) //nolint So(err, ShouldBeNil) So(actual, ShouldResemble, []*moira.ScheduledNotification{¬ificationOld, ¬ification, ¬ificationNew}) @@ -329,7 +329,7 @@ func TestGetNotificationsInTxWithLimit(t *testing.T) { Convey("Test with zero notifications without limit", func() { addNotifications(database, []moira.ScheduledNotification{}) err := client.Watch(ctx, func(tx *redis.Tx) error { - actual, err := getNotificationsInTxWithLimit(ctx, tx, now+database.getDelayedTimeInSeconds()*2, NotificationsLimitUnlimited) + actual, err := getNotificationsInTxWithLimit(ctx, tx, now+database.getDelayedTimeInSeconds()*2, notificationsLimitUnlimited) So(err, ShouldBeNil) So(actual, ShouldResemble, []*moira.ScheduledNotification{}) return nil @@ -343,7 +343,7 @@ func TestGetNotificationsInTxWithLimit(t *testing.T) { Convey("Test all notifications without limit", func() { addNotifications(database, []moira.ScheduledNotification{notification, notificationNew, notificationOld}) err := client.Watch(ctx, func(tx *redis.Tx) error { - actual, err := getNotificationsInTxWithLimit(ctx, tx, now+database.getDelayedTimeInSeconds()*2, NotificationsLimitUnlimited) + actual, err := getNotificationsInTxWithLimit(ctx, tx, now+database.getDelayedTimeInSeconds()*2, notificationsLimitUnlimited) So(err, ShouldBeNil) So(actual, ShouldResemble, []*moira.ScheduledNotification{¬ificationOld, ¬ification, ¬ificationNew}) return nil @@ -417,7 +417,7 @@ func TestGetLimitedNotifications(t *testing.T) { Convey("Test all notifications with different timestamps without limit", func() { notifications := []*moira.ScheduledNotification{¬ificationOld, ¬ification, ¬ificationNew} err := client.Watch(ctx, func(tx *redis.Tx) error { - actual, err := getLimitedNotifications(ctx, tx, NotificationsLimitUnlimited, notifications) + actual, err := getLimitedNotifications(ctx, tx, notificationsLimitUnlimited, notifications) So(err, ShouldBeNil) So(actual, ShouldResemble, []*moira.ScheduledNotification{¬ificationOld, ¬ification, ¬ificationNew}) return nil @@ -912,7 +912,7 @@ func TestFetchNotificationsDo(t *testing.T) { Convey("Without limit", func() { addNotifications(database, []moira.ScheduledNotification{notification, notificationNew, notificationOld}) - actual, err := database.fetchNotificationsDo(now+database.getDelayedTimeInSeconds(), NotificationsLimitUnlimited) + actual, err := database.fetchNotificationsDo(now+database.getDelayedTimeInSeconds(), notificationsLimitUnlimited) So(err, ShouldBeNil) So(actual, ShouldResemble, []*moira.ScheduledNotification{¬ificationOld, ¬ification, ¬ificationNew}) @@ -935,7 +935,7 @@ func TestFetchNotificationsDo(t *testing.T) { Convey("Without limit", func() { addNotifications(database, []moira.ScheduledNotification{}) - actual, err := database.fetchNotificationsDo(now+database.getDelayedTimeInSeconds(), NotificationsLimitUnlimited) + actual, err := database.fetchNotificationsDo(now+database.getDelayedTimeInSeconds(), notificationsLimitUnlimited) So(err, ShouldBeNil) So(actual, ShouldResemble, []*moira.ScheduledNotification{}) @@ -946,7 +946,7 @@ func TestFetchNotificationsDo(t *testing.T) { Convey("Test all notification with ts and without limit in db", func() { addNotifications(database, []moira.ScheduledNotification{notification, notificationNew, notificationOld, notification4}) - actual, err := database.fetchNotificationsDo(now+database.getDelayedTimeInSeconds(), NotificationsLimitUnlimited) + actual, err := database.fetchNotificationsDo(now+database.getDelayedTimeInSeconds(), notificationsLimitUnlimited) So(err, ShouldBeNil) So(actual, ShouldResemble, []*moira.ScheduledNotification{¬ificationOld, ¬ification4, ¬ification, ¬ificationNew}) @@ -1015,7 +1015,7 @@ func TestFetchNotificationsDo(t *testing.T) { Convey("Without limit", func() { addNotifications(database, []moira.ScheduledNotification{notificationOld, notificationOld2, notification, notificationNew, notificationNew2, notificationNew3}) - actual, err := database.fetchNotificationsDo(now+database.getDelayedTimeInSeconds()+3, NotificationsLimitUnlimited) + actual, err := database.fetchNotificationsDo(now+database.getDelayedTimeInSeconds()+3, notificationsLimitUnlimited) So(err, ShouldBeNil) So(actual, ShouldResemble, []*moira.ScheduledNotification{¬ificationOld, ¬ificationOld2, ¬ification, ¬ificationNew, ¬ificationNew3}) @@ -1051,7 +1051,7 @@ func TestFetchNotificationsDo(t *testing.T) { Convey("Without limit", func() { addNotifications(database, []moira.ScheduledNotification{notificationOld, notificationOld2, notification, notificationNew, notificationNew2, notificationNew3}) - actual, err := database.fetchNotificationsDo(now+database.getDelayedTimeInSeconds()+3, NotificationsLimitUnlimited) + actual, err := database.fetchNotificationsDo(now+database.getDelayedTimeInSeconds()+3, notificationsLimitUnlimited) So(err, ShouldBeNil) So(actual, ShouldResemble, []*moira.ScheduledNotification{¬ificationOld, ¬ificationOld2, ¬ification, ¬ificationNew, ¬ificationNew2}) @@ -1091,7 +1091,7 @@ func TestFetchNotificationsDo(t *testing.T) { Convey("without limit", func() { addNotifications(database, []moira.ScheduledNotification{notificationOld, notificationOld2, notification, notificationNew, notificationNew2, notificationNew3}) - actual, err := database.fetchNotificationsDo(now+database.getDelayedTimeInSeconds()+3, NotificationsLimitUnlimited) + actual, err := database.fetchNotificationsDo(now+database.getDelayedTimeInSeconds()+3, notificationsLimitUnlimited) So(err, ShouldBeNil) So(actual, ShouldResemble, []*moira.ScheduledNotification{¬ificationOld, ¬ificationOld2, ¬ification, ¬ificationNew, ¬ificationNew3}) From 3e3ccf352c93fef91299ac7aefd124b79adccfb7 Mon Sep 17 00:00:00 2001 From: Tetrergeru Date: Fri, 4 Oct 2024 13:04:22 +0200 Subject: [PATCH 15/19] Update carbonapi to nice version --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index c68615035..7e02d5d77 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/dustin/go-humanize v1.0.1 github.com/go-chi/chi v4.1.2+incompatible github.com/go-chi/render v1.0.1 - github.com/go-graphite/carbonapi v0.16.2-0.20240530091606-c2229eabd094 + github.com/go-graphite/carbonapi v0.17.0 github.com/go-graphite/protocol v1.0.0 github.com/go-redis/redis/v8 v8.11.5 github.com/go-redsync/redsync/v4 v4.4.4 diff --git a/go.sum b/go.sum index a0cb17b55..045c19e84 100644 --- a/go.sum +++ b/go.sum @@ -254,6 +254,8 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-graphite/carbonapi v0.16.2-0.20240530091606-c2229eabd094 h1:1obdNCH61kxvX5LLS0Pq4EP4U0GEHOutbVMgkH5yDwM= github.com/go-graphite/carbonapi v0.16.2-0.20240530091606-c2229eabd094/go.mod h1:EwQ1MJBzP8BBozLkgwTZdePM/5SqPSxhtY0uDdER2LQ= +github.com/go-graphite/carbonapi v0.17.0 h1:6JowndAU0qsxUoBftCBy23Rgt8dCxf+1wHxfGZ3GA2E= +github.com/go-graphite/carbonapi v0.17.0/go.mod h1:EwQ1MJBzP8BBozLkgwTZdePM/5SqPSxhtY0uDdER2LQ= github.com/go-graphite/protocol v1.0.0 h1:Fqb0mkVVtfMrn6vw6Ntm3raf3gVVZCOVdZu4JosW5qE= github.com/go-graphite/protocol v1.0.0/go.mod h1:eonkg/0UGhJUYu+PshOg1NzWSUcXskr/yHeQXJHJr8Y= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= From f16248b0a88bd2548fdc39f123519365a31b4e0f Mon Sep 17 00:00:00 2001 From: Tetrergeru Date: Fri, 4 Oct 2024 14:04:50 +0200 Subject: [PATCH 16/19] * --- database/redis/notification.go | 2 ++ metric_source/local/database_test.go | 14 ++++++++++++++ notifier/config.go | 1 + 3 files changed, 17 insertions(+) diff --git a/database/redis/notification.go b/database/redis/notification.go index 8d0485e6c..dc64f888c 100644 --- a/database/redis/notification.go +++ b/database/redis/notification.go @@ -15,6 +15,8 @@ import ( ) // Separate const to prevent cyclic dependencies. +// Original const is declared in notifier package, notifier depends on all metric source packages. +// Thus it prevents us from using database in tests for local metric source const notificationsLimitUnlimited = int64(-1) type notificationTypes struct { diff --git a/metric_source/local/database_test.go b/metric_source/local/database_test.go index a1a75e70f..d257acd58 100644 --- a/metric_source/local/database_test.go +++ b/metric_source/local/database_test.go @@ -178,6 +178,20 @@ func TestLocalSourceWithDatabase(t *testing.T) { "": {1.0, 2.0, 3.0, 4.0, 5.0}, }, }, + { + metrics: map[string]metricMock{ + "metric.foo": { + values: []float64{1.0, 2.0, 3.0, 4.0, 5.0}, + patterns: []string{"metric.*"}, + }, + }, + from: now - retention*4, + retention: retention, + target: "consolidateBy(metric.*, 'max')", + expected: map[string][]float64{ + // "": {1.0, 2.0, 3.0, 4.0, 5.0}, + }, + }, { metrics: map[string]metricMock{ "metric.1": { diff --git a/notifier/config.go b/notifier/config.go index a89b4b7ec..d30db4478 100644 --- a/notifier/config.go +++ b/notifier/config.go @@ -4,6 +4,7 @@ import ( "time" ) +// There is a duplicate of this constant in database package to prevent cyclic dependencies const NotificationsLimitUnlimited = int64(-1) // Config is sending settings including log settings. From 9bdab896e32e21c48521a1b7f81877ee66cfa7db Mon Sep 17 00:00:00 2001 From: Tetrergeru Date: Fri, 4 Oct 2024 14:44:59 +0200 Subject: [PATCH 17/19] Fix consolidations --- go.sum | 2 -- metric_source/local/database_test.go | 4 ++-- metric_source/local/eval.go | 9 ++++++++- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/go.sum b/go.sum index 045c19e84..ea5e36f2f 100644 --- a/go.sum +++ b/go.sum @@ -252,8 +252,6 @@ github.com/go-errors/errors v1.1.1/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWE github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-graphite/carbonapi v0.16.2-0.20240530091606-c2229eabd094 h1:1obdNCH61kxvX5LLS0Pq4EP4U0GEHOutbVMgkH5yDwM= -github.com/go-graphite/carbonapi v0.16.2-0.20240530091606-c2229eabd094/go.mod h1:EwQ1MJBzP8BBozLkgwTZdePM/5SqPSxhtY0uDdER2LQ= github.com/go-graphite/carbonapi v0.17.0 h1:6JowndAU0qsxUoBftCBy23Rgt8dCxf+1wHxfGZ3GA2E= github.com/go-graphite/carbonapi v0.17.0/go.mod h1:EwQ1MJBzP8BBozLkgwTZdePM/5SqPSxhtY0uDdER2LQ= github.com/go-graphite/protocol v1.0.0 h1:Fqb0mkVVtfMrn6vw6Ntm3raf3gVVZCOVdZu4JosW5qE= diff --git a/metric_source/local/database_test.go b/metric_source/local/database_test.go index d257acd58..2314bc366 100644 --- a/metric_source/local/database_test.go +++ b/metric_source/local/database_test.go @@ -188,8 +188,8 @@ func TestLocalSourceWithDatabase(t *testing.T) { from: now - retention*4, retention: retention, target: "consolidateBy(metric.*, 'max')", - expected: map[string][]float64{ - // "": {1.0, 2.0, 3.0, 4.0, 5.0}, + expected: map[string][]float64{ + `consolidateBy(metric.foo,"max")`: {1.0, 2.0, 3.0, 4.0, 5.0}, }, }, { diff --git a/metric_source/local/eval.go b/metric_source/local/eval.go index 0b0235b74..c49df115a 100644 --- a/metric_source/local/eval.go +++ b/metric_source/local/eval.go @@ -178,6 +178,13 @@ func (ctx *fetchCtx) getMetricsData(database moira.Database, metricRequests []pa fetchData := fetchData{database} for _, mr := range metricRequests { + // We must ignore all fields except for these + request := parser.MetricRequest{ + Metric: mr.Metric, + From: mr.From, + Until: mr.Until, + } + from := mr.From + ctx.from until := mr.Until + ctx.until @@ -193,7 +200,7 @@ func (ctx *fetchCtx) getMetricsData(database moira.Database, metricRequests []pa return err } - ctx.fetchedMetrics.metricsMap[mr] = metricsData + ctx.fetchedMetrics.metricsMap[request] = metricsData ctx.fetchedMetrics.metrics = append(ctx.fetchedMetrics.metrics, metricNames.metrics...) } return nil From 2a71175cd7b7541c0c948888c559e74f70d1030c Mon Sep 17 00:00:00 2001 From: Tetrergeru Date: Fri, 4 Oct 2024 14:49:05 +0200 Subject: [PATCH 18/19] Fix lint --- database/redis/notification.go | 2 +- notifier/config.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/database/redis/notification.go b/database/redis/notification.go index dc64f888c..82caf03d4 100644 --- a/database/redis/notification.go +++ b/database/redis/notification.go @@ -16,7 +16,7 @@ import ( // Separate const to prevent cyclic dependencies. // Original const is declared in notifier package, notifier depends on all metric source packages. -// Thus it prevents us from using database in tests for local metric source +// Thus it prevents us from using database in tests for local metric source. const notificationsLimitUnlimited = int64(-1) type notificationTypes struct { diff --git a/notifier/config.go b/notifier/config.go index d30db4478..34c6e53d4 100644 --- a/notifier/config.go +++ b/notifier/config.go @@ -4,7 +4,7 @@ import ( "time" ) -// There is a duplicate of this constant in database package to prevent cyclic dependencies +// There is a duplicate of this constant in database package to prevent cyclic dependencies. const NotificationsLimitUnlimited = int64(-1) // Config is sending settings including log settings. From 187b62bb63f5e70efe605e92b2ae2f227d8115fa Mon Sep 17 00:00:00 2001 From: Tetrergeru Date: Fri, 4 Oct 2024 14:50:28 +0200 Subject: [PATCH 19/19] Rewrite comment --- metric_source/local/eval.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metric_source/local/eval.go b/metric_source/local/eval.go index c49df115a..e8f22e59b 100644 --- a/metric_source/local/eval.go +++ b/metric_source/local/eval.go @@ -178,7 +178,7 @@ func (ctx *fetchCtx) getMetricsData(database moira.Database, metricRequests []pa fetchData := fetchData{database} for _, mr := range metricRequests { - // We must ignore all fields except for these + // Other fields are used in carbon for database side consolidations request := parser.MetricRequest{ Metric: mr.Metric, From: mr.From,