From 1c0d7971e7d356aec8efd0f187525db85874385a Mon Sep 17 00:00:00 2001 From: Stijn de Witt Date: Thu, 4 Feb 2021 20:23:08 +0100 Subject: [PATCH] 2.0.0-beta.14: Fine-tuning + Slightly updated default formats + Updated the README * Added a screenshot to illustrate alignment --- README.md | 566 ++++++++++++++++++++++++++++++---------- mods/formats/default.js | 2 +- package.json | 2 +- screenshot-beta.11.jpg | Bin 0 -> 69258 bytes 4 files changed, 426 insertions(+), 144 deletions(-) create mode 100644 screenshot-beta.11.jpg diff --git a/README.md b/README.md index 562f05a..2bee4e9 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# ulog v2.0.0-beta.13 +# ulog v2.0.0-beta.14 ### The Universal Logger [![npm](https://img.shields.io/npm/v/ulog.svg)](https://npmjs.com/package/ulog) @@ -8,36 +8,43 @@ . -![logo](https://unpkg.com/ulog@2.0.0-beta.13/ulog.png) +![logo](https://unpkg.com/ulog@2.0.0-beta.14/ulog.png) -## The logger for applications +## The logger for javascript applications `ulog` is *the* logger for Javascript applications. It's universal, meaning it runs everywhere. You can use `ulog` in your Express server application running on Node JS just as well as in your React single page application running in the browser. It just works. -![screenshot](https://unpkg.com/ulog@2.0.0-beta.13/screenshot.jpg) +![screenshot](https://unpkg.com/ulog@2.0.0-beta.14/screenshot.jpg) ## Features Ulog marries the feature sets from [`debug`](https://npmjs.com/package/debug) and [`loglevel`](https://npmjs.com/package/loglevel) and adds some of it's own! -| Feature | debug | loglevel |   ulog   -| -------------- | -------------- | -------------- | -------------- -| Debug mode | ✓ | | ✓ -| Levels | | ✓ | ✓ -| Dynamic cfg | | | ✓ -| Formatting | ✓ | | ✓ -| Config fmt | | | ✓ -| Preserve stack | | ✓ | ✓ -| Colors | ✓ | | ✓ -| Align | | | ✓ -| Add-ons/Mods | | ✓ | ✓ -| Lazy loading | | | ✓ -| Anylogger | ✓ (1) | ✓ (1) | ✓ (2) - -(1) via an adapter -(2) native support +| Feature |   debug   | loglevel |   ulog   | +| ------------------------------------------- | ------------------- | ------------------- | ------------------ | +| [Footprint](#footprint) | 3.2kB | 1.4kB | 2.8kB | +| [Debug mode](#debug-mode) | ✓ | ✓ (1) | ✓ | +| [Levels](#levels) | | ✓ | ✓ | +| [Configurable](#configure) | ✓ | ✓ (2) | ✓ | +| [Dynamic config](#dynamic-config) | | | ✓ | +| [Channels](#channels) | | | ✓ | +| [Outputs](#outputs) | | | ✓ | +| [Custom outputs](#custom-outputs) | | | ✓ | +| [Formatting](#formatting) | ✓ | | ✓ | +| [Preserves callstack](#preserves-callstack) | | ✓ | ✓ | +| [Configurable format](#configurable-format) | | | ✓ | +| [Custom formats](#custom-formats) | | | ✓ | +| [Colors](#colors) | ✓ | | ✓ | +| [Alignment](#alignment) | | | ✓ | +| [Add-ons / Mods](#mods) | | ✓ | ✓ | +| [Lazy loading](#lazy-loading) | | | ✓ | +| [Anylogger support](#anylogger-support) | ✓ (3) | ✓ (3) | ✓ | + +(1) emulated with levels +(2) in browser only +(3) via an adapter @@ -68,9 +75,11 @@ log('Logging is easy!') This way, your code is decoupled from `ulog` and if you ever want to switch to another logging library, you will be able to do so without having to change any of that code. -> **anylogger** -> -> [`anylogger`](https://npmjs.com/package/anylogger) is a logging facade that allows code to use logging without getting coupled to a specific logging system. You can use that code with any logging system out there. +##### Anylogger support +> [`anylogger`](https://npmjs.com/package/anylogger) is a logging facade that +> allows code to use logging without getting coupled to a specific logging +> system. You can use that code with any logging system out there. `ulog` has +> anylogger support built in. For other loggers, adapters are available. ## The logger for libraries @@ -107,7 +116,7 @@ log('Logging is easy') If you want, you can import `ulog` with a script tag: ```html - + @@ -120,19 +129,21 @@ log('Logging is easy!') ## Download -If you want the file for the browser to include in your project yourself, you can download it from here. +If you want the file for the browser to include in your project yourself, you +can download it from here. -* [ulog.min.js](https://unpkg.com/ulog@2.0.0-beta.13/ulog.min.js) (~2.8kB minified and gzipped) -* [ulog.lazy.min.js](https://unpkg.com/ulog@2.0.0-beta.13/ulog.lazy.min.js) (~4.3kB minified and gzipped) +* [ulog.min.js](https://unpkg.com/ulog@2.0.0-beta.14/ulog.min.js) (~2.8kB minified and gzipped) +* [ulog.lazy.min.js](https://unpkg.com/ulog@2.0.0-beta.14/ulog.lazy.min.js) (~4.3kB minified and gzipped) > `ulog.min.js` lazy loads `ulog.lazy.min.js` on demand, so make sure to include both files in your download -* [full.min.js](https://unpkg.com/ulog@2.0.0-beta.13/full.min.js) (~5.7kB minified and gzipped) +* [full.min.js](https://unpkg.com/ulog@2.0.0-beta.14/full.min.js) (~5.7kB minified and gzipped) > Full bundle, no lazy loading -I recommend to use a bundler instead. Loading lots of script tags is inefficient and hard to manage. -Also see the section on [lazy loading with webpack](#lazy-loading-with-webpack) +I recommend to use a bundler instead. Loading lots of script tags is +inefficient and hard to manage. Also see the section on +[lazy loading with webpack](#lazy-loading-with-webpack) ## Why `ulog` @@ -145,20 +156,7 @@ The two most popular logging libraries on NPM at the moment are [`debug`](https: Both these loggers lack the ability to configure the logger from the querystring, which I found to be a very desirable feature for web development as it allows you to create a URL that has the log config embedded, which you can then send to other developers or users etc. E.g: `https://example.com/page?log=debug`. -What I want is a logging library that combines the best aspects of both these loggers and adds the features that I miss in both. Specifically here are the features that I want in my ultimate logging library: - -* Simple API -* Supports all `console` log methods -* Supports levels -* Configurable at runtime (without requiring a restart) -* Accepts configuration from the querystring -* Leaves the call stack alone -* Formatted and colored log messages -* Configurable log output and formatting options built in -* Extensible -* Decoupled from client code -* Compact - +What I want is a logging library that combines the best aspects of both these loggers and adds the features that I miss in both. `ulog` is my attempt at building this library. It's base API is compatible with that of `debug` and `loglevel` and with the console, making it a drop-in replacement for all of these in many cases. It has a configuration mechanism that is compatible with that of `debug`, but that is more powerful and is monitored for changes at runtime. It accepts configuration from the querystring allowing you to craft URLs with log config embedded in it. It has powerful, configurable formatting included by default and it does this without mangling the call stack, so the filename/line number entries in the browser console remain unharmed. You can specify where the log output should go and where it should drain. It's completely modular, so you can not only easily add features through 'mods', but you can actually even drop features you don't need by not loading the mods those features are in. It has native `anylogger` support, decoupling the client code from the logger. And it supports lazy loading so we can get all those great features without bloating our bundle. I hope you will give `ulog` a try. If you have feedback on it, or found an issue, please let me know on the [issue tracker](https://github.com/download/ulog/issues). @@ -187,7 +185,7 @@ if (log.enabledFor('warn')) { Note that any logging code written for either `debug`, `loglevel` or the console should be able to do it's logging just like it did before, but now using a `ulog` logger instead. This backward compatibility should make migrating from any of these to `ulog` very easy. And because this is just the `anylogger` API, you should even be able to migrate back to `debug` or `loglevel` without any changes at all, by just including the right adapter in your entry point. Of course once you get used to `ulog`, you will never want to go back! :p -## Logging levels +## Levels `anylogger` defines 6 logging levels, which correspond with the natively available logging functions on the console. `ulog` creates constants for these levels on all loggers: @@ -257,6 +255,18 @@ relevant anyway. > Attention! Chromium-based browsers have their own level filter and by default, debug messages are filtered away. +## Footprint + +When we support logging with some logging library, we add code to our +application that many users don't actually need. There are techniques to remove +this code from our production builds, but they sacrifice logging with it. In +many scenarios we actually do want logging in the production builds. To assist +support personel in diagnosing user problems for example. So it's beneficial if +the minimum amount of code we need to load to support logging is small. This +minimum amount of code we call the *footprint*. `ulog` keeps its footprint +small by utilizing [lazy loading](#lazy-loading). + + ## Debug mode Debug mode is a feature that `ulog` copied from `debug` and it responds to the @@ -273,23 +283,34 @@ const log = anylogger('my-app') log('Hi!') // is output because logger is in debug mode ``` -## Outputs - -Outputs is a feature that separates `ulog` from `debug` and `loglevel`. This corresponds with what other libraries sometimes refer to as 'appenders'. In `ulog`, where messages are going is completely configurable at runtime. You can even configure where discarded messages are going! +## Channels -By default, all log methods on a logger are associated with one of two channels, `output` and `drain`. To configure these, two properties are added on each logger: - -* `log.output`, defaults to `'console'` -* `log.drain`, defaults to `'drain'` - -These correspond with config options [`log_output`](#config_option_log_output) -and [`log_drain`](#config_option_log_drain) respectively. +In `ulog`, logging is always sent to exactly one channel. By default, +two channels exist: `output`, for messages of loggers that are in +debug mode, or that are at an enabled level, and `drain`, for those +messages that are filtered away. By using a separate channel for the drain, we can override the default behavior of using noops for all log levels that are outside of the active levels. We could for example send *all* logging to a database and only later filter it, when we display it for example. +A channel has one or more configurable [outputs](#outputs) that can optionally +apply [formatting](#formatting) to the message. + + +## Outputs + +In `ulog`, where messages are going is completely configurable at runtime. +You can even configure where discarded messages are going. + +By default all log methods on a logger are associated with one of two channels, +`output` and `drain`. To configure the outputs for these channels, two +config options are available: + +* [config option `log_output`](#config-option-log_output), defaults to `'console'` +* [config option `log_drain`](#config-option-log_drain), defaults to `'drain'` + When the logger is created, each log method is sent either to the `output` channel, or to the `drain` channel, based on the current log level for that logger and whether that logger is in debug mode. @@ -371,72 +392,74 @@ This way you can add outputs that send log messages to memory, a file, localStor ## Formatting -Formatting is another feature that separates `ulog` from `debug` and `loglevel`. `debug` has formatting, but it is hardcoded and messes up the call stack and there is not much you can do about it. `loglevel` does not mess up the call stack, but it also has no formatting at all out of the box. If we are giving all loggers names, it would at least be good to see those names in the log output right? How else do we know which loggers to enable and disable? +Formatting is another feature that separates `ulog` from `debug` and +`loglevel`. `debug` has formatting, but it is hardcoded and messes up the +callstack and there is not much you can do about it. `loglevel` does not mess +up the callstack, but it also has no formatting at all out of the box. -Ulog uses [kurly](https://npmjs.com/package/kurly) to support advanced configurable and customizable formatting, *without mangling the call stack*. As long as only [static kurly tags](https://www.npmjs.com/package/kurly/v/2.0.0-beta.2#static-tags) are used as formats, the call stack can remain unharmed. +Ulog uses [kurly](https://npmjs.com/package/kurly) to support advanced, +configurable and customizable formatting, [without mangling the callstack](#preserves-callstack). -When we make a function that does some formatting and then calls `console.log` with the formatted message and we make the client code use our new function to do the logging (as `debug` does), we inject a function between `console.log` and the client code in the call stack that `console.log` uses to show the filenames and line numbers. The result will be that these will no longer point to the client code, but to that formatting function that was inserted. That is a problem imho as it breaks a very useful feature. Ulog finds a way around this, using static kurly tags and the fact that the console can do log formatting and can call `toString` on it's arguments to do formatting of the result. +### Configurable format -When formatting is used, the default format string on Node is: +The actual format used is configurable easily via `ulog`'s powerful +configuration mechanism. + +The default format string on Node is: ```sh -log_format=lvl name message perf +lvl name:22 message perf ``` -This makes the output closely match that of debug. It sacrifies the call stack for a colored and formatted `message` and having the `perf` measurements after the message i.s.o before it. +This makes the output closely match that of debug. It sacrifices the callstack +for a colored and formatted `message` and having the `perf` measurements after +the message i.s.o before it. On browsers, we want to spare the call stack, so there the default is: ```sh -log_format=lvl name perf +lvl name perf ``` -We don't include the message, but it will be appended as the last argument automatically. The result if nicely formatted messages with the filename/line number entries in the broswer debug console intact. +We don't include the `message`, but it will be appended as the last argument +automatically. The result is nicely formatted messages with the filename/line +number entries in the browser debug console intact. -### Types of formats +To override the default format, just set +[config option `log_format`](#config-option-log_format) to the format you want. -Formats come in two flavors: +Formats available out of the box include: -**dynamic** +* [x] [Format `date`](#format-date) +* [x] [Format `lvl`](#format-lvl) +* [x] [Format `message`](#format-message) +* [x] [Format `name`](#format-name) +* [x] [Format `perf`](#format-perf) +* [x] [Format `time`](#format-time) +* [x] [Fallback format](#fallback-format) -Dynamic formats have full access to the message. But they do mess up the call stack. A dynamic format has this signature: -```js -ulog.use({ - use: [ require('ulog/mods/formats') ], - format: { - dynamicFormat: function(ctx) { - // one-time init here - return function(rec) { - // rec.message contains full message - return /* ... */ - } - } - } -}) -``` +### Format syntax -**static** +`ulog` uses the new [options](https://www.npmjs.com/package/kurly/v/2.0.0-beta.2#options) +in `kurly` v2 to make tag open/close markers optional and enable nicer looking format +strings. This means that `lvl name perf` and `{lvl} {name} {perf}` are +equivalent. When using no open/close markers, any non-identifier symbols +following the tag name are considered nested text. For example for the format +string `name:22`, the `name` format will receive `':22'` as `ctx.text`. This +allows for parameterized formats, as `ulog` has done to support +[padding options](#padding-options). -Static formats do not have access to the message. But they do not break the call stack! So prefer static formats if possible. +### Preserves callstack -Static formats have this signature: +`ulog`'s formatting system has the unique (1) ability to do +formatting while [preserving the callstack](#preserves-callstack). As long as +only [static kurly tags](https://www.npmjs.com/package/kurly/v/2.0.0-beta.2#static-tags) +are used as formats, the call stack can remain unharmed. -```js -ulog.use({ - use: [ require('ulog/mods/formats') ], - format: { - staticFormat: function(ctx, rec) { - // one-time init here - return function(){ - // rec.message is undefined - // rec.name, rec.level etc is populated - return /* ... */ - } - } - } -}) -``` +> (1) I do not know of any other logger out there that has this feature, but if +> you do know one, please let me know in the +> [issue tracker](https://github.com/download/ulog/issues) ### Included formats @@ -482,19 +505,67 @@ All included formats support some padding options. For example, to pad out the logger names to 16 characters and align the text on the left, use `name<16` or `name:16`. To align the text on the right, use `name>16`. +### Custom formats -### Make your own custom format -You can easily add your own custom format to the list above. To do so, just `ulog.use` a mod with a `formats` property including your format, like so: +`ulog`'s formatting system is easily extendable by adding +[kurly tags](https://www.npmjs.com/package/kurly#tags) to a key `formats` +under a mod: -*index.js* ```js -var ulog = require('ulog') +import ulog from 'ulog' +import formats from 'ulog/mods/formats' ulog.use({ - use: [ require('ulog/mods/formats') ], + use: [ formats ], formats: { - cool: function(ctx) { + custom: (ctx) => (rec) => (['custom'].concat(rec.message)), + random: (ctx, rec) => () => Math.random() + } +}) +``` + +These tags then become available in the format string. + +> We used two different signatures here, because there are two types of formats. + +### Types of formats + +Formats come in two flavors: + +#### Dynamic formats + +Dynamic formats have full access to the message. But they do mess up the call stack. A dynamic format has this signature: + +```js +ulog.use({ + use: [ require('ulog/mods/formats') ], + format: { + dynamicFormat: function(ctx) { + // one-time init here return function(rec) { - return ['Cool!!'].concat(rec.message) + // rec.message contains full message + return /* ... */ + } + } + } +}) +``` + +#### Static formats + +Static formats do not have access to the message. But they do not break the call stack! So prefer static formats if possible. + +Static formats have this signature: + +```js +ulog.use({ + use: [ require('ulog/mods/formats') ], + format: { + staticFormat: function(ctx, rec) { + // one-time init here + return function(){ + // rec.message is undefined + // rec.name, rec.level etc is populated + return /* ... */ } } } @@ -503,21 +574,93 @@ ulog.use({ To read more about kurly and custom kurly tags, refer to the kurly documentation on [creating kurly tags](https://www.npmjs.com/package/kurly#creating-tags) +## Colors +Who doesn't like some colors?! Apart from making things prettier, when used +correctly they can actually also make our logs *easier* to read. Now I don't +know about you, but I find reading logs hard, so I'll take all the help I can +get! -## Configure +If you don't want colors, you can suppress them using +[config option `log_color`](#config-option-log_color). + + +## Alignment +Browsers have great debug consoles these days. They even include stacktrace +info for higher-level messages. But they did mess one thing up imho; the +messages at these higher levels are indented a bit more than the other +messages, making the logging harder to read. This can be clearly seen in the +screenshot from `ulog` v2.0.0-beta-11, which did not yet have alignment: -`ulog` features a simple, yet powerful and flexible configuration mechanism. On Node JS, we can configure `ulog` via program arguments, environment variables or a configuration file. On browsers, we use querystring arguments or localStorage. On both platforms, the configuration is monitored and changes to it are picked up by `ulog` at runtime without the need to restart the application. +![screenshot](https://unpkg.com/ulog@2.0.0-beta.14/screenshot-beta.11.jpg) -`ulog`'s configuration mechanism is an extension to that of [`debug`](https://npmjs.com/package/debug) and is compatible with it. `debug` is one of the most popular logging packages in the NPM ecosystem, with tens of thousands of packages depending on it, so having `ulog`'s configuration mechanism be compatible with it makes for a very smooth migration path. If your app or library is currently using `debug`, you should be able to replace it with `ulog` with no or only minor changes. +`ulog` now automatically adds some formatting that negates the extra indentation +the messages at these higher levels get, so all messages are nicely aligned: + +![screenshot](https://unpkg.com/ulog@2.0.0-beta.14/screenshot.jpg) + +You can control alignment with [config option `log_align`](#config-option-log_align). + + +## Configure + +`ulog` features a simple, yet powerful and flexible configuration mechanism. On +Node JS, we can configure `ulog` via program arguments, environment variables +or a configuration file. On browsers, we use querystring arguments or +localStorage. On both platforms, the configuration is monitored and changes to +it are picked up by `ulog` at runtime without the need to restart the +application. + +`ulog`'s configuration mechanism is an extension to that of +[`debug`](https://npmjs.com/package/debug) and is compatible with it. `debug` +is one of the most popular logging packages in the NPM ecosystem, with tens of +thousands of packages depending on it, so having `ulog`'s configuration +mechanism be compatible with it makes for a very smooth migration path. If your +app or library is currently using `debug`, you should be able to replace it +with `ulog` with no or only minor changes. We configure `ulog` by adjusting configuration options. * [`log`](#config_option_log): The main setting to control logger's levels with * [`debug`](#config_option_debug): For compatibility with `debug` * [`log_config`](#config_option_log_config): To specify the configuration file (Node JS only) -* [`log_output`](#config_option_log_output): To configure where logging should go (defaults to `console`) -* [`log_drain`](#config_option_log_drain): To configure where logs should drain (defaults to `drain`) +* [`log_output`](#config_option_log_output): To configure where logging should go +* [`log_drain`](#config_option_log_drain): To configure where logs should drain * [`log_format`](#config_option_log_format): To configure the format for log messages +* [`log_color`](#config_option_log_color): To enable or disable colors +* [`log_align`](#config_option_log_align): To enable or disable alignment + +### Log configuration syntax +`debug` has a simple but powerful configuration mechanism. You set an environment variable or localStorage option named `DEBUG` and you assign it a value that expresses which loggers to enable. E.g.: + +```sh +DEBUG=test,my:*,-my:lib +``` +The format is basically a comma-separated list of logger names, using the asterisk as a wildcard character and optionally negating the expression by preceding it with a minus sign. So the expression above includes `test` and `my:*` loggers, except for `my:lib` which is excluded. + +`ulog` extends this configuration mechanism. With `debug`, you can only turn loggers on and off, but `ulog` allows for a much more varied range of options. This is achieved by extending the configuration syntax so it also accepts the value applicable for the loggers matching the expression. Also we allow a semicolon-separated list of such expression=value pairs. For example, to set the logger `test` to debug and `my:*` loggers except for `my:lib` to info, we could write: + +```sh +log=test=debug;my:*,-my:lib=info +``` + +If an option only contains a value, `ulog` implicitly adds `*` as the expression. So we can write: +```sh +log=info +``` +and it's equivalent to +```sh +log=*=info +``` +We can even combine this. So we could write: +```sh +log=info;my:*=debug +``` +and it will set the level for all loggers to info, except for the ones starting with `my:`, which are set to debug. + +A special case is the config option [debug](#config_option_debug), which is designed to be compatible with `debug` so code using `ulog` will react to that setting in the same way. + +Most of the config options support this syntax. + ### Via program arguments On Node JS we can pass log configuration options as program arguments: @@ -557,37 +700,14 @@ In browsers, we can place our log configuration in localStorage and it will be r localStorage.setItem('log', 'debug') ``` -### Log configuration syntax -`debug` has a simple but powerful configuration mechanism. You set an environment variable or localStorage option named `DEBUG` and you assign it a value that expresses which loggers to enable. E.g.: +### Dynamic config +`ulog`'s configuration mechanism watches the configuration for changes while +the program is running and reacts to them in real-time. No more restarting your +application just to change some log level! On Node JS, `ulog` watches a +configuration file. Use +[Config option `log_format`](#config-option-log_format) to specify the +location. In browsers, `ulog` monitors `localStorage` for changes. -```sh -DEBUG=test,my:*,-my:lib -``` -The format is basically a comma-separated list of logger names, using the asterisk as a wildcard character and optionally negating the expression by preceding it with a minus sign. So the expression above includes `test` and `my:*` loggers, except for `my:lib` which is excluded. - -`ulog` extends this configuration mechanism. With `debug`, you can only turn loggers on and off, but `ulog` allows for a much more varied range of options. This is achieved by extending the configuration syntax so it also accepts the value applicable for the loggers matching the expression. Also we allow a semicolon-separated list of such expression=value pairs. For example, to set the logger `test` to debug and `my:*` loggers except for `my:lib` to info, we could write: - -```sh -log=test=debug;my:*,-my:lib=info -``` - -If an option only contains a value, `ulog` implicitly adds `*` as the expression. So we can write: -```sh -log=info -``` -and it's equivalent to -```sh -log=*=info -``` -We can even combine this. So we could write: -```sh -log=info;my:*=debug -``` -and it will set the level for all loggers to info, except for the ones starting with `my:`, which are set to debug. - -A special case is the config option [debug](#config_option_debug), which is designed to be compatible with `debug` so code using `ulog` will react to that setting in the same way. - -Most of the config options support this syntax. ### Config option `log` @@ -633,7 +753,7 @@ log_drain=my:*,-my:lib=noop ### Config option `log_format` -Specify the format to use. Defaults to `lvl name message perf` on Node JS and `lvl name perf` on browsers. +Specify the format to use. Defaults to `lvl name:22 message perf` on Node JS and `lvl name perf` on browsers. ```sh log_format=lvl name perf message;my:*=lvl name perf @@ -643,6 +763,166 @@ This sets `lvl name perf message` as the default format, while assigning a diffe For more details, refer to the [section on formatting](#formatting) +### Config option `log_color` + +Specify whether colors should be enabled. Defaults to `on`. + +```sh +log_color=off +``` + +### Config option `log_align` + +Specify whether messages should be aligned. Defaults to `on`. + +```sh +log_align=off +``` + +## Mods + +`ulog` is completely modular, consisting of a microscopically small core and a +whole bunch of mods. The mods are small pieces of functionality, designed to +be usable stand-alone or in combination with each other. All functionality that +`ulog` adds to `anylogger`, it adds in the form of mods. All, except for the +ability to add mods itself, in the form of method `ulog.use`, that is in core. + +To add a mod, call `ulog.use` with either an individual mod + +```js +ulog.use({ + // an empty mod +}) +``` + +or with an array of mods: + +```js +ulog.use([ + { /* a mod */ }, + { /* another mod */ }, +]) +``` + +A mod is an object that can define many things declaratively: + +* That it extends some core functionality +* That it uses other mods +* That it adds settings +* That it adds properties to loggers +* That it adds outputs / formats / other components +* That it watches some config option + +As an example, here is a mod that does most of these things: + +```js +var boolean = require('ulog/mods/props/boolean') + +ulog.use({ + use: [ require('./some/mod/we/use') ], + extend: { someProp: 'addedToUlog' }, + settings: { + cool: { + config: 'log_cool' + prop: boolean(), + } + }, + outputs: { + file: { + log: function(){ + console.info.apply(console, ['file'].concat([].slice.call(arguments))) + } + } + }, + formats: { + random: function(ctx, rec){ + return function(){ + return Math.random() + } + } + }, + watch: { + 'debug': function(){ + console.info('debug setting changed') + } + } +}) +``` + +Interestingly, most of these features of mods are being added by mods. For +example the ability to add settings is added by the `settings` mod. Studying +the way `ulog`'s featureset is built from mods by reading the source code of +the included mods is the best way to learn about writing mods for now. + + +## Lazy loading + +`ulog` being built with mods makes it easy to use lazy loading to reduce the +minimum [footprint](#footprint). If you use ulog from a [script tag](#script-tag) +(not recommended), you can get it for free. Otherwise, you have to configure +your bundler to code-split. + +### Lazy-loading with Webpack + +Have a look at [ulog.bundle.js](https://github.com/Download/ulog/blob/master/ulog.bundle.js) +for an example of doing lazy loading with [Webpack](https://webpack.js.org/). + +Basically it only loads `ulog/base` and then configures a watch that loads the +remaining mods on-demand. It's using Webpack-specific API `require.ensure` for +this. Other bundlers support it in similar ways. + +```js +var ulog = require('ulog/base') + +// add a mod to ulog to load logging on-demand +ulog.use({ + + watch: { + // watch for changes in these config keys + 'debug,log,log_output,log_format,log_color,log_align': + + // when changes happen, load the other mods if needed + function(){ + var ulog = this + // webpack specific API to lazy load modules + require.ensure( + // ensure these modules are loaded + [ + 'ulog/mods/debug', + 'ulog/mods/levels', + 'ulog/mods/outputs', + 'ulog/mods/formats', + 'ulog/mods/colors', + 'ulog/mods/align', + ], + // then execute this function, notice require being overridden + function(require){ + // add the mods to ulog + if (ulog.use([ + // use the overridden require to lazy load the modules + require('ulog/mods/debug'), + require('ulog/mods/levels'), + require('ulog/mods/outputs'), + require('ulog/mods/formats'), + require('ulog/mods/colors'), + require('ulog/mods/align'), + ])) { + // re-initialize the loggers if mods were added + ulog.ext() + } + }, + // chunkname webpack will use for these lazy modules: ulog.lazy.min.js + 'ulog.lazy' + ) + }, + } +}) +``` + +If you have successfully lazy-loaded `ulog` with other bundlers, please drop a +comment in the [issue tracker](https://github.com/ulog/issues), or create a +PR to add a section about it here in the README. + ## Decoupling code from `debug` @@ -695,6 +975,8 @@ Credits go to: which was a great inspiration for ulog. * Tim Perry for creating [loglevel](https://npmjs.com/package/loglevel), which was another great inspiration for ulog. +* Community members [Jakub Jirutka](https://github.com/jirutka) and + [Alex Kesling](https://github.com/akesling) for making code contributions. ## Copyright diff --git a/mods/formats/default.js b/mods/formats/default.js index 6186f27..b591590 100644 --- a/mods/formats/default.js +++ b/mods/formats/default.js @@ -1 +1 @@ -module.exports = "lvl name message perf" \ No newline at end of file +module.exports = "lvl name:22 message perf" \ No newline at end of file diff --git a/package.json b/package.json index 7013177..b291ce8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ulog", - "version": "2.0.0-beta.13", + "version": "2.0.0-beta.14", "description": "The universal logger", "main": "./ulog.js", "unpkg": "ulog.min.js", diff --git a/screenshot-beta.11.jpg b/screenshot-beta.11.jpg new file mode 100644 index 0000000000000000000000000000000000000000..25499e3aca6b0abb2558c42f31342635a1ec4912 GIT binary patch literal 69258 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Թ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