Skip to content

Commit

Permalink
Add trimming to all serializers and refactor to reuse the same trimmer
Browse files Browse the repository at this point in the history
  • Loading branch information
zbrydon committed Jul 17, 2024
1 parent 54f16e1 commit cfe5782
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 80 deletions.
4 changes: 3 additions & 1 deletion src/formatters/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { trimmer } from 'dtrim';
import type { LoggerOptions } from 'pino';

export const DEFAULT_MAX_OBJECT_DEPTH = 4;

export interface FormatterOptions {
/**
* Maximum property depth of objects being logged. Default: 4
Expand All @@ -17,7 +19,7 @@ export const createFormatters = (
opts: FormatterOptions & Required<Pick<LoggerOptions, 'serializers'>>,
): LoggerOptions['formatters'] => {
const trim = trimmer({
depth: opts.maxObjectDepth ?? 4,
depth: opts.maxObjectDepth ?? DEFAULT_MAX_OBJECT_DEPTH,
retain: new Set(Object.keys(opts.serializers)),
});

Expand Down
95 changes: 36 additions & 59 deletions src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -632,48 +632,34 @@ test('should log customized timestamp if timestamp logger option is supplied', a
expect(log.timestamp).toBe(mockTimestamp);
});

class Req {
get socket() {
return {
remoteAddress: 'localhost',
remotePort: '4000',
};
}
}
testLog(
'should not truncate objects with a non error serializer',
'should truncate objects with serializers',
{
req: new Req(),
notSerialized: {
errWithCause: {
a: {
b: {},
},
anyField: 'a'.repeat(555),
},
},
{
req: {
remoteAddress: 'localhost',
remotePort: '4000',
},
notSerialized: {
a: '[Object]',
},
},
'info',
{
maxObjectDepth: 2,
},
);

testLog(
'should truncate objects with error serializers',
{
errWithCause: {
err: {
a: {
b: {},
},
anyField: 'a'.repeat(555),
},
err: {
req: {
method: 'GET',
url: 'a'.repeat(555),
headers: [],
socket: { remoteAddress: 'localhost', remotePort: '4000' },
},
res: {
headers: { Origin: 'a'.repeat(555) },
status: 500,
foo: 'baz',
},
headers: {
'test-header': 'a'.repeat(555),
a: {
b: {},
},
Expand All @@ -684,44 +670,35 @@ testLog(
a: {
b: '[Object]',
},
anyField: `${'a'.repeat(512)}...`,
},
err: {
a: {
b: '[Object]',
},
anyField: `${'a'.repeat(512)}...`,
},
},
'info',
{
maxObjectDepth: 2,
},
);

testLog(
'should truncate strings longer than 512 characters with error serializers',
{
err: {
anyField: {
anyField: 'a'.repeat(555),
},
req: {
method: 'GET',
url: `${'a'.repeat(512)}...`,
headers: [],
remoteAddress: 'localhost',
remotePort: '4000',
},
errWithCause: {
anyField: {
anyField: 'a'.repeat(555),
res: {
headers: { Origin: `${'a'.repeat(512)}...` },
statusCode: 500,
},
headers: {
'test-header': `${'a'.repeat(512)}...`,
a: {
b: '[Object]',
},
},
},
'info',
{
err: {
anyField: {
anyField: `${'a'.repeat(512)}...`,
},
},
errWithCause: {
anyField: {
anyField: `${'a'.repeat(512)}...`,
},
},
maxObjectDepth: 2,
},
);

Expand Down
35 changes: 17 additions & 18 deletions src/serializers/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { trimmer } from 'dtrim';
import type pino from 'pino';
import { type SerializedError, err, errWithCause } from 'pino-std-serializers';
import { err, errWithCause } from 'pino-std-serializers';

import type { FormatterOptions } from '../formatters';
import { DEFAULT_MAX_OBJECT_DEPTH, type FormatterOptions } from '../formatters';

import { createOmitPropertiesSerializer } from './omitPropertiesSerializer';
import type { SerializerFn } from './types';
import type { SerializerFn, TrimmerFn } from './types';

export const DEFAULT_OMIT_HEADER_NAMES = Object.freeze([
'x-envoy-attempt-count',
Expand Down Expand Up @@ -61,7 +61,7 @@ const isObject = (value: unknown): boolean => {
};

const createReqSerializer =
(serializeHeaders: SerializerFn) => (request: Request) =>
(serializeHeaders: SerializerFn<unknown>) => (request: Request) =>
isObject(request)
? {
method: request.method,
Expand All @@ -80,15 +80,10 @@ const res = (response: Response) =>
}
: response;

const createErrSerializer =
(
serializer: (error: Error) => SerializedError,
opts: FormatterOptions,
): SerializerFn =>
(error: unknown): unknown =>
trimmer({
depth: opts.maxObjectDepth ?? 4,
})(serializer(error as Error));
const trimSerializerOutput =
<T>(serializer: SerializerFn<T>, trim: TrimmerFn) =>
(input: T): unknown =>
trim(serializer(input));

export const createSerializers = (
opts: SerializerOptions & FormatterOptions,
Expand All @@ -97,12 +92,16 @@ export const createSerializers = (
opts.omitHeaderNames ?? DEFAULT_OMIT_HEADER_NAMES,
);

const trim = trimmer({
depth: opts.maxObjectDepth ?? DEFAULT_MAX_OBJECT_DEPTH,
});

const serializers = {
err: createErrSerializer(err, opts),
errWithCause: createErrSerializer(errWithCause, opts),
req: createReqSerializer(serializeHeaders),
res,
headers: serializeHeaders,
err: trimSerializerOutput(err, trim),
errWithCause: trimSerializerOutput(errWithCause, trim),
req: trimSerializerOutput(createReqSerializer(serializeHeaders), trim),
res: trimSerializerOutput(res, trim),
headers: trimSerializerOutput(serializeHeaders, trim),
} satisfies pino.LoggerOptions['serializers'];

return serializers;
Expand Down
2 changes: 1 addition & 1 deletion src/serializers/omitPropertiesSerializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export const createOmitPropertiesSerializer = (
* A list of properties that should not be logged.
*/
properties: readonly string[],
): SerializerFn => {
): SerializerFn<unknown> => {
const uniquePropertySet = new Set(properties);

if (uniquePropertySet.size === 0) {
Expand Down
3 changes: 2 additions & 1 deletion src/serializers/types.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export type SerializerFn = (input: unknown) => unknown;
export type TrimmerFn = (input: unknown) => unknown;
export type SerializerFn<T> = (input: T) => unknown;

0 comments on commit cfe5782

Please sign in to comment.