@dxos/log 0.8.4-main.c4373fc → 0.8.4-main.c85a9c8dae

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/dist/lib/browser/chunk-IEP6GGEX.mjs +23 -0
  2. package/dist/lib/browser/chunk-IEP6GGEX.mjs.map +7 -0
  3. package/dist/lib/browser/chunk-M2YHSBML.mjs +133 -0
  4. package/dist/lib/browser/chunk-M2YHSBML.mjs.map +7 -0
  5. package/dist/lib/browser/index.mjs +221 -206
  6. package/dist/lib/browser/index.mjs.map +4 -4
  7. package/dist/lib/browser/meta.json +1 -1
  8. package/dist/lib/browser/platform/browser/index.mjs +26 -0
  9. package/dist/lib/browser/platform/browser/index.mjs.map +7 -0
  10. package/dist/lib/browser/platform/node/index.mjs +21 -0
  11. package/dist/lib/browser/platform/node/index.mjs.map +7 -0
  12. package/dist/lib/browser/processors/console-processor.mjs +107 -0
  13. package/dist/lib/browser/processors/console-processor.mjs.map +7 -0
  14. package/dist/lib/browser/processors/console-stub.mjs +9 -0
  15. package/dist/lib/browser/processors/console-stub.mjs.map +7 -0
  16. package/dist/lib/node-esm/chunk-2SZHAWBN.mjs +24 -0
  17. package/dist/lib/node-esm/chunk-2SZHAWBN.mjs.map +7 -0
  18. package/dist/lib/node-esm/chunk-62VKC2WQ.mjs +135 -0
  19. package/dist/lib/node-esm/chunk-62VKC2WQ.mjs.map +7 -0
  20. package/dist/lib/node-esm/index.mjs +216 -288
  21. package/dist/lib/node-esm/index.mjs.map +4 -4
  22. package/dist/lib/node-esm/meta.json +1 -1
  23. package/dist/lib/node-esm/platform/browser/index.mjs +27 -0
  24. package/dist/lib/node-esm/platform/browser/index.mjs.map +7 -0
  25. package/dist/lib/node-esm/platform/node/index.mjs +22 -0
  26. package/dist/lib/node-esm/platform/node/index.mjs.map +7 -0
  27. package/dist/lib/node-esm/processors/console-processor.mjs +108 -0
  28. package/dist/lib/node-esm/processors/console-processor.mjs.map +7 -0
  29. package/dist/lib/node-esm/processors/console-stub.mjs +10 -0
  30. package/dist/lib/node-esm/processors/console-stub.mjs.map +7 -0
  31. package/dist/types/src/config.d.ts.map +1 -1
  32. package/dist/types/src/context.d.ts.map +1 -1
  33. package/dist/types/src/dbg.d.ts +23 -0
  34. package/dist/types/src/dbg.d.ts.map +1 -0
  35. package/dist/types/src/decorators.d.ts +1 -1
  36. package/dist/types/src/decorators.d.ts.map +1 -1
  37. package/dist/types/src/index.d.ts +3 -2
  38. package/dist/types/src/index.d.ts.map +1 -1
  39. package/dist/types/src/log-buffer.d.ts +36 -0
  40. package/dist/types/src/log-buffer.d.ts.map +1 -0
  41. package/dist/types/src/log-buffer.test.d.ts +2 -0
  42. package/dist/types/src/log-buffer.test.d.ts.map +1 -0
  43. package/dist/types/src/log.d.ts +14 -18
  44. package/dist/types/src/log.d.ts.map +1 -1
  45. package/dist/types/src/options.d.ts +1 -6
  46. package/dist/types/src/options.d.ts.map +1 -1
  47. package/dist/types/src/platform/index.d.ts +1 -1
  48. package/dist/types/src/platform/index.d.ts.map +1 -1
  49. package/dist/types/src/processors/file-processor.d.ts.map +1 -1
  50. package/dist/types/src/processors/index.d.ts +3 -3
  51. package/dist/types/src/processors/index.d.ts.map +1 -1
  52. package/dist/types/tsconfig.tsbuildinfo +1 -1
  53. package/package.json +30 -12
  54. package/src/config.ts +1 -0
  55. package/src/context.ts +36 -5
  56. package/src/dbg.ts +34 -0
  57. package/src/decorators.ts +3 -3
  58. package/src/index.ts +3 -3
  59. package/src/log-buffer.test.ts +156 -0
  60. package/src/log-buffer.ts +108 -0
  61. package/src/log.test.ts +48 -18
  62. package/src/log.ts +103 -57
  63. package/src/options.ts +26 -10
  64. package/src/platform/index.ts +1 -1
  65. package/src/processors/file-processor.ts +2 -0
  66. package/src/processors/index.ts +3 -3
package/package.json CHANGED
@@ -1,13 +1,37 @@
1
1
  {
2
2
  "name": "@dxos/log",
3
- "version": "0.8.4-main.c4373fc",
3
+ "version": "0.8.4-main.c85a9c8dae",
4
4
  "description": "Logger",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/dxos/dxos"
10
+ },
7
11
  "license": "MIT",
8
12
  "author": "DXOS.org",
9
13
  "sideEffects": true,
10
14
  "type": "module",
15
+ "imports": {
16
+ "#platform": {
17
+ "source": {
18
+ "browser": "./src/platform/browser/index.ts",
19
+ "default": "./src/platform/node/index.ts"
20
+ },
21
+ "types": "./dist/types/src/platform/node/index.d.ts",
22
+ "browser": "./dist/lib/browser/platform/browser/index.mjs",
23
+ "default": "./dist/lib/node-esm/platform/node/index.mjs"
24
+ },
25
+ "#console-processor": {
26
+ "source": {
27
+ "browser": "./src/processors/console-stub.ts",
28
+ "default": "./src/processors/console-processor.ts"
29
+ },
30
+ "types": "./dist/types/src/processors/console-processor.d.ts",
31
+ "browser": "./dist/lib/browser/processors/console-stub.mjs",
32
+ "default": "./dist/lib/node-esm/processors/console-processor.mjs"
33
+ }
34
+ },
11
35
  "exports": {
12
36
  ".": {
13
37
  "types": "./dist/types/src/index.d.ts",
@@ -18,10 +42,6 @@
18
42
  }
19
43
  }
20
44
  },
21
- "browser": {
22
- "./src/platform/node/index.ts": "./src/platform/browser/index.ts",
23
- "./src/processors/console-processor.ts": "./src/processors/console-stub.ts"
24
- },
25
45
  "types": "dist/types/src/index.d.ts",
26
46
  "typesVersions": {
27
47
  "*": {}
@@ -31,17 +51,15 @@
31
51
  "src"
32
52
  ],
33
53
  "dependencies": {
34
- "chalk": "^4.1.0",
35
- "js-yaml": "^4.1.0",
54
+ "chalk": "^4.1.2",
55
+ "js-yaml": "4.1.1",
36
56
  "lodash.defaultsdeep": "^4.6.1",
37
- "lodash.omit": "^4.5.0",
38
- "@dxos/node-std": "0.8.4-main.c4373fc",
39
- "@dxos/util": "0.8.4-main.c4373fc"
57
+ "@dxos/node-std": "0.8.4-main.c85a9c8dae",
58
+ "@dxos/util": "0.8.4-main.c85a9c8dae"
40
59
  },
41
60
  "devDependencies": {
42
61
  "@types/js-yaml": "^4.0.5",
43
- "@types/lodash.defaultsdeep": "^4.6.6",
44
- "@types/lodash.omit": "^4.5.7"
62
+ "@types/lodash.defaultsdeep": "^4.6.6"
45
63
  },
46
64
  "publishConfig": {
47
65
  "access": "public"
package/src/config.ts CHANGED
@@ -19,6 +19,7 @@ export enum LogLevel {
19
19
  }
20
20
 
21
21
  export const levels: Record<string, LogLevel> = {
22
+ '*': LogLevel.TRACE,
22
23
  trace: LogLevel.TRACE,
23
24
  debug: LogLevel.DEBUG,
24
25
  verbose: LogLevel.VERBOSE,
package/src/context.ts CHANGED
@@ -27,8 +27,33 @@ export interface LogEntry {
27
27
  */
28
28
  export type LogProcessor = (config: LogConfig, entry: LogEntry) => void;
29
29
 
30
- const matchFilter = (filter: LogFilter, level: LogLevel, path: string) => {
31
- return level >= filter.level && (!filter.pattern || path.includes(filter.pattern));
30
+ /**
31
+ * Returns:
32
+ * true if the log entry matches the filter,
33
+ * false if should be excluded, or
34
+ * undefined if it the filter doesn't match the level.
35
+ */
36
+ const matchFilter = (filter: LogFilter, level: LogLevel, path?: string): boolean | undefined => {
37
+ // TODO(burdon): Support regexp.
38
+ if (filter.pattern?.startsWith('-')) {
39
+ // Exclude.
40
+ if (path?.includes(filter.pattern.slice(1))) {
41
+ if (level >= filter.level) {
42
+ return false;
43
+ }
44
+ }
45
+ } else {
46
+ // Include.
47
+ if (filter.pattern?.length) {
48
+ if (path?.includes(filter.pattern)) {
49
+ return level >= filter.level;
50
+ }
51
+ } else {
52
+ if (level >= filter.level) {
53
+ return true;
54
+ }
55
+ }
56
+ }
32
57
  };
33
58
 
34
59
  /**
@@ -36,10 +61,16 @@ const matchFilter = (filter: LogFilter, level: LogLevel, path: string) => {
36
61
  */
37
62
  export const shouldLog = (entry: LogEntry, filters?: LogFilter[]): boolean => {
38
63
  if (filters === undefined) {
39
- return true;
40
- } else {
41
- return filters.some((filter) => matchFilter(filter, entry.level, entry.meta?.F ?? ''));
64
+ return false;
42
65
  }
66
+
67
+ const results = filters
68
+ .map((filter) => matchFilter(filter, entry.level, entry.meta?.F))
69
+ .filter((result): result is boolean => result !== undefined);
70
+
71
+ // Skip if any are explicitely false.
72
+ // console.log({ level: entry.level, path: entry.meta?.F }, filters, results, results.length);
73
+ return results.length > 0 && !results.some((results) => results === false);
43
74
  };
44
75
 
45
76
  export const getContextFromEntry = (entry: LogEntry): Record<string, any> | undefined => {
package/src/dbg.ts ADDED
@@ -0,0 +1,34 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import { type CallMetadata } from './meta';
6
+ /**
7
+ * Debug-log value to console.
8
+ * Log's the expression being evaluated.
9
+ *
10
+ * If only one argument is provided, it will also be returned.
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * dbg(foo, bar);
15
+ * // foo = 1
16
+ * // bar = 2
17
+ *
18
+ * bar = dbg(foo * 2);
19
+ * // foo * 2 = 2
20
+ * ```
21
+ *
22
+ * NOTE: The second argument is injected by the log transform plugin.
23
+ */
24
+ export const dbg: {
25
+ <T>(value: T, _meta?: CallMetadata): T;
26
+ } = <T>(arg: T, meta?: CallMetadata): T => {
27
+ if (meta?.A) {
28
+ console.log(`${meta.A[0]} =`, arg);
29
+ } else {
30
+ console.log(arg);
31
+ }
32
+
33
+ return arg;
34
+ };
package/src/decorators.ts CHANGED
@@ -6,7 +6,7 @@ import { inspect } from 'node:util';
6
6
 
7
7
  import chalk from 'chalk';
8
8
 
9
- import type { LogMethods } from './log';
9
+ import { type LogMethods } from './log';
10
10
  import { type CallMetadata } from './meta';
11
11
 
12
12
  let nextPromiseId = 0;
@@ -191,13 +191,13 @@ const logAsyncRejected = (
191
191
  );
192
192
  };
193
193
 
194
+ const COLOR_FUNCTION = [220, 220, 170] as const;
195
+
194
196
  // https://github.com/dxos/dxos/issues/7286
195
197
  const greenCheck = typeof chalk.green === 'function' ? chalk.green('✔') : '✔';
196
198
 
197
199
  const formatTimeElapsed = (startTime: number) => chalk.gray(`${(performance.now() - startTime).toFixed(0)}ms`);
198
200
 
199
- const COLOR_FUNCTION = [220, 220, 170] as const;
200
-
201
201
  const formatFunction = (name: string) => chalk.bold(chalk.rgb(...COLOR_FUNCTION)(name));
202
202
 
203
203
  const formatPromise = (id: number) => chalk.blue(`Promise#${id}`);
package/src/index.ts CHANGED
@@ -2,9 +2,7 @@
2
2
  // Copyright 2022 DXOS.org
3
3
  //
4
4
 
5
- import omit from 'lodash.omit';
6
-
7
- import { pick } from '@dxos/util';
5
+ import { omit, pick } from '@dxos/util';
8
6
 
9
7
  export { omit, pick };
10
8
 
@@ -15,5 +13,7 @@ export { parseFilter } from './options';
15
13
  export * from './processors';
16
14
  export * from './scope';
17
15
  export type * from './meta';
16
+ export { dbg } from './dbg';
17
+ export * from './log-buffer';
18
18
 
19
19
  export { getCurrentOwnershipScope } from './experimental/ownership';
@@ -0,0 +1,156 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { describe, test } from 'vitest';
6
+
7
+ import { LogBuffer } from './log-buffer';
8
+
9
+ import { type LogConfig, type LogEntry, LogLevel } from './index';
10
+
11
+ const baseConfig: LogConfig = {
12
+ options: {},
13
+ filters: [{ level: LogLevel.DEBUG }],
14
+ processors: [],
15
+ };
16
+
17
+ const createEntry = (overrides: Partial<LogEntry> = {}): LogEntry => ({
18
+ level: LogLevel.INFO,
19
+ message: 'test message',
20
+ ...overrides,
21
+ });
22
+
23
+ describe('LogBuffer', () => {
24
+ test('pushes and serializes log entries', ({ expect }) => {
25
+ const buffer = new LogBuffer(10);
26
+ buffer.logProcessor(baseConfig, createEntry({ message: 'hello' }));
27
+ buffer.logProcessor(baseConfig, createEntry({ message: 'world' }));
28
+
29
+ expect(buffer.size).toBe(2);
30
+ const lines = buffer.serialize().split('\n');
31
+ expect(lines).toHaveLength(2);
32
+
33
+ const first = JSON.parse(lines[0]);
34
+ expect(first.m).toBe('hello');
35
+ expect(first.l).toBe('I');
36
+ expect(first.t).toBeDefined();
37
+
38
+ const second = JSON.parse(lines[1]);
39
+ expect(second.m).toBe('world');
40
+ });
41
+
42
+ test('evicts oldest entries when buffer is full', ({ expect }) => {
43
+ const buffer = new LogBuffer(3);
44
+ buffer.logProcessor(baseConfig, createEntry({ message: 'a' }));
45
+ buffer.logProcessor(baseConfig, createEntry({ message: 'b' }));
46
+ buffer.logProcessor(baseConfig, createEntry({ message: 'c' }));
47
+ buffer.logProcessor(baseConfig, createEntry({ message: 'd' }));
48
+
49
+ expect(buffer.size).toBe(3);
50
+ const lines = buffer.serialize().split('\n');
51
+ const messages = lines.map((line) => JSON.parse(line).m);
52
+ expect(messages).toEqual(['b', 'c', 'd']);
53
+ });
54
+
55
+ test('skips TRACE-level logs', ({ expect }) => {
56
+ const buffer = new LogBuffer(10);
57
+ buffer.logProcessor(baseConfig, createEntry({ level: LogLevel.TRACE, message: 'trace' }));
58
+ expect(buffer.size).toBe(0);
59
+ });
60
+
61
+ test('captures DEBUG-level and above', ({ expect }) => {
62
+ const buffer = new LogBuffer(10);
63
+ buffer.logProcessor(baseConfig, createEntry({ level: LogLevel.DEBUG, message: 'debug' }));
64
+ buffer.logProcessor(baseConfig, createEntry({ level: LogLevel.WARN, message: 'warn' }));
65
+ buffer.logProcessor(baseConfig, createEntry({ level: LogLevel.ERROR, message: 'error' }));
66
+
67
+ expect(buffer.size).toBe(3);
68
+ const lines = buffer.serialize().split('\n');
69
+ expect(JSON.parse(lines[0]).l).toBe('D');
70
+ expect(JSON.parse(lines[1]).l).toBe('W');
71
+ expect(JSON.parse(lines[2]).l).toBe('E');
72
+ });
73
+
74
+ test('captures file and line metadata', ({ expect }) => {
75
+ const buffer = new LogBuffer(10);
76
+ buffer.logProcessor(
77
+ baseConfig,
78
+ createEntry({
79
+ meta: { F: '/home/user/project/packages/sdk/test.ts', L: 42, S: undefined },
80
+ }),
81
+ );
82
+
83
+ const lines = buffer.serialize().split('\n');
84
+ const record = JSON.parse(lines[0]);
85
+ expect(record.f).toBe('packages/sdk/test.ts');
86
+ expect(record.n).toBe(42);
87
+ });
88
+
89
+ test('captures error stack', ({ expect }) => {
90
+ const buffer = new LogBuffer(10);
91
+ const error = new Error('boom');
92
+ buffer.logProcessor(baseConfig, createEntry({ error }));
93
+
94
+ const lines = buffer.serialize().split('\n');
95
+ const record = JSON.parse(lines[0]);
96
+ expect(record.e).toContain('boom');
97
+ });
98
+
99
+ test('truncates context to 500 chars', ({ expect }) => {
100
+ const buffer = new LogBuffer(10);
101
+ const longValue = 'x'.repeat(1000);
102
+ buffer.logProcessor(baseConfig, createEntry({ context: { data: longValue } }));
103
+
104
+ const lines = buffer.serialize().split('\n');
105
+ const record = JSON.parse(lines[0]);
106
+ expect(record.c).toBeDefined();
107
+ expect(record.c!.length).toBe(500);
108
+ });
109
+
110
+ test('skips Error context objects', ({ expect }) => {
111
+ const buffer = new LogBuffer(10);
112
+ buffer.logProcessor(baseConfig, createEntry({ context: new Error('ctx error') }));
113
+
114
+ const lines = buffer.serialize().split('\n');
115
+ const record = JSON.parse(lines[0]);
116
+ expect(record.c).toBeUndefined();
117
+ });
118
+
119
+ test('handles non-serializable context gracefully', ({ expect }) => {
120
+ const buffer = new LogBuffer(10);
121
+ const circular: Record<string, any> = {};
122
+ circular.self = circular;
123
+ buffer.logProcessor(baseConfig, createEntry({ context: circular }));
124
+
125
+ const lines = buffer.serialize().split('\n');
126
+ const record = JSON.parse(lines[0]);
127
+ expect(record.c).toBeUndefined();
128
+ });
129
+
130
+ test('serialize returns empty string for empty buffer', ({ expect }) => {
131
+ const buffer = new LogBuffer(10);
132
+ expect(buffer.serialize()).toBe('');
133
+ });
134
+
135
+ test('clear discards all entries', ({ expect }) => {
136
+ const buffer = new LogBuffer(10);
137
+ buffer.logProcessor(baseConfig, createEntry({ message: 'a' }));
138
+ buffer.logProcessor(baseConfig, createEntry({ message: 'b' }));
139
+ expect(buffer.size).toBe(2);
140
+
141
+ buffer.clear();
142
+ expect(buffer.size).toBe(0);
143
+ expect(buffer.serialize()).toBe('');
144
+ });
145
+
146
+ test('clear allows new entries', ({ expect }) => {
147
+ const buffer = new LogBuffer(10);
148
+ buffer.logProcessor(baseConfig, createEntry({ message: 'old' }));
149
+ buffer.clear();
150
+ buffer.logProcessor(baseConfig, createEntry({ message: 'new' }));
151
+
152
+ expect(buffer.size).toBe(1);
153
+ const record = JSON.parse(buffer.serialize());
154
+ expect(record.m).toBe('new');
155
+ });
156
+ });
@@ -0,0 +1,108 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { CircularBuffer } from '@dxos/util';
6
+
7
+ import { type LogConfig, LogLevel, shortLevelName } from './config';
8
+ import { type LogEntry, type LogProcessor } from './context';
9
+
10
+ const DEFAULT_BUFFER_SIZE = 2_000;
11
+ const MAX_CONTEXT_LENGTH = 500;
12
+
13
+ /**
14
+ * Compact log record with short property names for small serialized size.
15
+ */
16
+ export type LogRecord = {
17
+ /** ISO timestamp. */
18
+ t: string;
19
+ /** Level letter (D, V, I, W, E). */
20
+ l: string;
21
+ /** Message. */
22
+ m: string;
23
+ /** File path. */
24
+ f?: string;
25
+ /** Line number. */
26
+ n?: number;
27
+ /** Error stack. */
28
+ e?: string;
29
+ /** Context JSON. */
30
+ c?: string;
31
+ };
32
+
33
+ /**
34
+ * Captures recent log entries in a circular buffer for debug log dump.
35
+ */
36
+ export class LogBuffer {
37
+ private readonly _buffer: CircularBuffer<LogRecord>;
38
+
39
+ constructor(size = DEFAULT_BUFFER_SIZE) {
40
+ this._buffer = new CircularBuffer<LogRecord>(size);
41
+ }
42
+
43
+ /** Log processor that can be registered with `log.runtimeConfig.processors`. */
44
+ readonly logProcessor: LogProcessor = (_config: LogConfig, entry: LogEntry) => {
45
+ if (entry.level <= LogLevel.TRACE) {
46
+ return;
47
+ }
48
+
49
+ const record: LogRecord = {
50
+ t: new Date().toISOString(),
51
+ l: shortLevelName[entry.level] ?? '?',
52
+ m: entry.message ?? '',
53
+ };
54
+
55
+ if (entry.meta) {
56
+ record.f = getRelativeFilename(entry.meta.F);
57
+ record.n = entry.meta.L;
58
+ }
59
+
60
+ if (entry.error) {
61
+ record.e = entry.error.stack ?? entry.error.message;
62
+ }
63
+
64
+ if (entry.context != null) {
65
+ try {
66
+ const ctx = typeof entry.context === 'function' ? entry.context() : entry.context;
67
+ if (ctx != null && !(ctx instanceof Error)) {
68
+ let json = JSON.stringify(ctx);
69
+ if (json.length > MAX_CONTEXT_LENGTH) {
70
+ json = json.slice(0, MAX_CONTEXT_LENGTH);
71
+ }
72
+ record.c = json;
73
+ }
74
+ } catch {
75
+ // Skip context that throws or is non-serializable.
76
+ }
77
+ }
78
+
79
+ this._buffer.push(record);
80
+ };
81
+
82
+ /** Number of entries currently in the buffer. */
83
+ get size(): number {
84
+ return this._buffer.elementCount;
85
+ }
86
+
87
+ /** Discard all buffered entries. */
88
+ clear(): void {
89
+ this._buffer.clear();
90
+ }
91
+
92
+ /** Serialize buffer contents as NDJSON (newline-delimited JSON). */
93
+ serialize(): string {
94
+ const lines: string[] = [];
95
+ for (const record of this._buffer) {
96
+ lines.push(JSON.stringify(record));
97
+ }
98
+ return lines.join('\n');
99
+ }
100
+ }
101
+
102
+ const getRelativeFilename = (filename: string): string => {
103
+ const match = filename.match(/.+\/(packages\/.+\/.+)/);
104
+ if (match) {
105
+ return match[1];
106
+ }
107
+ return filename;
108
+ };
package/src/log.test.ts CHANGED
@@ -4,10 +4,11 @@
4
4
 
5
5
  import path from 'node:path';
6
6
 
7
- import { describe, test } from 'vitest';
7
+ import { beforeEach, describe, test } from 'vitest';
8
8
 
9
9
  import { LogLevel } from './config';
10
- import { log } from './log';
10
+ import { shouldLog } from './context';
11
+ import { type Log, createLog } from './log';
11
12
 
12
13
  class LogError extends Error {
13
14
  constructor(
@@ -25,13 +26,52 @@ class LogError extends Error {
25
26
  }
26
27
  }
27
28
 
28
- log.config({
29
- filter: LogLevel.DEBUG,
30
- });
29
+ describe('log', () => {
30
+ let log!: Log;
31
31
 
32
- /* eslint-disable prefer-arrow-functions/prefer-arrow-functions */
32
+ beforeEach(() => {
33
+ log = createLog();
34
+ log.config({
35
+ filter: LogLevel.DEBUG,
36
+ });
37
+ });
38
+
39
+ test('filters', ({ expect }) => {
40
+ const tests = [
41
+ { expected: 0, filter: 'ERROR' },
42
+ { expected: 2, filter: 'INFO' },
43
+ { expected: 1, filter: 'foo:INFO' },
44
+ { expected: 4, filter: 'DEBUG' },
45
+ { expected: 2, filter: 'DEBUG,-foo:*' },
46
+ { expected: 1, filter: 'INFO,-foo:*' },
47
+ { expected: 3, filter: 'DEBUG,-foo:INFO' },
48
+ { expected: 3, filter: 'foo:DEBUG,bar:INFO' },
49
+ ];
50
+
51
+ for (const test of tests) {
52
+ let count = 0;
53
+ const log = createLog();
54
+ const remove = log.addProcessor((config, entry) => {
55
+ if (shouldLog(entry, config.filters)) {
56
+ count++;
57
+ }
58
+ });
59
+ log.config({
60
+ filter: test.filter,
61
+ });
62
+
63
+ console.group(`Filter: "${test.filter}"`);
64
+ log.debug('line 1', {}, { F: 'foo.ts', L: 1, S: undefined });
65
+ log.info('line 2', {}, { F: 'foo.ts', L: 2, S: undefined });
66
+ log.debug('line 3', {}, { F: 'bar.ts', L: 3, S: undefined });
67
+ log.info('line 4', {}, { F: 'bar.ts', L: 4, S: undefined });
68
+ console.groupEnd();
69
+
70
+ expect(count, `Filter: "${test.filter}"`).toBe(test.expected);
71
+ remove();
72
+ }
73
+ });
33
74
 
34
- describe('log', () => {
35
75
  test('throws an error', () => {
36
76
  try {
37
77
  throw new LogError('Test failed', { value: 1 });
@@ -56,16 +96,6 @@ describe('log', () => {
56
96
  }
57
97
  });
58
98
 
59
- test('config', () => {
60
- log.config({
61
- filter: LogLevel.INFO,
62
- });
63
-
64
- log.debug('Debug level log message');
65
- log.info('Info level log message');
66
- log.warn('Warn level log message');
67
- });
68
-
69
99
  test('config file', () => {
70
100
  log.config({
71
101
  file: path.join('packages/common/log/test-config.yml'),
@@ -91,7 +121,7 @@ describe('log', () => {
91
121
  });
92
122
  });
93
123
 
94
- test('error', function () {
124
+ test('error', () => {
95
125
  const myError = new Error('Test error', { cause: new Error('Cause') });
96
126
  log.catch(myError);
97
127
  });