telegraf/cmd/telegraf/telegraf.go

344 lines
9.3 KiB
Go
Raw Normal View History

package main
import (
"context"
"errors"
2015-04-08 00:24:34 +08:00
"fmt"
"log"
"os"
"os/signal"
"strings"
"syscall"
"time"
"github.com/coreos/go-systemd/daemon"
"github.com/fatih/color"
"github.com/influxdata/tail/watch"
"gopkg.in/tomb.v1"
"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/agent"
"github.com/influxdata/telegraf/config"
"github.com/influxdata/telegraf/internal"
"github.com/influxdata/telegraf/logger"
"github.com/influxdata/telegraf/plugins/aggregators"
"github.com/influxdata/telegraf/plugins/inputs"
"github.com/influxdata/telegraf/plugins/outputs"
"github.com/influxdata/telegraf/plugins/parsers"
"github.com/influxdata/telegraf/plugins/processors"
"github.com/influxdata/telegraf/plugins/secretstores"
)
2022-08-25 10:46:58 +08:00
var stop chan struct{}
2022-08-25 10:46:58 +08:00
type GlobalFlags struct {
config []string
configDir []string
testWait int
watchConfig string
pidFile string
plugindDir string
test bool
debug bool
once bool
quiet bool
}
2022-08-25 10:46:58 +08:00
type WindowFlags struct {
service string
serviceName string
serviceDisplayName string
serviceRestartDelay string
serviceAutoRestart bool
console bool
}
2022-08-25 10:46:58 +08:00
type App interface {
Init(<-chan error, Filters, GlobalFlags, WindowFlags)
Run() error
// Secret store commands
ListSecretStores() ([]string, error)
GetSecretStore(string) (telegraf.SecretStore, error)
2022-08-25 10:46:58 +08:00
}
2016-01-08 06:21:10 +08:00
2022-08-25 10:46:58 +08:00
type Telegraf struct {
pprofErr <-chan error
inputFilters []string
outputFilters []string
configFiles []string
secretstoreFilters []string
2022-08-25 10:46:58 +08:00
GlobalFlags
WindowFlags
}
Telegraf support for built-in windows service. Updated windows dependencies Updated the windows dependencies so that the versions matched the dependencies for Mac OS and Linux. Additionally added some that were complained about being missing at compile time. Incorporated kardianos/service for management Incorporated the library github.com/kardianos/service to manage the service on the various platforms (including Windows). This required an alternate main function. The original main function was renamed to reloadLoop (as that is what the main loop in it does) (it also got a couple of parameters). The service management library calls it as the main body of the program. Merged service.go into telegraf.go Due to compilation issues on Windows, moved the code from service.go into telegraf.go and removed service.go entirely. Updated dependencies and fixed Windows service Updated the dependencies so that it builds properly on Windows, additionally, fixed the registered command for starting it as a service (needed to add the config file option). This currently standardizes it as a C:\telegraf\telegraf.conf on Windows. Added dependency for github.com/kardianos/service Removed the common dependencies from _windows file Removed all the common dependencies from the Godeps_windows file and modified Makefile to load Godeps and then Godeps_windows when building for Windows. This should reduce problems caused by the Godeps_windows file being forgotten when updating dependencies. Updated CHANGELOG.md with changes Ran `go fmt ./...` to format code Removed service library on all but Windows The service library [kardianos/service](github.com/kardianos/service) has been disabled on all platforms but windows, as there is already existing infrastructure for other platforms. Removed the dependency line for itself It appears that gdm accidentally added the project itself to the dependency list. This caused the dependency restoration to select an earlier version of the project during build. This only affected windows. This only affected builds after 020b2c70 Updated documentation for Windows Service Removed the documentation about using NSSM and added documentation on installing telegraf directly as a Windows Service. Added license info for kardianos/service Added the license information for github.com/kardianos/service which is licensed under the ZLib license, although that name is never mentioned the license text matches word for word. Changed the Windows Config file default location Updated the default location of the configuration file on Windows from C:\telegraf\telegraf.conf to C:\Program Files\Telegraf\telegraf.conf. With this change includes updating the directions, including directing that the executable be put into that same directory. Additionally, as noted in the instructions, the location of the config file for the service may be changed by specifying the location with the `-config` flag at install time. Fixed bug - Wrong data type: svcConfig svcConfig service.Config => svcConfig *service.Config (It needed to be a pointer)
2016-07-16 05:00:16 +08:00
func (t *Telegraf) Init(pprofErr <-chan error, f Filters, g GlobalFlags, w WindowFlags) {
t.pprofErr = pprofErr
t.inputFilters = f.input
t.outputFilters = f.output
t.secretstoreFilters = f.secretstore
t.GlobalFlags = g
t.WindowFlags = w
2022-08-25 10:46:58 +08:00
}
func (t *Telegraf) ListSecretStores() ([]string, error) {
c, err := t.loadConfiguration()
if err != nil {
return nil, err
}
ids := make([]string, 0, len(c.SecretStores))
for k := range c.SecretStores {
ids = append(ids, k)
}
return ids, nil
}
func (t *Telegraf) GetSecretStore(id string) (telegraf.SecretStore, error) {
c, err := t.loadConfiguration()
if err != nil {
return nil, err
}
store, found := c.SecretStores[id]
if !found {
return nil, errors.New("unknown secret store")
}
return store, nil
}
func (t *Telegraf) reloadLoop() error {
cfg, err := t.loadConfiguration()
if err != nil {
return err
}
reload := make(chan bool, 1)
reload <- true
for <-reload {
reload <- false
ctx, cancel := context.WithCancel(context.Background())
signals := make(chan os.Signal, 1)
signal.Notify(signals, os.Interrupt, syscall.SIGHUP,
syscall.SIGTERM, syscall.SIGINT)
if t.watchConfig != "" {
for _, fConfig := range t.configFiles {
if _, err := os.Stat(fConfig); err == nil {
go t.watchLocalConfig(signals, fConfig)
} else {
log.Printf("W! Cannot watch config %s: %s", fConfig, err)
}
}
}
go func() {
Telegraf support for built-in windows service. Updated windows dependencies Updated the windows dependencies so that the versions matched the dependencies for Mac OS and Linux. Additionally added some that were complained about being missing at compile time. Incorporated kardianos/service for management Incorporated the library github.com/kardianos/service to manage the service on the various platforms (including Windows). This required an alternate main function. The original main function was renamed to reloadLoop (as that is what the main loop in it does) (it also got a couple of parameters). The service management library calls it as the main body of the program. Merged service.go into telegraf.go Due to compilation issues on Windows, moved the code from service.go into telegraf.go and removed service.go entirely. Updated dependencies and fixed Windows service Updated the dependencies so that it builds properly on Windows, additionally, fixed the registered command for starting it as a service (needed to add the config file option). This currently standardizes it as a C:\telegraf\telegraf.conf on Windows. Added dependency for github.com/kardianos/service Removed the common dependencies from _windows file Removed all the common dependencies from the Godeps_windows file and modified Makefile to load Godeps and then Godeps_windows when building for Windows. This should reduce problems caused by the Godeps_windows file being forgotten when updating dependencies. Updated CHANGELOG.md with changes Ran `go fmt ./...` to format code Removed service library on all but Windows The service library [kardianos/service](github.com/kardianos/service) has been disabled on all platforms but windows, as there is already existing infrastructure for other platforms. Removed the dependency line for itself It appears that gdm accidentally added the project itself to the dependency list. This caused the dependency restoration to select an earlier version of the project during build. This only affected windows. This only affected builds after 020b2c70 Updated documentation for Windows Service Removed the documentation about using NSSM and added documentation on installing telegraf directly as a Windows Service. Added license info for kardianos/service Added the license information for github.com/kardianos/service which is licensed under the ZLib license, although that name is never mentioned the license text matches word for word. Changed the Windows Config file default location Updated the default location of the configuration file on Windows from C:\telegraf\telegraf.conf to C:\Program Files\Telegraf\telegraf.conf. With this change includes updating the directions, including directing that the executable be put into that same directory. Additionally, as noted in the instructions, the location of the config file for the service may be changed by specifying the location with the `-config` flag at install time. Fixed bug - Wrong data type: svcConfig svcConfig service.Config => svcConfig *service.Config (It needed to be a pointer)
2016-07-16 05:00:16 +08:00
select {
case sig := <-signals:
if sig == syscall.SIGHUP {
log.Printf("I! Reloading Telegraf config")
<-reload
reload <- true
Telegraf support for built-in windows service. Updated windows dependencies Updated the windows dependencies so that the versions matched the dependencies for Mac OS and Linux. Additionally added some that were complained about being missing at compile time. Incorporated kardianos/service for management Incorporated the library github.com/kardianos/service to manage the service on the various platforms (including Windows). This required an alternate main function. The original main function was renamed to reloadLoop (as that is what the main loop in it does) (it also got a couple of parameters). The service management library calls it as the main body of the program. Merged service.go into telegraf.go Due to compilation issues on Windows, moved the code from service.go into telegraf.go and removed service.go entirely. Updated dependencies and fixed Windows service Updated the dependencies so that it builds properly on Windows, additionally, fixed the registered command for starting it as a service (needed to add the config file option). This currently standardizes it as a C:\telegraf\telegraf.conf on Windows. Added dependency for github.com/kardianos/service Removed the common dependencies from _windows file Removed all the common dependencies from the Godeps_windows file and modified Makefile to load Godeps and then Godeps_windows when building for Windows. This should reduce problems caused by the Godeps_windows file being forgotten when updating dependencies. Updated CHANGELOG.md with changes Ran `go fmt ./...` to format code Removed service library on all but Windows The service library [kardianos/service](github.com/kardianos/service) has been disabled on all platforms but windows, as there is already existing infrastructure for other platforms. Removed the dependency line for itself It appears that gdm accidentally added the project itself to the dependency list. This caused the dependency restoration to select an earlier version of the project during build. This only affected windows. This only affected builds after 020b2c70 Updated documentation for Windows Service Removed the documentation about using NSSM and added documentation on installing telegraf directly as a Windows Service. Added license info for kardianos/service Added the license information for github.com/kardianos/service which is licensed under the ZLib license, although that name is never mentioned the license text matches word for word. Changed the Windows Config file default location Updated the default location of the configuration file on Windows from C:\telegraf\telegraf.conf to C:\Program Files\Telegraf\telegraf.conf. With this change includes updating the directions, including directing that the executable be put into that same directory. Additionally, as noted in the instructions, the location of the config file for the service may be changed by specifying the location with the `-config` flag at install time. Fixed bug - Wrong data type: svcConfig svcConfig service.Config => svcConfig *service.Config (It needed to be a pointer)
2016-07-16 05:00:16 +08:00
}
cancel()
case err := <-t.pprofErr:
2022-08-25 10:46:58 +08:00
log.Printf("E! pprof server failed: %v", err)
cancel()
Telegraf support for built-in windows service. Updated windows dependencies Updated the windows dependencies so that the versions matched the dependencies for Mac OS and Linux. Additionally added some that were complained about being missing at compile time. Incorporated kardianos/service for management Incorporated the library github.com/kardianos/service to manage the service on the various platforms (including Windows). This required an alternate main function. The original main function was renamed to reloadLoop (as that is what the main loop in it does) (it also got a couple of parameters). The service management library calls it as the main body of the program. Merged service.go into telegraf.go Due to compilation issues on Windows, moved the code from service.go into telegraf.go and removed service.go entirely. Updated dependencies and fixed Windows service Updated the dependencies so that it builds properly on Windows, additionally, fixed the registered command for starting it as a service (needed to add the config file option). This currently standardizes it as a C:\telegraf\telegraf.conf on Windows. Added dependency for github.com/kardianos/service Removed the common dependencies from _windows file Removed all the common dependencies from the Godeps_windows file and modified Makefile to load Godeps and then Godeps_windows when building for Windows. This should reduce problems caused by the Godeps_windows file being forgotten when updating dependencies. Updated CHANGELOG.md with changes Ran `go fmt ./...` to format code Removed service library on all but Windows The service library [kardianos/service](github.com/kardianos/service) has been disabled on all platforms but windows, as there is already existing infrastructure for other platforms. Removed the dependency line for itself It appears that gdm accidentally added the project itself to the dependency list. This caused the dependency restoration to select an earlier version of the project during build. This only affected windows. This only affected builds after 020b2c70 Updated documentation for Windows Service Removed the documentation about using NSSM and added documentation on installing telegraf directly as a Windows Service. Added license info for kardianos/service Added the license information for github.com/kardianos/service which is licensed under the ZLib license, although that name is never mentioned the license text matches word for word. Changed the Windows Config file default location Updated the default location of the configuration file on Windows from C:\telegraf\telegraf.conf to C:\Program Files\Telegraf\telegraf.conf. With this change includes updating the directions, including directing that the executable be put into that same directory. Additionally, as noted in the instructions, the location of the config file for the service may be changed by specifying the location with the `-config` flag at install time. Fixed bug - Wrong data type: svcConfig svcConfig service.Config => svcConfig *service.Config (It needed to be a pointer)
2016-07-16 05:00:16 +08:00
case <-stop:
cancel()
}
}()
err := t.runAgent(ctx, cfg)
if err != nil && err != context.Canceled {
2022-08-25 10:46:58 +08:00
return fmt.Errorf("[telegraf] Error running agent: %v", err)
}
}
2022-08-25 10:46:58 +08:00
return nil
}
func (t *Telegraf) watchLocalConfig(signals chan os.Signal, fConfig string) {
var mytomb tomb.Tomb
var watcher watch.FileWatcher
if t.watchConfig == "poll" {
watcher = watch.NewPollingFileWatcher(fConfig)
} else {
watcher = watch.NewInotifyFileWatcher(fConfig)
}
changes, err := watcher.ChangeEvents(&mytomb, 0)
if err != nil {
log.Printf("E! Error watching config: %s\n", err)
return
}
log.Println("I! Config watcher started")
select {
case <-changes.Modified:
log.Println("I! Config file modified")
case <-changes.Deleted:
// deleted can mean moved. wait a bit a check existence
<-time.After(time.Second)
if _, err := os.Stat(fConfig); err == nil {
log.Println("I! Config file overwritten")
} else {
log.Println("W! Config file deleted")
if err := watcher.BlockUntilExists(&mytomb); err != nil {
log.Printf("E! Cannot watch for config: %s\n", err.Error())
return
}
log.Println("I! Config file appeared")
}
case <-changes.Truncated:
log.Println("I! Config file truncated")
case <-mytomb.Dying():
log.Println("I! Config watcher ended")
return
}
mytomb.Done()
signals <- syscall.SIGHUP
}
func (t *Telegraf) loadConfiguration() (*config.Config, error) {
// If no other options are specified, load the config file and run.
c := config.NewConfig()
c.OutputFilters = t.outputFilters
c.InputFilters = t.inputFilters
c.SecretStoreFilters = t.secretstoreFilters
var configFiles []string
configFiles = append(configFiles, t.config...)
for _, fConfigDirectory := range t.configDir {
files, err := config.WalkDirectory(fConfigDirectory)
if err != nil {
return c, err
}
configFiles = append(configFiles, files...)
}
// providing no "config" or "config-directory" flag(s) should load default
// configuration files
if len(configFiles) == 0 {
configFiles = append(configFiles, "")
}
t.configFiles = configFiles
if err := c.LoadAll(configFiles...); err != nil {
return c, err
}
return c, nil
}
func (t *Telegraf) runAgent(ctx context.Context, c *config.Config) error {
if !(t.test || t.testWait != 0) && len(c.Outputs) == 0 {
return errors.New("no outputs found, did you provide a valid config file?")
}
if t.plugindDir == "" && len(c.Inputs) == 0 {
return errors.New("no inputs found, did you provide a valid config file?")
}
if int64(c.Agent.Interval) <= 0 {
return fmt.Errorf("agent interval must be positive, found %v", c.Agent.Interval)
}
if int64(c.Agent.FlushInterval) <= 0 {
return fmt.Errorf("agent flush_interval must be positive; found %v", c.Agent.Interval)
}
// Setup logging as configured.
telegraf.Debug = c.Agent.Debug || t.debug
2019-05-04 01:25:28 +08:00
logConfig := logger.LogConfig{
Debug: telegraf.Debug,
Quiet: c.Agent.Quiet || t.quiet,
LogTarget: c.Agent.LogTarget,
Logfile: c.Agent.Logfile,
RotationInterval: c.Agent.LogfileRotationInterval,
RotationMaxSize: c.Agent.LogfileRotationMaxSize,
RotationMaxArchives: c.Agent.LogfileRotationMaxArchives,
LogWithTimezone: c.Agent.LogWithTimezone,
2019-05-04 01:25:28 +08:00
}
if err := logger.SetupLogging(logConfig); err != nil {
return err
}
2022-08-25 10:46:58 +08:00
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, %d secret-stores",
len(inputs.Inputs),
len(aggregators.Aggregators),
len(processors.Processors),
len(parsers.Parsers),
len(outputs.Outputs),
len(secretstores.SecretStores),
)
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(), " "))
log.Printf("I! Loaded secretstores: %s", strings.Join(c.SecretstoreNames(), " "))
if !t.once && (t.test || t.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(), " "))
}
log.Printf("I! Tags enabled: %s", c.ListTags())
if count, found := c.Deprecations["inputs"]; found && (count[0] > 0 || count[1] > 0) {
log.Printf("W! Deprecated inputs: %d and %d options", count[0], count[1])
}
if count, found := c.Deprecations["aggregators"]; found && (count[0] > 0 || count[1] > 0) {
log.Printf("W! Deprecated aggregators: %d and %d options", count[0], count[1])
}
if count, found := c.Deprecations["processors"]; found && (count[0] > 0 || count[1] > 0) {
log.Printf("W! Deprecated processors: %d and %d options", count[0], count[1])
}
if count, found := c.Deprecations["outputs"]; found && (count[0] > 0 || count[1] > 0) {
log.Printf("W! Deprecated outputs: %d and %d options", count[0], count[1])
}
if count, found := c.Deprecations["secretstores"]; found && (count[0] > 0 || count[1] > 0) {
log.Printf("W! Deprecated secretstores: %d and %d options", count[0], count[1])
}
ag := agent.NewAgent(c)
// Notify systemd that telegraf is ready
// SdNotify() only tries to notify if the NOTIFY_SOCKET environment is set, so it's safe to call when systemd isn't present.
// Ignore the return values here because they're not valid for platforms that don't use systemd.
// For platforms that use systemd, telegraf doesn't log if the notification failed.
_, _ = daemon.SdNotify(false, daemon.SdNotifyReady)
if t.once {
wait := time.Duration(t.testWait) * time.Second
return ag.Once(ctx, wait)
}
if t.test || t.testWait != 0 {
wait := time.Duration(t.testWait) * time.Second
return ag.Test(ctx, wait)
}
if t.pidFile != "" {
f, err := os.OpenFile(t.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())
2022-08-25 10:46:58 +08:00
err = f.Close()
if err != nil {
return err
}
defer func() {
err := os.Remove(t.pidFile)
if err != nil {
log.Printf("E! Unable to remove pidfile: %s", err)
}
}()
}
}
return ag.Run(ctx)
}