# Modifiers
WARNING
Adze v1.x is now deprecated! Please upgrade to v2.x (opens new window)!
Once you have an Adze log instance you can now start applying modifiers. Modifiers are methods that alter the log in some way and then return the log instance so that you may chain more modifiers or terminate the instance. Keep in mind, some modifiers have a dependency on the presence of a label and labels rely on Shed.
# assert
This modifier accepts an assertion boolean expression and will only print if the boolean expression fails (is a falsy value).
# Interface
class BaseLog {
public assert(assertion: boolean): this;
}
# Example
import { adze } from 'adze';
const x = 2;
const y = 3;
// Let's assert that x and y should be equal
adze()
.assert(x === y)
.log('X does not equal Y');
// This log will not print because the assertion passes
adze()
.assert(x === 2)
.log('X does not equal 2');
// Let's look at the output with emoji's enabled
adze({ useEmoji: true })
.assert(x === y)
.log('X does not equal Y');
# Output
# count
The count modifier tells the log to increment a counter associated to the log's label.
# Interface
class BaseLog {
public get count(): this;
}
# Example
import { adze, createShed } from 'adze';
// A shed is required for labels and modifiers that depend on them
createShed();
for (let i = 0; i < 5; i += 1) {
adze().label('my-counter').count.log('Counting iterations.');
}
# Output
# countClear
The countClear modifier completely clears the count from a label. Rather than setting the count to 0 it instead becomes null.
NOTE: This method is deliberately a modifier rather than a terminator because it forces you to write a log that gives you insight into when a counter was cleared. It also makes the countClear log recallable from a bundle or the Shed in the order it was created.
This is not a standard API.
# Interface
class BaseLog {
public get countClear(): this;
}
# Example
import { adze, createShed } from 'adze';
// A shed is required for labels and modifiers that depend on them
createShed();
for (let i = 0; i < 4; i += 1) {
adze().label('my-counter').count.log('Counting iterations.');
}
adze().label('my-counter').countClear.log('Clearing the counter.');
adze().label('my-counter').log('A log with the my-counter label but no count.');
# Output
# countReset
The countReset modifier resets the counter associated to the log's label to 0.
NOTE: This method is deliberately a modifier rather than a terminator because it forces you to write a log that gives you insight into when a counter was reset. It also makes the countReset log recallable from a bundle or the Shed in the order it was created.
# Interface
class BaseLog {
public get countReset(): this;
}
# Example
import { adze, createShed } from 'adze';
// A shed is required for labels and modifiers that depend on them
createShed();
for (let i = 0; i < 4; i += 1) {
adze().label('my-counter').count.log('Counting iterations.');
}
adze().label('my-counter').countReset.log('Resetting the counter.');
for (let i = 0; i < 4; i += 1) {
adze().label('my-counter').count.log('Counting iterations again.');
}
# Output
# dir
The dir modifier transforms the output of the log by directing it to use the console.dir()
method for printing purposes only.
NOTE: Logs that use dir
as a modifier should only be given a single argument which is usually an object. If multiple arguments are given, behavior may differ between browser and node environments. Refer to the MDN docs for more details.
# Interface
class BaseLog {
public get dir(): this;
}
# Example
import { adze } from 'adze';
adze().dir.log({ foo: 'bar' });
# Output
# dirxml
The dirxml modifier transforms the output of the log by directing it to use the console.dirxml()
method for printing purposes only. This is mainly useful for logging out DOM elements.
NOTE: Logs that use dirxml
as a modifier should only be given a single argument which is usually a DOM Element or other XML object. If multiple arguments are given, behavior may differ between browser and node environments. Refer to the MDN docs for more details.
# Interface
class BaseLog {
public get dirxml(): this;
}
# Example
import { adze } from 'adze';
// create a new div element
const newDiv = document.createElement('div');
newDiv.setAttribute('id', 'test');
// and give it some content
const newContent = document.createTextNode('Hi there and greetings!');
// add the text node to the newly created div
newDiv.appendChild(newContent);
adze().dirxml.log(newDiv);
# Output
# dump
This modifier instructs the labeled log to print the context values from a thread.
Refer to the Mapped Diagnostic Context (MDC) page for more information about the purpose of MDC.
This modifier is dependent upon having a label and a Shed.
This is not a standard API.
# Interface
class BaseLog {
public get dump(): this;
}
# Example
import { adze, createShed } from 'adze';
const shed = createShed();
// Creating a shed listener is a great way to get meta data from your
// threaded logs to write to disk or pass to another plugin, library,
// or service.
shed.addListener([1, 2, 3, 4, 5, 6, 7, 8], (log) => {
// Do something with `log.context.added` or `log.context.subtracted`.
});
function add(a, b) {
const answer = a + b;
adze().label('foo').thread('added', { a, b, answer });
return answer;
}
function subtract(x, y) {
const answer = x - y;
adze().label('foo').thread('subtracted', { x, y, answer });
return answer;
}
add(1, 2);
subtract(4, 3);
adze().label('foo').dump.info('Results from our thread');
# Output
# group
The group modifier starts an uncollapsed group of logs. This means that all subsequent logs will be nested beneath this log until a groupEnd log occurs.
# Interface
class BaseLog {
public get group(): this;
}
# Example
import { adze } from 'adze';
// Some info about our app.
const version = 'v1.0.0';
const browser = 'firefox';
adze().group.info('App Information');
adze().info(`Version: ${version}`);
adze().info(`Browser: ${browser}`);
adze().groupEnd.info();
# Output
# groupCollapsed
The groupCollapsed modifier starts an collapsed group of logs. This means that all subsequent logs will be nested beneath this log until a groupEnd log occurs.
Note: This will not be collapsed in a terminal environment since there is no way to uncollapse it.
# Interface
class BaseLog {
public get groupCollapsed(): this;
}
# Example
import { adze } from 'adze';
// Some info about our app.
const version = 'v1.0.0';
const browser = 'firefox';
adze().groupCollapsed.info('App Information');
adze().info(`Version: ${version}`);
adze().info(`Browser: ${browser}`);
adze().groupEnd.info();
# Output
# groupEnd
The groupEnd modifier ends a log group. Any logs following a groupEnd will no longer be grouped.
# Interface
class BaseLog {
public get groupEnd(): this;
}
# Example
import { adze } from 'adze';
// Some info about our app.
const version = 'v1.0.0';
const browser = 'firefox';
adze().group.info('App Information');
adze().info(`Version: ${version}`);
adze().info(`Browser: ${browser}`);
adze().groupEnd.info(); // <-- Ends the group
adze().info('Some other information...');
# Output
# label
Applies an identifying label to a log. If a Shed is present, all logs that share the same label will be linked together behind the scenes. This enables global tracking for modifiers that require a label as a prerequisite.
These are the modifiers that require a label and a Shed to be useful:
This is not a standard API.
# Interface
class BaseLog {
public label(name: string): this;
}
# Example
import { adze, createShed } from 'adze';
createShed();
// Labels can be applied in any order in a modifier chain
adze().count.label('foo').log('Bar');
adze().label('foo').count.log('Foo');
# Output
# meta
The meta modifier allows you to attach meta data to your log instance. You can then retrieve it at a later time from within a log listener or by calling the data()
method on a log instance.
This is not a standard API.
# Interface
The interface of
meta<KV extends [string, any]>(...[key, val]: KV): this;
is available for Adze versions >= 1.2.0
class BaseLog {
// Types are Overloaded
public meta<T>(key: string, val: T): this;
public meta<KV extends [string, any]>(...[key, val]: KV): this;
}
# Example
import { adze, createShed } from 'adze';
// Let's optionally create a shed to show the use of meta data on listeners
const shed = createShed();
// We'll listen only to logs of level 6 which is "log"
shed.addListener([6], (data) => {
adze().info("My log's meta data!", data.meta);
});
// Let's create a super important message to attach as meta data
const info = 'Hello World!';
adze().meta('message', info).log('This log contains an important message.');
import { adze, createShed } from 'adze';
// Let's optionally create a shed to show the use of meta data on listeners
const shed = createShed();
// We'll listen only to logs of level 6 which is "log"
shed.addListener([6], (data) => {
adze().info("My log's meta data!", data.meta);
});
// Let's create a super important message to attach as meta data
const info = 'Hello World!';
adze().meta('message', info).log('This log contains an important message.');
# Output
# namespace / ns
This modifier adds one or more namespaces to a log. Multiple calls to the namespace modifier are additive by nature
and will not overwrite previously applied namespaces. These are mainly used as human readable group identifiers but are
also useful for filtering recalled logs and for identifying logs from a log listener. This modifier does not do any
special grouping under the hood. The ns()
method is just a shorter alias for namespace()
.
As of version 1.7.0, Adze now supports passing a Constraints type to the log factory that will allow you to centrally specify what namespaces are allowed to be used. This is beneficial because it will force users to add any new namespace that they might want to add to the central allowedNamespaces
type property. This will make it easier to filter namespaces throughout your application because you will only have a single place to look to understand what namespaces are being used.
Rest-of operator for namespace/ns available in Adze >= v1.5.0
Namespace constraint type available in Adze >= 1.7.0
Namespaces became additive by nature in Adze >= 1.8.0
This is not a standard API.
# Interface
class BaseLog {
public namespace(ns: string | string[]): this;
public ns(ns: string | string[]): this;
// Or alternatively with the restof operator (versions >= 1.5.0)
public namespace(...ns: string[]): this;
public ns(...ns: string[]): this;
}
# Example
import { adze } from 'adze';
adze().namespace('tix-123').log('Important info for a feature.');
adze()
.namespace(['tix-123', 'tix-456'])
.log('Important info for multiple features.');
adze()
.namespace('tix-123', 'tix-456', 'tix-789')
.log('Multiple namespace entry simplified by the restof operator.');
// ns() is a shorthand alias for namespace()
adze().ns('tix-456').log('More info');
// Multiple calls to namespace/ns are additive
adze().ns('foo', 'bar').ns('baz').log('This log has all applied namespaces.');
//----- Example with TS Constraints -----//
import adze, { Constraints } from 'adze';
// First we will create our app constraints by extending the Constraint interface
interface MyAppConstraints extends Constraints {
allowedNamespaces: 'foo' | 'bar' | 'hello' | 'world';
}
// Now we apply the constraints to our app's logger factory
const logger = adze<MyAppConstraints>().seal();
// Now when we define namespaces for a log a type error will be thrown if the
// namespace provided isn't in the allowedNamespaces union type.
logger().ns('foo', 'bar', 'baz').fail('This is not allowed.');
// ^^^^^
// Argument of type '"baz"' is not assignable to parameter of type '"foo" | "bar" | "hello" | "world"'.
# Output
# silent
The silent modifier allows a log to be terminated and cached but prevents it from printing to the console. This can be useful for providing a log to a log listener that you do not want to have printed.
This is not a standard API.
# Interface
class BaseLog {
public get silent(): this;
}
# Example
import { adze } from 'adze';
adze().log('Hello World!');
adze().silent.log('Crickets...');
adze().log('I guess nobody is home :(');
# Output
# table
The table modifier transforms the output of the log by directing it to use the console.table()
method for printing purposes only.
# Interface
class BaseLog {
public get table(): this;
}
# Example
import { adze } from 'adze';
const tabular_data = [
{ firstName: 'Andrew', lastName: 'Stacy' },
{ firstName: 'Jim', lastName: 'Bob' },
];
adze().table.log(tabular_data);
# Output
# test
This modifier accepts a boolean expression and will only print if the boolean expression passes (is a truthy value).
This is not a standard API.
# Interface
class BaseLog {
public test(expression: boolean): this;
}
# Example
import { adze } from 'adze';
const x = 2;
const y = 3;
// Let's test that x equals 2
adze()
.test(x === 2)
.log('X equals 2');
// This log will not print because the test fails
adze()
.test(x === y)
.log('X does not equal Y');
// Let's look at the output with emoji's enabled
adze({ useEmoji: true })
.test(y === 3)
.log('Y equals 3');
# Output
# time
This modifier starts a timer associated to the log's label. This is useful for taking performance measurements. A log with a time modifier must be followed by a log with a timeEnd modifier in order to get the final measurement.
This modifier is dependent upon having a label and a Shed.
# Interface
class BaseLog {
public get time(): this;
}
# Example
import { adze, createShed } from 'adze';
createShed();
// Let's create a timer for performance
adze().label('loop').time.log('Starting a timer.');
for (let i = 0; i < 10000; i += 1) {
// Do a lot of stuff that takes time
}
// End the timer to get the loop performance
adze().label('loop').timeEnd.log('Performance of our loop.');
// Let's see the output with emoji's
adze({ useEmoji: true }).label('loop').timeEnd.log('Performance of our loop.');
# Output
# timeEnd
This modifier ends a timer associated to the log's label. This is useful for taking performance measurements. A log with a timeEnd modifier must be preceded by a log with a time modifier in order to get the final measurement.
This modifier is dependent upon having a label and a Shed.
# Interface
class BaseLog {
public get time(): this;
}
# Example
import { adze, createShed } from 'adze';
createShed();
// Let's create a timer for performance
adze().label('loop').time.log('Starting a timer.');
for (let i = 0; i < 10000; i += 1) {
// Do a lot of stuff that takes time
}
// End the timer to get the loop performance
adze().label('loop').timeEnd.log('Performance of our loop.');
// Let's see the output with emoji's
adze({ useEmoji: true }).label('loop').timeEnd.log('Performance of our loop.');
# Output
# timeNow
This modifier logs the time ellapsed since the page has loaded. This is useful for measuring page load performance rather than performance of a particular piece of code. This modifier is not dependent upon a label or Shed.
This is not a standard API.
# Interface
class BaseLog {
public get timeNow(): this;
}
# Example
import { adze } from 'adze';
for (let i = 0; i < 10000; i += 1) {
// Do a lot of stuff that takes time
}
// Let's create a timer for performance
adze().timeNow.log('Recording the time ellapsed since page load.');
// Let's see what it looks like with emoji's enabled.
adze({ useEmoji: true }).timeNow.log(
'Recording the time ellapsed since page load.'
);
# Output
# timestamp
This modifier instructs the log to render an ISO 8601 (opens new window) timestamp.
This is not a standard API.
Version >= 1.1
# Interface
class BaseLog {
public get timestamp(): this;
}
# Example
import { adze } from 'adze';
adze().label('timestamped').timestamp.log('This log has a timestamp.');
# Output
# trace
This modifier instructs the log to print a stacktrace using the standard console.trace()
method.
NOTE: The styling for logs using this modifier varies by browser. Chrome will render the log message with proper styling while Firefox will only render the message unstyled.
# Interface
class BaseLog {
public get trace(): this;
}
# Example
import { adze } from 'adze';
adze().trace.log('Trying to find an issue...');