Skip to content

Commit

Permalink
feat: New option customLocate
Browse files Browse the repository at this point in the history
  • Loading branch information
unlight committed Feb 17, 2021
1 parent 76bb496 commit 9145c4c
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 46 deletions.
23 changes: 19 additions & 4 deletions src/index.spec.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,26 @@
import ansicolor from 'ansicolor';
import expect from 'expect';

import { messageColumnWidth } from './message-column-width';
import { nestologOptionsDefaults } from './nestolog-options.provider';
import { NestoLogger } from './nestologger.service';

describe('nestoLog', () => {
it('configure messageColumnWidth temp', () => {
const result = messageColumnWidth(nestologOptionsDefaults);
expect(result).not.toBeUndefined();
it('messageColumnWidth', () => {
const result = messageColumnWidth(nestologOptionsDefaults);
expect(result).not.toBeUndefined();
});

it('custom locate', () => {
let output = '';
const logger = new NestoLogger({
...nestologOptionsDefaults,
customLocate: true,
render: (input: string) => {
output = ansicolor.strip(input);
},
});
logger.log('Test message', 'Contex');
const lines = output.split('\n');
expect(lines).toHaveLength(2);
expect(lines[0]!.indexOf('Test message')).toEqual(lines[1]?.indexOf('<anonymous>'));
});
22 changes: 6 additions & 16 deletions src/nestolog-options.provider.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,16 @@
import { Provider } from '@nestjs/common';
import ololog from 'ololog';

export const NESTOLOG_OPTIONS = Symbol('NESTOLOG_OPTIONS');
import { nestologOptionsDefaults } from './nestolog-options';

export const nestologOptionsDefaults = {
time: true,
locate: true,
tag: true,
contextLimit: 13,
/**
* Word wrap width for message.
* If 0 (default) tries to auto detect.
* If -1 disable
*/
messageColumnWidth: 0,
};
export const NESTOLOG_OPTIONS = Symbol('NESTOLOG_OPTIONS');

export const nestologOptionsProvider: Provider = {
provide: NESTOLOG_OPTIONS,
useValue: nestologOptionsDefaults,
};

export type NestologOptions = Partial<
typeof nestologOptionsDefaults & Parameters<typeof ololog.configure>[0]
>;
export type NestologOptions = typeof nestologOptionsDefaults &
Parameters<typeof ololog.configure>[0];

export { nestologOptionsDefaults };
41 changes: 41 additions & 0 deletions src/nestolog-options.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import ololog from 'ololog';

import { Entry } from './types';

export const nestologOptionsDefaults = {
time: true,
locate: true,
tag: true,
contextLimit: 13,
/**
* Word wrap width for message.
* If 0 (default) tries to auto detect.
* If -1 disable
*/
messageColumnWidth: 0,
/**
* Alternative locate. Default ololog's locate add callee info to the last non-empty string
* Custom locate add callee info on next new line.
*/
customLocate: undefined as undefined | boolean | typeof customLocateDefault,
};

export type NestologOptions = Partial<
typeof nestologOptionsDefaults & Parameters<typeof ololog.configure>[0]
>;

export function customLocateDefault({ calleeShort, fileName, line }: Entry): string {
let result = '';
if (calleeShort) {
result += calleeShort;
}
if (fileName && line) {
if (result.length > 0) {
result += ' @ ';
}
result += fileName;
result += ':';
result += line;
}
return result;
}
2 changes: 1 addition & 1 deletion src/nestolog.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { NestoLogger } from './nestologger.service';

@Module({})
export class NestologModule {
static forRoot(options: NestologOptions = {}): DynamicModule {
static forRoot(options: Partial<NestologOptions> = {}): DynamicModule {
options = { ...nestologOptionsDefaults, ...options };
return {
module: NestologModule,
Expand Down
59 changes: 34 additions & 25 deletions src/nestologger.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import stringify from 'string.ify';
import wrapAnsi from 'wrap-ansi';

import { messageColumnWidth } from './message-column-width';
import { customLocateDefault } from './nestolog-options';
import { NESTOLOG_OPTIONS, NestologOptions } from './nestolog-options.provider';
import { Entry } from './types';

// ololog pipeline: stringify trim lines concat indent tag time locate join render returnValue

Expand All @@ -17,7 +19,7 @@ export class NestoLogger implements LoggerService {
verbose = this.debug;

constructor(
@Inject(NESTOLOG_OPTIONS) private readonly options: Required<NestologOptions>,
@Inject(NESTOLOG_OPTIONS) private readonly options: NestologOptions,
@Inject('ololog') @Optional() private readonly logger = ololog,
) {
this.logger = this.createLogger(logger);
Expand All @@ -29,6 +31,7 @@ export class NestoLogger implements LoggerService {
this.options.messageColumnWidth || messageColumnWidth(this.options, logger);
if (width && width > 0) {
logger = logger.configure({
locate: false,
'+lines': (lines: string[]) => {
lines = lines.map(line => wrapAnsi(line, width, { trim: false }));
return lines;
Expand All @@ -39,37 +42,34 @@ export class NestoLogger implements LoggerService {
}

log(message: any, context?: string): void {
const where = new StackTracey().clean().at(1);
const log = this.logger.configure({
locate: {
where: new StackTracey().clean().at(1),
},
locate: { where },
tag: { level: 'info' },
render: { consoleMethod: 'info' },
'concat+': this.concatContext(context),
'concat+': this.concatContext({ context, where }),
});
log(message);
}

warn(message: any, context?: string): void {
const where = new StackTracey().clean().at(1);
const log = this.logger.configure({
locate: {
where: new StackTracey().clean().at(1),
},
locate: { where },
tag: { level: 'warn' },
render: { consoleMethod: 'warn' },
'concat+': this.concatContext(context),
'concat+': this.concatContext({ context, where }),
});
log(message);
}

error(message: any, trace?: string, context?: string): void {
const where = new StackTracey().clean().at(1);
const log = this.logger.configure({
locate: {
where: new StackTracey().clean().at(1),
},
locate: { where },
tag: { level: 'error' },
render: { consoleMethod: 'error' },
'concat+': this.concatContext(context),
'concat+': this.concatContext({ context, where }),
});
if (!trace && message instanceof Error && !message.stack) {
Error.captureStackTrace(message);
Expand All @@ -81,26 +81,35 @@ export class NestoLogger implements LoggerService {
}

debug(message: any, context?: string): void {
const where = new StackTracey().clean().at(1);
const log = this.logger.configure({
locate: {
where: new StackTracey().clean().at(1),
},
locate: { where },
tag: { level: 'debug' },
render: { consoleMethod: 'debug' },
'concat+': this.concatContext(context),
'concat+': this.concatContext({ context, where }),
});
log(message);
}

private concatContext(context: string | undefined) {
const contextLimit = this.options.contextLimit;
if (!(context && contextLimit > 0)) {
return;
}
// eslint-disable-next-line consistent-return
private concatContext({ context, where }: { context?: string; where?: Entry }) {
const { contextLimit } = this.options;
const customLocate =
this.options.customLocate === true
? customLocateDefault
: this.options.customLocate;
return (lines: string[]) => {
context = stringify.limit(context, contextLimit).padEnd(contextLimit);
return bullet(ansicolor.yellow(context + ' '), lines) as string;
if (where && customLocate) {
lines.push(ansicolor.darkGray(customLocate(where)));
}
if (context) {
if (contextLimit > 0) {
context = stringify
.limit(context, contextLimit)
.padEnd(contextLimit);
}
return bullet(ansicolor.yellow(context + ' '), lines);
}
return lines;
};
}
}
36 changes: 36 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
export type LocatePrint = (args: {
calleeShort: string;
fileName: string;
line: string;
}) => string;

export interface Location {
file: string;
line?: number;
column?: number;
}

export interface Entry extends Location {
beforeParse: string;
callee: string;
index: boolean;
native: boolean;

calleeShort: string;
fileRelative: string;
fileShort: string;
fileName: string;
thirdParty: boolean;

hide?: boolean;
sourceLine?: string;
sourceFile?: SourceFile;
error?: Error;
}

export interface SourceFile {
path: string;
text: string;
lines: string[];
error?: Error;
}

0 comments on commit 9145c4c

Please sign in to comment.