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 }