package main import ( "os" "os/signal" "runtime" "syscall" "time" "amuz.es/gogs/infra/changer/http" "amuz.es/gogs/infra/changer/util" "gopkg.in/alecthomas/kingpin.v2" ) var ( app = kingpin.New(util.Config.Name(), "Inhouse internal user mgnt server").Author("Sangbum Kim") verbose = app.Flag("verbose", "Enable verbose mode.").Short('v').Bool() profile = app.Flag("profile", "Enable pprof mode.").Short('p').Bool() logDir = app.Flag("log-dir", "logstore directory.").Short('L').String() configFile = app.Flag("config-file", "config file path").Default("settings.yml").HintOptions("FILENAME").Short('C').String() logger = util.NewLogger("main") ) func systemStart(closeSignal chan struct{}, errorSignal chan error) { defer func() { if err := recover(); err != nil { errorSignal <- err.(error) } }() start := time.Now() app.Version(util.Config.Version()) if _, err := app.Parse(os.Args[1:]); err != nil { panic(err) } setMaxProcs() if err := util.LoadConfig(*configFile); err != nil { panic(err) } util.InitLogger(*verbose, *logDir, &util.Config.Logging.Application) showBanner(util.Config.Phase, util.Config.Version(), util.Config.BuildDate()) // init subsystem http.InitHttp( util.Config.Bind, util.Config.Prefix, &util.Config.Logging.Access, &util.Config.Ldap, &util.Config.Session, *profile, errorSignal, closeSignal) logger.Info("bootstrapped application ", time.Since(start)) util.NotifyDaemon(util.DaemonStarted) } func systemReload() { util.RotateLogger() } func systemTeardown(exitCode int) { logger.Info("closing application") util.NotifyDaemon(util.DaemonStopping) http.CloseHttp() logger.Info("bye") os.Exit(exitCode) } func main() { var ( exitCode = 0 exitSignal = make(chan os.Signal, 1) closeSignal = make(chan struct{}, 1) errorSignal = make(chan error, 10) ) systemStart(closeSignal, errorSignal) defer systemTeardown(exitCode) signal.Notify(exitSignal, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP) for { select { case <-closeSignal: logger.Info("Service request to close this application") return case sysSignal := <-exitSignal: switch sysSignal { case syscall.SIGHUP: systemReload() default: logger.Info("SYSCALL! ", sysSignal.String()) return } case err := <-errorSignal: logger.Error("exception raised! ", err) exitCode = -1 return } } } func setMaxProcs() { // TODO(vmarmol): Consider limiting if we have a CPU mask in effect. // Allow as many threads as we have cores unless the user specified a value. var numProcs int // if *maxProcs < 1 { numProcs = runtime.NumCPU() // } else { // numProcs = *maxProcs // } runtime.GOMAXPROCS(numProcs) // Check if the setting was successful. actualNumProcs := runtime.GOMAXPROCS(0) if actualNumProcs != numProcs { logger.Warn("Specified max procs of %v but using %v", numProcs, actualNumProcs) } } func showBanner(phase string, version string, buildDate string) { if util.LoggerIsStd() { logger.Info(` { { } }_{ __{ .-{ } }-. ` + util.Config.Name() + ` ( } { ) version: ` + version + ` ` + "|`-.._____..-'| buildDate: " + buildDate + ` | ;--. phase: ` + phase + ` | (__ \ | | ) ) | |/ / | / / | ( / \ y' ` + "`-.._____..-'") } else { logger. WithField("version", version). WithField("buildDate", buildDate). WithField("phase", phase). Info("##", util.Config.Name()) } }