Skip to content

Commit

Permalink
Merge pull request #164 from seek-oss/support-custom-log-levels
Browse files Browse the repository at this point in the history
Add support for configuring custom log levels
  • Loading branch information
AaronMoat authored Feb 5, 2025
2 parents f10791f + 305df0d commit d47d90e
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 7 deletions.
18 changes: 18 additions & 0 deletions .changeset/ninety-bobcats-return.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
'@seek/logger': minor
---

Add support for configuring custom log levels:

```ts
import createLogger from '@seek/logger';

const logger = createLogger({
name: 'my-app',
customLevels: {
foo: 35,
},
});

logger.foo('Bar');
```
50 changes: 50 additions & 0 deletions src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -831,3 +831,53 @@ test('it merges serializers', async () => {
expect(rootLog.headers).not.toHaveProperty('omit');
expect(rootLog).not.toHaveProperty('req');
});

test('allows custom levels', async () => {
const stream = sink();
const logger = createLogger(
{
name: 'my-app',
customLevels: {
something: 35,
},
},
stream,
);

logger.something('foo');

const somethingLog: any = await once(stream, 'data');
expect(somethingLog.level).toBe(35);
expect(somethingLog.msg).toBe('foo');
expect(somethingLog.name).toBe('my-app');

logger.info('info');

const infoLog: any = await once(stream, 'data');
expect(infoLog.level).toBe(30);
expect(infoLog.msg).toBe('info');
expect(infoLog.name).toBe('my-app');
});

test('using custom levels does not leak into types or runtypes of other loggers', () => {
const stream = sink();

createLogger(
{ name: 'custom-logger', customLevels: { something: 35 } },
stream,
);

const logger = createLogger({ name: 'my-app' }, stream);

expect(() => {
// @ts-expect-error - should not work
logger.something('foo');
}).toThrow();

logger.info('info');

const infoLog: any = stream.read();
expect(infoLog.level).toBe(30);
expect(infoLog.msg).toBe('info');
expect(infoLog.name).toBe('my-app');
});
15 changes: 8 additions & 7 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,22 @@ export { DEFAULT_OMIT_HEADER_NAMES } from './serializers';

export { pino };

export type LoggerOptions = pino.LoggerOptions &
FormatterOptions &
SerializerOptions;
export type Logger = pino.Logger;
export type LoggerOptions<CustomLevels extends string = never> =
pino.LoggerOptions<CustomLevels> & FormatterOptions & SerializerOptions;

export type Logger<CustomLevels extends string = never> =
pino.Logger<CustomLevels>;

/**
* Creates a logger that can enforce a strict logged object shape.
* @param opts - Logger options.
* @param destination - Destination stream. Default: `pino.destination({ sync: true })`.
*/
export default (
opts: LoggerOptions = {},
export default <CustomLevels extends string = never>(
opts: LoggerOptions<CustomLevels> = {},
destination: pino.DestinationStream = createDestination({ mock: false })
.destination,
): Logger => {
): Logger<CustomLevels> => {
opts.redact = redact.addDefaultRedactPathStrings(opts.redact);

const serializers = createSerializers(opts);
Expand Down

0 comments on commit d47d90e

Please sign in to comment.