Run starts, and blocks until a signal is received or Stop is called.
()
| 170 | |
| 171 | // Run starts, and blocks until a signal is received or Stop is called. |
| 172 | func (t *App) Run() error { |
| 173 | if !t.ModuleManager.IsUserVisibleModule(t.cfg.Target) { |
| 174 | level.Warn(log.Logger).Log("msg", "selected target is an internal module, is this intended?", "target", t.cfg.Target) |
| 175 | } |
| 176 | |
| 177 | serviceMap, err := t.ModuleManager.InitModuleServices(t.cfg.Target) |
| 178 | if err != nil { |
| 179 | return fmt.Errorf("failed to init module services: %w", err) |
| 180 | } |
| 181 | t.serviceMap = serviceMap |
| 182 | |
| 183 | servs := []services.Service(nil) |
| 184 | for _, s := range serviceMap { |
| 185 | servs = append(servs, s) |
| 186 | } |
| 187 | |
| 188 | sm, err := services.NewManager(servs...) |
| 189 | if err != nil { |
| 190 | return fmt.Errorf("failed to start service manager: %w", err) |
| 191 | } |
| 192 | |
| 193 | // Used to delay shutdown but return "not ready" during this delay. |
| 194 | shutdownRequested := atomic.NewBool(false) |
| 195 | // before starting servers, register /ready handler and gRPC health check service. |
| 196 | if t.cfg.InternalServer.Enable { |
| 197 | t.InternalServer.HTTP.Path("/ready").Methods("GET").Handler(t.readyHandler(sm, shutdownRequested)) |
| 198 | } |
| 199 | |
| 200 | t.Server.HTTPRouter().Path(addHTTPAPIPrefix(&t.cfg, api.PathBuildInfo)).Handler(t.buildinfoHandler()).Methods("GET") |
| 201 | |
| 202 | t.Server.HTTPRouter().Path("/ready").Handler(t.readyHandler(sm, shutdownRequested)) |
| 203 | t.Server.HTTPRouter().Path("/status").Handler(t.statusHandler()).Methods("GET") |
| 204 | t.Server.HTTPRouter().Path("/status/{endpoint}").Handler(t.statusHandler()).Methods("GET") |
| 205 | grpc_health_v1.RegisterHealthServer(t.Server.GRPC(), |
| 206 | grpcutil.NewHealthCheckFrom( |
| 207 | grpcutil.WithShutdownRequested(shutdownRequested), |
| 208 | grpcutil.WithManager(sm), |
| 209 | )) |
| 210 | |
| 211 | // Let's listen for events from this manager, and log them. |
| 212 | healthy := func() { level.Info(log.Logger).Log("msg", "Tempo started") } |
| 213 | stopped := func() { level.Info(log.Logger).Log("msg", "Tempo stopped") } |
| 214 | serviceFailed := func(service services.Service) { |
| 215 | // if any service fails, stop everything |
| 216 | sm.StopAsync() |
| 217 | |
| 218 | // let's find out which module failed |
| 219 | for m, s := range serviceMap { |
| 220 | if s == service { |
| 221 | err := service.FailureCase() |
| 222 | if errors.Is(err, modules.ErrStopProcess) { |
| 223 | level.Info(log.Logger).Log("msg", "received stop signal via return error", "module", m, "err", err) |
| 224 | } else if errors.Is(err, context.Canceled) { |
| 225 | return |
| 226 | } else if err != nil { |
| 227 | level.Error(log.Logger).Log("msg", "module failed", "module", m, "err", err) |
| 228 | } |
| 229 | return |