Permalink
Browse files

[core.logging] recreate outputStream if sighup doesn't dispose append…

…er within 500ms
  • Loading branch information...
spalger committed Dec 5, 2018
1 parent a64afc0 commit 693b3ab66d5f84eaa912eb89643d718e91b750bd
Showing with 54 additions and 8 deletions.
  1. +54 −8 src/core/server/logging/appenders/file/file_appender.ts
@@ -17,8 +17,12 @@
* under the License.
*/
import { EventEmitter } from 'events';
import { schema } from '@kbn/config-schema';
import { createWriteStream, WriteStream } from 'fs';
import { fromEvent } from 'rxjs';
import { delay } from 'rxjs/operators';
import { Layout, Layouts } from '../../layouts/layouts';
import { LogRecord } from '../../log_record';
@@ -35,11 +39,25 @@ export class FileAppender implements DisposableAppender {
path: schema.string(),
});
/**
* Simple buffer that will capture log records written while the writable stream
* is recreated
*/
private buffer?: LogRecord[];
/**
* Writable file stream to write formatted `LogRecord` to.
*/
private outputStream?: WriteStream;
private refreshFileDescriptorSub? = fromEvent(process as EventEmitter, 'SIGHUP')
.pipe(delay(500))
.subscribe(() =>
this.recreateOutputStream().catch(error => {
// TODO: what do we do with errors here?
})
);
/**
* Creates FileAppender instance with specified layout and file path.
* @param layout Instance of `Layout` sub-class responsible for `LogRecord` formatting.
@@ -52,23 +70,33 @@ export class FileAppender implements DisposableAppender {
* @param record `LogRecord` instance to be logged.
*/
public append(record: LogRecord) {
if (this.outputStream === undefined) {
this.outputStream = createWriteStream(this.path, {
encoding: 'utf8',
flags: 'a',
});
if (this.buffer) {
this.buffer.push(record);
return;
}
if (!this.outputStream) {
this.createOutputStream();
}
this.outputStream.write(`${this.layout.format(record)}\n`);
this.outputStream!.write(`${this.layout.format(record)}\n`);
}
/**
* Disposes `FileAppender`. Waits for the underlying file stream to be completely flushed and closed.
*/
public async dispose() {
await this.endOutputStream();
if (this.refreshFileDescriptorSub) {
this.refreshFileDescriptorSub.unsubscribe();
this.refreshFileDescriptorSub = undefined;
}
}
private async endOutputStream() {
await new Promise(resolve => {
if (this.outputStream === undefined) {
return resolve();
if (!this.outputStream) {
return;
}
this.outputStream.end(undefined, undefined, () => {
@@ -77,4 +105,22 @@ export class FileAppender implements DisposableAppender {
});
});
}
private createOutputStream() {
this.outputStream = createWriteStream(this.path, {
encoding: 'utf8',
flags: 'a',
});
}
private async recreateOutputStream() {
this.buffer = [];
await this.endOutputStream();
const records = this.buffer;
this.buffer = undefined;
for (const record of records) {
this.append(record);
}
}
}

0 comments on commit 693b3ab

Please sign in to comment.