New creates and initializes an App, immediately executing any functions registered via [Invoke] options. See the documentation of the App struct for details on the application's initialization, startup, and shutdown logic.
(opts ...Option)
| 420 | // registered via [Invoke] options. See the documentation of the App struct for |
| 421 | // details on the application's initialization, startup, and shutdown logic. |
| 422 | func New(opts ...Option) *App { |
| 423 | logger := fxlog.DefaultLogger(os.Stderr) |
| 424 | |
| 425 | app := &App{ |
| 426 | clock: fxclock.System, |
| 427 | startTimeout: DefaultTimeout, |
| 428 | stopTimeout: DefaultTimeout, |
| 429 | receivers: newSignalReceivers(), |
| 430 | } |
| 431 | app.root = &module{ |
| 432 | app: app, |
| 433 | // We start with a logger that writes to stderr. One of the |
| 434 | // following three things can change this: |
| 435 | // |
| 436 | // - fx.Logger was provided to change the output stream |
| 437 | // - fx.WithLogger was provided to change the logger |
| 438 | // implementation |
| 439 | // - Both, fx.Logger and fx.WithLogger were provided |
| 440 | // |
| 441 | // The first two cases are straightforward: we use what the |
| 442 | // user gave us. For the last case, however, we need to fall |
| 443 | // back to what was provided to fx.Logger if fx.WithLogger |
| 444 | // fails. |
| 445 | log: logger, |
| 446 | trace: []string{fxreflect.CallerStack(1, 2)[0].String()}, |
| 447 | } |
| 448 | |
| 449 | for _, opt := range opts { |
| 450 | opt.apply(app.root) |
| 451 | } |
| 452 | |
| 453 | // There are a few levels of wrapping on the lifecycle here. To quickly |
| 454 | // cover them: |
| 455 | // |
| 456 | // - lifecycleWrapper ensures that we don't unintentionally expose the |
| 457 | // Start and Stop methods of the internal lifecycle.Lifecycle type |
| 458 | // - lifecycleWrapper also adapts the internal lifecycle.Hook type into |
| 459 | // the public fx.Hook type. |
| 460 | // - appLogger ensures that the lifecycle always logs events to the |
| 461 | // "current" logger associated with the fx.App. |
| 462 | app.lifecycle = &lifecycleWrapper{ |
| 463 | lifecycle.New(appLogger{app}, app.clock), |
| 464 | } |
| 465 | |
| 466 | containerOptions := []dig.Option{ |
| 467 | dig.DeferAcyclicVerification(), |
| 468 | dig.DryRun(app.validate), |
| 469 | } |
| 470 | |
| 471 | if app.recoverFromPanics { |
| 472 | containerOptions = append(containerOptions, dig.RecoverFromPanics()) |
| 473 | } |
| 474 | |
| 475 | app.container = dig.New(containerOptions...) |
| 476 | app.root.build(app, app.container) |
| 477 | |
| 478 | // Provide Fx types first to increase the chance a custom logger |
| 479 | // can be successfully built in the face of unrelated DI failure. |