Use two separate inputs for metric router to simplify management. Activate --logfile option and close MultiChanTicker explicitly

This commit is contained in:
Thomas Roehl 2022-01-26 17:08:53 +01:00
parent 3fd77e6887
commit 5600cf1f5f
3 changed files with 87 additions and 43 deletions

View File

@ -28,19 +28,22 @@ type metricRouterConfig struct {
} }
type metricRouter struct { type metricRouter struct {
inputs []chan lp.CCMetric // List of all input channels coll_input chan lp.CCMetric // Input channel from CollectorManager
outputs []chan lp.CCMetric // List of all output channels recv_input chan lp.CCMetric // Input channel from ReceiveManager
done chan bool // channel to finish / stop metric router outputs []chan lp.CCMetric // List of all output channels
wg *sync.WaitGroup done chan bool // channel to finish / stop metric router
timestamp time.Time // timestamp wg *sync.WaitGroup
ticker mct.MultiChanTicker timestamp time.Time // timestamp
config metricRouterConfig timerdone chan bool // channel to finish / stop timestamp updater
ticker mct.MultiChanTicker
config metricRouterConfig
} }
// MetricRouter access functions // MetricRouter access functions
type MetricRouter interface { type MetricRouter interface {
Init(ticker mct.MultiChanTicker, wg *sync.WaitGroup, routerConfigFile string) error Init(ticker mct.MultiChanTicker, wg *sync.WaitGroup, routerConfigFile string) error
AddInput(input chan lp.CCMetric) AddCollectorInput(input chan lp.CCMetric)
AddReceiverInput(input chan lp.CCMetric)
AddOutput(output chan lp.CCMetric) AddOutput(output chan lp.CCMetric)
Start() Start()
Close() Close()
@ -53,7 +56,6 @@ type MetricRouter interface {
// * ticker (from variable ticker) // * ticker (from variable ticker)
// * configuration (read from config file in variable routerConfigFile) // * configuration (read from config file in variable routerConfigFile)
func (r *metricRouter) Init(ticker mct.MultiChanTicker, wg *sync.WaitGroup, routerConfigFile string) error { func (r *metricRouter) Init(ticker mct.MultiChanTicker, wg *sync.WaitGroup, routerConfigFile string) error {
r.inputs = make([]chan lp.CCMetric, 0)
r.outputs = make([]chan lp.CCMetric, 0) r.outputs = make([]chan lp.CCMetric, 0)
r.done = make(chan bool) r.done = make(chan bool)
r.wg = wg r.wg = wg
@ -77,12 +79,19 @@ func (r *metricRouter) Init(ticker mct.MultiChanTicker, wg *sync.WaitGroup, rout
func (r *metricRouter) StartTimer() { func (r *metricRouter) StartTimer() {
m := make(chan time.Time) m := make(chan time.Time)
r.ticker.AddChannel(m) r.ticker.AddChannel(m)
r.timerdone = make(chan bool)
go func() { go func() {
for { for {
t := <-m select {
r.timestamp = t case <-r.timerdone:
cclog.ComponentDebug("MetricRouter", "TIMER DONE")
return
case t := <-m:
r.timestamp = t
}
} }
}() }()
cclog.ComponentDebug("MetricRouter", "TIMER START")
} }
// EvalCondition evaluates condition Cond for metric data from point // EvalCondition evaluates condition Cond for metric data from point
@ -165,35 +174,35 @@ func (r *metricRouter) Start() {
if r.config.IntervalStamp { if r.config.IntervalStamp {
r.StartTimer() r.StartTimer()
} }
done := func() {
r.wg.Done()
cclog.ComponentDebug("MetricRouter", "DONE")
}
forward := func(point lp.CCMetric) {
cclog.ComponentDebug("MetricRouter", "FORWARD", point)
r.DoAddTags(point)
r.DoDelTags(point)
for _, o := range r.outputs {
o <- point
}
}
go func() { go func() {
for { for {
RouterLoop: // RouterLoop:
select { select {
case <-r.done: case <-r.done:
cclog.ComponentDebug("MetricRouter", "DONE") done()
r.wg.Done() return
break RouterLoop case p := <-r.coll_input:
default: if r.config.IntervalStamp {
for _, c := range r.inputs { p.SetTime(r.timestamp)
RouterInputLoop:
select {
case <-r.done:
cclog.ComponentDebug("MetricRouter", "DONE")
r.wg.Done()
break RouterInputLoop
case p := <-c:
cclog.ComponentDebug("MetricRouter", "FORWARD", p)
r.DoAddTags(p)
r.DoDelTags(p)
if r.config.IntervalStamp {
p.SetTime(r.timestamp)
}
for _, o := range r.outputs {
o <- p
}
default:
}
} }
forward(p)
case p := <-r.recv_input:
if r.config.IntervalStamp {
p.SetTime(r.timestamp)
}
forward(p)
} }
} }
}() }()
@ -201,8 +210,12 @@ func (r *metricRouter) Start() {
} }
// AddInput adds a input channel to the metric router // AddInput adds a input channel to the metric router
func (r *metricRouter) AddInput(input chan lp.CCMetric) { func (r *metricRouter) AddCollectorInput(input chan lp.CCMetric) {
r.inputs = append(r.inputs, input) r.coll_input = input
}
func (r *metricRouter) AddReceiverInput(input chan lp.CCMetric) {
r.recv_input = input
} }
// AddOutput adds a output channel to the metric router // AddOutput adds a output channel to the metric router
@ -212,7 +225,17 @@ func (r *metricRouter) AddOutput(output chan lp.CCMetric) {
// Close finishes / stops the metric router // Close finishes / stops the metric router
func (r *metricRouter) Close() { func (r *metricRouter) Close() {
r.done <- true select {
case r.done <- true:
default:
}
if r.config.IntervalStamp {
cclog.ComponentDebug("MetricRouter", "TIMER CLOSE")
select {
case r.timerdone <- true:
default:
}
}
cclog.ComponentDebug("MetricRouter", "CLOSE") cclog.ComponentDebug("MetricRouter", "CLOSE")
} }

View File

@ -1,27 +1,43 @@
package multiChanTicker package multiChanTicker
import ( import (
cclog "github.com/ClusterCockpit/cc-metric-collector/internal/ccLogger"
"time" "time"
) )
type multiChanTicker struct { type multiChanTicker struct {
ticker *time.Ticker ticker *time.Ticker
channels []chan time.Time channels []chan time.Time
done chan bool
} }
type MultiChanTicker interface { type MultiChanTicker interface {
Init(duration time.Duration) Init(duration time.Duration)
AddChannel(chan time.Time) AddChannel(chan time.Time)
Close()
} }
func (t *multiChanTicker) Init(duration time.Duration) { func (t *multiChanTicker) Init(duration time.Duration) {
t.ticker = time.NewTicker(duration) t.ticker = time.NewTicker(duration)
t.done = make(chan bool)
go func() { go func() {
done := func() {
cclog.ComponentDebug("MultiChanTicker", "DONE")
}
for { for {
select { select {
case <-t.done:
done()
return
case ts := <-t.ticker.C: case ts := <-t.ticker.C:
cclog.ComponentDebug("MultiChanTicker", "Tick", ts)
for _, c := range t.channels { for _, c := range t.channels {
c <- ts select {
case <-t.done:
done()
return
case c <- ts:
}
} }
} }
} }
@ -32,6 +48,11 @@ func (t *multiChanTicker) AddChannel(channel chan time.Time) {
t.channels = append(t.channels, channel) t.channels = append(t.channels, channel)
} }
func (t *multiChanTicker) Close() {
t.done <- true
cclog.ComponentDebug("MultiChanTicker", "CLOSE")
}
func NewTicker(duration time.Duration) MultiChanTicker { func NewTicker(duration time.Duration) MultiChanTicker {
t := &multiChanTicker{} t := &multiChanTicker{}
t.Init(duration) t.Init(duration)

View File

@ -3,7 +3,6 @@ package main
import ( import (
"encoding/json" "encoding/json"
"flag" "flag"
// "log"
"os" "os"
"os/signal" "os/signal"
"strings" "strings"
@ -158,6 +157,7 @@ func ReadCli() map[string]string {
// General shutdown function that gets executed in case of interrupt or graceful shutdown // General shutdown function that gets executed in case of interrupt or graceful shutdown
func shutdown(config *RuntimeConfig) { func shutdown(config *RuntimeConfig) {
cclog.Info("Shutdown...") cclog.Info("Shutdown...")
config.Ticker.Close()
if config.CollectManager != nil { if config.CollectManager != nil {
cclog.Debug("Shutdown CollectManager...") cclog.Debug("Shutdown CollectManager...")
config.CollectManager.Close() config.CollectManager.Close()
@ -228,7 +228,7 @@ func mainFunc() int {
// err = CreatePidfile(rcfg.CliArgs["pidfile"]) // err = CreatePidfile(rcfg.CliArgs["pidfile"])
if rcfg.CliArgs["logfile"] != "stderr" { if rcfg.CliArgs["logfile"] != "stderr" {
cclog.SetOutput(rcfg.CliArgs["logfile"]) cclog.SetOutput(rcfg.CliArgs["logfile"])
} }
// err = SetLogging(rcfg.CliArgs["logfile"]) // err = SetLogging(rcfg.CliArgs["logfile"])
// if err != nil { // if err != nil {
@ -261,7 +261,7 @@ func mainFunc() int {
} }
CollectToRouterChannel := make(chan lp.CCMetric) CollectToRouterChannel := make(chan lp.CCMetric)
rcfg.CollectManager.AddOutput(CollectToRouterChannel) rcfg.CollectManager.AddOutput(CollectToRouterChannel)
rcfg.Router.AddInput(CollectToRouterChannel) rcfg.Router.AddCollectorInput(CollectToRouterChannel)
} }
if len(rcfg.ConfigFile.ReceiverConfigFile) > 0 { if len(rcfg.ConfigFile.ReceiverConfigFile) > 0 {
rcfg.ReceiveManager, err = receivers.New(&rcfg.Sync, rcfg.ConfigFile.ReceiverConfigFile) rcfg.ReceiveManager, err = receivers.New(&rcfg.Sync, rcfg.ConfigFile.ReceiverConfigFile)
@ -271,7 +271,7 @@ func mainFunc() int {
} }
ReceiveToRouterChannel := make(chan lp.CCMetric) ReceiveToRouterChannel := make(chan lp.CCMetric)
rcfg.ReceiveManager.AddOutput(ReceiveToRouterChannel) rcfg.ReceiveManager.AddOutput(ReceiveToRouterChannel)
rcfg.Router.AddInput(ReceiveToRouterChannel) rcfg.Router.AddReceiverInput(ReceiveToRouterChannel)
use_recv = true use_recv = true
} }
prepare_shutdown(&rcfg) prepare_shutdown(&rcfg)