We've all had occasions where we've felt the need to simply pipe a tap(console.log)
to our Observables to get some insight into what is occuring at a certain time.
This operator aims to reduce the amount of typing you'll have to do!
Install the package:
npm install rxjs-debug-operator
It's super simple to add and use:
Use your prefered import method:
import { debug } from 'rxjs-debug-operator';
// OR
const { debug } = require('rxjs-debug-operator');
Then pipe it to your Observables:
const obs$ = source.pipe(debug());
You can add a label to help identify the Observable:
const obs$ = source.pipe(debug('My Observable'));
// OUTPUT
// My Observable {value}
It even allows you to turn it off if you are in a production environment, or for any other reason you wouldn't want to log to the console:
const obs$ = source.pipe(debug({ shouldIgnore: true }));
We can use it on its own to simply log out values to the console
const obs$ = of('my test value');
obs$.pipe(debug()).subscribe();
// OUTPUT:
// my test value
We can add a label to the logs:
const obs$ = of('my test value');
obs$.pipe(debug('Obserable A')).subscribe();
// OUTPUT:
// Obserable A my test value
// We can label it using the config object syntax:
const obs$ = of('my test value');
obs$.pipe(debug({ label: 'Obserable A' })).subscribe();
// OUTPUT:
// Obserable A my test value
// However, if we add a label and custom notification handlers,
// we will not get the label in the logs by default:
const obs$ = of('my test value');
obs$
.pipe(
debug({
label: 'Obserable A',
next: (value) => console.log(value),
})
)
.subscribe();
// OUTPUT:
// my test value
We can also set up our own notification handlers if we prefer:
const obs$ = of('my test value');
obs$
.pipe(debug({ next: (value) => console.log('my custom handler:', value) }))
.subscribe();
// OUTPUT:
// my custom handler: my test value
const obs$ = throwError('uh oh');
obs$
.pipe(debug({ error: (value) => console.log('my error handler:', value) }))
.subscribe();
// OUTPUT:
// my error handler: uh oh
const obs$ = of('my test value');
obs$
.pipe(debug({ complete: (value) => console.log('I completed') }))
.subscribe();
// OUTPUT:
// I completed
We can access the default logger for more flexibility:
const obs$ = of('my test value');
obs$
.pipe(
debug((logger) => ({
next: (v) => logger.warn('Warning!', v),
}))
)
.subscribe();
// OUTPUT
// WARN: Warning! my test value
You can set some globals that make it more convenient to change:
- the default logger
- a global prefix to be appended to all logs
- a global-level ignore flag
You can change the default logger by creating an object that matches the DebugLogger
interface, which can be seen below:
export interface DebugLogger {
log: (...args: unknown[]) => void;
error: (...args: unknown[]) => void;
warn?: (...args: unknown[]) => void;
debug?: (...args: unknown[]) => void;
info?: (...args: unknown[]) => void;
}
Once you have created your new logger, you can set it to be used as the default logger using setGlobalDebugConfig()
setGlobalDebugConfig({
logger: myNewLogger,
});
Now all your debug()
operators will use your new logger to log the values it receives.
You can also add a string prefix to all your logs at a global level, which can be useful to help identify logs.
setGlobalDebugConfig({
prefix: 'My Prefix',
});
You can also set whether all debug()
should not log at the global level. This can be useful for turning it off in production environments.
setGlobalDebugConfig({
shouldIgnore: isProduction,
});
import { DebugLogger, setGlobalDebugConfig } from 'rxjs-debug-operator';
const winston = require('winston');
const sysLogger = winston.createLogger({
level: 'info',
format: winston.format.json(),
transports: [
//
// - Write all logs with level `error` and below to `error.log`
// - Write all logs with level `info` and below to `combined.log`
//
new winston.transports.File({ filename: 'error.log', level: 'error' }),
new winston.transports.File({ filename: 'combined.log' }),
],
});
const debugLogger: DebugLogger = {
log: (v) => sysLogger.info(v),
error: (e) => sysLogger.error(e),
};
setGlobalDebugConfig({ logger: debugLogger });
const obs$ = of('my test value');
obs$.pipe(debug()).subscribe();
// OUTPUT
// 'my test value' written to `combined.log`
It should be noted that local config options passed to the debug()
operator will take precedence over any global values
debug(config?: Partial<DebugOperatorConfig>)
See the list of options available to configure the operator below
Option | Description | Type | Default |
---|---|---|---|
shouldIgnore |
Do not perform the Debug actions | boolean |
false |
label |
Add a label to the logs to help identify the Observable | string |
null |
next |
Action to perform when Observer receives a Next notification | (value: T) => void |
console.log |
error |
Action to perform when Observer receives an Error notification | (value: unknown) => void |
console.error |
complete |
Action to perform when Observer receives a Completion notification | () => void |
() => null |
setGlobalDebugConfig(config: Partial<GlobalDebugConfig>)
Option | Description | Type | Default |
---|---|---|---|
shouldIgnore |
Do not perform the Debug actions | boolean |
false |
prefix |
Add a label to the logs to help identify the Observable | string |
null |
logger |
Logger to use to log values recieved by debug() |
DebugLogger |
console |
Option | Description | Type | Default |
---|---|---|---|
log |
Basic log | (...args: unknown[]) => void |
console.log |
error |
Error log | (...args: unknown[]) => void |
console.error |
info? |
Info log | (...args: unknown[]) => void |
console.info |
warn? |
Warn log | (...args: unknown[]) => void |
console.warn |
debug? |
Debug log | (...args: unknown[]) => void |
console.debug |