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