1
0
Fork 0
cpu_ctrl/bootstrap.go

199 lines
4.7 KiB
Go

package main // import "amuz.es/src/infra/cpu_ctrl"
import (
"os"
"os/signal"
"syscall"
"fmt"
zlog "amuz.es/src/infra/goutils/logger/zap"
"go.uber.org/zap/zapcore"
"go.uber.org/multierr"
"amuz.es/src/infra/goutils/logger/rotater"
"amuz.es/src/infra/goutils/handler"
"amuz.es/src/infra/cpu_ctrl/daemon"
"amuz.es/src/infra/cpu_ctrl/producer"
"amuz.es/src/infra/cpu_ctrl/consumer"
"go.uber.org/zap"
"errors"
)
func finalCloser() {
if err := recover(); err != nil {
fmt.Fprintln(os.Stderr, err.(error).Error())
os.Exit(1)
}
}
// 로그 초기화
func initLogger() func() {
// 로깅설정
formatter := zapcore.NewConsoleEncoder(zlog.LogCommonFormat)
level := zap.InfoLevel
if *verbose {
level = zap.DebugLevel
}
// 전역 로거 초기화
var err error
logger, err = zlog.Init(
true,
formatter,
name,
"Stderr",
"",
nil,
level,
)
if err != nil {
panic(err)
}
// 로깅종료 및 exitcode 설정
return func() {}
}
// 애플리케이션이 종료를 위해 대기하는 부분
func initContext(handler *handler.Handler) (func(), func()) {
exitSignal := make(chan os.Signal, 1)
// return waiter
return func() {
daemon.NotifyDaemon(daemon.DaemonStarted)
// 시그널 처리
signal.Notify(exitSignal, syscall.SIGINT, syscall.SIGTERM, syscall.SIGUSR1)
for {
select {
case <-handler.Done():
logger.Info("self destruct to close this application")
return
case initialErr := <-handler.Error():
// 복구불가능한 에러(들) 모아서 넘겨주는 부분
merged := initialErr
logger.Error("main: ", initialErr)
for {
select {
case anotherErr := <-handler.Error():
merged = multierr.Append(merged, anotherErr)
logger.Error("main: ", anotherErr)
default:
// panic을 발생시켜 컨텍스트를 에러를 전달한다.
panic(merged)
}
}
case sysSignal := <-exitSignal:
//handle signal
switch sysSignal {
case syscall.SIGUSR1:
rotater.Rotate()
default:
logger.Info(sysSignal.String(), " received")
return
}
}
}
}, // return closer
func() {
daemon.NotifyDaemon(daemon.DaemonStopping)
logger.Info("main: main context waiting..")
// http 서버 기다린다.
handler.GracefulWait()
close(exitSignal)
}
}
// 메인 웹서버 초기화
func initProcessor(handler *handler.Handler) func() {
FanoutOsMetricInfo := func(sender <-chan producer.OSMetricInfo, receivers ...chan<- producer.OSMetricInfo) {
defer func() {
for _, receiver := range receivers {
close(receiver)
}
if err := recover(); err != nil {
handler.NotifyError(err.(error))
}
}()
for metric := range sender {
for _, receiver := range receivers {
select {
case receiver <- metric:
default:
logger.Warn("Some OSMetricInfo consumer blocked!")
}
}
}
}
FanoutSpeed := func(sender <-chan producer.FanspeedInfo, receivers ...chan<- producer.FanspeedInfo) {
defer func() {
for _, receiver := range receivers {
close(receiver)
}
if err := recover(); err != nil {
handler.NotifyError(err.(error))
}
}()
for speed := range sender {
for _, receiver := range receivers {
select {
case receiver <- speed:
default:
logger.Warn("Some Fanspeed consumer blocked!")
}
}
}
}
FanoutTempeture := func(sender <-chan producer.TempetureInfo, receivers ...chan<- producer.TempetureInfo) {
defer func() {
for _, receiver := range receivers {
close(receiver)
}
if err := recover(); err != nil {
handler.NotifyError(err.(error))
}
}()
for tempeture := range sender {
for _, receiver := range receivers {
select {
case receiver <- tempeture:
default:
logger.Warn("Some Tempeture consumer blocked!")
}
}
}
}
processorCount := producer.GetProcessorCount()
if processorCount == 0 {
panic(errors.New("cpu not found!"))
}
osMetricInfoChan := producer.NewOsMetric(
handler,
*SampleInterval,
)
tempetureInfoChan, fanspeedChan := producer.AggregateProcessorChannel(
handler,
*SampleInterval, processorCount,
*P, *I, *D,
*SetPoint,
)
simpleLogger := consumer.NewSampleOSLogger(*SampleInterval, handler)
fanController := consumer.NewFanControl(processorCount, *SampleInterval, handler)
metricLogger := consumer.NewInfluxMetric((*InfluxHost).String(), processorCount, handler)
handler.IncreaseWait()
go simpleLogger.StartControl()
handler.IncreaseWait()
go fanController.StartControl()
handler.IncreaseWait()
go metricLogger.StartLogging()
go FanoutOsMetricInfo(osMetricInfoChan, simpleLogger.Consumer())
go FanoutTempeture(tempetureInfoChan, metricLogger.TempetureConsumer())
go FanoutSpeed(fanspeedChan, fanController.Consumer(), metricLogger.FanSpeedConsumer())
return func() {}
}