concurrency-logger
v2.1.0
Published
Log HTTP requests/responses separately, visualize their concurrency and report logs/errors in context of a request
Downloads
3,978
Maintainers
Readme
concurrency-logger
HTTP logging middleware especially useful to unwind concurrent operations without losing the request context
Install
$ npm install concurrency-logger
Usage
With koa
Basic usage
import Koa from 'koa';
import createLogger from 'concurrency-logger';
const app = new Koa;
// Logger is stateful as it contains information about concurrent requests
// Same instance needs to be reused across requests
const logger = createLogger(/* options */);
app.use(logger);
Log from middleware
// Log something in context to a specific request to trace it back easily -
// also when there are multiple concurrent requests
app.use(async (context, next) => {
context.log('Log!');
context.log.info('Info!');
context.log.error('Error!');
await next();
});
Attach more context to the log
const logger = createLogger({
req: context => (
context.originalUrl + '\n' +
context.get('User-Agent')
)
});
Include localized timestamps
const logger = createLogger({
timestamp: true
});
Write log to file
import { createWriteStream } from 'fs';
// To read log use program that interprets ANSI escape codes,
// e.g. cat or less -r
const log = createWriteStream('logs/requests.log');
const logger = createLogger({
reporter: log
});
Adjust alert levels per method and response time
const logger = createLogger({
getLevel: (responseTime, context) => {
/*
GET
0 - 99ms: 0
100 - 149ms: 1
150 - 199ms: 2
200 - 249ms: 3
250 - 299ms: 4
300 - 349ms: 5
> 350ms : 6
POST
0 - 149ms: 0
150 - 225ms: 1
... : ...
*/
let threshold = 50; // ms
if (['POST', 'PUT'].includes(context.method)) {
threshold *= 1.5;
}
return Math.floor(responseTime / threshold) - 1;
}
});
Standalone
import createLogger from 'concurrency-logger';
const logger = createLogger(/* options */);
(async () => {
const context = {
method: 'GET',
originalUrl: '/'
};
const next = async () => {
await new Promise(resolve => setTimeout(resolve, 100));
context.status = 200;
};
try {
await logger(context, next);
} catch (error) {
// Errors are passed through
}
})();
API
| Option | Type | Default | Description | Example |
| ---- | ---- | ------- | ----------- | ------- |
| minSlots | integer | 1
| Amount of space that is provisioned to display concurrent request lanes. Number of lanes will automatically scale up as the number of concurrent requests grow. | 3
| getLevel | integer: function(responseTime: integer) | responseTime => Math.floor(responseTime / 50) - 1
| Map response time to alert level. Alert levels go from 0 (default color) to 6 (dark red). By default that means <100ms: 0
, <150ms: 1
<200ms: 2
, ..., >=350ms: 6
. | responseTime => Math.floor(responseTime / 100)
| width | integer, boolean(false
) | undefined
| If no width is provided, it will be dynamically read from process.stdout.columns
. Pass in an integer to break all lines according to the specified fixed (terminal character) width. Pass in false
if you want the lines not to break at all. | 80
, 132
, false
| timestamp | boolean | false
| Print localized timestamp for every requests. | true
, false
| slim | boolean | false
| "Slim mode": don't use an extra character between request lanes to shrink width, but make them harder to separate visually. | true
, false
| reporter | writable stream | process.stdout
| Specify a stream that handles the output lines. Write to terminal or stream to a log file, for example. Note that the lines contain ANSI color codes, so when streaming to a file you might need a program that can read those. E.g. less -r requests.log
| require('fs').createWriteStream('logs/requests.log')
| req | any: function(context: object) | context => context.originalUrl
| Attach additional information to the request log line. | context => context.originalUrl + '\n' + context.get('User-Agent')
| res | any: function(context: object) | context => context.originalUrl
| Attach additional information to the response log line. | context => context.originalUrl + '\n' + context.get('User-Agent')
Developing
Install development dependencies
$ npm install
Create new fixtures to test against
$ npm run create-fixtures
Manually review fixtures (you need a program that renders ANSI escape codes)
$ less -r test/fixtures/*
Run tests
$ npm test
Run code linter
$ npm run lint
Compile to ES5 from /src to /lib
$ npm run compile
Initialize demo project
$ git clone [email protected]:PabloSichert/concurrency-logger demo
$ cd demo
demo $ git checkout gh-pages
demo $ npm install
Build demo
demo $ npm run compile