'use strict';
|
|
const assert = require('assert');
|
const fs = require('mz/fs');
|
const debug = require('debug')('egg-logrotator:rotator');
|
|
|
class Rotator {
|
|
constructor(options) {
|
this.options = options || {};
|
assert(this.options.app, 'options.app is required');
|
this.app = this.options.app;
|
this.logger = this.app.coreLogger;
|
}
|
|
getRotateFiles() {
|
throw new Error('not implement');
|
}
|
|
async rotate() {
|
const files = await this.getRotateFiles();
|
assert(files instanceof Map, 'getRotateFiles should return a Map');
|
const rotatedFile = [];
|
for (const file of files.values()) {
|
try {
|
debug('rename from %s to %s', file.srcPath, file.targetPath);
|
await renameOrDelete(file.srcPath, file.targetPath);
|
rotatedFile.push(`${file.srcPath} -> ${file.targetPath}`);
|
} catch (err) {
|
err.message = `[egg-logrotator] rename ${file.srcPath}, found exception: ` + err.message;
|
this.logger.error(err);
|
}
|
}
|
|
if (rotatedFile.length) {
|
// tell every one to reload logger
|
this.logger.info('[egg-logrotator] broadcast log-reload');
|
this.app.messenger.sendToApp('log-reload');
|
this.app.messenger.sendToAgent('log-reload');
|
}
|
|
this.logger.info('[egg-logrotator] rotate files success by %s, files %j',
|
this.constructor.name, rotatedFile);
|
}
|
}
|
|
module.exports = Rotator;
|
|
// rename from srcPath to targetPath, for example foo.log.1 > foo.log.2
|
async function renameOrDelete(srcPath, targetPath) {
|
if (srcPath === targetPath) {
|
return;
|
}
|
const srcExists = await fs.exists(srcPath);
|
if (!srcExists) {
|
return;
|
}
|
const targetExists = await fs.exists(targetPath);
|
// if target file exists, then throw
|
// because the target file always be renamed first.
|
if (targetExists) {
|
const err = new Error(`targetFile ${targetPath} exists!!!`);
|
throw err;
|
}
|
await fs.rename(srcPath, targetPath);
|
}
|