A flexible logging utility that supports multiple destinations, making it easy to manage and extend project-wide logging strategies.
Install the package via your preferred package manager:
npm i @anakin-gbit/create-logger@latest
Call the logger factory with callerInfo
, and use the returned function in place of console.log()
:
import React from 'react'
import createLogger from '@anakin-gbit/create-logger'
const log = createLogger({
callerFileName: 'src/app/PrivacyPolicy/page.tsx',
callerFunction: 'PrivacyPolicyPage',
})
const PrivacyPolicyPage = () => {
log('Page rendered')
return <h1>Policy page</h1>
}
export default PrivacyPolicyPage
This will produce an output like:
[INFO]: Page rendered {
callerInfo: {
callerFileName: 'src/app/PrivacyPolicy/page.tsx',
callerFunction: 'PrivacyPolicyPage'
}
}
To override the default logToConsole
behavior, pass a destinations
array as the second argument:
import createLogger, {
logMessageOnlyToConsole,
logToConsole,
} from '@anakin-gbit/create-logger'
const log = createLogger(
{
callerFileName: 'src/app/PrivacyPolicy/page.tsx',
callerFunction: 'PrivacyPolicyPage',
},
{
destinations: [logMessageOnlyToConsole, logToConsole],
}
)
This works fine but is verbose and requires duplication across modules, making global logging changes harder.
Create a wrapper to centralize logging configuration, e.g. in src/lib/logger/index.ts
:
import createLoggerCore, {
logToConsole,
logMessageOnlyToConsole,
TLogger,
TCallerInfo,
} from 'anakin-gbit/create-logger'
const logDestinations = [logMessageOnlyToConsole, logToConsole]
const createLogger = (callerInfo: TCallerInfo): TLogger => {
return createLoggerCore(callerInfo, { destinations: logDestinations })
}
export { createLogger }
Now you can use consistent logging across the project without repeating configuration.
Once wrapped, using the logger is simple:
import { createLogger } from '@/lib/logger'
const log = createLogger({
callerFileName: 'src/app/PrivacyPolicy/page.tsx',
callerFunction: 'PrivacyPolicy',
})
You can now log messages like this:
log('Info message')
log('Warning with metadata', { meta: true }, 'warning')
log('Error with data', { error: 'details' }, 'error')
log('Caught exception', new Error('Something went wrong'))
Error
, the logger automatically sets the level to 'error'
.A destination is a function that receives:
message: string
data?: unknown
type: TMessageType
callerInfo: TCallerInfo
import fs from 'fs'
import path from 'path'
const logToFile: TLogHandler = (message, data, type, callerInfo) => {
let output = `[${new Date().toISOString()}] [${type}] [${callerInfo.callerFunction} in ${callerInfo.callerFileName}] ${message}`
if (data) {
output += `\nData: ${JSON.stringify(data)}`
}
fs.appendFileSync(path.resolve(__dirname, 'logs', 'application.log'), output + '\n')
}
🗂️ Ensure the
logs/
directory exists and is writable.
import createLoggerCore, {
logToConsole,
TLogger,
TCallerInfo,
} from 'anakin-gbit/create-logger'
import { logToFile } from './path/to/customDestinations'
const logDestinations = [logToConsole, logToFile]
const createLogger = (callerInfo: TCallerInfo): TLogger => {
return createLoggerCore(callerInfo, { destinations: logDestinations })
}
export { createLogger }
Now, all logs will go to the console and the log file.