npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@37bytes/logstory

v1.0.2

Published

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.

Downloads

61

Readme

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