diff --git a/extensions/vertx-http/deployment/src/main/java/io/quarkus/devui/deployment/BuildTimeContentProcessor.java b/extensions/vertx-http/deployment/src/main/java/io/quarkus/devui/deployment/BuildTimeContentProcessor.java index d8d98ded82555..e95d614d3389a 100644 --- a/extensions/vertx-http/deployment/src/main/java/io/quarkus/devui/deployment/BuildTimeContentProcessor.java +++ b/extensions/vertx-http/deployment/src/main/java/io/quarkus/devui/deployment/BuildTimeContentProcessor.java @@ -1,5 +1,20 @@ package io.quarkus.devui.deployment; +import static java.util.logging.Level.ALL; +import static java.util.logging.Level.CONFIG; +import static java.util.logging.Level.FINE; +import static java.util.logging.Level.FINER; +import static java.util.logging.Level.FINEST; +import static java.util.logging.Level.OFF; +import static java.util.logging.Level.SEVERE; +import static java.util.logging.Level.WARNING; +import static org.jboss.logmanager.Level.DEBUG; +import static org.jboss.logmanager.Level.ERROR; +import static org.jboss.logmanager.Level.FATAL; +import static org.jboss.logmanager.Level.INFO; +import static org.jboss.logmanager.Level.TRACE; +import static org.jboss.logmanager.Level.WARN; + import java.io.IOException; import java.io.InputStream; import java.io.UncheckedIOException; @@ -411,6 +426,7 @@ private void addFooterTabBuildTimeData(BuildTimeConstBuildItem internalBuildTime } internalBuildTimeData.addBuildTimeData("footerTabs", footerTabs); + internalBuildTimeData.addBuildTimeData("loggerLevels", LEVELS); } private void addVersionInfoBuildTimeData(BuildTimeConstBuildItem internalBuildTimeData, @@ -426,6 +442,22 @@ private void addVersionInfoBuildTimeData(BuildTimeConstBuildItem internalBuildTi internalBuildTimeData.addBuildTimeData("applicationInfo", applicationInfo); } + private static final List LEVELS = List.of( + OFF.getName(), + SEVERE.getName(), + ERROR.getName(), + FATAL.getName(), + WARNING.getName(), + WARN.getName(), + INFO.getName(), + DEBUG.getName(), + TRACE.getName(), + CONFIG.getName(), + FINE.getName(), + FINER.getName(), + FINEST.getName(), + ALL.getName()); + private static void computeColors(Map> themes, Map dark, Map light) { // Quarkus logo colors diff --git a/extensions/vertx-http/dev-ui-resources/src/main/resources/dev-ui/qwc/qwc-server-log.js b/extensions/vertx-http/dev-ui-resources/src/main/resources/dev-ui/qwc/qwc-server-log.js index 2396d0ee7c2a7..9f1d10ffe35cc 100644 --- a/extensions/vertx-http/dev-ui-resources/src/main/resources/dev-ui/qwc/qwc-server-log.js +++ b/extensions/vertx-http/dev-ui-resources/src/main/resources/dev-ui/qwc/qwc-server-log.js @@ -5,10 +5,16 @@ import { JsonRpc } from 'jsonrpc'; import { unsafeHTML } from 'lit-html/directives/unsafe-html.js'; import '@vaadin/icon'; import '@vaadin/dialog'; +import '@vaadin/select'; import '@vaadin/checkbox'; import '@vaadin/checkbox-group'; import { dialogHeaderRenderer, dialogRenderer } from '@vaadin/dialog/lit.js'; import 'qui-badge'; +import '@vaadin/grid'; +import { columnBodyRenderer } from '@vaadin/grid/lit.js'; +import '@vaadin/grid/vaadin-grid-sort-column.js'; +import '@vaadin/vertical-layout'; +import { loggerLevels } from 'devui-data'; /** * This component represent the Server Log @@ -73,13 +79,6 @@ export class QwcServerLog extends QwcHotReloadElement { color: var(--lumo-success-color-50pct); } - .columnsDialog{ - - } - - .levelsDialog{ - - } `; static properties = { @@ -91,10 +90,22 @@ export class QwcServerLog extends QwcHotReloadElement { _levelsDialogOpened: {state: true}, _columnsDialogOpened: {state: true}, _selectedColumns: {state: true}, + _allLoggers: {state: true, type: Array}, + _filteredLoggers: {state: true, type: Array}, + _loggerLevels: {state: false, type: Array} }; constructor() { super(); + this._loggerLevels = []; + for (let i in loggerLevels) { + let loggerLevel = loggerLevels[i]; + this._loggerLevels.push({ + 'label': loggerLevel, + 'value': loggerLevel, + }); + } + this.logControl .addToggle("On/off switch", true, (e) => { this._toggleOnOffClicked(e); @@ -129,6 +140,7 @@ export class QwcServerLog extends QwcHotReloadElement { this._addLogEntry(entry); }); }); + this._loadAllLoggers(); } disconnectedCallback() { @@ -136,11 +148,20 @@ export class QwcServerLog extends QwcHotReloadElement { this._toggleOnOff(false); } + _loadAllLoggers(){ + this.jsonRpc.getLoggers().then(jsonRpcResponse => { + this._allLoggers = jsonRpcResponse.result; + this._filteredLoggers = this._allLoggers; + }); + } + render() { - - return html` + if(this._filteredLoggers){ + return html` html` @@ -154,6 +175,8 @@ export class QwcServerLog extends QwcHotReloadElement { > html` @@ -176,7 +199,7 @@ export class QwcServerLog extends QwcHotReloadElement { ` )} `; - + } } _renderLogEntry(message){ @@ -379,11 +402,80 @@ export class QwcServerLog extends QwcHotReloadElement { } _renderLevelsDialog(){ - return html` - Hello levels - `; + if(this._filteredLoggers){ + return html` + + + + + + + + + + + + + `; + } } + _filterLoggers(e) { + const searchTerm = (e.detail.value || '').trim(); + if (searchTerm === '') { + this._filteredLoggers = this._allLoggers; + return; + } + + this._filteredLoggers = this._allLoggers.filter((level) => { + let i = this._matchLogger(level.name, searchTerm); + return i; + }); + } + + _matchLogger(value, term) { + if (!value) { + return false; + } + return value.toLowerCase().includes(term.toLowerCase()); + } + + _logLevelRenderer(logger){ + return html`${this._renderSelect(logger.name, logger.effectiveLevel)}`; + } + + _renderSelect(loggerName, loggerLevel){ + return html` + `; + } + + _logLevelSelectChanged(event){ + let name = event.target.id; + this._updateLogLevel(name, event.target.value); + } + + _updateLogLevel(name, value){ + this.jsonRpc.updateLogLevel({ + 'loggerName': name, + 'levelValue': value + }); + } + _renderColumnsDialog(){ return html` streamLog() { return logStreamBroadcaster.getLogStream(); } + @NonBlocking + public List getLoggers() { + LogContext logContext = LogContext.getLogContext(); + List values = new ArrayList<>(); + Enumeration loggerNames = logContext.getLoggerNames(); + while (loggerNames.hasMoreElements()) { + String loggerName = loggerNames.nextElement(); + JsonObject jsonObject = getLogger(loggerName); + if (jsonObject != null) { + values.add(jsonObject); + } + } + return values; + } + + @NonBlocking + public JsonObject getLogger(String loggerName) { + LogContext logContext = LogContext.getLogContext(); + if (loggerName != null && !loggerName.isEmpty()) { + Logger logger = logContext.getLogger(loggerName); + return JsonObject.of( + "name", loggerName, + "effectiveLevel", getEffectiveLogLevel(logger), + "configuredLevel", getConfiguredLogLevel(logger)); + } + return null; + } + + @NonBlocking + public JsonObject updateLogLevel(String loggerName, String levelValue) { + LogContext logContext = LogContext.getLogContext(); + Logger logger = logContext.getLogger(loggerName); + java.util.logging.Level level; + if (levelValue == null || levelValue.isBlank()) { + if (logger.getParent() != null) { + level = logger.getParent().getLevel(); + } else { + throw new IllegalArgumentException("The level of the root logger cannot be set to null"); + } + } else { + level = Level.parse(levelValue); + } + logger.setLevel(level); + LOG.info("Log level updated [" + loggerName + "] changed to [" + levelValue + "]"); + + return getLogger(loggerName); + } + + private String getConfiguredLogLevel(Logger logger) { + java.util.logging.Level level = logger.getLevel(); + return level != null ? level.getName() : null; + } + + private String getEffectiveLogLevel(Logger logger) { + if (logger == null) { + return null; + } + if (logger.getLevel() != null) { + return logger.getLevel().getName(); + } + return getEffectiveLogLevel(logger.getParent()); + } }