package app import ( "bitbucket.org/BlackBroker/heruvym/dal" "bitbucket.org/BlackBroker/heruvym/middleware" "bitbucket.org/BlackBroker/heruvym/service" "bitbucket.org/BlackBroker/heruvym/version" "context" "errors" "fmt" "github.com/BlackBroker/trashlog/wrappers/zaptg" "github.com/skeris/appInit" "github.com/skeris/authService/router" "go.uber.org/zap/zapcore" "net/http" "os" "os/signal" "syscall" "github.com/themakers/hlog" "go.uber.org/zap" ) type App struct { err chan error logger *zap.Logger } const ( ENV = "env" DEFAULT = "default" ) type Options struct { MongoURI string `env:"BB_MONGO_URI" default:"mongodb://localhost:27017"` NumberPortLocal string `env:"BB_PORT" default:"1488"` LoggerDevMode bool `env:"BB_IS_PROD" default:"false"` } var ( errInvalidOptions = errors.New("invalid options") ) var _ appInit.CommonApp = (*App)(nil) type InfoSvcStarted struct{} type InfoSvcReady struct{} type InfoSvcShutdown struct{ Signal string } type ErrorStoring struct{ Err error Uri string } type ErrorCanNotServe struct{ Err error } var zapOptions = []zap.Option{ zap.AddCaller(), zap.AddCallerSkip(2), zap.AddStacktrace(zap.ErrorLevel), } func New(ctx context.Context, opts interface{}) (appInit.CommonApp, error) { var ( err error zapLogger *zap.Logger errChan = make(chan error) options Options ok bool ) if options, ok = opts.(Options); !ok { return App{}, errInvalidOptions } if options.LoggerDevMode { zapLogger, err = zap.NewDevelopment(zapOptions...) if err != nil { return nil, err } } else { zapLogger, err = zap.NewProduction(zapOptions...) if err != nil { return nil, err } } zapLogger = zapLogger.With( zap.String("SvcCommit", version.Commit), zap.String("SvcVersion", version.Release), zap.String("SvcBuildTime", version.BuildTime), ) tl, err := zaptg.NewCore( ctx, zap.ErrorLevel, "1408111289:AAHfWZRiBQRncb2gl2LtU8OeASjfJi4e8YE", version.Release, version.Commit, 0, -1001230000451, ) if err != nil { panic(err) } zapLogger = zapLogger.WithOptions(zap.WrapCore(func(core zapcore.Core) zapcore.Core { return zapcore.NewTee(core, tl) })) logger := hlog.New(zapLogger) logger.Emit(InfoSvcStarted{}) apiMux := router.NewRouter(http.NewServeMux()) database, err := dal.New( ctx, options.MongoURI, "support", logger, ) if err != nil { return nil, err } heruvym := service.New(database, logger) interrupt := make(chan os.Signal, 1) signal.Notify(interrupt, os.Interrupt, syscall.SIGTERM) server := &http.Server{ Handler: http_middleware.Wrap(heruvym.Register(apiMux), zapLogger), Addr: fmt.Sprintf(":%s", options.NumberPortLocal), } go func() { killSignal := <-interrupt switch killSignal { case os.Interrupt: logger.Emit(InfoSvcShutdown{ Signal: "Interrupt", }) case syscall.SIGTERM: logger.Emit(InfoSvcShutdown{ Signal: "Terminate", }) } if err := server.Shutdown(ctx); err != nil { panic(err) } }() logger.Emit(InfoSvcStarted{}) if err := server.ListenAndServe(); err != nil { logger.Emit(ErrorCanNotServe{ Err: err, }) return nil, err } return &App{ logger: zapLogger, err: errChan, }, nil } func (a App) GetLogger() *zap.Logger { return a.logger } func (a App) GetErr() chan error { return a.err }