Comparing version 0.7.0 to 0.8.0
{ | ||
"name": "anylogger", | ||
"version": "0.7.0", | ||
"version": "0.8.0", | ||
"description": "Get a logger. Any logger.", | ||
"main": "any.js", | ||
"main": "anylogger.js", | ||
"files": [ | ||
"any.js", | ||
"any.min.js" | ||
"anylogger.js", | ||
"anylogger.min.js", | ||
"anylogger.spec.js" | ||
], | ||
@@ -13,3 +14,3 @@ "scripts": { | ||
"prepare": "npm run test && npm run build", | ||
"test": "mocha any.spec.js" | ||
"test": "mocha anylogger.spec.js" | ||
}, | ||
@@ -32,2 +33,3 @@ "author": "Stijn de Witt", | ||
"anylogger", | ||
"microscopically small", | ||
"tiny", | ||
@@ -37,4 +39,5 @@ "logging", | ||
"console", | ||
"1kB" | ||
"1kB", | ||
"logging facade" | ||
] | ||
} |
277
README.md
@@ -1,2 +0,2 @@ | ||
# anylogger <sub><sup>0.7.0</sup></sub> | ||
# anylogger <sub><sup>0.8.0</sup></sub> | ||
### Get a logger. Any logger. | ||
@@ -28,6 +28,4 @@ | ||
## What is this? | ||
## A logging facade | ||
**A logging facade** | ||
We, the Javascript community, really need a logging facade. There are dozens | ||
@@ -43,13 +41,17 @@ of logging libraries around and we library authors face a dilemma. Which logger | ||
facade object by the actual logging framework with an | ||
[adapter](https://en.wikipedia.org/wiki/Adapter_pattern). So what we need is | ||
a simple and small logging facade and a bunch of adapters for popular loggers. | ||
[adapter](https://en.wikipedia.org/wiki/Adapter_pattern). | ||
**Introducing `anylogger`** | ||
So what we need is a simple and small logging facade and a bunch of adapters | ||
for popular loggers. | ||
A tiny [366](#gzip-size) bytes logging facade that you can include in your library to have | ||
logging 'just work', while at the same time allowing application developers | ||
to plug in any logging framework they choose. Instead of building in your own | ||
library specific configuration mechanism, or forcing the choice for a certain | ||
logging framework on your users, or just abandoning logging altogether, choose | ||
`anylogger` and for just [366](#gzip-size) bytes shared between all libraries doing this, we can | ||
## Introducing `anylogger` | ||
A tiny ~[360](#gzip-size) bytes logging facade that you can include in your | ||
library to have logging 'just work', while at the same time allowing | ||
application developers to plug in any logging framework they choose. | ||
Instead of building in your own library specific configuration mechanism, | ||
or forcing the choice for a certain logging framework on your users, | ||
or just abandoning logging altogether, choose `anylogger` and for just | ||
~[360](#gzip-size) bytes shared between all libraries doing this, we can | ||
plug in any framework of our choice and all libraries will automatically | ||
@@ -67,4 +69,6 @@ start to use that framework. Wouldn't it be much better and easier? | ||
* [any.js](https://unpkg.com/anylogger@0.7.0/any.js) (fully commented source ~5kB) | ||
* [any.min.js](https://unpkg.com/anylogger@0.7.0/any.min.js) (minified 601B, gzipped [366](#gzip-size)B) | ||
* [anylogger.js](https://unpkg.com/anylogger@0.8.0/anylogger.js) | ||
(fully commented source ~5kB) | ||
* [anylogger.min.js](https://unpkg.com/anylogger@0.8.0/anylogger.min.js) | ||
(minified 592 bytes, gzipped ~[360](#gzip-size) bytes) | ||
@@ -76,3 +80,3 @@ | ||
```html | ||
<script src="https://unpkg.com/anylogger@0.7.0/any.min.js"></script> | ||
<script src="https://unpkg.com/anylogger@0.8.0/anylogger.min.js"></script> | ||
<script>(function(){ // IIFE | ||
@@ -88,3 +92,3 @@ var log = anylogger('index.html') | ||
Depending on your project type, install just anylogger, or anylogger + | ||
your logging framework of choice + an anylogger adapter. | ||
your logging framework of choice + an anylogger adapter if needed. | ||
@@ -98,8 +102,11 @@ ### Install in a library project | ||
This will add `anylogger` as a dependency to your `package.json`: | ||
This will add `anylogger` as a dependency to your `package.json`. | ||
To enforce that your library ends up using the same anylogger version | ||
as the application itself, add anylogger as a peer dependency: | ||
```json | ||
{ | ||
"dependencies": { | ||
"anylogger": ">= 0.7.0 < 2" | ||
"peerDependencies": { | ||
"anylogger": "^0.8.0" | ||
} | ||
@@ -109,33 +116,8 @@ } | ||
I recommend to expand the version range here. By default NPM will set a | ||
range looking like `"^0.7.0"`, which is equivalent to `"0.7.x"` or | ||
`">= 0.7.0 < 0.7.0"`. This version range is probably too narrow. When | ||
multiple libraries depend on the same library, if their version ranges overlap, | ||
NPM will be able to make them all use the same version. But if their version | ||
ranges do not overlap, NPM will bundle multiple versions of the same library. | ||
So ideally we make sure version ranges always overlap. To that end, this | ||
project will be very conservative towards any code changes and will take 2 | ||
major versions for any compatibility breaking changes; in the first major | ||
version, deprecation notices will be added but stuff will still work. | ||
In the next major version, the change will be implemented. So if your code is | ||
working without any deprecation notices, it should continue to work with all | ||
upcoming versions including the next major, up to (but not including) the | ||
second next major. | ||
> You can just copy the entry from `dependencies`, it should be the same. | ||
So I recommend accepting everything up to the second next major release. | ||
That means that currently while at version `0.7.0`, we should set the version | ||
range to everything equal to or above `0.7.0` and below `2.0.0`: | ||
When the user installs our library, if the peer dependency is not satisfied | ||
by the project, NPM will warn about it during installation. | ||
```json | ||
{ | ||
"dependencies": { | ||
"anylogger": ">= 0.7.0 < 2.0.0" | ||
} | ||
} | ||
``` | ||
This should minimize our chances of getting multiple conflicting versions | ||
added to our app. | ||
### Install in an application project | ||
@@ -152,17 +134,15 @@ If you are building an application project and have selected a logging | ||
> Changing the version range here is less important as NPM install will | ||
> install the latest version by default, and this project will not be | ||
> used within other projects anyway. As long as the version ranges of the | ||
> libraries the project is using cover the currently installed version, | ||
> everything should work out fine. | ||
or, for [ulog](https://npmjs.com/package/ulog) which has native anylogger | ||
support since v2: | ||
or, for [ulog](https://npmjs.com/package/ulog): | ||
```sh | ||
npm install --save anylogger ulog anylogger-ulog | ||
npm install --save anylogger ulog | ||
``` | ||
Check out all [available adapters](https://www.npmjs.com/search?q=keywords:anylogger). | ||
> Because `ulog` supports `anylogger` natively, we don't need an adapter | ||
Check out all | ||
[available adapters](https://www.npmjs.com/search?q=keywords:anylogger). | ||
## Include | ||
@@ -193,3 +173,4 @@ | ||
In your main entry point, include your adapter so it extends anylogger: | ||
In your main entry point, include your adapter or library with native support | ||
so it extends anylogger: | ||
@@ -199,3 +180,15 @@ ### require | ||
```js | ||
require('anylogger-ulog') | ||
// for debug | ||
var debug = require('debug') | ||
require('anylogger-debug') | ||
// libraries now use debug | ||
debug.enable('my-library') | ||
// or, for ulog | ||
var ulog = require('ulog') | ||
// native support! no adapter needed :) | ||
// libraries now use ulog | ||
ulog.enable('my-library') | ||
// etc, see the specific library or adapter for details on anylogger support | ||
``` | ||
@@ -206,3 +199,13 @@ | ||
```js | ||
import 'anylogger-ulog' | ||
// for debug | ||
import debug from 'debug' | ||
import 'anylogger-debug' | ||
// libraries now use debug | ||
debug.enable('my-library') // enable debug mode | ||
// or, for ulog | ||
import ulog from 'ulog' | ||
// native support! no adapter needed :) | ||
// libraries now use ulog | ||
ulog.enable('my-library') // enable debug mode | ||
``` | ||
@@ -237,8 +240,8 @@ | ||
log.info(log.name + ' starting...'); | ||
var error = new Error('Oh no!'); | ||
log.error('Something went wrong', error); | ||
log.error('Something went wrong', new Error('Oh no!')); | ||
``` | ||
If you are able to restrict yourself to the [Anylogger API](#anylogger-api), | ||
your code will be framework independent and will work with any logger. | ||
your code will be framework independent and will work with any supported | ||
logging library. | ||
@@ -260,3 +263,3 @@ ```js | ||
```js | ||
function anylogger(name, options) => logger | ||
function anylogger(name, config) => logger | ||
``` | ||
@@ -268,4 +271,3 @@ | ||
#### name | ||
String. Optional. Defaults to `undefined`. | ||
The name of the logger. | ||
The name of the logger. String. Optional. Defaults to `undefined`. | ||
The recommended format is `<package-name>[:<sub>[:<sub> [..]]]`, | ||
@@ -278,15 +280,15 @@ as this is the [convention](https://www.npmjs.com/package/debug#conventions) | ||
#### options | ||
Object. Optional. Defaults to `undefined`. | ||
An options object. The use of such options objects varies wildly | ||
amongst implementations so it is recommended to avoid using it where | ||
possible. However in case of implementations that require it, anylogger | ||
passes any options object it is given around to allow the different | ||
extensions to use it where needed. | ||
#### config | ||
An optional config object. Object. Optional. Defaults to `undefined`. | ||
The use of such config objects varies wildly amongst implementations so | ||
it is recommended to avoid using it where possible. However in case of | ||
implementations that require it, anylogger passes any config object it | ||
is given on to [`anylogger.create`](#anyloggercreate) and | ||
[`anylogger.new`](#anyloggernew) to allow it to be used where needed. | ||
**When no arguments are given**, anylogger returns an object containing | ||
**When no arguments are given** anylogger returns an object containing | ||
all loggers created so far, keyed by name. | ||
**When a name is given**, anylogger returns the existing logger with that | ||
name, or creates a new one by calling `anylogger.create`. | ||
**When a name is given** anylogger returns the existing logger with that | ||
name, or creates a new one by calling [`anylogger.create`](#anyloggercreate). | ||
@@ -298,4 +300,4 @@ The returned logger adheres to the Logging API described below. | ||
The logger returned by `anylogger` is a function that can do logging on it's | ||
own: | ||
The logger returned by [`anylogger`](#anylogger) is a function that can | ||
do logging on it's own: | ||
@@ -315,3 +317,3 @@ ```js | ||
Because of this, the logger created by anylogger is compatible with most | ||
logging frameworks out there, which mostly use one of these two approaches. | ||
logging frameworks out there, which mostly use one or both of these approaches. | ||
@@ -338,2 +340,3 @@ The main API looks like this (in pseudo code): | ||
Is your logging framework not supported? No fear, just... | ||
@@ -344,4 +347,2 @@ ## Write an anylogger adapter | ||
anylogger and the logging framework the adapter is for as peer dependencies. | ||
Again, make sure to choose a wide version range; 2 major versions is | ||
recommended. | ||
@@ -354,4 +355,5 @@ You then need to modify one or more of the | ||
It is recommended you call your library `anylogger-[adapter]`, where | ||
`[adapter]` should be replaced with the name of the logging framework the | ||
adapter is for. For example, the adapter for `ulog` is called `anylogger-ulog`. | ||
`[adapter]` should be replaced with the name of the logging framework | ||
the adapter is for. For example, the adapter for `debug` is called | ||
`anylogger-debug`. | ||
@@ -369,3 +371,14 @@ In addition, it is recommended you add the keyword `"anylogger"` to the | ||
#### anylogger.levels | ||
An object describing log levels, keyed by name. | ||
```js | ||
anylogger.levels = {error:1, warn:2, info:3, log:4, debug:5, trace:6} | ||
``` | ||
An object containing a mapping of level names to level values. | ||
In anylogger, a higher level of logging means more verbose logging: more | ||
log messages will be generated. The lowest level of logging (none at all) | ||
has value `0`. Higher levels have higher values. To be compliant with the | ||
anylogger API, loggers should support at least the default levels, but | ||
they may define additional levels and they may choose to use different | ||
numeric values for these levels. | ||
You can replace or change this object to include levels corresponding with | ||
@@ -377,19 +390,32 @@ those available in the framework you are writing an adapter for. Please | ||
#### anylogger.out | ||
An object (defaults to the native `console`, or `undefined`) containing the | ||
log methods to perform the actual log calls. You can replace this object | ||
with an object handling log calls in some different way. Anylogger will | ||
use the method with the name that matches the level name and if that is not | ||
available fall back to the `log` method, or to a noop. | ||
#### anylogger.create | ||
```js | ||
anylogger.create(name, config) => logger | ||
``` | ||
A method that is called whenever a new logger is created. Calls | ||
`anylogger.new` and `anylogger.ext`. You can override this method | ||
with your own factory, but it is probably easier to override just | ||
`anylogger.new`, chaining the old method. | ||
[`anylogger.new`](#anyloggernew) and [`anylogger.ext`](#anyloggerext). | ||
You can override this method with your own factory, but it is probably easier | ||
to override just `anylogger.new`, chaining the old method. | ||
##### name | ||
The name of the new logger. String. Required. | ||
##### config | ||
An optional config object. Object. Optional. | ||
#### anylogger.new | ||
A method that is called to create the logger function. You can chain | ||
this method and include any one-time customizations here: | ||
```js | ||
anylogger.new(name, config) => logger | ||
``` | ||
A method that is called to create the logger function. | ||
##### name | ||
The name of the new logger. String. Required. | ||
##### config | ||
An optional config object. Object. Optional. | ||
You can chain this method and include any one-time customizations here: | ||
```js | ||
@@ -402,5 +428,5 @@ import anylogger from 'anylogger' | ||
// override anylogger.new | ||
anylogger.new = function(name, options) { | ||
anylogger.new = (name, config) => { | ||
// call the original function to chain it | ||
var logger = make(name, options) | ||
var logger = make(name, config) | ||
// add your customizations | ||
@@ -413,26 +439,38 @@ logger.myCoolFeature = function(){logger.info('My cool feature!')} | ||
If you need to re-apply customizations any time relevant config changes (such as | ||
active log level changing), override `anylogger.ext`. | ||
If you need to re-apply customizations any time relevant config changes (such | ||
as active log level changing), override `anylogger.ext`. | ||
#### anylogger.ext | ||
A method that is called to extend the logger function. The default | ||
implementation loops over the `anylogger.levels` and creates log methods for | ||
each level. You can override or chain this method to change the way the log | ||
methods are (re-)created. By default, all log methods will delegate to the | ||
native console. But in a library that supports log levels, all methods | ||
corresponding to log levels lower than the currently active levels might be | ||
replaced with no-op methods instead. Or maybe the destination of the log | ||
messages might change dynamically based on configuration. Apply such changes | ||
in `anylogger.ext` as it will be called again whenever relevant config | ||
changes. This allows adapters to re-extend the logger so that the new | ||
configuration takes effect. | ||
```js | ||
anylogger.ext(logger) => logger | ||
``` | ||
A method that is called to extend the logger function. May be called multiple | ||
times on the same logger function. | ||
##### logger | ||
The logger that should be (re-)extended. Function. Required. | ||
The default implementation loops over the | ||
[`anylogger.levels`](#anyloggerlevels) and creates log methods for each level. | ||
You can override or chain this method to change the way the log methods are | ||
(re-)created. By default, all log methods will delegate to the native console. | ||
But in a library that supports log levels, all methods corresponding to log | ||
levels lower than the currently active levels might be replaced with no-op | ||
methods instead. Or maybe the destination of the log messages might change | ||
dynamically based on configuration. Apply such changes in `anylogger.ext` as it | ||
will be called again whenever relevant config changes. This allows adapters to | ||
(re-)extend the logger so that the new configuration takes effect. | ||
> You may need to ensure in your adapter that `anylogger.ext` is called | ||
> whenever relevant config changes. By hooking into setters for example. | ||
#### anylogger.log | ||
The log function returned by anylogger calls `anylogger.log` to handle the | ||
log calls. Only log calls invoked via the logger function itself are dispatched | ||
through this method. Calls to the log methods, e.g. to `log.info`, are routed | ||
directly to the corresponding method on `any.out`. Hence `any.out` is a better | ||
extension point when you need to intercept *all* log invocation. | ||
```js | ||
anylogger.log([level='log'], ...args) | ||
``` | ||
The log function returned by anylogger calls `anylogger.log`, which determines | ||
the log level and invokes the appropriate log method. | ||
Please have a look at the [source](https://unpkg.com/anylogger@0.7.0/any.js) | ||
Please have a look at the | ||
[source](https://unpkg.com/anylogger@0.8.0/anylogger.js) | ||
it should make it more clear how to write an adapter. Also consider studying | ||
@@ -451,3 +489,4 @@ the [available adapters](https://www.npmjs.com/search?q=keywords:anylogger) | ||
Add an issue in this project's [issue tracker](https://github.com/download/anylogger/issues) | ||
Add an issue in this project's | ||
[issue tracker](https://github.com/download/anylogger/issues) | ||
to let me know of any problems you find, or questions you may have. | ||
@@ -458,3 +497,3 @@ | ||
Copyright 2019 by [Stijn de Witt](http://StijnDeWitt.com). Some rights reserved. | ||
© 2019 by [Stijn de Witt](http://StijnDeWitt.com). Some rights reserved. | ||
@@ -461,0 +500,0 @@ |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
29505
6
272
484
1