@37bytes/logstory
TypeScript icon, indicating that this package has built-in type declarations

1.0.2 • Public • Published

Logstory

Logstory is a flexible and extensible logger for JavaScript that allows easy integration of additional features and sending events to monitoring systems such as Sentry or Graylog.

Key Features:

  • Easy Integration: The logger provides a convenient interface for embedding additional functions and middleware, allowing easy customization of its behavior according to the application's needs.
  • Middleware Support: The logger allows passing middleware that can handle or send events when warnings or errors occur. This enables integration with monitoring systems such as Sentry or Graylog for centralized log collection and analysis.
  • Configurable Log Level: The logger supports a customizable log level, allowing you to control the output of different message levels (debug, log, warn, error) based on your application requirements.
  • Development Environment Support: The logger automatically adapts to the development environment, allowing you to manage the log level based on the environment (e.g., enabling debug messages only in development mode).

Installation:

  • npm
    npm install @37bytes/logstory

Basic Usage:

createLogger.ts

import {
  applyConsoleProxyMiddleware,
  CreateLoggerParams,
  createLogstory,
  Logger,
  LogLevelState,
  MiddlewareFunction
} from '@37bytes/logstory';

// default settings
const defaultLogLevelState: LogLevelState = {
  debug: import.meta.env.DEV,
  log: import.meta.env.DEV,
  warn: true,
  error: true
};

export const createSimplePureLogger = (name: CreateLoggerParams['name']): Logger =>
  createLogstory({ name, logLevelState: defaultLogLevelState, consoleProxy: window.console });

// developming features
if (import.meta.env.DEV) {
  window.developingFeatures = window.developingFeatures || {};
  window.developingFeatures.createLogger = createLogstory;
  window.developingFeatures.createSimplePureLogger = createSimplePureLogger;
  createSimplePureLogger('createLogger').debug(
    'createLogger/createSimplePureLogger are available in window.developingFeatures'
  );
}

Example.tsx

const pureLogger = createSimplePureLogger('Test')

useEffect(() => {
  logger.debug('Debug message');
  logger.log('Log message');
  logger.warn('Warning message');
  logger.error('Error message');
}, [])

Change the logger name format:

You can customize the logger output to suit your needs

Default output

logger.debug('Debug message'); // -> 🥷[Feature]: debug message
logger.log('Log message'); // -> [Feature]: log message
logger.warn('Warning message'); // -> 😕😕😕️ [Test Feature]: Attention
logger.error('Error message'); // -> 🔥🔥🔥🔥🔥🔥\n[Test Feature]: Error

Your custom output

const customLoggerName = ({ loggerName, logLevel }: FormatLoggerNameParams): string => {
  if (logLevel === 'error') {
    return `! ${loggerName} !`;
  }
  return `[${loggerName}]`;
};

const logger = createLogstory({ name: 'Feature', formatLoggerName: customLoggerName });

logger.debug('Debug message'); // -> [Feature] debug message
logger.log('Log message'); // -> [Feature] log message
logger.warn('Warning message'); // -> [Feature] Attention
logger.error('Error message'); // -> ! Feature !: Error

Advanced Usage:

If you want to use Sentry or GrayLog with your logger, create a special console proxy and apply the applyConsoleProxyMiddleware function found in the package

createLogger.ts

import getTrackingServicesConsoleProxy from './getTrackingServicesConsoleProxy';
import {
  applyConsoleProxyMiddleware,
  CreateLoggerParams,
  createLogstory,
  Logger,
  LogLevelState,
  MiddlewareFunction
} from '@37bytes/logstory';

// default settings
const defaultLogLevelState: LogLevelState = {
  ebug: import.meta.env.DEV,
  log: import.meta.env.DEV,
  warn: true,
  error: true
};

// define your services for applyConsoleProxyMiddleware
export enum MiddlewareExtras {
  SENTRY = 'sentryExtra',
  GREY_LOG = 'greylogExtra'
}
export type ApplyMiddlewareMessage = unknown;
// you can specify different data
export type ApplyMiddlewareExtras = {
  [MiddlewareExtras.SENTRY]?: { tags: { loggerName: string } } // or & Record<string, unknown>;
  [MiddlewareExtras.GREY_LOG]?: { data: string[] } // or & Record<string, unknown>;
};

export type MiddlewareFunctionCallbackType = MiddlewareFunction<ApplyMiddlewareMessage, ApplyMiddlewareExtras>;

// Senrty 
const initSentry: MiddlewareFunctionCallbackType = ({ message, extras }) => {
  const { sentryExtra } = extras;
  Sentry.captureException(message, sentryExtra);
};

// Graylog
const initGrayLog: MiddlewareFunctionCallbackType = ({ message, extras }) => {
  const { greylogExtra } = extras;
  graylogLogger.warning(message as string, greylogExtra);
};

export const createSentryLogger = ({ name, logLevelState = defaultLogLevelState }: CreateLoggerParams = {}): Logger =>
  createLogger({
    name,
    logLevelState,
    consoleProxy: getTrackingServicesConsoleProxy(
        name,
        // use your console proxy and applyConsoleProxyMiddleware
        applyConsoleProxyMiddleware<ApplyMiddlewareMessage, ApplyMiddlewareExtras, MiddlewareFunctionCallbackType>([
            initSentry,
            initGrayLog
        ])
    )
});

export const createSimpleSentryLogger = (name: CreateLoggerParams['name']) => createSentryLogger({ name });

// developming features
if (import.meta.env.DEV) {
  window.developingFeatures = window.developingFeatures || {};
  window.developingFeatures.createSentryLogger = createSentryLogger;
  window.developingFeatures.createSimpleSentryLogger = createSimpleSentryLogger;
  createSimplePureLogger('createLogger').debug(
    'createLogger/createSentryLogger/createSimpleSentryLogger are available in window.developingFeatures'
  );
}

getTrackingServicesConsoleProxy.ts

import { LogLevel } from '@37bytes/logstory';
import { MiddlewareExtras, MiddlewareFunctionCallbackType } from './createLogger';

const sanitizePrefix = (prefix: unknown = '') => {
  if (typeof prefix !== 'string') {
    return '';
  }

  const startIndex = prefix.indexOf('[');
  if (startIndex >= 0) {
    return prefix.substring(startIndex);
  }

  return prefix;
};

const getTrackingServicesConsoleProxy = (
  loggerName: string = 'unknown',
  applyMiddleware: MiddlewareFunctionCallbackType
): Console =>
  new Proxy(console, {
    get(target, propKey, receiver) {
      switch (propKey as LogLevel) {
        case 'error':
            return function (...args: unknown[]) {
              // handle error and send data
              const [, error, extra] = args;
              applyMiddleware({
                message: error,
                extras: {
                  [MiddlewareExtras.SENTRY]: { tags: { loggerName } },
                  [MiddlewareExtras.GREY_LOG]: extra as ApplyMiddlewareExtras['graylogExtra']
                }
              });
              return Reflect.get(target, propKey, receiver)(...args);
        };
        case 'warn':
          return function (...args: unknown[]) {
              // handle warning and send data
              const [prefix, message, extra] = arguments;
              const fullMessage =
                  typeof message === 'string'
                      ? sanitizePrefix(prefix).replace('%o', message)
                      : 'Strange warning';

              applyMiddleware({
                  message: fullMessage,
                  extras: {
                      [MiddlewareExtras.SENTRY]: { tags: { loggerName } },
                      [MiddlewareExtras.GREY_LOG]: extra
                  }
              });

              return Reflect.get(target, propKey, receiver)(...args);
        };
        default:
            return Reflect.get(target, propKey, receiver);
      }
    }
  });

export default getTrackingServicesConsoleProxy;

logger call example

const logger = createSimpleSentryLogger('example');
logger.warn('Warn message')
logger.error(Error, { data: ['some data'] })

Issues

See the open issues for a full list of proposed features (and known issues).

version history

1.0.2

  • add formatLoggerName

1.0.1

  • fix readme

1.0.0

  • first version

Package Sidebar

Install

npm i @37bytes/logstory

Weekly Downloads

104

Version

1.0.2

License

MIT

Unpacked Size

12.9 kB

Total Files

11

Last publish

Collaborators

  • arhonist-37b
  • rispaev
  • yar_vav
  • rteslenko
  • tnikolaeva
  • dc.nikolaev
  • mgarmash