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 FanoutOsMetricInfo(osMetricInfoChan, simpleLogger.Consumer(), metricLogger.OsMetricConsumer()) go FanoutOsMetricInfo(osMetricInfoChan, metricLogger.OsMetricConsumer()) go FanoutTempeture(tempetureInfoChan, metricLogger.TempetureConsumer()) go FanoutSpeed(fanspeedChan, fanController.Consumer(), metricLogger.FanSpeedConsumer()) return func() {} }