Skip to content
This repository was archived by the owner on Jun 21, 2023. It is now read-only.

Commit 04d10cc

Browse files
committed
✨ Add sentry transform stream
Related: #28
1 parent be9c3c9 commit 04d10cc

5 files changed

Lines changed: 77 additions & 19 deletions

File tree

src/index.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@ const defaultLogger = (options: AckeeLoggerOptions & { loggerName?: string } = {
6969
serializers.disablePaths(options.disableFields);
7070
serializers.enablePaths(options.enableFields);
7171

72+
if (options.sentryDsn) {
73+
// Check library is available
74+
require('@sentry/node');
75+
}
76+
7277
const isTesting = process.env.NODE_ENV === 'test';
7378
const defaultLevel: Level = options.defaultLevel || (isTesting ? 'silent' : 'debug');
7479
const messageKey = 'message'; // best option for Google Stackdriver,
@@ -91,10 +96,6 @@ const defaultLogger = (options: AckeeLoggerOptions & { loggerName?: string } = {
9196
(pinoms as any).multistream(streams)
9297
) as PinoLogger) as AckeeLogger;
9398

94-
if (options.sentryDsn) {
95-
const sentry = require('@sentry/node');
96-
}
97-
9899
// Add maxLevel support to pino-multi-stream
99100
// This could be replaced with custom pass-through stream being passed to multistream, which would filter the messages
100101
const loggerStream = (logger as any)[(pino as any).symbols.streamSym] as any;

src/sentry.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { Transform, TransformCallback } from 'stream';
2+
import { captureException } from '@sentry/node';
3+
4+
class SentryTransformStream extends Transform {
5+
// tslint:disable-next-line:function-name
6+
public _transform(chunk: any, _encoding: string, callback: TransformCallback) {
7+
const obj = JSON.parse(chunk);
8+
captureException(obj);
9+
this.push(chunk);
10+
callback();
11+
}
12+
}
13+
export { SentryTransformStream };

src/streams.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { loggerNameKey, pkgVersionKey } from '.';
77
import { AckeeLoggerOptions, AckeeLoggerStream } from './interfaces';
88
import { levels } from './levels';
99
import { StackDriverFormatStream } from './stackdriver';
10+
import { SentryTransformStream } from './sentry';
1011

1112
const pkgJson = JSON.parse(fs.readFileSync(path.resolve(path.join(__dirname, '..', 'package.json')), 'utf8'));
1213

@@ -71,6 +72,11 @@ const initLoggerStreams = (
7172
}
7273

7374
streams = decorateStreams(streams, getDefaultTransformStream(options));
75+
76+
if (options.sentryDsn) {
77+
streams = decorateStreams(streams, SentryTransformStream);
78+
}
79+
7480
return streams;
7581
};
7682

src/tests/sentry-mocked.test.ts

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,43 @@
1-
import loggerFactory from '..';
1+
import { testWriteStream } from './utils';
2+
import { setContext } from '@sentry/core';
23

3-
jest.mock('@sentry/node', () => {});
4+
let loggerFactory;
5+
const captureException = jest.fn();
6+
const captureMessage = jest.fn();
47

5-
test('can create logger with options', () => {
6-
expect(() => loggerFactory()).not.toThrowError();
7-
expect(() => loggerFactory({ sentryDsn: 'DSN' })).not.toThrowError();
8-
});
8+
describe('sentry mocked', () => {
9+
beforeAll(() => {
10+
jest.mock('@sentry/node', () => {
11+
return {
12+
captureException,
13+
};
14+
});
15+
loggerFactory = require('..').default;
16+
});
17+
test('can create logger with options', () => {
18+
expect(() => loggerFactory()).not.toThrowError();
19+
expect(() => loggerFactory({ sentryDsn: 'DSN' })).not.toThrowError();
20+
});
21+
22+
test('can use custom stream', async () => {
23+
await new Promise((resolve, reject) => {
24+
const logger = loggerFactory({
25+
sentryDsn: 'DSN',
26+
});
27+
captureException.mockImplementation(x => {
28+
resolve();
29+
console.log({ captureException: x });
30+
});
31+
logger.info('Foo');
32+
});
33+
expect(captureException.mock.calls[0]).toMatchInlineSnapshot(`
34+
Array [
35+
Object {
36+
"level": 30,
37+
"message": "Foo",
38+
"v": 1,
39+
},
40+
]
41+
`);
42+
});
43+
});

src/tests/sentry.test.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
import loggerFactory from '..';
22

3-
jest.mock('@sentry/node', () => {
4-
throw new Error("Cannot find module '@sentry/node' from 'index.ts'");
3+
describe('sentry not available', () => {
4+
beforeAll(() => {
5+
jest.mock('@sentry/node', () => {
6+
throw new Error("Cannot find module '@sentry/node' from 'index.ts'");
7+
});
8+
});
9+
test('without sentry lib works by default, but crashes on provided', () => {
10+
expect(() => loggerFactory()).not.toThrowError();
11+
expect(() => loggerFactory({ sentryDsn: 'DSN' })).toThrowErrorMatchingInlineSnapshot(
12+
`"Cannot find module '@sentry/node' from 'index.ts'"`
13+
);
14+
});
515
});
6-
7-
test('without sentry lib works by default, but crashes on provided', () => {
8-
expect(() => loggerFactory()).not.toThrowError();
9-
expect(() => loggerFactory({ sentryDsn: 'DSN' })).toThrowErrorMatchingInlineSnapshot(
10-
`"Cannot find module '@sentry/node' from 'index.ts'"`
11-
);
12-
});

0 commit comments

Comments
 (0)