diff --git a/lib/controller.ts b/lib/controller.ts index 8b6e9abff..ac2500363 100644 --- a/lib/controller.ts +++ b/lib/controller.ts @@ -104,7 +104,7 @@ class Controller { logger.error('Check https://www.zigbee2mqtt.io/guide/installation/20_zigbee2mqtt-fails-to-start.html for possible solutions'); /* eslint-disable-line max-len */ logger.error('Exiting...'); logger.error(error.stack); - this.exitCallback(1); + await this.exit(1); } // Disable some legacy options on new network creation @@ -145,7 +145,7 @@ class Controller { logger.error(`MQTT failed to connect: ${error.message}`); logger.error('Exiting...'); await this.zigbee.stop(); - this.exitCallback(1); + await this.exit(1); } // Call extensions @@ -197,13 +197,18 @@ class Controller { try { await this.zigbee.stop(); logger.info('Stopped Zigbee2MQTT'); - this.exitCallback(0); + await this.exit(0); } catch (error) { logger.error('Failed to stop Zigbee2MQTT'); - this.exitCallback(1); + await this.exit(1); } } + async exit(code: number): Promise { + await logger.end(); + this.exitCallback(code); + } + @bind async onZigbeeAdapterDisconnected(): Promise { logger.error('Adapter disconnected, stopping'); await this.stop(); diff --git a/lib/util/logger.ts b/lib/util/logger.ts index 1d4cbffde..7d3ae49e8 100644 --- a/lib/util/logger.ts +++ b/lib/util/logger.ts @@ -91,8 +91,10 @@ if (settings.get().advanced.log_rotation) { transportFileOptions.maxsize = 10000000; // 10MB } +let fileTransport : winston.transport; if (output.includes('file')) { - transportsToUse.push(new winston.transports.File(transportFileOptions)); + fileTransport = new winston.transports.File(transportFileOptions); + transportsToUse.push(fileTransport); } /* istanbul ignore next */ @@ -181,6 +183,28 @@ function error(message: string): void { logger.error(message); } +// Workaround for https://github.com/winstonjs/winston/issues/1629. +// https://github.com/Koenkk/zigbee2mqtt/pull/10905 +/* istanbul ignore next */ +async function end(): Promise { + logger.end(); + + await new Promise((resolve) => { + if (!fileTransport) { + process.nextTick(resolve); + } else { + // @ts-ignore + if (fileTransport._dest) { + // @ts-ignore + fileTransport._dest.on('finish', resolve); + } else { + // @ts-ignore + fileTransport.on('open', () => fileTransport._dest.on('finish', resolve)); + } + } + }); +} + export default { - logOutput, warn, warning, error, info, debug, setLevel, getLevel, cleanup, addTransport, winston: logger, + logOutput, warn, warning, error, info, debug, setLevel, getLevel, cleanup, addTransport, end, winston: logger, }; diff --git a/test/stub/logger.js b/test/stub/logger.js index 5a8db036d..7fabca4c6 100644 --- a/test/stub/logger.js +++ b/test/stub/logger.js @@ -23,6 +23,7 @@ const mock = { setLevel: (newLevel) => {level = newLevel}, getLevel: () => level, setTransportsEnabled: (value) => {transportsEnabled = value}, + end: jest.fn(), }; jest.mock('../../lib/util/logger', () => (mock));