aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/controllers/api
diff options
context:
space:
mode:
Diffstat (limited to 'server/controllers/api')
-rw-r--r--server/controllers/api/server/index.ts2
-rw-r--r--server/controllers/api/server/logs.ts90
2 files changed, 92 insertions, 0 deletions
diff --git a/server/controllers/api/server/index.ts b/server/controllers/api/server/index.ts
index 814248e5f..de09588df 100644
--- a/server/controllers/api/server/index.ts
+++ b/server/controllers/api/server/index.ts
@@ -4,6 +4,7 @@ import { statsRouter } from './stats'
4import { serverRedundancyRouter } from './redundancy' 4import { serverRedundancyRouter } from './redundancy'
5import { serverBlocklistRouter } from './server-blocklist' 5import { serverBlocklistRouter } from './server-blocklist'
6import { contactRouter } from './contact' 6import { contactRouter } from './contact'
7import { logsRouter } from './logs'
7 8
8const serverRouter = express.Router() 9const serverRouter = express.Router()
9 10
@@ -12,6 +13,7 @@ serverRouter.use('/', serverRedundancyRouter)
12serverRouter.use('/', statsRouter) 13serverRouter.use('/', statsRouter)
13serverRouter.use('/', serverBlocklistRouter) 14serverRouter.use('/', serverBlocklistRouter)
14serverRouter.use('/', contactRouter) 15serverRouter.use('/', contactRouter)
16serverRouter.use('/', logsRouter)
15 17
16// --------------------------------------------------------------------------- 18// ---------------------------------------------------------------------------
17 19
diff --git a/server/controllers/api/server/logs.ts b/server/controllers/api/server/logs.ts
new file mode 100644
index 000000000..c551c67e3
--- /dev/null
+++ b/server/controllers/api/server/logs.ts
@@ -0,0 +1,90 @@
1import * as express from 'express'
2import { UserRight } from '../../../../shared/models/users'
3import { asyncMiddleware, authenticate, ensureUserHasRight } from '../../../middlewares'
4import { mtimeSortFilesDesc } from '../../../../shared/utils/logs/logs'
5import { readdir } from 'fs-extra'
6import { CONFIG, MAX_LOGS_OUTPUT_CHARACTERS } from '../../../initializers'
7import { createInterface } from 'readline'
8import { createReadStream } from 'fs'
9import { join } from 'path'
10import { getLogsValidator } from '../../../middlewares/validators/logs'
11import { LogLevel } from '../../../../shared/models/server/log-level.type'
12
13const logsRouter = express.Router()
14
15logsRouter.get('/logs',
16 authenticate,
17 ensureUserHasRight(UserRight.MANAGE_LOGS),
18 getLogsValidator,
19 asyncMiddleware(getLogs)
20)
21
22// ---------------------------------------------------------------------------
23
24export {
25 logsRouter
26}
27
28// ---------------------------------------------------------------------------
29
30async function getLogs (req: express.Request, res: express.Response) {
31 const logFiles = await readdir(CONFIG.STORAGE.LOG_DIR)
32 const sortedLogFiles = await mtimeSortFilesDesc(logFiles, CONFIG.STORAGE.LOG_DIR)
33 let currentSize = 0
34
35 const startDate = new Date(req.query.startDate)
36 const endDate = req.query.endDate ? new Date(req.query.endDate) : new Date()
37 const level: LogLevel = req.query.level || 'info'
38
39 let output = ''
40
41 for (const meta of sortedLogFiles) {
42 const path = join(CONFIG.STORAGE.LOG_DIR, meta.file)
43
44 const result = await getOutputFromFile(path, startDate, endDate, level, currentSize)
45 if (!result.output) break
46
47 output = output + result.output
48 currentSize = result.currentSize
49
50 if (currentSize > MAX_LOGS_OUTPUT_CHARACTERS) break
51 }
52
53 return res.json(output).end()
54}
55
56function getOutputFromFile (path: string, startDate: Date, endDate: Date, level: LogLevel, currentSize: number) {
57 const startTime = startDate.getTime()
58 const endTime = endDate.getTime()
59
60 const logsLevel: { [ id in LogLevel ]: number } = {
61 debug: 0,
62 info: 1,
63 warn: 2,
64 error: 3
65 }
66
67 return new Promise<{ output: string, currentSize: number }>(res => {
68 const stream = createReadStream(path)
69 let output = ''
70
71 stream.once('close', () => res({ output, currentSize }))
72
73 const rl = createInterface({
74 input: stream
75 })
76
77 rl.on('line', line => {
78 const log = JSON.parse(line)
79
80 const logTime = new Date(log.timestamp).getTime()
81 if (logTime >= startTime && logTime <= endTime && logsLevel[log.level] >= logsLevel[level]) {
82 output += line
83
84 currentSize += line.length
85
86 if (currentSize > MAX_LOGS_OUTPUT_CHARACTERS) stream.close()
87 }
88 })
89 })
90}