import { ConnectableObservable , Subscription } from 'rxjs' ; import { first , publishReplay , switchMap , concatMap , tap } from 'rxjs/operators' ; import { Env , RawConfigurationProvider } from '../config' ; import { Logger , LoggerFactory , LoggingConfigType , LoggingSystem } from '../logging' ; import { Server } from '../server' ; /**
 * Top-level entry point to kick off the app and start the Kibana server.
 */ export class Root { public readonly logger : LoggerFactory ; private readonly log : Logger ; private readonly loggingSystem : LoggingSystem ; private readonly server : Server ; private loggingConfigSubscription ? : Subscription ; constructor ( rawConfigProvider , env , private readonly onShutdown ? ) { this . loggingSystem = new LoggingSystem ( ) ; this . logger = this . loggingSystem . asLoggerFactory ( ) ; this . log = this . logger . get ( 'root' ) ; this . server = new Server ( rawConfigProvider , env , this . loggingSystem ) ; } public async preboot ( ) { try { this . server . setupCoreConfig ( ) ; await this . setupLogging ( ) ; this . log . debug ( 'prebooting root' ) ; return await this . server . preboot ( ) ; } catch ( e ) { await this . shutdown ( e ) ; throw e ; } } public async setup ( ) { try { this . log . debug ( 'setting up root' ) ; return await this . server . setup ( ) ; } catch ( e ) { await this . shutdown ( e ) ; throw e ; } } public async start ( ) { this . log . debug ( 'starting root' ) ; try { return await this . server . start ( ) ; } catch ( e ) { await this . shutdown ( e ) ; throw e ; } } public async shutdown ( reason ? ) { this . log . debug ( 'shutting root down' ) ; if ( reason ) { if ( reason . code === 'EADDRINUSE' && Number . isInteger ( reason . port ) ) { reason = new Error ( `Port ${ reason . port } is already in use. Another instance of Kibana may be running!` ) ; } this . log . fatal ( reason ) ; } await this . server . stop ( ) ; if ( this . loggingConfigSubscription !== undefined ) { this . loggingConfigSubscription . unsubscribe ( ) ; this . loggingConfigSubscription = undefined ; } await this . loggingSystem . stop ( ) ; if ( this . onShutdown !== undefined ) { this . onShutdown ( reason ) ; } } private async setupLogging ( ) { const { configService } = this . server ; const update$ = configService . getConfig$ ( ) . pipe ( switchMap ( ( ) => configService . atPath < LoggingConfigType > ( 'logging' ) ) , concatMap ( ( config ) => this . loggingSystem . upgrade ( config ) ) , tap ( { error : ( err ) => console . error ( 'Configuring logger failed:' , err ) } ) , publishReplay ( 1 ) ) as ConnectableObservable < void > ; const connectSubscription = update$ . connect ( ) ; await update$ . pipe ( first ( ) ) . toPromise ( ) ; this . loggingConfigSubscription = update$ . subscribe ( { error : ( err ) => this . shutdown ( err ) , } ) ; this . loggingConfigSubscription . add ( connectSubscription ) ; } }