github.com/vseinstrumentiru/lego@v1.0.2/run.go (about) 1 package LeGo 2 3 import ( 4 "context" 5 "emperror.dev/emperror" 6 "emperror.dev/errors/match" 7 "errors" 8 "github.com/gorilla/mux" 9 "github.com/oklog/run" 10 appkiterrors "github.com/sagikazarmark/appkit/errors" 11 appkitrun "github.com/sagikazarmark/appkit/run" 12 "github.com/vseinstrumentiru/lego/internal/lego" 13 "github.com/vseinstrumentiru/lego/internal/lego/monitor/exporter" 14 "github.com/vseinstrumentiru/lego/internal/lego/monitor/telemetry" 15 "github.com/vseinstrumentiru/lego/internal/lego/transport/event" 16 "github.com/vseinstrumentiru/lego/internal/lego/transport/grpc" 17 "github.com/vseinstrumentiru/lego/internal/lego/transport/http" 18 "github.com/vseinstrumentiru/lego/pkg/contexttool" 19 "logur.dev/logur" 20 "os" 21 "os/signal" 22 "syscall" 23 ) 24 25 func Run(ctx context.Context, app lego.App) { 26 s := newServer(app.GetName(), extractConfig(app)) 27 provideConfig(app, s.Config.Custom) 28 29 defer emperror.HandleRecover(s.Handler()) 30 31 // Do an upgrade on SIGHUP 32 go func() { 33 ch := make(chan os.Signal, 1) 34 signal.Notify(ch, syscall.SIGHUP) 35 for range ch { 36 s.Info("graceful reloading") 37 38 _ = s.Upgrader.Upgrade() 39 } 40 }() 41 42 { 43 config := s.Config.Monitor.Telemetry 44 45 if cApp, ok := app.(lego.AppWithStats); ok { 46 config.Stats = cApp.GetStats() 47 } 48 49 closer := telemetry.Run(s, s.Telemetry, config) 50 defer closer.Close() 51 } 52 53 { 54 const name = "app" 55 app.SetLogErr( 56 lego.NewContextAwareLogErr( 57 logur.WithField(s.Log(), "server", name), 58 s.Handler(), 59 contexttool.Extractor, 60 ). 61 WithFilter(appkiterrors.IsServiceError), 62 ) 63 } 64 65 pubApp, pubOk := app.(lego.AppWithPublishers) 66 subApp, subOk := app.(lego.AppWithEventHandlers) 67 pubOk, subOk = pubOk && s.Config.Events.Enabled, subOk && s.Config.Events.Enabled 68 69 if pubOk || subOk { 70 em, exec, interrupt := event.Run(s, s.Config.Events) 71 defer em.Close() 72 73 if pubOk { 74 err := pubApp.RegisterEventDispatcher(em.Publisher()) 75 emperror.Panic(err) 76 } 77 78 if cApp, ok := app.(lego.AppWithRegistration); ok { 79 closer, err := cApp.Register(s) 80 emperror.Panic(err) 81 82 defer lego.Close(closer) 83 } 84 85 if subOk { 86 err := subApp.RegisterEventHandlers(em) 87 emperror.Panic(err) 88 s.Background(exec, interrupt) 89 } 90 } else if cApp, ok := app.(lego.AppWithRegistration); ok { 91 closer, err := cApp.Register(s) 92 emperror.Panic(err) 93 94 defer lego.Close(closer) 95 } 96 97 if httpApp, ok := app.(lego.AppWithHttp); ok { 98 if !s.Config.Http.Enabled { 99 emperror.Panic(errors.New("http config not defined")) 100 } 101 102 var mw []mux.MiddlewareFunc 103 104 if s.Config.Monitor.Exporter.NewRelic.Enabled { 105 name := s.Config.Name 106 107 if s.Config.Monitor.Exporter.NewRelic.AppName != "" { 108 name = s.Config.Monitor.Exporter.NewRelic.AppName 109 } 110 111 mw = append(mw, exporter.NewRelicMiddleware(name, s.Config.Monitor.Exporter.NewRelic.Key, s.LogErr.WithFields(map[string]interface{}{"component": "newrelic"}))) 112 } 113 114 httpRouter, closer := http.Run(s, s.Config.Http, mw...) 115 defer closer.Close() 116 117 err := httpApp.RegisterHTTP(httpRouter) 118 emperror.Panic(err) 119 } 120 121 if grpcApp, ok := app.(lego.AppWithGrpc); ok { 122 if !s.Config.Grpc.Enabled { 123 emperror.Panic(errors.New("grpc config not defined")) 124 } 125 126 server, closer := grpc.Run(s, s.Config.Grpc) 127 defer closer.Close() 128 129 err := grpcApp.RegisterGRPC(server) 130 emperror.Panic(err) 131 } 132 133 if runApp, ok := app.(lego.AppWithRunner); ok { 134 terminate := make(chan bool, 1) 135 s.Runner.Add(func() error { 136 return runApp.Run(terminate) 137 }, func(err error) { 138 terminate <- true 139 }) 140 } 141 142 // Setup signal handler 143 s.Runner.Add(run.SignalHandler(ctx, syscall.SIGINT, syscall.SIGTERM)) 144 // Setup graceful restart 145 s.Runner.Add(appkitrun.GracefulRestart(ctx, s.Upgrader)) 146 147 err := s.Runner.Run() 148 if err != nil { 149 s.WithFilter(match.As(&run.SignalError{}).MatchError).Handle(err) 150 } 151 }