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

@leaflink/snitch

v1.2.1

Published

Front end logging inspired by winston.

Downloads

1,447

Readme

@leaflink/snitch

Contact Us Released via semantic-release

Simple and extensible browser logging, inspired by Winston.

Table of Contents

Installation

$ npm i @leaflink/snitch

Transports

Transports are a way of routing log messages to multiple destinations, with the ability to pre-process or format the message. @leaflink/snitch includes three transports by default (console, Sentry, and Datadog), but they can be extended using the Transport type exported by the logger.

Log Levels

Transports can be created with a log level to only handle messages with a certain severity. Log levels supported by @leaflink/snitch, in decreasing order by severity, are:

  • error
  • warn
  • info
  • debug

These levels cascade up, so a transport created with level debug will handle logs with that level as well as info, warn, and error, but a transport created with level error will not handle logs with the levels warn, info, or debug.

The level a log was called at is passed to transports to help determine how a message should be handled (for example, logging with console.<level> in the console transport).

Usage

Singleton Logger

The default export exposed by @leaflink/snitch is a singleton logger instance with no initial transports, which can be shared between modules easily. It does not include any transports by default to allow flexibility in per-environment transports.

import logger from '@leaflink/snitch';
import { ConsoleTransport } from '@leaflink/snitch/transports/console';

if (config.debug) {
  logger.addTransport(new ConsoleTransport());
}

New Logger

| Name | Default | Description | | --- | --- | --- | | transports | [] | Define transports when creating new logger instead of adding with .addTransport |

In other situations, you may want to have a logger instance (or multiple instances) created and managed inside your application. To support this, @leaflink/snitch also exports a Logger class that can be used to create logger instances, optionally with predefined transports.

import { Logger } from '@leaflink/snitch';
import { ConsoleTransport } from '@leaflink/snitch/transports/console';

const loggerInstance = new Logger({
  transports: [new ConsoleTransport()],
});

// `logger.log` is an alias for `logger.info` for convenience
loggerInstance.log('Example log message');

Console Transport

Parameters:

| Name | Default | Description | | --- | --- | --- | | level | debug | Minimum log level to handle. |

main.ts

import logger from '@leaflink/snitch';
import { ConsoleTransport } from '@leaflink/snitch/transports/console';

logger.addTransport(new ConsoleTransport());

call in component file

import logger from '@leaflink/snitch';

try {
  await someErroringMethod()
} catch (err) {
  logger.error(err)
}

Sentry Transport

Parameters:

| Name | Default | Description | | --- | --- | --- | | level | debug | Minimum log level to handle. | | sentryInstance | N/A, required | Initialized Sentry logger instance. |

main.ts

import * as Sentry from '@sentry/vue';
import logger from '@leaflink/snitch';
import { SentryTransport } from '@leaflink/snitch/transports/sentry';

// Important: init Sentry instance before creating transport
Sentry.init({
  // ...
});
logger.addTransport(new SentryTransport({
  sentryInstance: Sentry,
}));

call in component file

import logger from '@leaflink/snitch';

try {
  await someErroringMethod()
} catch (err) {
  // optional error context object
  const errorContext: Record<string, any> = getErrorContext();
  // `err` is Error | string
  logger.error(err, errorContext);
}

Datadog Logs Transport

Parameters:

| Name | Default | Description | | --- | --- | --- | | level | info | Minimum log level to handle. | | datadogLogsInstance | N/A, required | Initialized Datadog Logs instance. |

See Datadog Logs documentation for more on custom logging with Datadog.

main.ts

import { datadogLogs } from '@datadog/browser-logs';
import logger from '@leaflink/snitch';
import { DatadogTransport } from '@leaflink/snitch/transports/datadog';

// Important: init Datadog logs instance before creating transport
datadogLogs.init({
  // ...
});
logger.addTransport(new DatadogTransport({
  datadogLogsInstance: datadogLogs,
}));

call in component file

import logger from '@leaflink/snitch';

logger.info('File loaded!');

try {
  await someErroringMethod()
} catch (err) {
  // If an Error is passed as the message, this is captured as an exception in Datadog
  logger.error(err, { id: 123 });
}

With Log Level

main.ts

import logger from '@leaflink/snitch';
import { ConsoleTransport } from '@leaflink/snitch/transports/console';

logger.addTransport(new ConsoleTransport({
  level: 'info'
}));

Custom Transports

custom-transport.ts

import { LogLevel, Transport } from '@leaflink/snitch';
// imagine this has a `report(options<{message, context}>)` method
import CustomDestinationInstance from '@example/destination';

interface CustomTransportOptions {
  level?: LogLevel;
}

export class CustomTransport implements Transport {
  level: LogLevel;
  log: (message: string | object, meta: Record<string, unknown> | undefined, level: LogLevel) => void;

  constructor(opts?: ConsoleTransportOptions) {
    this.level = opts?.level || 'debug';
    this.log = (message, meta) => {
      CustomDestinationInstance.report({
        message,
        context: 'meta',
      })
    };
  }
}

main.ts

import logger from '@leaflink/snitch';
import { CustomTransport } from './custom-transport';

logger.add(new CustomTransport());

Note: You can add a custom transport in your project, but consider opening a PR in this repo instead!

Testing

Stubbing snitch

When there's a need to mock this logger or you want to test if a specific log was printed, you can just mock it inside you test file:

import logger from '@leaflink/snitch';

vi.mock('@leaflink/snitch');

it('should redirect to error page if fetching the user profile fails', async () => {
  // ...
  expect(logger.error).toHaveBeenCalled();
})