Procházet zdrojové kódy

Add a ‘metadata’ log level, and change checkpointing/level setting to use it.

Jason Grout před 5 roky
rodič
revize
5681e840b9

+ 10 - 13
packages/logconsole-extension/src/index.tsx

@@ -45,7 +45,7 @@ const LOG_CONSOLE_PLUGIN_ID = '@jupyterlab/logconsole-extension:plugin';
  * The command IDs used by the plugin.
  */
 namespace CommandIDs {
-  export const addTimestamp = 'logconsole:add-timestamp';
+  export const addCheckpoint = 'logconsole:add-checkpoint';
   export const clear = 'logconsole:clear';
   export const open = 'logconsole:open';
   export const setLevel = 'logconsole:set-level';
@@ -139,9 +139,9 @@ function activateLogConsole(
     logConsoleWidget.title.label = 'Log Console';
     logConsoleWidget.title.iconClass = 'jp-LogConsoleIcon';
 
-    const addTimestampButton = new CommandToolbarButton({
+    const addCheckpointButton = new CommandToolbarButton({
       commands: app.commands,
-      id: CommandIDs.addTimestamp
+      id: CommandIDs.addCheckpoint
     });
 
     const clearButton = new CommandToolbarButton({
@@ -150,8 +150,8 @@ function activateLogConsole(
     });
 
     logConsoleWidget.toolbar.addItem(
-      'lab-log-console-add-timestamp',
-      addTimestampButton
+      'lab-log-console-add-checkpoint',
+      addCheckpointButton
     );
     logConsoleWidget.toolbar.addItem('lab-log-console-clear', clearButton);
 
@@ -199,11 +199,10 @@ function activateLogConsole(
     }
   });
 
-  app.commands.addCommand(CommandIDs.addTimestamp, {
-    label: 'Add Timestamp',
+  app.commands.addCommand(CommandIDs.addCheckpoint, {
+    label: 'Add Checkpoint',
     execute: () => {
-      const logger = loggerRegistry.getLogger(logConsolePanel.source);
-      logger.log({ type: 'html', data: '<hr>', level: 'critical' });
+      logConsolePanel.logger.checkpoint();
     },
     isEnabled: () => logConsolePanel && logConsolePanel.source !== null,
     iconClass: 'jp-AddIcon'
@@ -212,8 +211,7 @@ function activateLogConsole(
   app.commands.addCommand(CommandIDs.clear, {
     label: 'Clear Log',
     execute: () => {
-      const logger = loggerRegistry.getLogger(logConsolePanel.source);
-      logger.clear();
+      logConsolePanel.logger.clear();
     },
     isEnabled: () => logConsolePanel && logConsolePanel.source !== null,
     // TODO: figure out how this jp-clearIcon class should work, analagous to jp-AddIcon
@@ -227,8 +225,7 @@ function activateLogConsole(
   app.commands.addCommand(CommandIDs.setLevel, {
     label: args => `Set Log Level to ${toTitleCase(args.level as string)}`,
     execute: (args: { level: LogLevel }) => {
-      const logger = loggerRegistry.getLogger(logConsolePanel.source);
-      logger.level = args.level;
+      logConsolePanel.logger.level = args.level;
     },
     isEnabled: () => logConsolePanel && logConsolePanel.source !== null
     // TODO: find good icon class

+ 60 - 24
packages/logconsole/src/logger.ts

@@ -22,6 +22,11 @@ import {
   LogLevel
 } from './tokens';
 
+/**
+ * All severity levels, including an internal one for metadata.
+ */
+type FullLogLevel = LogLevel | 'metadata';
+
 /**
  * Custom Notebook Output with log info.
  */
@@ -34,7 +39,7 @@ type ILogOutput = nbformat.IOutput & {
   /**
    * Log level
    */
-  level: LogLevel;
+  level: FullLogLevel;
 };
 
 /**
@@ -62,7 +67,7 @@ export class LogOutputModel extends OutputModel {
   /**
    * Log level
    */
-  level: LogLevel;
+  level: FullLogLevel;
 }
 
 /**
@@ -181,16 +186,23 @@ export class Logger implements ILogger {
    * The level of outputs logged
    */
   get level(): LogLevel {
-    return Private.LogLevel[this._level] as keyof typeof Private.LogLevel;
+    return this._level;
   }
   set level(newValue: LogLevel) {
-    let oldValue = Private.LogLevel[
-      this._level
-    ] as keyof typeof Private.LogLevel;
+    let oldValue = this._level;
     if (oldValue === newValue) {
       return;
     }
-    this._level = Private.LogLevel[newValue];
+    this._level = newValue;
+    this._log({
+      output: {
+        output_type: 'display_data',
+        data: {
+          'text/html': `Log level set to ${newValue}`
+        }
+      },
+      level: 'metadata'
+    });
     this._stateChanged.emit({ name: 'level', oldValue, newValue });
   }
 
@@ -257,12 +269,13 @@ export class Logger implements ILogger {
    */
   log(log: ILogPayload) {
     // Filter by our current log level
-    if (Private.LogLevel[log.level] < this._level) {
+    if (
+      Private.LogLevel[log.level as keyof typeof Private.LogLevel] <
+      Private.LogLevel[this._level as keyof typeof Private.LogLevel]
+    ) {
       return;
     }
-    const timestamp = new Date();
     let output: nbformat.IOutput = null;
-
     switch (log.type) {
       case 'text':
         output = {
@@ -288,20 +301,10 @@ export class Logger implements ILogger {
     }
 
     if (output) {
-      // First, make sure our version reflects the new message so things
-      // triggering from the signals below have the correct version.
-      this._version++;
-
-      // Next, trigger any displays of the message
-      this.outputAreaModel.add({
-        ...output,
-        timestamp: timestamp.valueOf(),
+      this._log({
+        output,
         level: log.level
       });
-
-      // Finally, tell people that the message was appended (and possibly
-      // already displayed).
-      this._contentChanged.emit('append');
     }
   }
 
@@ -313,11 +316,43 @@ export class Logger implements ILogger {
     this._contentChanged.emit('clear');
   }
 
+  /**
+   * Add a checkpoint to the log.
+   */
+  checkpoint() {
+    this._log({
+      output: {
+        output_type: 'display_data',
+        data: {
+          'text/html': '<hr/>'
+        }
+      },
+      level: 'metadata'
+    });
+  }
+
+  private _log(options: { output: nbformat.IOutput; level: FullLogLevel }) {
+    // First, make sure our version reflects the new message so things
+    // triggering from the signals below have the correct version.
+    this._version++;
+
+    // Next, trigger any displays of the message
+    this.outputAreaModel.add({
+      ...options.output,
+      timestamp: Date.now(),
+      level: options.level
+    });
+
+    // Finally, tell people that the message was appended (and possibly
+    // already displayed).
+    this._contentChanged.emit('append');
+  }
+
   private _contentChanged = new Signal<this, IContentChange>(this);
   private _stateChanged = new Signal<this, IStateChange>(this);
   private _rendermime: IRenderMimeRegistry | null = null;
   private _version = 0;
-  private _level: Private.LogLevel = Private.LogLevel.warning;
+  private _level: LogLevel = 'warning';
 }
 
 export namespace Logger {
@@ -339,6 +374,7 @@ namespace Private {
     info,
     warning,
     error,
-    critical
+    critical,
+    metadata
   }
 }

+ 4 - 0
packages/logconsole/src/tokens.ts

@@ -177,6 +177,10 @@ export interface ILogger {
    * @param log - The output to be logged.
    */
   log(log: ILogPayload): void;
+  /**
+   * Add a checkpoint in the log.
+   */
+  checkpoint(): void;
   /**
    * Clear all outputs logged.
    */

+ 6 - 1
packages/logconsole/src/widget.ts

@@ -30,6 +30,11 @@ function toTitleCase(value: string) {
   return value.length === 0 ? value : value[0].toUpperCase() + value.slice(1);
 }
 
+/**
+ * All severity levels, including an internal one for metadata.
+ */
+type FullLogLevel = LogLevel | 'metadata';
+
 /**
  * Log console output prompt implementation
  */
@@ -55,7 +60,7 @@ class LogConsoleOutputPrompt extends Widget implements IOutputPrompt {
   /**
    * Log level
    */
-  set level(value: LogLevel) {
+  set level(value: FullLogLevel) {
     this.node.dataset.logLevel = value;
     this.node.title = `${toTitleCase(value)} message`;
   }