Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

🌲 Cabin is the best self-hosted JavaScript and Node.js logging service. Made for@forwardemail.

License

NotificationsYou must be signed in to change notification settings

cabinjs/cabin

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

cabin

build statuscode stylestyled with prettiermade with lasslicensenpm downloads

Cabin is the best self-hostedJavaScript andNode.jslogging service.
Supports Node v18+, Browser Environments,Express,Koa, andLad

Cabin is compatible withSentry,Airbrake,Papertrail,Loggly, andBugsnag.

Table of Contents

Foreword

Please defer to Axe'sForeword for more insight.

Cabin is a layer on top of Axe that provides automatic logging for route middleware requests and errors.

Quick Start

npm install express axe cabin signale
constexpress=require('express');constAxe=require('axe');constCabin=require('cabin');constapp=express();const{ Signale}=require('signale');// initialize a new instance of Axe (see below TODO's that appeal to you)constlogger=newAxe({logger:newSignale()});// TODO: if you want to send logs to an HTTP endpoint then follow this guide:// https://github.com/cabinjs/axe/#send-logs-to-http-endpoint// TODO: if you want to send logs to Slack then follow this guide:// https://github.com/cabinjs/axe/#send-logs-to-slack// TODO: if you want to send logs to Sentry then follow this guide:// https://github.com/cabinjs/axe/#send-logs-to-sentry// TODO: if you want to send logs to Datadog then follow this guide:// https://github.com/cabinjs/axe/#send-logs-to-datadog// TODO: if you want to send logs to Papertrail then follow this guide:// https://github.com/cabinjs/axe/#send-logs-to-papertrail// TODO: if you want to suppress specific log metadata then follow this guide:// https://github.com/cabinjs/axe/#suppress-logger-data// initialize a new instance of Cabin with an Axe logger instanceconstcabin=newCabin({ logger});//// initialize route logging middleware//// NOTE: this will automatically log route middleware requests and errors//app.use(cabin.middleware);app.get('/',(req,res,next)=>res.send('OK'));// start the serverapp.listen(3000);
curl http://localhost:3000

Features

Security, Privacy, and Business Focused

Cabin will automatically detect and mask the following list of extremely sensitive types of data in your logs:

*Credit card numbers from the following providers are automatically detected and masked: Visa, Mastercard, American Express, Diners Club, Discover, JCB, UnionPay, Maestro, Mir, Elo, Hiper, Hipercard

Reduce Disk Storage Costs

Reduce your disk storage costs through Cabin's automatic conversion of Streams, Buffers, and ArrayBuffers to simplified, descriptive-only objects that otherwise would be unreadable (and obviously pollute your log files and disk storage).

Before:

{"request": {"body": {"file": {"type":"Buffer","data": [76,111,114,101,109,32,105,112,115,117,109,32,100,111,108,111,114,32,115,105,116,'...'        ]      }    }  }}

After

{"request": {"body": {"file": {"type":"Buffer","byteLength":2787      }    }  }}

Cross-Platform and Cross-Browser Compatible

Cabin works with the most popular Node.js HTTP frameworks (e.g.Express andKoa), request body handling packages (e.g.multer andbody-parser), and thepassport authentication framework.

It supportsNode v18+ and modern browsers out of the box (its browser-ready bundleis only 20 KB).

npx browserslist
and_chr 107and_ff 106and_qq 13.1and_uc 13.4android 107chrome 107chrome 106chrome 105edge 107edge 106edge 105firefox 106firefox 105firefox 102ios_saf 16.1ios_saf 16.0ios_saf 15.6ios_saf 15.5ios_saf 14.5-14.8kaios 2.5op_mini allop_mob 64opera 91opera 90safari 16.1safari 16.0safari 15.6samsung 18.0samsung 17.0

Send Logs to an HTTP endpoint

See theQuick Start section above and our guide athttps://github.com/cabinjs/axe/#send-logs-to-http-endpoint.

Send Logs to Slack

See theQuick Start section above and our guide athttps://github.com/cabinjs/axe/#send-logs-to-slack.

Send Logs to Sentry

See theQuick Start section above and our guide athttps://github.com/cabinjs/axe/#send-logs-to-sentry.

Send Logs to Datadog

See theQuick Start section above and our guide athttps://github.com/cabinjs/axe/#send-logs-to-datadog.

Send Logs to Papertrail

See theQuick Start section above and our guide athttps://github.com/cabinjs/axe/#send-logs-to-papertrail.

Suppress Logger Data

See theQuick Start section above and our guide athttps://github.com/cabinjs/axe/#suppress-logger-data.

Install

Note that as of v11.0.0 Cabin requires a peer dependency ofAxe to be installed.

npm:

npm install cabin axe

Usage

Logging

constCabin=require('cabin');constcabin=newCabin({// ... see the Quick Start and Options sections});cabin.info('hello world');cabin.error(newError('oops!'));

Route Logging Middleware

app.use(cabin.middleware);

See either theNode orBrowser instructions below for further route middleware usage and proper setup.

Node

The examples below show how to use Cabin in combination withAxe,Signale (instead ofconsole), and how to add an accurateX-Response-Time response time metric to your logs and response headers automatically.

Koa

  1. Install required and recommended dependencies:

    npm install koa cabin signale request-received koa-better-response-time koa-better-request-id
  2. Implement the example code below (also found here):

    constKoa=require('koa');constCabin=require('cabin');constRouter=require('koa-router');constrequestReceived=require('request-received');constresponseTime=require('koa-better-response-time');constrequestId=require('koa-better-request-id');const{ Signale}=require('signale');constapp=newKoa();constrouter=newRouter();constcabin=newCabin({logger:newSignale()});// adds request received hrtime and date symbols to request object// (which is used by Cabin internally to add `request.timestamp` to logsapp.use(requestReceived);// adds `X-Response-Time` header to responsesapp.use(responseTime());// adds or re-uses `X-Request-Id` headerapp.use(requestId());// use the cabin middleware (adds request-based logging and helpers)app.use(cabin.middleware);// add your user/session management middleware here (e.g. passport)// ...// an example home page routerouter.get('/',ctx=>{ctx.logger.info('visited home page');ctx.body='hello world';});// this assumes that you are using passport which// exposes `ctx.logout` to log out the logged in userrouter.get('/logout',ctx=>{ctx.logger.warn('Logged out');ctx.logout();ctx.redirect('/');});app.use(router.routes());app.use(router.allowedMethods());app.listen(3000,()=>{cabin.info('app started');});
  3. SeeKoa convenience methods below for helper utilities you can use while writing code.

Express

  1. Install required and recommended dependencies:

    npm install express cabin signale request-received response-time express-request-id
  2. Implement the example code below (also found here):

    constexpress=require('express');constCabin=require('cabin');constrequestReceived=require('request-received');constresponseTime=require('response-time');constrequestId=require('express-request-id');const{ Signale}=require('signale');constapp=express();constcabin=newCabin({logger:newSignale()});// adds request received hrtime and date symbols to request object// (which is used by Cabin internally to add `request.timestamp` to logsapp.use(requestReceived);// adds `X-Response-Time` header to responsesapp.use(responseTime());// adds or re-uses `X-Request-Id` headerapp.use(requestId());// use the cabin middleware (adds request-based logging and helpers)app.use(cabin.middleware);// add your user/session management middleware here (e.g. passport)// ...// an example home page routeapp.get('/',(req,res)=>{req.logger.info('visited home page');res.send('hello world');});// this assumes that you are using passport which// exposes `req.logout` to log out the logged in userapp.get('/logout',(req,res)=>{req.logger.warn('logged out');req.logout();res.redirect('/');});app.listen(3000,()=>{cabin.info('app started');});
  3. SeeExpress convenience methods below for helper utilities you can use while writing code.

Convenience Methods

In order to easily interact and use thelogger utility function exposed byapp.use(cabin.middleware), we expose convenient helper methods in Express and Koa:

Express
  • req.log
  • req.logger
  • res.log
  • res.logger
Koa
  • ctx.log
  • ctx.logger
  • ctx.request.log
  • ctx.request.logger
  • ctx.response.log
  • ctx.response.logger

Browser

This package requires Promise support, therefore you will need to polyfill if you are using an unsupported browser (namely Opera mini).

We no longer support IE as of Cabin v10.0.0+.

VanillaJS

This is the solution for you if you're just using<script> tags everywhere!

<scriptsrc="https://cdnjs.cloudflare.com/polyfill/v3/polyfill.min.js?features=Promise"></script><scriptsrc="https://unpkg.com/cabin"></script><scripttype="text/javascript">(function(){varcabin=newCabin();cabin.setUser({id:'1',email:'test@example.com',full_name:'Test'});cabin.info('viewed docs');})();</script>

Required Browser Features

We recommend usinghttps://cdnjs.cloudflare.com/polyfill (specifically with the bundle mentioned inVanillaJS above):

<scriptsrc="https://cdnjs.cloudflare.com/polyfill/v3/polyfill.min.js?features=Promise"></script>
  • Promise is not supported in op_mini all

Bundler

This assumes you are usingbrowserify,webpack,rollup, or another bundler.

constCabin=require('cabin');constcabin=newCabin();cabin.setUser({id:'1',email:'test@example.com',full_name:'Test'});cabin.info('viewed docs');

Automatic Request Logging

Server

For server-side logging of requests, the Cabin middlewarecabin.middleware will automatically log requests for you upon completion. Just make sure you are usingexpress-request-id middleware like in the examples above in order for theX-Request-Id header to be set (and re-used if already exists, e.g. generated from client side as in below). If you're using Koa make sure to usekoa-better-request-id as shown in the examples above.

Browser

We strongly recommend that you implement one of the following code snippets withxhook (for either VanillaJS or Bundler approaches) so that all your XHR requests have aX-Request-Id automatically added (which in turn ensures both client and server have matching request ID's). Imagine how awesome your logs will be when you can see the full trace starting with the client!

HTML
<scriptsrc="https://cdnjs.cloudflare.com/polyfill/v3/polyfill.min.js?features=Promise"></script><scriptsrc="https://unpkg.com/xhook"></script><scriptsrc="https://unpkg.com/cabin"></script><scriptsrc="https://unpkg.com/parse-request"></script><scriptsrc="https://unpkg.com/cuid"></script><script>(function(){varcabin=newCabin();cabin.setUser({id:'1',email:'test@example.com',full_name:'Test'});xhook.before(function(req){if(typeofreq.headers!=='object')req.headers={};if(!req.headers['X-Request-Id'])req.headers['X-Request-Id']=cuid();if(!req.headers['User-Agent'])req.headers['User-Agent']=window.navigator.userAgent;if(!req.headers['Referer'])req.headers['Referer']=window.document.referrer;if(!req.headers['Cookie'])req.headers['Cookie']=window.document.cookie;cabin.info('xhr',parseRequest({req:req}));});})();</script>
Pug

You can do a similar approach with React, EJS, or another templating language.

script(src='https://cdnjs.cloudflare.com/polyfill/v3/polyfill.min.js?features=Promise')script(src='https://unpkg.com/xhook')script(src='https://unpkg.com/cabin')script(src='https://unpkg.com/parse-request')script(src='https://unpkg.com/cuid')script.  (function() {var cabin=newCabin();cabin.setUser({      id:'1',      email:'test@example.com',      full_name:'Test'    });xhook.before(function(req) {if (typeofreq.headers!=='object')req.headers= {};if (!req.headers['X-Request-Id'])req.headers['X-Request-Id']=cuid();if (!req.headers['X-Request-Id'])req.headers['X-Request-Id']=cuid();if (!req.headers['User-Agent'])req.headers['User-Agent']=window.navigator.userAgent;if (!req.headers['Referer'])req.headers['Referer']=window.document.referrer;if (!req.headers['Cookie'])req.headers['Cookie']=window.document.cookie;cabin.info('xhr',parseRequest({ req: req }));    });  })();
Bundler

npm:

npm install cabin xhook cuid
constCabin=require('cabin');constxhook=require('xhook');constparseRequest=require('parse-request');constcuid=require('cuid');constcabin=newCabin();cabin.setUser({id:'1',email:'test@example.com',full_name:'Test'});xhook.before(req=>{if(typeofreq.headers!=='object')req.headers={};if(!req.headers['X-Request-Id'])req.headers['X-Request-Id']=cuid();//// NOTE: you may want to add User-Agent, Referer, and Cookie (see above)//cabin.info('xhr',parseRequest({req:req}));});

Stack Traces and Error Handling

We leave it up to you to decide how you wish to handle stack traces and errors, but we've documented our approaches for Node and Browser environments below.

Node

If you're usingLad, then you don't need to worry about error handling, as it's built-in (complete with graceful reloading, even for database connections).

However you can otherwise use a tool such asuncaught to listen for errors, or bind purely toprocess events emitted as shown below:

constCabin=require('cabin');constcabin=newCabin();process.on('uncaughtException',err=>{cabin.error(err);process.exit(1);});process.on('unhandledRejection',err=>{cabin.error(err);});

Browser

Since cross-browser support is very limited and non-standardized for errors and stack traces, we highly recommend to useStackTrace.

StackTrace

We recommend to useStackTrace instead ofTraceKit as it is a more modern alternative and provides much similarity between your Browser and your Node errors (stackframes are basically similar to representations in Gecko and V8, aka the ones you get with Node).

It does require you to have a polyfill if you're using it in the browser (only if you're supporting browsers that don't support standardized Promises/JSON). You'll basically needes6-promise andjson3 polyfills for browsers you wish to support that don't have them. The example below shows you how to polyfill, don't worry! You can reference Caniuse data onPromises andJSON respectively if you need.

The example below demonstrates using StackTrace withuncaught to catch global errors below.

<scriptsrc="https://cdnjs.cloudflare.com/polyfill/v3/polyfill.min.js?features=Promise"></script><scriptsrc="https://unpkg.com/stackframe"></script><scriptsrc="https://unpkg.com/stacktrace-js"></script><scriptsrc="https://unpkg.com/uncaught"></script><scriptsrc="https://unpkg.com/cabin"></script><scriptsrc="https://unpkg.com/prepare-stack-trace"></script><scripttype="text/javascript">(function(){//// Sourced from the StackTrace example from CabinJS docs// <https://github.com/cabinjs/cabin#stacktrace>//varcabin=newCabin();// Use cabin globally in your app (instead of `console`)window.cabin=cabin;// Bind event listenersuncaught.start();uncaught.addListener(function(err,event){if(!err){if(typeofErrorEvent==='function'&&eventinstanceofErrorEvent)returncabin.error(event.message,{event:event});cabin.error({event:event});return;}// this will transform the error's `stack` property// to be consistently similar to Gecko and V8 stackframesStackTrace.fromError(err).then(function(stackframes){err.stack=prepareStackTrace(err,stackframes);cabin.error(err);}).catch(function(err2){cabin.error(err);cabin.error(err2);});});})();</script>

Options

  • logger (Object orAxe instance) - if you have a custom logger you wish to use or an existingAxe instance – defaults to an instance ofAxe which usesconsole as the logger – if you do not pass an instance of Axe, then an instance will be created and thelogger option will be passed down
  • meta (Object) - defaults to an empty object - this will get passed as metadata (e.g. you could set a custommeta.user object here for every request)
  • parseRequest (Object) - defaults to an empty object, which means it will use the defaults fromparse-request (seeMetadata below)
  • errorProps (Array) - a list of properties to cherry-pick from the error object parsed out of err thanks toparse-err (by default all properties are returned; even non-enumerable ones and ones on the prototype object) (seeMetadata below)
  • message (Function) - inspired bymorgan, and defaults to adev-friendly format (or if in production mode, then it uses astandard Apache common log format)). – when requests finish, it will utilizelogger to output an error, warn, or info level log based off the status code, and this function is used to determine the string sent to the logger. It accepts one argumentoptions, which is comprised ofoptions.level,options.req,options.res, and optionally (if and only if Koa)options.ctx. It is required that this function return a String. Seesrc/message.js for the default message function. Note that both dev-friendly and Apache common log formats are stripped of basic auth lines for obvious security reasons.Note that if anull orundefined value is returned from the message function, then the logger will not be invoked unless there is an error.

Display Metadata and Stack Traces

Under the hood, Cabin usesAxe which provides us with several options, including one to show metadata (e.g. request headers, body, and user) and another to show stack traces for errors.

To show/hide application metadata and/or stack traces, see theAxe options documentation.

Cabin uses the packageparse-request to parse the request metadata for you automatically in your Express and Koa applications.

Here's an example of a parsed metadata object:

{request:{method:'POST',query:{foo:'bar',beep:'boop'},headers:{host:'127.0.0.1:63955','accept-encoding':'gzip, deflate','user-agent':'node-superagent/3.8.3',authorization:'Basic ********************',accept:'application/json',cookie:'foo=bar;beep=boop','content-type':'multipart/form-data; boundary=--------------------------930511303948232291410214','content-length':'1599',connection:'close'},cookies:{foo:'bar',beep:'boop'},body:'{"product_id":"5d0350ef2ca74d11ee6e4f00","name":"nifty","surname":"lettuce","bank_account_number":"1234567890","card":{"number":"****-****-****-****"},"stripe_token":"***************","favorite_color":"green"}',url:'/?foo=bar&beep=boop',timestamp:'2019-06-14T07:46:55.568Z',id:'fd6225ed-8db0-4862-8566-0c0ad6f4c7c9',http_version:'1.1',files:'{"avatar":[{"fieldname":"avatar","originalname":"avatar.png","encoding":"7bit","mimetype":"image/png","buffer":{"type":"Buffer","byteLength":216},"size":216}],"boop":[{"fieldname":"boop","originalname":"boop-1.txt","encoding":"7bit","mimetype":"text/plain","buffer":{"type":"Buffer","byteLength":7},"size":7},{"fieldname":"boop","originalname":"boop-2.txt","encoding":"7bit","mimetype":"text/plain","buffer":{"type":"Buffer","byteLength":7},"size":7}]}'},user:{ip_address:'::ffff:127.0.0.1'},id:'5d0350ef2ca74d11ee6e4f01',timestamp:'2019-06-14T07:46:55.000Z',duration:6.651317}

As you can see, sensitive data is masked and contextual user information metadata is automatically populated.

Related

  • Forward Email - Free, encrypted, and open-source email forwarding service for custom domains
  • Axe - Logging utility for Node and Browser environments. Chop up your logs!
  • Bree - The best job scheduler forNode.js
  • Lad - Scaffold aKoa webapp and API framework forNode.js
  • Lass - Scaffold a modern boilerplate forNode.js
  • koa-better-error-handler - A better error-handler for Lad and Koa. Makesctx.throw awesome!

License

MIT © Titanism

#


[8]ページ先頭

©2009-2025 Movatter.jp