Skip to content

Commit

Permalink
feat: move log into monitoring extension
Browse files Browse the repository at this point in the history
  • Loading branch information
louis-jan committed Apr 9, 2024
1 parent 1244f03 commit 20d0593
Show file tree
Hide file tree
Showing 32 changed files with 635 additions and 373 deletions.
16 changes: 6 additions & 10 deletions core/src/node/api/processors/app.ts
Original file line number Diff line number Diff line change
@@ -1,9 1,12 @@
import { basename, isAbsolute, join, relative } from 'path'

import { Processor } from './Processor'
import { getAppConfigurations as appConfiguration, updateAppConfiguration } from '../../helper'
import { log as writeLog, logServer as writeServerLog } from '../../helper/log'
import { appResourcePath } from '../../helper/path'
import {
log as writeLog,
appResourcePath,
getAppConfigurations as appConfiguration,
updateAppConfiguration,
} from '../../helper'

export class App implements Processor {
observer?: Function
Expand Down Expand Up @@ -56,13 59,6 @@ export class App implements Processor {
writeLog(args)
}

/**
* Log message to log file.
*/
logServer(args: any) {
writeServerLog(args)
}

getAppConfigurations() {
return appConfiguration()
}
Expand Down
36 changes: 20 additions & 16 deletions core/src/node/api/restful/helper/startStopModel.ts
Original file line number Diff line number Diff line change
@@ -1,7 1,11 @@
import fs from 'fs'
import { join } from 'path'
import { getJanDataFolderPath, getJanExtensionsPath, getSystemResourceInfo } from '../../../helper'
import { logServer } from '../../../helper/log'
import {
getJanDataFolderPath,
getJanExtensionsPath,
getSystemResourceInfo,
log,
} from '../../../helper'
import { ChildProcessWithoutNullStreams, spawn } from 'child_process'
import { Model, ModelSettingParams, PromptTemplate } from '../../../../types'
import {
Expand Down Expand Up @@ -69,7 73,7 @@ const runModel = async (modelId: string, settingParams?: ModelSettingParams): Pr
}),
}

logServer(`[NITRO]::Debug: Nitro model settings: ${JSON.stringify(nitroModelSettings)}`)
log(`[SERVER]::Debug: Nitro model settings: ${JSON.stringify(nitroModelSettings)}`)

// Convert settings.prompt_template to system_prompt, user_prompt, ai_prompt
if (modelMetadata.settings.prompt_template) {
Expand Down Expand Up @@ -140,7 144,7 @@ const runNitroAndLoadModel = async (modelId: string, modelSettings: NitroModelSe
}

const spawnNitroProcess = async (): Promise<void> => {
logServer(`[NITRO]::Debug: Spawning Nitro subprocess...`)
log(`[SERVER]::Debug: Spawning Nitro subprocess...`)

let binaryFolder = join(
getJanExtensionsPath(),
Expand All @@ -155,8 159,8 @@ const spawnNitroProcess = async (): Promise<void> => {

const args: string[] = ['1', LOCAL_HOST, NITRO_DEFAULT_PORT.toString()]
// Execute the binary
logServer(
`[NITRO]::Debug: Spawn nitro at path: ${executableOptions.executablePath}, and args: ${args}`
log(
`[SERVER]::Debug: Spawn nitro at path: ${executableOptions.executablePath}, and args: ${args}`
)
subprocess = spawn(
executableOptions.executablePath,
Expand All @@ -172,20 176,20 @@ const spawnNitroProcess = async (): Promise<void> => {

// Handle subprocess output
subprocess.stdout.on('data', (data: any) => {
logServer(`[NITRO]::Debug: ${data}`)
log(`[SERVER]::Debug: ${data}`)
})

subprocess.stderr.on('data', (data: any) => {
logServer(`[NITRO]::Error: ${data}`)
log(`[SERVER]::Error: ${data}`)
})

subprocess.on('close', (code: any) => {
logServer(`[NITRO]::Debug: Nitro exited with code: ${code}`)
log(`[SERVER]::Debug: Nitro exited with code: ${code}`)
subprocess = undefined
})

tcpPortUsed.waitUntilUsed(NITRO_DEFAULT_PORT, 300, 30000).then(() => {
logServer(`[NITRO]::Debug: Nitro is ready`)
log(`[SERVER]::Debug: Nitro is ready`)
})
}

Expand Down Expand Up @@ -271,7 275,7 @@ const validateModelStatus = async (): Promise<void> => {
retries: 5,
retryDelay: 500,
}).then(async (res: Response) => {
logServer(`[NITRO]::Debug: Validate model state success with response ${JSON.stringify(res)}`)
log(`[SERVER]::Debug: Validate model state success with response ${JSON.stringify(res)}`)
// If the response is OK, check model_loaded status.
if (res.ok) {
const body = await res.json()
Expand All @@ -286,7 290,7 @@ const validateModelStatus = async (): Promise<void> => {
}

const loadLLMModel = async (settings: NitroModelSettings): Promise<Response> => {
logServer(`[NITRO]::Debug: Loading model with params ${JSON.stringify(settings)}`)
log(`[SERVER]::Debug: Loading model with params ${JSON.stringify(settings)}`)
const fetchRT = require('fetch-retry')
const fetchRetry = fetchRT(fetch)

Expand All @@ -300,11 304,11 @@ const loadLLMModel = async (settings: NitroModelSettings): Promise<Response> =>
retryDelay: 500,
})
.then((res: any) => {
logServer(`[NITRO]::Debug: Load model success with response ${JSON.stringify(res)}`)
log(`[SERVER]::Debug: Load model success with response ${JSON.stringify(res)}`)
return Promise.resolve(res)
})
.catch((err: any) => {
logServer(`[NITRO]::Error: Load model failed with error ${err}`)
log(`[SERVER]::Error: Load model failed with error ${err}`)
return Promise.reject(err)
})
}
Expand All @@ -327,7 331,7 @@ export const stopModel = async (_modelId: string) => {
})
}, 5000)
const tcpPortUsed = require('tcp-port-used')
logServer(`[NITRO]::Debug: Request to kill Nitro`)
log(`[SERVER]::Debug: Request to kill Nitro`)

fetch(NITRO_HTTP_KILL_URL, {
method: 'DELETE',
Expand All @@ -341,7 345,7 @@ export const stopModel = async (_modelId: string) => {
// don't need to do anything, we still kill the subprocess
})
.then(() => tcpPortUsed.waitUntilFree(NITRO_DEFAULT_PORT, 300, 5000))
.then(() => logServer(`[NITRO]::Debug: Nitro process is terminated`))
.then(() => log(`[SERVER]::Debug: Nitro process is terminated`))
.then(() =>
resolve({
message: 'Model stopped',
Expand Down
28 changes: 0 additions & 28 deletions core/src/node/helper/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,31 150,3 @@ export const getEngineConfiguration = async (engineId: string) => {
full_url: undefined,
}
}

/**
* Utility function to get server log path
*
* @returns {string} The log path.
*/
export const getServerLogPath = (): string => {
const appConfigurations = getAppConfigurations()
const logFolderPath = join(appConfigurations.data_folder, 'logs')
if (!fs.existsSync(logFolderPath)) {
fs.mkdirSync(logFolderPath, { recursive: true })
}
return join(logFolderPath, 'server.log')
}

/**
* Utility function to get app log path
*
* @returns {string} The log path.
*/
export const getAppLogPath = (): string => {
const appConfigurations = getAppConfigurations()
const logFolderPath = join(appConfigurations.data_folder, 'logs')
if (!fs.existsSync(logFolderPath)) {
fs.mkdirSync(logFolderPath, { recursive: true })
}
return join(logFolderPath, 'app.log')
}
2 changes: 1 addition & 1 deletion core/src/node/helper/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 1,6 @@
export * from './config'
export * from './download'
export * from './log'
export * from './logger'
export * from './module'
export * from './path'
export * from './resource'
37 changes: 0 additions & 37 deletions core/src/node/helper/log.ts

This file was deleted.

81 changes: 81 additions & 0 deletions core/src/node/helper/logger.ts
Original file line number Diff line number Diff line change
@@ -0,0 1,81 @@
// Abstract Logger class that all loggers should extend.
export abstract class Logger {
// Each logger must have a unique name.
abstract name: string

/**
* Log message to log file.
* This method should be overridden by subclasses to provide specific logging behavior.
*/
abstract log(args: any): void
}

// LoggerManager is a singleton class that manages all registered loggers.
export class LoggerManager {
// Map of registered loggers, keyed by their names.
public loggers = new Map<string, Logger>()

// Array to store logs that are queued before the loggers are registered.
queuedLogs: any[] = []

// Flag to indicate whether flushLogs is currently running.
private isFlushing = false

// Register a new logger. If a logger with the same name already exists, it will be replaced.
register(logger: Logger) {
this.loggers.set(logger.name, logger)
}
// Unregister a logger by its name.
unregister(name: string) {
this.loggers.delete(name)
}

get(name: string) {
return this.loggers.get(name)
}

// Flush queued logs to all registered loggers.
flushLogs() {
// If flushLogs is already running, do nothing.
if (this.isFlushing) {
return
}

this.isFlushing = true

while (this.queuedLogs.length > 0 && this.loggers.size > 0) {
const log = this.queuedLogs.shift()
this.loggers.forEach((logger) => {
logger.log(log)
})
}

this.isFlushing = false
}

// Log message using all registered loggers.
log(args: any) {
this.queuedLogs.push(args)

this.flushLogs()
}

/**
* The instance of the logger.
* If an instance doesn't exist, it creates a new one.
* This ensures that there is only one LoggerManager instance at any time.
*/
static instance(): LoggerManager {
let instance: LoggerManager | undefined = global.core?.logger
if (!instance) {
instance = new LoggerManager()
if (!global.core) global.core = {}
global.core.logger = instance
}
return instance
}
}

export const log = (...args: any) => {
LoggerManager.instance().log(args)
}
5 changes: 2 additions & 3 deletions core/src/node/helper/resource.ts
Original file line number Diff line number Diff line change
@@ -1,11 1,10 @@
import { SystemResourceInfo } from '../../types'
import { physicalCpuCount } from './config'
import { log } from './log'
import { log } from './logger'

export const getSystemResourceInfo = async (): Promise<SystemResourceInfo> => {
const cpu = await physicalCpuCount()
const message = `[NITRO]::CPU informations - ${cpu}`
log(message)
log(`[NITRO]::CPU informations - ${cpu}`)

return {
numCpuPhysicalCore: cpu,
Expand Down
12 changes: 12 additions & 0 deletions core/src/types/monitoring/monitoringInterface.ts
Original file line number Diff line number Diff line change
@@ -1,3 1,5 @@
import { GpuSetting, OperatingSystemInfo } from '../miscellaneous'

/**
* Monitoring extension for system monitoring.
* @extends BaseExtension
Expand All @@ -14,4 16,14 @@ export interface MonitoringInterface {
* @returns {Promise<any>} A promise that resolves with the current system load.
*/
getCurrentLoad(): Promise<any>

/**
* Returns the GPU configuration.
*/
getGpuSetting(): Promise<GpuSetting>

/**
* Returns information about the operating system.
*/
getOsInfo(): Promise<OperatingSystemInfo>
}
3 changes: 0 additions & 3 deletions electron/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 24,6 @@ import { cleanUpAndQuit } from './utils/clean'
import { setupExtensions } from './utils/extension'
import { setupCore } from './utils/setup'
import { setupReactDevTool } from './utils/dev'
import { cleanLogs } from './utils/log'

import { trayManager } from './managers/tray'
import { logSystemInfo } from './utils/system'
Expand Down Expand Up @@ -75,7 74,6 @@ app
}
})
})
.then(() => cleanLogs())

app.on('second-instance', (_event, _commandLine, _workingDirectory) => {
windowManager.showMainWindow()
Expand Down Expand Up @@ -111,7 109,6 @@ function createMainWindow() {
windowManager.createMainWindow(preloadPath, startUrl)
}


/**
* Handles various IPC messages from the renderer process.
*/
Expand Down
Loading

0 comments on commit 20d0593

Please sign in to comment.