279 lines
8.8 KiB
Markdown
279 lines
8.8 KiB
Markdown
# Browser API
|
||
|
||
Pino is compatible with [`browserify`](https://npm.im/browserify) for browser-side usage:
|
||
|
||
This can be useful with isomorphic/universal JavaScript code.
|
||
|
||
By default, in the browser,
|
||
`pino` uses corresponding [Log4j](https://en.wikipedia.org/wiki/Log4j) `console` methods (`console.error`, `console.warn`, `console.info`, `console.debug`, `console.trace`) and uses `console.error` for any `fatal` level logs.
|
||
|
||
## Options
|
||
|
||
Pino can be passed a `browser` object in the options object,
|
||
which can have the following properties:
|
||
|
||
### `asObject` (Boolean)
|
||
|
||
```js
|
||
const pino = require('pino')({browser: {asObject: true}})
|
||
```
|
||
|
||
The `asObject` option will create a pino-like log object instead of
|
||
passing all arguments to a console method, for instance:
|
||
|
||
```js
|
||
pino.info('hi') // creates and logs {msg: 'hi', level: 30, time: <ts>}
|
||
```
|
||
|
||
When `write` is set, `asObject` will always be `true`.
|
||
|
||
### `asObjectBindingsOnly` (Boolean)
|
||
|
||
```js
|
||
const pino = require('pino')({browser: {asObjectBindingsOnly: true}})
|
||
```
|
||
|
||
The `asObjectBindingsOnly` option is similar to `asObject` but will keep the message
|
||
and arguments unformatted. This allows to defer formatting the message to the
|
||
actual call to `console` methods, where browsers then have richer formatting in
|
||
their devtools than when pino will format the message to a string first.
|
||
|
||
```js
|
||
pino.info('hello %s', 'world') // creates and logs {level: 30, time: <ts>}, 'hello %s', 'world'
|
||
```
|
||
|
||
### `formatters` (Object)
|
||
|
||
An object containing functions for formatting the shape of the log lines. When provided, it enables the logger to produce a pino-like log object with customized formatting. Currently, it supports formatting for the `level` object only.
|
||
|
||
##### `level`
|
||
|
||
Changes the shape of the log level. The default shape is `{ level: number }`.
|
||
The function takes two arguments, the label of the level (e.g. `'info'`)
|
||
and the numeric value (e.g. `30`).
|
||
|
||
```js
|
||
const formatters = {
|
||
level (label, number) {
|
||
return { level: number }
|
||
}
|
||
}
|
||
```
|
||
|
||
|
||
### `reportCaller` (Boolean)
|
||
|
||
Attempts to capture and include the originating callsite (file:line:column) for each log call in the browser logger.
|
||
|
||
- When used together with `asObject` (or when `formatters` are provided), the callsite is added as a `caller` string property on the emitted log object.
|
||
- In the default mode (non‑object), the callsite string is appended as the last argument passed to the corresponding `console` method. This makes the location visible in the console output even though the console’s clickable header still points to Pino internals.
|
||
|
||
```js
|
||
// Object mode: adds `caller` to the log object
|
||
const pino = require('pino')({
|
||
browser: {
|
||
asObject: true,
|
||
reportCaller: true
|
||
}
|
||
})
|
||
|
||
pino.info('hello')
|
||
// -> { level: 30, msg: 'hello', time: <ts>, caller: '/path/to/file.js:10:15' }
|
||
|
||
// Default mode: appends the caller string as the last console argument
|
||
const pino2 = require('pino')({
|
||
browser: {
|
||
reportCaller: true
|
||
}
|
||
})
|
||
|
||
pino2.info('hello')
|
||
// -> console receives: 'hello', '/path/to/file.js:10:15'
|
||
```
|
||
|
||
Notes:
|
||
|
||
- This is a best‑effort feature that parses the JavaScript Error stack. Stack formats vary across engines.
|
||
- The clickable link shown by devtools for a console message is determined by where `console.*` is invoked and cannot be changed by libraries; `reportCaller` surfaces the user callsite alongside the log message.
|
||
|
||
|
||
### `write` (Function | Object)
|
||
|
||
Instead of passing log messages to `console.log` they can be passed to
|
||
a supplied function.
|
||
|
||
If `write` is set to a single function, all logging objects are passed
|
||
to this function.
|
||
|
||
```js
|
||
const pino = require('pino')({
|
||
browser: {
|
||
write: (o) => {
|
||
// do something with o
|
||
}
|
||
}
|
||
})
|
||
```
|
||
|
||
If `write` is an object, it can have methods that correspond to the
|
||
levels. When a message is logged at a given level, the corresponding
|
||
method is called. If a method isn't present, the logging falls back
|
||
to using the `console`.
|
||
|
||
|
||
```js
|
||
const pino = require('pino')({
|
||
browser: {
|
||
write: {
|
||
info: function (o) {
|
||
//process info log object
|
||
},
|
||
error: function (o) {
|
||
//process error log object
|
||
}
|
||
}
|
||
}
|
||
})
|
||
```
|
||
|
||
### `serialize`: (Boolean | Array)
|
||
|
||
The serializers provided to `pino` are ignored by default in the browser, including
|
||
the standard serializers provided with Pino. Since the default destination for log
|
||
messages is the console, values such as `Error` objects are enhanced for inspection,
|
||
which they otherwise wouldn't be if the Error serializer was enabled.
|
||
|
||
We can turn all serializers on,
|
||
|
||
```js
|
||
const pino = require('pino')({
|
||
browser: {
|
||
serialize: true
|
||
}
|
||
})
|
||
```
|
||
|
||
Or we can selectively enable them via an array:
|
||
|
||
```js
|
||
const pino = require('pino')({
|
||
serializers: {
|
||
custom: myCustomSerializer,
|
||
another: anotherSerializer
|
||
},
|
||
browser: {
|
||
serialize: ['custom']
|
||
}
|
||
})
|
||
// following will apply myCustomSerializer to the custom property,
|
||
// but will not apply anotherSerializer to another key
|
||
pino.info({custom: 'a', another: 'b'})
|
||
```
|
||
|
||
When `serialize` is `true` the standard error serializer is also enabled (see https://github.com/pinojs/pino/blob/master/docs/api.md#stdSerializers).
|
||
This is a global serializer, which will apply to any `Error` objects passed to the logger methods.
|
||
|
||
If `serialize` is an array the standard error serializer is also automatically enabled, it can
|
||
be explicitly disabled by including a string in the serialize array: `!stdSerializers.err`, like so:
|
||
|
||
```js
|
||
const pino = require('pino')({
|
||
serializers: {
|
||
custom: myCustomSerializer,
|
||
another: anotherSerializer
|
||
},
|
||
browser: {
|
||
serialize: ['!stdSerializers.err', 'custom'] //will not serialize Errors, will serialize `custom` keys
|
||
}
|
||
})
|
||
```
|
||
|
||
The `serialize` array also applies to any child logger serializers (see https://github.com/pinojs/pino/blob/master/docs/api.md#discussion-2
|
||
for how to set child-bound serializers).
|
||
|
||
Unlike server pino the serializers apply to every object passed to the logger method,
|
||
if the `asObject` option is `true`, this results in the serializers applying to the
|
||
first object (as in server pino).
|
||
|
||
For more info on serializers see https://github.com/pinojs/pino/blob/master/docs/api.md#mergingobject.
|
||
|
||
### `transmit` (Object)
|
||
|
||
An object with `send` and `level` properties.
|
||
|
||
The `transmit.level` property specifies the minimum level (inclusive) of when the `send` function
|
||
should be called, if not supplied the `send` function be called based on the main logging `level`
|
||
(set via `options.level`, defaulting to `info`).
|
||
|
||
The `transmit` object must have a `send` function which will be called after
|
||
writing the log message. The `send` function is passed the level of the log
|
||
message and a `logEvent` object.
|
||
|
||
The `logEvent` object is a data structure representing a log message, it represents
|
||
the arguments passed to a logger statement, the level
|
||
at which they were logged, and the hierarchy of child bindings.
|
||
|
||
The `logEvent` format is structured like so:
|
||
|
||
```js
|
||
{
|
||
ts = Number,
|
||
messages = Array,
|
||
bindings = Array,
|
||
level: { label = String, value = Number}
|
||
}
|
||
```
|
||
|
||
The `ts` property is a Unix epoch timestamp in milliseconds, the time is taken from the moment the
|
||
logger method is called.
|
||
|
||
The `messages` array is all arguments passed to logger method, (for instance `logger.info('a', 'b', 'c')`
|
||
would result in `messages` array `['a', 'b', 'c']`).
|
||
|
||
The `bindings` array represents each child logger (if any), and the relevant bindings.
|
||
For instance, given `logger.child({a: 1}).child({b: 2}).info({c: 3})`, the bindings array
|
||
would hold `[{a: 1}, {b: 2}]` and the `messages` array would be `[{c: 3}]`. The `bindings`
|
||
are ordered according to their position in the child logger hierarchy, with the lowest index
|
||
being the top of the hierarchy.
|
||
|
||
By default, serializers are not applied to log output in the browser, but they will *always* be
|
||
applied to `messages` and `bindings` in the `logEvent` object. This allows us to ensure a consistent
|
||
format for all values between server and client.
|
||
|
||
The `level` holds the label (for instance `info`), and the corresponding numerical value
|
||
(for instance `30`). This could be important in cases where client-side level values and
|
||
labels differ from server-side.
|
||
|
||
The point of the `send` function is to remotely record log messages:
|
||
|
||
```js
|
||
const pino = require('pino')({
|
||
browser: {
|
||
transmit: {
|
||
level: 'warn',
|
||
send: function (level, logEvent) {
|
||
if (level === 'warn') {
|
||
// maybe send the logEvent to a separate endpoint
|
||
// or maybe analyze the messages further before sending
|
||
}
|
||
// we could also use the `logEvent.level.value` property to determine
|
||
// numerical value
|
||
if (logEvent.level.value >= 50) { // covers error and fatal
|
||
|
||
// send the logEvent somewhere
|
||
}
|
||
}
|
||
}
|
||
}
|
||
})
|
||
```
|
||
|
||
### `disabled` (Boolean)
|
||
|
||
```js
|
||
const pino = require('pino')({browser: {disabled: true}})
|
||
```
|
||
|
||
The `disabled` option will disable logging in browser if set
|
||
to `true`, by default it is set to `false`.
|