feat: Migrate to urfave/cli (#11700)
This commit is contained in:
parent
7feb2722a7
commit
a57434eb4e
|
|
@ -4,7 +4,6 @@ linters:
|
|||
# - telegraflinter
|
||||
- bodyclose
|
||||
- dogsled
|
||||
- errcheck
|
||||
- goprintffuncname
|
||||
- gosimple
|
||||
- govet
|
||||
|
|
@ -71,7 +70,7 @@ linters-settings:
|
|||
- name: unconditional-recursion
|
||||
- name: unexported-naming
|
||||
- name: unhandled-error
|
||||
arguments: ["fmt.Printf", "fmt.Println", "fmt.Print"]
|
||||
arguments: ["outputBuffer.Write", "fmt.Printf", "fmt.Println", "fmt.Print"]
|
||||
- name: unnecessary-stmt
|
||||
- name: unreachable-code
|
||||
# - name: unused-parameter
|
||||
|
|
|
|||
6
Makefile
6
Makefile
|
|
@ -46,11 +46,11 @@ GOOS ?= $(shell go env GOOS)
|
|||
GOARCH ?= $(shell go env GOARCH)
|
||||
HOSTGO := env -u GOOS -u GOARCH -u GOARM -- go
|
||||
INTERNAL_PKG=github.com/influxdata/telegraf/internal
|
||||
LDFLAGS := $(LDFLAGS) -X $(INTERNAL_PKG).commit=$(commit) -X $(INTERNAL_PKG).branch=$(branch)
|
||||
LDFLAGS := $(LDFLAGS) -X $(INTERNAL_PKG).Commit=$(commit) -X $(INTERNAL_PKG).Branch=$(branch)
|
||||
ifneq ($(tag),)
|
||||
LDFLAGS += -X $(INTERNAL_PKG).version=$(version)
|
||||
LDFLAGS += -X $(INTERNAL_PKG).Version=$(version)
|
||||
else
|
||||
LDFLAGS += -X $(INTERNAL_PKG).version=$(version)-$(commit)
|
||||
LDFLAGS += -X $(INTERNAL_PKG).Version=$(version)-$(commit)
|
||||
endif
|
||||
|
||||
# Go built-in race detector works only for 64 bits architectures.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,355 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log" //nolint:revive
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/influxdata/telegraf/config"
|
||||
"github.com/influxdata/telegraf/internal"
|
||||
"github.com/influxdata/telegraf/internal/goplugin"
|
||||
"github.com/influxdata/telegraf/logger"
|
||||
_ "github.com/influxdata/telegraf/plugins/aggregators/all"
|
||||
"github.com/influxdata/telegraf/plugins/inputs"
|
||||
_ "github.com/influxdata/telegraf/plugins/inputs/all"
|
||||
"github.com/influxdata/telegraf/plugins/outputs"
|
||||
_ "github.com/influxdata/telegraf/plugins/outputs/all"
|
||||
_ "github.com/influxdata/telegraf/plugins/parsers/all"
|
||||
_ "github.com/influxdata/telegraf/plugins/processors/all"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
type TelegrafConfig interface {
|
||||
CollectDeprecationInfos([]string, []string, []string, []string) map[string][]config.PluginDeprecationInfo
|
||||
PrintDeprecationList([]config.PluginDeprecationInfo)
|
||||
}
|
||||
|
||||
type Filters struct {
|
||||
section []string
|
||||
input []string
|
||||
output []string
|
||||
aggregator []string
|
||||
processor []string
|
||||
}
|
||||
|
||||
func processFilterFlags(section, input, output, aggregator, processor string) Filters {
|
||||
sectionFilters := deleteEmpty(strings.Split(section, ":"))
|
||||
inputFilters := deleteEmpty(strings.Split(input, ":"))
|
||||
outputFilters := deleteEmpty(strings.Split(output, ":"))
|
||||
aggregatorFilters := deleteEmpty(strings.Split(aggregator, ":"))
|
||||
processorFilters := deleteEmpty(strings.Split(processor, ":"))
|
||||
return Filters{sectionFilters, inputFilters, outputFilters, aggregatorFilters, processorFilters}
|
||||
}
|
||||
|
||||
func deleteEmpty(s []string) []string {
|
||||
var r []string
|
||||
for _, str := range s {
|
||||
if str != "" {
|
||||
r = append(r, str)
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// runApp defines all the subcommands and flags for Telegraf
|
||||
// this abstraction is used for testing, so outputBuffer and args can be changed
|
||||
func runApp(args []string, outputBuffer io.Writer, pprof Server, c TelegrafConfig, m App) error {
|
||||
pluginFilterFlags := []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "section-filter",
|
||||
Usage: "filter the sections to print, separator is ':'. Valid values are 'agent', 'global_tags', 'outputs', 'processors', 'aggregators' and 'inputs'",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "input-filter",
|
||||
Usage: "filter the inputs to enable, separator is ':'",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "output-filter",
|
||||
Usage: "filter the outputs to enable, separator is ':'",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "aggregator-filter",
|
||||
Usage: "filter the aggregators to enable, separator is ':'",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "processor-filter",
|
||||
Usage: "filter the processors to enable, separator is ':'",
|
||||
},
|
||||
}
|
||||
|
||||
extraFlags := append(pluginFilterFlags, cliFlags()...)
|
||||
|
||||
// This function is used when Telegraf is run with only flags
|
||||
action := func(cCtx *cli.Context) error {
|
||||
logger.SetupLogging(logger.LogConfig{})
|
||||
|
||||
// Deprecated: Use execd instead
|
||||
// Load external plugins, if requested.
|
||||
if cCtx.String("plugin-directory") != "" {
|
||||
log.Printf("I! Loading external plugins from: %s", cCtx.String("plugin-directory"))
|
||||
if err := goplugin.LoadExternalPlugins(cCtx.String("plugin-directory")); err != nil {
|
||||
return fmt.Errorf("E! %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// switch for flags which just do something and exit immediately
|
||||
switch {
|
||||
// print available input plugins
|
||||
case cCtx.Bool("deprecation-list"):
|
||||
filters := processFilterFlags(
|
||||
cCtx.String("section-filter"),
|
||||
cCtx.String("input-filter"),
|
||||
cCtx.String("output-filter"),
|
||||
cCtx.String("aggregator-filter"),
|
||||
cCtx.String("processor-filter"),
|
||||
)
|
||||
infos := c.CollectDeprecationInfos(
|
||||
filters.input, filters.output, filters.aggregator, filters.processor,
|
||||
)
|
||||
outputBuffer.Write([]byte("Deprecated Input Plugins:\n"))
|
||||
c.PrintDeprecationList(infos["inputs"])
|
||||
outputBuffer.Write([]byte("Deprecated Output Plugins:\n"))
|
||||
c.PrintDeprecationList(infos["outputs"])
|
||||
outputBuffer.Write([]byte("Deprecated Processor Plugins:\n"))
|
||||
c.PrintDeprecationList(infos["processors"])
|
||||
outputBuffer.Write([]byte("Deprecated Aggregator Plugins:\n"))
|
||||
c.PrintDeprecationList(infos["aggregators"])
|
||||
return nil
|
||||
// print available output plugins
|
||||
case cCtx.Bool("output-list"):
|
||||
outputBuffer.Write([]byte("Available Output Plugins:\n"))
|
||||
names := make([]string, 0, len(outputs.Outputs))
|
||||
for k := range outputs.Outputs {
|
||||
names = append(names, k)
|
||||
}
|
||||
sort.Strings(names)
|
||||
for _, k := range names {
|
||||
outputBuffer.Write([]byte(fmt.Sprintf(" %s\n", k)))
|
||||
}
|
||||
return nil
|
||||
// print available input plugins
|
||||
case cCtx.Bool("input-list"):
|
||||
outputBuffer.Write([]byte("Available Input Plugins:\n"))
|
||||
names := make([]string, 0, len(inputs.Inputs))
|
||||
for k := range inputs.Inputs {
|
||||
names = append(names, k)
|
||||
}
|
||||
sort.Strings(names)
|
||||
for _, k := range names {
|
||||
outputBuffer.Write([]byte(fmt.Sprintf(" %s\n", k)))
|
||||
}
|
||||
return nil
|
||||
// print usage for a plugin, ie, 'telegraf --usage mysql'
|
||||
case cCtx.String("usage") != "":
|
||||
err := PrintInputConfig(cCtx.String("usage"), outputBuffer)
|
||||
err2 := PrintOutputConfig(cCtx.String("usage"), outputBuffer)
|
||||
if err != nil && err2 != nil {
|
||||
return fmt.Errorf("E! %s and %s", err, err2)
|
||||
}
|
||||
return nil
|
||||
// DEPRECATED
|
||||
case cCtx.Bool("version"):
|
||||
outputBuffer.Write([]byte(fmt.Sprintf("%s\n", internal.FormatFullVersion())))
|
||||
return nil
|
||||
// DEPRECATED
|
||||
case cCtx.Bool("sample-config"):
|
||||
filters := processFilterFlags(
|
||||
cCtx.String("section-filter"),
|
||||
cCtx.String("input-filter"),
|
||||
cCtx.String("output-filter"),
|
||||
cCtx.String("aggregator-filter"),
|
||||
cCtx.String("processor-filter"),
|
||||
)
|
||||
|
||||
printSampleConfig(
|
||||
outputBuffer,
|
||||
filters.section,
|
||||
filters.input,
|
||||
filters.output,
|
||||
filters.aggregator,
|
||||
filters.processor,
|
||||
)
|
||||
return nil
|
||||
}
|
||||
|
||||
if cCtx.String("pprof-addr") != "" {
|
||||
pprof.Start(cCtx.String("pprof-addr"))
|
||||
}
|
||||
|
||||
filters := processFilterFlags(
|
||||
cCtx.String("section-filter"),
|
||||
cCtx.String("input-filter"),
|
||||
cCtx.String("output-filter"),
|
||||
cCtx.String("aggregator-filter"),
|
||||
cCtx.String("processor-filter"),
|
||||
)
|
||||
|
||||
g := GlobalFlags{
|
||||
config: cCtx.StringSlice("config"),
|
||||
configDir: cCtx.StringSlice("config-directory"),
|
||||
testWait: cCtx.Int("test-wait"),
|
||||
watchConfig: cCtx.String("watch-config"),
|
||||
pidFile: cCtx.String("pidfile"),
|
||||
plugindDir: cCtx.String("plugin-directory"),
|
||||
test: cCtx.Bool("test"),
|
||||
debug: cCtx.Bool("debug"),
|
||||
once: cCtx.Bool("once"),
|
||||
quiet: cCtx.Bool("quiet"),
|
||||
}
|
||||
|
||||
w := WindowFlags{
|
||||
service: cCtx.String("service"),
|
||||
serviceName: cCtx.String("service-name"),
|
||||
serviceDisplayName: cCtx.String("service-display-name"),
|
||||
serviceRestartDelay: cCtx.String("service-restart-delay"),
|
||||
serviceAutoRestart: cCtx.Bool("service-auto-restart"),
|
||||
console: cCtx.Bool("console"),
|
||||
}
|
||||
|
||||
m.Init(pprof.ErrChan(), filters, g, w)
|
||||
return m.Run()
|
||||
}
|
||||
|
||||
app := &cli.App{
|
||||
Name: "Telegraf",
|
||||
Usage: "The plugin-driven server agent for collecting & reporting metrics.",
|
||||
Writer: outputBuffer,
|
||||
Flags: append(
|
||||
[]cli.Flag{
|
||||
// String slice flags
|
||||
&cli.StringSliceFlag{
|
||||
Name: "config",
|
||||
Usage: "configuration file to load",
|
||||
},
|
||||
&cli.StringSliceFlag{
|
||||
Name: "config-directory",
|
||||
Usage: "directory containing additional *.conf files",
|
||||
},
|
||||
// Int flags
|
||||
&cli.IntFlag{
|
||||
Name: "test-wait",
|
||||
Usage: "wait up to this many seconds for service inputs to complete in test mode",
|
||||
},
|
||||
//
|
||||
// String flags
|
||||
&cli.StringFlag{
|
||||
Name: "usage",
|
||||
Usage: "print usage for a plugin, ie, 'telegraf --usage mysql'",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "pprof-addr",
|
||||
Usage: "pprof host/IP and port to listen on (e.g. 'localhost:6060')",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "watch-config",
|
||||
Usage: "monitoring config changes [notify, poll]",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "pidfile",
|
||||
Usage: "file to write our pid to",
|
||||
},
|
||||
//
|
||||
// Bool flags
|
||||
&cli.BoolFlag{
|
||||
Name: "once",
|
||||
Usage: "run one gather and exit",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "debug",
|
||||
Usage: "turn on debug logging",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "quiet",
|
||||
Usage: "run in quiet mode",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "test",
|
||||
Usage: "enable test mode: gather metrics, print them out, and exit. Note: Test mode only runs inputs, not processors, aggregators, or outputs",
|
||||
},
|
||||
// TODO: Change "deprecation-list, input-list, output-list" flags to become a subcommand "list" that takes
|
||||
// "input,output,aggregator,processor, deprecated" as parameters
|
||||
&cli.BoolFlag{
|
||||
Name: "deprecation-list",
|
||||
Usage: "print all deprecated plugins or plugin options",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "input-list",
|
||||
Usage: "print available input plugins",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "output-list",
|
||||
Usage: "print available output plugins",
|
||||
},
|
||||
//
|
||||
// !!! The following flags are DEPRECATED !!!
|
||||
// Already covered with the subcommand `./telegraf version`
|
||||
&cli.BoolFlag{
|
||||
Name: "version",
|
||||
Usage: "DEPRECATED: display the version and exit",
|
||||
},
|
||||
// Already covered with the subcommand `./telegraf config`
|
||||
&cli.BoolFlag{
|
||||
Name: "sample-config",
|
||||
Usage: "DEPRECATED: print out full sample configuration",
|
||||
},
|
||||
// Using execd plugin to add external plugins is preffered (less size impact, easier for end user)
|
||||
&cli.StringFlag{
|
||||
Name: "plugin-directory",
|
||||
Usage: "DEPRECATED: path to directory containing external plugins",
|
||||
},
|
||||
// !!!
|
||||
}, extraFlags...),
|
||||
Action: action,
|
||||
Commands: []*cli.Command{
|
||||
{
|
||||
Name: "config",
|
||||
Usage: "print out full sample configuration to stdout",
|
||||
Flags: pluginFilterFlags,
|
||||
Action: func(cCtx *cli.Context) error {
|
||||
// The sub_Filters are populated when the filter flags are set after the subcommand config
|
||||
// e.g. telegraf config --section-filter inputs
|
||||
filters := processFilterFlags(
|
||||
cCtx.String("section-filter"),
|
||||
cCtx.String("input-filter"),
|
||||
cCtx.String("output-filter"),
|
||||
cCtx.String("aggregator-filter"),
|
||||
cCtx.String("processor-filter"),
|
||||
)
|
||||
|
||||
printSampleConfig(
|
||||
outputBuffer,
|
||||
filters.section,
|
||||
filters.input,
|
||||
filters.output,
|
||||
filters.aggregator,
|
||||
filters.processor,
|
||||
)
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "version",
|
||||
Usage: "print current version to stdout",
|
||||
Action: func(cCtx *cli.Context) error {
|
||||
outputBuffer.Write([]byte(fmt.Sprintf("%s\n", internal.FormatFullVersion())))
|
||||
return nil
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return app.Run(args)
|
||||
}
|
||||
|
||||
func main() {
|
||||
agent := Telegraf{}
|
||||
pprof := NewPprofServer()
|
||||
c := config.NewConfig()
|
||||
err := runApp(os.Args, os.Stdout, pprof, c, &agent)
|
||||
if err != nil {
|
||||
log.Fatalf("E! %s", err)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,463 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/config"
|
||||
"github.com/influxdata/telegraf/internal"
|
||||
"github.com/influxdata/telegraf/plugins/inputs"
|
||||
"github.com/influxdata/telegraf/plugins/outputs"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
type MockTelegraf struct {
|
||||
GlobalFlags
|
||||
WindowFlags
|
||||
}
|
||||
|
||||
func NewMockTelegraf() *MockTelegraf {
|
||||
return &MockTelegraf{}
|
||||
}
|
||||
|
||||
func (m *MockTelegraf) Init(serverErr <-chan error, f Filters, g GlobalFlags, w WindowFlags) {
|
||||
m.GlobalFlags = g
|
||||
m.WindowFlags = w
|
||||
}
|
||||
|
||||
func (m *MockTelegraf) Run() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type MockConfig struct {
|
||||
Buffer io.Writer
|
||||
ExpectedDeprecatedPlugins map[string][]config.PluginDeprecationInfo
|
||||
}
|
||||
|
||||
func NewMockConfig(buffer io.Writer) *MockConfig {
|
||||
return &MockConfig{
|
||||
Buffer: buffer,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *MockConfig) CollectDeprecationInfos(inFilter, outFilter, aggFilter, procFilter []string) map[string][]config.PluginDeprecationInfo {
|
||||
return m.ExpectedDeprecatedPlugins
|
||||
}
|
||||
|
||||
func (m *MockConfig) PrintDeprecationList(plugins []config.PluginDeprecationInfo) {
|
||||
for _, p := range plugins {
|
||||
_, _ = m.Buffer.Write([]byte(fmt.Sprintf("plugin name: %s\n", p.Name)))
|
||||
}
|
||||
}
|
||||
|
||||
type MockServer struct {
|
||||
Address string
|
||||
}
|
||||
|
||||
func NewMockServer() *MockServer {
|
||||
return &MockServer{}
|
||||
}
|
||||
|
||||
func (m *MockServer) Start(address string) {
|
||||
m.Address = "localhost:6060"
|
||||
}
|
||||
|
||||
func (m *MockServer) ErrChan() <-chan error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestUsageFlag(t *testing.T) {
|
||||
tests := []struct {
|
||||
PluginName string
|
||||
ExpectedError string
|
||||
ExpectedOutput string
|
||||
}{
|
||||
{
|
||||
PluginName: "example",
|
||||
ExpectedError: "E! input example not found and output example not found",
|
||||
},
|
||||
{
|
||||
PluginName: "temp",
|
||||
ExpectedOutput: `
|
||||
# Read metrics about temperature
|
||||
[[inputs.temp]]
|
||||
# no configuration
|
||||
|
||||
`,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
buf := new(bytes.Buffer)
|
||||
args := os.Args[0:1]
|
||||
args = append(args, "--usage", test.PluginName)
|
||||
err := runApp(args, buf, NewMockServer(), NewMockConfig(buf), NewMockTelegraf())
|
||||
if test.ExpectedError != "" {
|
||||
require.ErrorContains(t, err, test.ExpectedError)
|
||||
continue
|
||||
}
|
||||
require.NoError(t, err)
|
||||
// To run this test on windows and linux, remove windows carriage return
|
||||
o := strings.Replace(buf.String(), "\r", "", -1)
|
||||
require.Equal(t, test.ExpectedOutput, o)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInputListFlag(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
args := os.Args[0:1]
|
||||
args = append(args, "--input-list")
|
||||
temp := inputs.Inputs
|
||||
inputs.Inputs = map[string]inputs.Creator{
|
||||
"test": func() telegraf.Input { return nil },
|
||||
}
|
||||
err := runApp(args, buf, NewMockServer(), NewMockConfig(buf), NewMockTelegraf())
|
||||
require.NoError(t, err)
|
||||
expectedOutput := `Available Input Plugins:
|
||||
test
|
||||
`
|
||||
require.Equal(t, expectedOutput, buf.String())
|
||||
inputs.Inputs = temp
|
||||
}
|
||||
|
||||
func TestOutputListFlag(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
args := os.Args[0:1]
|
||||
args = append(args, "--output-list")
|
||||
temp := outputs.Outputs
|
||||
outputs.Outputs = map[string]outputs.Creator{
|
||||
"test": func() telegraf.Output { return nil },
|
||||
}
|
||||
err := runApp(args, buf, NewMockServer(), NewMockConfig(buf), NewMockTelegraf())
|
||||
require.NoError(t, err)
|
||||
expectedOutput := `Available Output Plugins:
|
||||
test
|
||||
`
|
||||
require.Equal(t, expectedOutput, buf.String())
|
||||
outputs.Outputs = temp
|
||||
}
|
||||
|
||||
func TestDeprecationListFlag(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
args := os.Args[0:1]
|
||||
args = append(args, "--deprecation-list")
|
||||
mS := NewMockServer()
|
||||
mC := NewMockConfig(buf)
|
||||
mC.ExpectedDeprecatedPlugins = make(map[string][]config.PluginDeprecationInfo)
|
||||
mC.ExpectedDeprecatedPlugins["inputs"] = []config.PluginDeprecationInfo{
|
||||
{
|
||||
DeprecationInfo: config.DeprecationInfo{
|
||||
Name: "test",
|
||||
},
|
||||
},
|
||||
}
|
||||
err := runApp(args, buf, mS, mC, NewMockTelegraf())
|
||||
require.NoError(t, err)
|
||||
expectedOutput := `Deprecated Input Plugins:
|
||||
plugin name: test
|
||||
Deprecated Output Plugins:
|
||||
Deprecated Processor Plugins:
|
||||
Deprecated Aggregator Plugins:
|
||||
`
|
||||
|
||||
require.Equal(t, expectedOutput, buf.String())
|
||||
}
|
||||
|
||||
func TestPprofAddressFlag(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
args := os.Args[0:1]
|
||||
address := "localhost:6060"
|
||||
args = append(args, "--pprof-addr", address)
|
||||
m := NewMockServer()
|
||||
err := runApp(args, buf, m, NewMockConfig(buf), NewMockTelegraf())
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, address, m.Address)
|
||||
}
|
||||
|
||||
// !!! DEPRECATED !!!
|
||||
// TestPluginDirectoryFlag tests `--plugin-directory`
|
||||
func TestPluginDirectoryFlag(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
args := os.Args[0:1]
|
||||
args = append(args, "--plugin-directory", ".")
|
||||
err := runApp(args, buf, NewMockServer(), NewMockConfig(buf), NewMockTelegraf())
|
||||
require.ErrorContains(t, err, "E! go plugin support is not enabled")
|
||||
}
|
||||
|
||||
func TestCommandConfig(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
commands []string
|
||||
expectedHeaders []string
|
||||
removedHeaders []string
|
||||
expectedPlugins []string
|
||||
removedPlugins []string
|
||||
}{
|
||||
// Deprecated flag replaced with command "config"
|
||||
{
|
||||
name: "no filters",
|
||||
commands: []string{"--sample-config"},
|
||||
expectedHeaders: []string{
|
||||
outputHeader,
|
||||
inputHeader,
|
||||
aggregatorHeader,
|
||||
processorHeader,
|
||||
serviceInputHeader,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "no filters",
|
||||
commands: []string{"config"},
|
||||
expectedHeaders: []string{
|
||||
outputHeader,
|
||||
inputHeader,
|
||||
aggregatorHeader,
|
||||
processorHeader,
|
||||
serviceInputHeader,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "filter sections for inputs",
|
||||
commands: []string{"config", "--section-filter", "inputs"},
|
||||
expectedHeaders: []string{
|
||||
inputHeader,
|
||||
},
|
||||
removedHeaders: []string{
|
||||
outputHeader,
|
||||
aggregatorHeader,
|
||||
processorHeader,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "filter sections for inputs,outputs",
|
||||
commands: []string{"config", "--section-filter", "inputs:outputs"},
|
||||
expectedHeaders: []string{
|
||||
inputHeader,
|
||||
outputHeader,
|
||||
},
|
||||
removedHeaders: []string{
|
||||
aggregatorHeader,
|
||||
processorHeader,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "filter input plugins",
|
||||
commands: []string{"config", "--input-filter", "cpu:file"},
|
||||
expectedPlugins: []string{
|
||||
"[[inputs.cpu]]",
|
||||
"[[inputs.file]]",
|
||||
},
|
||||
removedPlugins: []string{
|
||||
"[[inputs.disk]]",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "filter output plugins",
|
||||
commands: []string{"config", "--output-filter", "influxdb:http"},
|
||||
expectedPlugins: []string{
|
||||
"[[outputs.influxdb]]",
|
||||
"[[outputs.http]]",
|
||||
},
|
||||
removedPlugins: []string{
|
||||
"[[outputs.file]]",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "filter processor plugins",
|
||||
commands: []string{"config", "--processor-filter", "date:enum"},
|
||||
expectedPlugins: []string{
|
||||
"[[processors.date]]",
|
||||
"[[processors.enum]]",
|
||||
},
|
||||
removedPlugins: []string{
|
||||
"[[processors.parser]]",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "filter aggregator plugins",
|
||||
commands: []string{"config", "--aggregator-filter", "basicstats:starlark"},
|
||||
expectedPlugins: []string{
|
||||
"[[aggregators.basicstats]]",
|
||||
"[[aggregators.starlark]]",
|
||||
},
|
||||
removedPlugins: []string{
|
||||
"[[aggregators.minmax]]",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
args := os.Args[0:1]
|
||||
args = append(args, test.commands...)
|
||||
err := runApp(args, buf, NewMockServer(), NewMockConfig(buf), NewMockTelegraf())
|
||||
require.NoError(t, err)
|
||||
output := buf.String()
|
||||
for _, e := range test.expectedHeaders {
|
||||
require.Contains(t, output, e, "expected header not found")
|
||||
}
|
||||
for _, r := range test.removedHeaders {
|
||||
require.NotContains(t, output, r, "removed header found")
|
||||
}
|
||||
for _, e := range test.expectedPlugins {
|
||||
require.Contains(t, output, e, "expected plugin not found")
|
||||
}
|
||||
for _, r := range test.removedPlugins {
|
||||
require.NotContains(t, output, r, "removed plugin found")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommandVersion(t *testing.T) {
|
||||
tests := []struct {
|
||||
Version string
|
||||
Branch string
|
||||
Commit string
|
||||
ExpectedOutput string
|
||||
}{
|
||||
{
|
||||
Version: "v2.0.0",
|
||||
ExpectedOutput: "Telegraf v2.0.0\n",
|
||||
},
|
||||
{
|
||||
ExpectedOutput: "Telegraf unknown\n",
|
||||
},
|
||||
{
|
||||
Version: "v2.0.0",
|
||||
Branch: "master",
|
||||
ExpectedOutput: "Telegraf v2.0.0 (git: master@unknown)\n",
|
||||
},
|
||||
{
|
||||
Version: "v2.0.0",
|
||||
Branch: "master",
|
||||
Commit: "123",
|
||||
ExpectedOutput: "Telegraf v2.0.0 (git: master@123)\n",
|
||||
},
|
||||
{
|
||||
Version: "v2.0.0",
|
||||
Commit: "123",
|
||||
ExpectedOutput: "Telegraf v2.0.0 (git: unknown@123)\n",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
buf := new(bytes.Buffer)
|
||||
args := os.Args[0:1]
|
||||
args = append(args, "version")
|
||||
internal.Version = test.Version
|
||||
internal.Branch = test.Branch
|
||||
internal.Commit = test.Commit
|
||||
err := runApp(args, buf, NewMockServer(), NewMockConfig(buf), NewMockTelegraf())
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, test.ExpectedOutput, buf.String())
|
||||
}
|
||||
}
|
||||
|
||||
// Deprecated in favor of command version
|
||||
func TestFlagVersion(t *testing.T) {
|
||||
tests := []struct {
|
||||
Version string
|
||||
Branch string
|
||||
Commit string
|
||||
ExpectedOutput string
|
||||
}{
|
||||
{
|
||||
Version: "v2.0.0",
|
||||
ExpectedOutput: "Telegraf v2.0.0\n",
|
||||
},
|
||||
{
|
||||
ExpectedOutput: "Telegraf unknown\n",
|
||||
},
|
||||
{
|
||||
Version: "v2.0.0",
|
||||
Branch: "master",
|
||||
ExpectedOutput: "Telegraf v2.0.0 (git: master@unknown)\n",
|
||||
},
|
||||
{
|
||||
Version: "v2.0.0",
|
||||
Branch: "master",
|
||||
Commit: "123",
|
||||
ExpectedOutput: "Telegraf v2.0.0 (git: master@123)\n",
|
||||
},
|
||||
{
|
||||
Version: "v2.0.0",
|
||||
Commit: "123",
|
||||
ExpectedOutput: "Telegraf v2.0.0 (git: unknown@123)\n",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
buf := new(bytes.Buffer)
|
||||
args := os.Args[0:1]
|
||||
args = append(args, "--version")
|
||||
internal.Version = test.Version
|
||||
internal.Branch = test.Branch
|
||||
internal.Commit = test.Commit
|
||||
err := runApp(args, buf, NewMockServer(), NewMockConfig(buf), NewMockTelegraf())
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, test.ExpectedOutput, buf.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestGlobablBoolFlags(t *testing.T) {
|
||||
commands := []string{
|
||||
"--debug",
|
||||
"--test",
|
||||
"--quiet",
|
||||
"--once",
|
||||
}
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
args := os.Args[0:1]
|
||||
args = append(args, commands...)
|
||||
m := NewMockTelegraf()
|
||||
err := runApp(args, buf, NewMockServer(), NewMockConfig(buf), m)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, true, m.debug)
|
||||
require.Equal(t, true, m.test)
|
||||
require.Equal(t, true, m.once)
|
||||
require.Equal(t, true, m.quiet)
|
||||
}
|
||||
|
||||
func TestFlagsAreSet(t *testing.T) {
|
||||
expectedInt := 1
|
||||
expectedString := "test"
|
||||
|
||||
commands := []string{
|
||||
"--config", expectedString,
|
||||
"--config-directory", expectedString,
|
||||
"--debug",
|
||||
"--test",
|
||||
"--quiet",
|
||||
"--once",
|
||||
"--test-wait", strconv.Itoa(expectedInt),
|
||||
"--watch-config", expectedString,
|
||||
"--pidfile", expectedString,
|
||||
}
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
args := os.Args[0:1]
|
||||
args = append(args, commands...)
|
||||
m := NewMockTelegraf()
|
||||
err := runApp(args, buf, NewMockServer(), NewMockConfig(buf), m)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, []string{expectedString}, m.config)
|
||||
require.Equal(t, []string{expectedString}, m.configDir)
|
||||
require.Equal(t, true, m.debug)
|
||||
require.Equal(t, true, m.test)
|
||||
require.Equal(t, true, m.once)
|
||||
require.Equal(t, true, m.quiet)
|
||||
require.Equal(t, expectedInt, m.testWait)
|
||||
require.Equal(t, expectedString, m.watchConfig)
|
||||
require.Equal(t, expectedString, m.pidFile)
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestWindowsFlagsAreSet(t *testing.T) {
|
||||
expectedString := "test"
|
||||
|
||||
commands := []string{
|
||||
"--service", expectedString,
|
||||
"--service-name", expectedString,
|
||||
"--service-display-name", expectedString,
|
||||
"--service-restart-delay", expectedString,
|
||||
"--service-auto-restart",
|
||||
"--console",
|
||||
}
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
args := os.Args[0:1]
|
||||
args = append(args, commands...)
|
||||
m := NewMockTelegraf()
|
||||
err := runApp(args, buf, NewMockServer(), NewMockConfig(buf), m)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, expectedString, m.service)
|
||||
require.Equal(t, expectedString, m.serviceName)
|
||||
require.Equal(t, expectedString, m.serviceDisplayName)
|
||||
require.Equal(t, expectedString, m.serviceRestartDelay)
|
||||
require.Equal(t, true, m.serviceAutoRestart)
|
||||
require.Equal(t, true, m.console)
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log" //nolint: revive
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Server interface {
|
||||
Start(string)
|
||||
ErrChan() <-chan error
|
||||
}
|
||||
|
||||
type PprofServer struct {
|
||||
err chan error
|
||||
}
|
||||
|
||||
func NewPprofServer() *PprofServer {
|
||||
return &PprofServer{
|
||||
err: make(chan error),
|
||||
}
|
||||
}
|
||||
|
||||
func (p *PprofServer) Start(address string) {
|
||||
go func() {
|
||||
pprofHostPort := address
|
||||
parts := strings.Split(pprofHostPort, ":")
|
||||
if len(parts) == 2 && parts[0] == "" {
|
||||
pprofHostPort = fmt.Sprintf("localhost:%s", parts[1])
|
||||
}
|
||||
pprofHostPort = "http://" + pprofHostPort + "/debug/pprof"
|
||||
|
||||
log.Printf("I! Starting pprof HTTP server at: %s", pprofHostPort)
|
||||
|
||||
if err := http.ListenAndServe(address, nil); err != nil {
|
||||
p.err <- fmt.Errorf("E! %w", err)
|
||||
}
|
||||
close(p.err)
|
||||
}()
|
||||
}
|
||||
|
||||
func (p *PprofServer) ErrChan() <-chan error {
|
||||
return p.err
|
||||
}
|
||||
|
|
@ -1,8 +1,9 @@
|
|||
package printer
|
||||
package main
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"io"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
|
|
@ -100,8 +101,9 @@ func sliceContains(name string, list []string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// PrintSampleConfig prints the sample config
|
||||
func PrintSampleConfig(
|
||||
// printSampleConfig prints the sample config
|
||||
func printSampleConfig(
|
||||
outputBuffer io.Writer,
|
||||
sectionFilters []string,
|
||||
inputFilters []string,
|
||||
outputFilters []string,
|
||||
|
|
@ -109,23 +111,23 @@ func PrintSampleConfig(
|
|||
processorFilters []string,
|
||||
) {
|
||||
// print headers
|
||||
fmt.Print(header)
|
||||
outputBuffer.Write([]byte(header))
|
||||
|
||||
if len(sectionFilters) == 0 {
|
||||
sectionFilters = sectionDefaults
|
||||
}
|
||||
printFilteredGlobalSections(sectionFilters)
|
||||
printFilteredGlobalSections(sectionFilters, outputBuffer)
|
||||
|
||||
// print output plugins
|
||||
if sliceContains("outputs", sectionFilters) {
|
||||
if len(outputFilters) != 0 {
|
||||
if len(outputFilters) >= 3 && outputFilters[1] != "none" {
|
||||
fmt.Print(outputHeader)
|
||||
outputBuffer.Write([]byte(outputHeader))
|
||||
}
|
||||
printFilteredOutputs(outputFilters, false)
|
||||
printFilteredOutputs(outputFilters, false, outputBuffer)
|
||||
} else {
|
||||
fmt.Print(outputHeader)
|
||||
printFilteredOutputs(outputDefaults, false)
|
||||
outputBuffer.Write([]byte(outputHeader))
|
||||
printFilteredOutputs(outputDefaults, false, outputBuffer)
|
||||
// Print non-default outputs, commented
|
||||
var pnames []string
|
||||
for pname := range outputs.Outputs {
|
||||
|
|
@ -134,7 +136,7 @@ func PrintSampleConfig(
|
|||
}
|
||||
}
|
||||
sort.Strings(pnames)
|
||||
printFilteredOutputs(pnames, true)
|
||||
printFilteredOutputs(pnames, true, outputBuffer)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -142,17 +144,17 @@ func PrintSampleConfig(
|
|||
if sliceContains("processors", sectionFilters) {
|
||||
if len(processorFilters) != 0 {
|
||||
if len(processorFilters) >= 3 && processorFilters[1] != "none" {
|
||||
fmt.Print(processorHeader)
|
||||
outputBuffer.Write([]byte(processorHeader))
|
||||
}
|
||||
printFilteredProcessors(processorFilters, false)
|
||||
printFilteredProcessors(processorFilters, false, outputBuffer)
|
||||
} else {
|
||||
fmt.Print(processorHeader)
|
||||
outputBuffer.Write([]byte(processorHeader))
|
||||
pnames := []string{}
|
||||
for pname := range processors.Processors {
|
||||
pnames = append(pnames, pname)
|
||||
}
|
||||
sort.Strings(pnames)
|
||||
printFilteredProcessors(pnames, true)
|
||||
printFilteredProcessors(pnames, true, outputBuffer)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -160,17 +162,17 @@ func PrintSampleConfig(
|
|||
if sliceContains("aggregators", sectionFilters) {
|
||||
if len(aggregatorFilters) != 0 {
|
||||
if len(aggregatorFilters) >= 3 && aggregatorFilters[1] != "none" {
|
||||
fmt.Print(aggregatorHeader)
|
||||
outputBuffer.Write([]byte(aggregatorHeader))
|
||||
}
|
||||
printFilteredAggregators(aggregatorFilters, false)
|
||||
printFilteredAggregators(aggregatorFilters, false, outputBuffer)
|
||||
} else {
|
||||
fmt.Print(aggregatorHeader)
|
||||
outputBuffer.Write([]byte(aggregatorHeader))
|
||||
pnames := []string{}
|
||||
for pname := range aggregators.Aggregators {
|
||||
pnames = append(pnames, pname)
|
||||
}
|
||||
sort.Strings(pnames)
|
||||
printFilteredAggregators(pnames, true)
|
||||
printFilteredAggregators(pnames, true, outputBuffer)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -178,12 +180,12 @@ func PrintSampleConfig(
|
|||
if sliceContains("inputs", sectionFilters) {
|
||||
if len(inputFilters) != 0 {
|
||||
if len(inputFilters) >= 3 && inputFilters[1] != "none" {
|
||||
fmt.Print(inputHeader)
|
||||
outputBuffer.Write([]byte(inputHeader))
|
||||
}
|
||||
printFilteredInputs(inputFilters, false)
|
||||
printFilteredInputs(inputFilters, false, outputBuffer)
|
||||
} else {
|
||||
fmt.Print(inputHeader)
|
||||
printFilteredInputs(inputDefaults, false)
|
||||
outputBuffer.Write([]byte(inputHeader))
|
||||
printFilteredInputs(inputDefaults, false, outputBuffer)
|
||||
// Print non-default inputs, commented
|
||||
var pnames []string
|
||||
for pname := range inputs.Inputs {
|
||||
|
|
@ -192,7 +194,7 @@ func PrintSampleConfig(
|
|||
}
|
||||
}
|
||||
sort.Strings(pnames)
|
||||
printFilteredInputs(pnames, true)
|
||||
printFilteredInputs(pnames, true, outputBuffer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -217,7 +219,7 @@ func PluginNameCounts(plugins []string) []string {
|
|||
return namecount
|
||||
}
|
||||
|
||||
func printFilteredProcessors(processorFilters []string, commented bool) {
|
||||
func printFilteredProcessors(processorFilters []string, commented bool, outputBuffer io.Writer) {
|
||||
// Filter processors
|
||||
var pnames []string
|
||||
for pname := range processors.Processors {
|
||||
|
|
@ -231,11 +233,11 @@ func printFilteredProcessors(processorFilters []string, commented bool) {
|
|||
for _, pname := range pnames {
|
||||
creator := processors.Processors[pname]
|
||||
output := creator()
|
||||
printConfig(pname, output, "processors", commented, processors.Deprecations[pname])
|
||||
printConfig(pname, output, "processors", commented, processors.Deprecations[pname], outputBuffer)
|
||||
}
|
||||
}
|
||||
|
||||
func printFilteredAggregators(aggregatorFilters []string, commented bool) {
|
||||
func printFilteredAggregators(aggregatorFilters []string, commented bool, outputBuffer io.Writer) {
|
||||
// Filter outputs
|
||||
var anames []string
|
||||
for aname := range aggregators.Aggregators {
|
||||
|
|
@ -249,11 +251,11 @@ func printFilteredAggregators(aggregatorFilters []string, commented bool) {
|
|||
for _, aname := range anames {
|
||||
creator := aggregators.Aggregators[aname]
|
||||
output := creator()
|
||||
printConfig(aname, output, "aggregators", commented, aggregators.Deprecations[aname])
|
||||
printConfig(aname, output, "aggregators", commented, aggregators.Deprecations[aname], outputBuffer)
|
||||
}
|
||||
}
|
||||
|
||||
func printFilteredInputs(inputFilters []string, commented bool) {
|
||||
func printFilteredInputs(inputFilters []string, commented bool, outputBuffer io.Writer) {
|
||||
// Filter inputs
|
||||
var pnames []string
|
||||
for pname := range inputs.Inputs {
|
||||
|
|
@ -284,7 +286,7 @@ func printFilteredInputs(inputFilters []string, commented bool) {
|
|||
continue
|
||||
}
|
||||
|
||||
printConfig(pname, input, "inputs", commented, inputs.Deprecations[pname])
|
||||
printConfig(pname, input, "inputs", commented, inputs.Deprecations[pname], outputBuffer)
|
||||
}
|
||||
|
||||
// Print Service Inputs
|
||||
|
|
@ -293,13 +295,13 @@ func printFilteredInputs(inputFilters []string, commented bool) {
|
|||
}
|
||||
sort.Strings(servInputNames)
|
||||
|
||||
fmt.Print(serviceInputHeader)
|
||||
outputBuffer.Write([]byte(serviceInputHeader))
|
||||
for _, name := range servInputNames {
|
||||
printConfig(name, servInputs[name], "inputs", commented, inputs.Deprecations[name])
|
||||
printConfig(name, servInputs[name], "inputs", commented, inputs.Deprecations[name], outputBuffer)
|
||||
}
|
||||
}
|
||||
|
||||
func printFilteredOutputs(outputFilters []string, commented bool) {
|
||||
func printFilteredOutputs(outputFilters []string, commented bool, outputBuffer io.Writer) {
|
||||
// Filter outputs
|
||||
var onames []string
|
||||
for oname := range outputs.Outputs {
|
||||
|
|
@ -313,21 +315,21 @@ func printFilteredOutputs(outputFilters []string, commented bool) {
|
|||
for _, oname := range onames {
|
||||
creator := outputs.Outputs[oname]
|
||||
output := creator()
|
||||
printConfig(oname, output, "outputs", commented, outputs.Deprecations[oname])
|
||||
printConfig(oname, output, "outputs", commented, outputs.Deprecations[oname], outputBuffer)
|
||||
}
|
||||
}
|
||||
|
||||
func printFilteredGlobalSections(sectionFilters []string) {
|
||||
func printFilteredGlobalSections(sectionFilters []string, outputBuffer io.Writer) {
|
||||
if sliceContains("global_tags", sectionFilters) {
|
||||
fmt.Print(globalTagsConfig)
|
||||
outputBuffer.Write([]byte(globalTagsConfig))
|
||||
}
|
||||
|
||||
if sliceContains("agent", sectionFilters) {
|
||||
fmt.Print(agentConfig)
|
||||
outputBuffer.Write([]byte(agentConfig))
|
||||
}
|
||||
}
|
||||
|
||||
func printConfig(name string, p telegraf.PluginDescriber, op string, commented bool, di telegraf.DeprecationInfo) {
|
||||
func printConfig(name string, p telegraf.PluginDescriber, op string, commented bool, di telegraf.DeprecationInfo, outputBuffer io.Writer) {
|
||||
comment := ""
|
||||
if commented {
|
||||
comment = "# "
|
||||
|
|
@ -338,44 +340,44 @@ func printConfig(name string, p telegraf.PluginDescriber, op string, commented b
|
|||
if di.RemovalIn != "" {
|
||||
removalNote = " and will be removed in " + di.RemovalIn
|
||||
}
|
||||
fmt.Printf("\n%s ## DEPRECATED: The '%s' plugin is deprecated in version %s%s, %s.", comment, name, di.Since, removalNote, di.Notice)
|
||||
outputBuffer.Write([]byte(fmt.Sprintf("\n%s ## DEPRECATED: The '%s' plugin is deprecated in version %s%s, %s.", comment, name, di.Since, removalNote, di.Notice)))
|
||||
}
|
||||
|
||||
config := p.SampleConfig()
|
||||
if config == "" {
|
||||
fmt.Printf("\n#[[%s.%s]]", op, name)
|
||||
fmt.Printf("\n%s # no configuration\n\n", comment)
|
||||
sample := p.SampleConfig()
|
||||
if sample == "" {
|
||||
outputBuffer.Write([]byte(fmt.Sprintf("\n#[[%s.%s]]", op, name)))
|
||||
outputBuffer.Write([]byte(fmt.Sprintf("\n%s # no configuration\n\n", comment)))
|
||||
} else {
|
||||
lines := strings.Split(config, "\n")
|
||||
fmt.Print("\n")
|
||||
lines := strings.Split(sample, "\n")
|
||||
outputBuffer.Write([]byte("\n"))
|
||||
for i, line := range lines {
|
||||
if i == len(lines)-1 {
|
||||
fmt.Print("\n")
|
||||
outputBuffer.Write([]byte("\n"))
|
||||
continue
|
||||
}
|
||||
fmt.Print(strings.TrimRight(comment+line, " ") + "\n")
|
||||
outputBuffer.Write([]byte(strings.TrimRight(comment+line, " ") + "\n"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PrintInputConfig prints the config usage of a single input.
|
||||
func PrintInputConfig(name string) error {
|
||||
func PrintInputConfig(name string, outputBuffer io.Writer) error {
|
||||
creator, ok := inputs.Inputs[name]
|
||||
if !ok {
|
||||
return fmt.Errorf("input %s not found", name)
|
||||
}
|
||||
|
||||
printConfig(name, creator(), "inputs", false, inputs.Deprecations[name])
|
||||
printConfig(name, creator(), "inputs", false, inputs.Deprecations[name], outputBuffer)
|
||||
return nil
|
||||
}
|
||||
|
||||
// PrintOutputConfig prints the config usage of a single output.
|
||||
func PrintOutputConfig(name string) error {
|
||||
func PrintOutputConfig(name string, outputBuffer io.Writer) error {
|
||||
creator, ok := outputs.Outputs[name]
|
||||
if !ok {
|
||||
return fmt.Errorf("output %s not found", name)
|
||||
}
|
||||
|
||||
printConfig(name, creator(), "outputs", false, outputs.Deprecations[name])
|
||||
printConfig(name, creator(), "outputs", false, outputs.Deprecations[name], outputBuffer)
|
||||
return nil
|
||||
}
|
||||
|
|
@ -3,138 +3,78 @@ package main
|
|||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
_ "net/http/pprof" // Comment this line to disable pprof endpoint.
|
||||
"log" //nolint:revive
|
||||
"os"
|
||||
"os/signal"
|
||||
"sort"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/coreos/go-systemd/daemon"
|
||||
|
||||
"github.com/fatih/color"
|
||||
|
||||
"github.com/influxdata/tail/watch"
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/agent"
|
||||
"github.com/influxdata/telegraf/config"
|
||||
"github.com/influxdata/telegraf/config/printer"
|
||||
"github.com/influxdata/telegraf/internal"
|
||||
"github.com/influxdata/telegraf/internal/goplugin"
|
||||
"github.com/influxdata/telegraf/logger"
|
||||
"github.com/influxdata/telegraf/plugins/aggregators"
|
||||
_ "github.com/influxdata/telegraf/plugins/aggregators/all"
|
||||
"github.com/influxdata/telegraf/plugins/inputs"
|
||||
_ "github.com/influxdata/telegraf/plugins/inputs/all"
|
||||
"github.com/influxdata/telegraf/plugins/outputs"
|
||||
_ "github.com/influxdata/telegraf/plugins/outputs/all"
|
||||
"github.com/influxdata/telegraf/plugins/parsers"
|
||||
_ "github.com/influxdata/telegraf/plugins/parsers/all"
|
||||
"github.com/influxdata/telegraf/plugins/processors"
|
||||
_ "github.com/influxdata/telegraf/plugins/processors/all"
|
||||
"gopkg.in/tomb.v1"
|
||||
)
|
||||
|
||||
type sliceFlags []string
|
||||
|
||||
func (i *sliceFlags) String() string {
|
||||
s := strings.Join(*i, " ")
|
||||
return "[" + s + "]"
|
||||
}
|
||||
|
||||
func (i *sliceFlags) Set(value string) error {
|
||||
*i = append(*i, value)
|
||||
return nil
|
||||
}
|
||||
|
||||
// If you update these, update usage.go and usage_windows.go
|
||||
var fDebug = flag.Bool("debug", false,
|
||||
"turn on debug logging")
|
||||
var pprofAddr = flag.String("pprof-addr", "",
|
||||
"pprof address to listen on, not activate pprof if empty")
|
||||
var fQuiet = flag.Bool("quiet", false,
|
||||
"run in quiet mode")
|
||||
var fTest = flag.Bool("test", false, "enable test mode: gather metrics, print them out, and exit. Note: Test mode only runs inputs, not processors, aggregators, or outputs")
|
||||
var fTestWait = flag.Int("test-wait", 0, "wait up to this many seconds for service inputs to complete in test mode")
|
||||
|
||||
var fConfigs sliceFlags
|
||||
var fConfigDirs sliceFlags
|
||||
var fWatchConfig = flag.String("watch-config", "", "Monitoring config changes [notify, poll]")
|
||||
var fVersion = flag.Bool("version", false, "display the version and exit")
|
||||
var fSampleConfig = flag.Bool("sample-config", false,
|
||||
"print out full sample configuration")
|
||||
var fPidfile = flag.String("pidfile", "", "file to write our pid to")
|
||||
var fDeprecationList = flag.Bool("deprecation-list", false,
|
||||
"print all deprecated plugins or plugin options.")
|
||||
var fSectionFilters = flag.String("section-filter", "",
|
||||
"filter the sections to print, separator is ':'. Valid values are 'agent', 'global_tags', 'outputs', 'processors', 'aggregators' and 'inputs'")
|
||||
var fInputFilters = flag.String("input-filter", "",
|
||||
"filter the inputs to enable, separator is :")
|
||||
var fInputList = flag.Bool("input-list", false,
|
||||
"print available input plugins.")
|
||||
var fOutputFilters = flag.String("output-filter", "",
|
||||
"filter the outputs to enable, separator is :")
|
||||
var fOutputList = flag.Bool("output-list", false,
|
||||
"print available output plugins.")
|
||||
var fAggregatorFilters = flag.String("aggregator-filter", "",
|
||||
"filter the aggregators to enable, separator is :")
|
||||
var fProcessorFilters = flag.String("processor-filter", "",
|
||||
"filter the processors to enable, separator is :")
|
||||
var fUsage = flag.String("usage", "",
|
||||
"print usage for a plugin, ie, 'telegraf --usage mysql'")
|
||||
|
||||
// Initialize the subcommand `telegraf config`
|
||||
// This duplicates the above filters which are used for `telegraf --sample-config` and `telegraf --deprecation-list`
|
||||
var configCmd = flag.NewFlagSet("config", flag.ExitOnError)
|
||||
var fSubSectionFilters = configCmd.String("section-filter", "",
|
||||
"filter the sections to print, separator is ':'. Valid values are 'agent', 'global_tags', 'outputs', 'processors', 'aggregators' and 'inputs'")
|
||||
var fSubInputFilters = configCmd.String("input-filter", "",
|
||||
"filter the inputs to enable, separator is :")
|
||||
var fSubOutputFilters = configCmd.String("output-filter", "",
|
||||
"filter the outputs to enable, separator is :")
|
||||
var fsubAggregatorFilters = configCmd.String("aggregator-filter", "",
|
||||
"filter the aggregators to enable, separator is :")
|
||||
var fSubProcessorFilters = configCmd.String("processor-filter", "",
|
||||
"filter the processors to enable, separator is :")
|
||||
|
||||
//nolint:varcheck,unused // False positive - this var is used for non-default build tag: windows
|
||||
var fService = flag.String("service", "",
|
||||
"operate on the service (windows only)")
|
||||
|
||||
//nolint:varcheck,unused // False positive - this var is used for non-default build tag: windows
|
||||
var fServiceName = flag.String("service-name", "telegraf",
|
||||
"service name (windows only)")
|
||||
|
||||
//nolint:varcheck,unused // False positive - this var is used for non-default build tag: windows
|
||||
var fServiceDisplayName = flag.String("service-display-name", "Telegraf Data Collector Service",
|
||||
"service display name (windows only)")
|
||||
|
||||
//nolint:varcheck,unused // False positive - this var is used for non-default build tag: windows
|
||||
var fServiceAutoRestart = flag.Bool("service-auto-restart", false,
|
||||
"auto restart service on failure (windows only)")
|
||||
|
||||
//nolint:varcheck,unused // False positive - this var is used for non-default build tag: windows
|
||||
var fServiceRestartDelay = flag.String("service-restart-delay", "5m",
|
||||
"delay before service auto restart, default is 5m (windows only)")
|
||||
|
||||
//nolint:varcheck,unused // False positive - this var is used for non-default build tag: windows
|
||||
var fRunAsConsole = flag.Bool("console", false,
|
||||
"run as console application (windows only)")
|
||||
var fPlugins = flag.String("plugin-directory", "",
|
||||
"path to directory containing external plugins")
|
||||
var fRunOnce = flag.Bool("once", false, "run one gather and exit")
|
||||
|
||||
var stop chan struct{}
|
||||
|
||||
func reloadLoop(
|
||||
inputFilters []string,
|
||||
outputFilters []string,
|
||||
) {
|
||||
type GlobalFlags struct {
|
||||
config []string
|
||||
configDir []string
|
||||
testWait int
|
||||
watchConfig string
|
||||
pidFile string
|
||||
plugindDir string
|
||||
test bool
|
||||
debug bool
|
||||
once bool
|
||||
quiet bool
|
||||
}
|
||||
|
||||
type WindowFlags struct {
|
||||
service string
|
||||
serviceName string
|
||||
serviceDisplayName string
|
||||
serviceRestartDelay string
|
||||
serviceAutoRestart bool
|
||||
console bool
|
||||
}
|
||||
|
||||
type App interface {
|
||||
Init(<-chan error, Filters, GlobalFlags, WindowFlags)
|
||||
Run() error
|
||||
}
|
||||
|
||||
type Telegraf struct {
|
||||
pprofErr <-chan error
|
||||
|
||||
inputFilters []string
|
||||
outputFilters []string
|
||||
|
||||
GlobalFlags
|
||||
WindowFlags
|
||||
}
|
||||
|
||||
func (a *Telegraf) Init(pprofErr <-chan error, f Filters, g GlobalFlags, w WindowFlags) {
|
||||
a.pprofErr = pprofErr
|
||||
a.inputFilters = f.input
|
||||
a.outputFilters = f.output
|
||||
a.GlobalFlags = g
|
||||
a.WindowFlags = w
|
||||
}
|
||||
|
||||
func (a *Telegraf) reloadLoop() error {
|
||||
reload := make(chan bool, 1)
|
||||
reload <- true
|
||||
for <-reload {
|
||||
|
|
@ -144,10 +84,10 @@ func reloadLoop(
|
|||
signals := make(chan os.Signal, 1)
|
||||
signal.Notify(signals, os.Interrupt, syscall.SIGHUP,
|
||||
syscall.SIGTERM, syscall.SIGINT)
|
||||
if *fWatchConfig != "" {
|
||||
for _, fConfig := range fConfigs {
|
||||
if a.watchConfig != "" {
|
||||
for _, fConfig := range a.config {
|
||||
if _, err := os.Stat(fConfig); err == nil {
|
||||
go watchLocalConfig(signals, fConfig)
|
||||
go a.watchLocalConfig(signals, fConfig)
|
||||
} else {
|
||||
log.Printf("W! Cannot watch config %s: %s", fConfig, err)
|
||||
}
|
||||
|
|
@ -162,22 +102,27 @@ func reloadLoop(
|
|||
reload <- true
|
||||
}
|
||||
cancel()
|
||||
case err := <-a.pprofErr:
|
||||
log.Printf("E! pprof server failed: %v", err)
|
||||
cancel()
|
||||
case <-stop:
|
||||
cancel()
|
||||
}
|
||||
}()
|
||||
|
||||
err := runAgent(ctx, inputFilters, outputFilters)
|
||||
err := a.runAgent(ctx)
|
||||
if err != nil && err != context.Canceled {
|
||||
log.Fatalf("E! [telegraf] Error running agent: %v", err)
|
||||
return fmt.Errorf("[telegraf] Error running agent: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func watchLocalConfig(signals chan os.Signal, fConfig string) {
|
||||
func (a *Telegraf) watchLocalConfig(signals chan os.Signal, fConfig string) {
|
||||
var mytomb tomb.Tomb
|
||||
var watcher watch.FileWatcher
|
||||
if *fWatchConfig == "poll" {
|
||||
if a.watchConfig == "poll" {
|
||||
watcher = watch.NewPollingFileWatcher(fConfig)
|
||||
} else {
|
||||
watcher = watch.NewInotifyFileWatcher(fConfig)
|
||||
|
|
@ -214,40 +159,37 @@ func watchLocalConfig(signals chan os.Signal, fConfig string) {
|
|||
signals <- syscall.SIGHUP
|
||||
}
|
||||
|
||||
func runAgent(ctx context.Context,
|
||||
inputFilters []string,
|
||||
outputFilters []string,
|
||||
) error {
|
||||
func (a *Telegraf) runAgent(ctx context.Context) error {
|
||||
// If no other options are specified, load the config file and run.
|
||||
c := config.NewConfig()
|
||||
c.OutputFilters = outputFilters
|
||||
c.InputFilters = inputFilters
|
||||
c.OutputFilters = a.outputFilters
|
||||
c.InputFilters = a.inputFilters
|
||||
var err error
|
||||
// providing no "config" flag should load default config
|
||||
if len(fConfigs) == 0 {
|
||||
if len(a.config) == 0 {
|
||||
err = c.LoadConfig("")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
for _, fConfig := range fConfigs {
|
||||
for _, fConfig := range a.config {
|
||||
err = c.LoadConfig(fConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
for _, fConfigDirectory := range fConfigDirs {
|
||||
for _, fConfigDirectory := range a.configDir {
|
||||
err = c.LoadDirectory(fConfigDirectory)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if !(*fTest || *fTestWait != 0) && len(c.Outputs) == 0 {
|
||||
if !(a.test || a.testWait != 0) && len(c.Outputs) == 0 {
|
||||
return errors.New("Error: no outputs found, did you provide a valid config file?")
|
||||
}
|
||||
if *fPlugins == "" && len(c.Inputs) == 0 {
|
||||
if a.plugindDir == "" && len(c.Inputs) == 0 {
|
||||
return errors.New("Error: no inputs found, did you provide a valid config file?")
|
||||
}
|
||||
|
||||
|
|
@ -260,10 +202,10 @@ func runAgent(ctx context.Context,
|
|||
}
|
||||
|
||||
// Setup logging as configured.
|
||||
telegraf.Debug = c.Agent.Debug || *fDebug
|
||||
telegraf.Debug = c.Agent.Debug || a.debug
|
||||
logConfig := logger.LogConfig{
|
||||
Debug: telegraf.Debug,
|
||||
Quiet: c.Agent.Quiet || *fQuiet,
|
||||
Quiet: c.Agent.Quiet || a.quiet,
|
||||
LogTarget: c.Agent.LogTarget,
|
||||
Logfile: c.Agent.Logfile,
|
||||
RotationInterval: c.Agent.LogfileRotationInterval,
|
||||
|
|
@ -274,7 +216,7 @@ func runAgent(ctx context.Context,
|
|||
|
||||
logger.SetupLogging(logConfig)
|
||||
|
||||
log.Printf("I! Starting Telegraf %s%s", internal.Version(), internal.Customized)
|
||||
log.Printf("I! Starting Telegraf %s%s", internal.Version, internal.Customized)
|
||||
log.Printf("I! Available plugins: %d inputs, %d aggregators, %d processors, %d parsers, %d outputs",
|
||||
len(inputs.Inputs),
|
||||
len(aggregators.Aggregators),
|
||||
|
|
@ -285,7 +227,7 @@ func runAgent(ctx context.Context,
|
|||
log.Printf("I! Loaded inputs: %s", strings.Join(c.InputNames(), " "))
|
||||
log.Printf("I! Loaded aggregators: %s", strings.Join(c.AggregatorNames(), " "))
|
||||
log.Printf("I! Loaded processors: %s", strings.Join(c.ProcessorNames(), " "))
|
||||
if !*fRunOnce && (*fTest || *fTestWait != 0) {
|
||||
if !a.once && (a.test || a.testWait != 0) {
|
||||
log.Print("W! " + color.RedString("Outputs are not used in testing mode!"))
|
||||
} else {
|
||||
log.Printf("I! Loaded outputs: %s", strings.Join(c.OutputNames(), " "))
|
||||
|
|
@ -316,27 +258,30 @@ func runAgent(ctx context.Context,
|
|||
// For platforms that use systemd, telegraf doesn't log if the notification failed.
|
||||
_, _ = daemon.SdNotify(false, daemon.SdNotifyReady)
|
||||
|
||||
if *fRunOnce {
|
||||
wait := time.Duration(*fTestWait) * time.Second
|
||||
if a.once {
|
||||
wait := time.Duration(a.testWait) * time.Second
|
||||
return ag.Once(ctx, wait)
|
||||
}
|
||||
|
||||
if *fTest || *fTestWait != 0 {
|
||||
wait := time.Duration(*fTestWait) * time.Second
|
||||
if a.test || a.testWait != 0 {
|
||||
wait := time.Duration(a.testWait) * time.Second
|
||||
return ag.Test(ctx, wait)
|
||||
}
|
||||
|
||||
if *fPidfile != "" {
|
||||
f, err := os.OpenFile(*fPidfile, os.O_CREATE|os.O_WRONLY, 0644)
|
||||
if a.pidFile != "" {
|
||||
f, err := os.OpenFile(a.pidFile, os.O_CREATE|os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
log.Printf("E! Unable to create pidfile: %s", err)
|
||||
} else {
|
||||
fmt.Fprintf(f, "%d\n", os.Getpid())
|
||||
_, _ = fmt.Fprintf(f, "%d\n", os.Getpid())
|
||||
|
||||
f.Close()
|
||||
err = f.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
err := os.Remove(*fPidfile)
|
||||
err := os.Remove(a.pidFile)
|
||||
if err != nil {
|
||||
log.Printf("E! Unable to remove pidfile: %s", err)
|
||||
}
|
||||
|
|
@ -346,192 +291,3 @@ func runAgent(ctx context.Context,
|
|||
|
||||
return ag.Run(ctx)
|
||||
}
|
||||
|
||||
func usageExit(rc int) {
|
||||
fmt.Println(internal.Usage)
|
||||
os.Exit(rc)
|
||||
}
|
||||
|
||||
func deleteEmpty(s []string) []string {
|
||||
var r []string
|
||||
for _, str := range s {
|
||||
if str != "" {
|
||||
r = append(r, str)
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Var(&fConfigs, "config", "configuration file to load")
|
||||
flag.Var(&fConfigDirs, "config-directory", "directory containing additional *.conf files")
|
||||
|
||||
flag.Usage = func() { usageExit(0) }
|
||||
flag.Parse()
|
||||
args := flag.Args()
|
||||
|
||||
sectionFilters, inputFilters, outputFilters := []string{}, []string{}, []string{}
|
||||
if *fSectionFilters != "" {
|
||||
sectionFilters = strings.Split(":"+strings.TrimSpace(*fSectionFilters)+":", ":")
|
||||
}
|
||||
if *fInputFilters != "" {
|
||||
inputFilters = strings.Split(":"+strings.TrimSpace(*fInputFilters)+":", ":")
|
||||
}
|
||||
if *fOutputFilters != "" {
|
||||
outputFilters = strings.Split(":"+strings.TrimSpace(*fOutputFilters)+":", ":")
|
||||
}
|
||||
|
||||
aggregatorFilters, processorFilters := []string{}, []string{}
|
||||
if *fAggregatorFilters != "" {
|
||||
aggregatorFilters = strings.Split(":"+strings.TrimSpace(*fAggregatorFilters)+":", ":")
|
||||
}
|
||||
if *fProcessorFilters != "" {
|
||||
processorFilters = strings.Split(":"+strings.TrimSpace(*fProcessorFilters)+":", ":")
|
||||
}
|
||||
|
||||
logger.SetupLogging(logger.LogConfig{})
|
||||
|
||||
// Load external plugins, if requested.
|
||||
if *fPlugins != "" {
|
||||
log.Printf("I! Loading external plugins from: %s", *fPlugins)
|
||||
if err := goplugin.LoadExternalPlugins(*fPlugins); err != nil {
|
||||
log.Fatal("E! " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
if *pprofAddr != "" {
|
||||
go func() {
|
||||
pprofHostPort := *pprofAddr
|
||||
parts := strings.Split(pprofHostPort, ":")
|
||||
if len(parts) == 2 && parts[0] == "" {
|
||||
pprofHostPort = fmt.Sprintf("localhost:%s", parts[1])
|
||||
}
|
||||
pprofHostPort = "http://" + pprofHostPort + "/debug/pprof"
|
||||
|
||||
log.Printf("I! Starting pprof HTTP server at: %s", pprofHostPort)
|
||||
|
||||
if err := http.ListenAndServe(*pprofAddr, nil); err != nil {
|
||||
log.Fatal("E! " + err.Error())
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
if len(args) > 0 {
|
||||
switch args[0] {
|
||||
case "version":
|
||||
fmt.Println(internal.FormatFullVersion())
|
||||
return
|
||||
case "config":
|
||||
err := configCmd.Parse(args[1:])
|
||||
if err != nil {
|
||||
log.Fatal("E! " + err.Error())
|
||||
}
|
||||
|
||||
// The sub_Filters are populated when the filter flags are set after the subcommand config
|
||||
// e.g. telegraf config --section-filter inputs
|
||||
subSectionFilters := deleteEmpty(strings.Split(":"+strings.TrimSpace(*fSubSectionFilters)+":", ":"))
|
||||
subInputFilters := deleteEmpty(strings.Split(":"+strings.TrimSpace(*fSubInputFilters)+":", ":"))
|
||||
subOutputFilters := deleteEmpty(strings.Split(":"+strings.TrimSpace(*fSubOutputFilters)+":", ":"))
|
||||
subAggregatorFilters := deleteEmpty(strings.Split(":"+strings.TrimSpace(*fsubAggregatorFilters)+":", ":"))
|
||||
subProcessorFilters := deleteEmpty(strings.Split(":"+strings.TrimSpace(*fSubProcessorFilters)+":", ":"))
|
||||
|
||||
// Overwrite the global filters if the subfilters are defined, this allows for backwards compatibility
|
||||
// Now you can still filter the sample config like so: telegraf --section-filter inputs config
|
||||
if len(subSectionFilters) > 0 {
|
||||
sectionFilters = subSectionFilters
|
||||
}
|
||||
if len(subInputFilters) > 0 {
|
||||
inputFilters = subInputFilters
|
||||
}
|
||||
if len(subOutputFilters) > 0 {
|
||||
outputFilters = subOutputFilters
|
||||
}
|
||||
if len(subAggregatorFilters) > 0 {
|
||||
aggregatorFilters = subAggregatorFilters
|
||||
}
|
||||
if len(subProcessorFilters) > 0 {
|
||||
processorFilters = subProcessorFilters
|
||||
}
|
||||
|
||||
printer.PrintSampleConfig(
|
||||
sectionFilters,
|
||||
inputFilters,
|
||||
outputFilters,
|
||||
aggregatorFilters,
|
||||
processorFilters,
|
||||
)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// switch for flags which just do something and exit immediately
|
||||
switch {
|
||||
case *fDeprecationList:
|
||||
c := config.NewConfig()
|
||||
infos := c.CollectDeprecationInfos(
|
||||
inputFilters,
|
||||
outputFilters,
|
||||
aggregatorFilters,
|
||||
processorFilters,
|
||||
)
|
||||
//nolint:revive // We will notice if Println fails
|
||||
fmt.Println("Deprecated Input Plugins: ")
|
||||
c.PrintDeprecationList(infos["inputs"])
|
||||
//nolint:revive // We will notice if Println fails
|
||||
fmt.Println("Deprecated Output Plugins: ")
|
||||
c.PrintDeprecationList(infos["outputs"])
|
||||
//nolint:revive // We will notice if Println fails
|
||||
fmt.Println("Deprecated Processor Plugins: ")
|
||||
c.PrintDeprecationList(infos["processors"])
|
||||
//nolint:revive // We will notice if Println fails
|
||||
fmt.Println("Deprecated Aggregator Plugins: ")
|
||||
c.PrintDeprecationList(infos["aggregators"])
|
||||
return
|
||||
case *fOutputList:
|
||||
fmt.Println("Available Output Plugins: ")
|
||||
names := make([]string, 0, len(outputs.Outputs))
|
||||
for k := range outputs.Outputs {
|
||||
names = append(names, k)
|
||||
}
|
||||
sort.Strings(names)
|
||||
for _, k := range names {
|
||||
fmt.Printf(" %s\n", k)
|
||||
}
|
||||
return
|
||||
case *fInputList:
|
||||
fmt.Println("Available Input Plugins:")
|
||||
names := make([]string, 0, len(inputs.Inputs))
|
||||
for k := range inputs.Inputs {
|
||||
names = append(names, k)
|
||||
}
|
||||
sort.Strings(names)
|
||||
for _, k := range names {
|
||||
fmt.Printf(" %s\n", k)
|
||||
}
|
||||
return
|
||||
case *fVersion:
|
||||
fmt.Println(internal.FormatFullVersion())
|
||||
return
|
||||
case *fSampleConfig:
|
||||
printer.PrintSampleConfig(
|
||||
sectionFilters,
|
||||
inputFilters,
|
||||
outputFilters,
|
||||
aggregatorFilters,
|
||||
processorFilters,
|
||||
)
|
||||
return
|
||||
case *fUsage != "":
|
||||
err := printer.PrintInputConfig(*fUsage)
|
||||
err2 := printer.PrintOutputConfig(*fUsage)
|
||||
if err != nil && err2 != nil {
|
||||
log.Fatalf("E! %s and %s", err, err2)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
run(
|
||||
inputFilters,
|
||||
outputFilters,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,10 +3,13 @@
|
|||
|
||||
package main
|
||||
|
||||
func run(inputFilters, outputFilters []string) {
|
||||
import "github.com/urfave/cli/v2"
|
||||
|
||||
func (t *Telegraf) Run() error {
|
||||
stop = make(chan struct{})
|
||||
reloadLoop(
|
||||
inputFilters,
|
||||
outputFilters,
|
||||
)
|
||||
return t.reloadLoop()
|
||||
}
|
||||
|
||||
func cliFlags() []cli.Flag {
|
||||
return []cli.Flag{}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,49 +6,83 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
|
||||
"github.com/influxdata/telegraf/logger"
|
||||
"github.com/kardianos/service"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func run(inputFilters, outputFilters []string) {
|
||||
// Register the eventlog logging target for windows.
|
||||
logger.RegisterEventLogger(*fServiceName)
|
||||
|
||||
if runtime.GOOS == "windows" && windowsRunAsService() {
|
||||
runAsWindowsService(
|
||||
inputFilters,
|
||||
outputFilters,
|
||||
)
|
||||
} else {
|
||||
stop = make(chan struct{})
|
||||
reloadLoop(
|
||||
inputFilters,
|
||||
outputFilters,
|
||||
)
|
||||
func cliFlags() []cli.Flag {
|
||||
return []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "service",
|
||||
Usage: "operate on the service (windows only)",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "service-name",
|
||||
Value: "telegraf",
|
||||
Usage: "service name (windows only)",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "service-display-name",
|
||||
Value: "Telegraf Data Collector Service",
|
||||
Usage: "service display name (windows only)",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "service-restart-delay",
|
||||
Value: "5m",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "service-auto-restart",
|
||||
Usage: "auto restart service on failure (windows only)",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "console",
|
||||
Usage: "run as console application (windows only)",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Telegraf) Run() error {
|
||||
// Register the eventlog logging target for windows.
|
||||
err := logger.RegisterEventLogger(t.serviceName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !t.windowsRunAsService() {
|
||||
stop = make(chan struct{})
|
||||
return t.reloadLoop()
|
||||
}
|
||||
|
||||
return t.runAsWindowsService()
|
||||
}
|
||||
|
||||
type program struct {
|
||||
inputFilters []string
|
||||
outputFilters []string
|
||||
*Telegraf
|
||||
}
|
||||
|
||||
func (p *program) Start(s service.Service) error {
|
||||
go p.run()
|
||||
go func() {
|
||||
stop = make(chan struct{})
|
||||
err := p.reloadLoop()
|
||||
if err != nil {
|
||||
fmt.Printf("E! %v\n", err)
|
||||
}
|
||||
close(stop)
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
func (p *program) run() {
|
||||
|
||||
func (p *program) run(errChan chan error) {
|
||||
stop = make(chan struct{})
|
||||
reloadLoop(
|
||||
p.inputFilters,
|
||||
p.outputFilters,
|
||||
)
|
||||
err := p.reloadLoop()
|
||||
errChan <- err
|
||||
close(stop)
|
||||
}
|
||||
|
||||
func (p *program) Stop(s service.Service) error {
|
||||
var empty struct{}
|
||||
stop <- empty // signal reloadLoop to finish (context cancel)
|
||||
|
|
@ -56,70 +90,68 @@ func (p *program) Stop(s service.Service) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func runAsWindowsService(inputFilters, outputFilters []string) {
|
||||
func (t *Telegraf) runAsWindowsService() error {
|
||||
programFiles := os.Getenv("ProgramFiles")
|
||||
if programFiles == "" { // Should never happen
|
||||
programFiles = "C:\\Program Files"
|
||||
}
|
||||
svcConfig := &service.Config{
|
||||
Name: *fServiceName,
|
||||
DisplayName: *fServiceDisplayName,
|
||||
Name: t.serviceName,
|
||||
DisplayName: t.serviceDisplayName,
|
||||
Description: "Collects data using a series of plugins and publishes it to " +
|
||||
"another series of plugins.",
|
||||
Arguments: []string{"--config", programFiles + "\\Telegraf\\telegraf.conf"},
|
||||
}
|
||||
|
||||
prg := &program{
|
||||
inputFilters: inputFilters,
|
||||
outputFilters: outputFilters,
|
||||
Telegraf: t,
|
||||
}
|
||||
s, err := service.New(prg, svcConfig)
|
||||
if err != nil {
|
||||
log.Fatal("E! " + err.Error())
|
||||
return fmt.Errorf("E! " + err.Error())
|
||||
}
|
||||
// Handle the --service flag here to prevent any issues with tooling that
|
||||
// may not have an interactive session, e.g. installing from Ansible.
|
||||
if *fService != "" {
|
||||
if len(fConfigs) > 0 {
|
||||
if t.service != "" {
|
||||
if len(t.config) > 0 {
|
||||
svcConfig.Arguments = []string{}
|
||||
}
|
||||
for _, fConfig := range fConfigs {
|
||||
for _, fConfig := range t.config {
|
||||
svcConfig.Arguments = append(svcConfig.Arguments, "--config", fConfig)
|
||||
}
|
||||
|
||||
for _, fConfigDirectory := range fConfigDirs {
|
||||
for _, fConfigDirectory := range t.configDir {
|
||||
svcConfig.Arguments = append(svcConfig.Arguments, "--config-directory", fConfigDirectory)
|
||||
}
|
||||
|
||||
//set servicename to service cmd line, to have a custom name after relaunch as a service
|
||||
svcConfig.Arguments = append(svcConfig.Arguments, "--service-name", *fServiceName)
|
||||
svcConfig.Arguments = append(svcConfig.Arguments, "--service-name", t.serviceName)
|
||||
|
||||
if *fServiceAutoRestart {
|
||||
svcConfig.Option = service.KeyValue{"OnFailure": "restart", "OnFailureDelayDuration": *fServiceRestartDelay}
|
||||
if t.serviceAutoRestart {
|
||||
svcConfig.Option = service.KeyValue{"OnFailure": "restart", "OnFailureDelayDuration": t.serviceRestartDelay}
|
||||
}
|
||||
|
||||
err := service.Control(s, *fService)
|
||||
err := service.Control(s, t.service)
|
||||
if err != nil {
|
||||
log.Fatal("E! " + err.Error())
|
||||
return fmt.Errorf("E! " + err.Error())
|
||||
}
|
||||
os.Exit(0)
|
||||
} else {
|
||||
logger.SetupLogging(logger.LogConfig{LogTarget: logger.LogTargetEventlog})
|
||||
err = s.Run()
|
||||
|
||||
if err != nil {
|
||||
log.Println("E! " + err.Error())
|
||||
return fmt.Errorf("E! " + err.Error())
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Return true if Telegraf should create a Windows service.
|
||||
func windowsRunAsService() bool {
|
||||
if *fService != "" {
|
||||
func (t *Telegraf) windowsRunAsService() bool {
|
||||
if t.service != "" {
|
||||
return true
|
||||
}
|
||||
|
||||
if *fRunAsConsole {
|
||||
if t.console {
|
||||
return false
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ func NewConfig() *Config {
|
|||
}
|
||||
|
||||
// Handle unknown version
|
||||
version := internal.Version()
|
||||
version := internal.Version
|
||||
if version == "" || version == "unknown" {
|
||||
version = "0.0.0-unknown"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@ import (
|
|||
"github.com/influxdata/telegraf/plugins/processors"
|
||||
)
|
||||
|
||||
// deprecationInfo contains all important information to describe a deprecated entity
|
||||
type deprecationInfo struct {
|
||||
// DeprecationInfo contains all important information to describe a deprecated entity
|
||||
type DeprecationInfo struct {
|
||||
// Name of the plugin or plugin option
|
||||
Name string
|
||||
// LogLevel is the level of deprecation which currently corresponds to a log-level
|
||||
|
|
@ -27,7 +27,7 @@ type deprecationInfo struct {
|
|||
info telegraf.DeprecationInfo
|
||||
}
|
||||
|
||||
func (di *deprecationInfo) determineEscalation(telegrafVersion *semver.Version) error {
|
||||
func (di *DeprecationInfo) determineEscalation(telegrafVersion *semver.Version) error {
|
||||
di.LogLevel = telegraf.None
|
||||
if di.info.Since == "" {
|
||||
return nil
|
||||
|
|
@ -64,12 +64,12 @@ func (di *deprecationInfo) determineEscalation(telegrafVersion *semver.Version)
|
|||
return nil
|
||||
}
|
||||
|
||||
// pluginDeprecationInfo holds all information about a deprecated plugin or it's options
|
||||
type pluginDeprecationInfo struct {
|
||||
deprecationInfo
|
||||
// PluginDeprecationInfo holds all information about a deprecated plugin or it's options
|
||||
type PluginDeprecationInfo struct {
|
||||
DeprecationInfo
|
||||
|
||||
// Options deprecated for this plugin
|
||||
Options []deprecationInfo
|
||||
Options []DeprecationInfo
|
||||
}
|
||||
|
||||
func (c *Config) incrementPluginDeprecations(category string) {
|
||||
|
|
@ -88,9 +88,9 @@ func (c *Config) incrementPluginOptionDeprecations(category string) {
|
|||
c.Deprecations[category] = newcounts
|
||||
}
|
||||
|
||||
func (c *Config) collectDeprecationInfo(category, name string, plugin interface{}, all bool) pluginDeprecationInfo {
|
||||
info := pluginDeprecationInfo{
|
||||
deprecationInfo: deprecationInfo{
|
||||
func (c *Config) collectDeprecationInfo(category, name string, plugin interface{}, all bool) PluginDeprecationInfo {
|
||||
info := PluginDeprecationInfo{
|
||||
DeprecationInfo: DeprecationInfo{
|
||||
Name: category + "." + name,
|
||||
LogLevel: telegraf.None,
|
||||
},
|
||||
|
|
@ -100,19 +100,19 @@ func (c *Config) collectDeprecationInfo(category, name string, plugin interface{
|
|||
switch category {
|
||||
case "aggregators":
|
||||
if pi, deprecated := aggregators.Deprecations[name]; deprecated {
|
||||
info.deprecationInfo.info = pi
|
||||
info.DeprecationInfo.info = pi
|
||||
}
|
||||
case "inputs":
|
||||
if pi, deprecated := inputs.Deprecations[name]; deprecated {
|
||||
info.deprecationInfo.info = pi
|
||||
info.DeprecationInfo.info = pi
|
||||
}
|
||||
case "outputs":
|
||||
if pi, deprecated := outputs.Deprecations[name]; deprecated {
|
||||
info.deprecationInfo.info = pi
|
||||
info.DeprecationInfo.info = pi
|
||||
}
|
||||
case "processors":
|
||||
if pi, deprecated := processors.Deprecations[name]; deprecated {
|
||||
info.deprecationInfo.info = pi
|
||||
info.DeprecationInfo.info = pi
|
||||
}
|
||||
}
|
||||
if err := info.determineEscalation(c.version); err != nil {
|
||||
|
|
@ -138,7 +138,7 @@ func (c *Config) collectDeprecationInfo(category, name string, plugin interface{
|
|||
if len(tags) < 1 || tags[0] == "" {
|
||||
return
|
||||
}
|
||||
optionInfo := deprecationInfo{Name: field.Name}
|
||||
optionInfo := DeprecationInfo{Name: field.Name}
|
||||
optionInfo.info.Since = tags[0]
|
||||
|
||||
if len(tags) > 1 {
|
||||
|
|
@ -190,10 +190,10 @@ func (c *Config) printUserDeprecation(category, name string, plugin interface{})
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Config) CollectDeprecationInfos(inFilter, outFilter, aggFilter, procFilter []string) map[string][]pluginDeprecationInfo {
|
||||
infos := make(map[string][]pluginDeprecationInfo)
|
||||
func (c *Config) CollectDeprecationInfos(inFilter, outFilter, aggFilter, procFilter []string) map[string][]PluginDeprecationInfo {
|
||||
infos := make(map[string][]PluginDeprecationInfo)
|
||||
|
||||
infos["inputs"] = make([]pluginDeprecationInfo, 0)
|
||||
infos["inputs"] = make([]PluginDeprecationInfo, 0)
|
||||
for name, creator := range inputs.Inputs {
|
||||
if len(inFilter) > 0 && !sliceContains(name, inFilter) {
|
||||
continue
|
||||
|
|
@ -207,7 +207,7 @@ func (c *Config) CollectDeprecationInfos(inFilter, outFilter, aggFilter, procFil
|
|||
}
|
||||
}
|
||||
|
||||
infos["outputs"] = make([]pluginDeprecationInfo, 0)
|
||||
infos["outputs"] = make([]PluginDeprecationInfo, 0)
|
||||
for name, creator := range outputs.Outputs {
|
||||
if len(outFilter) > 0 && !sliceContains(name, outFilter) {
|
||||
continue
|
||||
|
|
@ -221,7 +221,7 @@ func (c *Config) CollectDeprecationInfos(inFilter, outFilter, aggFilter, procFil
|
|||
}
|
||||
}
|
||||
|
||||
infos["processors"] = make([]pluginDeprecationInfo, 0)
|
||||
infos["processors"] = make([]PluginDeprecationInfo, 0)
|
||||
for name, creator := range processors.Processors {
|
||||
if len(procFilter) > 0 && !sliceContains(name, procFilter) {
|
||||
continue
|
||||
|
|
@ -235,7 +235,7 @@ func (c *Config) CollectDeprecationInfos(inFilter, outFilter, aggFilter, procFil
|
|||
}
|
||||
}
|
||||
|
||||
infos["aggregators"] = make([]pluginDeprecationInfo, 0)
|
||||
infos["aggregators"] = make([]PluginDeprecationInfo, 0)
|
||||
for name, creator := range aggregators.Aggregators {
|
||||
if len(aggFilter) > 0 && !sliceContains(name, aggFilter) {
|
||||
continue
|
||||
|
|
@ -252,7 +252,7 @@ func (c *Config) CollectDeprecationInfos(inFilter, outFilter, aggFilter, procFil
|
|||
return infos
|
||||
}
|
||||
|
||||
func (c *Config) PrintDeprecationList(plugins []pluginDeprecationInfo) {
|
||||
func (c *Config) PrintDeprecationList(plugins []PluginDeprecationInfo) {
|
||||
sort.Slice(plugins, func(i, j int) bool { return plugins[i].Name < plugins[j].Name })
|
||||
|
||||
for _, plugin := range plugins {
|
||||
|
|
|
|||
|
|
@ -81,6 +81,7 @@ following works:
|
|||
- github.com/couchbase/go-couchbase [MIT License](https://github.com/couchbase/go-couchbase/blob/master/LICENSE)
|
||||
- github.com/couchbase/gomemcached [MIT License](https://github.com/couchbase/gomemcached/blob/master/LICENSE)
|
||||
- github.com/couchbase/goutils [Apache License 2.0](https://github.com/couchbase/goutils/blob/master/LICENSE.md)
|
||||
- github.com/cpuguy83/go-md2man [MIT License](https://github.com/cpuguy83/go-md2man/blob/master/LICENSE.md)
|
||||
- github.com/davecgh/go-spew [ISC License](https://github.com/davecgh/go-spew/blob/master/LICENSE)
|
||||
- github.com/denisenkom/go-mssqldb [BSD 3-Clause "New" or "Revised" License](https://github.com/denisenkom/go-mssqldb/blob/master/LICENSE.txt)
|
||||
- github.com/devigned/tab [MIT License](https://github.com/devigned/tab/blob/master/LICENSE)
|
||||
|
|
@ -251,6 +252,7 @@ following works:
|
|||
- github.com/remyoudompheng/bigfft [BSD 3-Clause "New" or "Revised" License](https://github.com/remyoudompheng/bigfft/blob/master/LICENSE)
|
||||
- github.com/riemann/riemann-go-client [MIT License](https://github.com/riemann/riemann-go-client/blob/master/LICENSE)
|
||||
- github.com/robbiet480/go.nut [MIT License](https://github.com/robbiet480/go.nut/blob/master/LICENSE)
|
||||
- github.com/russross/blackfriday [BSD 2-Clause "Simplified" License](https://github.com/russross/blackfriday/blob/master/LICENSE.txt)
|
||||
- github.com/safchain/ethtool [Apache License 2.0](https://github.com/safchain/ethtool/blob/master/LICENSE)
|
||||
- github.com/samuel/go-zookeeper [BSD 3-Clause Clear License](https://github.com/samuel/go-zookeeper/blob/master/LICENSE)
|
||||
- github.com/shirou/gopsutil [BSD 3-Clause Clear License](https://github.com/shirou/gopsutil/blob/master/LICENSE)
|
||||
|
|
@ -272,6 +274,7 @@ following works:
|
|||
- github.com/tinylib/msgp [MIT License](https://github.com/tinylib/msgp/blob/master/LICENSE)
|
||||
- github.com/tklauser/go-sysconf [BSD 3-Clause "New" or "Revised" License](https://github.com/tklauser/go-sysconf/blob/master/LICENSE)
|
||||
- github.com/tklauser/numcpus [Apache License 2.0](https://github.com/tklauser/numcpus/blob/master/LICENSE)
|
||||
- github.com/urfave/cli [MIT License](https://github.com/urfave/cli/blob/main/LICENSE)
|
||||
- github.com/vapourismo/knx-go [MIT License](https://github.com/vapourismo/knx-go/blob/master/LICENSE)
|
||||
- github.com/vishvananda/netlink [Apache License 2.0](https://github.com/vishvananda/netlink/blob/master/LICENSE)
|
||||
- github.com/vishvananda/netns [Apache License 2.0](https://github.com/vishvananda/netns/blob/master/LICENSE)
|
||||
|
|
@ -285,6 +288,7 @@ following works:
|
|||
- github.com/xdg-go/stringprep [Apache License 2.0](https://github.com/xdg-go/stringprep/blob/master/LICENSE)
|
||||
- github.com/xdg/scram [Apache License 2.0](https://github.com/xdg-go/scram/blob/master/LICENSE)
|
||||
- github.com/xdg/stringprep [Apache License 2.0](https://github.com/xdg-go/stringprep/blob/master/LICENSE)
|
||||
- github.com/xrash/smetrics [MIT License](https://github.com/xrash/smetrics/blob/master/LICENSE)
|
||||
- github.com/youmark/pkcs8 [MIT License](https://github.com/youmark/pkcs8/blob/master/LICENSE)
|
||||
- github.com/yuin/gopher-lua [MIT License](https://github.com/yuin/gopher-lua/blob/master/LICENSE)
|
||||
- github.com/yusufpapurcu/wmi [MIT License](https://github.com/yusufpapurcu/wmi/blob/master/LICENSE)
|
||||
|
|
|
|||
13
go.mod
13
go.mod
|
|
@ -180,14 +180,6 @@ require (
|
|||
modernc.org/sqlite v1.17.3
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/imdario/mergo v0.3.12 // indirect
|
||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
|
||||
gopkg.in/macaroon-bakery.v3 v3.0.0 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.102.1 // indirect
|
||||
cloud.google.com/go/compute v1.7.0 // indirect
|
||||
|
|
@ -290,6 +282,7 @@ require (
|
|||
github.com/hashicorp/go-rootcerts v1.0.2 // indirect
|
||||
github.com/hashicorp/golang-lru v0.5.4 // indirect
|
||||
github.com/hashicorp/serf v0.9.7 // indirect
|
||||
github.com/imdario/mergo v0.3.12 // indirect
|
||||
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
|
||||
github.com/jackc/pgconn v1.13.0 // indirect
|
||||
github.com/jackc/pgio v1.0.0 // indirect
|
||||
|
|
@ -331,6 +324,7 @@ require (
|
|||
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect
|
||||
github.com/morikuni/aec v1.0.0 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/naoina/go-stringutil v0.1.0 // indirect
|
||||
|
|
@ -362,6 +356,7 @@ require (
|
|||
github.com/signalfx/com_signalfx_metrics_protobuf v0.0.2 // indirect
|
||||
github.com/signalfx/gohistogram v0.0.0-20160107210732-1ccfd2ff5083 // indirect
|
||||
github.com/signalfx/sapm-proto v0.7.2 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/stretchr/objx v0.4.0 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.0 // indirect
|
||||
|
|
@ -374,6 +369,7 @@ require (
|
|||
github.com/xdg-go/scram v1.1.1 // indirect
|
||||
github.com/xdg-go/stringprep v1.0.3 // indirect
|
||||
github.com/xdg/stringprep v1.0.3 // indirect
|
||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
|
||||
github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect
|
||||
github.com/yuin/gopher-lua v0.0.0-20200816102855-ee81675732da // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.2 // indirect
|
||||
|
|
@ -401,6 +397,7 @@ require (
|
|||
gopkg.in/httprequest.v1 v1.2.1 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/ini.v1 v1.66.6 // indirect
|
||||
gopkg.in/macaroon-bakery.v3 v3.0.0 // indirect
|
||||
gopkg.in/macaroon.v2 v2.1.0 // indirect
|
||||
gopkg.in/sourcemap.v1 v1.0.5 // indirect
|
||||
gopkg.in/tomb.v2 v2.0.0-20161208151619-d5d1b5820637 // indirect
|
||||
|
|
|
|||
|
|
@ -29,9 +29,9 @@ var (
|
|||
|
||||
// Set via LDFLAGS -X
|
||||
var (
|
||||
version = "unknown"
|
||||
branch = ""
|
||||
commit = ""
|
||||
Version = "unknown"
|
||||
Branch = ""
|
||||
Commit = ""
|
||||
)
|
||||
|
||||
type ReadWaitCloser struct {
|
||||
|
|
@ -39,28 +39,23 @@ type ReadWaitCloser struct {
|
|||
wg sync.WaitGroup
|
||||
}
|
||||
|
||||
// Version returns the telegraf agent version
|
||||
func Version() string {
|
||||
return version
|
||||
}
|
||||
|
||||
func FormatFullVersion() string {
|
||||
var parts = []string{"Telegraf"}
|
||||
|
||||
if version != "" {
|
||||
parts = append(parts, version)
|
||||
if Version != "" {
|
||||
parts = append(parts, Version)
|
||||
} else {
|
||||
parts = append(parts, "unknown")
|
||||
}
|
||||
|
||||
if branch != "" || commit != "" {
|
||||
if branch == "" {
|
||||
branch = "unknown"
|
||||
if Branch != "" || Commit != "" {
|
||||
if Branch == "" {
|
||||
Branch = "unknown"
|
||||
}
|
||||
if commit == "" {
|
||||
commit = "unknown"
|
||||
if Commit == "" {
|
||||
Commit = "unknown"
|
||||
}
|
||||
git := fmt.Sprintf("(git: %s@%s)", branch, commit)
|
||||
git := fmt.Sprintf("(git: %s@%s)", Branch, Commit)
|
||||
parts = append(parts, git)
|
||||
}
|
||||
|
||||
|
|
@ -70,7 +65,7 @@ func FormatFullVersion() string {
|
|||
// ProductToken returns a tag for Telegraf that can be used in user agents.
|
||||
func ProductToken() string {
|
||||
return fmt.Sprintf("Telegraf/%s Go/%s",
|
||||
Version(), strings.TrimPrefix(runtime.Version(), "go"))
|
||||
Version, strings.TrimPrefix(runtime.Version(), "go"))
|
||||
}
|
||||
|
||||
// ReadLines reads contents from a file and splits them by new lines.
|
||||
|
|
@ -82,8 +77,9 @@ func ReadLines(filename string) ([]string, error) {
|
|||
// ReadLines reads contents from file and splits them by new line.
|
||||
// The offset tells at which line number to start.
|
||||
// The count determines the number of lines to read (starting from offset):
|
||||
// n >= 0: at most n lines
|
||||
// n < 0: whole file
|
||||
//
|
||||
// n >= 0: at most n lines
|
||||
// n < 0: whole file
|
||||
func ReadLinesOffsetN(filename string, offset uint, n int) ([]string, error) {
|
||||
f, err := os.Open(filename)
|
||||
if err != nil {
|
||||
|
|
@ -244,9 +240,10 @@ func CompressWithGzip(data io.Reader) (io.ReadCloser, error) {
|
|||
|
||||
// ParseTimestamp parses a Time according to the standard Telegraf options.
|
||||
// These are generally displayed in the toml similar to:
|
||||
// json_time_key= "timestamp"
|
||||
// json_time_format = "2006-01-02T15:04:05Z07:00"
|
||||
// json_timezone = "America/Los_Angeles"
|
||||
//
|
||||
// json_time_key= "timestamp"
|
||||
// json_time_format = "2006-01-02T15:04:05Z07:00"
|
||||
// json_timezone = "America/Los_Angeles"
|
||||
//
|
||||
// The format can be one of "unix", "unix_ms", "unix_us", "unix_ns", or a Go
|
||||
// time layout suitable for time.Parse.
|
||||
|
|
@ -295,7 +292,8 @@ func parseUnix(format string, timestamp interface{}) (time.Time, error) {
|
|||
// Returns the integers before and after an optional decimal point. Both '.'
|
||||
// and ',' are supported for the decimal point. The timestamp can be an int64,
|
||||
// float64, or string.
|
||||
// ex: "42.5" -> (42, 5, nil)
|
||||
//
|
||||
// ex: "42.5" -> (42, 5, nil)
|
||||
func parseComponents(timestamp interface{}) (int64, int64, error) {
|
||||
switch ts := timestamp.(type) {
|
||||
case string:
|
||||
|
|
|
|||
|
|
@ -1,66 +0,0 @@
|
|||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package internal
|
||||
|
||||
const Usage = `Telegraf, The plugin-driven server agent for collecting and reporting metrics.
|
||||
|
||||
Usage:
|
||||
|
||||
telegraf [commands|flags]
|
||||
|
||||
The commands & flags are:
|
||||
|
||||
config print out full sample configuration to stdout
|
||||
version print the version to stdout
|
||||
|
||||
--aggregator-filter <filter> filter the aggregators to enable, separator is :
|
||||
--config <file> configuration file to load
|
||||
--config-directory <directory> directory containing additional *.conf files
|
||||
--watch-config Telegraf will restart on local config changes. Monitor changes
|
||||
using either fs notifications or polling. Valid values: 'inotify' or 'poll'.
|
||||
Monitoring is off by default.
|
||||
--plugin-directory directory containing *.so files, this directory will be
|
||||
searched recursively. Any Plugin found will be loaded
|
||||
and namespaced.
|
||||
--debug turn on debug logging
|
||||
--deprecation-list print all deprecated plugins or plugin options.
|
||||
--input-filter <filter> filter the inputs to enable, separator is :
|
||||
--input-list print available input plugins.
|
||||
--output-filter <filter> filter the outputs to enable, separator is :
|
||||
--output-list print available output plugins.
|
||||
--pidfile <file> file to write our pid to
|
||||
--pprof-addr <address> pprof address to listen on, don't activate pprof if empty
|
||||
--processor-filter <filter> filter the processors to enable, separator is :
|
||||
--quiet run in quiet mode
|
||||
--section-filter filter config sections to output, separator is :
|
||||
Valid values are 'agent', 'global_tags', 'outputs',
|
||||
'processors', 'aggregators' and 'inputs'
|
||||
--sample-config print out full sample configuration
|
||||
--once enable once mode: gather metrics once, write them, and exit
|
||||
--test enable test mode: gather metrics once and print them.
|
||||
No outputs are executed!
|
||||
--test-wait wait up to this many seconds for service inputs to complete
|
||||
in test or once mode. Implies --test if not used with --once.
|
||||
--usage <plugin> print usage for a plugin, ie, 'telegraf --usage mysql'
|
||||
--version display the version and exit
|
||||
|
||||
Examples:
|
||||
|
||||
# generate a telegraf config file:
|
||||
telegraf config > telegraf.conf
|
||||
|
||||
# generate config with only cpu input & influxdb output plugins defined
|
||||
telegraf config --input-filter cpu --output-filter influxdb
|
||||
|
||||
# run a single telegraf collection, outputting metrics to stdout
|
||||
telegraf --config telegraf.conf --test
|
||||
|
||||
# run telegraf with all plugins defined in config file
|
||||
telegraf --config telegraf.conf
|
||||
|
||||
# run telegraf, enabling the cpu & memory input, and influxdb output plugins
|
||||
telegraf --config telegraf.conf --input-filter cpu:mem --output-filter influxdb
|
||||
|
||||
# run telegraf with pprof
|
||||
telegraf --config telegraf.conf --pprof-addr localhost:6060`
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package internal
|
||||
|
||||
const Usage = `Telegraf, The plugin-driven server agent for collecting and reporting metrics.
|
||||
|
||||
Usage:
|
||||
|
||||
telegraf [commands|flags]
|
||||
|
||||
The commands & flags are:
|
||||
|
||||
config print out full sample configuration to stdout
|
||||
version print the version to stdout
|
||||
|
||||
--aggregator-filter <filter> filter the aggregators to enable, separator is :
|
||||
--config <file> configuration file to load
|
||||
--config-directory <directory> directory containing additional *.conf files
|
||||
--watch-config Telegraf will restart on local config changes. Monitor changes
|
||||
using either fs notifications or polling. Valid values: 'inotify' or 'poll'.
|
||||
Monitoring is off by default.
|
||||
--debug turn on debug logging
|
||||
--input-filter <filter> filter the inputs to enable, separator is :
|
||||
--input-list print available input plugins.
|
||||
--output-filter <filter> filter the outputs to enable, separator is :
|
||||
--output-list print available output plugins.
|
||||
--pidfile <file> file to write our pid to
|
||||
--pprof-addr <address> pprof address to listen on, don't activate pprof if empty
|
||||
--processor-filter <filter> filter the processors to enable, separator is :
|
||||
--quiet run in quiet mode
|
||||
--sample-config print out full sample configuration
|
||||
--section-filter filter config sections to output, separator is :
|
||||
Valid values are 'agent', 'global_tags', 'outputs',
|
||||
'processors', 'aggregators' and 'inputs'
|
||||
--once enable once mode: gather metrics once, write them, and exit
|
||||
--test enable test mode: gather metrics once and print them
|
||||
--test-wait wait up to this many seconds for service
|
||||
inputs to complete in test or once mode
|
||||
--usage <plugin> print usage for a plugin, ie, 'telegraf --usage mysql'
|
||||
--version display the version and exit
|
||||
|
||||
--console run as console application (windows only)
|
||||
--service <service> operate on the service (windows only)
|
||||
--service-name service name (windows only)
|
||||
--service-display-name service display name (windows only)
|
||||
--service-auto-restart auto restart service on failure (windows only)
|
||||
--service-restart-delay delay before service auto restart, default is 5m (windows only)
|
||||
|
||||
Examples:
|
||||
|
||||
# generate a telegraf config file:
|
||||
telegraf config > telegraf.conf
|
||||
|
||||
# generate config with only cpu input & influxdb output plugins defined
|
||||
telegraf --input-filter cpu --output-filter influxdb config
|
||||
|
||||
# run a single telegraf collection, outputting metrics to stdout
|
||||
telegraf --config telegraf.conf --test
|
||||
|
||||
# run telegraf with all plugins defined in config file
|
||||
telegraf --config telegraf.conf
|
||||
|
||||
# run telegraf, enabling the cpu & memory input, and influxdb output plugins
|
||||
telegraf --config telegraf.conf --input-filter cpu:mem --output-filter influxdb
|
||||
|
||||
# run telegraf with pprof
|
||||
telegraf --config telegraf.conf --pprof-addr localhost:6060
|
||||
|
||||
# run telegraf without service controller
|
||||
telegraf --console install --config "C:\Program Files\Telegraf\telegraf.conf"
|
||||
|
||||
# install telegraf service
|
||||
telegraf --service install --config "C:\Program Files\Telegraf\telegraf.conf"
|
||||
|
||||
# install telegraf service with custom name
|
||||
telegraf --service install --service-name=my-telegraf --service-display-name="My Telegraf"
|
||||
|
||||
# install telegraf service with auto restart and restart delay of 3 minutes
|
||||
telegraf --service install --service-auto-restart --service-restart-delay 3m`
|
||||
|
|
@ -19,6 +19,7 @@ import (
|
|||
)
|
||||
|
||||
// DO NOT REMOVE THE NEXT TWO LINES! This is required to embed the sampleConfig data.
|
||||
//
|
||||
//go:embed sample.conf
|
||||
var sampleConfig string
|
||||
|
||||
|
|
@ -126,11 +127,13 @@ type memstats struct {
|
|||
|
||||
// Gathers data from a particular URL
|
||||
// Parameters:
|
||||
// acc : The telegraf Accumulator to use
|
||||
// url : endpoint to send request to
|
||||
//
|
||||
// acc : The telegraf Accumulator to use
|
||||
// url : endpoint to send request to
|
||||
//
|
||||
// Returns:
|
||||
// error: Any error that may have occurred
|
||||
//
|
||||
// error: Any error that may have occurred
|
||||
func (i *InfluxDB) gatherURL(
|
||||
acc telegraf.Accumulator,
|
||||
url string,
|
||||
|
|
@ -147,7 +150,7 @@ func (i *InfluxDB) gatherURL(
|
|||
req.SetBasicAuth(i.Username, i.Password)
|
||||
}
|
||||
|
||||
req.Header.Set("User-Agent", "Telegraf/"+internal.Version())
|
||||
req.Header.Set("User-Agent", "Telegraf/"+internal.Version)
|
||||
|
||||
resp, err := i.client.Do(req)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ plugin.
|
|||
# collect_memstats = true
|
||||
```
|
||||
|
||||
## Measurements & Fields
|
||||
## Metrics
|
||||
|
||||
memstats are taken from the Go runtime:
|
||||
<https://golang.org/pkg/runtime/#MemStats>
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import (
|
|||
)
|
||||
|
||||
// DO NOT REMOVE THE NEXT TWO LINES! This is required to embed the sampleConfig data.
|
||||
//
|
||||
//go:embed sample.conf
|
||||
var sampleConfig string
|
||||
|
||||
|
|
@ -53,7 +54,7 @@ func (s *Self) Gather(acc telegraf.Accumulator) error {
|
|||
acc.AddFields("internal_memstats", fields, map[string]string{})
|
||||
}
|
||||
|
||||
telegrafVersion := inter.Version()
|
||||
telegrafVersion := inter.Version
|
||||
goVersion := strings.TrimPrefix(runtime.Version(), "go")
|
||||
|
||||
for _, m := range selfstat.Metrics() {
|
||||
|
|
|
|||
Loading…
Reference in New Issue