Log Factory

A flexible logging utility that supports multiple destinations, making it easy to manage and extend project-wide logging strategies.


Installation

Install the package via your preferred package manager:

bash
npm i @anakin-gbit/create-logger@latest

Usage

Option 1: Basic Usage

Call the logger factory with callerInfo, and use the returned function in place of console.log():

tsx
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:

bash
[INFO]: Page rendered {
  callerInfo: {
    callerFileName: 'src/app/PrivacyPolicy/page.tsx',
    callerFunction: 'PrivacyPolicyPage'
  }
}

Option 2: Specify Custom Destinations

To override the default logToConsole behavior, pass a destinations array as the second argument:

tsx
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.


Option 3 (Recommended): Create a Project-Level Wrapper

Create a wrapper to centralize logging configuration, e.g. in src/lib/logger/index.ts:

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.


Logging Example

Once wrapped, using the logger is simple:

ts
import { createLogger } from '@/lib/logger'

const log = createLogger({
  callerFileName: 'src/app/PrivacyPolicy/page.tsx',
  callerFunction: 'PrivacyPolicy',
})

You can now log messages like this:

ts
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'))
  • If the second argument is an Error, the logger automatically sets the level to 'error'.

Adding a Custom Destination

A destination is a function that receives:

  • message: string
  • data?: unknown
  • type: TMessageType
  • callerInfo: TCallerInfo

Step 1: Create the Destination

ts
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.


Step 2: Use It in Your Wrapper

ts
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.


Summary

  • Use the factory directly for quick setups.
  • Create a wrapper for consistency and maintainability.
  • Add custom destinations for flexible logging (e.g., file, API, external services).