From ea509702b6ed88951a1b7b109b5dc597ee81112d Mon Sep 17 00:00:00 2001 From: Kristóf Marussy Date: Sat, 2 Oct 2021 16:53:46 +0200 Subject: feat(web): add client-side logging support Also modified langauge-web/src/main/js/xtext/ServiceBuilder.js to make sure the new logger is used as soon as xtext is initialized. --- language-web/src/main/js/editor/EditorArea.tsx | 3 +- language-web/src/main/js/editor/EditorStore.ts | 13 ++++++- language-web/src/main/js/global.d.ts | 6 +++ language-web/src/main/js/logging.tsx | 49 ++++++++++++++++++++++++ language-web/src/main/js/xtext/ServiceBuilder.js | 27 +++++++++---- 5 files changed, 87 insertions(+), 11 deletions(-) create mode 100644 language-web/src/main/js/logging.tsx (limited to 'language-web/src/main/js') diff --git a/language-web/src/main/js/editor/EditorArea.tsx b/language-web/src/main/js/editor/EditorArea.tsx index f07a0ad8..531a57c9 100644 --- a/language-web/src/main/js/editor/EditorArea.tsx +++ b/language-web/src/main/js/editor/EditorArea.tsx @@ -15,8 +15,7 @@ export const EditorArea = observer(() => { onChange={(e) => editorStore.updateValue(e.target.value)} ref={fallbackTextarea} className={`problem-fallback-editor cm-s-${editorStore.codeMirrorTheme}`} - > - + /> ); } diff --git a/language-web/src/main/js/editor/EditorStore.ts b/language-web/src/main/js/editor/EditorStore.ts index 1ac2e79f..8b9432dd 100644 --- a/language-web/src/main/js/editor/EditorStore.ts +++ b/language-web/src/main/js/editor/EditorStore.ts @@ -8,8 +8,11 @@ import { import type { IXtextOptions, IXtextServices } from 'xtext/xtext-codemirror'; import type { IEditorChunk } from './editor'; +import { getLogger } from '../logging'; import type { ThemeStore } from '../theme/ThemeStore'; +const log = getLogger('EditorStore'); + const xtextLang = 'problem'; const xtextOptions: IXtextOptions = { @@ -52,12 +55,20 @@ export class EditorStore { xtextServices: observable.ref, initialSelection: false, }); + this.loadChunk(); + } + + private loadChunk(): void { + const loadingStartMillis = Date.now(); + log.info('Requesting editor chunk'); import('./editor').then(({ editorChunk }) => { runInAction(() => { this.chunk = editorChunk; }); + const loadingDurationMillis = Date.now() - loadingStartMillis; + log.info('Loaded editor chunk in', loadingDurationMillis, 'ms'); }).catch((error) => { - console.warn('Error while loading editor', error); + log.error('Error while loading editor', error); }); } diff --git a/language-web/src/main/js/global.d.ts b/language-web/src/main/js/global.d.ts index 39bda7f3..0533a46e 100644 --- a/language-web/src/main/js/global.d.ts +++ b/language-web/src/main/js/global.d.ts @@ -1,3 +1,9 @@ +declare const DEBUG: boolean; + +declare const PACKAGE_NAME: string; + +declare const PACKAGE_VERSION: string; + declare module '*.module.scss' { const cssVariables: { [key in string]?: string }; // eslint-disable-next-line import/no-default-export diff --git a/language-web/src/main/js/logging.tsx b/language-web/src/main/js/logging.tsx new file mode 100644 index 00000000..25f50f19 --- /dev/null +++ b/language-web/src/main/js/logging.tsx @@ -0,0 +1,49 @@ +import styles, { CSPair } from 'ansi-styles'; +import log from 'loglevel'; +import * as prefix from 'loglevel-plugin-prefix'; + +const colors: Record = { + TRACE: styles.magenta, + DEBUG: styles.cyan, + INFO: styles.blue, + WARN: styles.yellow, + ERROR: styles.red, +}; + +prefix.reg(log); + +if (DEBUG) { + log.setLevel(log.levels.DEBUG); +} else { + log.setLevel(log.levels.WARN); +} + +if ('chrome' in window) { + // Only Chromium supports console ANSI escape sequences. + prefix.apply(log, { + format(level, name, timestamp) { + const formattedTimestamp = `${styles.gray.open}[${timestamp.toString()}]${styles.gray.close}`; + const levelColor = colors[level.toUpperCase()] || styles.red; + const formattedLevel = `${levelColor.open}${level}${levelColor.close}`; + const formattedName = `${styles.green.open}(${name || 'root'})${styles.green.close}`; + return `${formattedTimestamp} ${formattedLevel} ${formattedName}`; + }, + }); +} else { + prefix.apply(log, { + template: '[%t] %l (%n)', + }); +} + +const appLogger = log.getLogger(PACKAGE_NAME); + +appLogger.info('Version:', PACKAGE_NAME, PACKAGE_VERSION); +appLogger.info('Debug mode:', DEBUG); + +export function getLoggerFromRoot(name: string | symbol): log.Logger { + return log.getLogger(name); +} + +export function getLogger(name: string | symbol): log.Logger { + return getLoggerFromRoot(`${PACKAGE_NAME}.${name.toString()}`); +} diff --git a/language-web/src/main/js/xtext/ServiceBuilder.js b/language-web/src/main/js/xtext/ServiceBuilder.js index 38b08ecc..57fcb310 100644 --- a/language-web/src/main/js/xtext/ServiceBuilder.js +++ b/language-web/src/main/js/xtext/ServiceBuilder.js @@ -18,10 +18,11 @@ define([ 'xtext/services/ContentAssistService', 'xtext/services/HoverService', 'xtext/services/OccurrencesService', - 'xtext/services/FormattingService' + 'xtext/services/FormattingService', + '../logging', ], function(jQuery, XtextService, LoadResourceService, SaveResourceService, HighlightingService, ValidationService, UpdateService, ContentAssistService, HoverService, OccurrencesService, - FormattingService) { + FormattingService, logging) { /** * Builder class for the Xtext services. @@ -179,12 +180,22 @@ define([ }); } - services.successListeners = []; + const log = logging.getLoggerFromRoot('xtext.XtextService'); + services.successListeners = [function(serviceType, result) { + if (log.getLevel() <= log.levels.TRACE) { + log.trace('service', serviceType, 'request success', JSON.parse(JSON.stringify(result))); + } + }]; services.errorListeners = [function(serviceType, severity, message, requestData) { - if (options.showErrorDialogs) - window.alert('Xtext service \'' + serviceType + '\' failed: ' + message); - else - console.log('Xtext service \'' + serviceType + '\' failed: ' + message); + const messageParts = ['service', serviceType, 'failed:', message || '(no message)']; + if (requestData) { + messageParts.push(JSON.parse(JSON.stringify(requestData))); + } + if (severity === 'warning') { + log.warn(...messageParts); + } else { + log.error(...messageParts); + } }]; } @@ -271,4 +282,4 @@ define([ } return ServiceBuilder; -}); \ No newline at end of file +}); -- cgit v1.2.3-54-g00ecf