fix telegraf swallowing panics in --test mode

this defer function was causing telegraf to call os.Exit(0) instead of
panicking when it was supposed to.

closes #2341
This commit is contained in:
Cameron Sparr 2017-02-01 17:14:47 +00:00
parent 285be648c4
commit dfba3ff37a
No known key found for this signature in database
GPG Key ID: 19E67263DCB25D0F
2 changed files with 105 additions and 89 deletions

View File

@ -46,6 +46,7 @@ It is highly recommended that all users migrate to the new riemann output plugin
- [#2262](https://github.com/influxdata/telegraf/issues/2262): Flush jitter can inhibit metric collection. - [#2262](https://github.com/influxdata/telegraf/issues/2262): Flush jitter can inhibit metric collection.
- [#2287](https://github.com/influxdata/telegraf/issues/2287): Kubernetes input: Handle null startTime for stopped pods. - [#2287](https://github.com/influxdata/telegraf/issues/2287): Kubernetes input: Handle null startTime for stopped pods.
- [#2356](https://github.com/influxdata/telegraf/issues/2356): cpu input panic when /proc/stat is empty. - [#2356](https://github.com/influxdata/telegraf/issues/2356): cpu input panic when /proc/stat is empty.
- [#2341](https://github.com/influxdata/telegraf/issues/2341): telegraf swallowing panics in --test mode.
## v1.2.1 [2017-02-01] ## v1.2.1 [2017-02-01]

View File

@ -109,94 +109,17 @@ Examples:
var stop chan struct{} var stop chan struct{}
var srvc service.Service func reloadLoop(
stop chan struct{},
type program struct{} inputFilters []string,
outputFilters []string,
func reloadLoop(stop chan struct{}, s service.Service) { aggregatorFilters []string,
defer func() { processorFilters []string,
if service.Interactive() { ) {
os.Exit(0)
}
return
}()
reload := make(chan bool, 1) reload := make(chan bool, 1)
reload <- true reload <- true
for <-reload { for <-reload {
reload <- false reload <- false
flag.Parse()
args := flag.Args()
var inputFilters []string
if *fInputFilters != "" {
inputFilter := strings.TrimSpace(*fInputFilters)
inputFilters = strings.Split(":"+inputFilter+":", ":")
}
var outputFilters []string
if *fOutputFilters != "" {
outputFilter := strings.TrimSpace(*fOutputFilters)
outputFilters = strings.Split(":"+outputFilter+":", ":")
}
var aggregatorFilters []string
if *fAggregatorFilters != "" {
aggregatorFilter := strings.TrimSpace(*fAggregatorFilters)
aggregatorFilters = strings.Split(":"+aggregatorFilter+":", ":")
}
var processorFilters []string
if *fProcessorFilters != "" {
processorFilter := strings.TrimSpace(*fProcessorFilters)
processorFilters = strings.Split(":"+processorFilter+":", ":")
}
if len(args) > 0 {
switch args[0] {
case "version":
fmt.Printf("Telegraf v%s (git: %s %s)\n", version, branch, commit)
return
case "config":
config.PrintSampleConfig(
inputFilters,
outputFilters,
aggregatorFilters,
processorFilters,
)
return
}
}
// switch for flags which just do something and exit immediately
switch {
case *fOutputList:
fmt.Println("Available Output Plugins:")
for k, _ := range outputs.Outputs {
fmt.Printf(" %s\n", k)
}
return
case *fInputList:
fmt.Println("Available Input Plugins:")
for k, _ := range inputs.Inputs {
fmt.Printf(" %s\n", k)
}
return
case *fVersion:
fmt.Printf("Telegraf v%s (git: %s %s)\n", version, branch, commit)
return
case *fSampleConfig:
config.PrintSampleConfig(
inputFilters,
outputFilters,
aggregatorFilters,
processorFilters,
)
return
case *fUsage != "":
if err := config.PrintInputConfig(*fUsage); err != nil {
if err2 := config.PrintOutputConfig(*fUsage); err2 != nil {
log.Fatalf("E! %s and %s", err, err2)
}
}
return
}
// If no other options are specified, load the config file and run. // If no other options are specified, load the config file and run.
c := config.NewConfig() c := config.NewConfig()
@ -237,7 +160,7 @@ func reloadLoop(stop chan struct{}, s service.Service) {
if err != nil { if err != nil {
log.Fatal("E! " + err.Error()) log.Fatal("E! " + err.Error())
} }
return os.Exit(0)
} }
err = ag.Connect() err = ag.Connect()
@ -290,14 +213,26 @@ func usageExit(rc int) {
os.Exit(rc) os.Exit(rc)
} }
type program struct {
inputFilters []string
outputFilters []string
aggregatorFilters []string
processorFilters []string
}
func (p *program) Start(s service.Service) error { func (p *program) Start(s service.Service) error {
srvc = s
go p.run() go p.run()
return nil return nil
} }
func (p *program) run() { func (p *program) run() {
stop = make(chan struct{}) stop = make(chan struct{})
reloadLoop(stop, srvc) reloadLoop(
stop,
p.inputFilters,
p.outputFilters,
p.aggregatorFilters,
p.processorFilters,
)
} }
func (p *program) Stop(s service.Service) error { func (p *program) Stop(s service.Service) error {
close(stop) close(stop)
@ -307,6 +242,74 @@ func (p *program) Stop(s service.Service) error {
func main() { func main() {
flag.Usage = func() { usageExit(0) } flag.Usage = func() { usageExit(0) }
flag.Parse() flag.Parse()
args := flag.Args()
inputFilters, outputFilters := []string{}, []string{}
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)+":", ":")
}
if len(args) > 0 {
switch args[0] {
case "version":
fmt.Printf("Telegraf v%s (git: %s %s)\n", version, branch, commit)
return
case "config":
config.PrintSampleConfig(
inputFilters,
outputFilters,
aggregatorFilters,
processorFilters,
)
return
}
}
// switch for flags which just do something and exit immediately
switch {
case *fOutputList:
fmt.Println("Available Output Plugins:")
for k, _ := range outputs.Outputs {
fmt.Printf(" %s\n", k)
}
return
case *fInputList:
fmt.Println("Available Input Plugins:")
for k, _ := range inputs.Inputs {
fmt.Printf(" %s\n", k)
}
return
case *fVersion:
fmt.Printf("Telegraf v%s (git: %s %s)\n", version, branch, commit)
return
case *fSampleConfig:
config.PrintSampleConfig(
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
}
if runtime.GOOS == "windows" { if runtime.GOOS == "windows" {
svcConfig := &service.Config{ svcConfig := &service.Config{
Name: "telegraf", Name: "telegraf",
@ -316,7 +319,12 @@ func main() {
Arguments: []string{"-config", "C:\\Program Files\\Telegraf\\telegraf.conf"}, Arguments: []string{"-config", "C:\\Program Files\\Telegraf\\telegraf.conf"},
} }
prg := &program{} prg := &program{
inputFilters: inputFilters,
outputFilters: outputFilters,
aggregatorFilters: aggregatorFilters,
processorFilters: processorFilters,
}
s, err := service.New(prg, svcConfig) s, err := service.New(prg, svcConfig)
if err != nil { if err != nil {
log.Fatal("E! " + err.Error()) log.Fatal("E! " + err.Error())
@ -334,6 +342,7 @@ func main() {
if err != nil { if err != nil {
log.Fatal("E! " + err.Error()) log.Fatal("E! " + err.Error())
} }
os.Exit(0)
} else { } else {
err = s.Run() err = s.Run()
if err != nil { if err != nil {
@ -342,6 +351,12 @@ func main() {
} }
} else { } else {
stop = make(chan struct{}) stop = make(chan struct{})
reloadLoop(stop, nil) reloadLoop(
stop,
inputFilters,
outputFilters,
aggregatorFilters,
processorFilters,
)
} }
} }