Skip to content

Commit

Permalink
chore: add back app logging function (#4614)
Browse files Browse the repository at this point in the history
  • Loading branch information
louis-menlo authored Feb 9, 2025
1 parent a9a63ab commit 05b124f
Show file tree
Hide file tree
Showing 2 changed files with 169 additions and 0 deletions.
2 changes: 2 additions & 0 deletions electron/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { setupReactDevTool } from './utils/dev'
import { trayManager } from './managers/tray'
import { logSystemInfo } from './utils/system'
import { registerGlobalShortcuts } from './utils/shortcut'
import { registerLogger } from './utils/logger'

const preloadPath = join(__dirname, 'preload.js')
const rendererPath = join(__dirname, '..', 'renderer')
Expand Down Expand Up @@ -79,6 +80,7 @@ app
})
.then(setupCore)
.then(createUserSpace)
.then(registerLogger)
.then(migrate)
.then(setupExtensions)
.then(setupMenu)
Expand Down
167 changes: 167 additions & 0 deletions electron/utils/logger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
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()
}

0 comments on commit 05b124f

Please sign in to comment.