@stencila/logga
Advanced tools
Comparing version 1.1.2 to 1.2.0
@@ -0,1 +1,8 @@ | ||
# [1.2.0](https://github.com/stencila/logga/compare/v1.1.2...v1.2.0) (2019-07-02) | ||
### Features | ||
* **Default handler:** Improve default handler and always use it ([64b8620](https://github.com/stencila/logga/commit/64b8620)) | ||
## [1.1.2](https://github.com/stencila/logga/compare/v1.1.1...v1.1.2) (2019-06-18) | ||
@@ -2,0 +9,0 @@ |
@@ -31,2 +31,31 @@ export declare enum LogLevel { | ||
/** | ||
* Remove a handler. | ||
* | ||
* @param handler Handler to remove | ||
*/ | ||
export declare function removeHandler(handler?: LogHandler): void; | ||
/** | ||
* Remove all handlers. | ||
*/ | ||
export declare function removeAllHandlers(): void; | ||
/** | ||
* Replace all existing handlers with a new handler. | ||
* | ||
* This is a convenience function that can be used to | ||
* replace the default handler with a new one which logs | ||
* to the console. | ||
*/ | ||
export declare function replaceHandlers(handler: LogHandler): void; | ||
/** | ||
* Default log data handler. | ||
* | ||
* Prints the data to stderr: | ||
* | ||
* - with cutesy emoji, colours and stack (for errors) if stderr is TTY (for human consumption) | ||
* - as JSON if stderr is not TTY (for machine consumption e.g. log files) | ||
* | ||
* @param data The log data to handle | ||
*/ | ||
export declare function defaultHandler(data: LogData): void; | ||
/** | ||
* Get a logger for the specific application or package. | ||
@@ -33,0 +62,0 @@ * |
"use strict"; | ||
var __assign = (this && this.__assign) || function () { | ||
__assign = Object.assign || function(t) { | ||
for (var s, i = 1, n = arguments.length; i < n; i++) { | ||
s = arguments[i]; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) | ||
t[p] = s[p]; | ||
} | ||
return t; | ||
}; | ||
return __assign.apply(this, arguments); | ||
}; | ||
exports.__esModule = true; | ||
@@ -50,12 +61,79 @@ var LOG_EVENT_NAME = Symbol('stencila:logga'); | ||
function addHandler(handler) { | ||
handler = | ||
handler || | ||
function (data) { | ||
console.error(data.tag + " - [" + LogLevel[data.level].toUpperCase() + "] - " + data.message); | ||
}; | ||
handler = handler || defaultHandler; | ||
// @ts-ignore | ||
process.on(LOG_EVENT_NAME, handler); | ||
process.addListener(LOG_EVENT_NAME, handler); | ||
} | ||
exports.addHandler = addHandler; | ||
/** | ||
* Remove a handler. | ||
* | ||
* @param handler Handler to remove | ||
*/ | ||
function removeHandler(handler) { | ||
handler = handler || defaultHandler; | ||
process.removeListener(LOG_EVENT_NAME, handler); | ||
} | ||
exports.removeHandler = removeHandler; | ||
/** | ||
* Remove all handlers. | ||
*/ | ||
function removeAllHandlers() { | ||
process.removeAllListeners(LOG_EVENT_NAME); | ||
} | ||
exports.removeAllHandlers = removeAllHandlers; | ||
/** | ||
* Replace all existing handlers with a new handler. | ||
* | ||
* This is a convenience function that can be used to | ||
* replace the default handler with a new one which logs | ||
* to the console. | ||
*/ | ||
function replaceHandlers(handler) { | ||
removeAllHandlers(); | ||
addHandler(handler); | ||
} | ||
exports.replaceHandlers = replaceHandlers; | ||
/** | ||
* Default log data handler. | ||
* | ||
* Prints the data to stderr: | ||
* | ||
* - with cutesy emoji, colours and stack (for errors) if stderr is TTY (for human consumption) | ||
* - as JSON if stderr is not TTY (for machine consumption e.g. log files) | ||
* | ||
* @param data The log data to handle | ||
*/ | ||
function defaultHandler(data) { | ||
var entry; | ||
if (process.stderr.isTTY) { | ||
var tag = data.tag, level = data.level, message = data.message, stack = data.stack; | ||
var index = level < 0 ? 0 : level > 3 ? 3 : level; | ||
var label = LogLevel[index].toUpperCase().padEnd(5, ' '); | ||
var emoji = [ | ||
'🚨', | ||
'⚠', | ||
'🛈', | ||
'🐛' // debug | ||
][index]; | ||
var colour = [ | ||
'\u001b[31;1m', | ||
'\u001b[33;1m', | ||
'\u001b[34;1m', | ||
'\u001b[30;1m' // grey (bright black) | ||
][index]; | ||
var cyan = '\u001b[36m'; | ||
var reset = '\u001b[0m'; | ||
entry = emoji + " " + colour + label + reset + " " + cyan + tag + reset + " " + message; | ||
if (level === LogLevel.error) | ||
entry += '\n ' + stack; | ||
} | ||
else { | ||
entry = JSON.stringify(__assign({ time: new Date().toISOString() }, data)); | ||
} | ||
console.error(entry); | ||
} | ||
exports.defaultHandler = defaultHandler; | ||
// Always enable the default handler | ||
addHandler(defaultHandler); | ||
/** | ||
* Get a logger for the specific application or package. | ||
@@ -62,0 +140,0 @@ * |
{ | ||
"name": "@stencila/logga", | ||
"version": "1.1.2", | ||
"version": "1.2.0", | ||
"description": "Unified logging across related Javascript modules", | ||
@@ -13,3 +13,2 @@ "main": "dist/index.js", | ||
"test:cover": "jest --collectCoverage", | ||
"test:watch": "jest --watchAll", | ||
"build": "tsc index.ts --outDir dist --declaration" | ||
@@ -31,5 +30,6 @@ }, | ||
"devDependencies": { | ||
"@stencila/dev-config": "^1.0.4", | ||
"@stencila/typescript-boilerplate": "^1.1.1", | ||
"@stencila/dev-config": "^1.0.6", | ||
"@types/jest": "^24.0.15", | ||
"jest": "^24.8.0", | ||
"ts-jest": "^24.0.2", | ||
"typescript": "^3.5.2" | ||
@@ -36,0 +36,0 @@ }, |
@@ -15,3 +15,3 @@ # Logga | ||
For example, `encoda` and `dockta` are two Typescript projects that use `logga` which we combine in the `stencila` command line tool. In the future, we'll also combine them into the `stencila` desktop Electron-based application. We want users of `encoda` and `dockta` to be able to use them as standalone tools, at the command line, and get feedback at the command line. But we also want to be able to handle log events from these packages in apps that integrate them and which may use a fancier CLI display (e.g. [Ink](https://github.com/vadimdemedes/ink)) or a HTML UI display (e.g. in Electron). | ||
For example, `encoda` and `dockta` are two Typescript projects that use `logga`. We want users of these projects to be able to use them as standalone tools and have log events printed at the command line. Both projects are also integrated into the `stencila` command line tool, and in the future, we'll also combine them into the `stencila` desktop Electron-based application. For each of these apps, we want to handle log events from both packages in a consistent way and display them in a way that is appropriate for the platform e.g. HTML messages when in Electron, log files when running as a server. | ||
@@ -30,23 +30,39 @@ ## Approach | ||
Create a new logger by calling `getLogger` with a unique tag to identify your app and/or module. Register a handler by calling `addHandler` with a handling function (defaults to printing to the `process.stderr`). Then emit log events using the `debug`, `info`, `warn` or `error` function (you can pass them a message string or a `LogInfo` object). | ||
Create a new logger by calling `getLogger` with a unique tag to identify your app and/or module. Then emit log events using the `debug`, `info`, `warn` and `error` functions. You can pass them a message string or a `LogInfo` object. | ||
```ts | ||
import { getLogger, addHandler } from '@stencila/logga' | ||
```js | ||
const { getLogger } = require('@stencila/logga') | ||
const logger = getLogger('app:module') | ||
addHandler() | ||
const log = getLogger('example') | ||
function doSomething() { | ||
logger.debug('A debug message') | ||
log.debug('This is line five.') | ||
log.info('Everything is just fine.') | ||
log.warn('Oh, oh, not no much.') | ||
log.error('Aaargh, an error!') | ||
try { | ||
// ... | ||
} catch (error) { | ||
const { message, stack } = error | ||
logger.error({ | ||
message: 'Woaaah something bad happened! ' + message, | ||
stack | ||
}) | ||
} | ||
try { | ||
throw new Error('I am an error object.') | ||
} catch (error) { | ||
const { message, stack } = error | ||
log.error({ | ||
message: 'Woaaah something bad happened! ' + message, | ||
stack | ||
}) | ||
} | ||
``` | ||
The default log handler prints log data to `stderr`. If `stderr` is TTY log data is formatted for human consumption with emoji, colours and stack trace (for errors): | ||
![](screenshot.png) | ||
If `stderr` is not TTY log data os formatted for machine consumption (e.g. for log files) as [ndjson](http://ndjson.org/), with a time stamp, if `stderr` (for machine consumption e.g. log files): | ||
```json | ||
{"time":"2019-07-02T21:19:24.872Z","tag":"example","level":3,"message":"This is line five.","stack":"Error\n at Object.<anonymous> (/home/nokome/stencila/source/logga/example.js:21:5)\n at Module._compile (internal/modules/cjs/loader.js:689:30)\n at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)\n at Module.load (internal/modules/cjs/loader.js:599:32)\n at tryModuleLoad (internal/modules/cjs/loader.js:538:12)\n at Function.Module._load (internal/modules/cjs/loader.js:530:3)\n at Function.Module.runMain (internal/modules/cjs/loader.js:742:12)\n at startup (internal/bootstrap/node.js:266:19)"} | ||
{"time":"2019-07-02T21:19:24.875Z","tag":"example","level":2,"message":"Everything is just fine.","stack":"Error\n at Object.<anonymous> (/home/nokome/stencila/source/logga/example.js:22:5)\n at Module._compile (internal/modules/cjs/loader.js:689:30)\n at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)\n at Module.load (internal/modules/cjs/loader.js:599:32)\n at tryModuleLoad (internal/modules/cjs/loader.js:538:12)\n at Function.Module._load (internal/modules/cjs/loader.js:530:3)\n at Function.Module.runMain (internal/modules/cjs/loader.js:742:12)\n at startup (internal/bootstrap/node.js:266:19)"} | ||
{"time":"2019-07-02T21:19:24.875Z","tag":"example","level":1,"message":"Oh, oh, not no much.","stack":"Error\n at Object.<anonymous> (/home/nokome/stencila/source/logga/example.js:23:5)\n at Module._compile (internal/modules/cjs/loader.js:689:30)\n at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)\n at Module.load (internal/modules/cjs/loader.js:599:32)\n at tryModuleLoad (internal/modules/cjs/loader.js:538:12)\n at Function.Module._load (internal/modules/cjs/loader.js:530:3)\n at Function.Module.runMain (internal/modules/cjs/loader.js:742:12)\n at startup (internal/bootstrap/node.js:266:19)"} | ||
{"time":"2019-07-02T21:19:24.875Z","tag":"example","level":0,"message":"Aaargh, an error!","stack":"Error\n at Object.<anonymous> (/home/nokome/stencila/source/logga/example.js:24:5)\n at Module._compile (internal/modules/cjs/loader.js:689:30)\n at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)\n at Module.load (internal/modules/cjs/loader.js:599:32)\n at tryModuleLoad (internal/modules/cjs/loader.js:538:12)\n at Function.Module._load (internal/modules/cjs/loader.js:530:3)\n at Function.Module.runMain (internal/modules/cjs/loader.js:742:12)\n at startup (internal/bootstrap/node.js:266:19)"} | ||
{"time":"2019-07-02T21:19:24.875Z","tag":"example","level":0,"message":"Woaaah something bad happened! I am an error object.","stack":"Error: I am an error object.\n at Object.<anonymous> (/home/nokome/stencila/source/logga/example.js:27:9)\n at Module._compile (internal/modules/cjs/loader.js:689:30)\n at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)\n at Module.load (internal/modules/cjs/loader.js:599:32)\n at tryModuleLoad (internal/modules/cjs/loader.js:538:12)\n at Function.Module._load (internal/modules/cjs/loader.js:530:3)\n at Function.Module.runMain (internal/modules/cjs/loader.js:742:12)\n at startup (internal/bootstrap/node.js:266:19)\n at bootstrapNodeJSCore (internal/bootstrap/node.js:596:3)"} | ||
``` | ||
You can register a new handler by calling `addHandler` with a handling function. Or use `replaceHandlers` to replace any existing log handlers (including the default). |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
26502
233
67
5