Skip to content

Commit

Permalink
[core.logging] recreate outputStream if sighup doesn't dispose append…
Browse files Browse the repository at this point in the history
…er within 500ms
  • Loading branch information
spalger committed Dec 5, 2018
1 parent a64afc0 commit 693b3ab
Showing 1 changed file with 54 additions and 8 deletions.
62 changes: 54 additions & 8 deletions src/core/server/logging/appenders/file/file_appender.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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.
Expand All @@ -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, () => {
Expand All @@ -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.