diff --git a/CHANGELOG.md b/CHANGELOG.md index a7586b76768..47f2cc8dc51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,10 @@ * [CHANGE] Compactor: delete source and output blocks from local disk on compaction failed, to reduce likelihood that subsequent compactions fail because of no space left on disk. #2261 * [CHANGE] Ruler: Remove unused CLI flags `-ruler.search-pending-for` and `-ruler.flush-period` (and their respective YAML config options). #2288 +* [CHANGE] Successful gRPC requests are no longer logged (only affects internal API calls). #2309 +* [CHANGE] Add new `-*.consul.cas-retry-delay` flags. They have a default value of `1s`, while previously there was no delay between retries. #2309 * [ENHANCEMENT] Alertmanager: Allow the HTTP `proxy_url` configuration option in the receiver's configuration. #2317 +* [ENHANCEMENT] ring: optimize shuffle-shard computation when lookback is used, and all instances have registered timestamp within the lookback window. In that case we can immediately return origial ring, because we would select all instances anyway. #2309 * [BUGFIX] Compactor: log the actual error on compaction failed. #2261 * [BUGFIX] Alertmanager: restore state from storage even when running a single replica. #2293 diff --git a/cmd/mimir/config-descriptor.json b/cmd/mimir/config-descriptor.json index 291e735b78f..9d1a50760dc 100644 --- a/cmd/mimir/config-descriptor.json +++ b/cmd/mimir/config-descriptor.json @@ -494,6 +494,17 @@ "fieldType": "string", "fieldCategory": "advanced" }, + { + "kind": "field", + "name": "log_request_at_info_level_enabled", + "required": false, + "desc": "Optionally log requests at info level instead of debug level.", + "fieldValue": null, + "fieldDefaultValue": false, + "fieldFlag": "server.log-request-at-info-level-enabled", + "fieldType": "boolean", + "fieldCategory": "advanced" + }, { "kind": "field", "name": "http_path_prefix", @@ -693,6 +704,17 @@ "fieldFlag": "distributor.ha-tracker.consul.watch-burst-size", "fieldType": "int", "fieldCategory": "advanced" + }, + { + "kind": "field", + "name": "cas_retry_delay", + "required": false, + "desc": "Maximum duration to wait before retrying a Compare And Swap (CAS) operation.", + "fieldValue": null, + "fieldDefaultValue": 1000000000, + "fieldFlag": "distributor.ha-tracker.consul.cas-retry-delay", + "fieldType": "duration", + "fieldCategory": "advanced" } ], "fieldValue": null, @@ -1013,6 +1035,17 @@ "fieldFlag": "distributor.ring.consul.watch-burst-size", "fieldType": "int", "fieldCategory": "advanced" + }, + { + "kind": "field", + "name": "cas_retry_delay", + "required": false, + "desc": "Maximum duration to wait before retrying a Compare And Swap (CAS) operation.", + "fieldValue": null, + "fieldDefaultValue": 1000000000, + "fieldFlag": "distributor.ring.consul.cas-retry-delay", + "fieldType": "duration", + "fieldCategory": "advanced" } ], "fieldValue": null, @@ -1860,6 +1893,17 @@ "fieldFlag": "ingester.ring.consul.watch-burst-size", "fieldType": "int", "fieldCategory": "advanced" + }, + { + "kind": "field", + "name": "cas_retry_delay", + "required": false, + "desc": "Maximum duration to wait before retrying a Compare And Swap (CAS) operation.", + "fieldValue": null, + "fieldDefaultValue": 1000000000, + "fieldFlag": "ingester.ring.consul.cas-retry-delay", + "fieldType": "duration", + "fieldCategory": "advanced" } ], "fieldValue": null, @@ -5749,6 +5793,17 @@ "fieldFlag": "compactor.ring.consul.watch-burst-size", "fieldType": "int", "fieldCategory": "advanced" + }, + { + "kind": "field", + "name": "cas_retry_delay", + "required": false, + "desc": "Maximum duration to wait before retrying a Compare And Swap (CAS) operation.", + "fieldValue": null, + "fieldDefaultValue": 1000000000, + "fieldFlag": "compactor.ring.consul.cas-retry-delay", + "fieldType": "duration", + "fieldCategory": "advanced" } ], "fieldValue": null, @@ -6166,6 +6221,17 @@ "fieldFlag": "store-gateway.sharding-ring.consul.watch-burst-size", "fieldType": "int", "fieldCategory": "advanced" + }, + { + "kind": "field", + "name": "cas_retry_delay", + "required": false, + "desc": "Maximum duration to wait before retrying a Compare And Swap (CAS) operation.", + "fieldValue": null, + "fieldDefaultValue": 1000000000, + "fieldFlag": "store-gateway.sharding-ring.consul.cas-retry-delay", + "fieldType": "duration", + "fieldCategory": "advanced" } ], "fieldValue": null, @@ -7062,6 +7128,17 @@ "fieldFlag": "ruler.ring.consul.watch-burst-size", "fieldType": "int", "fieldCategory": "advanced" + }, + { + "kind": "field", + "name": "cas_retry_delay", + "required": false, + "desc": "Maximum duration to wait before retrying a Compare And Swap (CAS) operation.", + "fieldValue": null, + "fieldDefaultValue": 1000000000, + "fieldFlag": "ruler.ring.consul.cas-retry-delay", + "fieldType": "duration", + "fieldCategory": "advanced" } ], "fieldValue": null, @@ -8375,6 +8452,17 @@ "fieldFlag": "alertmanager.sharding-ring.consul.watch-burst-size", "fieldType": "int", "fieldCategory": "advanced" + }, + { + "kind": "field", + "name": "cas_retry_delay", + "required": false, + "desc": "Maximum duration to wait before retrying a Compare And Swap (CAS) operation.", + "fieldValue": null, + "fieldDefaultValue": 1000000000, + "fieldFlag": "alertmanager.sharding-ring.consul.cas-retry-delay", + "fieldType": "duration", + "fieldCategory": "advanced" } ], "fieldValue": null, diff --git a/cmd/mimir/help-all.txt.tmpl b/cmd/mimir/help-all.txt.tmpl index 196d7b3b1bf..40756086ad4 100644 --- a/cmd/mimir/help-all.txt.tmpl +++ b/cmd/mimir/help-all.txt.tmpl @@ -172,6 +172,8 @@ Usage of ./cmd/mimir/mimir: True to block private and local addresses in Alertmanager receiver integrations. It blocks private addresses defined by RFC 1918 (IPv4 addresses) and RFC 4193 (IPv6 addresses), as well as loopback, local unicast and local multicast addresses. -alertmanager.sharding-ring.consul.acl-token string ACL Token used to interact with Consul. + -alertmanager.sharding-ring.consul.cas-retry-delay duration + Maximum duration to wait before retrying a Compare And Swap (CAS) operation. (default 1s) -alertmanager.sharding-ring.consul.client-timeout duration HTTP timeout when talking to Consul (default 20s) -alertmanager.sharding-ring.consul.consistent-reads @@ -565,6 +567,8 @@ Usage of ./cmd/mimir/mimir: Number of Go routines to use when syncing block meta files from the long term storage. (default 20) -compactor.ring.consul.acl-token string ACL Token used to interact with Consul. + -compactor.ring.consul.cas-retry-delay duration + Maximum duration to wait before retrying a Compare And Swap (CAS) operation. (default 1s) -compactor.ring.consul.client-timeout duration HTTP timeout when talking to Consul (default 20s) -compactor.ring.consul.consistent-reads @@ -657,6 +661,8 @@ Usage of ./cmd/mimir/mimir: Prometheus label to look for in samples to identify a Prometheus HA cluster. (default "cluster") -distributor.ha-tracker.consul.acl-token string ACL Token used to interact with Consul. + -distributor.ha-tracker.consul.cas-retry-delay duration + Maximum duration to wait before retrying a Compare And Swap (CAS) operation. (default 1s) -distributor.ha-tracker.consul.client-timeout duration HTTP timeout when talking to Consul (default 20s) -distributor.ha-tracker.consul.consistent-reads @@ -737,6 +743,8 @@ Usage of ./cmd/mimir/mimir: [experimental] Per-tenant request rate limit in requests per second. 0 to disable. -distributor.ring.consul.acl-token string ACL Token used to interact with Consul. + -distributor.ring.consul.cas-retry-delay duration + Maximum duration to wait before retrying a Compare And Swap (CAS) operation. (default 1s) -distributor.ring.consul.client-timeout duration HTTP timeout when talking to Consul (default 20s) -distributor.ring.consul.consistent-reads @@ -871,6 +879,8 @@ Usage of ./cmd/mimir/mimir: Period with which to update the per-tenant ingestion rates. (default 15s) -ingester.ring.consul.acl-token string ACL Token used to interact with Consul. + -ingester.ring.consul.cas-retry-delay duration + Maximum duration to wait before retrying a Compare And Swap (CAS) operation. (default 1s) -ingester.ring.consul.client-timeout duration HTTP timeout when talking to Consul (default 20s) -ingester.ring.consul.consistent-reads @@ -1456,6 +1466,8 @@ Usage of ./cmd/mimir/mimir: Minimum amount of time to wait before resending an alert to Alertmanager. (default 1m0s) -ruler.ring.consul.acl-token string ACL Token used to interact with Consul. + -ruler.ring.consul.cas-retry-delay duration + Maximum duration to wait before retrying a Compare And Swap (CAS) operation. (default 1s) -ruler.ring.consul.client-timeout duration HTTP timeout when talking to Consul (default 20s) -ruler.ring.consul.consistent-reads @@ -1584,6 +1596,8 @@ Usage of ./cmd/mimir/mimir: HTTP server key path. -server.http-write-timeout duration Write timeout for HTTP server (default 30s) + -server.log-request-at-info-level-enabled + Optionally log requests at info level instead of debug level. -server.log-source-ips-enabled Optionally log the source IPs. -server.log-source-ips-header string @@ -1596,6 +1610,8 @@ Usage of ./cmd/mimir/mimir: Register the intrumentation handlers (/metrics etc). (default true) -store-gateway.sharding-ring.consul.acl-token string ACL Token used to interact with Consul. + -store-gateway.sharding-ring.consul.cas-retry-delay duration + Maximum duration to wait before retrying a Compare And Swap (CAS) operation. (default 1s) -store-gateway.sharding-ring.consul.client-timeout duration HTTP timeout when talking to Consul (default 20s) -store-gateway.sharding-ring.consul.consistent-reads diff --git a/docs/sources/operators-guide/configuring/reference-configuration-parameters/index.md b/docs/sources/operators-guide/configuring/reference-configuration-parameters/index.md index dbfff162678..9b94cfde930 100644 --- a/docs/sources/operators-guide/configuring/reference-configuration-parameters/index.md +++ b/docs/sources/operators-guide/configuring/reference-configuration-parameters/index.md @@ -383,6 +383,10 @@ grpc_tls_config: # CLI flag: -server.log-source-ips-regex [log_source_ips_regex: | default = ""] +# (advanced) Optionally log requests at info level instead of debug level. +# CLI flag: -server.log-request-at-info-level-enabled +[log_request_at_info_level_enabled: | default = false] + # (advanced) Base path to serve all API routes from (e.g. /v1/) # CLI flag: -server.path-prefix [http_path_prefix: | default = ""] @@ -2437,6 +2441,11 @@ The `consul` block configures the consul client. The supported CLI flags `.consul.watch-burst-size [watch_burst_size: | default = 1] + +# (advanced) Maximum duration to wait before retrying a Compare And Swap (CAS) +# operation. +# CLI flag: -.consul.cas-retry-delay +[cas_retry_delay: | default = 1s] ``` ### memberlist diff --git a/go.mod b/go.mod index b8251d12db5..14c86a27611 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/golang/snappy v0.0.4 github.com/google/gopacket v1.1.19 github.com/gorilla/mux v1.8.0 - github.com/grafana/dskit v0.0.0-20220622130855-7bb188ccf75a + github.com/grafana/dskit v0.0.0-20220704121012-e441b77be778 github.com/grafana/e2e v0.1.1-0.20220519104354-1db01e4751fe github.com/hashicorp/golang-lru v0.5.4 github.com/json-iterator/go v1.1.12 @@ -39,7 +39,7 @@ require ( github.com/stretchr/testify v1.7.2 github.com/thanos-io/thanos v0.26.1-0.20220602051129-a6f6ce060ed4 github.com/uber/jaeger-client-go v2.30.0+incompatible - github.com/weaveworks/common v0.0.0-20211109170639-0684aab3d884 + github.com/weaveworks/common v0.0.0-20220706100410-67d27ed40fae go.uber.org/atomic v1.9.0 go.uber.org/goleak v1.1.12 golang.org/x/crypto v0.0.0-20220214200702-86341886e292 @@ -177,7 +177,6 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/common/sigv4 v0.1.0 // indirect github.com/prometheus/exporter-toolkit v0.7.1 // indirect - github.com/prometheus/node_exporter v1.0.0-rc.0.0.20200428091818-01054558c289 // indirect github.com/prometheus/procfs v0.7.3 // indirect github.com/rainycape/unidecode v0.0.0-20150907023854-cb7f23ec59be // indirect github.com/rs/cors v1.8.2 // indirect diff --git a/go.sum b/go.sum index 4bcab8eb432..19e1326c1c7 100644 --- a/go.sum +++ b/go.sum @@ -404,6 +404,7 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2 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.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/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= @@ -738,8 +739,8 @@ github.com/gosimple/slug v1.1.1 h1:fRu/digW+NMwBIP+RmviTK97Ho/bEj/C9swrCspN3D4= github.com/gosimple/slug v1.1.1/go.mod h1:ER78kgg1Mv0NQGlXiDe57DpCyfbNywXXZ9mIorhxAf0= github.com/grafana/dskit v0.0.0-20211021180445-3bd016e9d7f1/go.mod h1:uPG2nyK4CtgNDmWv7qyzYcdI+S90kHHRWvHnBtEMBXM= github.com/grafana/dskit v0.0.0-20220112093026-95274ccc858d/go.mod h1:M0/dlftwBvH7+hdNNpjMa/CUXD7gsew67mbkCuDlFXE= -github.com/grafana/dskit v0.0.0-20220622130855-7bb188ccf75a h1:D9L8ZU8QlXxUb9lQwiNLamt0nJXXETJVmtF7DxSqc9g= -github.com/grafana/dskit v0.0.0-20220622130855-7bb188ccf75a/go.mod h1:9It/K30QPyj/FuTqBb/SYnaS4/BJCP5YL4SRfXB7dG0= +github.com/grafana/dskit v0.0.0-20220704121012-e441b77be778 h1:JiAXp2IDSqW1q5rmPfMYyetuOr4GFLMCe9WvvnL5n9g= +github.com/grafana/dskit v0.0.0-20220704121012-e441b77be778/go.mod h1:vDNKB8ExYS07ItQoxr13Tjq1Kd2IQ7IsvmJLn9kK+g0= github.com/grafana/e2e v0.1.1-0.20220519104354-1db01e4751fe h1:mxrRWDjKtob43xF9nEhJthdtCzX35/800Sk7nE//YHQ= github.com/grafana/e2e v0.1.1-0.20220519104354-1db01e4751fe/go.mod h1:+26VJWpczg2OU3D0537acnHSHzhJORpxOs6F+M27tZo= github.com/grafana/memberlist v0.3.1-0.20220425183535-6b97a09b7167 h1:PgEQkGHR4YimSCEGT5IoswN9gJKZDVskf+he6UClCLw= @@ -1158,9 +1159,9 @@ github.com/prometheus/common/assets v0.1.0/go.mod h1:D17UVUE12bHbim7HzwUvtqm6gwB github.com/prometheus/common/sigv4 v0.1.0 h1:qoVebwtwwEhS85Czm2dSROY5fTo2PAPEVdDeppTwGX4= github.com/prometheus/common/sigv4 v0.1.0/go.mod h1:2Jkxxk9yYvCkE5G1sQT7GuEXm57JrvHu9k5YwTjsNtI= github.com/prometheus/exporter-toolkit v0.6.1/go.mod h1:ZUBIj498ePooX9t/2xtDjeQYwvRpiPP2lh5u4iblj2g= +github.com/prometheus/exporter-toolkit v0.7.0/go.mod h1:ZUBIj498ePooX9t/2xtDjeQYwvRpiPP2lh5u4iblj2g= github.com/prometheus/exporter-toolkit v0.7.1 h1:c6RXaK8xBVercEeUQ4tRNL8UGWzDHfvj9dseo1FcK1Y= github.com/prometheus/exporter-toolkit v0.7.1/go.mod h1:ZUBIj498ePooX9t/2xtDjeQYwvRpiPP2lh5u4iblj2g= -github.com/prometheus/node_exporter v1.0.0-rc.0.0.20200428091818-01054558c289 h1:dTUS1vaLWq+Y6XKOTnrFpoVsQKLCbCp1OLj24TDi7oM= github.com/prometheus/node_exporter v1.0.0-rc.0.0.20200428091818-01054558c289/go.mod h1:FGbBv5OPKjch+jNUJmEQpMZytIdyW0NdBtWFcfSKusc= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= @@ -1287,8 +1288,9 @@ github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv github.com/vultr/govultr/v2 v2.17.1 h1:UBmotwA0mkGtyJMakUF9jhLH/W3mN5wfGRn543i/BCA= github.com/vultr/govultr/v2 v2.17.1/go.mod h1:ZFOKGWmgjytfyjeyAdhQlSWwTjh2ig+X49cAp50dzXI= github.com/weaveworks/common v0.0.0-20210913144402-035033b78a78/go.mod h1:YU9FvnS7kUnRt6HY10G+2qHkwzP3n3Vb1XsXDsJTSp8= -github.com/weaveworks/common v0.0.0-20211109170639-0684aab3d884 h1:8xKd5YG67aKrYwyxXA55ox7AjCMqiMq4gWBVi+lkKLE= -github.com/weaveworks/common v0.0.0-20211109170639-0684aab3d884/go.mod h1:GWX2dQ7yjrgvqH0+d3kCJC5bsY8oOFwqjxFMHaRK4/k= +github.com/weaveworks/common v0.0.0-20220629114710-e3b70df0f08b/go.mod h1:YfOOLoW1Q/jIIu0WLeSwgStmrKjuJEZSKTAUc+0KFvE= +github.com/weaveworks/common v0.0.0-20220706100410-67d27ed40fae h1:Z8YibUpdBEdCq8nwrYXJQ8vYooevbmEBIdFpseXK3/8= +github.com/weaveworks/common v0.0.0-20220706100410-67d27ed40fae/go.mod h1:YfOOLoW1Q/jIIu0WLeSwgStmrKjuJEZSKTAUc+0KFvE= github.com/weaveworks/promrus v1.2.0 h1:jOLf6pe6/vss4qGHjXmGz4oDJQA+AOCqEL3FvvZGz7M= github.com/weaveworks/promrus v1.2.0/go.mod h1:SaE82+OJ91yqjrE1rsvBWVzNZKcHYFtMUyS1+Ogs/KA= github.com/xanzy/go-gitlab v0.15.0/go.mod h1:8zdQa/ri1dfn8eS3Ir1SyfvOKlw7WBJ8DVThkpGiXrs= diff --git a/pkg/mimir/mimir.go b/pkg/mimir/mimir.go index 6d2ddfc9fa3..cc0e88e3e2f 100644 --- a/pkg/mimir/mimir.go +++ b/pkg/mimir/mimir.go @@ -123,6 +123,7 @@ func (c *Config) RegisterFlags(f *flag.FlagSet, logger log.Logger) { c.ApplicationName = "Grafana Mimir" c.Server.MetricsNamespace = "cortex" c.Server.ExcludeRequestInLog = true + c.Server.DisableRequestSuccessLog = true // Set the default module list to 'all' c.Target = []string{All} diff --git a/pkg/querier/worker/scheduler_processor.go b/pkg/querier/worker/scheduler_processor.go index df52e4193f0..264eef7cbfa 100644 --- a/pkg/querier/worker/scheduler_processor.go +++ b/pkg/querier/worker/scheduler_processor.go @@ -15,7 +15,6 @@ import ( "github.com/go-kit/log/level" "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" @@ -219,7 +218,7 @@ func (sp *schedulerProcessor) createFrontendClient(addr string) (client.PoolClie opts, err := sp.grpcConfig.DialOption([]grpc.UnaryClientInterceptor{ otgrpc.OpenTracingClientInterceptor(opentracing.GlobalTracer()), middleware.ClientUserHeaderInterceptor, - dsmiddleware.PrometheusGRPCUnaryInstrumentation(sp.frontendClientRequestDuration), + middleware.UnaryClientInstrumentInterceptor(sp.frontendClientRequestDuration), }, nil) if err != nil { diff --git a/pkg/storage/tsdb/upload_test.go b/pkg/storage/tsdb/upload_test.go index 111bb3dc092..45fceefc22c 100644 --- a/pkg/storage/tsdb/upload_test.go +++ b/pkg/storage/tsdb/upload_test.go @@ -9,6 +9,7 @@ import ( "context" "os" "path" + "path/filepath" "testing" "github.com/go-kit/log" @@ -103,7 +104,8 @@ func TestUploadBlock(t *testing.T) { // Full block. require.NoError(t, UploadBlock(ctx, log.NewNopLogger(), bkt, path.Join(tmpDir, "test", b1.String()), nil)) require.Equal(t, 3, len(bkt.Objects())) - require.Equal(t, 3751, len(bkt.Objects()[path.Join(b1.String(), block.ChunksDirname, "000001")])) + chunkFileSize := getFileSize(t, filepath.Join(tmpDir, b1.String(), block.ChunksDirname, "000001")) + require.Equal(t, chunkFileSize, int64(len(bkt.Objects()[path.Join(b1.String(), block.ChunksDirname, "000001")]))) require.Equal(t, 401, len(bkt.Objects()[path.Join(b1.String(), block.IndexFilename)])) require.Equal(t, 570, len(bkt.Objects()[path.Join(b1.String(), block.MetaFilename)])) @@ -115,7 +117,7 @@ func TestUploadBlock(t *testing.T) { files := uploadedMeta.Thanos.Files require.Len(t, files, 3) - require.Equal(t, metadata.File{RelPath: "chunks/000001", SizeBytes: 3751}, files[0]) + require.Equal(t, metadata.File{RelPath: "chunks/000001", SizeBytes: chunkFileSize}, files[0]) require.Equal(t, metadata.File{RelPath: "index", SizeBytes: 401}, files[1]) require.Equal(t, metadata.File{RelPath: "meta.json", SizeBytes: 0}, files[2]) // meta.json is added to the files without its size. @@ -129,7 +131,8 @@ func TestUploadBlock(t *testing.T) { // Test Upload is idempotent. require.NoError(t, UploadBlock(ctx, log.NewNopLogger(), bkt, path.Join(tmpDir, "test", b1.String()), nil)) require.Equal(t, 3, len(bkt.Objects())) - require.Equal(t, 3751, len(bkt.Objects()[path.Join(b1.String(), block.ChunksDirname, "000001")])) + chunkFileSize := getFileSize(t, filepath.Join(tmpDir, b1.String(), block.ChunksDirname, "000001")) + require.Equal(t, chunkFileSize, int64(len(bkt.Objects()[path.Join(b1.String(), block.ChunksDirname, "000001")]))) require.Equal(t, 401, len(bkt.Objects()[path.Join(b1.String(), block.IndexFilename)])) require.Equal(t, 570, len(bkt.Objects()[path.Join(b1.String(), block.MetaFilename)])) }) @@ -148,8 +151,9 @@ func TestUploadBlock(t *testing.T) { err = UploadBlock(ctx, log.NewNopLogger(), bkt, path.Join(tmpDir, b2.String()), nil) require.NoError(t, err) + chunkFileSize := getFileSize(t, filepath.Join(tmpDir, b2.String(), block.ChunksDirname, "000001")) require.Equal(t, 6, len(bkt.Objects())) // 3 from b1, 3 from b2 - require.Equal(t, 3736, len(bkt.Objects()[path.Join(b2.String(), block.ChunksDirname, "000001")])) + require.Equal(t, chunkFileSize, int64(len(bkt.Objects()[path.Join(b2.String(), block.ChunksDirname, "000001")]))) require.Equal(t, 401, len(bkt.Objects()[path.Join(b2.String(), block.IndexFilename)])) require.Equal(t, 549, len(bkt.Objects()[path.Join(b2.String(), block.MetaFilename)])) @@ -200,3 +204,11 @@ func TestUploadBlock(t *testing.T) { require.Equal(t, updatedMeta.Thanos.Source, bucketMeta.Thanos.Source) }) } + +func getFileSize(t *testing.T, filepath string) int64 { + t.Helper() + + st, err := os.Stat(filepath) + require.NoError(t, err) + return st.Size() +} diff --git a/pkg/util/fieldcategory/overrides.go b/pkg/util/fieldcategory/overrides.go index c4b53816b5c..1e0cd08384b 100644 --- a/pkg/util/fieldcategory/overrides.go +++ b/pkg/util/fieldcategory/overrides.go @@ -63,6 +63,7 @@ var overrides = map[string]Category{ "server.log-source-ips-regex": Advanced, "server.path-prefix": Advanced, "server.register-instrumentation": Advanced, + "server.log-request-at-info-level-enabled": Advanced, } func AddOverrides(o map[string]Category) { diff --git a/vendor/github.com/grafana/dskit/grpcclient/instrumentation.go b/vendor/github.com/grafana/dskit/grpcclient/instrumentation.go index b22a5883405..c8d3528895a 100644 --- a/vendor/github.com/grafana/dskit/grpcclient/instrumentation.go +++ b/vendor/github.com/grafana/dskit/grpcclient/instrumentation.go @@ -6,18 +6,16 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/weaveworks/common/middleware" "google.golang.org/grpc" - - dsmiddleware "github.com/grafana/dskit/middleware" ) func Instrument(requestDuration *prometheus.HistogramVec) ([]grpc.UnaryClientInterceptor, []grpc.StreamClientInterceptor) { return []grpc.UnaryClientInterceptor{ otgrpc.OpenTracingClientInterceptor(opentracing.GlobalTracer()), middleware.ClientUserHeaderInterceptor, - dsmiddleware.PrometheusGRPCUnaryInstrumentation(requestDuration), + middleware.UnaryClientInstrumentInterceptor(requestDuration), }, []grpc.StreamClientInterceptor{ otgrpc.OpenTracingStreamClientInterceptor(opentracing.GlobalTracer()), middleware.StreamClientUserHeaderInterceptor, - dsmiddleware.PrometheusGRPCStreamInstrumentation(requestDuration), + middleware.StreamClientInstrumentInterceptor(requestDuration), } } diff --git a/vendor/github.com/grafana/dskit/kv/consul/client.go b/vendor/github.com/grafana/dskit/kv/consul/client.go index 0fefe4314cc..c7ef8d372e7 100644 --- a/vendor/github.com/grafana/dskit/kv/consul/client.go +++ b/vendor/github.com/grafana/dskit/kv/consul/client.go @@ -46,10 +46,10 @@ type Config struct { ConsistentReads bool `yaml:"consistent_reads" category:"advanced"` WatchKeyRateLimit float64 `yaml:"watch_rate_limit" category:"advanced"` // Zero disables rate limit WatchKeyBurstSize int `yaml:"watch_burst_size" category:"advanced"` // Burst when doing rate-limit, defaults to 1 + CasRetryDelay time.Duration `yaml:"cas_retry_delay" category:"advanced"` // Used in tests only. - MaxCasRetries int `yaml:"-"` - CasRetryDelay time.Duration `yaml:"-"` + MaxCasRetries int `yaml:"-"` } type kv interface { @@ -78,6 +78,7 @@ func (cfg *Config) RegisterFlags(f *flag.FlagSet, prefix string) { f.BoolVar(&cfg.ConsistentReads, prefix+"consul.consistent-reads", false, "Enable consistent reads to Consul.") f.Float64Var(&cfg.WatchKeyRateLimit, prefix+"consul.watch-rate-limit", 1, "Rate limit when watching key or prefix in Consul, in requests per second. 0 disables the rate limit.") f.IntVar(&cfg.WatchKeyBurstSize, prefix+"consul.watch-burst-size", 1, "Burst size used in rate limit. Values less than 1 are treated as 1.") + f.DurationVar(&cfg.CasRetryDelay, prefix+"consul.cas-retry-delay", 1*time.Second, "Maximum duration to wait before retrying a Compare And Swap (CAS) operation.") } // NewClient returns a new Client. diff --git a/vendor/github.com/grafana/dskit/middleware/grpc.go b/vendor/github.com/grafana/dskit/middleware/grpc.go deleted file mode 100644 index 66f0d376608..00000000000 --- a/vendor/github.com/grafana/dskit/middleware/grpc.go +++ /dev/null @@ -1,101 +0,0 @@ -package middleware - -import ( - "context" - "io" - "strconv" - "time" - - "github.com/prometheus/client_golang/prometheus" - grpcUtils "github.com/weaveworks/common/grpc" - "github.com/weaveworks/common/httpgrpc" - "google.golang.org/grpc" - "google.golang.org/grpc/metadata" -) - -// PrometheusGRPCUnaryInstrumentation records duration of gRPC requests client side. -func PrometheusGRPCUnaryInstrumentation(metric *prometheus.HistogramVec) grpc.UnaryClientInterceptor { - return func(ctx context.Context, method string, req, resp interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { - start := time.Now() - err := invoker(ctx, method, req, resp, cc, opts...) - metric.WithLabelValues(method, errorCode(err)).Observe(time.Since(start).Seconds()) - return err - } -} - -// PrometheusGRPCStreamInstrumentation records duration of streaming gRPC requests client side. -func PrometheusGRPCStreamInstrumentation(metric *prometheus.HistogramVec) grpc.StreamClientInterceptor { - return func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, - streamer grpc.Streamer, opts ...grpc.CallOption, - ) (grpc.ClientStream, error) { - start := time.Now() - stream, err := streamer(ctx, desc, cc, method, opts...) - return &instrumentedClientStream{ - metric: metric, - start: start, - method: method, - ClientStream: stream, - }, err - } -} - -type instrumentedClientStream struct { - metric *prometheus.HistogramVec - start time.Time - method string - grpc.ClientStream -} - -func (s *instrumentedClientStream) SendMsg(m interface{}) error { - err := s.ClientStream.SendMsg(m) - if err == nil { - return err - } - - if err == io.EOF { - s.metric.WithLabelValues(s.method, errorCode(nil)).Observe(time.Since(s.start).Seconds()) - } else { - s.metric.WithLabelValues(s.method, errorCode(err)).Observe(time.Since(s.start).Seconds()) - } - - return err -} - -func (s *instrumentedClientStream) RecvMsg(m interface{}) error { - err := s.ClientStream.RecvMsg(m) - if err == nil { - return err - } - - if err == io.EOF { - s.metric.WithLabelValues(s.method, errorCode(nil)).Observe(time.Since(s.start).Seconds()) - } else { - s.metric.WithLabelValues(s.method, errorCode(err)).Observe(time.Since(s.start).Seconds()) - } - - return err -} - -func (s *instrumentedClientStream) Header() (metadata.MD, error) { - md, err := s.ClientStream.Header() - if err != nil { - s.metric.WithLabelValues(s.method, errorCode(err)).Observe(time.Since(s.start).Seconds()) - } - return md, err -} - -func errorCode(err error) string { - respStatus := "2xx" - if err != nil { - if errResp, ok := httpgrpc.HTTPResponseFromError(err); ok { - statusFamily := int(errResp.Code / 100) - respStatus = strconv.Itoa(statusFamily) + "xx" - } else if grpcUtils.IsCanceled(err) { - respStatus = "cancel" - } else { - respStatus = "error" - } - } - - return respStatus -} diff --git a/vendor/github.com/grafana/dskit/ring/model.go b/vendor/github.com/grafana/dskit/ring/model.go index 4166d9e6f8e..fd58e534cb7 100644 --- a/vendor/github.com/grafana/dskit/ring/model.go +++ b/vendor/github.com/grafana/dskit/ring/model.go @@ -489,6 +489,27 @@ func (d *Desc) getTokensByZone() map[string][]uint32 { return MergeTokensByZone(zones) } +// getOldestRegisteredTimestamp returns unix timestamp of oldest "RegisteredTimestamp" value from all instances. +// If any instance has 0 value of RegisteredTimestamp, this function returns 0. +func (d *Desc) getOldestRegisteredTimestamp() int64 { + var result int64 + + for _, instance := range d.Ingesters { + switch { + case instance.RegisteredTimestamp == 0: + return 0 + + case result == 0: + result = instance.RegisteredTimestamp + + case instance.RegisteredTimestamp < result: + result = instance.RegisteredTimestamp + } + } + + return result +} + type CompareResult int // CompareResult responses diff --git a/vendor/github.com/grafana/dskit/ring/ring.go b/vendor/github.com/grafana/dskit/ring/ring.go index be78fee5980..1f7c2c928d3 100644 --- a/vendor/github.com/grafana/dskit/ring/ring.go +++ b/vendor/github.com/grafana/dskit/ring/ring.go @@ -167,6 +167,10 @@ type Ring struct { ringTokens []uint32 ringTokensByZone map[string][]uint32 + // Oldest value of RegisteredTimestamp from all instances. If any instance had RegisteredTimestamp == 0, + // then this value will be 0. + oldestRegisteredTimestamp int64 + // Maps a token with the information of the instance holding it. This map is immutable and // cannot be chanced in place because it's shared "as is" between subrings (the only way to // change it is to create a new one and replace it). @@ -310,6 +314,7 @@ func (r *Ring) updateRingState(ringDesc *Desc) { ringTokensByZone := ringDesc.getTokensByZone() ringInstanceByToken := ringDesc.getTokensInfo() ringZones := getZones(ringTokensByZone) + oldestRegisteredTimestamp := ringDesc.getOldestRegisteredTimestamp() r.mtx.Lock() defer r.mtx.Unlock() @@ -318,6 +323,7 @@ func (r *Ring) updateRingState(ringDesc *Desc) { r.ringTokensByZone = ringTokensByZone r.ringInstanceByToken = ringInstanceByToken r.ringZones = ringZones + r.oldestRegisteredTimestamp = oldestRegisteredTimestamp r.lastTopologyChange = now if r.shuffledSubringCache != nil { // Invalidate all cached subrings. @@ -603,8 +609,11 @@ func (r *Ring) ShuffleShard(identifier string, size int) ReadRing { } result := r.shuffleShard(identifier, size, 0, time.Now()) - - r.setCachedShuffledSubring(identifier, size, result) + // Only cache subring if it is different from this ring, to avoid deadlocks in getCachedShuffledSubring, + // when we update the cached ring. + if result != r { + r.setCachedShuffledSubring(identifier, size, result) + } return result } @@ -630,6 +639,16 @@ func (r *Ring) shuffleShard(identifier string, size int, lookbackPeriod time.Dur r.mtx.RLock() defer r.mtx.RUnlock() + // If all instances have RegisteredTimestamp within the lookback period, + // then all instances would be included in the resulting ring, so we can + // simply return this ring. + // + // If any instance had RegisteredTimestamp equal to 0 (it would not cause additional lookup of next instance), + // then r.oldestRegisteredTimestamp is zero too, and we skip this optimization. + if lookbackPeriod > 0 && r.oldestRegisteredTimestamp > 0 && r.oldestRegisteredTimestamp >= lookbackUntil { + return r + } + var numInstancesPerZone int var actualZones []string @@ -721,6 +740,8 @@ func (r *Ring) shuffleShard(identifier string, size int, lookbackPeriod time.Dur ringTokensByZone: shardTokensByZone, ringZones: getZones(shardTokensByZone), + oldestRegisteredTimestamp: shardDesc.getOldestRegisteredTimestamp(), + // We reference the original map as is in order to avoid copying. It's safe to do // because this map is immutable by design and it's a superset of the actual instances // with the subring. @@ -770,6 +791,11 @@ func (r *Ring) getCachedShuffledSubring(identifier string, size int) *Ring { return nil } + // No need to update cached subring, if it is the original ring itself. + if r == cached { + return cached + } + cached.mtx.Lock() defer cached.mtx.Unlock() diff --git a/vendor/github.com/prometheus/node_exporter/LICENSE b/vendor/github.com/prometheus/node_exporter/LICENSE deleted file mode 100644 index 261eeb9e9f8..00000000000 --- a/vendor/github.com/prometheus/node_exporter/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/prometheus/node_exporter/NOTICE b/vendor/github.com/prometheus/node_exporter/NOTICE deleted file mode 100644 index 970a9b237a9..00000000000 --- a/vendor/github.com/prometheus/node_exporter/NOTICE +++ /dev/null @@ -1,17 +0,0 @@ -Configurable modular Prometheus exporter for various node metrics. -Copyright 2013-2015 The Prometheus Authors - -This product includes software developed at -SoundCloud Ltd. (http://soundcloud.com/). - -The following components are included in this product: - -wifi -https://github.com/mdlayher/wifi -Copyright 2016-2017 Matt Layher -Licensed under the MIT License - -netlink -https://github.com/mdlayher/netlink -Copyright 2016-2017 Matt Layher -Licensed under the MIT License diff --git a/vendor/github.com/prometheus/node_exporter/https/README.md b/vendor/github.com/prometheus/node_exporter/https/README.md deleted file mode 100644 index e8e4504c916..00000000000 --- a/vendor/github.com/prometheus/node_exporter/https/README.md +++ /dev/null @@ -1,28 +0,0 @@ -# HTTPS Package for Prometheus - -The `https` directory contains a Go package and a sample configuration file for -running `node_exporter` with HTTPS instead of HTTP. We currently support TLS 1.3 -and TLS 1.2. - -To run a server with TLS, use the flag `--web.config`. - -e.g. `./node_exporter --web.config="web-config.yml"` -If the config is kept within the https directory. - -The config file should be written in YAML format, and is reloaded on each connection to check for new certificates and/or authentication policy. - -## Sample Config - -``` -tls_config: - # Certificate and key files for server to use to authenticate to client - cert_file: - key_file: - - # Server policy for client authentication. Maps to ClientAuth Policies - # For more detail on clientAuth options: [ClientAuthType](https://golang.org/pkg/crypto/tls/#ClientAuthType) - [ client_auth_type: | default = "NoClientCert" ] - - # CA certificate for client certificate authentication to the server - [ client_ca_file: ] -``` diff --git a/vendor/github.com/prometheus/node_exporter/https/tls_config.go b/vendor/github.com/prometheus/node_exporter/https/tls_config.go deleted file mode 100644 index 4b2986272e5..00000000000 --- a/vendor/github.com/prometheus/node_exporter/https/tls_config.go +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright 2019 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package https allows the implementation of TLS. -package https - -import ( - "crypto/tls" - "crypto/x509" - "io/ioutil" - "net/http" - - "github.com/pkg/errors" - "gopkg.in/yaml.v2" -) - -type Config struct { - TLSConfig TLSStruct `yaml:"tls_config"` -} - -type TLSStruct struct { - TLSCertPath string `yaml:"cert_file"` - TLSKeyPath string `yaml:"key_file"` - ClientAuth string `yaml:"client_auth_type"` - ClientCAs string `yaml:"client_ca_file"` -} - -func getTLSConfig(configPath string) (*tls.Config, error) { - content, err := ioutil.ReadFile(configPath) - if err != nil { - return nil, err - } - c := &Config{} - err = yaml.Unmarshal(content, c) - if err != nil { - return nil, err - } - return ConfigToTLSConfig(&c.TLSConfig) -} - -// ConfigToTLSConfig generates the golang tls.Config from the TLSStruct config. -func ConfigToTLSConfig(c *TLSStruct) (*tls.Config, error) { - cfg := &tls.Config{ - MinVersion: tls.VersionTLS12, - } - if len(c.TLSCertPath) == 0 { - return nil, errors.New("missing TLSCertPath") - } - if len(c.TLSKeyPath) == 0 { - return nil, errors.New("missing TLSKeyPath") - } - loadCert := func() (*tls.Certificate, error) { - cert, err := tls.LoadX509KeyPair(c.TLSCertPath, c.TLSKeyPath) - if err != nil { - return nil, errors.Wrap(err, "failed to load X509KeyPair") - } - return &cert, nil - } - // Confirm that certificate and key paths are valid. - if _, err := loadCert(); err != nil { - return nil, err - } - cfg.GetCertificate = func(*tls.ClientHelloInfo) (*tls.Certificate, error) { - return loadCert() - } - - if len(c.ClientCAs) > 0 { - clientCAPool := x509.NewCertPool() - clientCAFile, err := ioutil.ReadFile(c.ClientCAs) - if err != nil { - return nil, err - } - clientCAPool.AppendCertsFromPEM(clientCAFile) - cfg.ClientCAs = clientCAPool - } - if len(c.ClientAuth) > 0 { - switch s := (c.ClientAuth); s { - case "NoClientCert": - cfg.ClientAuth = tls.NoClientCert - case "RequestClientCert": - cfg.ClientAuth = tls.RequestClientCert - case "RequireClientCert": - cfg.ClientAuth = tls.RequireAnyClientCert - case "VerifyClientCertIfGiven": - cfg.ClientAuth = tls.VerifyClientCertIfGiven - case "RequireAndVerifyClientCert": - cfg.ClientAuth = tls.RequireAndVerifyClientCert - case "": - cfg.ClientAuth = tls.NoClientCert - default: - return nil, errors.New("Invalid ClientAuth: " + s) - } - } - if len(c.ClientCAs) > 0 && cfg.ClientAuth == tls.NoClientCert { - return nil, errors.New("Client CA's have been configured without a Client Auth Policy") - } - return cfg, nil -} - -// Listen starts the server on the given address. If tlsConfigPath isn't empty the server connection will be started using TLS. -func Listen(server *http.Server, tlsConfigPath string) error { - if (tlsConfigPath) == "" { - return server.ListenAndServe() - } - var err error - server.TLSConfig, err = getTLSConfig(tlsConfigPath) - if err != nil { - return err - } - // Set the GetConfigForClient method of the HTTPS server so that the config - // and certs are reloaded on new connections. - server.TLSConfig.GetConfigForClient = func(*tls.ClientHelloInfo) (*tls.Config, error) { - return getTLSConfig(tlsConfigPath) - } - return server.ListenAndServeTLS("", "") -} diff --git a/vendor/github.com/prometheus/node_exporter/https/web-config.yml b/vendor/github.com/prometheus/node_exporter/https/web-config.yml deleted file mode 100644 index 9937291cdcd..00000000000 --- a/vendor/github.com/prometheus/node_exporter/https/web-config.yml +++ /dev/null @@ -1,11 +0,0 @@ -tls_config: - # Certificate and key files for server to use to authenticate to client - cert_file: - key_file: - - # Server policy for client authentication. Maps to ClientAuth Policies - # For more detail on clientAuth options: [ClientAuthType](https://golang.org/pkg/crypto/tls/#ClientAuthType) - [ client_auth_type: | default = "NoClientCert" ] - - # CA certificate for client certificate authentication to the server - [ client_ca_file: ] diff --git a/vendor/github.com/weaveworks/common/instrument/instrument.go b/vendor/github.com/weaveworks/common/instrument/instrument.go index 07aa033c0c9..1a1352c842c 100644 --- a/vendor/github.com/weaveworks/common/instrument/instrument.go +++ b/vendor/github.com/weaveworks/common/instrument/instrument.go @@ -68,9 +68,16 @@ func (c *HistogramCollector) After(ctx context.Context, method, statusCode strin // (this will always work for a HistogramVec). func ObserveWithExemplar(ctx context.Context, histogram prometheus.Observer, seconds float64) { if traceID, ok := tracing.ExtractSampledTraceID(ctx); ok { + lbls := prometheus.Labels{"traceID": traceID} + if userID, err := user.ExtractUserID(ctx); err == nil { + lbls["user"] = userID + } + if orgID, err := user.ExtractOrgID(ctx); err == nil { + lbls["organization"] = orgID + } histogram.(prometheus.ExemplarObserver).ObserveWithExemplar( seconds, - prometheus.Labels{"traceID": traceID}, + lbls, ) return } diff --git a/vendor/github.com/weaveworks/common/middleware/grpc_instrumentation.go b/vendor/github.com/weaveworks/common/middleware/grpc_instrumentation.go index 5ced3989e80..90c955f1e82 100644 --- a/vendor/github.com/weaveworks/common/middleware/grpc_instrumentation.go +++ b/vendor/github.com/weaveworks/common/middleware/grpc_instrumentation.go @@ -1,6 +1,8 @@ package middleware import ( + "context" + "io" "strconv" "time" @@ -8,8 +10,8 @@ import ( grpcUtils "github.com/weaveworks/common/grpc" "github.com/weaveworks/common/httpgrpc" "github.com/weaveworks/common/instrument" - "golang.org/x/net/context" "google.golang.org/grpc" + "google.golang.org/grpc/metadata" ) func observe(ctx context.Context, hist *prometheus.HistogramVec, method string, err error, duration time.Duration) { @@ -45,3 +47,90 @@ func StreamServerInstrumentInterceptor(hist *prometheus.HistogramVec) grpc.Strea return err } } + +// UnaryClientInstrumentInterceptor records duration of gRPC requests client side. +func UnaryClientInstrumentInterceptor(metric *prometheus.HistogramVec) grpc.UnaryClientInterceptor { + return func(ctx context.Context, method string, req, resp interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { + start := time.Now() + err := invoker(ctx, method, req, resp, cc, opts...) + metric.WithLabelValues(method, errorCode(err)).Observe(time.Since(start).Seconds()) + return err + } +} + +// StreamClientInstrumentInterceptor records duration of streaming gRPC requests client side. +func StreamClientInstrumentInterceptor(metric *prometheus.HistogramVec) grpc.StreamClientInterceptor { + return func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, + streamer grpc.Streamer, opts ...grpc.CallOption, + ) (grpc.ClientStream, error) { + start := time.Now() + stream, err := streamer(ctx, desc, cc, method, opts...) + return &instrumentedClientStream{ + metric: metric, + start: start, + method: method, + ClientStream: stream, + }, err + } +} + +type instrumentedClientStream struct { + metric *prometheus.HistogramVec + start time.Time + method string + grpc.ClientStream +} + +func (s *instrumentedClientStream) SendMsg(m interface{}) error { + err := s.ClientStream.SendMsg(m) + if err == nil { + return nil + } + + if err == io.EOF { + s.metric.WithLabelValues(s.method, errorCode(nil)).Observe(time.Since(s.start).Seconds()) + } else { + s.metric.WithLabelValues(s.method, errorCode(err)).Observe(time.Since(s.start).Seconds()) + } + + return err +} + +func (s *instrumentedClientStream) RecvMsg(m interface{}) error { + err := s.ClientStream.RecvMsg(m) + if err == nil { + return nil + } + + if err == io.EOF { + s.metric.WithLabelValues(s.method, errorCode(nil)).Observe(time.Since(s.start).Seconds()) + } else { + s.metric.WithLabelValues(s.method, errorCode(err)).Observe(time.Since(s.start).Seconds()) + } + + return err +} + +func (s *instrumentedClientStream) Header() (metadata.MD, error) { + md, err := s.ClientStream.Header() + if err != nil { + s.metric.WithLabelValues(s.method, errorCode(err)).Observe(time.Since(s.start).Seconds()) + } + return md, err +} + +// errorCode converts an error into an error code string. +func errorCode(err error) string { + if err == nil { + return "2xx" + } + + if errResp, ok := httpgrpc.HTTPResponseFromError(err); ok { + statusFamily := int(errResp.Code / 100) + return strconv.Itoa(statusFamily) + "xx" + } else if grpcUtils.IsCanceled(err) { + return "cancel" + } else { + return "error" + } +} diff --git a/vendor/github.com/weaveworks/common/middleware/grpc_logging.go b/vendor/github.com/weaveworks/common/middleware/grpc_logging.go index 5a3a393c8aa..59994413cd8 100644 --- a/vendor/github.com/weaveworks/common/middleware/grpc_logging.go +++ b/vendor/github.com/weaveworks/common/middleware/grpc_logging.go @@ -20,13 +20,18 @@ const ( type GRPCServerLog struct { Log logging.Interface // WithRequest will log the entire request rather than just the error - WithRequest bool + WithRequest bool + DisableRequestSuccessLog bool } // UnaryServerInterceptor returns an interceptor that logs gRPC requests func (s GRPCServerLog) UnaryServerInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { begin := time.Now() resp, err := handler(ctx, req) + if err == nil && s.DisableRequestSuccessLog { + return resp, nil + } + entry := user.LogWith(ctx, s.Log).WithFields(logging.Fields{"method": info.FullMethod, "duration": time.Since(begin)}) if err != nil { if s.WithRequest { @@ -47,6 +52,10 @@ func (s GRPCServerLog) UnaryServerInterceptor(ctx context.Context, req interface func (s GRPCServerLog) StreamServerInterceptor(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { begin := time.Now() err := handler(srv, ss) + if err == nil && s.DisableRequestSuccessLog { + return nil + } + entry := user.LogWith(ss.Context(), s.Log).WithFields(logging.Fields{"method": info.FullMethod, "duration": time.Since(begin)}) if err != nil { if grpcUtils.IsCanceled(err) { diff --git a/vendor/github.com/weaveworks/common/middleware/logging.go b/vendor/github.com/weaveworks/common/middleware/logging.go index 81e1e48a271..015cc3b585f 100644 --- a/vendor/github.com/weaveworks/common/middleware/logging.go +++ b/vendor/github.com/weaveworks/common/middleware/logging.go @@ -14,9 +14,10 @@ import ( // Log middleware logs http requests type Log struct { - Log logging.Interface - LogRequestHeaders bool // LogRequestHeaders true -> dump http headers at debug log level - SourceIPs *SourceIPExtractor + Log logging.Interface + LogRequestHeaders bool // LogRequestHeaders true -> dump http headers at debug log level + LogRequestAtInfoLevel bool // LogRequestAtInfoLevel true -> log requests at info log level + SourceIPs *SourceIPExtractor } // logWithRequest information from the request and context as fields. @@ -42,11 +43,12 @@ func (l Log) Wrap(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { begin := time.Now() uri := r.RequestURI // capture the URI before running next, as it may get rewritten + requestLog := l.logWithRequest(r) // Log headers before running 'next' in case other interceptors change the data. headers, err := dumpRequest(r) if err != nil { headers = nil - l.logWithRequest(r).Errorf("Could not dump request headers: %v", err) + requestLog.Errorf("Could not dump request headers: %v", err) } var buf bytes.Buffer wrapped := newBadResponseLoggingWriter(w, &buf) @@ -56,20 +58,32 @@ func (l Log) Wrap(next http.Handler) http.Handler { if writeErr != nil { if errors.Is(writeErr, context.Canceled) { - l.logWithRequest(r).Debugf("%s %s %s, request cancelled: %s ws: %v; %s", r.Method, uri, time.Since(begin), writeErr, IsWSHandshakeRequest(r), headers) + if l.LogRequestAtInfoLevel { + requestLog.Infof("%s %s %s, request cancelled: %s ws: %v; %s", r.Method, uri, time.Since(begin), writeErr, IsWSHandshakeRequest(r), headers) + } else { + requestLog.Debugf("%s %s %s, request cancelled: %s ws: %v; %s", r.Method, uri, time.Since(begin), writeErr, IsWSHandshakeRequest(r), headers) + } } else { - l.logWithRequest(r).Warnf("%s %s %s, error: %s ws: %v; %s", r.Method, uri, time.Since(begin), writeErr, IsWSHandshakeRequest(r), headers) + requestLog.Warnf("%s %s %s, error: %s ws: %v; %s", r.Method, uri, time.Since(begin), writeErr, IsWSHandshakeRequest(r), headers) } return } if 100 <= statusCode && statusCode < 500 || statusCode == http.StatusBadGateway || statusCode == http.StatusServiceUnavailable { - l.logWithRequest(r).Debugf("%s %s (%d) %s", r.Method, uri, statusCode, time.Since(begin)) + if l.LogRequestAtInfoLevel { + requestLog.Infof("%s %s (%d) %s", r.Method, uri, statusCode, time.Since(begin)) + } else { + requestLog.Debugf("%s %s (%d) %s", r.Method, uri, statusCode, time.Since(begin)) + } if l.LogRequestHeaders && headers != nil { - l.logWithRequest(r).Debugf("ws: %v; %s", IsWSHandshakeRequest(r), string(headers)) + if l.LogRequestAtInfoLevel { + requestLog.Infof("ws: %v; %s", IsWSHandshakeRequest(r), string(headers)) + } else { + requestLog.Debugf("ws: %v; %s", IsWSHandshakeRequest(r), string(headers)) + } } } else { - l.logWithRequest(r).Warnf("%s %s (%d) %s Response: %q ws: %v; %s", + requestLog.Warnf("%s %s (%d) %s Response: %q ws: %v; %s", r.Method, uri, statusCode, time.Since(begin), buf.Bytes(), IsWSHandshakeRequest(r), headers) } }) diff --git a/vendor/github.com/weaveworks/common/server/server.go b/vendor/github.com/weaveworks/common/server/server.go index ff229ea8559..a956665b0ea 100644 --- a/vendor/github.com/weaveworks/common/server/server.go +++ b/vendor/github.com/weaveworks/common/server/server.go @@ -16,7 +16,7 @@ import ( "github.com/opentracing/opentracing-go" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" - node_https "github.com/prometheus/node_exporter/https" + "github.com/prometheus/exporter-toolkit/web" "golang.org/x/net/context" "golang.org/x/net/netutil" "google.golang.org/grpc" @@ -50,6 +50,14 @@ type SignalHandler interface { Stop() } +// TLSConfig contains TLS parameters for Config. +type TLSConfig struct { + TLSCertPath string `yaml:"cert_file"` + TLSKeyPath string `yaml:"key_file"` + ClientAuth string `yaml:"client_auth_type"` + ClientCAs string `yaml:"client_ca_file"` +} + // Config for a Server type Config struct { MetricsNamespace string `yaml:"-"` @@ -62,11 +70,12 @@ type Config struct { GRPCListenPort int `yaml:"grpc_listen_port"` GRPCConnLimit int `yaml:"grpc_listen_conn_limit"` - HTTPTLSConfig node_https.TLSStruct `yaml:"http_tls_config"` - GRPCTLSConfig node_https.TLSStruct `yaml:"grpc_tls_config"` + HTTPTLSConfig TLSConfig `yaml:"http_tls_config"` + GRPCTLSConfig TLSConfig `yaml:"grpc_tls_config"` - RegisterInstrumentation bool `yaml:"register_instrumentation"` - ExcludeRequestInLog bool `yaml:"-"` + RegisterInstrumentation bool `yaml:"register_instrumentation"` + ExcludeRequestInLog bool `yaml:"-"` + DisableRequestSuccessLog bool `yaml:"-"` ServerGracefulShutdownTimeout time.Duration `yaml:"graceful_shutdown_timeout"` HTTPServerReadTimeout time.Duration `yaml:"http_server_read_timeout"` @@ -91,12 +100,13 @@ type Config struct { GRPCServerMinTimeBetweenPings time.Duration `yaml:"grpc_server_min_time_between_pings"` GRPCServerPingWithoutStreamAllowed bool `yaml:"grpc_server_ping_without_stream_allowed"` - LogFormat logging.Format `yaml:"log_format"` - LogLevel logging.Level `yaml:"log_level"` - Log logging.Interface `yaml:"-"` - LogSourceIPs bool `yaml:"log_source_ips_enabled"` - LogSourceIPsHeader string `yaml:"log_source_ips_header"` - LogSourceIPsRegex string `yaml:"log_source_ips_regex"` + LogFormat logging.Format `yaml:"log_format"` + LogLevel logging.Level `yaml:"log_level"` + Log logging.Interface `yaml:"-"` + LogSourceIPs bool `yaml:"log_source_ips_enabled"` + LogSourceIPsHeader string `yaml:"log_source_ips_header"` + LogSourceIPsRegex string `yaml:"log_source_ips_regex"` + LogRequestAtInfoLevel bool `yaml:"log_request_at_info_level_enabled"` // If not set, default signal handler is used. SignalHandler SignalHandler `yaml:"-"` @@ -149,6 +159,7 @@ func (cfg *Config) RegisterFlags(f *flag.FlagSet) { f.BoolVar(&cfg.LogSourceIPs, "server.log-source-ips-enabled", false, "Optionally log the source IPs.") f.StringVar(&cfg.LogSourceIPsHeader, "server.log-source-ips-header", "", "Header field storing the source IPs. Only used if server.log-source-ips-enabled is true. If not set the default Forwarded, X-Real-IP and X-Forwarded-For headers are used") f.StringVar(&cfg.LogSourceIPsRegex, "server.log-source-ips-regex", "", "Regex for matching the source IPs. Only used if server.log-source-ips-enabled is true. If not set the default Forwarded, X-Real-IP and X-Forwarded-For headers are used") + f.BoolVar(&cfg.LogRequestAtInfoLevel, "server.log-request-at-info-level-enabled", false, "Optionally log requests at info level instead of debug level.") } // Server wraps a HTTP and gRPC server, and some common initialization. @@ -235,16 +246,26 @@ func New(cfg Config) (*Server, error) { // Setup TLS var httpTLSConfig *tls.Config if len(cfg.HTTPTLSConfig.TLSCertPath) > 0 && len(cfg.HTTPTLSConfig.TLSKeyPath) > 0 { - // Note: ConfigToTLSConfig from prometheus/node_exporter is awaiting security review. - httpTLSConfig, err = node_https.ConfigToTLSConfig(&cfg.HTTPTLSConfig) + // Note: ConfigToTLSConfig from prometheus/exporter-toolkit is awaiting security review. + httpTLSConfig, err = web.ConfigToTLSConfig(&web.TLSStruct{ + TLSCertPath: cfg.HTTPTLSConfig.TLSCertPath, + TLSKeyPath: cfg.HTTPTLSConfig.TLSKeyPath, + ClientAuth: cfg.HTTPTLSConfig.ClientAuth, + ClientCAs: cfg.HTTPTLSConfig.ClientCAs, + }) if err != nil { return nil, fmt.Errorf("error generating http tls config: %v", err) } } var grpcTLSConfig *tls.Config if len(cfg.GRPCTLSConfig.TLSCertPath) > 0 && len(cfg.GRPCTLSConfig.TLSKeyPath) > 0 { - // Note: ConfigToTLSConfig from prometheus/node_exporter is awaiting security review. - grpcTLSConfig, err = node_https.ConfigToTLSConfig(&cfg.GRPCTLSConfig) + // Note: ConfigToTLSConfig from prometheus/exporter-toolkit is awaiting security review. + grpcTLSConfig, err = web.ConfigToTLSConfig(&web.TLSStruct{ + TLSCertPath: cfg.GRPCTLSConfig.TLSCertPath, + TLSKeyPath: cfg.GRPCTLSConfig.TLSKeyPath, + ClientAuth: cfg.GRPCTLSConfig.ClientAuth, + ClientCAs: cfg.GRPCTLSConfig.ClientCAs, + }) if err != nil { return nil, fmt.Errorf("error generating grpc tls config: %v", err) } @@ -286,8 +307,9 @@ func New(cfg Config) (*Server, error) { // Setup gRPC server serverLog := middleware.GRPCServerLog{ - WithRequest: !cfg.ExcludeRequestInLog, - Log: log, + Log: log, + WithRequest: !cfg.ExcludeRequestInLog, + DisableRequestSuccessLog: cfg.DisableRequestSuccessLog, } grpcMiddleware := []grpc.UnaryServerInterceptor{ serverLog.UnaryServerInterceptor, @@ -367,8 +389,9 @@ func New(cfg Config) (*Server, error) { SourceIPs: sourceIPs, }, middleware.Log{ - Log: log, - SourceIPs: sourceIPs, + Log: log, + SourceIPs: sourceIPs, + LogRequestAtInfoLevel: cfg.LogRequestAtInfoLevel, }, middleware.Instrument{ RouteMatcher: router, diff --git a/vendor/modules.txt b/vendor/modules.txt index dddc31244e8..f9fff2b6d7f 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -432,7 +432,7 @@ github.com/gosimple/slug # github.com/grafana-tools/sdk v0.0.0-20211220201350-966b3088eec9 => github.com/colega/grafana-tools-sdk v0.0.0-20220323154849-711bca56d13f ## explicit; go 1.13 github.com/grafana-tools/sdk -# github.com/grafana/dskit v0.0.0-20220622130855-7bb188ccf75a +# github.com/grafana/dskit v0.0.0-20220704121012-e441b77be778 ## explicit; go 1.17 github.com/grafana/dskit/backoff github.com/grafana/dskit/concurrency @@ -448,7 +448,6 @@ github.com/grafana/dskit/kv/consul github.com/grafana/dskit/kv/etcd github.com/grafana/dskit/kv/memberlist github.com/grafana/dskit/limiter -github.com/grafana/dskit/middleware github.com/grafana/dskit/modules github.com/grafana/dskit/multierror github.com/grafana/dskit/netutil @@ -709,9 +708,6 @@ github.com/prometheus/common/sigv4 # github.com/prometheus/exporter-toolkit v0.7.1 ## explicit; go 1.14 github.com/prometheus/exporter-toolkit/web -# github.com/prometheus/node_exporter v1.0.0-rc.0.0.20200428091818-01054558c289 -## explicit; go 1.13 -github.com/prometheus/node_exporter/https # github.com/prometheus/procfs v0.7.3 ## explicit; go 1.13 github.com/prometheus/procfs @@ -872,8 +868,8 @@ github.com/vimeo/galaxycache/http github.com/vimeo/galaxycache/lru github.com/vimeo/galaxycache/promoter github.com/vimeo/galaxycache/singleflight -# github.com/weaveworks/common v0.0.0-20211109170639-0684aab3d884 -## explicit; go 1.13 +# github.com/weaveworks/common v0.0.0-20220706100410-67d27ed40fae +## explicit; go 1.14 github.com/weaveworks/common/errors github.com/weaveworks/common/grpc github.com/weaveworks/common/httpgrpc