JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 4133
  • Score
    100M100P100Q129149F
  • License ISC

A Logger for the Cloudflare workers environment that sends the logs to grafana loki

Package Exports

  • workers-loki-logger
  • workers-loki-logger/lib/cjs/index.js
  • workers-loki-logger/lib/esm/index.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (workers-loki-logger) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

Welcome to Workers Loki Logger 👋

GitHub branch checks state npm

A Logger for the Cloudflare workers environment that sends the logs to grafana loki

Install

npm install workers-loki-logger

Usage

When creating a logger and writing to it all logs are first stored in memory. It is sent to loki when the flush method is called.
It is recommended to use a wrapper function for the logger to ensure that the logs are flushed to loki.

Example with wrapper function

Features

  • Send logs to loki
  • Format exceptions as string
  • MDC to add additional information to the logs

API

new Logger()

Creates a new logger

import {Logger} from 'workers-loki-logger';

new Logger({
  cloudflareContext: context, // Cloudflare context if this option is set it will use the waitUntil function on flush
  lokiSecret: 'some-secret', // Secret for loki authentication
  lokiUrl: 'https://logs-prod-eu-west-0.grafana.net', // Url to loki
  stream: { // Stream options for loki
    worker: 'esm-worker-simple',
    environment: 'development',
  },
  mdc: { // If this option is set it will be used as the initial value for the MDC
    requestPath: '/some/path',
  }
});

logger.{info,warn,error,fatal}()

Write log

import {Logger} from 'workers-loki-logger';

declare const logger: Logger;

logger.info('message');

logger.warn('message');
logger.warn('message', new Error('some error'));

logger.error('message');
logger.error('message', new Error('some error'));

logger.fatal('message');
logger.fatal('message', new Error('some error'));

logger.{mdcSet,mdcDelete,mdcGet}()

Change MDC

import {Logger} from 'workers-loki-logger';

declare const logger: Logger;

logger.mdcSet('key', 'value');
logger.mdcGet('key');
logger.mdcDelete('key');

logger.flush()

Write logs to loki

import {Logger} from 'workers-loki-logger';

declare const logger: Logger;

await logger.flush();

Example

Example with wrapper function

import {Logger} from 'workers-loki-logger';

function getLogger(context: ExecutionContext, lokiSecret: string) {
  return new Logger({
    cloudflareContext: context,
    lokiSecret,
    lokiUrl: 'https://logs-prod-eu-west-0.grafana.net',
    stream: {
      worker: 'esm-worker-simple',
      environment: 'development',
    }
  });
}

type Environment = {
  LOKI_SECRET: string
}

// This function could be moved to a separate file and imported by multiple workers
function onFetch(handler: (request: Request, environment: Environment, context: ExecutionContext, logger: Logger) => Promise<Response>) {
  return async (request: Request, environment: Environment, context: ExecutionContext) => {
    const logger = getLogger(context, environment.LOKI_SECRET);
    logger.mdcSet('requestUrl', request.url);
    let response;
    try {
      response = await handler(request, environment, context, logger);
    } catch (error) {
      logger.error('Caught error', error);
      response = new Response('Internal Server Error', {status: 500});
    } finally {
      await logger.flush();
    }
    return response;
  };
}

export default {
  fetch: onFetch(async (request, environment, context, logger) => {
    logger.info('Request received' + request.url);
    return await fetch(request);
  })
};

Example with manually calling flush

import {Logger} from 'workers-loki-logger';

function getLogger(context: ExecutionContext, lokiSecret: string) {
  return new Logger({
    cloudflareContext: context,
    lokiSecret,
    lokiUrl: 'https://logs-prod-eu-west-0.grafana.net',
    stream: {
      worker: 'esm-worker-simple',
      environment: 'development',
    }
  });
}

export default {
  async fetch(request: Request, environment: { LOKI_SECRET: string }, context: ExecutionContext) {
    const logger = getLogger(context, environment.LOKI_SECRET);
    logger.mdcSet('requestUrl', request.url);
    logger.info('Request received' + request.url);
    let response;
    try {
      response = await fetch(request);
    } catch (error) {
      logger.error('Caught error', error);
      response = new Response('Internal Server Error', {status: 500});
    } finally {
      await logger.flush();
    }
    return response;
  }
};

Run tests

npm test

Me

👤 Donato Wolfisberg (donato@wolfibserg.dev) @SirCremefresh