You've already forked joplin
mirror of
https://github.com/laurent22/joplin.git
synced 2025-08-24 20:19:10 +02:00
Compare commits
33 Commits
server-v3.
...
issue-5521
Author | SHA1 | Date | |
---|---|---|---|
|
4a6bca7924 | ||
|
a3d14353fa | ||
|
2f5f685bc9 | ||
|
007b2926e9 | ||
|
8d817bc437 | ||
|
ce5abb7726 | ||
|
f9b445e0cf | ||
|
03feb3af5d | ||
|
1cdea38917 | ||
|
e906a1db75 | ||
|
e0d0936234 | ||
|
d9e96d199c | ||
|
8535ba9812 | ||
|
2ff14ba24b | ||
|
dbfad8b14d | ||
|
a9f8cd89db | ||
|
9e75cb3ee6 | ||
|
cb9c623d71 | ||
|
e29f139c8c | ||
|
e24fddbc5c | ||
|
9422e66e65 | ||
|
cae5e2671a | ||
|
4df9ce7530 | ||
|
4a52a240e3 | ||
|
d67b3ef9e6 | ||
|
044e1f6420 | ||
|
2af92ba550 | ||
|
c1684364ef | ||
|
e8e0bdc15e | ||
|
68fc749243 | ||
|
f9b842299e | ||
|
4b385fc43f | ||
|
b2e390c831 |
@@ -59,6 +59,8 @@ import Resource from './models/Resource';
|
||||
import { ProfileConfig } from './services/profileConfig/types';
|
||||
import initProfile from './services/profileConfig/initProfile';
|
||||
|
||||
import RotatingLogs from './RotatingLogs';
|
||||
|
||||
const appLogger: LoggerWrapper = Logger.create('App');
|
||||
|
||||
// const ntpClient = require('./vendor/ntp-client');
|
||||
@@ -85,6 +87,8 @@ export default class BaseApplication {
|
||||
|
||||
protected store_: Store<any> = null;
|
||||
|
||||
private rotatingLogs: RotatingLogs;
|
||||
|
||||
public constructor() {
|
||||
this.eventEmitter_ = new EventEmitter();
|
||||
this.decryptionWorker_resourceMetadataButNotBlobDecrypted = this.decryptionWorker_resourceMetadataButNotBlobDecrypted.bind(this);
|
||||
@@ -927,6 +931,18 @@ export default class BaseApplication {
|
||||
|
||||
await MigrationService.instance().run();
|
||||
|
||||
this.rotatingLogs = new RotatingLogs(profileDir);
|
||||
const processLogs = async () => {
|
||||
try {
|
||||
await this.rotatingLogs.cleanActiveLogFile();
|
||||
await this.rotatingLogs.deleteNonActiveLogFiles();
|
||||
} catch (error) {
|
||||
appLogger.error(error);
|
||||
}
|
||||
};
|
||||
shim.setTimeout(() => { void processLogs(); }, 60000);
|
||||
shim.setInterval(() => { void processLogs(); }, 24 * 60 * 60 * 1000);
|
||||
|
||||
return argv;
|
||||
}
|
||||
}
|
||||
|
45
packages/lib/RotatingLogs.test.ts
Normal file
45
packages/lib/RotatingLogs.test.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import { writeFile, readdir, remove } from 'fs-extra';
|
||||
import { createTempDir, msleep } from './testing/test-utils';
|
||||
import RotatingLogs from './RotatingLogs';
|
||||
|
||||
const createTestLogFile = async (dir: string) => {
|
||||
await writeFile(`${dir}/log.txt`, 'some content');
|
||||
};
|
||||
|
||||
describe('RotatingLogs', () => {
|
||||
test('should rename log.txt to log-TIMESTAMP.txt', async () => {
|
||||
let dir: string;
|
||||
try {
|
||||
dir = await createTempDir();
|
||||
await createTestLogFile(dir);
|
||||
let files: string[] = await readdir(dir);
|
||||
expect(files.find(file => file.match(/^log.txt$/gi))).toBeTruthy();
|
||||
expect(files.length).toBe(1);
|
||||
const rotatingLogs: RotatingLogs = new RotatingLogs(dir, 1, 1);
|
||||
await rotatingLogs.cleanActiveLogFile();
|
||||
files = await readdir(dir);
|
||||
expect(files.find(file => file.match(/^log.txt$/gi))).toBeFalsy();
|
||||
expect(files.find(file => file.match(/^log-[0-9]+.txt$/gi))).toBeTruthy();
|
||||
expect(files.length).toBe(1);
|
||||
} finally {
|
||||
await remove(dir);
|
||||
}
|
||||
});
|
||||
|
||||
test('should delete inative log file after 1ms', async () => {
|
||||
let dir: string;
|
||||
try {
|
||||
dir = await createTempDir();
|
||||
await createTestLogFile(dir);
|
||||
const rotatingLogs: RotatingLogs = new RotatingLogs(dir, 1, 1);
|
||||
await rotatingLogs.cleanActiveLogFile();
|
||||
await msleep(1);
|
||||
await rotatingLogs.deleteNonActiveLogFiles();
|
||||
const files = await readdir(dir);
|
||||
expect(files.find(file => file.match(/^log-[0-9]+.txt$/gi))).toBeFalsy();
|
||||
expect(files.length).toBe(0);
|
||||
} finally {
|
||||
await remove(dir);
|
||||
}
|
||||
});
|
||||
});
|
46
packages/lib/RotatingLogs.ts
Normal file
46
packages/lib/RotatingLogs.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import shim from './shim';
|
||||
import { Stat } from './fs-driver-base';
|
||||
|
||||
export default class RotatingLogs {
|
||||
|
||||
private logFilesDir: string;
|
||||
private maxFileSize: number = 1024 * 1024 * 100;
|
||||
private inactiveMaxAge: number = 90 * 24 * 60 * 60 * 1000;
|
||||
|
||||
public constructor(logFilesDir: string, maxFileSize: number = null, inactiveMaxAge: number = null) {
|
||||
this.logFilesDir = logFilesDir;
|
||||
if (maxFileSize) this.maxFileSize = maxFileSize;
|
||||
if (inactiveMaxAge) this.inactiveMaxAge = inactiveMaxAge;
|
||||
}
|
||||
|
||||
public async cleanActiveLogFile() {
|
||||
const stats: Stat = await this.fsDriver().stat(this.logFileFullpath());
|
||||
if (stats.size >= this.maxFileSize) {
|
||||
const newLogFile: string = this.logFileFullpath(this.getNameToNonActiveLogFile());
|
||||
await this.fsDriver().move(this.logFileFullpath(), newLogFile);
|
||||
}
|
||||
}
|
||||
|
||||
private getNameToNonActiveLogFile(): string {
|
||||
return `log-${Date.now()}.txt`;
|
||||
}
|
||||
|
||||
public async deleteNonActiveLogFiles() {
|
||||
const files: Stat[] = await this.fsDriver().readDirStats(this.logFilesDir);
|
||||
for (const file of files) {
|
||||
if (!file.path.match(/^log-[0-9]+.txt$/gi)) continue;
|
||||
const ageOfTheFile: number = Date.now() - file.birthtime;
|
||||
if (ageOfTheFile >= this.inactiveMaxAge) {
|
||||
await this.fsDriver().remove(this.logFileFullpath(file.path));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private logFileFullpath(fileName = 'log.txt'): string {
|
||||
return `${this.logFilesDir}/${fileName}`;
|
||||
}
|
||||
|
||||
private fsDriver() {
|
||||
return shim.fsDriver();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user