]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/controllers/api/server/logs.ts
Refactor log level choice
[github/Chocobozzz/PeerTube.git] / server / controllers / api / server / logs.ts
CommitLineData
41fb13c3 1import express from 'express'
2c22613c 2import { readdir, readFile } from 'fs-extra'
fd8710b8 3import { join } from 'path'
15a7eafb 4import { logger, mtimeSortFilesDesc } from '@server/helpers/logger'
fd8710b8 5import { LogLevel } from '../../../../shared/models/server/log-level.type'
4c7e60bc 6import { UserRight } from '../../../../shared/models/users'
6dd9de95 7import { CONFIG } from '../../../initializers/config'
4c7e60bc
C
8import { AUDIT_LOG_FILENAME, LOG_FILENAME, MAX_LOGS_OUTPUT_CHARACTERS } from '../../../initializers/constants'
9import { asyncMiddleware, authenticate, ensureUserHasRight } from '../../../middlewares'
10import { getAuditLogsValidator, getLogsValidator } from '../../../middlewares/validators/logs'
fd8710b8
C
11
12const logsRouter = express.Router()
13
14logsRouter.get('/logs',
15 authenticate,
16 ensureUserHasRight(UserRight.MANAGE_LOGS),
17 getLogsValidator,
18 asyncMiddleware(getLogs)
19)
20
566c125d
C
21logsRouter.get('/audit-logs',
22 authenticate,
23 ensureUserHasRight(UserRight.MANAGE_LOGS),
24 getAuditLogsValidator,
25 asyncMiddleware(getAuditLogs)
26)
27
fd8710b8
C
28// ---------------------------------------------------------------------------
29
30export {
31 logsRouter
32}
33
34// ---------------------------------------------------------------------------
35
566c125d
C
36const auditLogNameFilter = generateLogNameFilter(AUDIT_LOG_FILENAME)
37async function getAuditLogs (req: express.Request, res: express.Response) {
38 const output = await generateOutput({
39 startDateQuery: req.query.startDate,
40 endDateQuery: req.query.endDate,
41 level: 'audit',
42 nameFilter: auditLogNameFilter
43 })
44
45 return res.json(output).end()
46}
47
48const logNameFilter = generateLogNameFilter(LOG_FILENAME)
fd8710b8 49async function getLogs (req: express.Request, res: express.Response) {
566c125d
C
50 const output = await generateOutput({
51 startDateQuery: req.query.startDate,
52 endDateQuery: req.query.endDate,
53 level: req.query.level || 'info',
54 nameFilter: logNameFilter
55 })
56
57 return res.json(output).end()
58}
59
60async function generateOutput (options: {
a1587156
C
61 startDateQuery: string
62 endDateQuery?: string
63 level: LogLevel
566c125d
C
64 nameFilter: RegExp
65}) {
66 const { startDateQuery, level, nameFilter } = options
67
fd8710b8
C
68 const logFiles = await readdir(CONFIG.STORAGE.LOG_DIR)
69 const sortedLogFiles = await mtimeSortFilesDesc(logFiles, CONFIG.STORAGE.LOG_DIR)
70 let currentSize = 0
71
566c125d
C
72 const startDate = new Date(startDateQuery)
73 const endDate = options.endDateQuery ? new Date(options.endDateQuery) : new Date()
fd8710b8 74
2c22613c 75 let output: string[] = []
fd8710b8
C
76
77 for (const meta of sortedLogFiles) {
566c125d
C
78 if (nameFilter.exec(meta.file) === null) continue
79
fd8710b8 80 const path = join(CONFIG.STORAGE.LOG_DIR, meta.file)
3c0d0c66 81 logger.debug('Opening %s to fetch logs.', path)
fd8710b8
C
82
83 const result = await getOutputFromFile(path, startDate, endDate, level, currentSize)
84 if (!result.output) break
85
2c22613c 86 output = result.output.concat(output)
fd8710b8
C
87 currentSize = result.currentSize
88
2c22613c 89 if (currentSize > MAX_LOGS_OUTPUT_CHARACTERS || (result.logTime && result.logTime < startDate.getTime())) break
fd8710b8
C
90 }
91
566c125d 92 return output
fd8710b8
C
93}
94
2c22613c 95async function getOutputFromFile (path: string, startDate: Date, endDate: Date, level: LogLevel, currentSize: number) {
fd8710b8
C
96 const startTime = startDate.getTime()
97 const endTime = endDate.getTime()
2c22613c 98 let logTime: number
fd8710b8
C
99
100 const logsLevel: { [ id in LogLevel ]: number } = {
566c125d 101 audit: -1,
fd8710b8
C
102 debug: 0,
103 info: 1,
104 warn: 2,
105 error: 3
106 }
107
2c22613c
C
108 const content = await readFile(path)
109 const lines = content.toString().split('\n')
110 const output: any[] = []
fd8710b8 111
2c22613c 112 for (let i = lines.length - 1; i >= 0; i--) {
a1587156 113 const line = lines[i]
2c22613c 114 let log: any
fd8710b8 115
2c22613c
C
116 try {
117 log = JSON.parse(line)
118 } catch {
119 // Maybe there a multiple \n at the end of the file
120 continue
121 }
fd8710b8 122
2c22613c 123 logTime = new Date(log.timestamp).getTime()
a1587156 124 if (logTime >= startTime && logTime <= endTime && logsLevel[log.level] >= logsLevel[level]) {
2c22613c 125 output.push(log)
fd8710b8 126
2c22613c 127 currentSize += line.length
fd8710b8 128
2c22613c
C
129 if (currentSize > MAX_LOGS_OUTPUT_CHARACTERS) break
130 } else if (logTime < startTime) {
131 break
132 }
133 }
fd8710b8 134
2c22613c 135 return { currentSize, output: output.reverse(), logTime }
fd8710b8 136}
566c125d
C
137
138function generateLogNameFilter (baseName: string) {
3c0d0c66 139 return new RegExp('^' + baseName.replace(/\.log$/, '') + '\\d*.log$')
566c125d 140}