168 lines
4.3 KiB
TypeScript
168 lines
4.3 KiB
TypeScript
import {
|
|
createWriteStream,
|
|
existsSync,
|
|
mkdirSync,
|
|
readdir,
|
|
stat,
|
|
unlink,
|
|
writeFileSync,
|
|
} from 'fs'
|
|
import util from 'util'
|
|
import {
|
|
getAppConfigurations,
|
|
getJanDataFolderPath,
|
|
Logger,
|
|
LoggerManager,
|
|
} from '@janhq/core/node'
|
|
import path, { join } from 'path'
|
|
|
|
/**
|
|
* File Logger
|
|
*/
|
|
export class FileLogger implements Logger {
|
|
name = 'file'
|
|
logCleaningInterval: number = 120000
|
|
timeout: NodeJS.Timeout | undefined
|
|
appLogPath: string = './'
|
|
logEnabled: boolean = true
|
|
|
|
constructor(
|
|
logEnabled: boolean = true,
|
|
logCleaningInterval: number = 120000
|
|
) {
|
|
this.logEnabled = logEnabled
|
|
if (logCleaningInterval) this.logCleaningInterval = logCleaningInterval
|
|
|
|
const appConfigurations = getAppConfigurations()
|
|
const logFolderPath = join(appConfigurations.data_folder, 'logs')
|
|
if (!existsSync(logFolderPath)) {
|
|
mkdirSync(logFolderPath, { recursive: true })
|
|
}
|
|
|
|
this.appLogPath = join(logFolderPath, 'app.log')
|
|
}
|
|
|
|
log(args: any) {
|
|
if (!this.logEnabled) return
|
|
let message = args[0]
|
|
const scope = args[1]
|
|
if (!message) return
|
|
const path = this.appLogPath
|
|
if (!scope && !message.startsWith('[')) {
|
|
message = `[APP]::${message}`
|
|
} else if (scope) {
|
|
message = `${scope}::${message}`
|
|
}
|
|
|
|
message = `${new Date().toISOString()} ${message}`
|
|
|
|
writeLog(message, path)
|
|
}
|
|
|
|
cleanLogs(
|
|
maxFileSizeBytes?: number | undefined,
|
|
daysToKeep?: number | undefined
|
|
): void {
|
|
// clear existing timeout
|
|
// in case we rerun it with different values
|
|
if (this.timeout) clearTimeout(this.timeout)
|
|
this.timeout = undefined
|
|
|
|
if (!this.logEnabled) return
|
|
|
|
console.log(
|
|
'Validating app logs. Next attempt in ',
|
|
this.logCleaningInterval
|
|
)
|
|
|
|
const size = maxFileSizeBytes ?? 1 * 1024 * 1024 // 1 MB
|
|
const days = daysToKeep ?? 7 // 7 days
|
|
const logDirectory = path.join(getJanDataFolderPath(), 'logs')
|
|
// Perform log cleaning
|
|
const currentDate = new Date()
|
|
if (existsSync(logDirectory))
|
|
readdir(logDirectory, (err, files) => {
|
|
if (err) {
|
|
console.error('Error reading log directory:', err)
|
|
return
|
|
}
|
|
|
|
files.forEach((file) => {
|
|
const filePath = path.join(logDirectory, file)
|
|
stat(filePath, (err, stats) => {
|
|
if (err) {
|
|
console.error('Error getting file stats:', err)
|
|
return
|
|
}
|
|
|
|
// Check size
|
|
if (stats.size > size) {
|
|
unlink(filePath, (err) => {
|
|
if (err) {
|
|
console.error('Error deleting log file:', err)
|
|
return
|
|
}
|
|
console.debug(
|
|
`Deleted log file due to exceeding size limit: ${filePath}`
|
|
)
|
|
})
|
|
} else {
|
|
// Check age
|
|
const creationDate = new Date(stats.ctime)
|
|
const daysDifference = Math.floor(
|
|
(currentDate.getTime() - creationDate.getTime()) /
|
|
(1000 * 3600 * 24)
|
|
)
|
|
if (daysDifference > days) {
|
|
unlink(filePath, (err) => {
|
|
if (err) {
|
|
console.error('Error deleting log file:', err)
|
|
return
|
|
}
|
|
console.debug(`Deleted old log file: ${filePath}`)
|
|
})
|
|
}
|
|
}
|
|
})
|
|
})
|
|
})
|
|
|
|
// Schedule the next execution with doubled delays
|
|
this.timeout = setTimeout(
|
|
() => this.cleanLogs(maxFileSizeBytes, daysToKeep),
|
|
this.logCleaningInterval
|
|
)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Write log function implementation
|
|
* @param message
|
|
* @param logPath
|
|
*/
|
|
const writeLog = (message: string, logPath: string) => {
|
|
if (!existsSync(logPath)) {
|
|
const logDirectory = path.join(getJanDataFolderPath(), 'logs')
|
|
if (!existsSync(logDirectory)) {
|
|
mkdirSync(logDirectory)
|
|
}
|
|
writeFileSync(logPath, message)
|
|
} else {
|
|
const logFile = createWriteStream(logPath, {
|
|
flags: 'a',
|
|
})
|
|
logFile.write(util.format(message) + '\n')
|
|
logFile.close()
|
|
console.debug(message)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Register logger for global application logging
|
|
*/
|
|
export const registerLogger = () => {
|
|
const logger = new FileLogger()
|
|
LoggerManager.instance().register(logger)
|
|
logger.cleanLogs()
|
|
}
|