Skip to content

Commit a88c452

Browse files
committed
Accept objects for logging
This lets you pass in an object without having to iterate over the keys and turn them into Field instances yourself.
1 parent ad83cad commit a88c452

File tree

1 file changed

+80
-35
lines changed

1 file changed

+80
-35
lines changed

packages/logger/src/logger.ts

+80-35
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,20 @@ export class Time {
3939
) { }
4040
}
4141

42+
// tslint:disable-next-line no-any
43+
export type FieldArray = Array<Field<any>>;
44+
45+
// Same as FieldArray but supports taking an object or undefined.
4246
// `undefined` is allowed to make it easy to conditionally display a field.
43-
// For example: `error && field("error", error)`
47+
// For example: `error && field("error", error)`.
48+
// For objects, the logger will iterate over the keys and turn them into
49+
// instances of Field.
4450
// tslint:disable-next-line no-any
45-
export type FieldArray = Array<Field<any> | undefined>;
51+
export type LogArgument = Array<Field<any> | undefined | object>;
4652

4753
// Functions can be used to remove the need to perform operations when the
4854
// logging level won't output the result anyway.
49-
export type LogCallback = () => [string, ...FieldArray];
55+
export type LogCallback = () => [string, ...LogArgument];
5056

5157
/**
5258
* Creates a time field
@@ -82,13 +88,19 @@ export abstract class Formatter {
8288
public abstract tag(name: string, color: string): void;
8389

8490
/**
85-
* Add string or arbitrary variable.
91+
* Add string variable.
8692
*/
8793
public abstract push(arg: string, color?: string, weight?: string): void;
94+
/**
95+
* Add arbitrary variable.
96+
*/
8897
public abstract push(arg: any): void; // tslint:disable-line no-any
8998

99+
/**
100+
* Add fields.
101+
*/
90102
// tslint:disable-next-line no-any
91-
public abstract fields(fields: Array<Field<any>>): void;
103+
public abstract fields(fields: FieldArray): void;
92104

93105
/**
94106
* Flush out the built arguments.
@@ -120,6 +132,9 @@ export abstract class Formatter {
120132
* Browser formatter.
121133
*/
122134
export class BrowserFormatter extends Formatter {
135+
/**
136+
* Add a tag.
137+
*/
123138
public tag(name: string, color: string): void {
124139
this.format += `%c ${name} `;
125140
this.args.push(
@@ -131,6 +146,9 @@ export class BrowserFormatter extends Formatter {
131146
this.push(" ");
132147
}
133148

149+
/**
150+
* Add an argument.
151+
*/
134152
public push(arg: any, color: string = "inherit", weight: string = "normal"): void { // tslint:disable-line no-any
135153
if (color || weight) {
136154
this.format += "%c";
@@ -143,8 +161,11 @@ export class BrowserFormatter extends Formatter {
143161
this.args.push(arg);
144162
}
145163

164+
/**
165+
* Add fields.
166+
*/
146167
// tslint:disable-next-line no-any
147-
public fields(fields: Array<Field<any>>): void {
168+
public fields(fields: FieldArray): void {
148169
// tslint:disable-next-line no-console
149170
console.groupCollapsed(...this.flush());
150171
fields.forEach((field) => {
@@ -166,6 +187,9 @@ export class BrowserFormatter extends Formatter {
166187
* Server (Node) formatter.
167188
*/
168189
export class ServerFormatter extends Formatter {
190+
/**
191+
* Add a tag.
192+
*/
169193
public tag(name: string, color: string): void {
170194
const [r, g, b] = this.hexToRgb(color);
171195
while (name.length < 5) {
@@ -175,6 +199,9 @@ export class ServerFormatter extends Formatter {
175199
this.format += `\u001B[38;2;${r};${g};${b}m${name} \u001B[0m`;
176200
}
177201

202+
/**
203+
* Add an argument.
204+
*/
178205
public push(arg: any, color?: string, weight?: string): void { // tslint:disable-line no-any
179206
if (weight === "bold") {
180207
this.format += "\u001B[1m";
@@ -190,8 +217,11 @@ export class ServerFormatter extends Formatter {
190217
this.args.push(arg);
191218
}
192219

220+
/**
221+
* Add fields.
222+
*/
193223
// tslint:disable-next-line no-any
194-
public fields(fields: Array<Field<any>>): void {
224+
public fields(fields: FieldArray): void {
195225
// tslint:disable-next-line no-any
196226
const obj: { [key: string]: any} = {};
197227
this.format += "\u001B[38;2;140;140;140m";
@@ -257,80 +287,83 @@ export class Logger {
257287
this.muted = true;
258288
}
259289

290+
/**
291+
* Extend the logger (for example to send the logs elsewhere).
292+
*/
260293
public extend(extender: Extender): void {
261294
this.extenders.push(extender);
262295
}
263296

264297
/**
265-
* Outputs information.
298+
* Log information.
266299
*/
267300
public info(fn: LogCallback): void;
268-
public info(message: string, ...fields: FieldArray): void;
269-
public info(message: LogCallback | string, ...fields: FieldArray): void {
301+
public info(message: string, ...args: LogArgument): void;
302+
public info(message: LogCallback | string, ...args: LogArgument): void {
270303
this.handle({
271304
type: "info",
272305
message,
273-
fields,
306+
args,
274307
tagColor: "#008FBF",
275308
level: Level.Info,
276309
});
277310
}
278311

279312
/**
280-
* Outputs a warning.
313+
* Log a warning.
281314
*/
282315
public warn(fn: LogCallback): void;
283-
public warn(message: string, ...fields: FieldArray): void;
284-
public warn(message: LogCallback | string, ...fields: FieldArray): void {
316+
public warn(message: string, ...args: LogArgument): void;
317+
public warn(message: LogCallback | string, ...args: LogArgument): void {
285318
this.handle({
286319
type: "warn",
287320
message,
288-
fields,
321+
args,
289322
tagColor: "#FF9D00",
290323
level: Level.Warning,
291324
});
292325
}
293326

294327
/**
295-
* Outputs a trace message.
328+
* Log a trace message.
296329
*/
297330
public trace(fn: LogCallback): void;
298-
public trace(message: string, ...fields: FieldArray): void;
299-
public trace(message: LogCallback | string, ...fields: FieldArray): void {
331+
public trace(message: string, ...args: LogArgument): void;
332+
public trace(message: LogCallback | string, ...args: LogArgument): void {
300333
this.handle({
301334
type: "trace",
302335
message,
303-
fields,
336+
args,
304337
tagColor: "#888888",
305338
level: Level.Trace,
306339
});
307340
}
308341

309342
/**
310-
* Outputs a debug message.
343+
* Log a debug message.
311344
*/
312345
public debug(fn: LogCallback): void;
313-
public debug(message: string, ...fields: FieldArray): void;
314-
public debug(message: LogCallback | string, ...fields: FieldArray): void {
346+
public debug(message: string, ...args: LogArgument): void;
347+
public debug(message: LogCallback | string, ...args: LogArgument): void {
315348
this.handle({
316349
type: "debug",
317350
message,
318-
fields,
351+
args,
319352
tagColor: "#84009E",
320353
level: Level.Debug,
321354
});
322355
}
323356

324357
/**
325-
* Outputs an error.
358+
* Log an error.
326359
*/
327360
public error(fn: LogCallback): void;
328-
public error(message: string, ...fields: FieldArray): void;
329-
public error(message: LogCallback | string, ...fields: FieldArray): void {
361+
public error(message: string, ...args: LogArgument): void;
362+
public error(message: LogCallback | string, ...args: LogArgument): void {
330363
this.handle({
331364
type: "error",
332365
message,
333-
fields,
366+
args,
334367
tagColor: "#B00000",
335368
level: Level.Error,
336369
});
@@ -350,29 +383,41 @@ export class Logger {
350383
}
351384

352385
/**
353-
* Outputs a message.
386+
* Log a message.
354387
*/
355388
private handle(options: {
356389
type: "trace" | "info" | "warn" | "debug" | "error";
357390
message: string | LogCallback;
358-
fields?: FieldArray;
391+
args?: LogArgument;
359392
level: Level;
360393
tagColor: string;
361394
}): void {
362395
if (this.level > options.level || this.muted) {
363396
return;
364397
}
365398

366-
let passedFields = options.fields || [];
367399
if (typeof options.message === "function") {
368400
const values = options.message();
369401
options.message = values.shift() as string;
370-
passedFields = values as FieldArray;
402+
options.args = values as FieldArray;
371403
}
372404

373-
const fields = (this.defaultFields
374-
? passedFields.filter((f) => !!f).concat(this.defaultFields)
375-
: passedFields.filter((f) => !!f)) as Array<Field<any>>; // tslint:disable-line no-any
405+
const fields: FieldArray = [];
406+
if (options.args) {
407+
options.args.forEach((arg) => {
408+
if (arg instanceof Field) {
409+
fields.push(arg);
410+
} else if (arg) {
411+
Object.keys(arg).forEach((k) => {
412+
// tslint:disable-next-line no-any
413+
fields.push(field(k, (arg as any)[k]));
414+
});
415+
}
416+
});
417+
}
418+
if (this.defaultFields) {
419+
fields.push(...this.defaultFields);
420+
}
376421

377422
const now = Date.now();
378423
let times: Array<Field<Time>> = [];
@@ -410,7 +455,7 @@ export class Logger {
410455
this.extenders.forEach((extender) => {
411456
extender({
412457
section: this.name,
413-
fields: options.fields,
458+
fields,
414459
level: options.level,
415460
message: options.message as string,
416461
type: options.type,

0 commit comments

Comments
 (0)