Skip to content

Commit cc62498

Browse files
committed
implemented more logging
1 parent bf6be5e commit cc62498

File tree

3 files changed

+160
-46
lines changed

3 files changed

+160
-46
lines changed

src/obj/backup-manager.ts

Lines changed: 48 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -42,25 +42,19 @@ export class BackupManager {
4242
const downloadPath = (AppSettings.settings.backup.downloadPath === '') ? AppSettings.appPath : AppSettings.settings.backup.downloadPath;
4343
const timeString = moment().format('YYYY-MM-DD_H-mm') + '_';
4444
const targetPath = path.join(downloadPath, timeString + name);
45-
const errorFile = `${timeString}${name}_errors.log`;
4645
const statisticsFile = `${timeString}${name}_statistics.txt`;
47-
46+
const logsFile = `${timeString}${name}.log`;
47+
const errorFile = `${timeString}${name}_errors.log`;
4848
if (fs.existsSync(path.join(downloadPath, errorFile))) {
4949
fs.unlinkSync(path.join(downloadPath, errorFile));
5050
}
51+
5152
if (fs.existsSync(path.join(downloadPath, statisticsFile))) {
5253
fs.unlinkSync(path.join(downloadPath, statisticsFile));
5354
}
54-
55-
const subscr = this.ftpManager.error.subscribe((message: string) => {
56-
ConsoleOutput.error(`${moment().format('L LTS')}: ${message}`);
57-
const line = `${moment().format('L LTS')}:\t${message}\n`;
58-
errors += line;
59-
fs.appendFile(path.join(downloadPath, `${timeString}${name}_errors.log`), line, {
60-
encoding: 'utf8'
61-
}, () => {
62-
});
63-
});
55+
if (fs.existsSync(path.join(downloadPath, logsFile))) {
56+
fs.unlinkSync(path.join(downloadPath, logsFile));
57+
}
6458

6559
ConsoleOutput.info(`Remote path: ${AppSettings.settings.backup.root}\nDownload path: ${downloadPath}\n`);
6660

@@ -69,46 +63,78 @@ export class BackupManager {
6963
this.ftpManager.statistics.ended = Date.now();
7064
this.ftpManager.statistics.duration = (this.ftpManager.statistics.ended - this.ftpManager.statistics.started) / 1000 / 60;
7165

72-
ConsoleOutput.success('Backup finished!');
66+
this.ftpManager.logger.log('Backup finsihed', 'success');
7367
const statistics = `\n-- Statistics: --
7468
Started: ${moment(this.ftpManager.statistics.started).format('L LTS')}
7569
Ended: ${moment(this.ftpManager.statistics.ended).format('L LTS')}
7670
Duration: ${ConsoleOutput.getTimeString(this.ftpManager.statistics.duration * 60 * 1000)} (H:m:s)
7771
7872
Folders: ${this.ftpManager.statistics.folders}
7973
Files: ${this.ftpManager.statistics.files}
80-
Errors: ${errors.split('\n').length - 1}`;
74+
Errors: ${this.ftpManager.logger.errorLogs.length}`;
8175

8276
ConsoleOutput.log('\n' + statistics);
8377
fs.writeFileSync(path.join(downloadPath, `${timeString}${name}_statistics.txt`), statistics, {
8478
encoding: 'utf-8'
8579
});
8680

87-
if (errors !== '') {
88-
ConsoleOutput.error(`There are errors. Please read the errors.log file for further information.`);
81+
if (this.ftpManager.logger.errorLogs.length > 0) {
82+
const warning = `There are errors. Please read the errors.log file for further information.`;
83+
ConsoleOutput.error(warning);
84+
this.ftpManager.logger.add(warning, 'warning');
8985
}
90-
subscr.unsubscribe();
9186
this.ftpManager.close();
9287

9388
// check zipping
9489
if (AppSettings.settings.backup.zip.enabled) {
95-
console.log(`\nZip folder...`);
90+
this.ftpManager.logger.log('\nZip folder...', 'info');
9691
this.createZipFile(downloadPath, timeString + name, this.ftpManager.statistics.files,
9792
AppSettings.settings.backup.zip.password).then(() => {
98-
ConsoleOutput.success('Zip file created!');
99-
rimraf(targetPath, () => {
100-
console.log('done');
101-
});
93+
this.ftpManager.logger.log('Zip file created!', 'success');
94+
this.writeErrorLogs(downloadPath, name, timeString);
95+
this.writeLogs(downloadPath, name, timeString);
96+
rimraf(targetPath, () => {});
10297
}).catch((error) => {
10398
ConsoleOutput.error(error);
99+
this.ftpManager.logger.add('Zipping failed!', 'error');
100+
this.writeErrorLogs(downloadPath, name, timeString);
101+
this.writeLogs(downloadPath, name, timeString);
104102
});
103+
} else {
104+
this.writeErrorLogs(downloadPath, name, timeString);
105+
this.writeLogs(downloadPath, name, timeString);
105106
}
106107
}).catch((error) => {
107108
ConsoleOutput.error(error);
108109
this.ftpManager.close();
109110
});
110111
}
111112

113+
private writeErrorLogs(downloadPath: string, name: string, timeString: string) {
114+
const errorFile = `${timeString}${name}_errors.log`;
115+
const errors = this.ftpManager.logger.errorLogs;
116+
117+
let fileContent = '';
118+
for (const loggerEntry of errors) {
119+
fileContent += `${loggerEntry.toString()}\n`;
120+
}
121+
fs.writeFileSync(path.join(downloadPath, errorFile), fileContent, {
122+
encoding: 'utf8'
123+
});
124+
}
125+
126+
private writeLogs(downloadPath: string, name: string, timeString: string) {
127+
const logFile = `${timeString}${name}.log`;
128+
129+
let fileContent = '';
130+
for (const loggerEntry of this.ftpManager.logger.queue) {
131+
fileContent += `${loggerEntry.toString()}\n`;
132+
}
133+
fs.writeFileSync(path.join(downloadPath, logFile), fileContent, {
134+
encoding: 'utf8'
135+
});
136+
}
137+
112138
/**
113139
* creates a zip archive
114140
* @param path

src/obj/ftp-manager.ts

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,28 @@ import * as fs from 'fs-extra';
55
import {Subject} from 'rxjs';
66
import {AppSettings, Configuration} from '../app-settings';
77
import {ConsoleOutput} from './console-output';
8+
import {Logger} from './logger';
89
import moment = require('moment');
910

1011
export class FtpManager {
12+
get logger(): Logger {
13+
return this._logger;
14+
}
15+
1116
private isReady = false;
1217
private _client: ftp.Client;
1318
private currentDirectory = '';
1419

1520
public readyChange: Subject<boolean>;
16-
public error: Subject<string>;
1721
private connectionOptions: FTPConnectionOptions;
1822

1923
private folderQueue: {
2024
remotePath: string,
2125
downloadPath: string
2226
}[] = [];
2327

28+
private _logger: Logger = new Logger();
29+
2430
private readonly protocol: 'ftp' | 'ftps' = 'ftps';
2531

2632
public statistics = {
@@ -37,7 +43,6 @@ export class FtpManager {
3743
this._client = new ftp.Client(configuration.server.timeout * 1000);
3844
this._client.ftp.verbose = configuration.server.verbose;
3945
this.readyChange = new Subject<boolean>();
40-
this.error = new Subject<string>();
4146
this.connectionOptions = {
4247
host: configuration.server.host,
4348
port: configuration.server.port,
@@ -60,7 +65,7 @@ export class FtpManager {
6065
*/
6166
private async connect() {
6267
try {
63-
ConsoleOutput.info(`connect via ${this.protocol}...`);
68+
this.logger.log(`connect via ${this.protocol}...`, 'info');
6469
await this._client.access({
6570
host: this.connectionOptions.host,
6671
user: this.connectionOptions.user,
@@ -103,7 +108,7 @@ export class FtpManager {
103108
public async gotTo(path: string) {
104109
return new Promise<void>((resolve, reject) => {
105110
if (this.isReady) {
106-
ConsoleOutput.info(`open ${path}`);
111+
this.logger.log(`open ${path}`, 'info');
107112
this._client.cd(path).then(() => {
108113
this._client.pwd().then((dir) => {
109114
if (dir === this.currentDirectory) {
@@ -255,10 +260,10 @@ export class FtpManager {
255260
try {
256261
await this._downloadFolder(remotePath, downloadPath);
257262
this.statistics.folders++;
258-
ConsoleOutput.success(`${this.getCurrentTimeString()}===> Directory downloaded: ${remotePath}\n`);
263+
this.logger.log(`directory downloaded: ${remotePath}\n`, 'success', remotePath);
259264
} catch (e) {
260-
this.error.next(e);
261-
ConsoleOutput.error(e);
265+
this._logger.add(e.message, 'error', remotePath);
266+
this.logger.log(e.toString(), 'error', remotePath);
262267
}
263268
}
264269
}
@@ -273,7 +278,7 @@ export class FtpManager {
273278
this.recursives++;
274279

275280
if (this.recursives % 100 === 99) {
276-
ConsoleOutput.info('WAIT');
281+
this.logger.log('wait...', 'info');
277282
await this.wait(0);
278283
}
279284

@@ -282,49 +287,46 @@ export class FtpManager {
282287
await fs.mkdir(downloadPath, {recursive: true});
283288
}
284289
} catch (e) {
285-
this.error.next(e);
290+
this._logger.add(e.message, 'error', remotePath);
286291
return true;
287292
}
288293

289294
let list: FileInfo[] = [];
290295
if (this._client.closed) {
291296
try {
292-
console.log(`RECONNECT...`);
297+
this.logger.log('RECONNECT...', 'warning');
293298
await this.connect();
294299
} catch (e) {
295300
throw new Error(e);
296301
}
297302
}
298303
try {
299-
console.log(`download folder ${remotePath} ...`);
304+
this.logger.log(`download folder ${remotePath} ...`, 'info');
300305
list = await this.listEntries(remotePath);
301306
} catch (e) {
302-
this.error.next(e);
307+
this._logger.add(e.message, 'error', remotePath);
303308
return true;
304309
}
305310

306311
for (const fileInfo of list) {
307312
if (fileInfo.isDirectory) {
308313
const folderPath = remotePath + fileInfo.name + '/';
309314
const targetPath = Path.join(downloadPath, fileInfo.name);
310-
try {
311-
this.folderQueue.push({remotePath: folderPath, downloadPath: targetPath});
312-
} catch (e) {
313-
this.error.next(e);
314-
}
315+
this.folderQueue.push({remotePath: folderPath, downloadPath: targetPath});
315316
} else if (fileInfo.isFile) {
317+
const filePath = remotePath + fileInfo.name;
316318
try {
317-
const filePath = remotePath + fileInfo.name;
318319
await this.downloadFile(filePath, downloadPath, fileInfo);
319320
} catch (e) {
320-
this.error.next(e);
321+
this._logger.add(e.message, 'error', filePath);
321322
}
322323
}
323324
}
324325
try {
325326
await this.goUp();
326327
return true;
327328
} catch (e) {
329+
this._logger.add(e.message, 'error', remotePath);
328330
throw e;
329331
}
330332
}
@@ -355,7 +357,7 @@ export class FtpManager {
355357
this.recursives++;
356358

357359
if (this.recursives % 100 === 99) {
358-
ConsoleOutput.info('WAIT');
360+
this.logger.log('wait..', 'info');
359361
await this.wait(0);
360362
}
361363

@@ -381,15 +383,15 @@ export class FtpManager {
381383
percentStr += percent.toFixed(2);
382384

383385
if (AppSettings.settings.console.tty) {
384-
ConsoleOutput.logLive(`${this.getCurrentTimeString()}---> ${info.type} (${percentStr}%): ${info.name}`);
386+
ConsoleOutput.logLive(`${this.getCurrentTimeString()} ---> ${info.type} (${percentStr}%): ${info.name}`);
385387
} else {
386-
ConsoleOutput.log(`${this.getCurrentTimeString()}---> ${info.type} (${percentStr}%): ${info.name}`);
388+
ConsoleOutput.log(`${this.getCurrentTimeString()} ---> ${info.type} (${percentStr}%): ${info.name}`);
387389
}
388390
};
389391

390392
if (this._client.closed) {
391393
try {
392-
console.log(`RECONNECT...`);
394+
this.logger.log('RECONNECT...', 'warning');
393395
await this.connect();
394396
} catch (e) {
395397
throw new Error(e);
@@ -398,6 +400,7 @@ export class FtpManager {
398400
this._client.trackProgress(handler);
399401
try {
400402
await this._client.downloadTo(Path.join(downloadPath, fileInfo.name), fileInfo.name);
403+
this.logger.add(`downloaded file`, 'success', downloadPath);
401404
this._client.trackProgress(undefined);
402405
this.statistics.files++;
403406
return true;
@@ -430,7 +433,6 @@ export class FtpManager {
430433
}
431434
}
432435

433-
434436
export interface FTPConnectionOptions {
435437
host: string;
436438
port: number;

src/obj/logger.ts

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import moment = require('moment');
2+
import {ConsoleOutput} from './console-output';
3+
4+
export class Logger {
5+
get queue(): LoggerEntry[] {
6+
return this._queue;
7+
}
8+
9+
private _queue: LoggerEntry[] = [];
10+
11+
constructor() {
12+
}
13+
14+
public add(message: string, type: 'error' | 'success' | 'info' | 'warning', path: string = '') {
15+
this._queue.push(new LoggerEntry(message, type, path));
16+
this.sort();
17+
}
18+
19+
public log(message: string, type: 'error' | 'success' | 'info' | 'warning', path: string = '') {
20+
this.add(message, type, path);
21+
22+
switch (type) {
23+
case 'success':
24+
ConsoleOutput.success(message);
25+
break;
26+
case 'info':
27+
ConsoleOutput.info(message);
28+
break;
29+
case 'error':
30+
ConsoleOutput.error(message);
31+
break;
32+
case 'warning':
33+
ConsoleOutput.warning(message);
34+
break;
35+
}
36+
}
37+
38+
public get errorLogs(): LoggerEntry[] {
39+
return this._queue.filter((a) => {
40+
return a.type === 'error';
41+
});
42+
}
43+
44+
private sort() {
45+
this._queue = this._queue.sort((a, b) => {
46+
if (a.timestamp === b.timestamp) {
47+
return 0;
48+
}
49+
return (a.timestamp < b.timestamp) ? -1 : 1;
50+
});
51+
}
52+
}
53+
54+
export class LoggerEntry {
55+
get path(): string {
56+
return this._path;
57+
}
58+
59+
get message(): string {
60+
return this._message;
61+
}
62+
63+
get type(): 'error' | 'success' | 'info' | 'warning' {
64+
return this._type;
65+
}
66+
67+
get timestamp(): number {
68+
return this._timestamp;
69+
}
70+
71+
private _timestamp: number;
72+
private _type: 'error' | 'success' | 'info' | 'warning';
73+
private _message: string;
74+
private _path: string = '';
75+
76+
constructor(message: string, type: 'error' | 'success' | 'info' | 'warning', path: string = '') {
77+
this._type = type;
78+
this._message = message;
79+
this._path = path;
80+
}
81+
82+
public toString() {
83+
const imploded = this._message.replace(/\n/g, ' | ');
84+
return `${moment(this._timestamp).format('L LTS')}\t${this._type.toUpperCase()}\t${this._path}\t${imploded}`;
85+
}
86+
}

0 commit comments

Comments
 (0)