Skip to content

Commit

Permalink
Feat: Enable configuring default remove paths
Browse files Browse the repository at this point in the history
Also corrected `ExtendedRedact` definition as `removePaths` should only
have been on the pino `redactOptions` type.
  • Loading branch information
ConradLang committed Sep 20, 2023
1 parent 91a9f13 commit 8bcb486
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 30 deletions.
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,24 @@ const logger = createLogger({
});
```

#### Removal of Default Properties

The library will remove a set of default properties.
To bypass this, set `ignoreDefaultRemovePaths` to `true` on the `redact` options.

Example:

```typescript
const logger = createLogger({
name: 'my-app',
redact: {
paths: ['req.headers["x-redact-this"]'],
removePaths: ['req.headers["x-remove-this"]'],
ignoreDefaultRemovePaths: true,
},
});
```

### Trimming

The following trimming rules apply to all logging data:
Expand Down
68 changes: 51 additions & 17 deletions src/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import split from 'split2';

import { defaultRemovePaths } from './redact';

import createLogger, { type LoggerOptions } from '.';

const bearerToken =
Expand Down Expand Up @@ -472,35 +474,67 @@ testLog(
['req.headers.x-remove-me'],
);

const buildObjectFromPath = (path: string): Record<string, unknown> =>
path
.split(/[.\[]/)
.reverse()
.reduce(
(previous, current) => {
const key = current.replace(/["\[\]]/g, '');
if (!previous) {
return { [key]: 'Default path property' };
}

return { [key]: previous };
},
undefined as unknown as Record<string, unknown>,
);

const buildObjectFromDefaultRemovePaths = (): Record<string, unknown> =>
!defaultRemovePaths?.[0] ? {} : buildObjectFromPath(defaultRemovePaths[0]);

testLog(
'should redact or remove specified paths where property names contain dots',
'should remove default paths when ignoreDefaultRemovePaths is missing',
{
msg: 'allowed',
data: {
top: {
prop1: 'Should be redacted',
prop2: 'Should be removed',
},
['top.prop1']: 'Should be removed',
['top.prop2']: 'Should be redacted',
},
redact: 'Should be redacted',
remove: 'Should be removed',
...buildObjectFromDefaultRemovePaths(),
},
{
msg: 'allowed',
data: {
top: { prop1: '[Redacted]' },
['top.prop2']: '[Redacted]',
redact: '[Redacted]',
},
'info',
{
maxObjectDepth: 20,
redact: {
paths: ['redact'],
removePaths: ['remove'],
},
},
['remove', ...defaultRemovePaths],
);

testLog(
'should not remove default paths when ignoreDefaultRemovePaths is true',
{
redact: 'Should be redacted',
remove: 'Should be removed',
...buildObjectFromDefaultRemovePaths(),
},
{
redact: '[Redacted]',
...buildObjectFromDefaultRemovePaths(),
},
'info',
{
maxObjectDepth: 20,
redact: {
paths: ['data.top.prop1', 'data["top.prop2"]'],
removePaths: ['data.top.prop2', 'data["top.prop1"]'],
paths: ['redact'],
removePaths: ['remove'],
ignoreDefaultRemovePaths: true,
},
},
['data.top.prop2', ['data', 'top.prop1']],
['remove'],
);

testLog(
Expand Down
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import serializers from './serializers';
export { pino };

export type LoggerOptions = Omit<pino.LoggerOptions, 'redact'> &
FormatterOptions & { redact?: redact.ExtendedRedactOptions };
FormatterOptions & { redact?: redact.ExtendedRedact };
export type Logger = pino.Logger;

/**
Expand Down
40 changes: 28 additions & 12 deletions src/redact/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,42 @@ import type * as pino from 'pino';
// TODO: Redact cookies?
export const defaultRedact = [];

export type ExtendedRedactOptions = pino.LoggerOptions['redact'] & {
export const defaultRemovePaths: string[] = [];

type redactOptions = Extract<pino.LoggerOptions['redact'], { paths: string[] }>;

type extendedRedactOptions = redactOptions & {
/**
* A list of paths to remove from the logged object instead of redacting them.
* Note that if you are only removing, rather use the `paths` property and set `remove` to `true`.
*/
removePaths?: string[];

/**
* When `true`, the `defaultRemovePaths` will not be appended to the `removePaths` list.
*/
ignoreDefaultRemovePaths?: true;
};

type ExtendedRedact = string[] | ExtendedRedactOptions | undefined;
export type ExtendedRedact = string[] | extendedRedactOptions | undefined;

const addDefaultRedactPathStrings = (
const appendDefaultRedactAndRemove = (
redact: ExtendedRedact,
): ExtendedRedact => {
if (!redact) {
return defaultRedact;
}
if (Array.isArray(redact)) {
return redact.concat(defaultRedact);
}
return redact;
): extendedRedactOptions | undefined => {
const inputRedact =
typeof redact !== 'undefined' && !Array.isArray(redact)
? redact
: { paths: redact ?? [] };

const paths = inputRedact.paths.concat(defaultRedact);
const inputRemovePaths = inputRedact.removePaths ?? [];
const removePaths = inputRedact.ignoreDefaultRemovePaths
? inputRemovePaths
: inputRemovePaths.concat(defaultRemovePaths);

return paths.length === 0 && removePaths.length === 0
? undefined
: { ...inputRedact, paths, removePaths };
};

const STARTS_WITH_INVALID_CHARS = '^[^$_a-zA-Z]';
Expand Down Expand Up @@ -66,4 +82,4 @@ const configureRedactCensor = (redact: ExtendedRedact): ExtendedRedact => {
};

export const configureRedact = (redact: ExtendedRedact): ExtendedRedact =>
configureRedactCensor(addDefaultRedactPathStrings(redact));
configureRedactCensor(appendDefaultRedactAndRemove(redact));

0 comments on commit 8bcb486

Please sign in to comment.