Migration to dskit/ring (#4641)

k70
Susana Ferreira 4 years ago committed by GitHub
parent 2ac409c23e
commit 2d24e2ea64
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 38
      go.mod
  2. 78
      go.sum
  3. 6
      pkg/distributor/distributor.go
  4. 4
      pkg/distributor/distributor_test.go
  5. 2
      pkg/ingester/flush_test.go
  6. 4
      pkg/ingester/ingester.go
  7. 2
      pkg/ingester/transfer.go
  8. 2
      pkg/ingester/transfer_test.go
  9. 2
      pkg/loki/loki.go
  10. 5
      pkg/loki/modules.go
  11. 2
      pkg/lokifrontend/frontend/config.go
  12. 2
      pkg/lokifrontend/frontend/v2/frontend.go
  13. 2
      pkg/lokifrontend/frontend/v2/frontend_scheduler_worker.go
  14. 4
      pkg/querier/ingester_querier.go
  15. 2
      pkg/querier/ingester_querier_test.go
  16. 4
      pkg/querier/querier_mock_test.go
  17. 4
      pkg/querier/querier_test.go
  18. 2
      pkg/querier/worker/scheduler_processor.go
  19. 2
      pkg/querier/worker/worker.go
  20. 2
      pkg/querier/worker_service.go
  21. 11
      pkg/scheduler/scheduler.go
  22. 10
      pkg/storage/stores/shipper/compactor/compactor.go
  23. 2
      pkg/util/ring.go
  24. 8
      pkg/util/ring_config.go
  25. 2
      pkg/util/ring_watcher.go
  26. 44
      vendor/github.com/armon/go-metrics/inmem.go
  27. 33
      vendor/github.com/armon/go-metrics/inmem_endpoint.go
  28. 34
      vendor/github.com/armon/go-metrics/prometheus/prometheus.go
  29. 10
      vendor/github.com/aws/aws-sdk-go/aws/client/logger.go
  30. 208
      vendor/github.com/aws/aws-sdk-go/aws/endpoints/defaults.go
  31. 2
      vendor/github.com/aws/aws-sdk-go/aws/version.go
  32. 2677
      vendor/github.com/aws/aws-sdk-go/service/dynamodb/api.go
  33. 18109
      vendor/github.com/aws/aws-sdk-go/service/ec2/api.go
  34. 4924
      vendor/github.com/aws/aws-sdk-go/service/lightsail/api.go
  35. 4308
      vendor/github.com/aws/aws-sdk-go/service/s3/api.go
  36. 1033
      vendor/github.com/aws/aws-sdk-go/service/sns/api.go
  37. 204
      vendor/github.com/aws/aws-sdk-go/service/sso/api.go
  38. 252
      vendor/github.com/aws/aws-sdk-go/service/sts/api.go
  39. 2
      vendor/github.com/cortexproject/cortex/pkg/alertmanager/alertmanager_client.go
  40. 7
      vendor/github.com/cortexproject/cortex/pkg/alertmanager/alertmanager_ring.go
  41. 4
      vendor/github.com/cortexproject/cortex/pkg/alertmanager/distributor.go
  42. 2
      vendor/github.com/cortexproject/cortex/pkg/alertmanager/lifecycle.go
  43. 14
      vendor/github.com/cortexproject/cortex/pkg/alertmanager/multitenant.go
  44. 2
      vendor/github.com/cortexproject/cortex/pkg/api/api.go
  45. 6
      vendor/github.com/cortexproject/cortex/pkg/compactor/compactor.go
  46. 2
      vendor/github.com/cortexproject/cortex/pkg/compactor/compactor_ring.go
  47. 2
      vendor/github.com/cortexproject/cortex/pkg/cortex/cortex.go
  48. 5
      vendor/github.com/cortexproject/cortex/pkg/cortex/modules.go
  49. 8
      vendor/github.com/cortexproject/cortex/pkg/distributor/distributor.go
  50. 2
      vendor/github.com/cortexproject/cortex/pkg/distributor/distributor_ring.go
  51. 5
      vendor/github.com/cortexproject/cortex/pkg/distributor/ingester_client_pool.go
  52. 2
      vendor/github.com/cortexproject/cortex/pkg/distributor/query.go
  53. 4
      vendor/github.com/cortexproject/cortex/pkg/ingester/ingester.go
  54. 4
      vendor/github.com/cortexproject/cortex/pkg/ingester/ingester_v2.go
  55. 2
      vendor/github.com/cortexproject/cortex/pkg/ingester/transfer.go
  56. 2
      vendor/github.com/cortexproject/cortex/pkg/querier/blocks_store_balanced_set.go
  57. 8
      vendor/github.com/cortexproject/cortex/pkg/querier/blocks_store_queryable.go
  58. 4
      vendor/github.com/cortexproject/cortex/pkg/querier/blocks_store_replicated_set.go
  59. 2
      vendor/github.com/cortexproject/cortex/pkg/querier/store_gateway_client.go
  60. 2
      vendor/github.com/cortexproject/cortex/pkg/querier/worker/scheduler_processor.go
  61. 3
      vendor/github.com/cortexproject/cortex/pkg/ruler/client_pool.go
  62. 2
      vendor/github.com/cortexproject/cortex/pkg/ruler/lifecycle.go
  63. 12
      vendor/github.com/cortexproject/cortex/pkg/ruler/ruler.go
  64. 8
      vendor/github.com/cortexproject/cortex/pkg/ruler/ruler_ring.go
  65. 12
      vendor/github.com/cortexproject/cortex/pkg/storegateway/gateway.go
  66. 7
      vendor/github.com/cortexproject/cortex/pkg/storegateway/gateway_ring.go
  67. 2
      vendor/github.com/cortexproject/cortex/pkg/storegateway/sharding_strategy.go
  68. 30
      vendor/github.com/fatih/color/README.md
  69. 25
      vendor/github.com/fatih/color/color.go
  70. 2
      vendor/github.com/fatih/color/doc.go
  71. 9
      vendor/github.com/go-kit/kit/log/README.md
  72. 2
      vendor/github.com/go-kit/kit/log/doc.go
  73. 82
      vendor/github.com/go-kit/kit/log/json_logger.go
  74. 9
      vendor/github.com/go-kit/kit/log/level/doc.go
  75. 139
      vendor/github.com/go-kit/kit/log/level/level.go
  76. 146
      vendor/github.com/go-kit/kit/log/log.go
  77. 51
      vendor/github.com/go-kit/kit/log/logfmt_logger.go
  78. 8
      vendor/github.com/go-kit/kit/log/nop_logger.go
  79. 117
      vendor/github.com/go-kit/kit/log/stdlib.go
  80. 86
      vendor/github.com/go-kit/kit/log/sync.go
  81. 76
      vendor/github.com/go-kit/kit/log/value.go
  82. 15
      vendor/github.com/grafana/dskit/ring/basic_lifecycler.go
  83. 0
      vendor/github.com/grafana/dskit/ring/basic_lifecycler_delegates.go
  84. 6
      vendor/github.com/grafana/dskit/ring/basic_lifecycler_metrics.go
  85. 4
      vendor/github.com/grafana/dskit/ring/batch.go
  86. 11
      vendor/github.com/grafana/dskit/ring/client/pool.go
  87. 2
      vendor/github.com/grafana/dskit/ring/client/ring_service_discovery.go
  88. 0
      vendor/github.com/grafana/dskit/ring/flush.go
  89. 44
      vendor/github.com/grafana/dskit/ring/http.go
  90. 229
      vendor/github.com/grafana/dskit/ring/lifecycler.go
  91. 40
      vendor/github.com/grafana/dskit/ring/lifecycler_metrics.go
  92. 32
      vendor/github.com/grafana/dskit/ring/model.go
  93. 0
      vendor/github.com/grafana/dskit/ring/replication_set.go
  94. 0
      vendor/github.com/grafana/dskit/ring/replication_set_tracker.go
  95. 0
      vendor/github.com/grafana/dskit/ring/replication_strategy.go
  96. 198
      vendor/github.com/grafana/dskit/ring/ring.go
  97. 2
      vendor/github.com/grafana/dskit/ring/ring.pb.go
  98. 2
      vendor/github.com/grafana/dskit/ring/ring.proto
  99. 45
      vendor/github.com/grafana/dskit/ring/shard/shard.go
  100. 2
      vendor/github.com/grafana/dskit/ring/tokens.go
  101. Some files were not shown because too many files have changed in this diff Show More

@ -13,7 +13,7 @@ require (
github.com/Shopify/sarama v1.30.0
github.com/Workiva/go-datastructures v1.0.53
github.com/alicebob/miniredis/v2 v2.14.3
github.com/aws/aws-sdk-go v1.40.37
github.com/aws/aws-sdk-go v1.40.45
github.com/bmatcuk/doublestar v1.2.2
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b
github.com/buger/jsonparser v1.1.1
@ -21,18 +21,18 @@ require (
github.com/cespare/xxhash v1.1.0
github.com/cespare/xxhash/v2 v2.1.2
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf
github.com/cortexproject/cortex v1.10.1-0.20211014125347-85c378182d0d
github.com/cortexproject/cortex v1.10.1-0.20211104100946-3f329a21cad4
github.com/davecgh/go-spew v1.1.1
github.com/docker/docker v20.10.8+incompatible
github.com/docker/go-plugins-helpers v0.0.0-20181025120712-1e6269c305b8
github.com/drone/envsubst v1.0.2
github.com/dustin/go-humanize v1.0.0
github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb
github.com/fatih/color v1.9.0
github.com/fatih/color v1.12.0
github.com/felixge/fgprof v0.9.1
github.com/fluent/fluent-bit-go v0.0.0-20190925192703-ea13c021720c
github.com/fsouza/fake-gcs-server v1.7.0
github.com/go-kit/kit v0.11.0 // indirect
github.com/go-kit/kit v0.12.0 // indirect
github.com/go-kit/log v0.2.0
github.com/go-logfmt/logfmt v0.5.1
github.com/go-redis/redis/v8 v8.11.4
@ -43,7 +43,7 @@ require (
github.com/google/go-cmp v0.5.6
github.com/gorilla/mux v1.8.0
github.com/gorilla/websocket v1.4.2
github.com/grafana/dskit v0.0.0-20211011144203-3a88ec0b675f
github.com/grafana/dskit v0.0.0-20211021180445-3bd016e9d7f1
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0
github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645
github.com/hashicorp/consul/api v1.10.1
@ -54,12 +54,12 @@ require (
github.com/influxdata/telegraf v1.16.3
github.com/jmespath/go-jmespath v0.4.0
github.com/joncrlsn/dque v2.2.1-0.20200515025108-956d14155fa2+incompatible
github.com/json-iterator/go v1.1.11
github.com/json-iterator/go v1.1.12
github.com/klauspost/compress v1.13.6
github.com/klauspost/pgzip v1.2.5
github.com/minio/minio-go/v7 v7.0.10
github.com/mitchellh/mapstructure v1.4.1
github.com/modern-go/reflect2 v1.0.1
github.com/mitchellh/mapstructure v1.4.2
github.com/modern-go/reflect2 v1.0.2
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f
github.com/ncw/swift v1.0.52
github.com/oklog/run v1.1.0
@ -86,11 +86,11 @@ require (
github.com/weaveworks/common v0.0.0-20211015155308-ebe5bdc2c89e
go.etcd.io/bbolt v1.3.6
go.uber.org/atomic v1.9.0
go.uber.org/goleak v1.1.10
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519
golang.org/x/net v0.0.0-20211101193420-4a448f8816b3
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365
golang.org/x/sys v0.0.0-20210917161153-d61c044b1678
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac
google.golang.org/api v0.57.0
google.golang.org/grpc v1.40.0
@ -126,7 +126,7 @@ require (
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect
github.com/alecthomas/units v0.0.0-20210912230133-d1bdfacee922 // indirect
github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a // indirect
github.com/armon/go-metrics v0.3.6 // indirect
github.com/armon/go-metrics v0.3.9 // indirect
github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
@ -182,9 +182,9 @@ require (
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.2.0.20201207153454-9f6bf00c00a7 // indirect
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed // indirect
github.com/hashicorp/errwrap v1.0.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.1 // indirect
github.com/hashicorp/go-hclog v0.12.2 // indirect
github.com/hashicorp/go-immutable-radix v1.2.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-hclog v0.16.2 // indirect
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
github.com/hashicorp/go-msgpack v0.5.5 // indirect
github.com/hashicorp/go-multierror v1.1.0 // indirect
github.com/hashicorp/go-rootcerts v1.0.2 // indirect
@ -210,7 +210,7 @@ require (
github.com/mailru/easyjson v0.7.6 // indirect
github.com/mattn/go-colorable v0.1.8 // indirect
github.com/mattn/go-ieproxy v0.0.1 // indirect
github.com/mattn/go-isatty v0.0.12 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
github.com/miekg/dns v1.1.43 // indirect
github.com/minio/md5-simd v1.1.0 // indirect
@ -229,7 +229,7 @@ require (
github.com/prometheus/common/sigv4 v0.1.0 // indirect
github.com/prometheus/exporter-toolkit v0.6.1 // indirect
github.com/prometheus/node_exporter v1.0.0-rc.0.0.20200428091818-01054558c289 // indirect
github.com/prometheus/procfs v0.6.0 // indirect
github.com/prometheus/procfs v0.7.3 // indirect
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
github.com/rs/cors v1.8.0 // indirect
github.com/rs/xid v1.2.1 // indirect
@ -250,15 +250,13 @@ require (
go.etcd.io/etcd/client/v3 v3.5.0 // indirect
go.mongodb.org/mongo-driver v1.5.1 // indirect
go.opencensus.io v0.23.0 // indirect
go.uber.org/multierr v1.6.0 // indirect
go.uber.org/zap v1.17.0 // indirect
go.uber.org/multierr v1.7.0 // indirect
go.uber.org/zap v1.19.1 // indirect
go4.org/intern v0.0.0-20210108033219-3eb7198706b2 // indirect
go4.org/unsafe/assume-no-moving-gc v0.0.0-20201222180813-1025295fd063 // indirect
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f // indirect
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/tools v0.1.5 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20210921142501-181ce0d877f6 // indirect
google.golang.org/protobuf v1.27.1 // indirect

@ -157,8 +157,9 @@ github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/HdrHistogram/hdrhistogram-go v0.9.0/go.mod h1:nxrse8/Tzg2tg3DZcZjm6qEclQKK70g0KxO61gFFZD4=
github.com/HdrHistogram/hdrhistogram-go v1.0.1/go.mod h1:BWJ+nMSHY3L41Zj7CA3uXnloDp7xxV0YvstAE7nKTaM=
github.com/HdrHistogram/hdrhistogram-go v1.1.0 h1:6dpdDPTRoo78HxAJ6T1HfMiKSnqhgRRqzCuPshRkQ7I=
github.com/HdrHistogram/hdrhistogram-go v1.1.0/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo=
github.com/HdrHistogram/hdrhistogram-go v1.1.2 h1:5IcZpTvzydCQeHzK4Ef/D5rrSqwxob0t8PQPMybUNFM=
github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo=
github.com/Jeffail/gabs v1.1.0/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc=
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
@ -269,8 +270,9 @@ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmV
github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878/go.mod h1:3AMJUQhVx52RsWOnlkpikZr01T/yAVN2gn0861vByNg=
github.com/armon/go-metrics v0.3.0/go.mod h1:zXjbSimjXTd7vOpY8B0/2LpvNvDoXBuplAD+gJD3GYs=
github.com/armon/go-metrics v0.3.3/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
github.com/armon/go-metrics v0.3.6 h1:x/tmtOF9cDBoXH7XoAGOz2qqm1DknFD1590XmD/DUJ8=
github.com/armon/go-metrics v0.3.6/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
github.com/armon/go-metrics v0.3.9 h1:O2sNqxBdvq8Eq5xmzljcYzAORli6RWCvEym4cJf9m18=
github.com/armon/go-metrics v0.3.9/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
@ -306,17 +308,23 @@ github.com/aws/aws-sdk-go v1.38.35/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2z
github.com/aws/aws-sdk-go v1.38.60/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
github.com/aws/aws-sdk-go v1.38.68/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
github.com/aws/aws-sdk-go v1.40.11/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q=
github.com/aws/aws-sdk-go v1.40.37 h1:I+Q6cLctkFyMMrKukcDnj+i2kjrQ37LGiOM6xmsxC48=
github.com/aws/aws-sdk-go v1.40.37/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q=
github.com/aws/aws-sdk-go v1.40.45 h1:QN1nsY27ssD/JmW4s83qmSb+uL6DG4GmCDzjmJB4xUI=
github.com/aws/aws-sdk-go v1.40.45/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q=
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
github.com/aws/aws-sdk-go-v2 v1.7.0/go.mod h1:tb9wi5s61kTDA5qCkcDbt3KRVV74GGslQkl/DRdX/P4=
github.com/aws/aws-sdk-go-v2 v1.9.1/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4=
github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.5.0/go.mod h1:acH3+MQoiMzozT/ivU+DbRg7Ooo2298RdRaWcOv+4vM=
github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.8.1/go.mod h1:CM+19rL1+4dFWnOQKwDc7H1KwXTz+h61oUSHyhV0b3o=
github.com/aws/smithy-go v1.5.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E=
github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E=
github.com/baidubce/bce-sdk-go v0.9.81 h1:n8KfThLG9fvGv3A+RtTt/jKhg/FPPRpo+iNnS2r+iPI=
github.com/baidubce/bce-sdk-go v0.9.81/go.mod h1:zbYJMQwE4IZuyrJiFO8tO8NbtYiKTFTbwh4eIsqjVdg=
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc=
github.com/beevik/ntp v0.2.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg=
github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM=
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/benbjohnson/immutable v0.2.1/go.mod h1:uc6OHo6PN2++n98KHLxW8ef4W42ylHiQSENghE1ezxI=
github.com/benbjohnson/tmpl v1.0.0/go.mod h1:igT620JFIi44B6awvU9IsDhR77IXWtFigTLil/RPdps=
github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
@ -357,6 +365,7 @@ github.com/cactus/go-statsd-client/statsd v0.0.0-20191106001114-12b4e2b38748/go.
github.com/caio/go-tdigest v2.3.0+incompatible/go.mod h1:sHQM/ubZStBUmF1WbB8FAm8q9GjDajLC5T7ydxE3JHI=
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
github.com/casbin/casbin/v2 v2.31.6/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg=
github.com/casbin/casbin/v2 v2.37.0/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg=
github.com/cenkalti/backoff v0.0.0-20181003080854-62661b46c409/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
github.com/cenkalti/backoff v1.0.0/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
github.com/cenkalti/backoff v2.0.0+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
@ -393,6 +402,7 @@ github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6D
github.com/circonus-labs/circonusllhist v0.0.0-20161110002650-365d370cc145/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
github.com/cisco-ie/nx-telemetry-proto v0.0.0-20190531143454-82441e232cf6/go.mod h1:ugEfq4B8T8ciw/h5mCkgdiDRFS4CkqqhH2dymDB4knc=
github.com/clbanning/mxj v1.8.4/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng=
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
@ -532,8 +542,8 @@ github.com/cortexproject/cortex v1.7.1-0.20210224085859-66d6fb5b0d42/go.mod h1:u
github.com/cortexproject/cortex v1.7.1-0.20210316085356-3fedc1108a49/go.mod h1:/DBOW8TzYBTE/U+O7Whs7i7E2eeeZl1iRVDtIqxn5kg=
github.com/cortexproject/cortex v1.8.1-0.20210422151339-cf1c444e0905/go.mod h1:xxm4/CLvTmDxwE7yXwtClR4dIvkG4S09o5DygPOgc1U=
github.com/cortexproject/cortex v1.10.1-0.20210820081236-70dddb6b70b8/go.mod h1:F8PX2IHaeFvqCci46Y+fhskJkCtLvh0OqCKFtWyjP7w=
github.com/cortexproject/cortex v1.10.1-0.20211014125347-85c378182d0d h1:2KZVBpjU3NtLZ5oEB7c0TXIGKZYH6vc4pENecdbcCxw=
github.com/cortexproject/cortex v1.10.1-0.20211014125347-85c378182d0d/go.mod h1:VZ2fFzUCWcyyneToKNu+ALOpGUJIdkInXy4MOhCo/xw=
github.com/cortexproject/cortex v1.10.1-0.20211104100946-3f329a21cad4 h1:UmeSnQx9LDkclyvdwg+JdPT0ZJBDPetgLMGOUQSEHL0=
github.com/cortexproject/cortex v1.10.1-0.20211104100946-3f329a21cad4/go.mod h1:ce+HHGktmHrcpBNN1dV6q1MksC38KR2s6BKZwiQTYyc=
github.com/couchbase/go-couchbase v0.0.0-20180501122049-16db1f1fe037/go.mod h1:TWI8EKQMs5u5jLKW/tsb9VwauIrMIxQG1r5fMsswK5U=
github.com/couchbase/gomemcached v0.0.0-20180502221210-0da75df14530/go.mod h1:srVSlQLB8iXBVXHgnqemxUXqN6FCvClgCMPCsjBDR7c=
github.com/couchbase/goutils v0.0.0-20180530154633-e865a1461c8a/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs=
@ -690,8 +700,9 @@ github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLi
github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb h1:IT4JYU7k4ikYg1SCxNI1/Tieq/NFvh6dzLdgi7eu0tM=
github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb/go.mod h1:bH6Xx7IW64qjjJq8M2u4dxNaBiDfKK+z/3eGDpXEQhc=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s=
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc=
github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
github.com/fatih/structs v0.0.0-20180123065059-ebf56d35bba7/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
github.com/fatih/structtag v1.1.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94=
github.com/felixge/fgprof v0.9.1 h1:E6FUJ2Mlv043ipLOCFqo8+cHo9MhQ203E2cdEK/isEs=
@ -707,6 +718,7 @@ github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
github.com/foxcpp/go-mockdns v0.0.0-20201212160233-ede2f9158d15/go.mod h1:tPg4cp4nseejPd+UKxtCVQ2hUxNTZ7qQZJa7CLriIeo=
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
github.com/franela/goblin v0.0.0-20210519012713-85d372ac71e2/go.mod h1:VzmDKDJVZI3aJmnRI9VjAn9nJ8qPPsN1fqzr9dqInIo=
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
github.com/frankban/quicktest v1.10.2/go.mod h1:K+q6oSqb0W0Ininfk863uOk1lMy69l/P6txr3mVT54s=
github.com/frankban/quicktest v1.11.3 h1:8sXhOn0uLys67V8EsXLc6eszDs8VXWxL3iRvebPhedY=
@ -739,8 +751,9 @@ github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3I
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o=
github.com/go-kit/kit v0.11.0 h1:IGmIEl7aHTYh6E2HlT+ptILBotjo4xl8PMDl852etiI=
github.com/go-kit/kit v0.11.0/go.mod h1:73/6Ixaufkvb5Osvkls8C79vuQ49Ba1rUEUYNSf+FUw=
github.com/go-kit/kit v0.12.0 h1:e4o3o3IsBfAKQh5Qbbiqyfu97Ku7jrO/JbohvztANh4=
github.com/go-kit/kit v0.12.0/go.mod h1:lHd+EkCZPIwYItmGDDRdhinkzX2A1sj+M9biaEaizzs=
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
github.com/go-kit/log v0.2.0 h1:7i2K3eKTos3Vc0enKCfnVcgHh2olr/MyfboYq7cAcFw=
github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
@ -1129,8 +1142,8 @@ github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad
github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY=
github.com/grafana/dskit v0.0.0-20210818123532-6645f87e9e12/go.mod h1:QaNAQaCSFOtG/NHf6Jd/zh67H25kkrVCq36U61Y2Mhw=
github.com/grafana/dskit v0.0.0-20210819132858-471020752967/go.mod h1:uF46UNN1/feB1egpq8UGbBBKvJjGgZauW7pcVbeFLLM=
github.com/grafana/dskit v0.0.0-20211011144203-3a88ec0b675f h1:FvvSVEbnGeM2bUivGmsiXTi8URJyBU7TcFEEoRe5wWI=
github.com/grafana/dskit v0.0.0-20211011144203-3a88ec0b675f/go.mod h1:uPG2nyK4CtgNDmWv7qyzYcdI+S90kHHRWvHnBtEMBXM=
github.com/grafana/dskit v0.0.0-20211021180445-3bd016e9d7f1 h1:Qf+/W3Tup0nO21tgJmO14WJK0yyrm4L2UJipZP+Zoow=
github.com/grafana/dskit v0.0.0-20211021180445-3bd016e9d7f1/go.mod h1:uPG2nyK4CtgNDmWv7qyzYcdI+S90kHHRWvHnBtEMBXM=
github.com/grafana/gocql v0.0.0-20200605141915-ba5dc39ece85 h1:xLuzPoOzdfNb/RF/IENCw+oLVdZB4G21VPhkHBgwSHY=
github.com/grafana/gocql v0.0.0-20200605141915-ba5dc39ece85/go.mod h1:crI9WX6p0IhrqB+DqIUHulRW853PaNFf7o4UprV//3I=
github.com/grafana/tail v0.0.0-20201004203643-7aa4e4a91f03 h1:fGgFrAraMB0BaPfYumu+iulfDXwHm+GFyHA4xEtBqI8=
@ -1187,17 +1200,20 @@ github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brv
github.com/hashicorp/go-bexpr v0.1.0/go.mod h1:ANbpTX1oAql27TZkKVeW8p1w8NTdnyzPe/0qqPCKohU=
github.com/hashicorp/go-checkpoint v0.0.0-20171009173528-1545e56e46de/go.mod h1:xIwEieBHERyEvaeKF/TcHh1Hu+lxPM+n2vT1+g9I4m4=
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM=
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
github.com/hashicorp/go-discover v0.0.0-20190403160810-22221edb15cd/go.mod h1:ueUgD9BeIocT7QNuvxSyJyPAM9dfifBcaWmeybb67OY=
github.com/hashicorp/go-hclog v0.0.0-20180402200405-69ff559dc25f/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI=
github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
github.com/hashicorp/go-hclog v0.12.2 h1:F1fdYblUEsxKiailtkhCCG2g4bipEgaHiDc8vffNpD4=
github.com/hashicorp/go-hclog v0.12.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
github.com/hashicorp/go-hclog v0.16.2 h1:K4ev2ib4LdQETX5cSZBG0DVLk1jwGqSPXBjdah3veNs=
github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-immutable-radix v1.1.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-immutable-radix v1.2.0 h1:l6UW37iCXwZkZoAbEYnptSHVE/cQ5bOTPYG5W3vf9+8=
github.com/hashicorp/go-immutable-radix v1.2.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc=
github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-memdb v0.0.0-20180223233045-1289e7fffe71/go.mod h1:kbfItVoBJwCfKXDXN4YoAXjxcFVZ7MRrJzyTX6H4giE=
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-msgpack v0.5.4/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
@ -1273,6 +1289,7 @@ github.com/huandu/xstrings v1.0.0/go.mod h1:4qWG/gcEcfX4z/mBDHJ++3ReCw9ibxbsNJbc
github.com/huandu/xstrings v1.3.1 h1:4jgBlKK6tLKFvO8u5pmYjG91cqytmDCDvGh7ECVFfFs=
github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
github.com/hudl/fargo v1.4.0/go.mod h1:9Ai6uvFy5fQNq6VPKtg+Ceq1+eTY4nKUlR2JElEOcDo=
github.com/iancoleman/strcase v0.0.0-20180726023541-3605ed457bf7/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE=
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=
@ -1373,8 +1390,9 @@ github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/jsternberg/zap-logfmt v1.0.0/go.mod h1:uvPs/4X51zdkcm5jXl5SYoN+4RK21K8mysFmDaM/h+o=
@ -1405,6 +1423,7 @@ github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYs
github.com/klauspost/compress v1.11.12/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.13.1/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
@ -1499,8 +1518,9 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
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=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
@ -1539,6 +1559,7 @@ github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WT
github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721/go.mod h1:Ickgr2WtCLZ2MDGd4Gr0geeCH5HybhRJbonOgQpvSxc=
github.com/mileusna/useragent v0.0.0-20190129205925-3e331f0949a5/go.mod h1:JWhYAp2EXqUtsxTKdeGlY8Wp44M7VxThC9FEoNGi2IE=
github.com/minio/highwayhash v1.0.1/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY=
github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY=
github.com/minio/md5-simd v1.1.0 h1:QPfiOqlZH+Cj9teu0t9b1nTBfPbyTl16Of5MeuShdK4=
github.com/minio/md5-simd v1.1.0/go.mod h1:XpBqgZULrMYD3R+M28PcmP0CkI7PEMzB3U77ZrKZ0Gw=
github.com/minio/minio-go/v6 v6.0.44/go.mod h1:qD0lajrGW49lKZLtXKtCB4X/qkMf0a5tBvN2PaZg7Gg=
@ -1569,8 +1590,9 @@ github.com/mitchellh/mapstructure v1.2.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR
github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.4.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.4.2 h1:6h7AQ0yhTcIsmFmnAwQls75jp2Gzs4iB8W7pjMO+rqo=
github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/mitchellh/reflectwalk v1.0.1 h1:FVzMWA5RllMAKIdUSC8mdWo3XtwoecrH79BY70sEEpE=
@ -1588,8 +1610,9 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
@ -1612,11 +1635,14 @@ github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5Vgl
github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
github.com/nats-io/jwt v1.2.2/go.mod h1:/xX356yQA6LuXI9xWW7mZNpxgF2mBmGecH+Fj34sP5Q=
github.com/nats-io/jwt/v2 v2.0.2/go.mod h1:VRP+deawSXyhNjXmxPCHskrR6Mq50BqpEI5SEcNiGlY=
github.com/nats-io/jwt/v2 v2.0.3/go.mod h1:VRP+deawSXyhNjXmxPCHskrR6Mq50BqpEI5SEcNiGlY=
github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k=
github.com/nats-io/nats-server/v2 v2.1.4/go.mod h1:Jw1Z28soD/QasIA2uWjXyM9El1jly3YwyFOuR8tH1rg=
github.com/nats-io/nats-server/v2 v2.2.6/go.mod h1:sEnFaxqe09cDmfMgACxZbziXnhQFhwk+aKkZjBBRYrI=
github.com/nats-io/nats-server/v2 v2.5.0/go.mod h1:Kj86UtrXAL6LwYRA6H4RqzkHhK0Vcv2ZnKD5WbQ1t3g=
github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w=
github.com/nats-io/nats.go v1.11.0/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w=
github.com/nats-io/nats.go v1.12.1/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w=
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
github.com/nats-io/nkeys v0.2.0/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s=
@ -1655,6 +1681,7 @@ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
github.com/onsi/ginkgo v1.14.1/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
github.com/onsi/ginkgo v1.15.0/go.mod h1:hF8qUzuuC8DJGygJH3726JnCZX4MYbRB8yFfISqnKUg=
github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E=
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
@ -1668,6 +1695,7 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y
github.com/onsi/gomega v1.10.2/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
github.com/onsi/gomega v1.10.5/go.mod h1:gza4q3jKQJijlu05nKWRCW/GavJumGt8aNRxWg7mt48=
github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY=
github.com/onsi/gomega v1.16.0 h1:6gjqkI8iiRHMvdccRJM8rVKjCWk6ZIm6FTm3ddIe4/c=
github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
@ -1728,6 +1756,7 @@ github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUr
github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE=
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
github.com/performancecopilot/speed/v4 v4.0.0/go.mod h1:qxrSyuDGrTOWfV+uKRFhfxw6h/4HXRGUiZiufxo49BM=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/peterh/liner v1.0.1-0.20180619022028-8c1271fcf47f/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc=
github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
@ -1851,8 +1880,9 @@ github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+Gx
github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4=
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU=
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/prometheus v0.0.0-20180315085919-58e2a31db8de/go.mod h1:oAIUtOny2rjMX0OWN5vPR5/q/twIROJvdqnQKDdil/s=
github.com/prometheus/prometheus v0.0.0-20190818123050-43acd0e2e93f/go.mod h1:rMTlmxGCvukf2KMu3fClMDKLLoJ5hl61MhcJ7xKakf0=
github.com/prometheus/prometheus v0.0.0-20200609090129-a6600f564e3c/go.mod h1:S5n0C6tSgdnwWshBUceRx5G1OsjLv/EeZ9t3wIfEtsY=
@ -2234,14 +2264,16 @@ go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/automaxprocs v1.2.0/go.mod h1:YfO3fm683kQpzETxlTGZhGIVmXAhaw3gxeBADbpZtnU=
go.uber.org/automaxprocs v1.4.0/go.mod h1:/mTEdr7LvHhs0v7mjdxDreTz1OG5zdZGqgOnhWiR/+Q=
go.uber.org/goleak v1.0.0/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0=
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723 h1:sHOAIxRGBp443oHZIPB+HsUGaksVCXVQENPxwTfQdH4=
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/multierr v1.7.0 h1:zaiO/rmgFjbmCXdSYJWQcdvOCsthmdaHfr3Gm2Kx4Ec=
go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
@ -2249,8 +2281,9 @@ go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
go.uber.org/zap v1.14.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
go.uber.org/zap v1.14.1/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc=
go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ=
go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U=
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
go.uber.org/zap v1.19.1 h1:ue41HOKd1vGURxrmeKIgELGb3jPW9DMUDGtsinblHwI=
go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
go4.org/intern v0.0.0-20210108033219-3eb7198706b2 h1:VFTf+jjIgsldaz/Mr00VaCSswHJrI2hIjQygE/W4IMg=
go4.org/intern v0.0.0-20210108033219-3eb7198706b2/go.mod h1:vLqJ+12kCw61iCWsPto0EOHhBS+o4rO5VIucbc9g2Cc=
go4.org/unsafe/assume-no-moving-gc v0.0.0-20201222175341-b30ae309168e/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E=
@ -2300,6 +2333,7 @@ golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210915214749-c084706c2272/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210920023735-84f357641f63/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
@ -2605,8 +2639,9 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/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-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365 h1:6wSTsvPddg9gc/mVEEyk9oOAoxn+bT4Z9q1zx+4RwA4=
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210917161153-d61c044b1678 h1:J27LZFQBFoihqXoegpscI10HpjZ7B5WQLLKL2FZXQKw=
golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE=
@ -2873,6 +2908,7 @@ google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEc
google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210917145530-b395a37504d4/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210921142501-181ce0d877f6 h1:2ncG/LajxmrclaZH+ppVi02rQxz4eXYJzGHdFN4Y9UA=
google.golang.org/genproto v0.0.0-20210921142501-181ce0d877f6/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=

@ -7,11 +7,11 @@ import (
"time"
cortex_distributor "github.com/cortexproject/cortex/pkg/distributor"
"github.com/cortexproject/cortex/pkg/ring"
ring_client "github.com/cortexproject/cortex/pkg/ring/client"
"github.com/cortexproject/cortex/pkg/tenant"
util_log "github.com/cortexproject/cortex/pkg/util/log"
"github.com/grafana/dskit/limiter"
"github.com/grafana/dskit/ring"
ring_client "github.com/grafana/dskit/ring/client"
"github.com/grafana/dskit/services"
lru "github.com/hashicorp/golang-lru"
"github.com/opentracing/opentracing-go"
@ -99,7 +99,7 @@ func New(cfg Config, clientCfg client.Config, configs *runtime.TenantConfigs, in
if overrides.IngestionRateStrategy() == validation.GlobalIngestionRateStrategy {
var err error
distributorsRing, err = ring.NewLifecycler(cfg.DistributorRing.ToLifecyclerConfig(), nil, "distributor", ring.DistributorRingKey, false, registerer)
distributorsRing, err = ring.NewLifecycler(cfg.DistributorRing.ToLifecyclerConfig(), nil, "distributor", ring.DistributorRingKey, false, util_log.Logger, prometheus.WrapRegistererWithPrefix("cortex_", registerer))
if err != nil {
return nil, err
}

@ -11,13 +11,13 @@ import (
"testing"
"time"
"github.com/cortexproject/cortex/pkg/ring"
ring_client "github.com/cortexproject/cortex/pkg/ring/client"
"github.com/cortexproject/cortex/pkg/util/test"
"github.com/go-kit/log"
"github.com/grafana/dskit/flagext"
"github.com/grafana/dskit/kv"
"github.com/grafana/dskit/kv/consul"
"github.com/grafana/dskit/ring"
ring_client "github.com/grafana/dskit/ring/client"
"github.com/grafana/dskit/services"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/model"

@ -10,11 +10,11 @@ import (
"testing"
"time"
"github.com/cortexproject/cortex/pkg/ring"
"github.com/cortexproject/cortex/pkg/tenant"
gokitlog "github.com/go-kit/log"
"github.com/grafana/dskit/flagext"
"github.com/grafana/dskit/kv"
"github.com/grafana/dskit/ring"
"github.com/grafana/dskit/services"
"github.com/prometheus/common/model"
"github.com/prometheus/prometheus/pkg/labels"

@ -9,11 +9,11 @@ import (
"sync"
"time"
"github.com/cortexproject/cortex/pkg/ring"
"github.com/cortexproject/cortex/pkg/tenant"
"github.com/cortexproject/cortex/pkg/util"
util_log "github.com/cortexproject/cortex/pkg/util/log"
"github.com/go-kit/log/level"
"github.com/grafana/dskit/ring"
"github.com/grafana/dskit/services"
"github.com/pkg/errors"
"github.com/prometheus/client_golang/prometheus"
@ -218,7 +218,7 @@ func New(cfg Config, clientConfig client.Config, store ChunkStore, limits *valid
}
i.wal = wal
i.lifecycler, err = ring.NewLifecycler(cfg.LifecyclerConfig, i, "ingester", ring.IngesterRingKey, !cfg.WAL.Enabled || cfg.WAL.FlushOnShutdown, registerer)
i.lifecycler, err = ring.NewLifecycler(cfg.LifecyclerConfig, i, "ingester", ring.IngesterRingKey, !cfg.WAL.Enabled || cfg.WAL.FlushOnShutdown, util_log.Logger, prometheus.WrapRegistererWithPrefix("cortex_", registerer))
if err != nil {
return nil, err
}

@ -6,10 +6,10 @@ import (
"os"
"time"
"github.com/cortexproject/cortex/pkg/ring"
util_log "github.com/cortexproject/cortex/pkg/util/log"
"github.com/go-kit/log/level"
"github.com/grafana/dskit/backoff"
"github.com/grafana/dskit/ring"
"github.com/pkg/errors"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"

@ -8,11 +8,11 @@ import (
"testing"
"time"
"github.com/cortexproject/cortex/pkg/ring"
util_log "github.com/cortexproject/cortex/pkg/util/log"
gokitlog "github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/grafana/dskit/kv"
"github.com/grafana/dskit/ring"
"github.com/grafana/dskit/services"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

@ -8,7 +8,6 @@ import (
"net/http"
cortex_tripper "github.com/cortexproject/cortex/pkg/querier/queryrange"
"github.com/cortexproject/cortex/pkg/ring"
cortex_ruler "github.com/cortexproject/cortex/pkg/ruler"
"github.com/cortexproject/cortex/pkg/ruler/rulestore"
"github.com/cortexproject/cortex/pkg/util"
@ -20,6 +19,7 @@ import (
"github.com/grafana/dskit/grpcutil"
"github.com/grafana/dskit/kv/memberlist"
"github.com/grafana/dskit/modules"
"github.com/grafana/dskit/ring"
"github.com/grafana/dskit/runtimeconfig"
"github.com/grafana/dskit/services"
"github.com/pkg/errors"

@ -14,13 +14,13 @@ import (
"github.com/cortexproject/cortex/pkg/cortex"
"github.com/cortexproject/cortex/pkg/frontend/v1/frontendv1pb"
"github.com/cortexproject/cortex/pkg/frontend/v2/frontendv2pb"
"github.com/cortexproject/cortex/pkg/ring"
cortex_ruler "github.com/cortexproject/cortex/pkg/ruler"
"github.com/cortexproject/cortex/pkg/scheduler/schedulerpb"
util_log "github.com/cortexproject/cortex/pkg/util/log"
"github.com/go-kit/log/level"
"github.com/grafana/dskit/kv/codec"
"github.com/grafana/dskit/kv/memberlist"
"github.com/grafana/dskit/ring"
"github.com/grafana/dskit/runtimeconfig"
"github.com/grafana/dskit/services"
"github.com/prometheus/client_golang/prometheus"
@ -128,11 +128,10 @@ func (t *Loki) initServer() (services.Service, error) {
func (t *Loki) initRing() (_ services.Service, err error) {
t.Cfg.Ingester.LifecyclerConfig.RingConfig.KVStore.Multi.ConfigProvider = multiClientRuntimeConfigChannel(t.runtimeConfig)
t.Cfg.Ingester.LifecyclerConfig.RingConfig.KVStore.MemberlistKV = t.MemberlistKV.GetMemberlistKV
t.ring, err = ring.New(t.Cfg.Ingester.LifecyclerConfig.RingConfig, "ingester", ring.IngesterRingKey, prometheus.DefaultRegisterer)
t.ring, err = ring.New(t.Cfg.Ingester.LifecyclerConfig.RingConfig, "ingester", ring.IngesterRingKey, util_log.Logger, prometheus.DefaultRegisterer)
if err != nil {
return
}
prometheus.MustRegister(t.ring)
t.Server.HTTP.Path("/ring").Methods("GET", "POST").Handler(t.ring)
return t.ring, nil
}

@ -4,9 +4,9 @@ import (
"flag"
"net/http"
"github.com/cortexproject/cortex/pkg/ring"
"github.com/cortexproject/cortex/pkg/util"
"github.com/go-kit/log"
"github.com/grafana/dskit/ring"
"github.com/pkg/errors"
"github.com/prometheus/client_golang/prometheus"

@ -11,12 +11,12 @@ import (
"github.com/cortexproject/cortex/pkg/frontend/v2/frontendv2pb"
"github.com/cortexproject/cortex/pkg/querier/stats"
"github.com/cortexproject/cortex/pkg/ring"
"github.com/cortexproject/cortex/pkg/tenant"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/grafana/dskit/flagext"
"github.com/grafana/dskit/grpcclient"
"github.com/grafana/dskit/ring"
"github.com/grafana/dskit/services"
"github.com/opentracing/opentracing-go"
"github.com/pkg/errors"

@ -7,12 +7,12 @@ import (
"time"
"github.com/cortexproject/cortex/pkg/frontend/v2/frontendv2pb"
"github.com/cortexproject/cortex/pkg/ring"
"github.com/cortexproject/cortex/pkg/scheduler/schedulerpb"
"github.com/cortexproject/cortex/pkg/util"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/grafana/dskit/backoff"
"github.com/grafana/dskit/ring"
"github.com/grafana/dskit/services"
"github.com/pkg/errors"
"github.com/weaveworks/common/httpgrpc"

@ -7,9 +7,9 @@ import (
"time"
cortex_distributor "github.com/cortexproject/cortex/pkg/distributor"
"github.com/cortexproject/cortex/pkg/ring"
ring_client "github.com/cortexproject/cortex/pkg/ring/client"
util_log "github.com/cortexproject/cortex/pkg/util/log"
"github.com/grafana/dskit/ring"
ring_client "github.com/grafana/dskit/ring/client"
"github.com/grafana/dskit/services"
"github.com/pkg/errors"
"github.com/prometheus/common/model"

@ -5,7 +5,7 @@ import (
"testing"
"time"
"github.com/cortexproject/cortex/pkg/ring"
"github.com/grafana/dskit/ring"
"github.com/prometheus/prometheus/pkg/labels"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"

@ -7,9 +7,9 @@ import (
"time"
"github.com/cortexproject/cortex/pkg/distributor"
"github.com/cortexproject/cortex/pkg/ring"
ring_client "github.com/cortexproject/cortex/pkg/ring/client"
"github.com/grafana/dskit/grpcclient"
"github.com/grafana/dskit/ring"
ring_client "github.com/grafana/dskit/ring/client"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/model"
"github.com/prometheus/prometheus/pkg/labels"

@ -8,9 +8,9 @@ import (
"testing"
"time"
"github.com/cortexproject/cortex/pkg/ring"
ring_client "github.com/cortexproject/cortex/pkg/ring/client"
"github.com/grafana/dskit/flagext"
"github.com/grafana/dskit/ring"
ring_client "github.com/grafana/dskit/ring/client"
"github.com/prometheus/common/model"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"

@ -9,7 +9,6 @@ import (
"github.com/cortexproject/cortex/pkg/frontend/v2/frontendv2pb"
querier_stats "github.com/cortexproject/cortex/pkg/querier/stats"
"github.com/cortexproject/cortex/pkg/ring/client"
"github.com/cortexproject/cortex/pkg/scheduler/schedulerpb"
util_log "github.com/cortexproject/cortex/pkg/util/log"
"github.com/go-kit/log"
@ -17,6 +16,7 @@ import (
"github.com/grafana/dskit/backoff"
"github.com/grafana/dskit/grpcclient"
dskit_middleware "github.com/grafana/dskit/middleware"
"github.com/grafana/dskit/ring/client"
"github.com/grafana/dskit/services"
otgrpc "github.com/opentracing-contrib/go-grpc"
"github.com/opentracing/opentracing-go"

@ -7,11 +7,11 @@ import (
"sync"
"time"
"github.com/cortexproject/cortex/pkg/ring"
"github.com/cortexproject/cortex/pkg/util"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/grafana/dskit/grpcclient"
"github.com/grafana/dskit/ring"
"github.com/grafana/dskit/services"
"github.com/pkg/errors"
"github.com/prometheus/client_golang/prometheus"

@ -4,10 +4,10 @@ import (
"fmt"
"net/http"
"github.com/cortexproject/cortex/pkg/ring"
util_log "github.com/cortexproject/cortex/pkg/util/log"
"github.com/go-kit/log/level"
"github.com/gorilla/mux"
"github.com/grafana/dskit/ring"
"github.com/grafana/dskit/services"
"github.com/opentracing-contrib/go-stdlib/nethttp"
"github.com/opentracing/opentracing-go"

@ -8,8 +8,9 @@ import (
"sync"
"time"
util_log "github.com/cortexproject/cortex/pkg/util/log"
"github.com/cortexproject/cortex/pkg/frontend/v2/frontendv2pb"
"github.com/cortexproject/cortex/pkg/ring"
"github.com/cortexproject/cortex/pkg/scheduler/queue"
"github.com/cortexproject/cortex/pkg/scheduler/schedulerpb"
"github.com/cortexproject/cortex/pkg/tenant"
@ -19,6 +20,7 @@ import (
"github.com/go-kit/log/level"
"github.com/grafana/dskit/grpcclient"
"github.com/grafana/dskit/kv"
"github.com/grafana/dskit/ring"
"github.com/grafana/dskit/services"
otgrpc "github.com/opentracing-contrib/go-grpc"
"github.com/opentracing/opentracing-go"
@ -189,7 +191,7 @@ func NewScheduler(cfg Config, limits Limits, log log.Logger, registerer promethe
if err != nil {
return nil, errors.Wrap(err, "create KV store client")
}
lifecyclerCfg, err := cfg.SchedulerRing.ToLifecyclerConfig(ringNumTokens)
lifecyclerCfg, err := cfg.SchedulerRing.ToLifecyclerConfig(ringNumTokens, log)
if err != nil {
return nil, errors.Wrap(err, "invalid ring lifecycler config")
}
@ -207,14 +209,11 @@ func NewScheduler(cfg Config, limits Limits, log log.Logger, registerer promethe
}
ringCfg := cfg.SchedulerRing.ToRingConfig(ringReplicationFactor)
s.ring, err = ring.NewWithStoreClientAndStrategy(ringCfg, ringNameForServer, ringKey, ringStore, ring.NewIgnoreUnhealthyInstancesReplicationStrategy())
s.ring, err = ring.NewWithStoreClientAndStrategy(ringCfg, ringNameForServer, ringKey, ringStore, ring.NewIgnoreUnhealthyInstancesReplicationStrategy(), prometheus.WrapRegistererWithPrefix("cortex_", registerer), util_log.Logger)
if err != nil {
return nil, errors.Wrap(err, "create ring client")
}
if registerer != nil {
registerer.MustRegister(s.ring)
}
svcs = append(svcs, s.ringLifecycler, s.ring)
} else {
// Always run if no scheduler ring is being used.

@ -9,10 +9,10 @@ import (
"sync"
"time"
"github.com/cortexproject/cortex/pkg/ring"
util_log "github.com/cortexproject/cortex/pkg/util/log"
"github.com/go-kit/log/level"
"github.com/grafana/dskit/kv"
"github.com/grafana/dskit/ring"
"github.com/grafana/dskit/services"
"github.com/pkg/errors"
"github.com/prometheus/client_golang/prometheus"
@ -131,7 +131,7 @@ func NewCompactor(cfg Config, storageConfig storage.Config, schemaConfig loki_st
if err != nil {
return nil, errors.Wrap(err, "create KV store client")
}
lifecyclerCfg, err := cfg.CompactorRing.ToLifecyclerConfig(ringNumTokens)
lifecyclerCfg, err := cfg.CompactorRing.ToLifecyclerConfig(ringNumTokens, util_log.Logger)
if err != nil {
return nil, errors.Wrap(err, "invalid ring lifecycler config")
}
@ -149,15 +149,11 @@ func NewCompactor(cfg Config, storageConfig storage.Config, schemaConfig loki_st
}
ringCfg := cfg.CompactorRing.ToRingConfig(ringReplicationFactor)
compactor.ring, err = ring.NewWithStoreClientAndStrategy(ringCfg, ringNameForServer, ringKey, ringStore, ring.NewIgnoreUnhealthyInstancesReplicationStrategy())
compactor.ring, err = ring.NewWithStoreClientAndStrategy(ringCfg, ringNameForServer, ringKey, ringStore, ring.NewIgnoreUnhealthyInstancesReplicationStrategy(), prometheus.WrapRegistererWithPrefix("cortex_", r), util_log.Logger)
if err != nil {
return nil, errors.Wrap(err, "create ring client")
}
if r != nil {
r.MustRegister(compactor.ring)
}
compactor.subservices, err = services.NewManager(compactor.ringLifecycler, compactor.ring)
if err != nil {
return nil, err

@ -3,7 +3,7 @@ package util
import (
"hash/fnv"
"github.com/cortexproject/cortex/pkg/ring"
"github.com/grafana/dskit/ring"
)
// TokenFor generates a token used for finding ingesters from ring

@ -6,12 +6,14 @@ import (
"os"
"time"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/grafana/dskit/flagext"
"github.com/grafana/dskit/kv"
"github.com/cortexproject/cortex/pkg/ring"
util_log "github.com/cortexproject/cortex/pkg/util/log"
"github.com/grafana/dskit/ring"
)
// RingConfig masks the ring lifecycler config which contains
@ -64,8 +66,8 @@ func (cfg *RingConfig) RegisterFlagsWithPrefix(flagsPrefix, storePrefix string,
}
// ToLifecyclerConfig returns a LifecyclerConfig based on the compactor ring config.
func (cfg *RingConfig) ToLifecyclerConfig(numTokens int) (ring.BasicLifecyclerConfig, error) {
instanceAddr, err := ring.GetInstanceAddr(cfg.InstanceAddr, cfg.InstanceInterfaceNames)
func (cfg *RingConfig) ToLifecyclerConfig(numTokens int, logger log.Logger) (ring.BasicLifecyclerConfig, error) {
instanceAddr, err := ring.GetInstanceAddr(cfg.InstanceAddr, cfg.InstanceInterfaceNames, logger)
if err != nil {
return ring.BasicLifecyclerConfig{}, err
}

@ -5,10 +5,10 @@ import (
"fmt"
"time"
"github.com/cortexproject/cortex/pkg/ring"
"github.com/cortexproject/cortex/pkg/util"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/grafana/dskit/ring"
"github.com/grafana/dskit/services"
)

@ -55,6 +55,10 @@ type IntervalMetrics struct {
// Samples maps the key to an AggregateSample,
// which has the rolled up view of a sample
Samples map[string]SampledValue
// done is closed when this interval has ended, and a new IntervalMetrics
// has been created to receive any future metrics.
done chan struct{}
}
// NewIntervalMetrics creates a new IntervalMetrics for a given interval
@ -65,6 +69,7 @@ func NewIntervalMetrics(intv time.Time) *IntervalMetrics {
Points: make(map[string][]float32),
Counters: make(map[string]SampledValue),
Samples: make(map[string]SampledValue),
done: make(chan struct{}),
}
}
@ -245,6 +250,8 @@ func (i *InmemSink) Data() []*IntervalMetrics {
copyCurrent := intervals[n-1]
current.RLock()
*copyCurrent = *current
// RWMutex is not safe to copy, so create a new instance on the copy
copyCurrent.RWMutex = sync.RWMutex{}
copyCurrent.Gauges = make(map[string]GaugeValue, len(current.Gauges))
for k, v := range current.Gauges {
@ -268,33 +275,39 @@ func (i *InmemSink) Data() []*IntervalMetrics {
return intervals
}
func (i *InmemSink) getExistingInterval(intv time.Time) *IntervalMetrics {
i.intervalLock.RLock()
defer i.intervalLock.RUnlock()
// getInterval returns the current interval. A new interval is created if no
// previous interval exists, or if the current time is beyond the window for the
// current interval.
func (i *InmemSink) getInterval() *IntervalMetrics {
intv := time.Now().Truncate(i.interval)
// Attempt to return the existing interval first, because it only requires
// a read lock.
i.intervalLock.RLock()
n := len(i.intervals)
if n > 0 && i.intervals[n-1].Interval == intv {
defer i.intervalLock.RUnlock()
return i.intervals[n-1]
}
return nil
}
i.intervalLock.RUnlock()
func (i *InmemSink) createInterval(intv time.Time) *IntervalMetrics {
i.intervalLock.Lock()
defer i.intervalLock.Unlock()
// Check for an existing interval
n := len(i.intervals)
// Re-check for an existing interval now that the lock is re-acquired.
n = len(i.intervals)
if n > 0 && i.intervals[n-1].Interval == intv {
return i.intervals[n-1]
}
// Add the current interval
current := NewIntervalMetrics(intv)
i.intervals = append(i.intervals, current)
n++
if n > 0 {
close(i.intervals[n-1].done)
}
// Truncate the intervals if they are too long
n++
// Prune old intervals if the count exceeds the max.
if n >= i.maxIntervals {
copy(i.intervals[0:], i.intervals[n-i.maxIntervals:])
i.intervals = i.intervals[:i.maxIntervals]
@ -302,15 +315,6 @@ func (i *InmemSink) createInterval(intv time.Time) *IntervalMetrics {
return current
}
// getInterval returns the current interval to write to
func (i *InmemSink) getInterval() *IntervalMetrics {
intv := time.Now().Truncate(i.interval)
if m := i.getExistingInterval(intv); m != nil {
return m
}
return i.createInterval(intv)
}
// Flattens the key for formatting, removes spaces
func (i *InmemSink) flattenKey(parts []string) string {
buf := &bytes.Buffer{}

@ -1,6 +1,7 @@
package metrics
import (
"context"
"fmt"
"net/http"
"sort"
@ -68,6 +69,10 @@ func (i *InmemSink) DisplayMetrics(resp http.ResponseWriter, req *http.Request)
interval = data[n-2]
}
return newMetricSummaryFromInterval(interval), nil
}
func newMetricSummaryFromInterval(interval *IntervalMetrics) MetricsSummary {
interval.RLock()
defer interval.RUnlock()
@ -103,7 +108,7 @@ func (i *InmemSink) DisplayMetrics(resp http.ResponseWriter, req *http.Request)
summary.Counters = formatSamples(interval.Counters)
summary.Samples = formatSamples(interval.Samples)
return summary, nil
return summary
}
func formatSamples(source map[string]SampledValue) []SampledValue {
@ -129,3 +134,29 @@ func formatSamples(source map[string]SampledValue) []SampledValue {
return output
}
type Encoder interface {
Encode(interface{}) error
}
// Stream writes metrics using encoder.Encode each time an interval ends. Runs
// until the request context is cancelled, or the encoder returns an error.
// The caller is responsible for logging any errors from encoder.
func (i *InmemSink) Stream(ctx context.Context, encoder Encoder) {
interval := i.getInterval()
for {
select {
case <-interval.done:
summary := newMetricSummaryFromInterval(interval)
if err := encoder.Encode(summary); err != nil {
return
}
// update interval to the next one
interval = i.getInterval()
case <-ctx.Done():
return
}
}
}

@ -5,7 +5,6 @@ package prometheus
import (
"fmt"
"log"
"math"
"regexp"
"strings"
"sync"
@ -31,17 +30,16 @@ type PrometheusOpts struct {
Expiration time.Duration
Registerer prometheus.Registerer
// Gauges, Summaries, and Counters allow us to pre-declare metrics by giving their Name, Help, and ConstLabels to
// the PrometheusSink when it is created. Metrics declared in this way will be initialized at zero and will not be
// deleted when their expiry is reached.
// - Gauges and Summaries will be set to NaN when they expire.
// - Counters continue to Collect their last known value.
// Ex:
// PrometheusOpts{
// Gauges, Summaries, and Counters allow us to pre-declare metrics by giving
// their Name, Help, and ConstLabels to the PrometheusSink when it is created.
// Metrics declared in this way will be initialized at zero and will not be
// deleted or altered when their expiry is reached.
//
// Ex: PrometheusOpts{
// Expiration: 10 * time.Second,
// Gauges: []GaugeDefinition{
// {
// Name: []string{ "application", "component", "measurement"},
// Name: []string{ "application", "component", "measurement"},
// Help: "application_component_measurement provides an example of how to declare static metrics",
// ConstLabels: []metrics.Label{ { Name: "my_label", Value: "does_not_change" }, },
// },
@ -139,21 +137,24 @@ func (p *PrometheusSink) Describe(c chan<- *prometheus.Desc) {
// logic to clean up ephemeral metrics if their value haven't been set for a
// duration exceeding our allowed expiration time.
func (p *PrometheusSink) Collect(c chan<- prometheus.Metric) {
p.collectAtTime(c, time.Now())
}
// collectAtTime allows internal testing of the expiry based logic here without
// mocking clocks or making tests timing sensitive.
func (p *PrometheusSink) collectAtTime(c chan<- prometheus.Metric, t time.Time) {
expire := p.expiration != 0
now := time.Now()
p.gauges.Range(func(k, v interface{}) bool {
if v == nil {
return true
}
g := v.(*gauge)
lastUpdate := g.updatedAt
if expire && lastUpdate.Add(p.expiration).Before(now) {
if expire && lastUpdate.Add(p.expiration).Before(t) {
if g.canDelete {
p.gauges.Delete(k)
return true
}
// We have not observed the gauge this interval so we don't know its value.
g.Set(math.NaN())
}
g.Collect(c)
return true
@ -164,13 +165,11 @@ func (p *PrometheusSink) Collect(c chan<- prometheus.Metric) {
}
s := v.(*summary)
lastUpdate := s.updatedAt
if expire && lastUpdate.Add(p.expiration).Before(now) {
if expire && lastUpdate.Add(p.expiration).Before(t) {
if s.canDelete {
p.summaries.Delete(k)
return true
}
// We have observed nothing in this interval.
s.Observe(math.NaN())
}
s.Collect(c)
return true
@ -181,12 +180,11 @@ func (p *PrometheusSink) Collect(c chan<- prometheus.Metric) {
}
count := v.(*counter)
lastUpdate := count.updatedAt
if expire && lastUpdate.Add(p.expiration).Before(now) {
if expire && lastUpdate.Add(p.expiration).Before(t) {
if count.canDelete {
p.counters.Delete(k)
return true
}
// Counters remain at their previous value when not observed, so we do not set it to NaN.
}
count.Collect(c)
return true

@ -53,7 +53,7 @@ var LogHTTPRequestHandler = request.NamedHandler{
}
func logRequest(r *request.Request) {
if !r.Config.LogLevel.AtLeast(aws.LogDebug) {
if !r.Config.LogLevel.AtLeast(aws.LogDebug) || r.Config.Logger == nil {
return
}
@ -94,6 +94,10 @@ var LogHTTPRequestHeaderHandler = request.NamedHandler{
}
func logRequestHeader(r *request.Request) {
if !r.Config.LogLevel.AtLeast(aws.LogDebug) || r.Config.Logger == nil {
return
}
b, err := httputil.DumpRequestOut(r.HTTPRequest, false)
if err != nil {
r.Config.Logger.Log(fmt.Sprintf(logReqErrMsg,
@ -124,7 +128,7 @@ var LogHTTPResponseHandler = request.NamedHandler{
}
func logResponse(r *request.Request) {
if !r.Config.LogLevel.AtLeast(aws.LogDebug) {
if !r.Config.LogLevel.AtLeast(aws.LogDebug) || r.Config.Logger == nil {
return
}
@ -186,7 +190,7 @@ var LogHTTPResponseHeaderHandler = request.NamedHandler{
}
func logResponseHeader(r *request.Request) {
if r.Config.Logger == nil {
if !r.Config.LogLevel.AtLeast(aws.LogDebug) || r.Config.Logger == nil {
return
}

@ -1148,6 +1148,14 @@ var awsPartition = partition{
"us-west-2": endpoint{},
},
},
"braket": service{
Endpoints: endpoints{
"us-east-1": endpoint{},
"us-west-1": endpoint{},
"us-west-2": endpoint{},
},
},
"budgets": service{
PartitionEndpoint: "aws-global",
IsRegionalized: boxedFalse,
@ -1473,6 +1481,7 @@ var awsPartition = partition{
"codecommit": service{
Endpoints: endpoints{
"af-south-1": endpoint{},
"ap-east-1": endpoint{},
"ap-northeast-1": endpoint{},
"ap-northeast-2": endpoint{},
@ -4117,6 +4126,27 @@ var awsPartition = partition{
"us-west-2": endpoint{},
},
},
"kafkaconnect": service{
Endpoints: endpoints{
"ap-northeast-1": endpoint{},
"ap-northeast-2": endpoint{},
"ap-south-1": endpoint{},
"ap-southeast-1": endpoint{},
"ap-southeast-2": endpoint{},
"ca-central-1": endpoint{},
"eu-central-1": endpoint{},
"eu-north-1": endpoint{},
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
"us-west-1": endpoint{},
"us-west-2": endpoint{},
},
},
"kinesis": service{
Endpoints: endpoints{
@ -4244,6 +4274,7 @@ var awsPartition = partition{
"ap-east-1": endpoint{},
"ap-northeast-1": endpoint{},
"ap-northeast-2": endpoint{},
"ap-northeast-3": endpoint{},
"ap-south-1": endpoint{},
"ap-southeast-1": endpoint{},
"ap-southeast-2": endpoint{},
@ -4697,6 +4728,26 @@ var awsPartition = partition{
"us-west-2": endpoint{},
},
},
"mediapackage-vod": service{
Endpoints: endpoints{
"ap-northeast-1": endpoint{},
"ap-northeast-2": endpoint{},
"ap-south-1": endpoint{},
"ap-southeast-1": endpoint{},
"ap-southeast-2": endpoint{},
"eu-central-1": endpoint{},
"eu-north-1": endpoint{},
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
"us-west-1": endpoint{},
"us-west-2": endpoint{},
},
},
"mediastore": service{
Endpoints: endpoints{
@ -4771,6 +4822,20 @@ var awsPartition = partition{
"us-east-1": endpoint{},
},
},
"models-v2-lex": service{
Endpoints: endpoints{
"ap-northeast-1": endpoint{},
"ap-southeast-1": endpoint{},
"ap-southeast-2": endpoint{},
"ca-central-1": endpoint{},
"eu-central-1": endpoint{},
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"us-east-1": endpoint{},
"us-west-2": endpoint{},
},
},
"models.lex": service{
Defaults: endpoint{
CredentialScope: credentialScope{
@ -5024,6 +5089,62 @@ var awsPartition = partition{
},
},
},
"network-firewall": service{
Endpoints: endpoints{
"af-south-1": endpoint{},
"ap-east-1": endpoint{},
"ap-northeast-1": endpoint{},
"ap-northeast-2": endpoint{},
"ap-northeast-3": endpoint{},
"ap-south-1": endpoint{},
"ap-southeast-1": endpoint{},
"ap-southeast-2": endpoint{},
"ca-central-1": endpoint{},
"eu-central-1": endpoint{},
"eu-north-1": endpoint{},
"eu-south-1": endpoint{},
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"fips-ca-central-1": endpoint{
Hostname: "network-firewall-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
},
"fips-us-east-1": endpoint{
Hostname: "network-firewall-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
"fips-us-east-2": endpoint{
Hostname: "network-firewall-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
},
"fips-us-west-1": endpoint{
Hostname: "network-firewall-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
},
"fips-us-west-2": endpoint{
Hostname: "network-firewall-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
"us-west-1": endpoint{},
"us-west-2": endpoint{},
},
},
"oidc": service{
Endpoints: endpoints{
@ -5789,6 +5910,20 @@ var awsPartition = partition{
"us-west-2": endpoint{},
},
},
"runtime-v2-lex": service{
Endpoints: endpoints{
"ap-northeast-1": endpoint{},
"ap-southeast-1": endpoint{},
"ap-southeast-2": endpoint{},
"ca-central-1": endpoint{},
"eu-central-1": endpoint{},
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"us-east-1": endpoint{},
"us-west-2": endpoint{},
},
},
"runtime.lex": service{
Defaults: endpoint{
CredentialScope: credentialScope{
@ -7339,9 +7474,33 @@ var awsPartition = partition{
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
"us-west-2": endpoint{},
"transcribestreaming-fips-ca-central-1": endpoint{
Hostname: "transcribestreaming-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
},
"transcribestreaming-fips-us-east-1": endpoint{
Hostname: "transcribestreaming-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
"transcribestreaming-fips-us-east-2": endpoint{
Hostname: "transcribestreaming-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
},
"transcribestreaming-fips-us-west-2": endpoint{
Hostname: "transcribestreaming-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
"us-west-2": endpoint{},
},
},
"transfer": service{
@ -10031,6 +10190,36 @@ var awsusgovPartition = partition{
},
},
},
"network-firewall": service{
Endpoints: endpoints{
"fips-us-gov-east-1": endpoint{
Hostname: "network-firewall-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
},
"fips-us-gov-west-1": endpoint{
Hostname: "network-firewall-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
"us-gov-east-1": endpoint{},
"us-gov-west-1": endpoint{},
},
},
"oidc": service{
Endpoints: endpoints{
"us-gov-west-1": endpoint{
Hostname: "oidc.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
},
},
"organizations": service{
PartitionEndpoint: "aws-us-gov-global",
IsRegionalized: boxedFalse,
@ -10414,6 +10603,19 @@ var awsusgovPartition = partition{
"us-gov-west-1": endpoint{},
},
},
"servicediscovery": service{
Endpoints: endpoints{
"servicediscovery-fips": endpoint{
Hostname: "servicediscovery-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
"us-gov-east-1": endpoint{},
"us-gov-west-1": endpoint{},
},
},
"servicequotas": service{
Defaults: endpoint{
Protocols: []string{"https"},

@ -5,4 +5,4 @@ package aws
const SDKName = "aws-sdk-go"
// SDKVersion is the version of this SDK
const SDKVersion = "1.40.37"
const SDKVersion = "1.40.45"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -513,12 +513,20 @@ type AccountInfo struct {
EmailAddress *string `locationName:"emailAddress" min:"1" type:"string"`
}
// String returns the string representation
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s AccountInfo) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s AccountInfo) GoString() string {
return s.String()
}
@ -548,6 +556,10 @@ type GetRoleCredentialsInput struct {
// (https://docs.aws.amazon.com/singlesignon/latest/OIDCAPIReference/API_CreateToken.html)
// in the AWS SSO OIDC API Reference Guide.
//
// AccessToken is a sensitive parameter and its value will be
// replaced with "sensitive" in string returned by GetRoleCredentialsInput's
// String and GoString methods.
//
// AccessToken is a required field
AccessToken *string `location:"header" locationName:"x-amz-sso_bearer_token" type:"string" required:"true" sensitive:"true"`
@ -562,12 +574,20 @@ type GetRoleCredentialsInput struct {
RoleName *string `location:"querystring" locationName:"role_name" type:"string" required:"true"`
}
// String returns the string representation
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetRoleCredentialsInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetRoleCredentialsInput) GoString() string {
return s.String()
}
@ -616,12 +636,20 @@ type GetRoleCredentialsOutput struct {
RoleCredentials *RoleCredentials `locationName:"roleCredentials" type:"structure"`
}
// String returns the string representation
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetRoleCredentialsOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetRoleCredentialsOutput) GoString() string {
return s.String()
}
@ -641,12 +669,20 @@ type InvalidRequestException struct {
Message_ *string `locationName:"message" type:"string"`
}
// String returns the string representation
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s InvalidRequestException) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s InvalidRequestException) GoString() string {
return s.String()
}
@ -696,6 +732,10 @@ type ListAccountRolesInput struct {
// (https://docs.aws.amazon.com/singlesignon/latest/OIDCAPIReference/API_CreateToken.html)
// in the AWS SSO OIDC API Reference Guide.
//
// AccessToken is a sensitive parameter and its value will be
// replaced with "sensitive" in string returned by ListAccountRolesInput's
// String and GoString methods.
//
// AccessToken is a required field
AccessToken *string `location:"header" locationName:"x-amz-sso_bearer_token" type:"string" required:"true" sensitive:"true"`
@ -712,12 +752,20 @@ type ListAccountRolesInput struct {
NextToken *string `location:"querystring" locationName:"next_token" type:"string"`
}
// String returns the string representation
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ListAccountRolesInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ListAccountRolesInput) GoString() string {
return s.String()
}
@ -776,12 +824,20 @@ type ListAccountRolesOutput struct {
RoleList []*RoleInfo `locationName:"roleList" type:"list"`
}
// String returns the string representation
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ListAccountRolesOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ListAccountRolesOutput) GoString() string {
return s.String()
}
@ -805,6 +861,10 @@ type ListAccountsInput struct {
// (https://docs.aws.amazon.com/singlesignon/latest/OIDCAPIReference/API_CreateToken.html)
// in the AWS SSO OIDC API Reference Guide.
//
// AccessToken is a sensitive parameter and its value will be
// replaced with "sensitive" in string returned by ListAccountsInput's
// String and GoString methods.
//
// AccessToken is a required field
AccessToken *string `location:"header" locationName:"x-amz-sso_bearer_token" type:"string" required:"true" sensitive:"true"`
@ -816,12 +876,20 @@ type ListAccountsInput struct {
NextToken *string `location:"querystring" locationName:"next_token" type:"string"`
}
// String returns the string representation
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ListAccountsInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ListAccountsInput) GoString() string {
return s.String()
}
@ -871,12 +939,20 @@ type ListAccountsOutput struct {
NextToken *string `locationName:"nextToken" type:"string"`
}
// String returns the string representation
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ListAccountsOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ListAccountsOutput) GoString() string {
return s.String()
}
@ -900,16 +976,28 @@ type LogoutInput struct {
// (https://docs.aws.amazon.com/singlesignon/latest/OIDCAPIReference/API_CreateToken.html)
// in the AWS SSO OIDC API Reference Guide.
//
// AccessToken is a sensitive parameter and its value will be
// replaced with "sensitive" in string returned by LogoutInput's
// String and GoString methods.
//
// AccessToken is a required field
AccessToken *string `location:"header" locationName:"x-amz-sso_bearer_token" type:"string" required:"true" sensitive:"true"`
}
// String returns the string representation
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s LogoutInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s LogoutInput) GoString() string {
return s.String()
}
@ -937,12 +1025,20 @@ type LogoutOutput struct {
_ struct{} `type:"structure"`
}
// String returns the string representation
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s LogoutOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s LogoutOutput) GoString() string {
return s.String()
}
@ -955,12 +1051,20 @@ type ResourceNotFoundException struct {
Message_ *string `locationName:"message" type:"string"`
}
// String returns the string representation
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ResourceNotFoundException) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ResourceNotFoundException) GoString() string {
return s.String()
}
@ -1020,20 +1124,36 @@ type RoleCredentials struct {
// The key that is used to sign the request. For more information, see Using
// Temporary Security Credentials to Request Access to AWS Resources (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html)
// in the AWS IAM User Guide.
//
// SecretAccessKey is a sensitive parameter and its value will be
// replaced with "sensitive" in string returned by RoleCredentials's
// String and GoString methods.
SecretAccessKey *string `locationName:"secretAccessKey" type:"string" sensitive:"true"`
// The token used for temporary credentials. For more information, see Using
// Temporary Security Credentials to Request Access to AWS Resources (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html)
// in the AWS IAM User Guide.
//
// SessionToken is a sensitive parameter and its value will be
// replaced with "sensitive" in string returned by RoleCredentials's
// String and GoString methods.
SessionToken *string `locationName:"sessionToken" type:"string" sensitive:"true"`
}
// String returns the string representation
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s RoleCredentials) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s RoleCredentials) GoString() string {
return s.String()
}
@ -1073,12 +1193,20 @@ type RoleInfo struct {
RoleName *string `locationName:"roleName" type:"string"`
}
// String returns the string representation
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s RoleInfo) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s RoleInfo) GoString() string {
return s.String()
}
@ -1104,12 +1232,20 @@ type TooManyRequestsException struct {
Message_ *string `locationName:"message" type:"string"`
}
// String returns the string representation
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s TooManyRequestsException) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s TooManyRequestsException) GoString() string {
return s.String()
}
@ -1161,12 +1297,20 @@ type UnauthorizedException struct {
Message_ *string `locationName:"message" type:"string"`
}
// String returns the string representation
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s UnauthorizedException) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s UnauthorizedException) GoString() string {
return s.String()
}

@ -1605,12 +1605,20 @@ type AssumeRoleInput struct {
TransitiveTagKeys []*string `type:"list"`
}
// String returns the string representation
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s AssumeRoleInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s AssumeRoleInput) GoString() string {
return s.String()
}
@ -1785,12 +1793,20 @@ type AssumeRoleOutput struct {
SourceIdentity *string `min:"2" type:"string"`
}
// String returns the string representation
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s AssumeRoleOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s AssumeRoleOutput) GoString() string {
return s.String()
}
@ -1917,12 +1933,20 @@ type AssumeRoleWithSAMLInput struct {
SAMLAssertion *string `min:"4" type:"string" required:"true"`
}
// String returns the string representation
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s AssumeRoleWithSAMLInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s AssumeRoleWithSAMLInput) GoString() string {
return s.String()
}
@ -2089,12 +2113,20 @@ type AssumeRoleWithSAMLOutput struct {
SubjectType *string `type:"string"`
}
// String returns the string representation
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s AssumeRoleWithSAMLOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s AssumeRoleWithSAMLOutput) GoString() string {
return s.String()
}
@ -2264,12 +2296,20 @@ type AssumeRoleWithWebIdentityInput struct {
WebIdentityToken *string `min:"4" type:"string" required:"true"`
}
// String returns the string representation
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s AssumeRoleWithWebIdentityInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s AssumeRoleWithWebIdentityInput) GoString() string {
return s.String()
}
@ -2432,12 +2472,20 @@ type AssumeRoleWithWebIdentityOutput struct {
SubjectFromWebIdentityToken *string `min:"6" type:"string"`
}
// String returns the string representation
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s AssumeRoleWithWebIdentityOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s AssumeRoleWithWebIdentityOutput) GoString() string {
return s.String()
}
@ -2505,12 +2553,20 @@ type AssumedRoleUser struct {
AssumedRoleId *string `min:"2" type:"string" required:"true"`
}
// String returns the string representation
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s AssumedRoleUser) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s AssumedRoleUser) GoString() string {
return s.String()
}
@ -2552,12 +2608,20 @@ type Credentials struct {
SessionToken *string `type:"string" required:"true"`
}
// String returns the string representation
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s Credentials) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s Credentials) GoString() string {
return s.String()
}
@ -2595,12 +2659,20 @@ type DecodeAuthorizationMessageInput struct {
EncodedMessage *string `min:"1" type:"string" required:"true"`
}
// String returns the string representation
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DecodeAuthorizationMessageInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DecodeAuthorizationMessageInput) GoString() string {
return s.String()
}
@ -2637,12 +2709,20 @@ type DecodeAuthorizationMessageOutput struct {
DecodedMessage *string `type:"string"`
}
// String returns the string representation
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DecodeAuthorizationMessageOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DecodeAuthorizationMessageOutput) GoString() string {
return s.String()
}
@ -2672,12 +2752,20 @@ type FederatedUser struct {
FederatedUserId *string `min:"2" type:"string" required:"true"`
}
// String returns the string representation
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s FederatedUser) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s FederatedUser) GoString() string {
return s.String()
}
@ -2706,12 +2794,20 @@ type GetAccessKeyInfoInput struct {
AccessKeyId *string `min:"16" type:"string" required:"true"`
}
// String returns the string representation
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetAccessKeyInfoInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetAccessKeyInfoInput) GoString() string {
return s.String()
}
@ -2745,12 +2841,20 @@ type GetAccessKeyInfoOutput struct {
Account *string `type:"string"`
}
// String returns the string representation
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetAccessKeyInfoOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetAccessKeyInfoOutput) GoString() string {
return s.String()
}
@ -2765,12 +2869,20 @@ type GetCallerIdentityInput struct {
_ struct{} `type:"structure"`
}
// String returns the string representation
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetCallerIdentityInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetCallerIdentityInput) GoString() string {
return s.String()
}
@ -2794,12 +2906,20 @@ type GetCallerIdentityOutput struct {
UserId *string `type:"string"`
}
// String returns the string representation
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetCallerIdentityOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetCallerIdentityOutput) GoString() string {
return s.String()
}
@ -2949,12 +3069,20 @@ type GetFederationTokenInput struct {
Tags []*Tag `type:"list"`
}
// String returns the string representation
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetFederationTokenInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetFederationTokenInput) GoString() string {
return s.String()
}
@ -3057,12 +3185,20 @@ type GetFederationTokenOutput struct {
PackedPolicySize *int64 `type:"integer"`
}
// String returns the string representation
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetFederationTokenOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetFederationTokenOutput) GoString() string {
return s.String()
}
@ -3120,12 +3256,20 @@ type GetSessionTokenInput struct {
TokenCode *string `min:"6" type:"string"`
}
// String returns the string representation
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetSessionTokenInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetSessionTokenInput) GoString() string {
return s.String()
}
@ -3181,12 +3325,20 @@ type GetSessionTokenOutput struct {
Credentials *Credentials `type:"structure"`
}
// String returns the string representation
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetSessionTokenOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetSessionTokenOutput) GoString() string {
return s.String()
}
@ -3209,12 +3361,20 @@ type PolicyDescriptorType struct {
Arn *string `locationName:"arn" min:"20" type:"string"`
}
// String returns the string representation
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s PolicyDescriptorType) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s PolicyDescriptorType) GoString() string {
return s.String()
}
@ -3267,12 +3427,20 @@ type Tag struct {
Value *string `type:"string" required:"true"`
}
// String returns the string representation
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s Tag) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s Tag) GoString() string {
return s.String()
}

@ -7,6 +7,7 @@ import (
"github.com/go-kit/log"
"github.com/grafana/dskit/crypto/tls"
"github.com/grafana/dskit/grpcclient"
"github.com/grafana/dskit/ring/client"
"github.com/pkg/errors"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
@ -14,7 +15,6 @@ import (
"google.golang.org/grpc/health/grpc_health_v1"
"github.com/cortexproject/cortex/pkg/alertmanager/alertmanagerpb"
"github.com/cortexproject/cortex/pkg/ring/client"
)
// ClientsPool is the interface used to get the client from the pool for a specified address.

@ -6,11 +6,12 @@ import (
"os"
"time"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/grafana/dskit/flagext"
"github.com/grafana/dskit/kv"
"github.com/grafana/dskit/ring"
"github.com/cortexproject/cortex/pkg/ring"
util_log "github.com/cortexproject/cortex/pkg/util/log"
)
@ -94,8 +95,8 @@ func (cfg *RingConfig) RegisterFlags(f *flag.FlagSet) {
// ToLifecyclerConfig returns a LifecyclerConfig based on the alertmanager
// ring config.
func (cfg *RingConfig) ToLifecyclerConfig() (ring.BasicLifecyclerConfig, error) {
instanceAddr, err := ring.GetInstanceAddr(cfg.InstanceAddr, cfg.InstanceInterfaceNames)
func (cfg *RingConfig) ToLifecyclerConfig(logger log.Logger) (ring.BasicLifecyclerConfig, error) {
instanceAddr, err := ring.GetInstanceAddr(cfg.InstanceAddr, cfg.InstanceInterfaceNames, logger)
if err != nil {
return ring.BasicLifecyclerConfig{}, err
}

@ -12,6 +12,8 @@ import (
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/grafana/dskit/ring"
"github.com/grafana/dskit/ring/client"
"github.com/grafana/dskit/services"
"github.com/opentracing/opentracing-go"
"github.com/pkg/errors"
@ -20,8 +22,6 @@ import (
"github.com/weaveworks/common/user"
"github.com/cortexproject/cortex/pkg/alertmanager/merger"
"github.com/cortexproject/cortex/pkg/ring"
"github.com/cortexproject/cortex/pkg/ring/client"
"github.com/cortexproject/cortex/pkg/tenant"
"github.com/cortexproject/cortex/pkg/util"
util_log "github.com/cortexproject/cortex/pkg/util/log"

@ -1,7 +1,7 @@
package alertmanager
import (
"github.com/cortexproject/cortex/pkg/ring"
"github.com/grafana/dskit/ring"
)
func (r *MultitenantAlertmanager) OnRingInstanceRegister(_ *ring.BasicLifecycler, ringDesc ring.Desc, instanceExists bool, instanceID string, instanceDesc ring.InstanceDesc) (ring.InstanceState, ring.Tokens) {

@ -18,6 +18,8 @@ import (
"github.com/grafana/dskit/concurrency"
"github.com/grafana/dskit/flagext"
"github.com/grafana/dskit/kv"
"github.com/grafana/dskit/ring"
"github.com/grafana/dskit/ring/client"
"github.com/grafana/dskit/services"
"github.com/pkg/errors"
"github.com/prometheus/alertmanager/cluster"
@ -34,8 +36,6 @@ import (
"github.com/cortexproject/cortex/pkg/alertmanager/alertmanagerpb"
"github.com/cortexproject/cortex/pkg/alertmanager/alertspb"
"github.com/cortexproject/cortex/pkg/alertmanager/alertstore"
"github.com/cortexproject/cortex/pkg/ring"
"github.com/cortexproject/cortex/pkg/ring/client"
"github.com/cortexproject/cortex/pkg/tenant"
"github.com/cortexproject/cortex/pkg/util"
util_log "github.com/cortexproject/cortex/pkg/util/log"
@ -398,7 +398,7 @@ func createMultitenantAlertmanager(cfg *MultitenantAlertmanagerConfig, fallbackC
}
if cfg.ShardingEnabled {
lifecyclerCfg, err := am.cfg.ShardingRing.ToLifecyclerConfig()
lifecyclerCfg, err := am.cfg.ShardingRing.ToLifecyclerConfig(am.logger)
if err != nil {
return nil, errors.Wrap(err, "failed to initialize Alertmanager's lifecycler config")
}
@ -409,20 +409,16 @@ func createMultitenantAlertmanager(cfg *MultitenantAlertmanagerConfig, fallbackC
delegate = ring.NewLeaveOnStoppingDelegate(delegate, am.logger)
delegate = ring.NewAutoForgetDelegate(am.cfg.ShardingRing.HeartbeatTimeout*ringAutoForgetUnhealthyPeriods, delegate, am.logger)
am.ringLifecycler, err = ring.NewBasicLifecycler(lifecyclerCfg, RingNameForServer, RingKey, ringStore, delegate, am.logger, am.registry)
am.ringLifecycler, err = ring.NewBasicLifecycler(lifecyclerCfg, RingNameForServer, RingKey, ringStore, delegate, am.logger, prometheus.WrapRegistererWithPrefix("cortex_", am.registry))
if err != nil {
return nil, errors.Wrap(err, "failed to initialize Alertmanager's lifecycler")
}
am.ring, err = ring.NewWithStoreClientAndStrategy(am.cfg.ShardingRing.ToRingConfig(), RingNameForServer, RingKey, ringStore, ring.NewIgnoreUnhealthyInstancesReplicationStrategy())
am.ring, err = ring.NewWithStoreClientAndStrategy(am.cfg.ShardingRing.ToRingConfig(), RingNameForServer, RingKey, ringStore, ring.NewIgnoreUnhealthyInstancesReplicationStrategy(), prometheus.WrapRegistererWithPrefix("cortex_", am.registry), am.logger)
if err != nil {
return nil, errors.Wrap(err, "failed to initialize Alertmanager's ring")
}
if am.registry != nil {
am.registry.MustRegister(am.ring)
}
am.grpcServer = server.NewServer(&handlerForGRPCServer{am: am})
am.alertmanagerClientsPool = newAlertmanagerClientsPool(client.NewRingServiceDiscovery(am.ring), cfg.AlertmanagerClient, logger, am.registry)

@ -12,6 +12,7 @@ import (
"github.com/felixge/fgprof"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/grafana/dskit/ring"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/prometheus/storage"
"github.com/weaveworks/common/middleware"
@ -30,7 +31,6 @@ import (
"github.com/cortexproject/cortex/pkg/frontend/v2/frontendv2pb"
"github.com/cortexproject/cortex/pkg/ingester/client"
"github.com/cortexproject/cortex/pkg/querier"
"github.com/cortexproject/cortex/pkg/ring"
"github.com/cortexproject/cortex/pkg/ruler"
"github.com/cortexproject/cortex/pkg/scheduler"
"github.com/cortexproject/cortex/pkg/scheduler/schedulerpb"

@ -17,6 +17,7 @@ import (
"github.com/go-kit/log/level"
"github.com/grafana/dskit/backoff"
"github.com/grafana/dskit/flagext"
"github.com/grafana/dskit/ring"
"github.com/grafana/dskit/services"
"github.com/pkg/errors"
"github.com/prometheus/client_golang/prometheus"
@ -28,7 +29,6 @@ import (
"github.com/thanos-io/thanos/pkg/compact/downsample"
"github.com/thanos-io/thanos/pkg/objstore"
"github.com/cortexproject/cortex/pkg/ring"
"github.com/cortexproject/cortex/pkg/storage/bucket"
cortex_tsdb "github.com/cortexproject/cortex/pkg/storage/tsdb"
"github.com/cortexproject/cortex/pkg/storage/tsdb/bucketindex"
@ -367,12 +367,12 @@ func (c *Compactor) starting(ctx context.Context) error {
// Initialize the compactors ring if sharding is enabled.
if c.compactorCfg.ShardingEnabled {
lifecyclerCfg := c.compactorCfg.ShardingRing.ToLifecyclerConfig()
c.ringLifecycler, err = ring.NewLifecycler(lifecyclerCfg, ring.NewNoopFlushTransferer(), "compactor", ring.CompactorRingKey, false, c.registerer)
c.ringLifecycler, err = ring.NewLifecycler(lifecyclerCfg, ring.NewNoopFlushTransferer(), "compactor", ring.CompactorRingKey, false, c.logger, prometheus.WrapRegistererWithPrefix("cortex_", c.registerer))
if err != nil {
return errors.Wrap(err, "unable to initialize compactor ring lifecycler")
}
c.ring, err = ring.New(lifecyclerCfg.RingConfig, "compactor", ring.CompactorRingKey, c.registerer)
c.ring, err = ring.New(lifecyclerCfg.RingConfig, "compactor", ring.CompactorRingKey, c.logger, prometheus.WrapRegistererWithPrefix("cortex_", c.registerer))
if err != nil {
return errors.Wrap(err, "unable to initialize compactor ring")
}

@ -8,8 +8,8 @@ import (
"github.com/go-kit/log/level"
"github.com/grafana/dskit/flagext"
"github.com/grafana/dskit/kv"
"github.com/grafana/dskit/ring"
"github.com/cortexproject/cortex/pkg/ring"
util_log "github.com/cortexproject/cortex/pkg/util/log"
)

@ -16,6 +16,7 @@ import (
"github.com/grafana/dskit/grpcutil"
"github.com/grafana/dskit/kv/memberlist"
"github.com/grafana/dskit/modules"
"github.com/grafana/dskit/ring"
"github.com/grafana/dskit/runtimeconfig"
"github.com/grafana/dskit/services"
"github.com/pkg/errors"
@ -50,7 +51,6 @@ import (
"github.com/cortexproject/cortex/pkg/querier/queryrange"
"github.com/cortexproject/cortex/pkg/querier/tenantfederation"
querier_worker "github.com/cortexproject/cortex/pkg/querier/worker"
"github.com/cortexproject/cortex/pkg/ring"
"github.com/cortexproject/cortex/pkg/ruler"
"github.com/cortexproject/cortex/pkg/ruler/rulestore"
"github.com/cortexproject/cortex/pkg/scheduler"

@ -12,6 +12,7 @@ import (
"github.com/grafana/dskit/kv/codec"
"github.com/grafana/dskit/kv/memberlist"
"github.com/grafana/dskit/modules"
"github.com/grafana/dskit/ring"
"github.com/grafana/dskit/runtimeconfig"
"github.com/grafana/dskit/services"
"github.com/opentracing-contrib/go-stdlib/nethttp"
@ -43,7 +44,6 @@ import (
"github.com/cortexproject/cortex/pkg/querier/queryrange"
"github.com/cortexproject/cortex/pkg/querier/tenantfederation"
querier_worker "github.com/cortexproject/cortex/pkg/querier/worker"
"github.com/cortexproject/cortex/pkg/ring"
"github.com/cortexproject/cortex/pkg/ruler"
"github.com/cortexproject/cortex/pkg/scheduler"
"github.com/cortexproject/cortex/pkg/storegateway"
@ -137,11 +137,10 @@ func (t *Cortex) initServer() (services.Service, error) {
func (t *Cortex) initRing() (serv services.Service, err error) {
t.Cfg.Ingester.LifecyclerConfig.RingConfig.KVStore.Multi.ConfigProvider = multiClientRuntimeConfigChannel(t.RuntimeConfig)
t.Ring, err = ring.New(t.Cfg.Ingester.LifecyclerConfig.RingConfig, "ingester", ring.IngesterRingKey, prometheus.DefaultRegisterer)
t.Ring, err = ring.New(t.Cfg.Ingester.LifecyclerConfig.RingConfig, "ingester", ring.IngesterRingKey, util_log.Logger, prometheus.WrapRegistererWithPrefix("cortex_", prometheus.DefaultRegisterer))
if err != nil {
return nil, err
}
prometheus.MustRegister(t.Ring)
t.API.RegisterRing(t.Ring)

@ -12,6 +12,8 @@ import (
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/grafana/dskit/limiter"
"github.com/grafana/dskit/ring"
ring_client "github.com/grafana/dskit/ring/client"
"github.com/grafana/dskit/services"
"github.com/opentracing/opentracing-go"
"github.com/pkg/errors"
@ -29,8 +31,6 @@ import (
"github.com/cortexproject/cortex/pkg/cortexpb"
ingester_client "github.com/cortexproject/cortex/pkg/ingester/client"
"github.com/cortexproject/cortex/pkg/prom1/storage/metric"
"github.com/cortexproject/cortex/pkg/ring"
ring_client "github.com/cortexproject/cortex/pkg/ring/client"
"github.com/cortexproject/cortex/pkg/tenant"
"github.com/cortexproject/cortex/pkg/util"
"github.com/cortexproject/cortex/pkg/util/extract"
@ -211,12 +211,12 @@ func New(cfg Config, clientConfig ingester_client.Config, limits *validation.Ove
if !canJoinDistributorsRing {
ingestionRateStrategy = newInfiniteIngestionRateStrategy()
} else if limits.IngestionRateStrategy() == validation.GlobalIngestionRateStrategy {
distributorsLifeCycler, err = ring.NewLifecycler(cfg.DistributorRing.ToLifecyclerConfig(), nil, "distributor", ring.DistributorRingKey, true, reg)
distributorsLifeCycler, err = ring.NewLifecycler(cfg.DistributorRing.ToLifecyclerConfig(), nil, "distributor", ring.DistributorRingKey, true, log, prometheus.WrapRegistererWithPrefix("cortex_", reg))
if err != nil {
return nil, err
}
distributorsRing, err = ring.New(cfg.DistributorRing.ToRingConfig(), "distributor", ring.DistributorRingKey, reg)
distributorsRing, err = ring.New(cfg.DistributorRing.ToRingConfig(), "distributor", ring.DistributorRingKey, log, prometheus.WrapRegistererWithPrefix("cortex_", reg))
if err != nil {
return nil, errors.Wrap(err, "failed to initialize distributors' ring client")
}

@ -8,8 +8,8 @@ import (
"github.com/go-kit/log/level"
"github.com/grafana/dskit/flagext"
"github.com/grafana/dskit/kv"
"github.com/grafana/dskit/ring"
"github.com/cortexproject/cortex/pkg/ring"
util_log "github.com/cortexproject/cortex/pkg/util/log"
)

@ -5,11 +5,10 @@ import (
"time"
"github.com/go-kit/log"
"github.com/grafana/dskit/ring"
ring_client "github.com/grafana/dskit/ring/client"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"github.com/cortexproject/cortex/pkg/ring"
ring_client "github.com/cortexproject/cortex/pkg/ring/client"
)
var clients = promauto.NewGauge(prometheus.GaugeOpts{

@ -7,6 +7,7 @@ import (
"time"
"github.com/grafana/dskit/grpcutil"
"github.com/grafana/dskit/ring"
"github.com/opentracing/opentracing-go"
"github.com/prometheus/common/model"
"github.com/prometheus/prometheus/pkg/labels"
@ -15,7 +16,6 @@ import (
"github.com/cortexproject/cortex/pkg/cortexpb"
ingester_client "github.com/cortexproject/cortex/pkg/ingester/client"
"github.com/cortexproject/cortex/pkg/querier/stats"
"github.com/cortexproject/cortex/pkg/ring"
"github.com/cortexproject/cortex/pkg/tenant"
"github.com/cortexproject/cortex/pkg/util"
"github.com/cortexproject/cortex/pkg/util/extract"

@ -13,6 +13,7 @@ import (
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/gogo/status"
"github.com/grafana/dskit/ring"
"github.com/grafana/dskit/services"
"github.com/pkg/errors"
"github.com/prometheus/client_golang/prometheus"
@ -27,7 +28,6 @@ import (
cortex_chunk "github.com/cortexproject/cortex/pkg/chunk"
"github.com/cortexproject/cortex/pkg/cortexpb"
"github.com/cortexproject/cortex/pkg/ingester/client"
"github.com/cortexproject/cortex/pkg/ring"
"github.com/cortexproject/cortex/pkg/storage/tsdb"
"github.com/cortexproject/cortex/pkg/tenant"
"github.com/cortexproject/cortex/pkg/util"
@ -266,7 +266,7 @@ func New(cfg Config, clientConfig client.Config, limits *validation.Overrides, c
// During WAL recovery, it will create new user states which requires the limiter.
// Hence initialise the limiter before creating the WAL.
// The '!cfg.WALConfig.WALEnabled' argument says don't flush on shutdown if the WAL is enabled.
i.lifecycler, err = ring.NewLifecycler(cfg.LifecyclerConfig, i, "ingester", ring.IngesterRingKey, !cfg.WALConfig.WALEnabled || cfg.WALConfig.FlushOnShutdown, registerer)
i.lifecycler, err = ring.NewLifecycler(cfg.LifecyclerConfig, i, "ingester", ring.IngesterRingKey, !cfg.WALConfig.WALEnabled || cfg.WALConfig.FlushOnShutdown, logger, prometheus.WrapRegistererWithPrefix("cortex_", registerer))
if err != nil {
return nil, err
}

@ -14,6 +14,7 @@ import (
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/grafana/dskit/concurrency"
"github.com/grafana/dskit/ring"
"github.com/grafana/dskit/services"
"github.com/oklog/ulid"
"github.com/pkg/errors"
@ -35,7 +36,6 @@ import (
"github.com/cortexproject/cortex/pkg/chunk/encoding"
"github.com/cortexproject/cortex/pkg/cortexpb"
"github.com/cortexproject/cortex/pkg/ingester/client"
"github.com/cortexproject/cortex/pkg/ring"
"github.com/cortexproject/cortex/pkg/storage/bucket"
cortex_tsdb "github.com/cortexproject/cortex/pkg/storage/tsdb"
"github.com/cortexproject/cortex/pkg/tenant"
@ -511,7 +511,7 @@ func NewV2(cfg Config, clientConfig client.Config, limits *validation.Overrides,
}, i.getOldestUnshippedBlockMetric)
}
i.lifecycler, err = ring.NewLifecycler(cfg.LifecyclerConfig, i, "ingester", ring.IngesterRingKey, cfg.BlocksStorageConfig.TSDB.FlushBlocksOnShutdown, registerer)
i.lifecycler, err = ring.NewLifecycler(cfg.LifecyclerConfig, i, "ingester", ring.IngesterRingKey, cfg.BlocksStorageConfig.TSDB.FlushBlocksOnShutdown, logger, prometheus.WrapRegistererWithPrefix("cortex_", registerer))
if err != nil {
return nil, err
}

@ -10,6 +10,7 @@ import (
"github.com/go-kit/log/level"
"github.com/grafana/dskit/backoff"
"github.com/grafana/dskit/ring"
"github.com/pkg/errors"
"github.com/prometheus/common/model"
"github.com/weaveworks/common/user"
@ -17,7 +18,6 @@ import (
"github.com/cortexproject/cortex/pkg/chunk/encoding"
"github.com/cortexproject/cortex/pkg/cortexpb"
"github.com/cortexproject/cortex/pkg/ingester/client"
"github.com/cortexproject/cortex/pkg/ring"
)
var (

@ -9,6 +9,7 @@ import (
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/grafana/dskit/ring/client"
"github.com/grafana/dskit/services"
"github.com/oklog/ulid"
"github.com/pkg/errors"
@ -16,7 +17,6 @@ import (
"github.com/thanos-io/thanos/pkg/discovery/dns"
"github.com/thanos-io/thanos/pkg/extprom"
"github.com/cortexproject/cortex/pkg/ring/client"
"github.com/cortexproject/cortex/pkg/util"
)

@ -13,6 +13,7 @@ import (
"github.com/go-kit/log/level"
"github.com/gogo/protobuf/types"
"github.com/grafana/dskit/kv"
"github.com/grafana/dskit/ring"
"github.com/grafana/dskit/services"
"github.com/oklog/ulid"
"github.com/pkg/errors"
@ -32,7 +33,6 @@ import (
"github.com/cortexproject/cortex/pkg/cortexpb"
"github.com/cortexproject/cortex/pkg/querier/series"
"github.com/cortexproject/cortex/pkg/querier/stats"
"github.com/cortexproject/cortex/pkg/ring"
"github.com/cortexproject/cortex/pkg/storage/bucket"
cortex_tsdb "github.com/cortexproject/cortex/pkg/storage/tsdb"
"github.com/cortexproject/cortex/pkg/storage/tsdb/bucketindex"
@ -217,15 +217,11 @@ func NewBlocksStoreQueryableFromConfig(querierCfg Config, gatewayCfg storegatewa
return nil, errors.Wrap(err, "failed to create store-gateway ring backend")
}
storesRing, err := ring.NewWithStoreClientAndStrategy(storesRingCfg, storegateway.RingNameForClient, storegateway.RingKey, storesRingBackend, ring.NewIgnoreUnhealthyInstancesReplicationStrategy())
storesRing, err := ring.NewWithStoreClientAndStrategy(storesRingCfg, storegateway.RingNameForClient, storegateway.RingKey, storesRingBackend, ring.NewIgnoreUnhealthyInstancesReplicationStrategy(), prometheus.WrapRegistererWithPrefix("cortex_", reg), logger)
if err != nil {
return nil, errors.Wrap(err, "failed to create store-gateway ring client")
}
if reg != nil {
reg.MustRegister(storesRing)
}
stores, err = newBlocksStoreReplicationSet(storesRing, gatewayCfg.ShardingStrategy, randomLoadBalancing, limits, querierCfg.StoreGatewayClient, logger, reg)
if err != nil {
return nil, errors.Wrap(err, "failed to create store set")

@ -6,13 +6,13 @@ import (
"math/rand"
"github.com/go-kit/log"
"github.com/grafana/dskit/ring"
"github.com/grafana/dskit/ring/client"
"github.com/grafana/dskit/services"
"github.com/oklog/ulid"
"github.com/pkg/errors"
"github.com/prometheus/client_golang/prometheus"
"github.com/cortexproject/cortex/pkg/ring"
"github.com/cortexproject/cortex/pkg/ring/client"
cortex_tsdb "github.com/cortexproject/cortex/pkg/storage/tsdb"
"github.com/cortexproject/cortex/pkg/storegateway"
"github.com/cortexproject/cortex/pkg/util"

@ -7,13 +7,13 @@ import (
"github.com/go-kit/log"
"github.com/grafana/dskit/crypto/tls"
"github.com/grafana/dskit/grpcclient"
"github.com/grafana/dskit/ring/client"
"github.com/pkg/errors"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"google.golang.org/grpc"
"google.golang.org/grpc/health/grpc_health_v1"
"github.com/cortexproject/cortex/pkg/ring/client"
"github.com/cortexproject/cortex/pkg/storegateway/storegatewaypb"
)

@ -11,6 +11,7 @@ import (
"github.com/grafana/dskit/backoff"
"github.com/grafana/dskit/grpcclient"
dsmiddleware "github.com/grafana/dskit/middleware"
"github.com/grafana/dskit/ring/client"
"github.com/grafana/dskit/services"
otgrpc "github.com/opentracing-contrib/go-grpc"
"github.com/opentracing/opentracing-go"
@ -24,7 +25,6 @@ import (
"github.com/cortexproject/cortex/pkg/frontend/v2/frontendv2pb"
querier_stats "github.com/cortexproject/cortex/pkg/querier/stats"
"github.com/cortexproject/cortex/pkg/ring/client"
"github.com/cortexproject/cortex/pkg/scheduler/schedulerpb"
"github.com/cortexproject/cortex/pkg/util/httpgrpcutil"
util_log "github.com/cortexproject/cortex/pkg/util/log"

@ -5,14 +5,13 @@ import (
"github.com/go-kit/log"
"github.com/grafana/dskit/grpcclient"
"github.com/grafana/dskit/ring/client"
"github.com/grafana/dskit/services"
"github.com/pkg/errors"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"google.golang.org/grpc"
"google.golang.org/grpc/health/grpc_health_v1"
"github.com/cortexproject/cortex/pkg/ring/client"
)
// ClientsPool is the interface used to get the client from the pool for a specified address.

@ -1,7 +1,7 @@
package ruler
import (
"github.com/cortexproject/cortex/pkg/ring"
"github.com/grafana/dskit/ring"
)
func (r *Ruler) OnRingInstanceRegister(_ *ring.BasicLifecycler, ringDesc ring.Desc, instanceExists bool, instanceID string, instanceDesc ring.InstanceDesc) (ring.InstanceState, ring.Tokens) {

@ -18,6 +18,7 @@ import (
"github.com/grafana/dskit/flagext"
"github.com/grafana/dskit/grpcclient"
"github.com/grafana/dskit/kv"
"github.com/grafana/dskit/ring"
"github.com/grafana/dskit/services"
"github.com/pkg/errors"
"github.com/prometheus/client_golang/prometheus"
@ -30,7 +31,6 @@ import (
"golang.org/x/sync/errgroup"
"github.com/cortexproject/cortex/pkg/cortexpb"
"github.com/cortexproject/cortex/pkg/ring"
"github.com/cortexproject/cortex/pkg/ruler/rulespb"
"github.com/cortexproject/cortex/pkg/ruler/rulestore"
"github.com/cortexproject/cortex/pkg/tenant"
@ -295,10 +295,6 @@ func newRuler(cfg Config, manager MultiTenantManager, reg prometheus.Registerer,
if err = enableSharding(ruler, ringStore); err != nil {
return nil, errors.Wrap(err, "setup ruler sharding ring")
}
if reg != nil {
reg.MustRegister(ruler.ring)
}
}
ruler.Service = services.NewBasicService(ruler.starting, ruler.run, ruler.stopping)
@ -306,7 +302,7 @@ func newRuler(cfg Config, manager MultiTenantManager, reg prometheus.Registerer,
}
func enableSharding(r *Ruler, ringStore kv.Client) error {
lifecyclerCfg, err := r.cfg.Ring.ToLifecyclerConfig()
lifecyclerCfg, err := r.cfg.Ring.ToLifecyclerConfig(r.logger)
if err != nil {
return errors.Wrap(err, "failed to initialize ruler's lifecycler config")
}
@ -318,12 +314,12 @@ func enableSharding(r *Ruler, ringStore kv.Client) error {
delegate = ring.NewAutoForgetDelegate(r.cfg.Ring.HeartbeatTimeout*ringAutoForgetUnhealthyPeriods, delegate, r.logger)
rulerRingName := "ruler"
r.lifecycler, err = ring.NewBasicLifecycler(lifecyclerCfg, rulerRingName, ring.RulerRingKey, ringStore, delegate, r.logger, r.registry)
r.lifecycler, err = ring.NewBasicLifecycler(lifecyclerCfg, rulerRingName, ring.RulerRingKey, ringStore, delegate, r.logger, prometheus.WrapRegistererWithPrefix("cortex_", r.registry))
if err != nil {
return errors.Wrap(err, "failed to initialize ruler's lifecycler")
}
r.ring, err = ring.NewWithStoreClientAndStrategy(r.cfg.Ring.ToRingConfig(), rulerRingName, ring.RulerRingKey, ringStore, ring.NewIgnoreUnhealthyInstancesReplicationStrategy())
r.ring, err = ring.NewWithStoreClientAndStrategy(r.cfg.Ring.ToRingConfig(), rulerRingName, ring.RulerRingKey, ringStore, ring.NewIgnoreUnhealthyInstancesReplicationStrategy(), prometheus.WrapRegistererWithPrefix("cortex_", r.registry), r.logger)
if err != nil {
return errors.Wrap(err, "failed to initialize ruler's ring")
}

@ -6,10 +6,10 @@ import (
"os"
"time"
"github.com/go-kit/log"
"github.com/grafana/dskit/flagext"
"github.com/grafana/dskit/kv"
"github.com/cortexproject/cortex/pkg/ring"
"github.com/grafana/dskit/ring"
)
const (
@ -71,8 +71,8 @@ func (cfg *RingConfig) RegisterFlags(f *flag.FlagSet) {
// ToLifecyclerConfig returns a LifecyclerConfig based on the ruler
// ring config.
func (cfg *RingConfig) ToLifecyclerConfig() (ring.BasicLifecyclerConfig, error) {
instanceAddr, err := ring.GetInstanceAddr(cfg.InstanceAddr, cfg.InstanceInterfaceNames)
func (cfg *RingConfig) ToLifecyclerConfig(logger log.Logger) (ring.BasicLifecyclerConfig, error) {
instanceAddr, err := ring.GetInstanceAddr(cfg.InstanceAddr, cfg.InstanceInterfaceNames, logger)
if err != nil {
return ring.BasicLifecyclerConfig{}, err
}

@ -10,6 +10,7 @@ import (
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/grafana/dskit/kv"
"github.com/grafana/dskit/ring"
"github.com/grafana/dskit/services"
"github.com/pkg/errors"
"github.com/prometheus/client_golang/prometheus"
@ -19,7 +20,6 @@ import (
"github.com/thanos-io/thanos/pkg/store/storepb"
"github.com/weaveworks/common/logging"
"github.com/cortexproject/cortex/pkg/ring"
"github.com/cortexproject/cortex/pkg/storage/bucket"
cortex_tsdb "github.com/cortexproject/cortex/pkg/storage/tsdb"
"github.com/cortexproject/cortex/pkg/storegateway/storegatewaypb"
@ -146,7 +146,7 @@ func newStoreGateway(gatewayCfg Config, storageCfg cortex_tsdb.BlocksStorageConf
var shardingStrategy ShardingStrategy
if gatewayCfg.ShardingEnabled {
lifecyclerCfg, err := gatewayCfg.ShardingRing.ToLifecyclerConfig()
lifecyclerCfg, err := gatewayCfg.ShardingRing.ToLifecyclerConfig(logger)
if err != nil {
return nil, errors.Wrap(err, "invalid ring lifecycler config")
}
@ -158,21 +158,17 @@ func newStoreGateway(gatewayCfg Config, storageCfg cortex_tsdb.BlocksStorageConf
delegate = ring.NewTokensPersistencyDelegate(gatewayCfg.ShardingRing.TokensFilePath, ring.JOINING, delegate, logger)
delegate = ring.NewAutoForgetDelegate(ringAutoForgetUnhealthyPeriods*gatewayCfg.ShardingRing.HeartbeatTimeout, delegate, logger)
g.ringLifecycler, err = ring.NewBasicLifecycler(lifecyclerCfg, RingNameForServer, RingKey, ringStore, delegate, logger, reg)
g.ringLifecycler, err = ring.NewBasicLifecycler(lifecyclerCfg, RingNameForServer, RingKey, ringStore, delegate, logger, prometheus.WrapRegistererWithPrefix("cortex_", reg))
if err != nil {
return nil, errors.Wrap(err, "create ring lifecycler")
}
ringCfg := gatewayCfg.ShardingRing.ToRingConfig()
g.ring, err = ring.NewWithStoreClientAndStrategy(ringCfg, RingNameForServer, RingKey, ringStore, ring.NewIgnoreUnhealthyInstancesReplicationStrategy())
g.ring, err = ring.NewWithStoreClientAndStrategy(ringCfg, RingNameForServer, RingKey, ringStore, ring.NewIgnoreUnhealthyInstancesReplicationStrategy(), prometheus.WrapRegistererWithPrefix("cortex_", reg), logger)
if err != nil {
return nil, errors.Wrap(err, "create ring client")
}
if reg != nil {
reg.MustRegister(g.ring)
}
// Instance the right strategy.
switch gatewayCfg.ShardingStrategy {
case util.ShardingStrategyDefault:

@ -6,11 +6,12 @@ import (
"os"
"time"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/grafana/dskit/flagext"
"github.com/grafana/dskit/kv"
"github.com/grafana/dskit/ring"
"github.com/cortexproject/cortex/pkg/ring"
util_log "github.com/cortexproject/cortex/pkg/util/log"
)
@ -129,8 +130,8 @@ func (cfg *RingConfig) ToRingConfig() ring.Config {
return rc
}
func (cfg *RingConfig) ToLifecyclerConfig() (ring.BasicLifecyclerConfig, error) {
instanceAddr, err := ring.GetInstanceAddr(cfg.InstanceAddr, cfg.InstanceInterfaceNames)
func (cfg *RingConfig) ToLifecyclerConfig(logger log.Logger) (ring.BasicLifecyclerConfig, error) {
instanceAddr, err := ring.GetInstanceAddr(cfg.InstanceAddr, cfg.InstanceInterfaceNames, logger)
if err != nil {
return ring.BasicLifecyclerConfig{}, err
}

@ -5,13 +5,13 @@ import (
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/grafana/dskit/ring"
"github.com/oklog/ulid"
"github.com/thanos-io/thanos/pkg/block"
"github.com/thanos-io/thanos/pkg/block/metadata"
"github.com/thanos-io/thanos/pkg/extprom"
"github.com/thanos-io/thanos/pkg/objstore"
"github.com/cortexproject/cortex/pkg/ring"
cortex_tsdb "github.com/cortexproject/cortex/pkg/storage/tsdb"
)

@ -1,20 +1,11 @@
# Archived project. No maintenance.
This project is not maintained anymore and is archived. Feel free to fork and
make your own changes if needed. For more detail read my blog post: [Taking an indefinite sabbatical from my projects](https://arslan.io/2018/10/09/taking-an-indefinite-sabbatical-from-my-projects/)
Thanks to everyone for their valuable feedback and contributions.
# Color [![GoDoc](https://godoc.org/github.com/fatih/color?status.svg)](https://godoc.org/github.com/fatih/color)
# color [![](https://github.com/fatih/color/workflows/build/badge.svg)](https://github.com/fatih/color/actions) [![PkgGoDev](https://pkg.go.dev/badge/github.com/fatih/color)](https://pkg.go.dev/github.com/fatih/color)
Color lets you use colorized outputs in terms of [ANSI Escape
Codes](http://en.wikipedia.org/wiki/ANSI_escape_code#Colors) in Go (Golang). It
has support for Windows too! The API can be used in several ways, pick one that
suits you.
![Color](https://i.imgur.com/c1JI0lA.png)
![Color](https://user-images.githubusercontent.com/438920/96832689-03b3e000-13f4-11eb-9803-46f4c4de3406.jpg)
## Install
@ -136,14 +127,16 @@ fmt.Println("All text will now be bold magenta.")
There might be a case where you want to explicitly disable/enable color output. the
`go-isatty` package will automatically disable color output for non-tty output streams
(for example if the output were piped directly to `less`)
(for example if the output were piped directly to `less`).
`Color` has support to disable/enable colors both globally and for single color
definitions. For example suppose you have a CLI app and a `--no-color` bool flag. You
can easily disable the color output with:
The `color` package also disables color output if the [`NO_COLOR`](https://no-color.org) environment
variable is set (regardless of its value).
```go
`Color` has support to disable/enable colors programatically both globally and
for single color definitions. For example suppose you have a CLI app and a
`--no-color` bool flag. You can easily disable the color output with:
```go
var flagNoColor = flag.Bool("no-color", false, "Disable color output")
if *flagNoColor {
@ -165,6 +158,10 @@ c.EnableColor()
c.Println("This prints again cyan...")
```
## GitHub Actions
To output color in GitHub Actions (or other CI systems that support ANSI colors), make sure to set `color.NoColor = false` so that it bypasses the check for non-tty output streams.
## Todo
* Save/Return previous values
@ -179,4 +176,3 @@ c.Println("This prints again cyan...")
## License
The MIT License (MIT) - see [`LICENSE.md`](https://github.com/fatih/color/blob/master/LICENSE.md) for more details

@ -15,9 +15,11 @@ import (
var (
// NoColor defines if the output is colorized or not. It's dynamically set to
// false or true based on the stdout's file descriptor referring to a terminal
// or not. This is a global option and affects all colors. For more control
// over each color block use the methods DisableColor() individually.
NoColor = os.Getenv("TERM") == "dumb" ||
// or not. It's also set to true if the NO_COLOR environment variable is
// set (regardless of its value). This is a global option and affects all
// colors. For more control over each color block use the methods
// DisableColor() individually.
NoColor = noColorExists() || os.Getenv("TERM") == "dumb" ||
(!isatty.IsTerminal(os.Stdout.Fd()) && !isatty.IsCygwinTerminal(os.Stdout.Fd()))
// Output defines the standard output of the print functions. By default
@ -33,6 +35,12 @@ var (
colorsCacheMu sync.Mutex // protects colorsCache
)
// noColorExists returns true if the environment variable NO_COLOR exists.
func noColorExists() bool {
_, exists := os.LookupEnv("NO_COLOR")
return exists
}
// Color defines a custom color object which is defined by SGR parameters.
type Color struct {
params []Attribute
@ -108,7 +116,14 @@ const (
// New returns a newly created color object.
func New(value ...Attribute) *Color {
c := &Color{params: make([]Attribute, 0)}
c := &Color{
params: make([]Attribute, 0),
}
if noColorExists() {
c.noColor = boolPtr(true)
}
c.Add(value...)
return c
}
@ -387,7 +402,7 @@ func (c *Color) EnableColor() {
}
func (c *Color) isNoColorSet() bool {
// check first if we have user setted action
// check first if we have user set action
if c.noColor != nil {
return *c.noColor
}

@ -118,6 +118,8 @@ the color output with:
color.NoColor = true // disables colorized output
}
You can also disable the color by setting the NO_COLOR environment variable to any value.
It also has support for single color definitions (local). You can
disable/enable color output on the fly:

@ -1,5 +1,14 @@
# package log
**Deprecation notice:** The core Go kit log packages (log, log/level, log/term, and
log/syslog) have been moved to their own repository at github.com/go-kit/log.
The corresponding packages in this directory remain for backwards compatibility.
Their types alias the types and their functions call the functions provided by
the new repository. Using either import path should be equivalent. Prefer the
new import path when practical.
______
`package log` provides a minimal interface for structured logging in services.
It may be wrapped to encode conventions, enforce type-safety, provide leveled
logging, and so on. It can be used for both typical application log events,

@ -1,5 +1,7 @@
// Package log provides a structured logger.
//
// Deprecated: Use github.com/go-kit/log instead.
//
// Structured logging produces logs easily consumed later by humans or
// machines. Humans might be interested in debugging errors, or tracing
// specific requests. Machines might be interested in counting interesting

@ -1,91 +1,15 @@
package log
import (
"encoding"
"encoding/json"
"fmt"
"io"
"reflect"
)
type jsonLogger struct {
io.Writer
}
"github.com/go-kit/log"
)
// NewJSONLogger returns a Logger that encodes keyvals to the Writer as a
// single JSON object. Each log event produces no more than one call to
// w.Write. The passed Writer must be safe for concurrent use by multiple
// goroutines if the returned Logger will be used concurrently.
func NewJSONLogger(w io.Writer) Logger {
return &jsonLogger{w}
}
func (l *jsonLogger) Log(keyvals ...interface{}) error {
n := (len(keyvals) + 1) / 2 // +1 to handle case when len is odd
m := make(map[string]interface{}, n)
for i := 0; i < len(keyvals); i += 2 {
k := keyvals[i]
var v interface{} = ErrMissingValue
if i+1 < len(keyvals) {
v = keyvals[i+1]
}
merge(m, k, v)
}
enc := json.NewEncoder(l.Writer)
enc.SetEscapeHTML(false)
return enc.Encode(m)
}
func merge(dst map[string]interface{}, k, v interface{}) {
var key string
switch x := k.(type) {
case string:
key = x
case fmt.Stringer:
key = safeString(x)
default:
key = fmt.Sprint(x)
}
// We want json.Marshaler and encoding.TextMarshaller to take priority over
// err.Error() and v.String(). But json.Marshall (called later) does that by
// default so we force a no-op if it's one of those 2 case.
switch x := v.(type) {
case json.Marshaler:
case encoding.TextMarshaler:
case error:
v = safeError(x)
case fmt.Stringer:
v = safeString(x)
}
dst[key] = v
}
func safeString(str fmt.Stringer) (s string) {
defer func() {
if panicVal := recover(); panicVal != nil {
if v := reflect.ValueOf(str); v.Kind() == reflect.Ptr && v.IsNil() {
s = "NULL"
} else {
panic(panicVal)
}
}
}()
s = str.String()
return
}
func safeError(err error) (s interface{}) {
defer func() {
if panicVal := recover(); panicVal != nil {
if v := reflect.ValueOf(err); v.Kind() == reflect.Ptr && v.IsNil() {
s = nil
} else {
panic(panicVal)
}
}
}()
s = err.Error()
return
return log.NewJSONLogger(w)
}

@ -1,6 +1,9 @@
// Package level implements leveled logging on top of Go kit's log package. To
// use the level package, create a logger as per normal in your func main, and
// wrap it with level.NewFilter.
// Package level implements leveled logging on top of Go kit's log package.
//
// Deprecated: Use github.com/go-kit/log/level instead.
//
// To use the level package, create a logger as per normal in your func main,
// and wrap it with level.NewFilter.
//
// var logger log.Logger
// logger = log.NewLogfmtLogger(os.Stderr)

@ -1,25 +1,28 @@
package level
import "github.com/go-kit/kit/log"
import (
"github.com/go-kit/log"
"github.com/go-kit/log/level"
)
// Error returns a logger that includes a Key/ErrorValue pair.
func Error(logger log.Logger) log.Logger {
return log.WithPrefix(logger, Key(), ErrorValue())
return level.Error(logger)
}
// Warn returns a logger that includes a Key/WarnValue pair.
func Warn(logger log.Logger) log.Logger {
return log.WithPrefix(logger, Key(), WarnValue())
return level.Warn(logger)
}
// Info returns a logger that includes a Key/InfoValue pair.
func Info(logger log.Logger) log.Logger {
return log.WithPrefix(logger, Key(), InfoValue())
return level.Info(logger)
}
// Debug returns a logger that includes a Key/DebugValue pair.
func Debug(logger log.Logger) log.Logger {
return log.WithPrefix(logger, Key(), DebugValue())
return level.Debug(logger)
}
// NewFilter wraps next and implements level filtering. See the commentary on
@ -28,76 +31,40 @@ func Debug(logger log.Logger) log.Logger {
// Info, Warn or Error helper methods are squelched and non-leveled log
// events are passed to next unmodified.
func NewFilter(next log.Logger, options ...Option) log.Logger {
l := &logger{
next: next,
}
for _, option := range options {
option(l)
}
return l
}
type logger struct {
next log.Logger
allowed level
squelchNoLevel bool
errNotAllowed error
errNoLevel error
}
func (l *logger) Log(keyvals ...interface{}) error {
var hasLevel, levelAllowed bool
for i := 1; i < len(keyvals); i += 2 {
if v, ok := keyvals[i].(*levelValue); ok {
hasLevel = true
levelAllowed = l.allowed&v.level != 0
break
}
}
if !hasLevel && l.squelchNoLevel {
return l.errNoLevel
}
if hasLevel && !levelAllowed {
return l.errNotAllowed
}
return l.next.Log(keyvals...)
return level.NewFilter(next, options...)
}
// Option sets a parameter for the leveled logger.
type Option func(*logger)
type Option = level.Option
// AllowAll is an alias for AllowDebug.
func AllowAll() Option {
return AllowDebug()
return level.AllowAll()
}
// AllowDebug allows error, warn, info and debug level log events to pass.
func AllowDebug() Option {
return allowed(levelError | levelWarn | levelInfo | levelDebug)
return level.AllowDebug()
}
// AllowInfo allows error, warn and info level log events to pass.
func AllowInfo() Option {
return allowed(levelError | levelWarn | levelInfo)
return level.AllowInfo()
}
// AllowWarn allows error and warn level log events to pass.
func AllowWarn() Option {
return allowed(levelError | levelWarn)
return level.AllowWarn()
}
// AllowError allows only error level log events to pass.
func AllowError() Option {
return allowed(levelError)
return level.AllowError()
}
// AllowNone allows no leveled log events to pass.
func AllowNone() Option {
return allowed(0)
}
func allowed(allowed level) Option {
return func(l *logger) { l.allowed = allowed }
return level.AllowNone()
}
// ErrNotAllowed sets the error to return from Log when it squelches a log
@ -105,7 +72,7 @@ func allowed(allowed level) Option {
// ErrNotAllowed is nil; in this case the log event is squelched with no
// error.
func ErrNotAllowed(err error) Option {
return func(l *logger) { l.errNotAllowed = err }
return level.ErrNotAllowed(err)
}
// SquelchNoLevel instructs Log to squelch log events with no level, so that
@ -113,93 +80,41 @@ func ErrNotAllowed(err error) Option {
// to true and a log event is squelched in this way, the error value
// configured with ErrNoLevel is returned to the caller.
func SquelchNoLevel(squelch bool) Option {
return func(l *logger) { l.squelchNoLevel = squelch }
return level.SquelchNoLevel(squelch)
}
// ErrNoLevel sets the error to return from Log when it squelches a log event
// with no level. By default, ErrNoLevel is nil; in this case the log event is
// squelched with no error.
func ErrNoLevel(err error) Option {
return func(l *logger) { l.errNoLevel = err }
return level.ErrNoLevel(err)
}
// NewInjector wraps next and returns a logger that adds a Key/level pair to
// the beginning of log events that don't already contain a level. In effect,
// this gives a default level to logs without a level.
func NewInjector(next log.Logger, level Value) log.Logger {
return &injector{
next: next,
level: level,
}
}
type injector struct {
next log.Logger
level interface{}
}
func (l *injector) Log(keyvals ...interface{}) error {
for i := 1; i < len(keyvals); i += 2 {
if _, ok := keyvals[i].(*levelValue); ok {
return l.next.Log(keyvals...)
}
}
kvs := make([]interface{}, len(keyvals)+2)
kvs[0], kvs[1] = key, l.level
copy(kvs[2:], keyvals)
return l.next.Log(kvs...)
func NewInjector(next log.Logger, lvl Value) log.Logger {
return level.NewInjector(next, lvl)
}
// Value is the interface that each of the canonical level values implement.
// It contains unexported methods that prevent types from other packages from
// implementing it and guaranteeing that NewFilter can distinguish the levels
// defined in this package from all other values.
type Value interface {
String() string
levelVal()
}
type Value = level.Value
// Key returns the unique key added to log events by the loggers in this
// package.
func Key() interface{} { return key }
func Key() interface{} { return level.Key() }
// ErrorValue returns the unique value added to log events by Error.
func ErrorValue() Value { return errorValue }
func ErrorValue() Value { return level.ErrorValue() }
// WarnValue returns the unique value added to log events by Warn.
func WarnValue() Value { return warnValue }
func WarnValue() Value { return level.WarnValue() }
// InfoValue returns the unique value added to log events by Info.
func InfoValue() Value { return infoValue }
func InfoValue() Value { return level.InfoValue() }
// DebugValue returns the unique value added to log events by Debug.
func DebugValue() Value { return debugValue }
var (
// key is of type interface{} so that it allocates once during package
// initialization and avoids allocating every time the value is added to a
// []interface{} later.
key interface{} = "level"
errorValue = &levelValue{level: levelError, name: "error"}
warnValue = &levelValue{level: levelWarn, name: "warn"}
infoValue = &levelValue{level: levelInfo, name: "info"}
debugValue = &levelValue{level: levelDebug, name: "debug"}
)
type level byte
const (
levelDebug level = 1 << iota
levelInfo
levelWarn
levelError
)
type levelValue struct {
name string
level
}
func (v *levelValue) String() string { return v.name }
func (v *levelValue) levelVal() {}
func DebugValue() Value { return level.DebugValue() }

@ -1,19 +1,19 @@
package log
import "errors"
import (
"github.com/go-kit/log"
)
// Logger is the fundamental interface for all log operations. Log creates a
// log event from keyvals, a variadic sequence of alternating keys and values.
// Implementations must be safe for concurrent use by multiple goroutines. In
// particular, any implementation of Logger that appends to keyvals or
// modifies or retains any of its elements must make a copy first.
type Logger interface {
Log(keyvals ...interface{}) error
}
type Logger = log.Logger
// ErrMissingValue is appended to keyvals slices with odd length to substitute
// the missing value.
var ErrMissingValue = errors.New("(MISSING)")
var ErrMissingValue = log.ErrMissingValue
// With returns a new contextual logger with keyvals prepended to those passed
// to calls to Log. If logger is also a contextual logger created by With,
@ -22,25 +22,7 @@ var ErrMissingValue = errors.New("(MISSING)")
// The returned Logger replaces all value elements (odd indexes) containing a
// Valuer with their generated value for each call to its Log method.
func With(logger Logger, keyvals ...interface{}) Logger {
if len(keyvals) == 0 {
return logger
}
l := newContext(logger)
kvs := append(l.keyvals, keyvals...)
if len(kvs)%2 != 0 {
kvs = append(kvs, ErrMissingValue)
}
return &context{
logger: l.logger,
// Limiting the capacity of the stored keyvals ensures that a new
// backing array is created if the slice must grow in Log or With.
// Using the extra capacity without copying risks a data race that
// would violate the Logger interface contract.
keyvals: kvs[:len(kvs):len(kvs)],
hasValuer: l.hasValuer || containsValuer(keyvals),
sKeyvals: l.sKeyvals,
sHasValuer: l.sHasValuer,
}
return log.With(logger, keyvals...)
}
// WithPrefix returns a new contextual logger with keyvals prepended to those
@ -50,31 +32,7 @@ func With(logger Logger, keyvals ...interface{}) Logger {
// The returned Logger replaces all value elements (odd indexes) containing a
// Valuer with their generated value for each call to its Log method.
func WithPrefix(logger Logger, keyvals ...interface{}) Logger {
if len(keyvals) == 0 {
return logger
}
l := newContext(logger)
// Limiting the capacity of the stored keyvals ensures that a new
// backing array is created if the slice must grow in Log or With.
// Using the extra capacity without copying risks a data race that
// would violate the Logger interface contract.
n := len(l.keyvals) + len(keyvals)
if len(keyvals)%2 != 0 {
n++
}
kvs := make([]interface{}, 0, n)
kvs = append(kvs, keyvals...)
if len(kvs)%2 != 0 {
kvs = append(kvs, ErrMissingValue)
}
kvs = append(kvs, l.keyvals...)
return &context{
logger: l.logger,
keyvals: kvs,
hasValuer: l.hasValuer || containsValuer(keyvals),
sKeyvals: l.sKeyvals,
sHasValuer: l.sHasValuer,
}
return log.WithPrefix(logger, keyvals...)
}
// WithSuffix returns a new contextual logger with keyvals appended to those
@ -84,96 +42,10 @@ func WithPrefix(logger Logger, keyvals ...interface{}) Logger {
// The returned Logger replaces all value elements (odd indexes) containing a
// Valuer with their generated value for each call to its Log method.
func WithSuffix(logger Logger, keyvals ...interface{}) Logger {
if len(keyvals) == 0 {
return logger
}
l := newContext(logger)
// Limiting the capacity of the stored keyvals ensures that a new
// backing array is created if the slice must grow in Log or With.
// Using the extra capacity without copying risks a data race that
// would violate the Logger interface contract.
n := len(l.sKeyvals) + len(keyvals)
if len(keyvals)%2 != 0 {
n++
}
kvs := make([]interface{}, 0, n)
kvs = append(kvs, keyvals...)
if len(kvs)%2 != 0 {
kvs = append(kvs, ErrMissingValue)
}
kvs = append(l.sKeyvals, kvs...)
return &context{
logger: l.logger,
keyvals: l.keyvals,
hasValuer: l.hasValuer,
sKeyvals: kvs,
sHasValuer: l.sHasValuer || containsValuer(keyvals),
}
}
// context is the Logger implementation returned by With, WithPrefix, and
// WithSuffix. It wraps a Logger and holds keyvals that it includes in all
// log events. Its Log method calls bindValues to generate values for each
// Valuer in the context keyvals.
//
// A context must always have the same number of stack frames between calls to
// its Log method and the eventual binding of Valuers to their value. This
// requirement comes from the functional requirement to allow a context to
// resolve application call site information for a Caller stored in the
// context. To do this we must be able to predict the number of logging
// functions on the stack when bindValues is called.
//
// Two implementation details provide the needed stack depth consistency.
//
// 1. newContext avoids introducing an additional layer when asked to
// wrap another context.
// 2. With, WithPrefix, and WithSuffix avoid introducing an additional
// layer by returning a newly constructed context with a merged keyvals
// rather than simply wrapping the existing context.
type context struct {
logger Logger
keyvals []interface{}
sKeyvals []interface{} // suffixes
hasValuer bool
sHasValuer bool
}
func newContext(logger Logger) *context {
if c, ok := logger.(*context); ok {
return c
}
return &context{logger: logger}
}
// Log replaces all value elements (odd indexes) containing a Valuer in the
// stored context with their generated value, appends keyvals, and passes the
// result to the wrapped Logger.
func (l *context) Log(keyvals ...interface{}) error {
kvs := append(l.keyvals, keyvals...)
if len(kvs)%2 != 0 {
kvs = append(kvs, ErrMissingValue)
}
if l.hasValuer {
// If no keyvals were appended above then we must copy l.keyvals so
// that future log events will reevaluate the stored Valuers.
if len(keyvals) == 0 {
kvs = append([]interface{}{}, l.keyvals...)
}
bindValues(kvs[:(len(l.keyvals))])
}
kvs = append(kvs, l.sKeyvals...)
if l.sHasValuer {
bindValues(kvs[len(kvs) - len(l.sKeyvals):])
}
return l.logger.Log(kvs...)
return log.WithSuffix(logger, keyvals...)
}
// LoggerFunc is an adapter to allow use of ordinary functions as Loggers. If
// f is a function with the appropriate signature, LoggerFunc(f) is a Logger
// object that calls f.
type LoggerFunc func(...interface{}) error
// Log implements Logger by calling f(keyvals...).
func (f LoggerFunc) Log(keyvals ...interface{}) error {
return f(keyvals...)
}
type LoggerFunc = log.LoggerFunc

@ -1,62 +1,15 @@
package log
import (
"bytes"
"io"
"sync"
"github.com/go-logfmt/logfmt"
"github.com/go-kit/log"
)
type logfmtEncoder struct {
*logfmt.Encoder
buf bytes.Buffer
}
func (l *logfmtEncoder) Reset() {
l.Encoder.Reset()
l.buf.Reset()
}
var logfmtEncoderPool = sync.Pool{
New: func() interface{} {
var enc logfmtEncoder
enc.Encoder = logfmt.NewEncoder(&enc.buf)
return &enc
},
}
type logfmtLogger struct {
w io.Writer
}
// NewLogfmtLogger returns a logger that encodes keyvals to the Writer in
// logfmt format. Each log event produces no more than one call to w.Write.
// The passed Writer must be safe for concurrent use by multiple goroutines if
// the returned Logger will be used concurrently.
func NewLogfmtLogger(w io.Writer) Logger {
return &logfmtLogger{w}
}
func (l logfmtLogger) Log(keyvals ...interface{}) error {
enc := logfmtEncoderPool.Get().(*logfmtEncoder)
enc.Reset()
defer logfmtEncoderPool.Put(enc)
if err := enc.EncodeKeyvals(keyvals...); err != nil {
return err
}
// Add newline to the end of the buffer
if err := enc.EndRecord(); err != nil {
return err
}
// The Logger interface requires implementations to be safe for concurrent
// use by multiple goroutines. For this implementation that means making
// only one call to l.w.Write() for each call to Log.
if _, err := l.w.Write(enc.buf.Bytes()); err != nil {
return err
}
return nil
return log.NewLogfmtLogger(w)
}

@ -1,8 +1,8 @@
package log
type nopLogger struct{}
import "github.com/go-kit/log"
// NewNopLogger returns a logger that doesn't do anything.
func NewNopLogger() Logger { return nopLogger{} }
func (nopLogger) Log(...interface{}) error { return nil }
func NewNopLogger() Logger {
return log.NewNopLogger()
}

@ -1,11 +1,9 @@
package log
import (
"bytes"
"io"
"log"
"regexp"
"strings"
"github.com/go-kit/log"
)
// StdlibWriter implements io.Writer by invoking the stdlib log.Print. It's
@ -14,42 +12,29 @@ import (
//
// If you have any choice in the matter, you shouldn't use this. Prefer to
// redirect the stdlib log to the Go kit logger via NewStdlibAdapter.
type StdlibWriter struct{}
// Write implements io.Writer.
func (w StdlibWriter) Write(p []byte) (int, error) {
log.Print(strings.TrimSpace(string(p)))
return len(p), nil
}
type StdlibWriter = log.StdlibWriter
// StdlibAdapter wraps a Logger and allows it to be passed to the stdlib
// logger's SetOutput. It will extract date/timestamps, filenames, and
// messages, and place them under relevant keys.
type StdlibAdapter struct {
Logger
timestampKey string
fileKey string
messageKey string
prefix string
joinPrefixToMsg bool
}
type StdlibAdapter = log.StdlibAdapter
// StdlibAdapterOption sets a parameter for the StdlibAdapter.
type StdlibAdapterOption func(*StdlibAdapter)
type StdlibAdapterOption = log.StdlibAdapterOption
// TimestampKey sets the key for the timestamp field. By default, it's "ts".
func TimestampKey(key string) StdlibAdapterOption {
return func(a *StdlibAdapter) { a.timestampKey = key }
return log.TimestampKey(key)
}
// FileKey sets the key for the file and line field. By default, it's "caller".
func FileKey(key string) StdlibAdapterOption {
return func(a *StdlibAdapter) { a.fileKey = key }
return log.FileKey(key)
}
// MessageKey sets the key for the actual log message. By default, it's "msg".
func MessageKey(key string) StdlibAdapterOption {
return func(a *StdlibAdapter) { a.messageKey = key }
return log.MessageKey(key)
}
// Prefix configures the adapter to parse a prefix from stdlib log events. If
@ -59,93 +44,11 @@ func MessageKey(key string) StdlibAdapterOption {
// By default, the prefix isn't included in the msg key. Set joinPrefixToMsg to
// true if you want to include the parsed prefix in the msg.
func Prefix(prefix string, joinPrefixToMsg bool) StdlibAdapterOption {
return func(a *StdlibAdapter) { a.prefix = prefix; a.joinPrefixToMsg = joinPrefixToMsg }
return log.Prefix(prefix, joinPrefixToMsg)
}
// NewStdlibAdapter returns a new StdlibAdapter wrapper around the passed
// logger. It's designed to be passed to log.SetOutput.
func NewStdlibAdapter(logger Logger, options ...StdlibAdapterOption) io.Writer {
a := StdlibAdapter{
Logger: logger,
timestampKey: "ts",
fileKey: "caller",
messageKey: "msg",
}
for _, option := range options {
option(&a)
}
return a
}
func (a StdlibAdapter) Write(p []byte) (int, error) {
p = a.handlePrefix(p)
result := subexps(p)
keyvals := []interface{}{}
var timestamp string
if date, ok := result["date"]; ok && date != "" {
timestamp = date
}
if time, ok := result["time"]; ok && time != "" {
if timestamp != "" {
timestamp += " "
}
timestamp += time
}
if timestamp != "" {
keyvals = append(keyvals, a.timestampKey, timestamp)
}
if file, ok := result["file"]; ok && file != "" {
keyvals = append(keyvals, a.fileKey, file)
}
if msg, ok := result["msg"]; ok {
msg = a.handleMessagePrefix(msg)
keyvals = append(keyvals, a.messageKey, msg)
}
if err := a.Logger.Log(keyvals...); err != nil {
return 0, err
}
return len(p), nil
}
func (a StdlibAdapter) handlePrefix(p []byte) []byte {
if a.prefix != "" {
p = bytes.TrimPrefix(p, []byte(a.prefix))
}
return p
}
func (a StdlibAdapter) handleMessagePrefix(msg string) string {
if a.prefix == "" {
return msg
}
msg = strings.TrimPrefix(msg, a.prefix)
if a.joinPrefixToMsg {
msg = a.prefix + msg
}
return msg
}
const (
logRegexpDate = `(?P<date>[0-9]{4}/[0-9]{2}/[0-9]{2})?[ ]?`
logRegexpTime = `(?P<time>[0-9]{2}:[0-9]{2}:[0-9]{2}(\.[0-9]+)?)?[ ]?`
logRegexpFile = `(?P<file>.+?:[0-9]+)?`
logRegexpMsg = `(: )?(?P<msg>(?s:.*))`
)
var (
logRegexp = regexp.MustCompile(logRegexpDate + logRegexpTime + logRegexpFile + logRegexpMsg)
)
func subexps(line []byte) map[string]string {
m := logRegexp.FindSubmatch(line)
if len(m) < len(logRegexp.SubexpNames()) {
return map[string]string{}
}
result := map[string]string{}
for i, name := range logRegexp.SubexpNames() {
result[name] = strings.TrimRight(string(m[i]), "\n")
}
return result
return log.NewStdlibAdapter(logger, options...)
}

@ -2,8 +2,8 @@ package log
import (
"io"
"sync"
"sync/atomic"
"github.com/go-kit/log"
)
// SwapLogger wraps another logger that may be safely replaced while other
@ -12,29 +12,7 @@ import (
//
// SwapLogger serves well as a package global logger that can be changed by
// importers.
type SwapLogger struct {
logger atomic.Value
}
type loggerStruct struct {
Logger
}
// Log implements the Logger interface by forwarding keyvals to the currently
// wrapped logger. It does not log anything if the wrapped logger is nil.
func (l *SwapLogger) Log(keyvals ...interface{}) error {
s, ok := l.logger.Load().(loggerStruct)
if !ok || s.Logger == nil {
return nil
}
return s.Log(keyvals...)
}
// Swap replaces the currently wrapped logger with logger. Swap may be called
// concurrently with calls to Log from other goroutines.
func (l *SwapLogger) Swap(logger Logger) {
l.logger.Store(loggerStruct{logger})
}
type SwapLogger = log.SwapLogger
// NewSyncWriter returns a new writer that is safe for concurrent use by
// multiple goroutines. Writes to the returned writer are passed on to w. If
@ -47,53 +25,7 @@ func (l *SwapLogger) Swap(logger Logger) {
// Fd() uintptr
// }
func NewSyncWriter(w io.Writer) io.Writer {
switch w := w.(type) {
case fdWriter:
return &fdSyncWriter{fdWriter: w}
default:
return &syncWriter{Writer: w}
}
}
// syncWriter synchronizes concurrent writes to an io.Writer.
type syncWriter struct {
sync.Mutex
io.Writer
}
// Write writes p to the underlying io.Writer. If another write is already in
// progress, the calling goroutine blocks until the syncWriter is available.
func (w *syncWriter) Write(p []byte) (n int, err error) {
w.Lock()
defer w.Unlock()
return w.Writer.Write(p)
}
// fdWriter is an io.Writer that also has an Fd method. The most common
// example of an fdWriter is an *os.File.
type fdWriter interface {
io.Writer
Fd() uintptr
}
// fdSyncWriter synchronizes concurrent writes to an fdWriter.
type fdSyncWriter struct {
sync.Mutex
fdWriter
}
// Write writes p to the underlying io.Writer. If another write is already in
// progress, the calling goroutine blocks until the fdSyncWriter is available.
func (w *fdSyncWriter) Write(p []byte) (n int, err error) {
w.Lock()
defer w.Unlock()
return w.fdWriter.Write(p)
}
// syncLogger provides concurrent safe logging for another Logger.
type syncLogger struct {
mu sync.Mutex
logger Logger
return log.NewSyncWriter(w)
}
// NewSyncLogger returns a logger that synchronizes concurrent use of the
@ -101,13 +33,5 @@ type syncLogger struct {
// only one goroutine will be allowed to log to the wrapped logger at a time.
// The other goroutines will block until the logger is available.
func NewSyncLogger(logger Logger) Logger {
return &syncLogger{logger: logger}
}
// Log logs keyvals to the underlying Logger. If another log is already in
// progress, the calling goroutine blocks until the syncLogger is available.
func (l *syncLogger) Log(keyvals ...interface{}) error {
l.mu.Lock()
defer l.mu.Unlock()
return l.logger.Log(keyvals...)
return log.NewSyncLogger(logger)
}

@ -1,37 +1,15 @@
package log
import (
"runtime"
"strconv"
"strings"
"time"
"github.com/go-kit/log"
)
// A Valuer generates a log value. When passed to With, WithPrefix, or
// WithSuffix in a value element (odd indexes), it represents a dynamic
// value which is re-evaluated with each log event.
type Valuer func() interface{}
// bindValues replaces all value elements (odd indexes) containing a Valuer
// with their generated value.
func bindValues(keyvals []interface{}) {
for i := 1; i < len(keyvals); i += 2 {
if v, ok := keyvals[i].(Valuer); ok {
keyvals[i] = v()
}
}
}
// containsValuer returns true if any of the value elements (odd indexes)
// contain a Valuer.
func containsValuer(keyvals []interface{}) bool {
for i := 1; i < len(keyvals); i += 2 {
if _, ok := keyvals[i].(Valuer); ok {
return true
}
}
return false
}
type Valuer = log.Valuer
// Timestamp returns a timestamp Valuer. It invokes the t function to get the
// time; unless you are doing something tricky, pass time.Now.
@ -39,7 +17,7 @@ func containsValuer(keyvals []interface{}) bool {
// Most users will want to use DefaultTimestamp or DefaultTimestampUTC, which
// are TimestampFormats that use the RFC3339Nano format.
func Timestamp(t func() time.Time) Valuer {
return func() interface{} { return t() }
return log.Timestamp(t)
}
// TimestampFormat returns a timestamp Valuer with a custom time format. It
@ -50,61 +28,25 @@ func Timestamp(t func() time.Time) Valuer {
// Most users will want to use DefaultTimestamp or DefaultTimestampUTC, which
// are TimestampFormats that use the RFC3339Nano format.
func TimestampFormat(t func() time.Time, layout string) Valuer {
return func() interface{} {
return timeFormat{
time: t(),
layout: layout,
}
}
}
// A timeFormat represents an instant in time and a layout used when
// marshaling to a text format.
type timeFormat struct {
time time.Time
layout string
}
func (tf timeFormat) String() string {
return tf.time.Format(tf.layout)
}
// MarshalText implements encoding.TextMarshaller.
func (tf timeFormat) MarshalText() (text []byte, err error) {
// The following code adapted from the standard library time.Time.Format
// method. Using the same undocumented magic constant to extend the size
// of the buffer as seen there.
b := make([]byte, 0, len(tf.layout)+10)
b = tf.time.AppendFormat(b, tf.layout)
return b, nil
return log.TimestampFormat(t, layout)
}
// Caller returns a Valuer that returns a file and line from a specified depth
// in the callstack. Users will probably want to use DefaultCaller.
func Caller(depth int) Valuer {
return func() interface{} {
_, file, line, _ := runtime.Caller(depth)
idx := strings.LastIndexByte(file, '/')
// using idx+1 below handles both of following cases:
// idx == -1 because no "/" was found, or
// idx >= 0 and we want to start at the character after the found "/".
return file[idx+1:] + ":" + strconv.Itoa(line)
}
return log.Caller(depth)
}
var (
// DefaultTimestamp is a Valuer that returns the current wallclock time,
// respecting time zones, when bound.
DefaultTimestamp = TimestampFormat(time.Now, time.RFC3339Nano)
DefaultTimestamp = log.DefaultTimestamp
// DefaultTimestampUTC is a Valuer that returns the current time in UTC
// when bound.
DefaultTimestampUTC = TimestampFormat(
func() time.Time { return time.Now().UTC() },
time.RFC3339Nano,
)
DefaultTimestampUTC = log.DefaultTimestampUTC
// DefaultCaller is a Valuer that returns the file and line where the Log
// method was invoked. It can only be used with log.With.
DefaultCaller = Caller(3)
DefaultCaller = log.DefaultCaller
)

@ -9,13 +9,12 @@ import (
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/grafana/dskit/kv"
"github.com/grafana/dskit/services"
"github.com/pkg/errors"
"github.com/prometheus/client_golang/prometheus"
"github.com/cortexproject/cortex/pkg/util"
util_log "github.com/cortexproject/cortex/pkg/util/log"
"github.com/grafana/dskit/kv"
"github.com/grafana/dskit/services"
dstime "github.com/grafana/dskit/time"
)
type BasicLifecyclerDelegate interface {
@ -183,7 +182,7 @@ func (l *BasicLifecycler) starting(ctx context.Context) error {
}
func (l *BasicLifecycler) running(ctx context.Context) error {
heartbeatTickerStop, heartbeatTickerChan := util.NewDisableableTicker(l.cfg.HeartbeatPeriod)
heartbeatTickerStop, heartbeatTickerChan := dstime.NewDisableableTicker(l.cfg.HeartbeatPeriod)
defer heartbeatTickerStop()
for {
@ -195,7 +194,7 @@ func (l *BasicLifecycler) running(ctx context.Context) error {
f()
case <-ctx.Done():
level.Info(util_log.Logger).Log("msg", "ring lifecycler is shutting down", "ring", l.ringName)
level.Info(l.logger).Log("msg", "ring lifecycler is shutting down", "ring", l.ringName)
return nil
}
}
@ -215,7 +214,7 @@ func (l *BasicLifecycler) stopping(runningError error) error {
}()
// Heartbeat while the stopping delegate function is running.
heartbeatTickerStop, heartbeatTickerChan := util.NewDisableableTicker(l.cfg.HeartbeatPeriod)
heartbeatTickerStop, heartbeatTickerChan := dstime.NewDisableableTicker(l.cfg.HeartbeatPeriod)
defer heartbeatTickerStop()
heartbeatLoop:
@ -293,7 +292,7 @@ func (l *BasicLifecycler) registerInstance(ctx context.Context) error {
}
func (l *BasicLifecycler) waitStableTokens(ctx context.Context, period time.Duration) error {
heartbeatTickerStop, heartbeatTickerChan := util.NewDisableableTicker(l.cfg.HeartbeatPeriod)
heartbeatTickerStop, heartbeatTickerChan := dstime.NewDisableableTicker(l.cfg.HeartbeatPeriod)
defer heartbeatTickerStop()
// The first observation will occur after the specified period.

@ -14,17 +14,17 @@ type BasicLifecyclerMetrics struct {
func NewBasicLifecyclerMetrics(ringName string, reg prometheus.Registerer) *BasicLifecyclerMetrics {
return &BasicLifecyclerMetrics{
heartbeats: promauto.With(reg).NewCounter(prometheus.CounterOpts{
Name: "cortex_ring_member_heartbeats_total",
Name: "ring_member_heartbeats_total",
Help: "The total number of heartbeats sent.",
ConstLabels: prometheus.Labels{"name": ringName},
}),
tokensOwned: promauto.With(reg).NewGauge(prometheus.GaugeOpts{
Name: "cortex_ring_member_tokens_owned",
Name: "ring_member_tokens_owned",
Help: "The number of tokens owned in the ring.",
ConstLabels: prometheus.Labels{"name": ringName},
}),
tokensToOwn: promauto.With(reg).NewGauge(prometheus.GaugeOpts{
Name: "cortex_ring_member_tokens_to_own",
Name: "ring_member_tokens_to_own",
Help: "The number of tokens to own in the ring.",
ConstLabels: prometheus.Labels{"name": ringName},
}),

@ -37,9 +37,12 @@ type itemTracker struct {
// Callback is passed the instance to target, and the indexes of the keys
// to send to that instance.
//
// cleanup() is always called, either on an error before starting the batches or after they all finish.
//
// Not implemented as a method on Ring so we can test separately.
func DoBatch(ctx context.Context, op Operation, r ReadRing, keys []uint32, callback func(InstanceDesc, []int) error, cleanup func()) error {
if r.InstancesCount() <= 0 {
cleanup()
return fmt.Errorf("DoBatch: InstancesCount <= 0")
}
expectedTrackers := len(keys) * (r.ReplicationFactor() + 1) / r.InstancesCount()
@ -54,6 +57,7 @@ func DoBatch(ctx context.Context, op Operation, r ReadRing, keys []uint32, callb
for i, key := range keys {
replicationSet, err := r.Get(key, op, bufDescs[:0], bufHosts[:0], bufZones[:0])
if err != nil {
cleanup()
return err
}
itemTrackers[i].minSuccess = len(replicationSet.Instances) - replicationSet.MaxErrors

@ -9,13 +9,12 @@ import (
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/grafana/dskit/services"
"github.com/prometheus/client_golang/prometheus"
"github.com/weaveworks/common/user"
"google.golang.org/grpc/health/grpc_health_v1"
"github.com/cortexproject/cortex/pkg/util"
util_log "github.com/cortexproject/cortex/pkg/util/log"
"github.com/grafana/dskit/ring/util"
"github.com/grafana/dskit/services"
)
// PoolClient is the interface that should be implemented by a
@ -161,7 +160,7 @@ func (p *Pool) removeStaleClients() {
serviceAddrs, err := p.discovery()
if err != nil {
level.Error(util_log.Logger).Log("msg", "error removing stale clients", "err", err)
level.Error(p.logger).Log("msg", "error removing stale clients", "err", err)
return
}
@ -169,7 +168,7 @@ func (p *Pool) removeStaleClients() {
if util.StringsContain(serviceAddrs, addr) {
continue
}
level.Info(util_log.Logger).Log("msg", "removing stale client", "addr", addr)
level.Info(p.logger).Log("msg", "removing stale client", "addr", addr)
p.RemoveClientFor(addr)
}
}
@ -182,7 +181,7 @@ func (p *Pool) cleanUnhealthy() {
if ok {
err := healthCheck(client, p.cfg.HealthCheckTimeout)
if err != nil {
level.Warn(util_log.Logger).Log("msg", fmt.Sprintf("removing %s failing healthcheck", p.clientName), "addr", addr, "reason", err)
level.Warn(p.logger).Log("msg", fmt.Sprintf("removing %s failing healthcheck", p.clientName), "addr", addr, "reason", err)
p.RemoveClientFor(addr)
}
}

@ -3,7 +3,7 @@ package client
import (
"errors"
"github.com/cortexproject/cortex/pkg/ring"
"github.com/grafana/dskit/ring"
)
func NewRingServiceDiscovery(r ring.ReadRing) PoolServiceDiscovery {

@ -2,17 +2,16 @@ package ring
import (
"context"
"encoding/json"
"fmt"
"html/template"
"math"
"net/http"
"sort"
"strings"
"time"
"github.com/go-kit/log/level"
"github.com/cortexproject/cortex/pkg/util"
"github.com/cortexproject/cortex/pkg/util/log"
)
const pageContent = `
@ -20,10 +19,10 @@ const pageContent = `
<html>
<head>
<meta charset="UTF-8">
<title>Cortex Ring Status</title>
<title>Ring Status</title>
</head>
<body>
<h1>Cortex Ring Status</h1>
<h1>Ring Status</h1>
<p>Current time: {{ .Now }}</p>
<form action="" method="POST">
<input type="hidden" name="csrf_token" value="$__CSRF_TOKEN_PLACEHOLDER__">
@ -108,7 +107,7 @@ func (r *Ring) ServeHTTP(w http.ResponseWriter, req *http.Request) {
if req.Method == http.MethodPost {
ingesterID := req.FormValue("forget")
if err := r.forget(req.Context(), ingesterID); err != nil {
level.Error(log.WithContext(req.Context(), log.Logger)).Log("msg", "error forgetting instance", "err", err)
level.Error(r.logger).Log("msg", "error forgetting instance", "err", err)
}
// Implement PRG pattern to prevent double-POST and work with CSRF middleware.
@ -174,7 +173,7 @@ func (r *Ring) ServeHTTP(w http.ResponseWriter, req *http.Request) {
tokensParam := req.URL.Query().Get("tokens")
util.RenderHTTPResponse(w, struct {
renderHTTPResponse(w, struct {
Ingesters []interface{} `json:"shards"`
Now time.Time `json:"now"`
ShowTokens bool `json:"-"`
@ -184,3 +183,34 @@ func (r *Ring) ServeHTTP(w http.ResponseWriter, req *http.Request) {
ShowTokens: tokensParam == "true",
}, pageTemplate, req)
}
// RenderHTTPResponse either responds with json or a rendered html page using the passed in template
// by checking the Accepts header
func renderHTTPResponse(w http.ResponseWriter, v interface{}, t *template.Template, r *http.Request) {
accept := r.Header.Get("Accept")
if strings.Contains(accept, "application/json") {
writeJSONResponse(w, v)
return
}
err := t.Execute(w, v)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
// WriteJSONResponse writes some JSON as a HTTP response.
func writeJSONResponse(w http.ResponseWriter, v interface{}) {
w.Header().Set("Content-Type", "application/json")
data, err := json.Marshal(v)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// We ignore errors here, because we cannot do anything about them.
// Write will trigger sending Status code, so we cannot send a different status code afterwards.
// Also this isn't internal error, but error communicating with client.
_, _ = w.Write(data)
}

@ -9,38 +9,17 @@ import (
"sync"
"time"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/grafana/dskit/flagext"
"github.com/grafana/dskit/kv"
"github.com/grafana/dskit/services"
"github.com/pkg/errors"
perrors "github.com/pkg/errors"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"go.uber.org/atomic"
"github.com/cortexproject/cortex/pkg/util"
"github.com/cortexproject/cortex/pkg/util/log"
)
var (
consulHeartbeats = promauto.NewCounterVec(prometheus.CounterOpts{
Name: "cortex_member_consul_heartbeats_total",
Help: "The total number of heartbeats sent to consul.",
}, []string{"name"})
tokensOwned = promauto.NewGaugeVec(prometheus.GaugeOpts{
Name: "cortex_member_ring_tokens_owned",
Help: "The number of tokens owned in the ring.",
}, []string{"name"})
tokensToOwn = promauto.NewGaugeVec(prometheus.GaugeOpts{
Name: "cortex_member_ring_tokens_to_own",
Help: "The number of tokens to own in the ring.",
}, []string{"name"})
shutdownDuration = promauto.NewHistogramVec(prometheus.HistogramOpts{
Name: "cortex_shutdown_duration_seconds",
Help: "Duration (in seconds) of cortex shutdown procedure (ie transfer or flush).",
Buckets: prometheus.ExponentialBuckets(10, 2, 8), // Biggest bucket is 10*2^(9-1) = 2560, or 42 mins.
}, []string{"op", "status", "name"})
"github.com/grafana/dskit/flagext"
"github.com/grafana/dskit/kv"
"github.com/grafana/dskit/services"
dstime "github.com/grafana/dskit/time"
)
// LifecyclerConfig is the config to build a Lifecycler.
@ -48,16 +27,17 @@ type LifecyclerConfig struct {
RingConfig Config `yaml:"ring"`
// Config for the ingester lifecycle control
NumTokens int `yaml:"num_tokens"`
HeartbeatPeriod time.Duration `yaml:"heartbeat_period"`
ObservePeriod time.Duration `yaml:"observe_period"`
JoinAfter time.Duration `yaml:"join_after"`
MinReadyDuration time.Duration `yaml:"min_ready_duration"`
InfNames []string `yaml:"interface_names"`
FinalSleep time.Duration `yaml:"final_sleep"`
TokensFilePath string `yaml:"tokens_file_path"`
Zone string `yaml:"availability_zone"`
UnregisterOnShutdown bool `yaml:"unregister_on_shutdown"`
NumTokens int `yaml:"num_tokens"`
HeartbeatPeriod time.Duration `yaml:"heartbeat_period"`
ObservePeriod time.Duration `yaml:"observe_period"`
JoinAfter time.Duration `yaml:"join_after"`
MinReadyDuration time.Duration `yaml:"min_ready_duration"`
InfNames []string `yaml:"interface_names"`
FinalSleep time.Duration `yaml:"final_sleep"`
TokensFilePath string `yaml:"tokens_file_path"`
Zone string `yaml:"availability_zone"`
UnregisterOnShutdown bool `yaml:"unregister_on_shutdown"`
ReadinessCheckRingHealth bool `yaml:"readiness_check_ring_health"`
// For testing, you can override the address and ID of this ingester
Addr string `yaml:"address" doc:"hidden"`
@ -87,14 +67,13 @@ func (cfg *LifecyclerConfig) RegisterFlagsWithPrefix(prefix string, f *flag.Flag
f.DurationVar(&cfg.HeartbeatPeriod, prefix+"heartbeat-period", 5*time.Second, "Period at which to heartbeat to consul. 0 = disabled.")
f.DurationVar(&cfg.JoinAfter, prefix+"join-after", 0*time.Second, "Period to wait for a claim from another member; will join automatically after this.")
f.DurationVar(&cfg.ObservePeriod, prefix+"observe-period", 0*time.Second, "Observe tokens after generating to resolve collisions. Useful when using gossiping ring.")
f.DurationVar(&cfg.MinReadyDuration, prefix+"min-ready-duration", 1*time.Minute, "Minimum duration to wait before becoming ready. This is to work around race conditions with ingesters exiting and updating the ring.")
f.DurationVar(&cfg.MinReadyDuration, prefix+"min-ready-duration", 15*time.Second, "Minimum duration to wait after the internal readiness checks have passed but before succeeding the readiness endpoint. This is used to slowdown deployment controllers (eg. Kubernetes) after an instance is ready and before they proceed with a rolling update, to give the rest of the cluster instances enough time to receive ring updates.")
f.DurationVar(&cfg.FinalSleep, prefix+"final-sleep", 30*time.Second, "Duration to sleep for before exiting, to ensure metrics are scraped.")
f.StringVar(&cfg.TokensFilePath, prefix+"tokens-file-path", "", "File path where tokens are stored. If empty, tokens are not stored at shutdown and restored at startup.")
hostname, err := os.Hostname()
if err != nil {
level.Error(log.Logger).Log("msg", "failed to get hostname", "err", err)
os.Exit(1)
panic(fmt.Errorf("failed to get hostname %s", err))
}
cfg.InfNames = []string{"eth0", "en0"}
@ -104,6 +83,7 @@ func (cfg *LifecyclerConfig) RegisterFlagsWithPrefix(prefix string, f *flag.Flag
f.StringVar(&cfg.ID, prefix+"lifecycler.ID", hostname, "ID to register in the ring.")
f.StringVar(&cfg.Zone, prefix+"availability-zone", "", "The availability zone where this instance is running.")
f.BoolVar(&cfg.UnregisterOnShutdown, prefix+"unregister-on-shutdown", true, "Unregister from the ring upon clean shutdown. It can be useful to disable for rolling restarts with consistent naming in conjunction with -distributor.extend-writes=false.")
f.BoolVar(&cfg.ReadinessCheckRingHealth, prefix+"readiness-check-ring-health", true, "When enabled the readiness probe succeeds only after all instances are ACTIVE and healthy in the ring, otherwise only the instance itself is checked. This option should be disabled if in your cluster multiple instances can be rolled out simultaneously, otherwise rolling updates may be slowed down.")
}
// Lifecycler is responsible for managing the lifecycle of entries in the ring.
@ -135,19 +115,22 @@ type Lifecycler struct {
registeredAt time.Time
// Controls the ready-reporting
readyLock sync.Mutex
startTime time.Time
ready bool
readyLock sync.Mutex
ready bool
readySince time.Time
// Keeps stats updated at every heartbeat period
countersLock sync.RWMutex
healthyInstancesCount int
zonesCount int
lifecyclerMetrics *LifecyclerMetrics
logger log.Logger
}
// NewLifecycler creates new Lifecycler. It must be started via StartAsync.
func NewLifecycler(cfg LifecyclerConfig, flushTransferer FlushTransferer, ringName, ringKey string, flushOnShutdown bool, reg prometheus.Registerer) (*Lifecycler, error) {
addr, err := GetInstanceAddr(cfg.Addr, cfg.InfNames)
func NewLifecycler(cfg LifecyclerConfig, flushTransferer FlushTransferer, ringName, ringKey string, flushOnShutdown bool, logger log.Logger, reg prometheus.Registerer) (*Lifecycler, error) {
addr, err := GetInstanceAddr(cfg.Addr, cfg.InfNames, logger)
if err != nil {
return nil, err
}
@ -157,8 +140,8 @@ func NewLifecycler(cfg LifecyclerConfig, flushTransferer FlushTransferer, ringNa
store, err := kv.NewClient(
cfg.RingConfig.KVStore,
codec,
kv.RegistererWithKVName(prometheus.WrapRegistererWithPrefix("cortex_", reg), ringName+"-lifecycler"),
log.Logger,
kv.RegistererWithKVName(reg, ringName+"-lifecycler"),
logger,
)
if err != nil {
return nil, err
@ -166,7 +149,7 @@ func NewLifecycler(cfg LifecyclerConfig, flushTransferer FlushTransferer, ringNa
zone := cfg.Zone
if zone != "" {
log.WarnExperimentalUse("Zone aware replication")
level.Warn(logger).Log("msg", "experimental feature in use", "feature", "Zone aware replication")
}
// We do allow a nil FlushTransferer, but to keep the ring logic easier we assume
@ -176,10 +159,9 @@ func NewLifecycler(cfg LifecyclerConfig, flushTransferer FlushTransferer, ringNa
}
l := &Lifecycler{
cfg: cfg,
flushTransferer: flushTransferer,
KVStore: store,
cfg: cfg,
flushTransferer: flushTransferer,
KVStore: store,
Addr: fmt.Sprintf("%s:%d", addr, port),
ID: cfg.ID,
RingName: ringName,
@ -187,14 +169,13 @@ func NewLifecycler(cfg LifecyclerConfig, flushTransferer FlushTransferer, ringNa
flushOnShutdown: atomic.NewBool(flushOnShutdown),
unregisterOnShutdown: atomic.NewBool(cfg.UnregisterOnShutdown),
Zone: zone,
actorChan: make(chan func()),
state: PENDING,
startTime: time.Now(),
actorChan: make(chan func()),
state: PENDING,
lifecyclerMetrics: NewLifecyclerMetrics(ringName, reg),
logger: logger,
}
tokensToOwn.WithLabelValues(l.RingName).Set(float64(cfg.NumTokens))
l.lifecyclerMetrics.tokensToOwn.Set(float64(cfg.NumTokens))
l.BasicService = services.
NewBasicService(nil, l.loop, l.stopping).
@ -214,36 +195,64 @@ func (i *Lifecycler) CheckReady(ctx context.Context) error {
return nil
}
// Ingester always take at least minReadyDuration to become ready to work
// around race conditions with ingesters exiting and updating the ring
if time.Since(i.startTime) < i.cfg.MinReadyDuration {
return fmt.Errorf("waiting for %v after startup", i.cfg.MinReadyDuration)
if err := i.checkRingHealthForReadiness(ctx); err != nil {
// Reset the min ready duration counter.
i.readySince = time.Time{}
return err
}
desc, err := i.KVStore.Get(ctx, i.RingKey)
if err != nil {
level.Error(log.Logger).Log("msg", "error talking to the KV store", "ring", i.RingName, "err", err)
return fmt.Errorf("error talking to the KV store: %s", err)
// Honor the min ready duration. The duration counter start after all readiness checks have
// passed.
if i.readySince.IsZero() {
i.readySince = time.Now()
}
if time.Since(i.readySince) < i.cfg.MinReadyDuration {
return fmt.Errorf("waiting for %v after being ready", i.cfg.MinReadyDuration)
}
i.ready = true
return nil
}
func (i *Lifecycler) checkRingHealthForReadiness(ctx context.Context) error {
// Ensure the instance holds some tokens.
if len(i.getTokens()) == 0 {
return fmt.Errorf("this instance owns no tokens")
}
// If ring health checking is enabled we make sure all instances in the ring are ACTIVE and healthy,
// otherwise we just check this instance.
desc, err := i.KVStore.Get(ctx, i.RingKey)
if err != nil {
level.Error(i.logger).Log("msg", "error talking to the KV store", "ring", i.RingName, "err", err)
return fmt.Errorf("error talking to the KV store: %s", err)
}
ringDesc, ok := desc.(*Desc)
if !ok || ringDesc == nil {
return fmt.Errorf("no ring returned from the KV store")
}
if err := ringDesc.Ready(time.Now(), i.cfg.RingConfig.HeartbeatTimeout); err != nil {
level.Warn(log.Logger).Log("msg", "found an existing instance(s) with a problem in the ring, "+
"this instance cannot become ready until this problem is resolved. "+
"The /ring http endpoint on the distributor (or single binary) provides visibility into the ring.",
"ring", i.RingName, "err", err)
return err
if i.cfg.ReadinessCheckRingHealth {
if err := ringDesc.IsReady(time.Now(), i.cfg.RingConfig.HeartbeatTimeout); err != nil {
level.Warn(i.logger).Log("msg", "found an existing instance(s) with a problem in the ring, "+
"this instance cannot become ready until this problem is resolved. "+
"The /ring http endpoint on the distributor (or single binary) provides visibility into the ring.",
"ring", i.RingName, "err", err)
return err
}
} else {
instance, ok := ringDesc.Ingesters[i.ID]
if !ok {
return fmt.Errorf("instance %s not found in the ring", i.ID)
}
if err := instance.IsReady(time.Now(), i.cfg.RingConfig.HeartbeatTimeout); err != nil {
return err
}
}
i.ready = true
return nil
}
@ -294,7 +303,7 @@ func (i *Lifecycler) getTokens() Tokens {
}
func (i *Lifecycler) setTokens(tokens Tokens) {
tokensOwned.WithLabelValues(i.RingName).Set(float64(len(tokens)))
i.lifecyclerMetrics.tokensOwned.Set(float64(len(tokens)))
i.stateMtx.Lock()
defer i.stateMtx.Unlock()
@ -302,7 +311,7 @@ func (i *Lifecycler) setTokens(tokens Tokens) {
i.tokens = tokens
if i.cfg.TokensFilePath != "" {
if err := i.tokens.StoreToFile(i.cfg.TokensFilePath); err != nil {
level.Error(log.Logger).Log("msg", "error storing tokens to disk", "path", i.cfg.TokensFilePath, "err", err)
level.Error(i.logger).Log("msg", "error storing tokens to disk", "path", i.cfg.TokensFilePath, "err", err)
}
}
}
@ -342,7 +351,7 @@ func (i *Lifecycler) ClaimTokensFor(ctx context.Context, ingesterID string) erro
ing := ringDesc.Ingesters[i.ID]
ing.Timestamp = time.Now().Unix()
// Tokens of the leaving ingester may have been generated by an older version of Cortex which
// Tokens of the leaving ingester may have been generated by an older version which
// doesn't guarantee sorted tokens, so we enforce sorting here.
sort.Sort(tokens)
ing.Tokens = tokens
@ -352,7 +361,7 @@ func (i *Lifecycler) ClaimTokensFor(ctx context.Context, ingesterID string) erro
}
if err := i.KVStore.CAS(ctx, i.RingKey, claimTokens); err != nil {
level.Error(log.Logger).Log("msg", "Failed to write to the KV store", "ring", i.RingName, "err", err)
level.Error(i.logger).Log("msg", "Failed to write to the KV store", "ring", i.RingName, "err", err)
}
i.setTokens(tokens)
@ -392,19 +401,19 @@ func (i *Lifecycler) loop(ctx context.Context) error {
// We do various period tasks
autoJoinAfter := time.After(i.cfg.JoinAfter)
var observeChan <-chan time.Time = nil
var observeChan <-chan time.Time
heartbeatTickerStop, heartbeatTickerChan := util.NewDisableableTicker(i.cfg.HeartbeatPeriod)
heartbeatTickerStop, heartbeatTickerChan := dstime.NewDisableableTicker(i.cfg.HeartbeatPeriod)
defer heartbeatTickerStop()
for {
select {
case <-autoJoinAfter:
level.Debug(log.Logger).Log("msg", "JoinAfter expired", "ring", i.RingName)
level.Debug(i.logger).Log("msg", "JoinAfter expired", "ring", i.RingName)
// Will only fire once, after auto join timeout. If we haven't entered "JOINING" state,
// then pick some tokens and enter ACTIVE state.
if i.GetState() == PENDING {
level.Info(log.Logger).Log("msg", "auto-joining cluster after timeout", "ring", i.RingName)
level.Info(i.logger).Log("msg", "auto-joining cluster after timeout", "ring", i.RingName)
if i.cfg.ObservePeriod > 0 {
// let's observe the ring. By using JOINING state, this ingester will be ignored by LEAVING
@ -413,7 +422,7 @@ func (i *Lifecycler) loop(ctx context.Context) error {
return perrors.Wrapf(err, "failed to pick tokens in the KV store, ring: %s", i.RingName)
}
level.Info(log.Logger).Log("msg", "observing tokens before going ACTIVE", "ring", i.RingName)
level.Info(i.logger).Log("msg", "observing tokens before going ACTIVE", "ring", i.RingName)
observeChan = time.After(i.cfg.ObservePeriod)
} else {
if err := i.autoJoin(context.Background(), ACTIVE); err != nil {
@ -428,33 +437,33 @@ func (i *Lifecycler) loop(ctx context.Context) error {
observeChan = nil
if s := i.GetState(); s != JOINING {
level.Error(log.Logger).Log("msg", "unexpected state while observing tokens", "state", s, "ring", i.RingName)
level.Error(i.logger).Log("msg", "unexpected state while observing tokens", "state", s, "ring", i.RingName)
}
if i.verifyTokens(context.Background()) {
level.Info(log.Logger).Log("msg", "token verification successful", "ring", i.RingName)
level.Info(i.logger).Log("msg", "token verification successful", "ring", i.RingName)
err := i.changeState(context.Background(), ACTIVE)
if err != nil {
level.Error(log.Logger).Log("msg", "failed to set state to ACTIVE", "ring", i.RingName, "err", err)
level.Error(i.logger).Log("msg", "failed to set state to ACTIVE", "ring", i.RingName, "err", err)
}
} else {
level.Info(log.Logger).Log("msg", "token verification failed, observing", "ring", i.RingName)
level.Info(i.logger).Log("msg", "token verification failed, observing", "ring", i.RingName)
// keep observing
observeChan = time.After(i.cfg.ObservePeriod)
}
case <-heartbeatTickerChan:
consulHeartbeats.WithLabelValues(i.RingName).Inc()
i.lifecyclerMetrics.consulHeartbeats.Inc()
if err := i.updateConsul(context.Background()); err != nil {
level.Error(log.Logger).Log("msg", "failed to write to the KV store, sleeping", "ring", i.RingName, "err", err)
level.Error(i.logger).Log("msg", "failed to write to the KV store, sleeping", "ring", i.RingName, "err", err)
}
case f := <-i.actorChan:
f()
case <-ctx.Done():
level.Info(log.Logger).Log("msg", "lifecycler loop() exited gracefully", "ring", i.RingName)
level.Info(i.logger).Log("msg", "lifecycler loop() exited gracefully", "ring", i.RingName)
return nil
}
}
@ -471,13 +480,13 @@ func (i *Lifecycler) stopping(runningError error) error {
return nil
}
heartbeatTickerStop, heartbeatTickerChan := util.NewDisableableTicker(i.cfg.HeartbeatPeriod)
heartbeatTickerStop, heartbeatTickerChan := dstime.NewDisableableTicker(i.cfg.HeartbeatPeriod)
defer heartbeatTickerStop()
// Mark ourselved as Leaving so no more samples are send to us.
err := i.changeState(context.Background(), LEAVING)
if err != nil {
level.Error(log.Logger).Log("msg", "failed to set state to LEAVING", "ring", i.RingName, "err", err)
level.Error(i.logger).Log("msg", "failed to set state to LEAVING", "ring", i.RingName, "err", err)
}
// Do the transferring / flushing on a background goroutine so we can continue
@ -492,9 +501,9 @@ heartbeatLoop:
for {
select {
case <-heartbeatTickerChan:
consulHeartbeats.WithLabelValues(i.RingName).Inc()
i.lifecyclerMetrics.consulHeartbeats.Inc()
if err := i.updateConsul(context.Background()); err != nil {
level.Error(log.Logger).Log("msg", "failed to write to the KV store, sleeping", "ring", i.RingName, "err", err)
level.Error(i.logger).Log("msg", "failed to write to the KV store, sleeping", "ring", i.RingName, "err", err)
}
case <-done:
@ -506,7 +515,7 @@ heartbeatLoop:
if err := i.unregister(context.Background()); err != nil {
return perrors.Wrapf(err, "failed to unregister from the KV store, ring: %s", i.RingName)
}
level.Info(log.Logger).Log("msg", "instance removed from the KV store", "ring", i.RingName)
level.Info(i.logger).Log("msg", "instance removed from the KV store", "ring", i.RingName)
}
return nil
@ -525,10 +534,10 @@ func (i *Lifecycler) initRing(ctx context.Context) error {
if i.cfg.TokensFilePath != "" {
tokensFromFile, err = LoadTokensFromFile(i.cfg.TokensFilePath)
if err != nil && !os.IsNotExist(err) {
level.Error(log.Logger).Log("msg", "error loading tokens from file", "err", err)
level.Error(i.logger).Log("msg", "error loading tokens from file", "err", err)
}
} else {
level.Info(log.Logger).Log("msg", "not loading tokens from file, tokens file path is empty")
level.Info(i.logger).Log("msg", "not loading tokens from file, tokens file path is empty")
}
err = i.KVStore.CAS(ctx, i.RingKey, func(in interface{}) (out interface{}, retry bool, err error) {
@ -547,7 +556,7 @@ func (i *Lifecycler) initRing(ctx context.Context) error {
// We use the tokens from the file only if it does not exist in the ring yet.
if len(tokensFromFile) > 0 {
level.Info(log.Logger).Log("msg", "adding tokens from file", "num_tokens", len(tokensFromFile))
level.Info(i.logger).Log("msg", "adding tokens from file", "num_tokens", len(tokensFromFile))
if len(tokensFromFile) >= i.cfg.NumTokens {
i.setState(ACTIVE)
}
@ -557,7 +566,7 @@ func (i *Lifecycler) initRing(ctx context.Context) error {
}
// Either we are a new ingester, or consul must have restarted
level.Info(log.Logger).Log("msg", "instance not found in ring, adding with no tokens", "ring", i.RingName)
level.Info(i.logger).Log("msg", "instance not found in ring, adding with no tokens", "ring", i.RingName)
ringDesc.AddIngester(i.ID, i.Addr, i.Zone, []uint32{}, i.GetState(), registeredAt)
return ringDesc, true, nil
}
@ -571,7 +580,7 @@ func (i *Lifecycler) initRing(ctx context.Context) error {
// to set it back to PENDING in order to start the lifecycle from the
// beginning.
if instanceDesc.State == JOINING {
level.Warn(log.Logger).Log("msg", "instance found in ring as JOINING, setting to PENDING",
level.Warn(i.logger).Log("msg", "instance found in ring as JOINING, setting to PENDING",
"ring", i.RingName)
instanceDesc.State = PENDING
return ringDesc, true, nil
@ -589,7 +598,7 @@ func (i *Lifecycler) initRing(ctx context.Context) error {
tokens, _ := ringDesc.TokensFor(i.ID)
i.setTokens(tokens)
level.Info(log.Logger).Log("msg", "existing entry found in ring", "state", i.GetState(), "tokens", len(tokens), "ring", i.RingName)
level.Info(i.logger).Log("msg", "existing entry found in ring", "state", i.GetState(), "tokens", len(tokens), "ring", i.RingName)
// Update the ring if the instance has been changed and the heartbeat is disabled.
// We dont need to update KV here when heartbeat is enabled as this info will eventually be update on KV
@ -634,7 +643,7 @@ func (i *Lifecycler) verifyTokens(ctx context.Context) bool {
// uh, oh... our tokens are not our anymore. Let's try new ones.
needTokens := i.cfg.NumTokens - len(ringTokens)
level.Info(log.Logger).Log("msg", "generating new tokens", "count", needTokens, "ring", i.RingName)
level.Info(i.logger).Log("msg", "generating new tokens", "count", needTokens, "ring", i.RingName)
newTokens := GenerateTokens(needTokens, takenTokens)
ringTokens = append(ringTokens, newTokens...)
@ -653,7 +662,7 @@ func (i *Lifecycler) verifyTokens(ctx context.Context) bool {
})
if err != nil {
level.Error(log.Logger).Log("msg", "failed to verify tokens", "ring", i.RingName, "err", err)
level.Error(i.logger).Log("msg", "failed to verify tokens", "ring", i.RingName, "err", err)
return false
}
@ -692,7 +701,7 @@ func (i *Lifecycler) autoJoin(ctx context.Context, targetState InstanceState) er
// At this point, we should not have any tokens, and we should be in PENDING state.
myTokens, takenTokens := ringDesc.TokensFor(i.ID)
if len(myTokens) > 0 {
level.Error(log.Logger).Log("msg", "tokens already exist for this instance - wasn't expecting any!", "num_tokens", len(myTokens), "ring", i.RingName)
level.Error(i.logger).Log("msg", "tokens already exist for this instance - wasn't expecting any!", "num_tokens", len(myTokens), "ring", i.RingName)
}
newTokens := GenerateTokens(i.cfg.NumTokens-len(myTokens), takenTokens)
@ -730,7 +739,7 @@ func (i *Lifecycler) updateConsul(ctx context.Context) error {
instanceDesc, ok := ringDesc.Ingesters[i.ID]
if !ok {
// consul must have restarted
level.Info(log.Logger).Log("msg", "found empty ring, inserting tokens", "ring", i.RingName)
level.Info(i.logger).Log("msg", "found empty ring, inserting tokens", "ring", i.RingName)
ringDesc.AddIngester(i.ID, i.Addr, i.Zone, i.getTokens(), i.GetState(), i.getRegisteredAt())
} else {
instanceDesc.Timestamp = time.Now().Unix()
@ -765,7 +774,7 @@ func (i *Lifecycler) changeState(ctx context.Context, state InstanceState) error
return fmt.Errorf("Changing instance state from %v -> %v is disallowed", currState, state)
}
level.Info(log.Logger).Log("msg", "changing instance state from", "old_state", currState, "new_state", state, "ring", i.RingName)
level.Info(i.logger).Log("msg", "changing instance state from", "old_state", currState, "new_state", state, "ring", i.RingName)
i.setState(state)
return i.updateConsul(ctx)
}
@ -820,20 +829,20 @@ func (i *Lifecycler) processShutdown(ctx context.Context) {
transferStart := time.Now()
if err := i.flushTransferer.TransferOut(ctx); err != nil {
if err == ErrTransferDisabled {
level.Info(log.Logger).Log("msg", "transfers are disabled")
level.Info(i.logger).Log("msg", "transfers are disabled")
} else {
level.Error(log.Logger).Log("msg", "failed to transfer chunks to another instance", "ring", i.RingName, "err", err)
shutdownDuration.WithLabelValues("transfer", "fail", i.RingName).Observe(time.Since(transferStart).Seconds())
level.Error(i.logger).Log("msg", "failed to transfer chunks to another instance", "ring", i.RingName, "err", err)
i.lifecyclerMetrics.shutdownDuration.WithLabelValues("transfer", "fail").Observe(time.Since(transferStart).Seconds())
}
} else {
flushRequired = false
shutdownDuration.WithLabelValues("transfer", "success", i.RingName).Observe(time.Since(transferStart).Seconds())
i.lifecyclerMetrics.shutdownDuration.WithLabelValues("transfer", "success").Observe(time.Since(transferStart).Seconds())
}
if flushRequired {
flushStart := time.Now()
i.flushTransferer.Flush()
shutdownDuration.WithLabelValues("flush", "success", i.RingName).Observe(time.Since(flushStart).Seconds())
i.lifecyclerMetrics.shutdownDuration.WithLabelValues("flush", "success").Observe(time.Since(flushStart).Seconds())
}
// Sleep so the shutdownDuration metric can be collected.
@ -842,7 +851,7 @@ func (i *Lifecycler) processShutdown(ctx context.Context) {
// unregister removes our entry from consul.
func (i *Lifecycler) unregister(ctx context.Context) error {
level.Debug(log.Logger).Log("msg", "unregistering instance from ring", "ring", i.RingName)
level.Debug(i.logger).Log("msg", "unregistering instance from ring", "ring", i.RingName)
return i.KVStore.CAS(ctx, i.RingKey, func(in interface{}) (out interface{}, retry bool, err error) {
if in == nil {

@ -0,0 +1,40 @@
package ring
import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
)
type LifecyclerMetrics struct {
consulHeartbeats prometheus.Counter
tokensOwned prometheus.Gauge
tokensToOwn prometheus.Gauge
shutdownDuration *prometheus.HistogramVec
}
func NewLifecyclerMetrics(ringName string, reg prometheus.Registerer) *LifecyclerMetrics {
return &LifecyclerMetrics{
consulHeartbeats: promauto.With(reg).NewCounter(prometheus.CounterOpts{
Name: "member_consul_heartbeats_total",
Help: "The total number of heartbeats sent to consul.",
ConstLabels: prometheus.Labels{"name": ringName},
}),
tokensOwned: promauto.With(reg).NewGauge(prometheus.GaugeOpts{
Name: "member_ring_tokens_owned",
Help: "The number of tokens owned in the ring.",
ConstLabels: prometheus.Labels{"name": ringName},
}),
tokensToOwn: promauto.With(reg).NewGauge(prometheus.GaugeOpts{
Name: "member_ring_tokens_to_own",
Help: "The number of tokens to own in the ring.",
ConstLabels: prometheus.Labels{"name": ringName},
}),
shutdownDuration: promauto.With(reg).NewHistogramVec(prometheus.HistogramOpts{
Name: "shutdown_duration_seconds",
Help: "Duration (in seconds) of shutdown procedure (ie transfer or flush).",
Buckets: prometheus.ExponentialBuckets(10, 2, 8), // Biggest bucket is 10*2^(9-1) = 2560, or 42 mins.
ConstLabels: prometheus.Labels{"name": ringName},
}, []string{"op", "status"}),
}
}

@ -7,6 +7,7 @@ import (
"time"
"github.com/gogo/protobuf/proto"
"github.com/grafana/dskit/kv/codec"
"github.com/grafana/dskit/kv/memberlist"
)
@ -96,16 +97,15 @@ func (d *Desc) FindIngestersByState(state InstanceState) []InstanceDesc {
return result
}
// Ready returns no error when all ingesters are active and healthy.
func (d *Desc) Ready(now time.Time, heartbeatTimeout time.Duration) error {
// IsReady returns no error when all instance are ACTIVE and healthy,
// and the ring has some tokens.
func (d *Desc) IsReady(now time.Time, heartbeatTimeout time.Duration) error {
numTokens := 0
for id, ingester := range d.Ingesters {
if !ingester.IsHeartbeatHealthy(heartbeatTimeout, now) {
return fmt.Errorf("instance %s past heartbeat timeout", id)
} else if ingester.State != ACTIVE {
return fmt.Errorf("instance %s in state %v", id, ingester.State)
for _, instance := range d.Ingesters {
if err := instance.IsReady(now, heartbeatTimeout); err != nil {
return err
}
numTokens += len(ingester.Tokens)
numTokens += len(instance.Tokens)
}
if numTokens == 0 {
@ -147,6 +147,17 @@ func (i *InstanceDesc) IsHeartbeatHealthy(heartbeatTimeout time.Duration, now ti
return now.Sub(time.Unix(i.Timestamp, 0)) <= heartbeatTimeout
}
// IsReady returns no error if the instance is ACTIVE and healthy.
func (i *InstanceDesc) IsReady(now time.Time, heartbeatTimeout time.Duration) error {
if !i.IsHeartbeatHealthy(heartbeatTimeout, now) {
return fmt.Errorf("instance %s past heartbeat timeout", i.Addr)
}
if i.State != ACTIVE {
return fmt.Errorf("instance %s in state %v", i.Addr, i.State)
}
return nil
}
// Merge merges other ring into this one. Returns sub-ring that represents the change,
// and can be sent out to other clients.
//
@ -423,7 +434,7 @@ func (d *Desc) getTokensInfo() map[uint32]instanceInfo {
func (d *Desc) GetTokens() []uint32 {
instances := make([][]uint32, 0, len(d.Ingesters))
for _, instance := range d.Ingesters {
// Tokens may not be sorted for an older version of Cortex which, so we enforce sorting here.
// Tokens may not be sorted for an older version which, so we enforce sorting here.
tokens := instance.Tokens
if !sort.IsSorted(Tokens(tokens)) {
sort.Sort(Tokens(tokens))
@ -440,7 +451,7 @@ func (d *Desc) GetTokens() []uint32 {
func (d *Desc) getTokensByZone() map[string][]uint32 {
zones := map[string][][]uint32{}
for _, instance := range d.Ingesters {
// Tokens may not be sorted for an older version of Cortex which, so we enforce sorting here.
// Tokens may not be sorted for an older version which, so we enforce sorting here.
tokens := instance.Tokens
if !sort.IsSorted(Tokens(tokens)) {
sort.Sort(Tokens(tokens))
@ -455,6 +466,7 @@ func (d *Desc) getTokensByZone() map[string][]uint32 {
type CompareResult int
// CompareResult responses
const (
Equal CompareResult = iota // Both rings contain same exact instances.
EqualButStatesAndTimestamps // Both rings contain the same instances with the same data except states and timestamps (may differ).

@ -11,15 +11,19 @@ import (
"sync"
"time"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/grafana/dskit/kv"
"github.com/grafana/dskit/services"
"github.com/pkg/errors"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"github.com/grafana/dskit/kv"
shardUtil "github.com/grafana/dskit/ring/shard"
"github.com/grafana/dskit/ring/util"
"github.com/grafana/dskit/services"
"github.com/cortexproject/cortex/pkg/util"
"github.com/cortexproject/cortex/pkg/util/log"
util_math "github.com/cortexproject/cortex/pkg/util/math"
"github.com/grafana/dskit/flagext"
dsmath "github.com/grafana/dskit/math"
)
const (
@ -44,7 +48,6 @@ const (
// ReadRing represents the read interface to the ring.
type ReadRing interface {
prometheus.Collector
// Get returns n (or more) instances which form the replicas for the given key.
// bufDescs, bufHosts and bufZones are slices to be overwritten for the return value
@ -99,6 +102,7 @@ var (
// WriteNoExtend is like Write, but with no replicaset extension.
WriteNoExtend = NewOp([]InstanceState{ACTIVE}, nil)
// Read operation that extends the replica set if an instance is not ACTIVE or LEAVING
Read = NewOp([]InstanceState{ACTIVE, PENDING, LEAVING}, func(s InstanceState) bool {
// To match Write with extended replica set we have to also increase the
// size of the replica set for Read, but we can read from LEAVING ingesters.
@ -128,10 +132,11 @@ var (
// Config for a Ring
type Config struct {
KVStore kv.Config `yaml:"kvstore"`
HeartbeatTimeout time.Duration `yaml:"heartbeat_timeout"`
ReplicationFactor int `yaml:"replication_factor"`
ZoneAwarenessEnabled bool `yaml:"zone_awareness_enabled"`
KVStore kv.Config `yaml:"kvstore"`
HeartbeatTimeout time.Duration `yaml:"heartbeat_timeout"`
ReplicationFactor int `yaml:"replication_factor"`
ZoneAwarenessEnabled bool `yaml:"zone_awareness_enabled"`
ExcludedZones flagext.StringSliceCSV `yaml:"excluded_zones"`
// Whether the shuffle-sharding subring cache is disabled. This option is set
// internally and never exposed to the user.
@ -150,6 +155,7 @@ func (cfg *Config) RegisterFlagsWithPrefix(prefix string, f *flag.FlagSet) {
f.DurationVar(&cfg.HeartbeatTimeout, prefix+"ring.heartbeat-timeout", time.Minute, "The heartbeat timeout after which ingesters are skipped for reads/writes. 0 = never (timeout disabled).")
f.IntVar(&cfg.ReplicationFactor, prefix+"distributor.replication-factor", 3, "The number of ingesters to write to and read from.")
f.BoolVar(&cfg.ZoneAwarenessEnabled, prefix+"distributor.zone-awareness-enabled", false, "True to enable the zone-awareness and replicate ingested samples across different availability zones.")
f.Var(&cfg.ExcludedZones, prefix+"distributor.excluded-zones", "Comma-separated list of zones to exclude from the ring. Instances in excluded zones will be filtered out from the ring.")
}
type instanceInfo struct {
@ -187,11 +193,13 @@ type Ring struct {
// If set to nil, no caching is done (used by tests, and subrings).
shuffledSubringCache map[subringCacheKey]*Ring
memberOwnershipDesc *prometheus.Desc
numMembersDesc *prometheus.Desc
totalTokensDesc *prometheus.Desc
numTokensDesc *prometheus.Desc
oldestTimestampDesc *prometheus.Desc
memberOwnershipGaugeVec *prometheus.GaugeVec
numMembersGaugeVec *prometheus.GaugeVec
totalTokensGauge prometheus.Gauge
numTokensGaugeVec *prometheus.GaugeVec
oldestTimestampGaugeVec *prometheus.GaugeVec
logger log.Logger
}
type subringCacheKey struct {
@ -200,23 +208,23 @@ type subringCacheKey struct {
}
// New creates a new Ring. Being a service, Ring needs to be started to do anything.
func New(cfg Config, name, key string, reg prometheus.Registerer) (*Ring, error) {
func New(cfg Config, name, key string, logger log.Logger, reg prometheus.Registerer) (*Ring, error) {
codec := GetCodec()
// Suffix all client names with "-ring" to denote this kv client is used by the ring
store, err := kv.NewClient(
cfg.KVStore,
codec,
kv.RegistererWithKVName(prometheus.WrapRegistererWithPrefix("cortex_", reg), name+"-ring"),
log.Logger,
kv.RegistererWithKVName(reg, name+"-ring"),
logger,
)
if err != nil {
return nil, err
}
return NewWithStoreClientAndStrategy(cfg, name, key, store, NewDefaultReplicationStrategy())
return NewWithStoreClientAndStrategy(cfg, name, key, store, NewDefaultReplicationStrategy(), reg, logger)
}
func NewWithStoreClientAndStrategy(cfg Config, name, key string, store kv.Client, strategy ReplicationStrategy) (*Ring, error) {
func NewWithStoreClientAndStrategy(cfg Config, name, key string, store kv.Client, strategy ReplicationStrategy, reg prometheus.Registerer, logger log.Logger) (*Ring, error) {
if cfg.ReplicationFactor <= 0 {
return nil, fmt.Errorf("ReplicationFactor must be greater than zero: %d", cfg.ReplicationFactor)
}
@ -228,36 +236,31 @@ func NewWithStoreClientAndStrategy(cfg Config, name, key string, store kv.Client
strategy: strategy,
ringDesc: &Desc{},
shuffledSubringCache: map[subringCacheKey]*Ring{},
memberOwnershipDesc: prometheus.NewDesc(
"cortex_ring_member_ownership_percent",
"The percent ownership of the ring by member",
[]string{"member"},
map[string]string{"name": name},
),
numMembersDesc: prometheus.NewDesc(
"cortex_ring_members",
"Number of members in the ring",
[]string{"state"},
map[string]string{"name": name},
),
totalTokensDesc: prometheus.NewDesc(
"cortex_ring_tokens_total",
"Number of tokens in the ring",
nil,
map[string]string{"name": name},
),
numTokensDesc: prometheus.NewDesc(
"cortex_ring_tokens_owned",
"The number of tokens in the ring owned by the member",
[]string{"member"},
map[string]string{"name": name},
),
oldestTimestampDesc: prometheus.NewDesc(
"cortex_ring_oldest_member_timestamp",
"Timestamp of the oldest member in the ring.",
[]string{"state"},
map[string]string{"name": name},
),
memberOwnershipGaugeVec: promauto.With(reg).NewGaugeVec(prometheus.GaugeOpts{
Name: "ring_member_ownership_percent",
Help: "The percent ownership of the ring by member",
ConstLabels: map[string]string{"name": name}},
[]string{"member"}),
numMembersGaugeVec: promauto.With(reg).NewGaugeVec(prometheus.GaugeOpts{
Name: "ring_members",
Help: "Number of members in the ring",
ConstLabels: map[string]string{"name": name}},
[]string{"state"}),
totalTokensGauge: promauto.With(reg).NewGauge(prometheus.GaugeOpts{
Name: "ring_tokens_total",
Help: "Number of tokens in the ring",
ConstLabels: map[string]string{"name": name}}),
numTokensGaugeVec: promauto.With(reg).NewGaugeVec(prometheus.GaugeOpts{
Name: "ring_tokens_owned",
Help: "The number of tokens in the ring owned by the member",
ConstLabels: map[string]string{"name": name}},
[]string{"member"}),
oldestTimestampGaugeVec: promauto.With(reg).NewGaugeVec(prometheus.GaugeOpts{
Name: "ring_oldest_member_timestamp",
Help: "Timestamp of the oldest member in the ring.",
ConstLabels: map[string]string{"name": name}},
[]string{"state"}),
logger: logger,
}
r.Service = services.NewBasicService(r.starting, r.loop, nil).WithName(fmt.Sprintf("%s ring client", name))
@ -272,19 +275,35 @@ func (r *Ring) starting(ctx context.Context) error {
if err != nil {
return errors.Wrap(err, "unable to initialise ring state")
}
if value == nil {
level.Info(log.Logger).Log("msg", "ring doesn't exist in KV store yet")
return nil
if value != nil {
r.updateRingState(value.(*Desc))
} else {
level.Info(r.logger).Log("msg", "ring doesn't exist in KV store yet")
}
r.updateRingState(value.(*Desc))
return nil
}
func (r *Ring) loop(ctx context.Context) error {
// Update the ring metrics at start of the main loop.
r.updateRingMetrics()
go func() {
// Start metrics update ticker to update the ring metrics.
ticker := time.NewTicker(10 * time.Second)
defer ticker.Stop()
for {
select {
case <-ticker.C:
r.updateRingMetrics()
case <-ctx.Done():
return
}
}
}()
r.KVClient.WatchKey(ctx, r.key, func(value interface{}) bool {
if value == nil {
level.Info(log.Logger).Log("msg", "ring doesn't exist in KV store yet")
level.Info(r.logger).Log("msg", "ring doesn't exist in KV store yet")
return true
}
@ -299,6 +318,15 @@ func (r *Ring) updateRingState(ringDesc *Desc) {
prevRing := r.ringDesc
r.mtx.RUnlock()
// Filter out all instances belonging to excluded zones.
if len(r.cfg.ExcludedZones) > 0 {
for instanceID, instance := range ringDesc.Ingesters {
if util.StringsContain(r.cfg.ExcludedZones, instance.Zone) {
delete(ringDesc.Ingesters, instanceID)
}
}
}
rc := prevRing.RingCompare(ringDesc)
if rc == Equal || rc == EqualButStatesAndTimestamps {
// No need to update tokens or zones. Only states and timestamps
@ -454,7 +482,7 @@ func (r *Ring) GetReplicationSetForOperation(op Operation) (ReplicationSet, erro
// Given data is replicated to RF different zones, we can tolerate a number of
// RF/2 failing zones. However, we need to protect from the case the ring currently
// contains instances in a number of zones < RF.
numReplicatedZones := util_math.Min(len(r.ringZones), r.cfg.ReplicationFactor)
numReplicatedZones := dsmath.Min(len(r.ringZones), r.cfg.ReplicationFactor)
minSuccessZones := (numReplicatedZones / 2) + 1
maxUnavailableZones = minSuccessZones - 1
@ -505,15 +533,6 @@ func (r *Ring) GetReplicationSetForOperation(op Operation) (ReplicationSet, erro
}, nil
}
// Describe implements prometheus.Collector.
func (r *Ring) Describe(ch chan<- *prometheus.Desc) {
ch <- r.memberOwnershipDesc
ch <- r.numMembersDesc
ch <- r.totalTokensDesc
ch <- r.oldestTimestampDesc
ch <- r.numTokensDesc
}
// countTokens returns the number of tokens and tokens within the range for each instance.
// The ring read lock must be already taken when calling this function.
func (r *Ring) countTokens() (map[string]uint32, map[string]uint32) {
@ -545,25 +564,15 @@ func (r *Ring) countTokens() (map[string]uint32, map[string]uint32) {
return numTokens, owned
}
// Collect implements prometheus.Collector.
func (r *Ring) Collect(ch chan<- prometheus.Metric) {
// updateRingMetrics updates ring metrics.
func (r *Ring) updateRingMetrics() {
r.mtx.RLock()
defer r.mtx.RUnlock()
numTokens, ownedRange := r.countTokens()
for id, totalOwned := range ownedRange {
ch <- prometheus.MustNewConstMetric(
r.memberOwnershipDesc,
prometheus.GaugeValue,
float64(totalOwned)/float64(math.MaxUint32),
id,
)
ch <- prometheus.MustNewConstMetric(
r.numTokensDesc,
prometheus.GaugeValue,
float64(numTokens[id]),
id,
)
r.memberOwnershipGaugeVec.WithLabelValues(id).Set(float64(totalOwned) / float64(math.MaxUint32))
r.numTokensGaugeVec.WithLabelValues(id).Set(float64(numTokens[id]))
}
numByState := map[string]int{}
@ -587,27 +596,12 @@ func (r *Ring) Collect(ch chan<- prometheus.Metric) {
}
for state, count := range numByState {
ch <- prometheus.MustNewConstMetric(
r.numMembersDesc,
prometheus.GaugeValue,
float64(count),
state,
)
r.numMembersGaugeVec.WithLabelValues(state).Set(float64(count))
}
for state, timestamp := range oldestTimestampByState {
ch <- prometheus.MustNewConstMetric(
r.oldestTimestampDesc,
prometheus.GaugeValue,
float64(timestamp),
state,
)
}
ch <- prometheus.MustNewConstMetric(
r.totalTokensDesc,
prometheus.GaugeValue,
float64(len(r.ringTokens)),
)
r.oldestTimestampGaugeVec.WithLabelValues(state).Set(float64(timestamp))
}
r.totalTokensGauge.Set(float64(len(r.ringTokens)))
}
// ShuffleShard returns a subring for the provided identifier (eg. a tenant ID)
@ -671,7 +665,7 @@ func (r *Ring) shuffleShard(identifier string, size int, lookbackPeriod time.Dur
var actualZones []string
if r.cfg.ZoneAwarenessEnabled {
numInstancesPerZone = util.ShuffleShardExpectedInstancesPerZone(size, len(r.ringZones))
numInstancesPerZone = shardUtil.ShuffleShardExpectedInstancesPerZone(size, len(r.ringZones))
actualZones = r.ringZones
} else {
numInstancesPerZone = size
@ -696,7 +690,7 @@ func (r *Ring) shuffleShard(identifier string, size int, lookbackPeriod time.Dur
// Since we consider each zone like an independent ring, we have to use dedicated
// pseudo-random generator for each zone, in order to guarantee the "consistency"
// property when the shard size changes or a new zone is added.
random := rand.New(rand.NewSource(util.ShuffleShardSeed(identifier, zone)))
random := rand.New(rand.NewSource(shardUtil.ShuffleShardSeed(identifier, zone)))
// To select one more instance while guaranteeing the "consistency" property,
// we do pick a random value from the generator and resolve uniqueness collisions
@ -866,7 +860,7 @@ func NewOp(healthyStates []InstanceState, shouldExtendReplicaSet func(s Instance
}
if shouldExtendReplicaSet != nil {
for _, s := range []InstanceState{ACTIVE, LEAVING, PENDING, JOINING, LEFT} {
for _, s := range []InstanceState{ACTIVE, LEAVING, PENDING, JOINING, LEAVING, LEFT} {
if shouldExtendReplicaSet(s) {
op |= (0x10000 << s)
}

@ -122,7 +122,7 @@ type InstanceDesc struct {
// When an instance is already registered in the ring with a value of 0 it's NOT safe to
// update the timestamp to "now" because it would break the contract, given the instance
// was already registered before "now". If unknown (0), it should be left as is, and the
// Cortex code will properly deal with that.
// code will properly deal with that.
RegisteredTimestamp int64 `protobuf:"varint,8,opt,name=registered_timestamp,json=registeredTimestamp,proto3" json:"registered_timestamp,omitempty"`
}

@ -37,7 +37,7 @@ message InstanceDesc {
// When an instance is already registered in the ring with a value of 0 it's NOT safe to
// update the timestamp to "now" because it would break the contract, given the instance
// was already registered before "now". If unknown (0), it should be left as is, and the
// Cortex code will properly deal with that.
// code will properly deal with that.
int64 registered_timestamp = 8;
}

@ -0,0 +1,45 @@
package shard
import (
"crypto/md5"
"encoding/binary"
"math"
"unsafe"
)
var (
seedSeparator = []byte{0}
)
// ShuffleShardSeed returns seed for random number generator, computed from provided identifier.
func ShuffleShardSeed(identifier, zone string) int64 {
// Use the identifier to compute a hash we'll use to seed the random.
hasher := md5.New()
hasher.Write(yoloBuf(identifier)) // nolint:errcheck
if zone != "" {
hasher.Write(seedSeparator) // nolint:errcheck
hasher.Write(yoloBuf(zone)) // nolint:errcheck
}
checksum := hasher.Sum(nil)
// Generate the seed based on the first 64 bits of the checksum.
return int64(binary.BigEndian.Uint64(checksum))
}
// ShuffleShardExpectedInstancesPerZone returns the number of instances that should be selected for each
// zone when zone-aware replication is enabled. The algorithm expects the shard size to be divisible
// by the number of zones, in order to have nodes balanced across zones. If it's not, we do round up.
func ShuffleShardExpectedInstancesPerZone(shardSize, numZones int) int {
return int(math.Ceil(float64(shardSize) / float64(numZones)))
}
// ShuffleShardExpectedInstances returns the total number of instances that should be selected for a given
// tenant. If zone-aware replication is disabled, the input numZones should be 1.
func ShuffleShardExpectedInstances(shardSize, numZones int) int {
return ShuffleShardExpectedInstancesPerZone(shardSize, numZones) * numZones
}
// yoloBuf will return an unsafe pointer to a string, as the name yolo.yoloBuf implies use at your own risk.
func yoloBuf(s string) []byte {
return *((*[]byte)(unsafe.Pointer(&s)))
}

@ -79,7 +79,7 @@ func LoadTokensFromFile(tokenFilePath string) (Tokens, error) {
var t Tokens
err = t.Unmarshal(b)
// Tokens may have been written to file by an older version of Cortex which
// Tokens may have been written to file by an older version which
// doesn't guarantee sorted tokens, so we enforce sorting here.
if !sort.IsSorted(t) {
sort.Sort(t)

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save