2015-04-01 16:34:32 +00:00
package main
import (
2018-11-05 21:34:28 +00:00
"context"
"errors"
2015-04-01 16:34:32 +00:00
"flag"
2015-04-07 16:24:34 +00:00
"fmt"
2015-04-01 16:34:32 +00:00
"log"
2017-03-30 01:28:43 +00:00
"net/http"
_ "net/http/pprof" // Comment this line to disable pprof endpoint.
2015-04-01 16:34:32 +00:00
"os"
"os/signal"
2019-12-17 20:44:17 +00:00
"sort"
2015-04-01 16:34:32 +00:00
"strings"
2016-01-17 08:08:02 +00:00
"syscall"
2019-06-14 19:06:25 +00:00
"time"
2015-04-01 16:34:32 +00:00
2016-01-27 21:21:36 +00:00
"github.com/influxdata/telegraf/agent"
2020-05-04 18:09:10 +00:00
"github.com/influxdata/telegraf/config"
2018-05-04 21:16:21 +00:00
"github.com/influxdata/telegraf/internal"
2019-09-20 23:50:19 +00:00
"github.com/influxdata/telegraf/internal/goplugin"
2016-09-30 21:37:56 +00:00
"github.com/influxdata/telegraf/logger"
2016-10-03 17:49:30 +00:00
_ "github.com/influxdata/telegraf/plugins/aggregators/all"
2016-03-03 16:09:49 +00:00
"github.com/influxdata/telegraf/plugins/inputs"
2016-01-20 18:57:35 +00:00
_ "github.com/influxdata/telegraf/plugins/inputs/all"
2016-03-06 12:08:51 +00:00
"github.com/influxdata/telegraf/plugins/outputs"
2016-01-20 18:57:35 +00:00
_ "github.com/influxdata/telegraf/plugins/outputs/all"
2016-09-08 14:22:10 +00:00
_ "github.com/influxdata/telegraf/plugins/processors/all"
2015-04-01 16:34:32 +00:00
)
2020-04-20 17:49:10 +00:00
// If you update these, update usage.go and usage_windows.go
2015-08-24 20:52:46 +00:00
var fDebug = flag . Bool ( "debug" , false ,
2016-09-30 21:37:56 +00:00
"turn on debug logging" )
2017-03-30 01:28:43 +00:00
var pprofAddr = flag . String ( "pprof-addr" , "" ,
"pprof address to listen on, not activate pprof if empty" )
2016-01-15 19:25:56 +00:00
var fQuiet = flag . Bool ( "quiet" , false ,
"run in quiet mode" )
2020-04-20 17:49:10 +00:00
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" )
2019-06-14 19:06:25 +00:00
var fTestWait = flag . Int ( "test-wait" , 0 , "wait up to this many seconds for service inputs to complete in test mode" )
2015-04-01 16:34:32 +00:00
var fConfig = flag . String ( "config" , "" , "configuration file to load" )
2016-01-07 20:39:43 +00:00
var fConfigDirectory = flag . String ( "config-directory" , "" ,
2015-11-25 21:30:54 +00:00
"directory containing additional *.conf files" )
2018-09-10 18:53:04 +00:00
var fVersion = flag . Bool ( "version" , false , "display the version and exit" )
2015-08-24 20:52:46 +00:00
var fSampleConfig = flag . Bool ( "sample-config" , false ,
"print out full sample configuration" )
2015-06-18 18:31:16 +00:00
var fPidfile = flag . String ( "pidfile" , "" , "file to write our pid to" )
2019-04-26 03:34:40 +00:00
var fSectionFilters = flag . String ( "section-filter" , "" ,
"filter the sections to print, separator is ':'. Valid values are 'agent', 'global_tags', 'outputs', 'processors', 'aggregators' and 'inputs'" )
2016-01-07 20:39:43 +00:00
var fInputFilters = flag . String ( "input-filter" , "" ,
2016-01-17 22:32:24 +00:00
"filter the inputs to enable, separator is :" )
2016-03-07 10:42:01 +00:00
var fInputList = flag . Bool ( "input-list" , false ,
2016-03-18 02:06:44 +00:00
"print available input plugins." )
2016-01-07 20:39:43 +00:00
var fOutputFilters = flag . String ( "output-filter" , "" ,
2015-09-22 01:38:57 +00:00
"filter the outputs to enable, separator is :" )
2016-03-06 12:08:51 +00:00
var fOutputList = flag . Bool ( "output-list" , false ,
2016-03-07 10:42:01 +00:00
"print available output plugins." )
2016-10-05 09:58:30 +00:00
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 :" )
2015-08-24 20:52:46 +00:00
var fUsage = flag . String ( "usage" , "" ,
2017-08-11 23:26:00 +00:00
"print usage for a plugin, ie, 'telegraf --usage mysql'" )
2016-08-08 14:55:16 +00:00
var fService = flag . String ( "service" , "" ,
2018-09-10 18:53:04 +00:00
"operate on the service (windows only)" )
2018-09-28 01:41:24 +00:00
var fServiceName = flag . String ( "service-name" , "telegraf" , "service name (windows only)" )
2019-05-01 01:34:19 +00:00
var fServiceDisplayName = flag . String ( "service-display-name" , "Telegraf Data Collector Service" , "service display name (windows only)" )
2018-01-25 23:04:09 +00:00
var fRunAsConsole = flag . Bool ( "console" , false , "run as console application (windows only)" )
2019-07-30 04:34:03 +00:00
var fPlugins = flag . String ( "plugin-directory" , "" ,
"path to directory containing external plugins" )
2016-01-07 22:21:10 +00:00
2016-05-02 23:22:28 +00:00
var (
2018-08-12 23:52:35 +00:00
version string
commit string
branch string
2016-05-02 23:22:28 +00:00
)
2015-04-01 16:34:32 +00:00
2016-07-15 21:00:16 +00:00
var stop chan struct { }
2017-02-01 17:14:47 +00:00
func reloadLoop (
inputFilters [ ] string ,
outputFilters [ ] string ,
aggregatorFilters [ ] string ,
processorFilters [ ] string ,
) {
2016-01-17 08:08:02 +00:00
reload := make ( chan bool , 1 )
reload <- true
for <- reload {
reload <- false
2016-07-15 21:00:16 +00:00
2018-11-05 21:34:28 +00:00
ctx , cancel := context . WithCancel ( context . Background ( ) )
2015-04-07 00:24:24 +00:00
2020-04-20 17:49:10 +00:00
signals := make ( chan os . Signal , 1 )
2018-11-15 23:44:36 +00:00
signal . Notify ( signals , os . Interrupt , syscall . SIGHUP ,
syscall . SIGTERM , syscall . SIGINT )
2016-01-17 08:08:02 +00:00
go func ( ) {
2016-07-15 21:00:16 +00:00
select {
case sig := <- signals :
2016-08-08 14:55:16 +00:00
if sig == syscall . SIGHUP {
2018-11-05 21:34:28 +00:00
log . Printf ( "I! Reloading Telegraf config" )
2016-08-08 14:55:16 +00:00
<- reload
reload <- true
2016-07-15 21:00:16 +00:00
}
2018-11-05 21:34:28 +00:00
cancel ( )
2016-07-15 21:00:16 +00:00
case <- stop :
2018-11-05 21:34:28 +00:00
cancel ( )
2016-01-17 08:08:02 +00:00
}
} ( )
2015-04-07 00:24:24 +00:00
2018-11-05 21:34:28 +00:00
err := runAgent ( ctx , inputFilters , outputFilters )
2019-05-31 23:50:44 +00:00
if err != nil && err != context . Canceled {
2018-11-05 21:34:28 +00:00
log . Fatalf ( "E! [telegraf] Error running agent: %v" , err )
}
}
}
func runAgent ( ctx context . Context ,
inputFilters [ ] string ,
outputFilters [ ] string ,
) error {
2018-11-15 23:45:56 +00:00
log . Printf ( "I! Starting Telegraf %s" , version )
2018-11-05 21:34:28 +00:00
// If no other options are specified, load the config file and run.
c := config . NewConfig ( )
c . OutputFilters = outputFilters
c . InputFilters = inputFilters
err := c . LoadConfig ( * fConfig )
if err != nil {
return err
}
if * fConfigDirectory != "" {
err = c . LoadDirectory ( * fConfigDirectory )
if err != nil {
return err
2016-01-17 08:08:02 +00:00
}
2018-11-05 21:34:28 +00:00
}
if ! * fTest && len ( c . Outputs ) == 0 {
return errors . New ( "Error: no outputs found, did you provide a valid config file?" )
}
2019-07-30 04:34:03 +00:00
if * fPlugins == "" && len ( c . Inputs ) == 0 {
2018-11-05 21:34:28 +00:00
return errors . New ( "Error: no inputs found, did you provide a valid config file?" )
}
if int64 ( c . Agent . Interval . Duration ) <= 0 {
return fmt . Errorf ( "Agent interval must be positive, found %s" ,
c . Agent . Interval . Duration )
}
if int64 ( c . Agent . FlushInterval . Duration ) <= 0 {
return fmt . Errorf ( "Agent flush_interval must be positive; found %s" ,
c . Agent . Interval . Duration )
}
2016-01-17 08:08:02 +00:00
2018-11-05 21:34:28 +00:00
ag , err := agent . NewAgent ( c )
if err != nil {
return err
2016-01-17 08:08:02 +00:00
}
2018-11-05 21:34:28 +00:00
2018-11-15 23:45:56 +00:00
// Setup logging as configured.
2019-05-03 17:25:28 +00:00
logConfig := logger . LogConfig {
Debug : ag . Config . Agent . Debug || * fDebug ,
Quiet : ag . Config . Agent . Quiet || * fQuiet ,
2019-08-28 21:34:44 +00:00
LogTarget : ag . Config . Agent . LogTarget ,
2019-05-03 17:25:28 +00:00
Logfile : ag . Config . Agent . Logfile ,
RotationInterval : ag . Config . Agent . LogfileRotationInterval ,
RotationMaxSize : ag . Config . Agent . LogfileRotationMaxSize ,
RotationMaxArchives : ag . Config . Agent . LogfileRotationMaxArchives ,
}
logger . SetupLogging ( logConfig )
2018-11-05 21:34:28 +00:00
2019-06-14 19:06:25 +00:00
if * fTest || * fTestWait != 0 {
testWaitDuration := time . Duration ( * fTestWait ) * time . Second
return ag . Test ( ctx , testWaitDuration )
2018-11-05 21:34:28 +00:00
}
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 outputs: %s" , strings . Join ( c . OutputNames ( ) , " " ) )
log . Printf ( "I! Tags enabled: %s" , c . ListTags ( ) )
if * fPidfile != "" {
f , err := os . OpenFile ( * fPidfile , 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 ( ) )
f . Close ( )
defer func ( ) {
err := os . Remove ( * fPidfile )
if err != nil {
log . Printf ( "E! Unable to remove pidfile: %s" , err )
}
} ( )
}
}
return ag . Run ( ctx )
2015-04-01 16:34:32 +00:00
}
2016-01-07 20:39:43 +00:00
2016-02-02 00:44:19 +00:00
func usageExit ( rc int ) {
2018-05-04 21:16:21 +00:00
fmt . Println ( internal . Usage )
2016-02-02 00:44:19 +00:00
os . Exit ( rc )
2016-01-07 20:39:43 +00:00
}
2016-07-15 21:00:16 +00:00
2018-08-12 23:52:35 +00:00
func formatFullVersion ( ) string {
var parts = [ ] string { "Telegraf" }
if version != "" {
parts = append ( parts , version )
} else {
parts = append ( parts , "unknown" )
2017-06-27 20:24:06 +00:00
}
2018-08-12 23:52:35 +00:00
if branch != "" || commit != "" {
if branch == "" {
branch = "unknown"
}
if commit == "" {
commit = "unknown"
}
git := fmt . Sprintf ( "(git: %s %s)" , branch , commit )
parts = append ( parts , git )
}
return strings . Join ( parts , " " )
2017-06-27 20:24:06 +00:00
}
2016-07-15 21:00:16 +00:00
func main ( ) {
2016-10-05 12:53:43 +00:00
flag . Usage = func ( ) { usageExit ( 0 ) }
2016-09-30 21:37:56 +00:00
flag . Parse ( )
2017-02-01 17:14:47 +00:00
args := flag . Args ( )
2019-04-26 03:34:40 +00:00
sectionFilters , inputFilters , outputFilters := [ ] string { } , [ ] string { } , [ ] string { }
if * fSectionFilters != "" {
sectionFilters = strings . Split ( ":" + strings . TrimSpace ( * fSectionFilters ) + ":" , ":" )
}
2017-02-01 17:14:47 +00:00
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 ) + ":" , ":" )
}
2019-07-30 04:47:49 +00:00
logger . SetupLogging ( logger . LogConfig { } )
2019-07-30 04:34:03 +00:00
// Load external plugins, if requested.
if * fPlugins != "" {
2019-07-30 04:47:49 +00:00
log . Printf ( "I! Loading external plugins from: %s" , * fPlugins )
2019-09-20 23:50:19 +00:00
if err := goplugin . LoadExternalPlugins ( * fPlugins ) ; err != nil {
2019-07-30 04:47:49 +00:00
log . Fatal ( "E! " + err . Error ( ) )
2019-07-30 04:34:03 +00:00
}
}
2017-03-30 01:28:43 +00:00
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 ( ) )
}
} ( )
}
2017-02-01 17:14:47 +00:00
if len ( args ) > 0 {
switch args [ 0 ] {
case "version" :
2018-08-12 23:52:35 +00:00
fmt . Println ( formatFullVersion ( ) )
2017-02-01 17:14:47 +00:00
return
case "config" :
config . PrintSampleConfig (
2019-04-26 03:34:40 +00:00
sectionFilters ,
2017-02-01 17:14:47 +00:00
inputFilters ,
outputFilters ,
aggregatorFilters ,
processorFilters ,
)
return
}
}
// switch for flags which just do something and exit immediately
switch {
case * fOutputList :
2019-12-17 20:44:17 +00:00
fmt . Println ( "Available Output Plugins: " )
names := make ( [ ] string , 0 , len ( outputs . Outputs ) )
2018-10-19 20:32:54 +00:00
for k := range outputs . Outputs {
2019-12-17 20:44:17 +00:00
names = append ( names , k )
}
sort . Strings ( names )
for _ , k := range names {
2017-02-01 17:14:47 +00:00
fmt . Printf ( " %s\n" , k )
}
return
case * fInputList :
fmt . Println ( "Available Input Plugins:" )
2019-12-17 20:44:17 +00:00
names := make ( [ ] string , 0 , len ( inputs . Inputs ) )
2018-10-19 20:32:54 +00:00
for k := range inputs . Inputs {
2019-12-17 20:44:17 +00:00
names = append ( names , k )
}
sort . Strings ( names )
for _ , k := range names {
2017-02-01 17:14:47 +00:00
fmt . Printf ( " %s\n" , k )
}
return
case * fVersion :
2018-08-12 23:52:35 +00:00
fmt . Println ( formatFullVersion ( ) )
2017-02-01 17:14:47 +00:00
return
case * fSampleConfig :
config . PrintSampleConfig (
2019-04-26 03:34:40 +00:00
sectionFilters ,
2017-02-01 17:14:47 +00:00
inputFilters ,
outputFilters ,
aggregatorFilters ,
processorFilters ,
)
return
case * fUsage != "" :
err := config . PrintInputConfig ( * fUsage )
err2 := config . PrintOutputConfig ( * fUsage )
if err != nil && err2 != nil {
log . Fatalf ( "E! %s and %s" , err , err2 )
}
return
}
2018-10-09 20:45:07 +00:00
shortVersion := version
if shortVersion == "" {
shortVersion = "unknown"
}
// Configure version
if err := internal . SetVersion ( shortVersion ) ; err != nil {
log . Println ( "Telegraf version already configured to: " + internal . Version ( ) )
}
2020-04-20 17:49:10 +00:00
run (
inputFilters ,
outputFilters ,
aggregatorFilters ,
processorFilters ,
)
2019-03-27 01:17:27 +00:00
}