135 lines
4.2 KiB
TypeScript
135 lines
4.2 KiB
TypeScript
import * as fs from 'fs'
|
|
import { createGzip } from 'zlib'
|
|
import { pino, transport } from 'pino'
|
|
import { createTransport } from 'nodemailer'
|
|
import { config } from 'dotenv'
|
|
|
|
export default defineNuxtPlugin(() => {
|
|
useNuxtApp().$logger.log('[logger.server.ts] Plugin geladen!')
|
|
// Format the Date in log file name
|
|
const getCurrentDate = () => {
|
|
const now = new Date()
|
|
const year = now.getFullYear()
|
|
const month = String(now.getMonth() + 1).padStart(2, '0') // Monat von 0-11
|
|
const day = String(now.getDate()).padStart(2, '0')
|
|
return `${year}-${month}-${day}`
|
|
}
|
|
|
|
config()
|
|
// Standardwerte für Konfiguration
|
|
const maxFiles = parseInt(process.env.LOG_MAX_FILES || '10') // Maximale Anzahl von Log-Dateien
|
|
const logDirectory = process.env.LOG_DIRECTORY || './logs' // Verzeichnis für Log-Dateien
|
|
const alertThreshold = parseInt(process.env.LOG_ALERT_THRESHOLD || '5') // Warnschwelle für Log-Dateien
|
|
const alertEmail =
|
|
process.env.LOG_ALERT_EMAIL || 'robert.rapp@mindboost.team' // E-Mail-Adresse für Warnungen
|
|
const checkInterval = parseInt(
|
|
process.env.LOG_CHECK_INTERVAL || (30 * 60 * 1000).toString()
|
|
) // Überwachungsintervall
|
|
const currentDate = getCurrentDate() // Format: 2023-11-27
|
|
|
|
// Sicherstellen, dass das Log-Verzeichnis existiert
|
|
if (!fs.existsSync(logDirectory)) {
|
|
fs.mkdirSync(logDirectory, { recursive: true })
|
|
}
|
|
|
|
// Transport für Pino
|
|
const pinotransport = transport({
|
|
target: 'pino/file',
|
|
options: {
|
|
destination: `${logDirectory}/app-${currentDate}.log`,
|
|
mkdir: true,
|
|
rotate: {
|
|
interval: '1d', // Log-Rotation täglich
|
|
size: '10M' // Maximalgröße für einzelne Logs
|
|
}
|
|
}
|
|
})
|
|
|
|
// Logger erstellen
|
|
const logger = pino(pinotransport)
|
|
// Funktion zur E-Mail-Benachrichtigung
|
|
async function sendAlertEmail (fileCount: number) {
|
|
const transporter = createTransport({
|
|
host: process.env.SMTP_HOST,
|
|
port: parseInt(process.env.SMTP_PORT || '465'),
|
|
secure: process.env.SMTP_SECURE === 'true', // TLS/SSL basierend auf ENV
|
|
auth: {
|
|
user: process.env.SMTP_USER,
|
|
pass: process.env.SMTP_PASS
|
|
}
|
|
})
|
|
|
|
const message = {
|
|
from: process.env.SMTP_USER || 'app@mindboost.team',
|
|
to: alertEmail,
|
|
subject: 'Warnung: Hohe Anzahl von Log-Dateien',
|
|
text: `Es wurden heute bereits ${fileCount} Log-Dateien erstellt. Schau es dir bitte mal an.`
|
|
}
|
|
|
|
try {
|
|
await transporter.sendMail(message)
|
|
logger.info('Warn-E-Mail wurde erfolgreich gesendet.')
|
|
} catch (error) {
|
|
logger.error('Fehler beim Senden der Warn-E-Mail:', error)
|
|
}
|
|
}
|
|
|
|
// Funktion zur Überwachung der Log-Dateien
|
|
function monitorLogs () {
|
|
fs.readdir(logDirectory, (err, files) => {
|
|
if (err) {
|
|
logger.error('Fehler beim Lesen des Log-Verzeichnisses:', err)
|
|
return
|
|
}
|
|
const logFiles = files.filter(file => file.endsWith('.log'))
|
|
logger.info(`Aktuelle Anzahl von Log-Dateien: ${logFiles.length}`)
|
|
|
|
if (logFiles.length >= alertThreshold) {
|
|
sendAlertEmail(logFiles.length)
|
|
}
|
|
|
|
if (logFiles.length > maxFiles) {
|
|
zipOldLogs(logFiles)
|
|
}
|
|
})
|
|
}
|
|
// Funktion zum Zippen alter Logs
|
|
function zipOldLogs (logFiles: string[]) {
|
|
const filesToZip = logFiles.slice(0, logFiles.length - maxFiles)
|
|
filesToZip.forEach((file) => {
|
|
const inputPath = `${logDirectory}/${file}`
|
|
const outputPath = `${inputPath}.gz`
|
|
|
|
const gzip = createGzip()
|
|
const source = fs.createReadStream(inputPath)
|
|
const destination = fs.createWriteStream(outputPath)
|
|
|
|
source
|
|
.pipe(gzip)
|
|
.pipe(destination)
|
|
.on('finish', () => {
|
|
fs.unlinkSync(inputPath) // Originaldatei löschen
|
|
logger.info(`Log-Datei wurde erfolgreich gezippt: ${outputPath}`)
|
|
})
|
|
.on('error', (err) => {
|
|
logger.error(`Fehler beim Zippen der Log-Datei ${file}:`, err)
|
|
})
|
|
})
|
|
}
|
|
|
|
// Log-Rotation überwachen
|
|
pinotransport.on('drain', () => {
|
|
logger.info('Neue Log-Datei wurde erstellt oder rotiert.')
|
|
monitorLogs()
|
|
})
|
|
|
|
// Überwachung alle 30 Minuten ausführen
|
|
setInterval(monitorLogs, checkInterval)
|
|
|
|
return {
|
|
provide: {
|
|
logger
|
|
}
|
|
}
|
|
})
|