github.com/yankunsam/loki/v2@v2.6.3-0.20220817130409-389df5235c27/clients/cmd/fluent-bit/config.go (about)

     1  package main
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  	"fmt"
     7  	"io/ioutil"
     8  	"strconv"
     9  	"strings"
    10  	"time"
    11  
    12  	"github.com/grafana/dskit/flagext"
    13  	"github.com/prometheus/common/model"
    14  	"github.com/weaveworks/common/logging"
    15  
    16  	"github.com/grafana/loki/clients/pkg/logentry/logql"
    17  	"github.com/grafana/loki/clients/pkg/promtail/client"
    18  
    19  	lokiflag "github.com/grafana/loki/pkg/util/flagext"
    20  )
    21  
    22  var defaultClientCfg = client.Config{}
    23  
    24  func init() {
    25  	// Init everything with default values.
    26  	flagext.RegisterFlags(&defaultClientCfg)
    27  }
    28  
    29  type ConfigGetter interface {
    30  	Get(key string) string
    31  }
    32  
    33  type format int
    34  
    35  const (
    36  	jsonFormat format = iota
    37  	kvPairFormat
    38  )
    39  
    40  const (
    41  	falseStr = "false"
    42  	trueStr  = "true"
    43  )
    44  
    45  type config struct {
    46  	clientConfig         client.Config
    47  	bufferConfig         bufferConfig
    48  	logLevel             logging.Level
    49  	autoKubernetesLabels bool
    50  	removeKeys           []string
    51  	labelKeys            []string
    52  	lineFormat           format
    53  	dropSingleKey        bool
    54  	labelMap             map[string]interface{}
    55  }
    56  
    57  func parseConfig(cfg ConfigGetter) (*config, error) {
    58  	res := &config{}
    59  
    60  	res.clientConfig = defaultClientCfg
    61  	res.bufferConfig = defaultBufferConfig
    62  
    63  	url := cfg.Get("URL")
    64  	var clientURL flagext.URLValue
    65  	if url == "" {
    66  		url = "http://localhost:3100/loki/api/v1/push"
    67  	}
    68  	err := clientURL.Set(url)
    69  	if err != nil {
    70  		return nil, errors.New("failed to parse client URL")
    71  	}
    72  	res.clientConfig.URL = clientURL
    73  
    74  	// cfg.Get will return empty string if not set, which is handled by the client library as no tenant
    75  	res.clientConfig.TenantID = cfg.Get("TenantID")
    76  
    77  	batchWait := cfg.Get("BatchWait")
    78  	if batchWait != "" {
    79  		// first try to parse as seconds format.
    80  		batchWaitSeconds, err := strconv.Atoi(batchWait)
    81  		if err == nil {
    82  			res.clientConfig.BatchWait = time.Duration(batchWaitSeconds) * time.Second
    83  		} else {
    84  			batchWaitValue, err := time.ParseDuration(batchWait)
    85  			if err != nil {
    86  				return nil, fmt.Errorf("failed to parse BatchWait: %s", batchWait)
    87  			}
    88  			res.clientConfig.BatchWait = batchWaitValue
    89  		}
    90  	}
    91  
    92  	batchSize := cfg.Get("BatchSize")
    93  	if batchSize != "" {
    94  		batchSizeValue, err := strconv.Atoi(batchSize)
    95  		if err != nil {
    96  			return nil, fmt.Errorf("failed to parse BatchSize: %s", batchSize)
    97  		}
    98  		res.clientConfig.BatchSize = batchSizeValue
    99  	}
   100  
   101  	timeout := cfg.Get("Timeout")
   102  	if timeout != "" {
   103  		timeoutValue, err := time.ParseDuration(timeout)
   104  		if err != nil {
   105  			return nil, fmt.Errorf("failed to parse Timeout: %s", timeout)
   106  		}
   107  		res.clientConfig.Timeout = timeoutValue
   108  	}
   109  
   110  	minBackoff := cfg.Get("MinBackoff")
   111  	if minBackoff != "" {
   112  		minBackoffValue, err := time.ParseDuration(minBackoff)
   113  		if err != nil {
   114  			return nil, fmt.Errorf("failed to parse MinBackoff: %s", minBackoff)
   115  		}
   116  		res.clientConfig.BackoffConfig.MinBackoff = minBackoffValue
   117  	}
   118  
   119  	maxBackoff := cfg.Get("MaxBackoff")
   120  	if maxBackoff != "" {
   121  		maxBackoffValue, err := time.ParseDuration(maxBackoff)
   122  		if err != nil {
   123  			return nil, fmt.Errorf("failed to parse MaxBackoff: %s", maxBackoff)
   124  		}
   125  		res.clientConfig.BackoffConfig.MaxBackoff = maxBackoffValue
   126  	}
   127  
   128  	maxRetries := cfg.Get("MaxRetries")
   129  	if maxRetries != "" {
   130  		maxRetriesValue, err := strconv.Atoi(maxRetries)
   131  		if err != nil {
   132  			return nil, fmt.Errorf("failed to parse MaxRetries: %s", maxRetries)
   133  		}
   134  		res.clientConfig.BackoffConfig.MaxRetries = maxRetriesValue
   135  	}
   136  
   137  	labels := cfg.Get("Labels")
   138  	if labels == "" {
   139  		labels = `{job="fluent-bit"}`
   140  	}
   141  	matchers, err := logql.ParseMatchers(labels)
   142  	if err != nil {
   143  		return nil, err
   144  	}
   145  	labelSet := make(model.LabelSet)
   146  	for _, m := range matchers {
   147  		labelSet[model.LabelName(m.Name)] = model.LabelValue(m.Value)
   148  	}
   149  	res.clientConfig.ExternalLabels = lokiflag.LabelSet{LabelSet: labelSet}
   150  
   151  	logLevel := cfg.Get("LogLevel")
   152  	if logLevel == "" {
   153  		logLevel = "info"
   154  	}
   155  	var level logging.Level
   156  	if err := level.Set(logLevel); err != nil {
   157  		return nil, fmt.Errorf("invalid log level: %v", logLevel)
   158  	}
   159  	res.logLevel = level
   160  
   161  	autoKubernetesLabels := cfg.Get("AutoKubernetesLabels")
   162  	switch autoKubernetesLabels {
   163  	case falseStr, "":
   164  		res.autoKubernetesLabels = false
   165  	case trueStr:
   166  		res.autoKubernetesLabels = true
   167  	default:
   168  		return nil, fmt.Errorf("invalid boolean AutoKubernetesLabels: %v", autoKubernetesLabels)
   169  	}
   170  
   171  	removeKey := cfg.Get("RemoveKeys")
   172  	if removeKey != "" {
   173  		res.removeKeys = strings.Split(removeKey, ",")
   174  	}
   175  
   176  	labelKeys := cfg.Get("LabelKeys")
   177  	if labelKeys != "" {
   178  		res.labelKeys = strings.Split(labelKeys, ",")
   179  	}
   180  
   181  	dropSingleKey := cfg.Get("DropSingleKey")
   182  	switch dropSingleKey {
   183  	case falseStr:
   184  		res.dropSingleKey = false
   185  	case trueStr, "":
   186  		res.dropSingleKey = true
   187  	default:
   188  		return nil, fmt.Errorf("invalid boolean DropSingleKey: %v", dropSingleKey)
   189  	}
   190  
   191  	lineFormat := cfg.Get("LineFormat")
   192  	switch lineFormat {
   193  	case "json", "":
   194  		res.lineFormat = jsonFormat
   195  	case "key_value":
   196  		res.lineFormat = kvPairFormat
   197  	default:
   198  		return nil, fmt.Errorf("invalid format: %s", lineFormat)
   199  	}
   200  
   201  	labelMapPath := cfg.Get("LabelMapPath")
   202  	if labelMapPath != "" {
   203  		content, err := ioutil.ReadFile(labelMapPath)
   204  		if err != nil {
   205  			return nil, fmt.Errorf("failed to open LabelMap file: %s", err)
   206  		}
   207  		if err := json.Unmarshal(content, &res.labelMap); err != nil {
   208  			return nil, fmt.Errorf("failed to Unmarshal LabelMap file: %s", err)
   209  		}
   210  		res.labelKeys = nil
   211  	}
   212  
   213  	// enable loki plugin buffering
   214  	buffer := cfg.Get("Buffer")
   215  	switch buffer {
   216  	case falseStr, "":
   217  		res.bufferConfig.buffer = false
   218  	case trueStr:
   219  		res.bufferConfig.buffer = true
   220  	default:
   221  		return nil, fmt.Errorf("invalid boolean Buffer: %v", buffer)
   222  	}
   223  
   224  	// buffering type
   225  	bufferType := cfg.Get("BufferType")
   226  	if bufferType != "" {
   227  		res.bufferConfig.bufferType = bufferType
   228  	}
   229  
   230  	// dque directory
   231  	queueDir := cfg.Get("DqueDir")
   232  	if queueDir != "" {
   233  		res.bufferConfig.dqueConfig.queueDir = queueDir
   234  	}
   235  
   236  	// dque segment size (queueEntry unit)
   237  	queueSegmentSize := cfg.Get("DqueSegmentSize")
   238  	if queueSegmentSize != "" {
   239  		res.bufferConfig.dqueConfig.queueSegmentSize, err = strconv.Atoi(queueSegmentSize)
   240  		if err != nil {
   241  			return nil, fmt.Errorf("impossible to convert string to integer DqueSegmentSize: %v", queueSegmentSize)
   242  		}
   243  	}
   244  
   245  	// dque control file change sync to disk as they happen aka dque.turbo mode
   246  	queueSync := cfg.Get("DqueSync")
   247  	switch queueSync {
   248  	case "normal", "":
   249  		res.bufferConfig.dqueConfig.queueSync = false
   250  	case "full":
   251  		res.bufferConfig.dqueConfig.queueSync = true
   252  	default:
   253  		return nil, fmt.Errorf("invalid string queueSync: %v", queueSync)
   254  	}
   255  
   256  	// dque name
   257  	queueName := cfg.Get("DqueName")
   258  	if queueName != "" {
   259  		res.bufferConfig.dqueConfig.queueName = queueName
   260  	}
   261  
   262  	res.clientConfig.Client.TLSConfig.CAFile = cfg.Get("ca_file")
   263  	res.clientConfig.Client.TLSConfig.CertFile = cfg.Get("cert_file")
   264  	res.clientConfig.Client.TLSConfig.KeyFile = cfg.Get("key_file")
   265  
   266  	insecureSkipVerify := cfg.Get("insecure_skip_verify")
   267  	switch insecureSkipVerify {
   268  	case "false", "":
   269  		res.clientConfig.Client.TLSConfig.InsecureSkipVerify = false
   270  	case "true":
   271  		res.clientConfig.Client.TLSConfig.InsecureSkipVerify = true
   272  	default:
   273  		return nil, fmt.Errorf("invalid string insecure_skip_verify: %v", insecureSkipVerify)
   274  	}
   275  
   276  	return res, nil
   277  }