Prosody log rotation every 24 hour.

This commit is contained in:
John Livingston 2021-05-12 14:59:52 +02:00
parent c5bcf611d3
commit 4cf9ab51aa
6 changed files with 115 additions and 4 deletions

View File

@ -8,6 +8,7 @@
* Starting with Peertube 3.2.0, builtin prosody save room history on server. So when a user connects, he can get previously send messages.
* Starting with Peertube 3.2.0, builtin prosody also activate mod_muc_moderation, enabling moderators to moderate messages.
* Prosody log level will be the same as the Peertube's one.
* Prosody log rotation every 24 hour.
### Fixes

View File

@ -12,7 +12,7 @@ This roadmap is given as an indication. It will be updated as we go along accord
[x] | [x] | Common | Chat should not be displayed in playlists | v2.2.0
[x] | [x] | Builtin Prosody | Do not use a temp folder, use the one provided by Peertube>=3.2.0. | Not Released Yet
[x] | [ ] | Builtin Prosody | Use Peertube log level for prosody. | Not Released Yet
[ ] | [x] | Builtin Prosody | Rotate prosody logs.
[ ] | [x] | Builtin Prosody | Rotate prosody logs. | Not Released Yet
[x] | [x] | Builtin Prosody | Data Persistence | Not Released Yet
[ ] | [x] | Common | Add a checkbox per video to activate livechat. Only on lives.
[ ] | [x] | Builtin Prosody | Docker: check how to install and use Prosody on docker installations. Do the documentation.

5
package-lock.json generated
View File

@ -3620,6 +3620,11 @@
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
"dev": true
},
"log-rotate": {
"version": "0.2.8",
"resolved": "https://registry.npmjs.org/log-rotate/-/log-rotate-0.2.8.tgz",
"integrity": "sha512-r9I3eKh2EH+jjbg+tqvACtBjmCdyyyKQsElVF+a/tYCQDOmHQxTvlDEB6GFn2UAZcsF13LTV814bhXspWMu96g=="
},
"logform": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/logform/-/logform-2.2.0.tgz",

View File

@ -31,7 +31,8 @@
"async": "^3.2.0",
"body-parser": "^1.19.0",
"decache": "^4.6.0",
"express-http-proxy": "^1.6.2"
"express-http-proxy": "^1.6.2",
"log-rotate": "^0.2.8"
},
"devDependencies": {
"@purtuga/esm-webpack-plugin": "^1.1.1",

View File

@ -1,4 +1,5 @@
import { getProsodyConfig, getProsodyFilePaths, writeProsodyConfig } from './config'
import { startProsodyLogRotate, stopProsodyLogRotate } from './logrotate'
import { changeHttpBindRoute } from '../routers/webchat'
import * as fs from 'fs'
import * as child_process from 'child_process'
@ -58,6 +59,15 @@ async function getProsodyAbout (options: RegisterServerOptions): Promise<string>
return ctl.message
}
async function reloadProsody (options: RegisterServerOptions): Promise<boolean> {
const reload = await prosodyCtl(options, 'reload')
if (reload.code) {
options.peertubeHelpers.logger.error('reloadProsody failed: ' + JSON.stringify(reload))
return false
}
return true
}
interface ProsodyRunning {
ok: boolean
messages: string[]
@ -208,9 +218,10 @@ async function ensureProsodyRunning (options: RegisterServerOptions): Promise<vo
}
if (!processStarted) {
logger.error('It seems that the Prosody process is not up')
} else {
logger.info('Prosody is running')
return
}
logger.info('Prosody is running')
startProsodyLogRotate(options, filePaths, reloadProsody)
}
async function ensureProsodyNotRunning (options: RegisterServerOptions): Promise<void> {
@ -218,6 +229,8 @@ async function ensureProsodyNotRunning (options: RegisterServerOptions): Promise
const logger = peertubeHelpers.logger
logger.info('Checking if Prosody is running, and shutting it down if so')
stopProsodyLogRotate(options)
// NB: this function is called on plugin unregister, even if prosody is not used
// so we must avoid creating the working dir now
const filePaths = await getProsodyFilePaths(options)

View File

@ -0,0 +1,91 @@
import type { ProsodyFilePaths } from './config/paths'
type Rotate = (file: string, options: {
count?: number
compress?: boolean
}, cb: Function) => void
const rotate: Rotate = require('log-rotate')
interface ProsodyLogRotate {
timer: NodeJS.Timeout
lastRotation: number
}
type ReloadProsody = (options: RegisterServerOptions) => Promise<boolean>
let logRotate: ProsodyLogRotate | undefined
async function _rotate (options: RegisterServerOptions, path: string): Promise<void> {
const p = new Promise<void>((resolve) => {
// I dont use compress.
// I guess that this could cause log losses, because the prosody reload will not happen immediatly.
rotate(path, { count: 14, compress: false }, (err: any) => {
if (err) {
options.peertubeHelpers.logger.error('Failed to rotate file ' + path, err)
return resolve()
}
return resolve()
})
})
return p
}
function startProsodyLogRotate (options: RegisterServerOptions, paths: ProsodyFilePaths, reload: ReloadProsody): void {
const logger = options.peertubeHelpers.logger
const checkInterval = process.env.NODE_ENV === 'test' ? 60 * 1000 : 60 * 60 * 1000 // check every hour
const rotateEvery = process.env.NODE_ENV === 'test' ? 2 * 60 * 1000 : 24 * 60 * 60 * 1000 // rotate every 24hour
// TODO: also rotate when file is too big
if (logRotate) {
stopProsodyLogRotate(options)
}
logger.info('Starting Prosody log rotation')
const timer = setInterval(() => {
logger.debug('Checking if Prosody logs need to be rotated')
if (!logRotate) {
logger.error('Seems that we dont need to rotate Prosody logs, but the timer was called.')
return
}
if (logRotate.lastRotation + rotateEvery - 1000 > Date.now()) {
// minus 1000 to not miss next check
logger.debug('To soon to rotate.')
return
}
logger.info('Rotating Prosody log files.')
logRotate.lastRotation = Date.now()
const p = Promise.all([
_rotate(options, paths.log),
_rotate(options, paths.error)
])
p.then(() => {
reload(options).then(() => {
logger.debug('Prosody reloaded')
}, () => {
logger.error('Prosody failed to reload')
})
}, (err) => {
logger.error('Failed rotating logs', err)
})
}, checkInterval)
logRotate = {
timer: timer,
lastRotation: Date.now()
}
}
function stopProsodyLogRotate (options: RegisterServerOptions): void {
const logger = options.peertubeHelpers.logger
if (logRotate === undefined) {
return
}
logger.info('Stoping Prosody log rotation')
clearInterval(logRotate.timer)
}
export {
startProsodyLogRotate,
stopProsodyLogRotate
}