Files

208 lines
6.8 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Logger
Detox Logger API allows you to save your custom messages and events alongside the built-in ones.
In addition to being formatted and printed to the console, they can be preserved as log artifacts if you enable them via [`--record-logs`] CLI option or [`artifacts.plugins.log.enabled`] in the config:
- `<artifacts-location>/detox.log` – plain text log;
- `<artifacts-location>/detox.trace.json` – [Trace Event format] file, viewable via [Perfetto] or `chrome://tracing`.
![](../img/log-example.png)
Below we’ll be listing all the public properties and methods of the logger.
## Properties
### `log.level` \[enum]
**Read-only.** Returns the current [log level](../config/logger.mdx#loggerlevel-enum), one of values:
`fatal`, `error`, `warn`, `info`, `debug`, `trace`.
## Methods
### `log.*([event,] ...msg)`
Logs an instant message with an optional [event metadata].
There are six methods for producing log messages varying by log level:
* `log.fatal([event,] ...msg)`
* `log.error([event,] ...msg)`
* `log.warn([event,] ...msg)`
* `log.info([event,] ...msg)`
* `log.debug([event,] ...msg)`
* `log.trace([event,] ...msg)`
Example:
```js
const { log } = require('detox');
log.info('Some message');
// detox[2020] i Some message
log.error({ err: new Error('Test') }, 'An error message');
// detox[2020] i An error message
// err: Test
```
### `log.*.begin([event,] msg)`
Logs a beginning of a _duration event_ with an optional [event metadata].
Duration events are displayed as continuous colorful segments on the timeline and can be stacked if you
call the method multiple times, e.g.:
```js
log.info.begin({ data: { email } }, 'Login Flow');
// detox[2020] B Login Flow
// data: { email: '[email protected]' }
log.info.begin('Nested sub-flow');
// detox[2020] B Nested sub-flow
```
Make sure you always end your events so that they don't get marked as unfinished, like shown on the screenshot below:
![](../img/timeline-artifact-unfinished.png)
### `log.*.end([event, msg])`
Logs an end of a duration event with an optional [event metadata] and a message. If the message is omitted,
the logger prints the corresponding message from the duration begin event:
```js
log.info.end();
// detox[2020] E Nested sub-flow
log.info.end({ success: true }, 'Login Flow (custom end message)');
// detox[2020] E Login Flow (custom end message)
```
### `log.*.complete([event,] msg, functionOrPromise)`
A convenience method to wrap functions and promises with [`log.*.begin`] and [`log.*.end`], e.g.:
```js
await log.info.complete('Login Flow', async () => {
// …
});
// detox[2020] B Login Flow
// detox[2020] E Login Flow
```
As a bonus, this wrapper also adds `{ success: true }` or `{ success: false, error }` metadata to
the end event.
Effectively, `begin` and `end` can even be called in two complete different places - such as `beforeEach` and `afterEach`, but that is discouraged.
In fact, `log.*.complete()` is the recommended way of tracing things, e.g.:
## Event metadata
All the log methods accept an optional first argument which can contain some custom
metadata: numbers, strings and booleans:
```js
detox.log.info({ /* metadata */ }, message);
detox.log.trace.begin({ /* metadata */ }, message);
detox.log.trace.end({ /* metadata */ });
```
Aside from custom user properties, there are a few meaningful properties that affect the timeline representation.
### `id` \[string \| number]
Use arbitrary IDs when you have a risk of overlapping concurrent events, e.g.:
```js
await Promise.all([
await detox.log.complete({ id: 1 }, 'Do this', async () => { /* … */ }),
await detox.log.complete({ id: 2 }, 'Do that', async () => { /* … */ }),
]);
```
Using IDs will prevent situations like this, where the nested event outlasts its parent:
```plain text
B E
|-- event 1 ----|
B E
|-- event 2 -----|
```
In the example above, the actual sequence of calls will be:
```js
log.info.begin('event 1');
log.info.begin('event 2');
log.info.end(); // from event 1
log.info.end(); // from event 2
```
Therefore, it will be interpreted erroneously on the timeline, as if the second event has ended before the first one:
```plain text
B E
|-- event 1 --------|
B E
|-- event 2 -|
```
When you begin an event with a specific `id` while there's already some other duration event, the logger allocates another "lane" for that event by assigning a distinct `tid` (thread ID) to it:
![](../img/timeline-tid.png)
### `cat` \[string \| string\[]]
Event category. Helpful for filtering specific events.
Pass either a string of comma-separated values or a string array, e.g.:
```js
log.info({ cat: 'login,login-email' }, 'Starting e-mail login flow...');
// is identical to:
log.info({ cat: ['login', 'login-email'] }, 'Starting e-mail login flow...');
```
### `cname` \[string]
Custom event color. See the available color names [here](https://github.com/catapult-project/catapult/blob/main/tracing/tracing/base/color_scheme.html).
### `*` \[string \| number \| boolean]
Your custom properties, e.g.:
```js
detox.log.info({ login: '[email protected]' }, 'Entering credentials...');
```
Custom properties are not printed to the terminal logs, but there are a few reserved names which have
an extra formatting due to our default [`logger.options.stringifiers`] — these are: `args`, `data`, `error`, `stack`, `origin`.
Also, there are a few reserved properties which cannot be logged:
- `pid` — process ID,
- `tid` — thread ID,
- `ts` — timestamp,
- `ph` — phase: _begin_ (B), _end_ (E), _instant_ (i) event.
## Artifacts
The logger subsystem produces two artifacts when [`--record-logs`] CLI option is enabled or [`artifacts.plugins.log.enabled`] config is set to true.
### `detox.log`
This file contains all the log messages you could see in the terminal window, except that there are messages of all the log levels, from `fatal` to `trace`.
### `detox.trace.json`
JSON file, which, if loaded into [Perfetto] or `chrome://tracing` (internal address in Google Chrome browser), would look something like this:
![Timeline artifact example](../img/timeline-artifact.png)
The tracing view provides a visual, hierarchical representation of the various processes that took place during the execution of the testing session, over the execution’s _time-line_. These processes appear as hierarchical _sections_ – sometimes visually ordered in a parent-child way, depending on their formation time and context.
[`log.*.begin`]: #logbeginevent-msg
[`log.*.end`]: #logendevent-msg
[`logger.options.stringifiers`]: ../config/logger.mdx#loggeroptions-bunyandebugstreamoptions
[`--record-logs`]: ../cli/test.md
[`artifacts.plugins.log.enabled`]: ../config/artifacts.mdx#example
[Trace Event format]: https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview
[Perfetto]: https://ui.perfetto.dev
[Event metadata]: #event-metadata