1package client
2
3import (
4	"flag"
5	"time"
6
7	"github.com/grafana/dskit/backoff"
8	"github.com/grafana/dskit/flagext"
9	"github.com/prometheus/common/config"
10
11	lokiflag "github.com/grafana/loki/pkg/util/flagext"
12)
13
14// NOTE the helm chart for promtail and fluent-bit also have defaults for these values, please update to match if you make changes here.
15const (
16	BatchWait      = 1 * time.Second
17	BatchSize  int = 1024 * 1024
18	MinBackoff     = 500 * time.Millisecond
19	MaxBackoff     = 5 * time.Minute
20	MaxRetries int = 10
21	Timeout        = 10 * time.Second
22)
23
24// Config describes configuration for a HTTP pusher client.
25type Config struct {
26	URL       flagext.URLValue
27	BatchWait time.Duration
28	BatchSize int
29
30	Client config.HTTPClientConfig `yaml:",inline"`
31
32	BackoffConfig backoff.Config `yaml:"backoff_config"`
33	// The labels to add to any time series or alerts when communicating with loki
34	ExternalLabels lokiflag.LabelSet `yaml:"external_labels,omitempty"`
35	Timeout        time.Duration     `yaml:"timeout"`
36
37	// The tenant ID to use when pushing logs to Loki (empty string means
38	// single tenant mode)
39	TenantID string `yaml:"tenant_id"`
40}
41
42// RegisterFlags with prefix registers flags where every name is prefixed by
43// prefix. If prefix is a non-empty string, prefix should end with a period.
44func (c *Config) RegisterFlagsWithPrefix(prefix string, f *flag.FlagSet) {
45	f.Var(&c.URL, prefix+"client.url", "URL of log server")
46	f.DurationVar(&c.BatchWait, prefix+"client.batch-wait", BatchWait, "Maximum wait period before sending batch.")
47	f.IntVar(&c.BatchSize, prefix+"client.batch-size-bytes", BatchSize, "Maximum batch size to accrue before sending. ")
48	// Default backoff schedule: 0.5s, 1s, 2s, 4s, 8s, 16s, 32s, 64s, 128s, 256s(4.267m) For a total time of 511.5s(8.5m) before logs are lost
49	f.IntVar(&c.BackoffConfig.MaxRetries, prefix+"client.max-retries", MaxRetries, "Maximum number of retires when sending batches.")
50	f.DurationVar(&c.BackoffConfig.MinBackoff, prefix+"client.min-backoff", MinBackoff, "Initial backoff time between retries.")
51	f.DurationVar(&c.BackoffConfig.MaxBackoff, prefix+"client.max-backoff", MaxBackoff, "Maximum backoff time between retries.")
52	f.DurationVar(&c.Timeout, prefix+"client.timeout", Timeout, "Maximum time to wait for server to respond to a request")
53	f.Var(&c.ExternalLabels, prefix+"client.external-labels", "list of external labels to add to each log (e.g: --client.external-labels=lb1=v1,lb2=v2)")
54
55	f.StringVar(&c.TenantID, prefix+"client.tenant-id", "", "Tenant ID to use when pushing logs to Loki.")
56}
57
58// RegisterFlags registers flags.
59func (c *Config) RegisterFlags(flags *flag.FlagSet) {
60	c.RegisterFlagsWithPrefix("", flags)
61}
62
63// UnmarshalYAML implement Yaml Unmarshaler
64func (c *Config) UnmarshalYAML(unmarshal func(interface{}) error) error {
65	type raw Config
66	var cfg raw
67	if c.URL.URL != nil {
68		// we used flags to set that value, which already has sane default.
69		cfg = raw(*c)
70	} else {
71		// force sane defaults.
72		cfg = raw{
73			BackoffConfig: backoff.Config{
74				MaxBackoff: MaxBackoff,
75				MaxRetries: MaxRetries,
76				MinBackoff: MinBackoff,
77			},
78			BatchSize: BatchSize,
79			BatchWait: BatchWait,
80			Timeout:   Timeout,
81		}
82	}
83
84	if err := unmarshal(&cfg); err != nil {
85		return err
86	}
87
88	*c = Config(cfg)
89	return nil
90}
91