@signalk/streams
Version:
Utilities for handling streams of Signal K data
126 lines (124 loc) • 4.78 kB
JavaScript
;
/*
* Copyright 2017 Scott Bender (scott@scottbender.net)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getLogger = getLogger;
exports.getFullLogDir = getFullLogDir;
exports.listLogFiles = listLogFiles;
const file_timestamp_stream_1 = __importDefault(require("file-timestamp-stream"));
const path_1 = __importDefault(require("path"));
const fs_1 = __importDefault(require("fs"));
let debug = require('debug')('signalk:streams:logging');
const filenamePattern = /skserver-raw_\d\d\d\d-\d\d-\d\dT\d\d\.log/;
const loggers = {};
class FileTimestampStreamWithDelete extends file_timestamp_stream_1.default {
app;
filesToKeep;
fullLogDir;
prevFilename;
constructor(app, fullLogDir, filesToKeep, options) {
super(options);
this.app = app;
this.filesToKeep = filesToKeep;
this.fullLogDir = fullLogDir;
this.prevFilename = undefined;
debug = (options.createDebug ?? require('debug'))('signalk:streams:logging');
}
newFilename() {
if (this.prevFilename !== this.currentFilename) {
this.prevFilename = this.currentFilename;
this.deleteOldFiles();
}
return super.newFilename();
}
deleteOldFiles() {
debug('Checking for old log files');
listLogFiles(this.app, (err, files) => {
if (err) {
console.error(err);
}
else if (files &&
this.filesToKeep !== undefined &&
files.length > this.filesToKeep) {
const sortedFiles = files.sort();
const numToDelete = files.length - this.filesToKeep;
debug(`Will delete ${numToDelete} files`);
for (let i = 0; i < numToDelete; i++) {
const fileName = path_1.default.join(this.fullLogDir, sortedFiles[i]);
debug(`Deleting ${fileName}`);
fs_1.default.unlink(fileName, (unlinkErr) => {
if (unlinkErr) {
console.error(unlinkErr);
}
else {
debug(`${fileName} was deleted`);
}
});
}
}
});
}
}
function getLogger(app, discriminator = '', logdir) {
const fullLogdir = getFullLogDir(app, logdir);
if (!loggers[fullLogdir]) {
const fileName = path_1.default.join(fullLogdir, 'skserver-raw_%Y-%m-%dT%H.log');
debug(`logging to ${fileName}`);
let fileTimestampStream;
if (app.config.settings.keepMostRecentLogsOnly === undefined ||
app.config.settings.keepMostRecentLogsOnly) {
fileTimestampStream = new FileTimestampStreamWithDelete(app, fullLogdir, app.config.settings.logCountToKeep, { path: fileName });
}
else {
fileTimestampStream = new file_timestamp_stream_1.default({ path: fileName });
}
loggers[fullLogdir] = fileTimestampStream;
}
const logger = loggers[fullLogdir];
logger.on('error', (err) => {
console.error(`Error opening data logging file: ${err.message}`);
});
return (msg) => {
try {
const logMsg = msg;
logger.write(Date.now() +
';' +
discriminator +
';' +
(logMsg.updates ? JSON.stringify(msg) : String(msg)) +
'\n');
}
catch (e) {
console.error(e);
}
};
}
function getFullLogDir(app, logdir) {
const dir = logdir || app.config.settings.loggingDirectory || app.config.configPath;
return path_1.default.isAbsolute(dir) ? dir : path_1.default.join(app.config.configPath, dir);
}
function listLogFiles(app, cb) {
fs_1.default.readdir(getFullLogDir(app), (err, files) => {
if (!err) {
cb(undefined, files.filter((filename) => filenamePattern.test(filename)));
}
else {
cb(err);
}
});
}