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

@deboxsoft/logger

v1.0.1

Published

logger for koa

Downloads

2

Readme

debox-logger

Add logger to your koa2 server in 3 lines

Usage

Installation

npm i --save debox-logger

Quick Start

const { logger } = require('debox-logger');
app.use(logger());

request log will look like

{
  "req": {
    "headers": {
      "host": "localhost:3000",
      "connection": "keep-alive",
      "upgrade-insecure-requests": "1",
      "user-agent":
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36",
      "accept":
        "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
      "dnt": "1",
      "accept-encoding": "gzip, deflate, sdch, br",
      "accept-language":
        "zh-CN,zh;q=0.8,en;q=0.6,zh-TW;q=0.4,de;q=0.2,ja;q=0.2,it;q=0.2"
    },
    "url": "/hello",
    "method": "GET",
    "href": "http://localhost:3000/hello",
    "query": {}
  },
  "started_at": 1494554053492,
  "res": {
    "headers": {
      "content-type": "application/json; charset=utf-8",
      "content-length": "16"
    },
    "status": 200
  },
  "duration": 8,
  "level": "info",
  "message": "HTTP GET /hello"
}

Configuration

Each parameter has a default value, and you can customize your logger by changing the configuration

app.use(
  logger({
    transports: new winston.transports.Console({ json: true, stringify: true }),
    level: 'info',
    reqKeys: [
      'headers',
      'url',
      'method',
      'httpVersion',
      'href',
      'query',
      'length',
    ],
    reqSelect: [],
    reqUnselect: ['headers.cookie'],
    resKeys: ['headers', 'status'],
    resSelect: [],
    resUnselect: [],
  })
);

Many configuration explain can be found in logger

Examples

Do not record any request fields

app.use(
  logger({
    reqKeys: [],
  })
);

The req object will be empty

{
  "req": {},
  "started_at": 1494486039864,
  "res": {
    "headers": {
      "content-type": "text/plain; charset=utf-8",
      "content-length": "8"
    },
    "status": 200
  },
  "duration": 26,
  "level": "info",
  "message": "HTTP GET /"
}

Do not record any response fields

app.use(
  logger({
    resKeys: [],
  })
);

The res object will be empty

{
  "req": {
    "headers": {
      "host": "127.0.0.1:59534",
      "accept-encoding": "gzip, deflate",
      "user-agent": "node-superagent/3.5.2",
      "connection": "close"
    },
    "url": "/",
    "method": "GET",
    "href": "http://127.0.0.1:59534/",
    "query": {}
  },
  "started_at": 1494486039864,
  "res": {},
  "duration": 26,
  "level": "info",
  "message": "HTTP GET /"
}

Do not record UA

app.use(
  logger({
    reqUnselect: ['headers.cookies', 'headers.user-agent'],
  })
);

The UA of request will be ignored

{
  "req": {
    "headers": {
      "host": "127.0.0.1:59534",
      "accept-encoding": "gzip, deflate",
      "connection": "close"
    },
    "url": "/",
    "method": "GET",
    "href": "http://127.0.0.1:59534/",
    "query": {}
  },
  "started_at": 1494486039864,
  "res": {
    "headers": {
      "content-type": "text/plain; charset=utf-8",
      "content-length": "8"
    },
    "status": 200
  },
  "duration": 26,
  "level": "info",
  "message": "HTTP GET /"
}

Record a response body filed

app.use(
  logger({
    resSelect: ['body.success'],
  })
);

The success field on body will be recorded

{
  "req": {
    "headers": {
      "host": "127.0.0.1:59534",
      "accept-encoding": "gzip, deflate",
      "connection": "close"
    },
    "url": "/",
    "method": "GET",
    "href": "http://127.0.0.1:59534/",
    "query": {}
  },
  "started_at": 1494486039864,
  "res": {
    "headers": {
      "content-type": "text/plain; charset=utf-8",
      "content-length": "8"
    },
    "status": 200,
    "body": {
      // Any possible value given by the server
      "success": false
    }
  },
  "duration": 26,
  "level": "info",
  "message": "HTTP GET /"
}

Simple Benchmark

At node 8.2

middleware x 90,281 ops/sec ±7.89% (13 runs sampled)

At node 8.4

middleware x 112,011 ops/sec ±10.26% (18 runs sampled)

Schema Stringify

With fast-json-stringify support, default transport logger is much faster

total ops/sec { jsonstringify: 73544 }
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
total ops/sec { schemastringify: 90223 }
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓

schemastringify is 1.23x faster then jsonstringify in this case

Math.floor vs parseInt

JSPerf link in HERE

Testing in Chrome 70.0.3505 / Mac OS X 10.13.5

parseInt(401 / 100, 10) { 160,092,130 Ops/sec }
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
Math.floor(401 / 100) { 810,032,369 Ops/sec }
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓

Math.floor is 5.06x faster then parseInt in this case

JSDoc

clone

clone object

Parameters

  • obj any

keysRecorder

keysRecorder use ldoash pick, get and set to collect data from given target object

Parameters

  • payload Object input arguments (optional, default {})
    • payload.defaults Array<string>? default keys will be collected
    • payload.selects Array<string>? keys will be collected as additional part
    • payload.unselects Array<string>? keys that will be ignored at last

Examples

// without payload
const recorder = keysRecorder();
recorder(); // {}
recorder({ foo: 1, bar: 2, foobar: { a: 3, b: 4 } }); // {}

// with defaults
const recorder = keysRecorder({ defaults: ['foo'] });
recorder(); // {}
recorder({ foo: 1, bar: 2, foobar: { a: 3, b: 4 } }); // { foo: 1 }

// with defaults and selects
const recorder = keysRecorder({ defaults: ['foo'], selects: ['foobar'] });
recorder(); // {}
recorder({
  foo: 1,
  bar: 2,
  foobar: { a: 3, b: 4 },
}); // { foo: 1, foobar: { a: 3, b: 4 } }

// with defaults and unselects
const recorder = keysRecorder({
  defaults: ['foobar'],
  unselects: ['foobar.a'],
});
recorder(); // {}
recorder({
  foo: 1,
  bar: 2,
  foobar: { a: 3, b: 4 },
}); // { foobar: { a: 3 } }

// with defaults and selects and unselects
const recorder = keysRecorder({
  defaults: ['foo'],
  selects: ['foobar'],
  unselects: ['foobar.b'],
});
recorder(); // {}
recorder({
  foo: 1,
  bar: 2,
  foobar: { a: 3, b: 4 },
}); // { foo: 1, foobar: { a: 3 } }

Returns function closure function, setting by given payload

logger

logger middleware for koa2 use winston

Parameters

  • payload object input arguments (optional, default {})
    • payload.transports Array<object> customize transports (optional, default [newFastJsonConsole({stringify})])
    • payload.level string default log level of logger (optional, default 'info')
    • payload.reqKeys string default request fields to be logged (optional, default ['headers','url','method', 'httpVersion','href','query','length'])
    • payload.reqSelect string additional request fields to be logged (optional, default [])
    • payload.reqUnselect string request field will be removed from the log (optional, default ['headers.cookie'])
    • payload.resKeys string default response fields to be logged (optional, default ['headers','status'])
    • payload.resSelect string additional response fields to be logged (optional, default [])
    • payload.resUnselect string response field will be removed from the log (optional, default [])
    • payload.logger string? customize winston logger
    • payload.msg string customize log msg (optional, default HTTP%s%s)

Examples

const { logger } = require('debox-logger');
app.use(logger());
// request logger look like down here
// {
//   "req": {
//     "headers": {
//       "host": "127.0.0.1:59534",
//       "accept-encoding": "gzip, deflate",
//       "user-agent": "node-superagent/3.5.2",
//       "connection": "close"
//     },
//     "url": "/",
//     "method": "GET",
//     "href": "http://127.0.0.1:59534/",
//     "query": {}
//   },
//   "started_at": 1494486039864,
//   "res": {
//     "headers": {
//       "content-type": "text/plain; charset=utf-8",
//       "content-length": "8"
//     },
//     "status": 200
//   },
//   "duration": 26,
//   "level": "info",
//   "message": "HTTP GET /"
// }

Returns function logger middleware