Skip to content

chore: add GCS HTTP config #4005

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions cmd/pyroscope/help-all.txt.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -897,8 +897,24 @@ Usage of ./pyroscope:
Local filesystem storage directory. (default "./data-shared")
-storage.gcs.bucket-name string
GCS bucket name
-storage.gcs.expect-continue-timeout duration
The time to wait for a server's first response headers after fully writing the request headers if the request has an Expect header. 0 to send the request body immediately. (default 1s)
-storage.gcs.http.idle-conn-timeout duration
The time an idle connection will remain idle before closing. (default 1m30s)
-storage.gcs.http.insecure-skip-verify
If the client connects to GCS via HTTPS and this option is enabled, the client will accept any certificate and hostname.
-storage.gcs.http.response-header-timeout duration
The amount of time the client will wait for a servers response headers. (default 2m0s)
-storage.gcs.max-connections-per-host int
Maximum number of connections per host. 0 means no limit.
-storage.gcs.max-idle-connections int
Maximum number of idle (keep-alive) connections across all hosts. 0 means no limit.
-storage.gcs.max-idle-connections-per-host int
Maximum number of idle (keep-alive) connections to keep per-host. If 0, a built-in default value is used. (default 100)
-storage.gcs.service-account string
JSON either from a Google Developers Console client_credentials.json file, or a Google Developers service account key. Needs to be valid JSON, not a filesystem path.
-storage.gcs.tls-handshake-timeout duration
Maximum time to wait for a TLS handshake. 0 means no limit. (default 10s)
-storage.s3.access-key-id string
S3 access key ID
-storage.s3.bucket-lookup-type string
Expand Down
16 changes: 16 additions & 0 deletions cmd/pyroscope/help.txt.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -315,8 +315,24 @@ Usage of ./pyroscope:
Local filesystem storage directory. (default "./data-shared")
-storage.gcs.bucket-name string
GCS bucket name
-storage.gcs.expect-continue-timeout duration
The time to wait for a server's first response headers after fully writing the request headers if the request has an Expect header. 0 to send the request body immediately. (default 1s)
-storage.gcs.http.idle-conn-timeout duration
The time an idle connection will remain idle before closing. (default 1m30s)
-storage.gcs.http.insecure-skip-verify
If the client connects to GCS via HTTPS and this option is enabled, the client will accept any certificate and hostname.
-storage.gcs.http.response-header-timeout duration
The amount of time the client will wait for a servers response headers. (default 2m0s)
-storage.gcs.max-connections-per-host int
Maximum number of connections per host. 0 means no limit.
-storage.gcs.max-idle-connections int
Maximum number of idle (keep-alive) connections across all hosts. 0 means no limit.
-storage.gcs.max-idle-connections-per-host int
Maximum number of idle (keep-alive) connections to keep per-host. If 0, a built-in default value is used. (default 100)
-storage.gcs.service-account string
JSON either from a Google Developers Console client_credentials.json file, or a Google Developers service account key. Needs to be valid JSON, not a filesystem path.
-storage.gcs.tls-handshake-timeout duration
Maximum time to wait for a TLS handshake. 0 means no limit. (default 10s)
-storage.s3.access-key-id string
S3 access key ID
-storage.s3.bucket-name string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2356,6 +2356,44 @@ The gcs_backend block configures the connection to Google Cloud Storage object s
# 3. On Google Compute Engine it fetches credentials from the metadata server.
# CLI flag: -storage.gcs.service-account
[service_account: <string> | default = ""]

http:
# The time an idle connection will remain idle before closing.
# CLI flag: -storage.gcs.http.idle-conn-timeout
[idle_conn_timeout: <duration> | default = 1m30s]

# The amount of time the client will wait for a servers response headers.
# CLI flag: -storage.gcs.http.response-header-timeout
[response_header_timeout: <duration> | default = 2m]

# If the client connects to GCS via HTTPS and this option is enabled, the
# client will accept any certificate and hostname.
# CLI flag: -storage.gcs.http.insecure-skip-verify
[insecure_skip_verify: <boolean> | default = false]

# Maximum time to wait for a TLS handshake. 0 means no limit.
# CLI flag: -storage.gcs.tls-handshake-timeout
[tls_handshake_timeout: <duration> | default = 10s]

# The time to wait for a server's first response headers after fully writing
# the request headers if the request has an Expect header. 0 to send the
# request body immediately.
# CLI flag: -storage.gcs.expect-continue-timeout
[expect_continue_timeout: <duration> | default = 1s]

# Maximum number of idle (keep-alive) connections across all hosts. 0 means no
# limit.
# CLI flag: -storage.gcs.max-idle-connections
[max_idle_conns: <int> | default = 0]

# Maximum number of idle (keep-alive) connections to keep per-host. If 0, a
# built-in default value is used.
# CLI flag: -storage.gcs.max-idle-connections-per-host
[max_idle_conns_per_host: <int> | default = 100]

# Maximum number of connections per host. 0 means no limit.
# CLI flag: -storage.gcs.max-connections-per-host
[max_conns_per_host: <int> | default = 0]
```

### azure_storage_backend
Expand Down
23 changes: 11 additions & 12 deletions pkg/objstore/client/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"regexp"
"strings"

"github.com/go-kit/log"
"github.com/samber/lo"
"github.com/thanos-io/objstore"

Expand Down Expand Up @@ -70,11 +69,11 @@ func (cfg *StorageBackendConfig) supportedBackends() []string {
}

// RegisterFlags registers the backend storage config.
func (cfg *StorageBackendConfig) RegisterFlags(f *flag.FlagSet, logger log.Logger) {
cfg.RegisterFlagsWithPrefix("", f, logger)
func (cfg *StorageBackendConfig) RegisterFlags(f *flag.FlagSet) {
cfg.RegisterFlagsWithPrefix("", f)
}

func (cfg *StorageBackendConfig) RegisterFlagsWithPrefixAndDefaultDirectory(prefix, dir string, f *flag.FlagSet, logger log.Logger) {
func (cfg *StorageBackendConfig) RegisterFlagsWithPrefixAndDefaultDirectory(prefix, dir string, f *flag.FlagSet) {
cfg.S3.RegisterFlagsWithPrefix(prefix, f)
cfg.GCS.RegisterFlagsWithPrefix(prefix, f)
cfg.Azure.RegisterFlagsWithPrefix(prefix, f)
Expand All @@ -84,8 +83,8 @@ func (cfg *StorageBackendConfig) RegisterFlagsWithPrefixAndDefaultDirectory(pref
f.StringVar(&cfg.Backend, prefix+"backend", None, fmt.Sprintf("Backend storage to use. Supported backends are: %s.", strings.Join(cfg.supportedBackends(), ", ")))
}

func (cfg *StorageBackendConfig) RegisterFlagsWithPrefix(prefix string, f *flag.FlagSet, logger log.Logger) {
cfg.RegisterFlagsWithPrefixAndDefaultDirectory(prefix, "", f, logger)
func (cfg *StorageBackendConfig) RegisterFlagsWithPrefix(prefix string, f *flag.FlagSet) {
cfg.RegisterFlagsWithPrefixAndDefaultDirectory(prefix, "", f)
}

func (cfg *StorageBackendConfig) Validate() error {
Expand Down Expand Up @@ -119,17 +118,17 @@ type Config struct {
}

// RegisterFlags registers the backend storage config.
func (cfg *Config) RegisterFlags(f *flag.FlagSet, logger log.Logger) {
cfg.RegisterFlagsWithPrefix("", f, logger)
func (cfg *Config) RegisterFlags(f *flag.FlagSet) {
cfg.RegisterFlagsWithPrefix("", f)
}

func (cfg *Config) RegisterFlagsWithPrefixAndDefaultDirectory(prefix, dir string, f *flag.FlagSet, logger log.Logger) {
cfg.StorageBackendConfig.RegisterFlagsWithPrefixAndDefaultDirectory(prefix, dir, f, logger)
func (cfg *Config) RegisterFlagsWithPrefixAndDefaultDirectory(prefix, dir string, f *flag.FlagSet) {
cfg.StorageBackendConfig.RegisterFlagsWithPrefixAndDefaultDirectory(prefix, dir, f)
f.StringVar(&cfg.StoragePrefix, prefix+"storage-prefix", "", "Prefix for all objects stored in the backend storage. For simplicity, it may only contain digits and English alphabet letters.")
}

func (cfg *Config) RegisterFlagsWithPrefix(prefix string, f *flag.FlagSet, logger log.Logger) {
cfg.RegisterFlagsWithPrefixAndDefaultDirectory(prefix, "./data-shared", f, logger)
func (cfg *Config) RegisterFlagsWithPrefix(prefix string, f *flag.FlagSet) {
cfg.RegisterFlagsWithPrefixAndDefaultDirectory(prefix, "./data-shared", f)
}

func (cfg *Config) Validate() error {
Expand Down
12 changes: 12 additions & 0 deletions pkg/objstore/providers/gcs/bucket_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ import (
"context"

"github.com/go-kit/log"
"github.com/prometheus/common/model"
"github.com/thanos-io/objstore"
"github.com/thanos-io/objstore/exthttp"
"github.com/thanos-io/objstore/providers/gcs"
"gopkg.in/yaml.v3"
)
Expand All @@ -19,6 +21,16 @@ func NewBucketClient(ctx context.Context, cfg Config, name string, logger log.Lo
bucketConfig := gcs.Config{
Bucket: cfg.BucketName,
ServiceAccount: cfg.ServiceAccount.String(),
HTTPConfig: exthttp.HTTPConfig{
IdleConnTimeout: model.Duration(cfg.HTTP.IdleConnTimeout),
ResponseHeaderTimeout: model.Duration(cfg.HTTP.ResponseHeaderTimeout),
InsecureSkipVerify: cfg.HTTP.InsecureSkipVerify,
TLSHandshakeTimeout: model.Duration(cfg.HTTP.TLSHandshakeTimeout),
ExpectContinueTimeout: model.Duration(cfg.HTTP.ExpectContinueTimeout),
MaxIdleConns: cfg.HTTP.MaxIdleConns,
MaxIdleConnsPerHost: cfg.HTTP.MaxIdleConnsPerHost,
MaxConnsPerHost: cfg.HTTP.MaxConnsPerHost,
},
}

// Thanos currently doesn't support passing the config as is, but expects a YAML,
Expand Down
26 changes: 26 additions & 0 deletions pkg/objstore/providers/gcs/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package gcs

import (
"flag"
"time"

"github.com/grafana/dskit/flagext"
)
Expand All @@ -15,6 +16,7 @@ import (
type Config struct {
BucketName string `yaml:"bucket_name"`
ServiceAccount flagext.Secret `yaml:"service_account" doc:"description_method=GCSServiceAccountLongDescription"`
HTTP HTTPConfig `yaml:"http"`
}

// RegisterFlags registers the flags for GCS storage
Expand All @@ -26,6 +28,30 @@ func (cfg *Config) RegisterFlags(f *flag.FlagSet) {
func (cfg *Config) RegisterFlagsWithPrefix(prefix string, f *flag.FlagSet) {
f.StringVar(&cfg.BucketName, prefix+"gcs.bucket-name", "", "GCS bucket name")
f.Var(&cfg.ServiceAccount, prefix+"gcs.service-account", cfg.GCSServiceAccountShortDescription())
cfg.HTTP.RegisterFlagsWithPrefix(prefix, f)
}

type HTTPConfig struct {
IdleConnTimeout time.Duration `yaml:"idle_conn_timeout"`
ResponseHeaderTimeout time.Duration `yaml:"response_header_timeout"`
InsecureSkipVerify bool `yaml:"insecure_skip_verify"`
TLSHandshakeTimeout time.Duration `yaml:"tls_handshake_timeout"`
ExpectContinueTimeout time.Duration `yaml:"expect_continue_timeout"`
MaxIdleConns int `yaml:"max_idle_conns"`
MaxIdleConnsPerHost int `yaml:"max_idle_conns_per_host"`
MaxConnsPerHost int `yaml:"max_conns_per_host"`
}
Comment on lines +34 to +43
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably better to mark them all as advanced:

Suggested change
type HTTPConfig struct {
IdleConnTimeout time.Duration `yaml:"idle_conn_timeout"`
ResponseHeaderTimeout time.Duration `yaml:"response_header_timeout"`
InsecureSkipVerify bool `yaml:"insecure_skip_verify"`
TLSHandshakeTimeout time.Duration `yaml:"tls_handshake_timeout"`
ExpectContinueTimeout time.Duration `yaml:"expect_continue_timeout"`
MaxIdleConns int `yaml:"max_idle_conns"`
MaxIdleConnsPerHost int `yaml:"max_idle_conns_per_host"`
MaxConnsPerHost int `yaml:"max_conns_per_host"`
}
type HTTPConfig struct {
IdleConnTimeout time.Duration `yaml:"idle_conn_timeout"` `category:"advanced"`
ResponseHeaderTimeout time.Duration `yaml:"response_header_timeout"` `category:"advanced"`
InsecureSkipVerify bool `yaml:"insecure_skip_verify"` `category:"advanced"`
TLSHandshakeTimeout time.Duration `yaml:"tls_handshake_timeout"` `category:"advanced"`
ExpectContinueTimeout time.Duration `yaml:"expect_continue_timeout"` `category:"advanced"`
MaxIdleConns int `yaml:"max_idle_conns"` `category:"advanced"`
MaxIdleConnsPerHost int `yaml:"max_idle_conns_per_host"` `category:"advanced"`
MaxConnsPerHost int `yaml:"max_conns_per_host"` `category:"advanced"`
}

Copy link
Collaborator Author

@kolesnikovae kolesnikovae Mar 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've been thinking about it and decided to make it symmetric with the S3 config.

Actually, now that I look at it, it should be advanced – I'll add it in the follow up PR

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding it in #4007


// RegisterFlagsWithPrefix registers the flags for s3 storage with the provided prefix
func (cfg *HTTPConfig) RegisterFlagsWithPrefix(prefix string, f *flag.FlagSet) {
f.DurationVar(&cfg.IdleConnTimeout, prefix+"gcs.http.idle-conn-timeout", 90*time.Second, "The time an idle connection will remain idle before closing.")
f.DurationVar(&cfg.ResponseHeaderTimeout, prefix+"gcs.http.response-header-timeout", 2*time.Minute, "The amount of time the client will wait for a servers response headers.")
f.BoolVar(&cfg.InsecureSkipVerify, prefix+"gcs.http.insecure-skip-verify", false, "If the client connects to GCS via HTTPS and this option is enabled, the client will accept any certificate and hostname.")
f.DurationVar(&cfg.TLSHandshakeTimeout, prefix+"gcs.tls-handshake-timeout", 10*time.Second, "Maximum time to wait for a TLS handshake. 0 means no limit.")
f.DurationVar(&cfg.ExpectContinueTimeout, prefix+"gcs.expect-continue-timeout", 1*time.Second, "The time to wait for a server's first response headers after fully writing the request headers if the request has an Expect header. 0 to send the request body immediately.")
f.IntVar(&cfg.MaxIdleConns, prefix+"gcs.max-idle-connections", 0, "Maximum number of idle (keep-alive) connections across all hosts. 0 means no limit.")
f.IntVar(&cfg.MaxIdleConnsPerHost, prefix+"gcs.max-idle-connections-per-host", 100, "Maximum number of idle (keep-alive) connections to keep per-host. If 0, a built-in default value is used.")
f.IntVar(&cfg.MaxConnsPerHost, prefix+"gcs.max-connections-per-host", 0, "Maximum number of connections per host. 0 means no limit.")
}

func (cfg *Config) GCSServiceAccountShortDescription() string {
Expand Down
15 changes: 9 additions & 6 deletions pkg/phlare/phlare.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ import (
phlareobj "github.com/grafana/pyroscope/pkg/objstore"
objstoreclient "github.com/grafana/pyroscope/pkg/objstore/client"
"github.com/grafana/pyroscope/pkg/operations"
phlarecontext "github.com/grafana/pyroscope/pkg/phlare/context"
"github.com/grafana/pyroscope/pkg/phlaredb"
"github.com/grafana/pyroscope/pkg/querier"
"github.com/grafana/pyroscope/pkg/querier/worker"
Expand Down Expand Up @@ -131,8 +130,8 @@ type StorageConfig struct {
Bucket objstoreclient.Config `yaml:",inline"`
}

func (c *StorageConfig) RegisterFlagsWithContext(ctx context.Context, f *flag.FlagSet) {
c.Bucket.RegisterFlagsWithPrefix("storage.", f, phlarecontext.Logger(ctx))
func (c *StorageConfig) RegisterFlags(f *flag.FlagSet) {
c.Bucket.RegisterFlagsWithPrefix("storage.", f)
}

type SelfProfilingConfig struct {
Expand Down Expand Up @@ -161,11 +160,11 @@ func (c *SelfProfilingConfig) RegisterFlags(f *flag.FlagSet) {
}

func (c *Config) RegisterFlags(f *flag.FlagSet) {
c.RegisterFlagsWithContext(context.Background(), f)
c.RegisterFlagsWithContext(f)
}

// RegisterFlagsWithContext registers flag.
func (c *Config) RegisterFlagsWithContext(ctx context.Context, f *flag.FlagSet) {
func (c *Config) RegisterFlagsWithContext(f *flag.FlagSet) {
// Set the default module list to 'all'
c.Target = []string{All}
f.StringVar(&c.ConfigFile, "config.file", "", "yaml file to load")
Expand All @@ -191,7 +190,6 @@ func (c *Config) RegisterFlagsWithContext(ctx context.Context, f *flag.FlagSet)
c.StoreGateway.RegisterFlags(f, util.Logger)
c.PhlareDB.RegisterFlags(f)
c.Tracing.RegisterFlags(f)
c.Storage.RegisterFlagsWithContext(ctx, f)
c.SelfProfiling.RegisterFlags(f)
c.RuntimeConfig.RegisterFlags(f)
c.Analytics.RegisterFlags(f)
Expand All @@ -208,6 +206,7 @@ func (c *Config) registerServerFlagsWithChangedDefaultValues(fs *flag.FlagSet) {

// Register to throwaway flags first. Default values are remembered during registration and cannot be changed,
// but we can take values from throwaway flag set and reregister into supplied flags with new default values.
c.Storage.RegisterFlags(throwaway)
c.Server.RegisterFlags(throwaway)
c.Ingester.RegisterFlags(throwaway)
c.Distributor.RegisterFlags(throwaway, log.NewLogfmtLogger(os.Stderr))
Expand All @@ -233,6 +232,10 @@ func (c *Config) registerServerFlagsWithChangedDefaultValues(fs *flag.FlagSet) {
"segment-writer.heartbeat-timeout": "1m",
"segment-writer.unregister-on-shutdown": "false",
"segment-writer.min-ready-duration": "30s",
"storage.s3.http.idle-conn-timeout": "10m",
"storage.s3.max-idle-connections-per-host": "1000",
"storage.gcs.http.idle-conn-timeout": "10m",
"storage.gcs.max-idle-connections-per-host": "1000",
"compaction-worker.metrics-exporter.rules-source.static": "[]",
} {
overrides[k] = v
Expand Down
Loading