aono-file-handler
Version:
Aono handler that write to a log file with support for custom formatters and log rotation.
90 lines • 3.16 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FileHandler = void 0;
const fs = require("fs");
const util_1 = require("util");
const path_1 = require("path");
const Builder_1 = require("./Builder");
const LogstashFormatter_1 = require("./LogstashFormatter");
const open = (0, util_1.promisify)(fs.open);
const write = (0, util_1.promisify)(fs.write);
const close = (0, util_1.promisify)(fs.close);
const exists = (0, util_1.promisify)(fs.exists);
const mkdir = (0, util_1.promisify)(fs.mkdir);
const HUNDRED_MEGS = 100 * 1024 * 1024;
const LOGSTASH_FORMATTER = new LogstashFormatter_1.LogstashFormatter();
/**
* @author Maciej Chalapuk (maciej@chalapuk.pl)
*/
class FileHandler {
static builder() {
return new Builder_1.Builder();
}
constructor(prefix, formatter = LOGSTASH_FORMATTER, rotationBytesThreshold = HUNDRED_MEGS) {
this.prefix = prefix;
this.formatter = formatter;
this.rotationBytesThreshold = rotationBytesThreshold;
this._bytesWritten = 0;
this._currentFile = null;
this._currentFileSize = 0;
this._format = this.formatter.format.bind(this.formatter);
}
get currentFile() {
return this._currentFile;
}
get currentFileSize() {
return this._currentFile ? this._currentFileSize : null;
}
get bytesWritten() {
return this._bytesWritten;
}
async write(entries) {
if (entries.length === 0) {
return;
}
if (this.currentFile === null) {
for (let i = 0;; i++) {
this._currentFile = this._createFilePath(entries[0].timestamp, i > 0 ? `.${i}` : "");
await ensureDirectoryExists(this._currentFile);
try {
this._fd = await open(this._currentFile, 'ax');
break;
}
catch (e) {
if (e.code === 'EEXIST') {
continue;
}
throw e;
}
}
}
const serializedEntries = entries.map(this._format).join('');
const result = await write(this._fd, serializedEntries);
this._bytesWritten += result.bytesWritten;
this._currentFileSize += result.bytesWritten;
if (this._currentFileSize >= this.rotationBytesThreshold) {
// New file will be created when handling next batch of entries.
this._currentFile = null;
this._currentFileSize = 0;
await close(this._fd);
}
}
_createFilePath(timestamp, suffix = "") {
return `${this.prefix}.${dateSuffix(new Date(timestamp))}${suffix}`;
}
}
exports.FileHandler = FileHandler;
exports.default = FileHandler;
async function ensureDirectoryExists(filePath) {
const dir = (0, path_1.dirname)(filePath);
if (await exists(dir)) {
return;
}
ensureDirectoryExists(dir);
await mkdir(dir);
}
function dateSuffix(date) {
const iso = date.toISOString();
return `${iso.slice(0, 10)}_${iso.slice(11, 23)}`;
}
//# sourceMappingURL=FileHandler.js.map