refactor[Logger]: filtering logs with environment variable (#8299)

refactor(Logger): enhance logging with environment variable support

- Updated LoggerService to utilize environment variables for filtering logs by level and module in development mode.
- Modified the logging level handling to use constants from the logger configuration.
- Enhanced documentation to include details on using environment variables for log filtering in both English and Chinese documentation files.
- Cleaned up unused type definitions related to logging.
This commit is contained in:
fullex 2025-07-21 09:37:48 +08:00 committed by GitHub
parent ebe7cce161
commit 5204438c0c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 204 additions and 60 deletions

View File

@ -135,12 +135,36 @@ If the worker is relatively simple (just one file), you can also use method chai
const logger = loggerService.initWindowSource('Worker').withContext('LetsWork') const logger = loggerService.initWindowSource('Worker').withContext('LetsWork')
``` ```
## Filtering Logs with Environment Variables
In a development environment, you can define environment variables to filter displayed logs by level and module. This helps developers focus on their specific logs and improves development efficiency.
Environment variables can be set in the terminal or defined in the `.env` file in the project's root directory. The available variables are as follows:
| Variable Name | Description |
| ------- | ------- |
| CSLOGGER_MAIN_LEVEL | Log level for the `main` process. Logs below this level will not be displayed. |
| CSLOGGER_MAIN_SHOW_MODULES | Filters log modules for the `main` process. Use a comma (`,`) to separate modules. The filter is case-sensitive. Only logs from modules in this list will be displayed. |
| CSLOGGER_RENDERER_LEVEL | Log level for the `renderer` process. Logs below this level will not be displayed. |
| CSLOGGER_RENDERER_SHOW_MODULES | Filters log modules for the `renderer` process. Use a comma (`,`) to separate modules. The filter is case-sensitive. Only logs from modules in this list will be displayed. |
Example:
```bash
CSLOGGER_MAIN_LEVEL=verbose
CSLOGGER_MAIN_SHOW_MODULES=MCPService,SelectionService
```
Note:
- Environment variables are only effective in the development environment.
- These variables only affect the logs displayed in the terminal or DevTools. They do not affect file logging or the `logToMain` recording logic.
## Log Level Usage Guidelines ## Log Level Usage Guidelines
There are many log levels. The following are the guidelines that should be followed in CherryStudio for when to use each level: There are many log levels. The following are the guidelines that should be followed in CherryStudio for when to use each level:
(Arranged from highest to lowest log level) (Arranged from highest to lowest log level)
| Log Level | Core Definition & Use Case | Example | | Log Level | Core Definition & Use case | Example |
| :------------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | :------------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`error`** | **Critical error causing the program to crash or core functionality to become unusable.** <br> This is the highest-priority log, usually requiring immediate reporting or user notification. | - Main or renderer process crash. <br> - Failure to read/write critical user data files (e.g., database, configuration files), preventing the application from running. <br> - All unhandled exceptions. | | **`error`** | **Critical error causing the program to crash or core functionality to become unusable.** <br> This is the highest-priority log, usually requiring immediate reporting or user notification. | - Main or renderer process crash. <br> - Failure to read/write critical user data files (e.g., database, configuration files), preventing the application from running. <br> - All unhandled exceptions. |
| **`warn`** | **Potential issue or unexpected situation that does not affect the program's core functionality.** <br> The program can recover or use a fallback. | - Configuration file `settings.json` is missing; started with default settings. <br> - Auto-update check failed, but does not affect the use of the current version. <br> - A non-essential plugin failed to load. | | **`warn`** | **Potential issue or unexpected situation that does not affect the program's core functionality.** <br> The program can recover or use a fallback. | - Configuration file `settings.json` is missing; started with default settings. <br> - Auto-update check failed, but does not affect the use of the current version. <br> - A non-essential plugin failed to load. |

View File

@ -136,6 +136,30 @@ logger.info('message', { logToMain: true })
const logger = loggerService.initWindowSource('Worker').withContext('LetsWork') const logger = loggerService.initWindowSource('Worker').withContext('LetsWork')
``` ```
## 使用环境变量来筛选要显示的日志
在开发环境中可以通过环境变量的定义来筛选要显示的日志的级别和module。开发者可以专注于自己的日志提高开发效率。
环境变量可以在终端中自行设置,或者在开发根目录的`.env`文件中进行定义,可以定义的变量如下:
| 变量名 | 含义 |
| ----- | ----- |
| CSLOGGER_MAIN_LEVEL | 用于`main`进程的日志级别,低于该级别的日志将不显示 |
| CSLOGGER_MAIN_SHOW_MODULES | 用于`main`进程的日志module筛选用`,`分隔区分大小写。只有在该列表中的module的日志才会显示 |
| CSLOGGER_RENDERER_LEVEL | 用于`renderer`进程的日志级别,低于该级别的日志将不显示 |
| CSLOGGER_RENDERER_SHOW_MODULES | 用于`renderer`进程的日志module筛选用`,`分隔区分大小写。只有在该列表中的module的日志才会显示 |
示例:
```bash
CSLOGGER_MAIN_LEVEL=vebose
CSLOGGER_MAIN_SHOW_MODULES=MCPService,SelectionService
```
注意:
- 环境变量仅在开发环境中生效
- 该变量仅会改变在终端或在devTools中显示的日志不会影响文件日志和`logToMain`的记录逻辑
## 日志级别的使用规范 ## 日志级别的使用规范
日志有很多级别什么时候应该用哪个级别下面是在CherryStudio中应该遵循的规范 日志有很多级别什么时候应该用哪个级别下面是在CherryStudio中应该遵循的规范

View File

@ -22,7 +22,7 @@
}, },
"scripts": { "scripts": {
"start": "electron-vite preview", "start": "electron-vite preview",
"dev": "electron-vite dev", "dev": "dotenv electron-vite dev",
"debug": "electron-vite -- --inspect --sourcemap --remote-debugging-port=9222", "debug": "electron-vite -- --inspect --sourcemap --remote-debugging-port=9222",
"build": "npm run typecheck && electron-vite build", "build": "npm run typecheck && electron-vite build",
"build:check": "yarn typecheck && yarn check:i18n && yarn test", "build:check": "yarn typecheck && yarn check:i18n && yarn test",

View File

@ -0,0 +1,28 @@
export type LogSourceWithContext = {
process: 'main' | 'renderer'
window?: string // only for renderer process
module?: string
context?: Record<string, any>
}
export type LogLevel = 'error' | 'warn' | 'info' | 'debug' | 'verbose' | 'silly' | 'none'
export const LEVEL = {
ERROR: 'error',
WARN: 'warn',
INFO: 'info',
DEBUG: 'debug',
VERBOSE: 'verbose',
SILLY: 'silly',
NONE: 'none'
} satisfies Record<string, LogLevel>
export const LEVEL_MAP: Record<LogLevel, number> = {
error: 10,
warn: 8,
info: 6,
debug: 4,
verbose: 2,
silly: 0,
none: -1
}

View File

@ -9,12 +9,3 @@ export type LoaderReturn = {
message?: string message?: string
messageSource?: 'preprocess' | 'embedding' messageSource?: 'preprocess' | 'embedding'
} }
export type LogSourceWithContext = {
process: 'main' | 'renderer'
window?: string // only for renderer process
module?: string
context?: Record<string, any>
}
export type LogLevel = 'error' | 'warn' | 'info' | 'debug' | 'verbose' | 'silly'

View File

@ -1,4 +1,5 @@
import type { LogLevel, LogSourceWithContext } from '@shared/config/types' import type { LogLevel, LogSourceWithContext } from '@shared/config/logger'
import { LEVEL, LEVEL_MAP } from '@shared/config/logger'
import { IpcChannel } from '@shared/IpcChannel' import { IpcChannel } from '@shared/IpcChannel'
import { app, ipcMain } from 'electron' import { app, ipcMain } from 'electron'
import os from 'os' import os from 'os'
@ -38,7 +39,7 @@ const SYSTEM_INFO = {
} }
const APP_VERSION = `v${app?.getVersion?.() || 'unknown'}` const APP_VERSION = `v${app?.getVersion?.() || 'unknown'}`
const DEFAULT_LEVEL = isDev ? 'silly' : 'info' const DEFAULT_LEVEL = isDev ? LEVEL.SILLY : LEVEL.INFO
/** /**
* IMPORTANT: How to use LoggerService * IMPORTANT: How to use LoggerService
@ -50,6 +51,10 @@ class LoggerService {
private static instance: LoggerService private static instance: LoggerService
private logger: winston.Logger private logger: winston.Logger
// env variables, only used in dev mode
private envLevel: LogLevel = LEVEL.NONE
private envShowModules: string[] = []
private logsDir: string = '' private logsDir: string = ''
private module: string = '' private module: string = ''
@ -63,6 +68,34 @@ class LoggerService {
// Create logs directory path // Create logs directory path
this.logsDir = path.join(app.getPath('userData'), 'logs') this.logsDir = path.join(app.getPath('userData'), 'logs')
// env variables, only used in dev mode
// only affect console output, not affect file output
if (isDev) {
// load env level if exists
if (
process.env.CSLOGGER_MAIN_LEVEL &&
Object.values(LEVEL).includes(process.env.CSLOGGER_MAIN_LEVEL as LogLevel)
) {
this.envLevel = process.env.CSLOGGER_MAIN_LEVEL as LogLevel
// eslint-disable-next-line no-restricted-syntax
console.log(colorText(`[LoggerService] env CSLOGGER_MAIN_LEVEL loaded: ${this.envLevel}`, 'BLUE'))
}
// load env show module if exists
if (process.env.CSLOGGER_MAIN_SHOW_MODULES) {
const showModules = process.env.CSLOGGER_MAIN_SHOW_MODULES.split(',')
.map((module) => module.trim())
.filter((module) => module !== '')
if (showModules.length > 0) {
this.envShowModules = showModules
// eslint-disable-next-line no-restricted-syntax
console.log(
colorText(`[LoggerService] env CSLOGGER_MAIN_SHOW_MODULES loaded: ${this.envShowModules.join(' ')}`, 'BLUE')
)
}
}
}
// Configure transports based on environment // Configure transports based on environment
const transports: winston.transport[] = [] const transports: winston.transport[] = []
@ -89,7 +122,8 @@ class LoggerService {
// Configure Winston logger // Configure Winston logger
this.logger = winston.createLogger({ this.logger = winston.createLogger({
level: DEFAULT_LEVEL, // Development: all levels, Production: info and above // Development: all levels, Production: info and above
level: DEFAULT_LEVEL,
format: winston.format.combine( format: winston.format.combine(
winston.format.splat(), winston.format.splat(),
winston.format.timestamp({ winston.format.timestamp({
@ -155,6 +189,15 @@ class LoggerService {
*/ */
private processLog(source: LogSourceWithContext, level: LogLevel, message: string, meta: any[]): void { private processLog(source: LogSourceWithContext, level: LogLevel, message: string, meta: any[]): void {
if (isDev) { if (isDev) {
// skip if env level is set and current level is less than env level
if (this.envLevel !== LEVEL.NONE && LEVEL_MAP[level] < LEVEL_MAP[this.envLevel]) {
return
}
// skip if env show modules is set and current module is not in the list
if (this.module && this.envShowModules.length > 0 && !this.envShowModules.includes(this.module)) {
return
}
const datetimeColored = colorText( const datetimeColored = colorText(
new Date().toLocaleString('zh-CN', { new Date().toLocaleString('zh-CN', {
hour: '2-digit', hour: '2-digit',
@ -174,39 +217,39 @@ class LoggerService {
} }
switch (level) { switch (level) {
case 'error': case LEVEL.ERROR:
// eslint-disable-next-line no-restricted-syntax // eslint-disable-next-line no-restricted-syntax
console.error( console.error(
`${datetimeColored} ${colorText(colorText('<ERROR>', 'RED'), 'BOLD')}${moduleString}${message}`, `${datetimeColored} ${colorText(colorText('<ERROR>', 'RED'), 'BOLD')}${moduleString}${message}`,
...meta ...meta
) )
break break
case 'warn': case LEVEL.WARN:
// eslint-disable-next-line no-restricted-syntax // eslint-disable-next-line no-restricted-syntax
console.warn( console.warn(
`${datetimeColored} ${colorText(colorText('<WARN>', 'YELLOW'), 'BOLD')}${moduleString}${message}`, `${datetimeColored} ${colorText(colorText('<WARN>', 'YELLOW'), 'BOLD')}${moduleString}${message}`,
...meta ...meta
) )
break break
case 'info': case LEVEL.INFO:
// eslint-disable-next-line no-restricted-syntax // eslint-disable-next-line no-restricted-syntax
console.info( console.info(
`${datetimeColored} ${colorText(colorText('<INFO>', 'GREEN'), 'BOLD')}${moduleString}${message}`, `${datetimeColored} ${colorText(colorText('<INFO>', 'GREEN'), 'BOLD')}${moduleString}${message}`,
...meta ...meta
) )
break break
case 'debug': case LEVEL.DEBUG:
// eslint-disable-next-line no-restricted-syntax // eslint-disable-next-line no-restricted-syntax
console.debug( console.debug(
`${datetimeColored} ${colorText(colorText('<DEBUG>', 'BLUE'), 'BOLD')}${moduleString}${message}`, `${datetimeColored} ${colorText(colorText('<DEBUG>', 'BLUE'), 'BOLD')}${moduleString}${message}`,
...meta ...meta
) )
break break
case 'verbose': case LEVEL.VERBOSE:
// eslint-disable-next-line no-restricted-syntax // eslint-disable-next-line no-restricted-syntax
console.log(`${datetimeColored} ${colorText('<VERBOSE>', 'BOLD')}${moduleString}${message}`, ...meta) console.log(`${datetimeColored} ${colorText('<VERBOSE>', 'BOLD')}${moduleString}${message}`, ...meta)
break break
case 'silly': case LEVEL.SILLY:
// eslint-disable-next-line no-restricted-syntax // eslint-disable-next-line no-restricted-syntax
console.log(`${datetimeColored} ${colorText('<SILLY>', 'BOLD')}${moduleString}${message}`, ...meta) console.log(`${datetimeColored} ${colorText('<SILLY>', 'BOLD')}${moduleString}${message}`, ...meta)
break break
@ -225,7 +268,7 @@ class LoggerService {
meta.push(sourceWithContext) meta.push(sourceWithContext)
// add extra system information for error and warn levels // add extra system information for error and warn levels
if (level === 'error' || level === 'warn') { if (level === LEVEL.ERROR || level === LEVEL.WARN) {
const extra = { const extra = {
sys: SYSTEM_INFO, sys: SYSTEM_INFO,
appver: APP_VERSION appver: APP_VERSION
@ -241,42 +284,42 @@ class LoggerService {
* Log error message * Log error message
*/ */
public error(message: string, ...data: any[]): void { public error(message: string, ...data: any[]): void {
this.processMainLog('error', message, data) this.processMainLog(LEVEL.ERROR, message, data)
} }
/** /**
* Log warning message * Log warning message
*/ */
public warn(message: string, ...data: any[]): void { public warn(message: string, ...data: any[]): void {
this.processMainLog('warn', message, data) this.processMainLog(LEVEL.WARN, message, data)
} }
/** /**
* Log info message * Log info message
*/ */
public info(message: string, ...data: any[]): void { public info(message: string, ...data: any[]): void {
this.processMainLog('info', message, data) this.processMainLog(LEVEL.INFO, message, data)
} }
/** /**
* Log verbose message * Log verbose message
*/ */
public verbose(message: string, ...data: any[]): void { public verbose(message: string, ...data: any[]): void {
this.processMainLog('verbose', message, data) this.processMainLog(LEVEL.VERBOSE, message, data)
} }
/** /**
* Log debug message * Log debug message
*/ */
public debug(message: string, ...data: any[]): void { public debug(message: string, ...data: any[]): void {
this.processMainLog('debug', message, data) this.processMainLog(LEVEL.DEBUG, message, data)
} }
/** /**
* Log silly level message * Log silly level message
*/ */
public silly(message: string, ...data: any[]): void { public silly(message: string, ...data: any[]): void {
this.processMainLog('silly', message, data) this.processMainLog(LEVEL.SILLY, message, data)
} }
/** /**
@ -304,7 +347,7 @@ class LoggerService {
* Set the minimum log level * Set the minimum log level
* @param level - The log level to set * @param level - The log level to set
*/ */
public setLevel(level: string): void { public setLevel(level: LogLevel): void {
this.logger.level = level this.logger.level = level
} }
@ -312,8 +355,8 @@ class LoggerService {
* Get the current log level * Get the current log level
* @returns The current log level * @returns The current log level
*/ */
public getLevel(): string { public getLevel(): LogLevel {
return this.logger.level return this.logger.level as LogLevel
} }
/** /**

View File

@ -3,7 +3,7 @@ import { electronAPI } from '@electron-toolkit/preload'
import { SpanEntity, TokenUsage } from '@mcp-trace/trace-core' import { SpanEntity, TokenUsage } from '@mcp-trace/trace-core'
import { SpanContext } from '@opentelemetry/api' import { SpanContext } from '@opentelemetry/api'
import { UpgradeChannel } from '@shared/config/constant' import { UpgradeChannel } from '@shared/config/constant'
import type { LogLevel, LogSourceWithContext } from '@shared/config/types' import type { LogLevel, LogSourceWithContext } from '@shared/config/logger'
import { IpcChannel } from '@shared/IpcChannel' import { IpcChannel } from '@shared/IpcChannel'
import { import {
AddMemoryOptions, AddMemoryOptions,

View File

@ -1,22 +1,14 @@
import type { LogLevel, LogSourceWithContext } from '@shared/config/types' import type { LogLevel, LogSourceWithContext } from '@shared/config/logger'
import { LEVEL, LEVEL_MAP } from '@shared/config/logger'
// check if the current process is a worker // check if the current process is a worker
const IS_WORKER = typeof window === 'undefined' const IS_WORKER = typeof window === 'undefined'
// check if we are in the dev env // check if we are in the dev env
// DO NOT use `constants.ts` here, because the files contains other dependencies that will fail in worker process
const IS_DEV = IS_WORKER ? false : window.electron?.process?.env?.NODE_ENV === 'development' const IS_DEV = IS_WORKER ? false : window.electron?.process?.env?.NODE_ENV === 'development'
// the level number is different from real definition, it only for convenience const DEFAULT_LEVEL = IS_DEV ? LEVEL.SILLY : LEVEL.INFO
const LEVEL_MAP: Record<LogLevel, number> = { const MAIN_LOG_LEVEL = LEVEL.WARN
error: 5,
warn: 4,
info: 3,
verbose: 2,
debug: 1,
silly: 0
}
const DEFAULT_LEVEL = IS_DEV ? 'silly' : 'info'
const MAIN_LOG_LEVEL = 'warn'
/** /**
* IMPORTANT: How to use LoggerService * IMPORTANT: How to use LoggerService
@ -27,6 +19,11 @@ const MAIN_LOG_LEVEL = 'warn'
class LoggerService { class LoggerService {
private static instance: LoggerService private static instance: LoggerService
// env variables, only used in dev mode
// only affect console output, not affect logToMain
private envLevel: LogLevel = LEVEL.NONE
private envShowModules: string[] = []
private level: LogLevel = DEFAULT_LEVEL private level: LogLevel = DEFAULT_LEVEL
private logToMainLevel: LogLevel = MAIN_LOG_LEVEL private logToMainLevel: LogLevel = MAIN_LOG_LEVEL
@ -35,7 +32,33 @@ class LoggerService {
private context: Record<string, any> = {} private context: Record<string, any> = {}
private constructor() { private constructor() {
// if (IS_DEV) {
if (
window.electron?.process?.env?.CSLOGGER_RENDERER_LEVEL &&
Object.values(LEVEL).includes(window.electron?.process?.env?.CSLOGGER_RENDERER_LEVEL as LogLevel)
) {
this.envLevel = window.electron?.process?.env?.CSLOGGER_RENDERER_LEVEL as LogLevel
// eslint-disable-next-line no-restricted-syntax
console.log(
`%c[LoggerService] env CSLOGGER_RENDERER_LEVEL loaded: ${this.envLevel}`,
'color: blue; font-weight: bold'
)
}
if (window.electron?.process?.env?.CSLOGGER_RENDERER_SHOW_MODULES) {
const showModules = window.electron?.process?.env?.CSLOGGER_RENDERER_SHOW_MODULES.split(',')
.map((module) => module.trim())
.filter((module) => module !== '')
if (showModules.length > 0) {
this.envShowModules = showModules
// eslint-disable-next-line no-restricted-syntax
console.log(
`%c[LoggerService] env CSLOGGER_RENDERER_SHOW_MODULES loaded: ${this.envShowModules.join(' ')}`,
'color: blue; font-weight: bold'
)
}
}
}
} }
/** /**
@ -96,36 +119,47 @@ class LoggerService {
return return
} }
const currentLevel = LEVEL_MAP[level]
// if in dev mode, check if the env variables are set and use the env level and show modules to skip logs
if (IS_DEV) {
if (this.envLevel !== LEVEL.NONE && currentLevel < LEVEL_MAP[this.envLevel]) {
return
}
if (this.module && this.envShowModules.length > 0 && !this.envShowModules.includes(this.module)) {
return
}
}
// skip log if level is lower than default level // skip log if level is lower than default level
const levelNumber = LEVEL_MAP[level] if (currentLevel < LEVEL_MAP[this.level]) {
if (levelNumber < LEVEL_MAP[this.level]) {
return return
} }
const logMessage = this.module ? `[${this.module}] ${message}` : message const logMessage = this.module ? `[${this.module}] ${message}` : message
switch (level) { switch (level) {
case 'error': case LEVEL.ERROR:
// eslint-disable-next-line no-restricted-syntax // eslint-disable-next-line no-restricted-syntax
console.error(logMessage, ...data) console.error(logMessage, ...data)
break break
case 'warn': case LEVEL.WARN:
// eslint-disable-next-line no-restricted-syntax // eslint-disable-next-line no-restricted-syntax
console.warn(logMessage, ...data) console.warn(logMessage, ...data)
break break
case 'info': case LEVEL.INFO:
// eslint-disable-next-line no-restricted-syntax // eslint-disable-next-line no-restricted-syntax
console.info(logMessage, ...data) console.info(logMessage, ...data)
break break
case 'verbose': case LEVEL.VERBOSE:
// eslint-disable-next-line no-restricted-syntax // eslint-disable-next-line no-restricted-syntax
console.log(logMessage, ...data) console.log(logMessage, ...data)
break break
case 'debug': case LEVEL.DEBUG:
// eslint-disable-next-line no-restricted-syntax // eslint-disable-next-line no-restricted-syntax
console.debug(logMessage, ...data) console.debug(logMessage, ...data)
break break
case 'silly': case LEVEL.SILLY:
// eslint-disable-next-line no-restricted-syntax // eslint-disable-next-line no-restricted-syntax
console.log(logMessage, ...data) console.log(logMessage, ...data)
break break
@ -134,7 +168,7 @@ class LoggerService {
// if the last data is an object with logToMain: true, force log to main // if the last data is an object with logToMain: true, force log to main
const forceLogToMain = data.length > 0 && data[data.length - 1]?.logToMain === true const forceLogToMain = data.length > 0 && data[data.length - 1]?.logToMain === true
if (levelNumber >= LEVEL_MAP[this.logToMainLevel] || forceLogToMain) { if (currentLevel >= LEVEL_MAP[this.logToMainLevel] || forceLogToMain) {
const source: LogSourceWithContext = { const source: LogSourceWithContext = {
process: 'renderer', process: 'renderer',
window: this.window, window: this.window,
@ -163,42 +197,42 @@ class LoggerService {
* Log error message * Log error message
*/ */
public error(message: string, ...data: any[]): void { public error(message: string, ...data: any[]): void {
this.processLog('error', message, data) this.processLog(LEVEL.ERROR, message, data)
} }
/** /**
* Log warning message * Log warning message
*/ */
public warn(message: string, ...data: any[]): void { public warn(message: string, ...data: any[]): void {
this.processLog('warn', message, data) this.processLog(LEVEL.WARN, message, data)
} }
/** /**
* Log info message * Log info message
*/ */
public info(message: string, ...data: any[]): void { public info(message: string, ...data: any[]): void {
this.processLog('info', message, data) this.processLog(LEVEL.INFO, message, data)
} }
/** /**
* Log verbose message * Log verbose message
*/ */
public verbose(message: string, ...data: any[]): void { public verbose(message: string, ...data: any[]): void {
this.processLog('verbose', message, data) this.processLog(LEVEL.VERBOSE, message, data)
} }
/** /**
* Log debug message * Log debug message
*/ */
public debug(message: string, ...data: any[]): void { public debug(message: string, ...data: any[]): void {
this.processLog('debug', message, data) this.processLog(LEVEL.DEBUG, message, data)
} }
/** /**
* Log silly level message * Log silly level message
*/ */
public silly(message: string, ...data: any[]): void { public silly(message: string, ...data: any[]): void {
this.processLog('silly', message, data) this.processLog(LEVEL.SILLY, message, data)
} }
/** /**