Skip to content

Commit d23213c

Browse files
authored
Add a setting to configure the default log level for the Log Console (jupyterlab#17547)
* Add a setting to configure the default log level * docstrings * tweaks * Translatable settings * add test
1 parent 060d850 commit d23213c

File tree

5 files changed

+110
-3
lines changed

5 files changed

+110
-3
lines changed

packages/logconsole-extension/schema/plugin.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,19 @@
3939
"title": "Status Bar Item flash",
4040
"description": "Whether to flash on new log message or not",
4141
"default": true
42+
},
43+
"defaultLogLevel": {
44+
"type": "string",
45+
"title": "Default Log Level",
46+
"description": "Default log level for loggers",
47+
"oneOf": [
48+
{ "const": "critical", "title": "Critical" },
49+
{ "const": "error", "title": "Error" },
50+
{ "const": "warning", "title": "Warning" },
51+
{ "const": "info", "title": "Info" },
52+
{ "const": "debug", "title": "Debug" }
53+
],
54+
"default": "warning"
4255
}
4356
},
4457
"additionalProperties": false,

packages/logconsole-extension/src/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,8 @@ function activateLogConsole(
298298
loggerRegistry.maxLength = settings.get('maxLogEntries')
299299
.composite as number;
300300
status.model.flashEnabled = settings.get('flash').composite as boolean;
301+
loggerRegistry.defaultLogLevel = settings.get('defaultLogLevel')
302+
.composite as LogLevel;
301303
};
302304

303305
Promise.all([settingRegistry.load(LOG_CONSOLE_PLUGIN_ID), app.restored])

packages/logconsole/src/logger.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ export class Logger implements ILogger {
201201
contentFactory: new LogConsoleModelContentFactory(),
202202
maxLength: options.maxLength
203203
});
204+
this._level = options.level ?? 'warning';
204205
}
205206

206207
/**
@@ -408,10 +409,16 @@ export class Logger implements ILogger {
408409
private _stateChanged = new Signal<this, IStateChange>(this);
409410
private _rendermime: IRenderMimeRegistry | null = null;
410411
private _version = 0;
411-
private _level: LogLevel = 'warning';
412+
private _level: LogLevel;
412413
}
413414

415+
/**
416+
* The namespace for Logger class statics.
417+
*/
414418
export namespace Logger {
419+
/**
420+
* The options used to initialize a Logger.
421+
*/
415422
export interface IOptions {
416423
/**
417424
* The log source identifier.
@@ -421,10 +428,20 @@ export namespace Logger {
421428
* The maximum number of messages to store.
422429
*/
423430
maxLength: number;
431+
/**
432+
* The default log level.
433+
*/
434+
level?: LogLevel;
424435
}
425436
}
426437

438+
/**
439+
* The namespace for Logger class private statics.
440+
*/
427441
namespace Private {
442+
/**
443+
* The log level enum.
444+
*/
428445
export enum LogLevel {
429446
debug,
430447
info,

packages/logconsole/src/registry.ts

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,12 @@
44
import { IRenderMimeRegistry } from '@jupyterlab/rendermime';
55
import { ISignal, Signal } from '@lumino/signaling';
66
import { Logger } from './logger';
7-
import { ILogger, ILoggerRegistry, ILoggerRegistryChange } from './tokens';
7+
import {
8+
ILogger,
9+
ILoggerRegistry,
10+
ILoggerRegistryChange,
11+
LogLevel
12+
} from './tokens';
813

914
/**
1015
* A concrete implementation of ILoggerRegistry.
@@ -19,6 +24,7 @@ export class LoggerRegistry implements ILoggerRegistry {
1924
constructor(options: LoggerRegistry.IOptions) {
2025
this._defaultRendermime = options.defaultRendermime;
2126
this._maxLength = options.maxLength;
27+
this._defaultLogLevel = options.defaultLogLevel ?? 'warning';
2228
}
2329

2430
/**
@@ -35,7 +41,11 @@ export class LoggerRegistry implements ILoggerRegistry {
3541
return logger;
3642
}
3743

38-
logger = new Logger({ source, maxLength: this.maxLength });
44+
logger = new Logger({
45+
source,
46+
maxLength: this.maxLength,
47+
level: this.defaultLogLevel
48+
});
3949
logger.rendermime = this._defaultRendermime;
4050
loggers.set(source, logger);
4151

@@ -73,6 +83,17 @@ export class LoggerRegistry implements ILoggerRegistry {
7383
});
7484
}
7585

86+
/**
87+
* The default log level for new loggers.
88+
* The new value will be applied to new loggers only.
89+
*/
90+
get defaultLogLevel(): LogLevel {
91+
return this._defaultLogLevel;
92+
}
93+
set defaultLogLevel(value: LogLevel) {
94+
this._defaultLogLevel = value;
95+
}
96+
7697
/**
7798
* Whether the register is disposed.
7899
*/
@@ -95,13 +116,31 @@ export class LoggerRegistry implements ILoggerRegistry {
95116
private _defaultRendermime: IRenderMimeRegistry;
96117
private _loggers = new Map<string, ILogger>();
97118
private _maxLength: number;
119+
private _defaultLogLevel: LogLevel;
98120
private _registryChanged = new Signal<this, ILoggerRegistryChange>(this);
99121
private _isDisposed = false;
100122
}
101123

124+
/**
125+
* The namespace for LoggerRegistry class statics.
126+
*/
102127
export namespace LoggerRegistry {
128+
/**
129+
* The options used to initialize a LoggerRegistry.
130+
*/
103131
export interface IOptions {
132+
/**
133+
* The default rendermime to render outputs with when logger is not
134+
* supplied with one.
135+
*/
104136
defaultRendermime: IRenderMimeRegistry;
137+
/**
138+
* The maximum length of the log messages.
139+
*/
105140
maxLength: number;
141+
/**
142+
* The default log level for the loggers.
143+
*/
144+
defaultLogLevel?: LogLevel;
106145
}
107146
}

packages/logconsole/test/registry.spec.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,20 @@ describe('LoggerRegistry', () => {
4343
expect(registry).toBeInstanceOf(LoggerRegistry);
4444
expect(registry.maxLength).toBe(10);
4545
});
46+
47+
it('should use "warning" as the default log level if not specified', () => {
48+
expect(registry.defaultLogLevel).toBe('warning');
49+
});
50+
51+
it('should use the provided default log level if specified', () => {
52+
const customRegistry = new LoggerRegistry({
53+
defaultRendermime,
54+
maxLength: 10,
55+
defaultLogLevel: 'info'
56+
});
57+
expect(customRegistry.defaultLogLevel).toBe('info');
58+
customRegistry.dispose();
59+
});
4660
});
4761

4862
describe('#getLogger()', () => {
@@ -85,4 +99,26 @@ describe('LoggerRegistry', () => {
8599
expect(B.maxLength).toEqual(12);
86100
});
87101
});
102+
103+
describe('#defaultLogLevel', () => {
104+
it('should be applied to newly created loggers', () => {
105+
const A = registry.getLogger('A');
106+
expect(A.level).toBe(registry.defaultLogLevel);
107+
});
108+
109+
it('should only affect loggers created after it is changed', () => {
110+
const A = registry.getLogger('A');
111+
expect(A.level).toBe('warning');
112+
113+
registry.defaultLogLevel = 'info';
114+
expect(registry.defaultLogLevel).toBe('info');
115+
116+
// A's level should not be changed
117+
expect(A.level).toBe('warning');
118+
119+
// B should get the new default
120+
const B = registry.getLogger('B');
121+
expect(B.level).toBe('info');
122+
});
123+
});
88124
});

0 commit comments

Comments
 (0)