diff options
Diffstat (limited to 'server/controllers/api')
-rw-r--r-- | server/controllers/api/server/logs.ts | 52 |
1 files changed, 28 insertions, 24 deletions
diff --git a/server/controllers/api/server/logs.ts b/server/controllers/api/server/logs.ts index c551c67e3..5fa3c8787 100644 --- a/server/controllers/api/server/logs.ts +++ b/server/controllers/api/server/logs.ts | |||
@@ -2,10 +2,8 @@ import * as express from 'express' | |||
2 | import { UserRight } from '../../../../shared/models/users' | 2 | import { UserRight } from '../../../../shared/models/users' |
3 | import { asyncMiddleware, authenticate, ensureUserHasRight } from '../../../middlewares' | 3 | import { asyncMiddleware, authenticate, ensureUserHasRight } from '../../../middlewares' |
4 | import { mtimeSortFilesDesc } from '../../../../shared/utils/logs/logs' | 4 | import { mtimeSortFilesDesc } from '../../../../shared/utils/logs/logs' |
5 | import { readdir } from 'fs-extra' | 5 | import { readdir, readFile } from 'fs-extra' |
6 | import { CONFIG, MAX_LOGS_OUTPUT_CHARACTERS } from '../../../initializers' | 6 | import { CONFIG, MAX_LOGS_OUTPUT_CHARACTERS } from '../../../initializers' |
7 | import { createInterface } from 'readline' | ||
8 | import { createReadStream } from 'fs' | ||
9 | import { join } from 'path' | 7 | import { join } from 'path' |
10 | import { getLogsValidator } from '../../../middlewares/validators/logs' | 8 | import { getLogsValidator } from '../../../middlewares/validators/logs' |
11 | import { LogLevel } from '../../../../shared/models/server/log-level.type' | 9 | import { LogLevel } from '../../../../shared/models/server/log-level.type' |
@@ -36,7 +34,7 @@ async function getLogs (req: express.Request, res: express.Response) { | |||
36 | const endDate = req.query.endDate ? new Date(req.query.endDate) : new Date() | 34 | const endDate = req.query.endDate ? new Date(req.query.endDate) : new Date() |
37 | const level: LogLevel = req.query.level || 'info' | 35 | const level: LogLevel = req.query.level || 'info' |
38 | 36 | ||
39 | let output = '' | 37 | let output: string[] = [] |
40 | 38 | ||
41 | for (const meta of sortedLogFiles) { | 39 | for (const meta of sortedLogFiles) { |
42 | const path = join(CONFIG.STORAGE.LOG_DIR, meta.file) | 40 | const path = join(CONFIG.STORAGE.LOG_DIR, meta.file) |
@@ -44,18 +42,19 @@ async function getLogs (req: express.Request, res: express.Response) { | |||
44 | const result = await getOutputFromFile(path, startDate, endDate, level, currentSize) | 42 | const result = await getOutputFromFile(path, startDate, endDate, level, currentSize) |
45 | if (!result.output) break | 43 | if (!result.output) break |
46 | 44 | ||
47 | output = output + result.output | 45 | output = result.output.concat(output) |
48 | currentSize = result.currentSize | 46 | currentSize = result.currentSize |
49 | 47 | ||
50 | if (currentSize > MAX_LOGS_OUTPUT_CHARACTERS) break | 48 | if (currentSize > MAX_LOGS_OUTPUT_CHARACTERS || (result.logTime && result.logTime < startDate.getTime())) break |
51 | } | 49 | } |
52 | 50 | ||
53 | return res.json(output).end() | 51 | return res.json(output).end() |
54 | } | 52 | } |
55 | 53 | ||
56 | function getOutputFromFile (path: string, startDate: Date, endDate: Date, level: LogLevel, currentSize: number) { | 54 | async function getOutputFromFile (path: string, startDate: Date, endDate: Date, level: LogLevel, currentSize: number) { |
57 | const startTime = startDate.getTime() | 55 | const startTime = startDate.getTime() |
58 | const endTime = endDate.getTime() | 56 | const endTime = endDate.getTime() |
57 | let logTime: number | ||
59 | 58 | ||
60 | const logsLevel: { [ id in LogLevel ]: number } = { | 59 | const logsLevel: { [ id in LogLevel ]: number } = { |
61 | debug: 0, | 60 | debug: 0, |
@@ -64,27 +63,32 @@ function getOutputFromFile (path: string, startDate: Date, endDate: Date, level: | |||
64 | error: 3 | 63 | error: 3 |
65 | } | 64 | } |
66 | 65 | ||
67 | return new Promise<{ output: string, currentSize: number }>(res => { | 66 | const content = await readFile(path) |
68 | const stream = createReadStream(path) | 67 | const lines = content.toString().split('\n') |
69 | let output = '' | 68 | const output: any[] = [] |
70 | 69 | ||
71 | stream.once('close', () => res({ output, currentSize })) | 70 | for (let i = lines.length - 1; i >= 0; i--) { |
71 | const line = lines[ i ] | ||
72 | let log: any | ||
72 | 73 | ||
73 | const rl = createInterface({ | 74 | try { |
74 | input: stream | 75 | log = JSON.parse(line) |
75 | }) | 76 | } catch { |
77 | // Maybe there a multiple \n at the end of the file | ||
78 | continue | ||
79 | } | ||
76 | 80 | ||
77 | rl.on('line', line => { | 81 | logTime = new Date(log.timestamp).getTime() |
78 | const log = JSON.parse(line) | 82 | if (logTime >= startTime && logTime <= endTime && logsLevel[ log.level ] >= logsLevel[ level ]) { |
83 | output.push(log) | ||
79 | 84 | ||
80 | const logTime = new Date(log.timestamp).getTime() | 85 | currentSize += line.length |
81 | if (logTime >= startTime && logTime <= endTime && logsLevel[log.level] >= logsLevel[level]) { | ||
82 | output += line | ||
83 | 86 | ||
84 | currentSize += line.length | 87 | if (currentSize > MAX_LOGS_OUTPUT_CHARACTERS) break |
88 | } else if (logTime < startTime) { | ||
89 | break | ||
90 | } | ||
91 | } | ||
85 | 92 | ||
86 | if (currentSize > MAX_LOGS_OUTPUT_CHARACTERS) stream.close() | 93 | return { currentSize, output: output.reverse(), logTime } |
87 | } | ||
88 | }) | ||
89 | }) | ||
90 | } | 94 | } |