github.com/influxdata/telegraf@v1.30.3/cmd/telegraf/printer.go (about) 1 package main 2 3 import ( 4 _ "embed" 5 "fmt" 6 "io" 7 "sort" 8 "strings" 9 10 "github.com/influxdata/telegraf" 11 "github.com/influxdata/telegraf/internal/choice" 12 "github.com/influxdata/telegraf/plugins/aggregators" 13 "github.com/influxdata/telegraf/plugins/inputs" 14 "github.com/influxdata/telegraf/plugins/outputs" 15 "github.com/influxdata/telegraf/plugins/processors" 16 "github.com/influxdata/telegraf/plugins/secretstores" 17 ) 18 19 var ( 20 // Default sections 21 sectionDefaults = []string{"global_tags", "agent", "secretstores", "outputs", "processors", "aggregators", "inputs"} 22 23 // Default input plugins 24 inputDefaults = []string{"cpu", "mem", "swap", "system", "kernel", "processes", "disk", "diskio"} 25 26 // Default output plugins 27 outputDefaults = []string{} 28 ) 29 30 var header = `# Telegraf Configuration 31 # 32 # Telegraf is entirely plugin driven. All metrics are gathered from the 33 # declared inputs, and sent to the declared outputs. 34 # 35 # Plugins must be declared in here to be active. 36 # To deactivate a plugin, comment out the name and any variables. 37 # 38 # Use 'telegraf -config telegraf.conf -test' to see what metrics a config 39 # file would generate. 40 # 41 # Environment variables can be used anywhere in this config file, simply surround 42 # them with ${}. For strings the variable must be within quotes (ie, "${STR_VAR}"), 43 # for numbers and booleans they should be plain (ie, ${INT_VAR}, ${BOOL_VAR}) 44 45 ` 46 var globalTagsConfig = ` 47 # Global tags can be specified here in key="value" format. 48 [global_tags] 49 # dc = "us-east-1" # will tag all metrics with dc=us-east-1 50 # rack = "1a" 51 ## Environment variables can be used as tags, and throughout the config file 52 # user = "$USER" 53 54 ` 55 56 // DO NOT REMOVE THE NEXT TWO LINES! This is required to embed the agentConfig data. 57 // 58 //go:embed agent.conf 59 var agentConfig string 60 61 var secretstoreHeader = ` 62 ############################################################################### 63 # SECRETSTORE PLUGINS # 64 ############################################################################### 65 66 ` 67 68 var outputHeader = ` 69 ############################################################################### 70 # OUTPUT PLUGINS # 71 ############################################################################### 72 73 ` 74 75 var processorHeader = ` 76 ############################################################################### 77 # PROCESSOR PLUGINS # 78 ############################################################################### 79 80 ` 81 82 var aggregatorHeader = ` 83 ############################################################################### 84 # AGGREGATOR PLUGINS # 85 ############################################################################### 86 87 ` 88 89 var inputHeader = ` 90 ############################################################################### 91 # INPUT PLUGINS # 92 ############################################################################### 93 94 ` 95 96 var serviceInputHeader = ` 97 ############################################################################### 98 # SERVICE INPUT PLUGINS # 99 ############################################################################### 100 101 ` 102 103 // printSampleConfig prints the sample config 104 func printSampleConfig(outputBuffer io.Writer, filters Filters) { 105 sectionFilters := filters.section 106 inputFilters := filters.input 107 outputFilters := filters.output 108 aggregatorFilters := filters.aggregator 109 processorFilters := filters.processor 110 secretstoreFilters := filters.secretstore 111 112 // print headers 113 outputBuffer.Write([]byte(header)) 114 115 if len(sectionFilters) == 0 { 116 sectionFilters = sectionDefaults 117 } 118 printFilteredGlobalSections(sectionFilters, outputBuffer) 119 120 // print secretstore plugins 121 if choice.Contains("secretstores", sectionFilters) { 122 if len(secretstoreFilters) != 0 { 123 if len(secretstoreFilters) >= 3 && secretstoreFilters[1] != "none" { 124 fmt.Print(secretstoreHeader) 125 } 126 printFilteredSecretstores(secretstoreFilters, false, outputBuffer) 127 } else { 128 fmt.Print(secretstoreHeader) 129 snames := []string{} 130 for sname := range secretstores.SecretStores { 131 snames = append(snames, sname) 132 } 133 sort.Strings(snames) 134 printFilteredSecretstores(snames, true, outputBuffer) 135 } 136 } 137 138 // print output plugins 139 if choice.Contains("outputs", sectionFilters) { 140 if len(outputFilters) != 0 { 141 if len(outputFilters) >= 3 && outputFilters[1] != "none" { 142 outputBuffer.Write([]byte(outputHeader)) 143 } 144 printFilteredOutputs(outputFilters, false, outputBuffer) 145 } else { 146 outputBuffer.Write([]byte(outputHeader)) 147 printFilteredOutputs(outputDefaults, false, outputBuffer) 148 // Print non-default outputs, commented 149 var pnames []string 150 for pname := range outputs.Outputs { 151 if !choice.Contains(pname, outputDefaults) { 152 pnames = append(pnames, pname) 153 } 154 } 155 printFilteredOutputs(pnames, true, outputBuffer) 156 } 157 } 158 159 // print processor plugins 160 if choice.Contains("processors", sectionFilters) { 161 if len(processorFilters) != 0 { 162 if len(processorFilters) >= 3 && processorFilters[1] != "none" { 163 outputBuffer.Write([]byte(processorHeader)) 164 } 165 printFilteredProcessors(processorFilters, false, outputBuffer) 166 } else { 167 outputBuffer.Write([]byte(processorHeader)) 168 pnames := []string{} 169 for pname := range processors.Processors { 170 pnames = append(pnames, pname) 171 } 172 printFilteredProcessors(pnames, true, outputBuffer) 173 } 174 } 175 176 // print aggregator plugins 177 if choice.Contains("aggregators", sectionFilters) { 178 if len(aggregatorFilters) != 0 { 179 if len(aggregatorFilters) >= 3 && aggregatorFilters[1] != "none" { 180 outputBuffer.Write([]byte(aggregatorHeader)) 181 } 182 printFilteredAggregators(aggregatorFilters, false, outputBuffer) 183 } else { 184 outputBuffer.Write([]byte(aggregatorHeader)) 185 pnames := []string{} 186 for pname := range aggregators.Aggregators { 187 pnames = append(pnames, pname) 188 } 189 printFilteredAggregators(pnames, true, outputBuffer) 190 } 191 } 192 193 // print input plugins 194 if choice.Contains("inputs", sectionFilters) { 195 if len(inputFilters) != 0 { 196 if len(inputFilters) >= 3 && inputFilters[1] != "none" { 197 outputBuffer.Write([]byte(inputHeader)) 198 } 199 printFilteredInputs(inputFilters, false, outputBuffer) 200 } else { 201 outputBuffer.Write([]byte(inputHeader)) 202 printFilteredInputs(inputDefaults, false, outputBuffer) 203 // Print non-default inputs, commented 204 var pnames []string 205 for pname := range inputs.Inputs { 206 if !choice.Contains(pname, inputDefaults) { 207 pnames = append(pnames, pname) 208 } 209 } 210 printFilteredInputs(pnames, true, outputBuffer) 211 } 212 } 213 } 214 215 func printFilteredProcessors(processorFilters []string, commented bool, outputBuffer io.Writer) { 216 // Filter processors 217 var pnames []string 218 for pname := range processors.Processors { 219 if choice.Contains(pname, processorFilters) { 220 pnames = append(pnames, pname) 221 } 222 } 223 sort.Strings(pnames) 224 225 // Print Outputs 226 for _, pname := range pnames { 227 creator := processors.Processors[pname] 228 output := creator() 229 printConfig(pname, output, "processors", commented, processors.Deprecations[pname], outputBuffer) 230 } 231 } 232 233 func printFilteredAggregators(aggregatorFilters []string, commented bool, outputBuffer io.Writer) { 234 // Filter outputs 235 var anames []string 236 for aname := range aggregators.Aggregators { 237 if choice.Contains(aname, aggregatorFilters) { 238 anames = append(anames, aname) 239 } 240 } 241 sort.Strings(anames) 242 243 // Print Outputs 244 for _, aname := range anames { 245 creator := aggregators.Aggregators[aname] 246 output := creator() 247 printConfig(aname, output, "aggregators", commented, aggregators.Deprecations[aname], outputBuffer) 248 } 249 } 250 251 func printFilteredInputs(inputFilters []string, commented bool, outputBuffer io.Writer) { 252 // Filter inputs 253 var pnames []string 254 for pname := range inputs.Inputs { 255 if choice.Contains(pname, inputFilters) { 256 pnames = append(pnames, pname) 257 } 258 } 259 sort.Strings(pnames) 260 261 // cache service inputs to print them at the end 262 servInputs := make(map[string]telegraf.ServiceInput) 263 // for alphabetical looping: 264 servInputNames := []string{} 265 266 // Print Inputs 267 for _, pname := range pnames { 268 // Skip inputs that are registered twice for backward compatibility 269 switch pname { 270 case "cisco_telemetry_gnmi", "io", "KNXListener": 271 continue 272 } 273 creator := inputs.Inputs[pname] 274 input := creator() 275 276 if p, ok := input.(telegraf.ServiceInput); ok { 277 servInputs[pname] = p 278 servInputNames = append(servInputNames, pname) 279 continue 280 } 281 282 printConfig(pname, input, "inputs", commented, inputs.Deprecations[pname], outputBuffer) 283 } 284 285 // Print Service Inputs 286 if len(servInputs) == 0 { 287 return 288 } 289 sort.Strings(servInputNames) 290 291 outputBuffer.Write([]byte(serviceInputHeader)) 292 for _, name := range servInputNames { 293 printConfig(name, servInputs[name], "inputs", commented, inputs.Deprecations[name], outputBuffer) 294 } 295 } 296 297 func printFilteredOutputs(outputFilters []string, commented bool, outputBuffer io.Writer) { 298 // Filter outputs 299 var onames []string 300 var influxdbV2 string 301 302 for oname := range outputs.Outputs { 303 if choice.Contains(oname, outputFilters) { 304 // Make influxdb_v2 the exception and have it be first in the list 305 // Store it and add it later 306 if oname == "influxdb_v2" { 307 influxdbV2 = oname 308 continue 309 } 310 311 onames = append(onames, oname) 312 } 313 } 314 sort.Strings(onames) 315 316 if influxdbV2 != "" { 317 onames = append([]string{influxdbV2}, onames...) 318 } 319 320 // Print Outputs 321 for _, oname := range onames { 322 creator := outputs.Outputs[oname] 323 output := creator() 324 printConfig(oname, output, "outputs", commented, outputs.Deprecations[oname], outputBuffer) 325 } 326 } 327 328 func printFilteredSecretstores(secretstoreFilters []string, commented bool, outputBuffer io.Writer) { 329 // Filter secretstores 330 var snames []string 331 for sname := range secretstores.SecretStores { 332 if choice.Contains(sname, secretstoreFilters) { 333 snames = append(snames, sname) 334 } 335 } 336 sort.Strings(snames) 337 338 // Print SecretStores 339 for _, sname := range snames { 340 creator := secretstores.SecretStores[sname] 341 store := creator("dummy") 342 printConfig(sname, store, "secretstores", commented, secretstores.Deprecations[sname], outputBuffer) 343 } 344 } 345 346 func printFilteredGlobalSections(sectionFilters []string, outputBuffer io.Writer) { 347 if choice.Contains("global_tags", sectionFilters) { 348 outputBuffer.Write([]byte(globalTagsConfig)) 349 } 350 351 if choice.Contains("agent", sectionFilters) { 352 outputBuffer.Write([]byte(agentConfig)) 353 } 354 } 355 356 func printConfig(name string, p telegraf.PluginDescriber, op string, commented bool, di telegraf.DeprecationInfo, outputBuffer io.Writer) { 357 comment := "" 358 if commented { 359 comment = "# " 360 } 361 362 if di.Since != "" { 363 removalNote := "" 364 if di.RemovalIn != "" { 365 removalNote = " and will be removed in " + di.RemovalIn 366 } 367 fmt.Fprintf(outputBuffer, "\n%s ## DEPRECATED: The %q plugin is deprecated in version %s%s, %s.", 368 comment, name, di.Since, removalNote, di.Notice) 369 } 370 371 sample := p.SampleConfig() 372 if sample == "" { 373 fmt.Fprintf(outputBuffer, "\n#[[%s.%s]]", op, name) 374 fmt.Fprintf(outputBuffer, "\n%s # no configuration\n\n", comment) 375 } else { 376 lines := strings.Split(sample, "\n") 377 outputBuffer.Write([]byte("\n")) 378 for i, line := range lines { 379 if i == len(lines)-1 { 380 outputBuffer.Write([]byte("\n")) 381 continue 382 } 383 outputBuffer.Write([]byte(strings.TrimRight(comment+line, " ") + "\n")) 384 } 385 } 386 } 387 388 // PrintInputConfig prints the config usage of a single input. 389 func PrintInputConfig(name string, outputBuffer io.Writer) error { 390 creator, ok := inputs.Inputs[name] 391 if !ok { 392 return fmt.Errorf("input %s not found", name) 393 } 394 395 printConfig(name, creator(), "inputs", false, inputs.Deprecations[name], outputBuffer) 396 return nil 397 } 398 399 // PrintOutputConfig prints the config usage of a single output. 400 func PrintOutputConfig(name string, outputBuffer io.Writer) error { 401 creator, ok := outputs.Outputs[name] 402 if !ok { 403 return fmt.Errorf("output %s not found", name) 404 } 405 406 printConfig(name, creator(), "outputs", false, outputs.Deprecations[name], outputBuffer) 407 return nil 408 }