Skip to content

Commit

Permalink
Merge pull request quarkusio#15024 from phillip-kruger/dev-ui-log-str…
Browse files Browse the repository at this point in the history
…eam-updates

Small Dev-UI logstream changes to allow for better reuse
  • Loading branch information
gastaldi committed Feb 12, 2021
2 parents f0af7ce + 10a2b2a commit 9170b6f
Show file tree
Hide file tree
Showing 8 changed files with 345 additions and 86 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@
top: 0px;
}

#logstreamManagerNavAppInfo, #logstreamManagerNavBrand {
display: none;
}

#logstreamViewLogButton, #logstreamHideLogButton {
color: #9a9da0;
font-size:0.73em;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,22 @@
var myself = $('script[src*=logstream]');

// Get the non application root path
var frameworkRootPath = myself.attr('data-frameworkRootPath');
if (typeof frameworkRootPath === "undefined" ) {
var pathname = window.location.pathname;
var frameworkRootPath = pathname.substr(0, pathname.indexOf('/dev/'));
}
// Get the streaming path
var streamingPath = myself.attr('data-streamingPath');
if (typeof streamingPath === "undefined" ) {
var streamingPath = "/dev/logstream";
}
// See if we should show on start
var showOnStart = myself.attr('data-showOnStart');
if (typeof showOnStart === "undefined" ) {
var showOnStart = false;
}

var zoom = 0.90;
var linespace = 1.00;
var tabspace = 1;
Expand All @@ -15,7 +34,9 @@ var filter = "";
var localstoragekey = "quarkus_logging_manager_state";

$('document').ready(function () {
hideLog();
if(!showOnStart){
hideLog();
}
loadSettings();

openSocket();
Expand Down Expand Up @@ -616,15 +637,14 @@ function openSocket() {
return;
}
// Create a new instance of the websocket
var loc = window.location, new_uri;
if (loc.protocol === "https:") {
var new_uri;
if (window.location.protocol === "https:") {
new_uri = "wss:";
} else {
new_uri = "ws:";
}
var pathname = loc.pathname;
var devpath = pathname.substr(0, pathname.indexOf('/dev/'));
new_uri += "//" + loc.host + devpath + "/dev/logstream";

new_uri += "//" + window.location.host + frameworkRootPath + streamingPath;
webSocket = new WebSocket(new_uri);

webSocket.onmessage = function (event) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<div id="logstreamManagerLog">
<a id="logstreamInformationSection"></a>
<a id="logstreamFollowLogButton" data-toggle="tooltip" data-placement="left" title="Follow log (auto scroll)"><i id="logstreamFollowLogButtonIcon" class="text-success fas fa-circle-notch fa-spin"></i></a>
<div id="logstreamLogTerminal" class="bg-dark text-light ">
<samp id="logstreamLogTerminalText" class="text-wrap">
</samp>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
<!-- Filter -->
<div class="modal fade" id="logstreamFilterModal" tabindex="-1" aria-labelledby="logstreamFilterModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog modal-dialog-centered modal-sl">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="logstreamFilterModalLabel">Filter</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="logstreamFilterModalInputIcon"><i class="fas fa-filter"></i></span>
</div>
<input id="logstreamFilterModalInput" type="text" class="form-control" placeholder="Filter log" aria-label="Filter" aria-describedby="logstreamFilterModalInputIcon">
<div class="input-group-append">
<button id="logstreamFilterModalInputButton" type="button" class="btn btn-success">Apply</button>
</div>
</div>
</div>
</div>
</div>
</div>

<!-- Levels -->
<div class="modal fade" id="logstreamLogLevelsModal" tabindex="-1" aria-labelledby="logstreamLogLevelsModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-dialog-scrollable modal-xl">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="logstreamLogLevelsModalLabel">Log Levels</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<table class="table table-hover table-sm">
<tbody id="logstreamLogLevelsModalTableBody">
</tbody>
</table>
</div>
</div>
</div>
</div>

<!-- Columns -->
<div class="modal fade" id="logstreamColumnsModal" tabindex="-1" aria-labelledby="logstreamColumnsModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-sm">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="logstreamColumnsModalLabel">Columns</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="custom-control custom-switch">
<input checked type="checkbox" class="custom-control-input" id="logstreamColumnsModalLevelIconSwitch">
<label class="custom-control-label" for="logstreamColumnsModalLevelIconSwitch">Log Level Icon</label>
</div>

<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" id="logstreamColumnsModalSequenceNumberSwitch">
<label class="custom-control-label" for="logstreamColumnsModalSequenceNumberSwitch">Sequence Number</label>
</div>

<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" id="logstreamColumnsModalHostNameSwitch">
<label class="custom-control-label" for="logstreamColumnsModalHostNameSwitch">Host Name</label>
</div>

<div class="custom-control custom-switch">
<input checked type="checkbox" class="custom-control-input" id="logstreamColumnsModalDateSwitch">
<label class="custom-control-label" for="logstreamColumnsModalDateSwitch">Date</label>
</div>

<div class="custom-control custom-switch">
<input checked type="checkbox" class="custom-control-input" id="logstreamColumnsModalTimeSwitch">
<label class="custom-control-label" for="logstreamColumnsModalTimeSwitch">Time</label>
</div>

<div class="custom-control custom-switch">
<input checked type="checkbox" class="custom-control-input" id="logstreamColumnsModalLevelSwitch">
<label class="custom-control-label" for="logstreamColumnsModalLevelSwitch">Log Level</label>
</div>

<div class="custom-control custom-switch">
<input checked type="checkbox" class="custom-control-input" id="logstreamColumnsModalLoggerNameAbbreviatedSwitch">
<label class="custom-control-label" for="logstreamColumnsModalLoggerNameAbbreviatedSwitch">Logger Name (Abbreviated)</label>
</div>

<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" id="logstreamColumnsModalLoggerNameSwitch">
<label class="custom-control-label" for="logstreamColumnsModalLoggerNameSwitch">Logger Name</label>
</div>

<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" id="logstreamColumnsModalLoggerClassNameSwitch">
<label class="custom-control-label" for="logstreamColumnsModalLoggerClassNameSwitch">Logger Class Name</label>
</div>

<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" id="logstreamColumnsModalSourceClassFullAbbreviatedSwitch">
<label class="custom-control-label" for="logstreamColumnsModalSourceClassFullAbbreviatedSwitch">Full Class Name (Abbreviated)</label>
</div>

<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" id="logstreamColumnsModalSourceClassFullSwitch">
<label class="custom-control-label" for="logstreamColumnsModalSourceClassFullSwitch">Full Class Name</label>
</div>

<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" id="logstreamColumnsModalSourceClassSwitch">
<label class="custom-control-label" for="logstreamColumnsModalSourceClassSwitch">Class Name</label>
</div>

<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" id="logstreamColumnsModalSourceMethodNameSwitch">
<label class="custom-control-label" for="logstreamColumnsModalSourceMethodNameSwitch">Method Name</label>
</div>

<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" id="logstreamColumnsModalSourceFileNameSwitch">
<label class="custom-control-label" for="logstreamColumnsModalSourceFileNameSwitch">File Name</label>
</div>

<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" id="logstreamColumnsModalSourceLineNumberSwitch">
<label class="custom-control-label" for="logstreamColumnsModalSourceLineNumberSwitch">Line Number</label>
</div>

<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" id="logstreamColumnsModalProcessIdSwitch">
<label class="custom-control-label" for="logstreamColumnsModalProcessIdSwitch">Process Id</label>
</div>

<div class="custom-control custom-switch">
<input checked type="checkbox" class="custom-control-input" id="logstreamColumnsModalProcessNameSwitch">
<label class="custom-control-label" for="logstreamColumnsModalProcessNameSwitch">Process Name</label>
</div>

<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" id="logstreamColumnsModalThreadIdSwitch">
<label class="custom-control-label" for="logstreamColumnsModalThreadIdSwitch">Thread Id</label>
</div>

<div class="custom-control custom-switch">
<input checked type="checkbox" class="custom-control-input" id="logstreamColumnsModalThreadNameSwitch">
<label class="custom-control-label" for="logstreamColumnsModalThreadNameSwitch">Thread Name</label>
</div>

<div class="custom-control custom-switch">
<input checked type="checkbox" class="custom-control-input" id="logstreamColumnsModalMessageSwitch">
<label class="custom-control-label" for="logstreamColumnsModalMessageSwitch">Log message</label>
</div>

</div>
</div>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<nav id="logstreamManagerNav" class="navbar position-sticky navbar-expand-lg navbar-dark bg-dark">
<a id="logstreamManagerNavBrand" class="navbar-brand" href="">
<img src="{frameworkRootPath}/dev/resources/images/quarkus_icon_rgb_reverse.svg" width="40" height="30" class="d-inline-block align-middle" alt="Quarkus"/>
<span id="navbar_title" class="align-middle">Logging manager</span>
</a>
<div class="collapse navbar-collapse" id="logstreamManagerNavText">
<ul class="navbar-nav mr-auto">
<li class="nav-item" data-toggle="tooltip" data-placement="bottom" title="Stop log stream">
<a id="logstreamStopStartButton" class="logstreamIcon nav-link"><i class="fas fa-stop"></i></a>
</li>
<li class="nav-item" data-toggle="tooltip" data-placement="bottom" title="Clear log">
<a id="logstreamClearLogButton" class="logstreamIcon nav-link"><i class="fas fa-trash-alt"></i></a>
</li>
<li class="nav-item" data-toggle="tooltip" data-placement="bottom" title="Zoom out">
<a id="logstreamZoomOutButton" class="logstreamIcon nav-link"><i class="fas fa-search-minus"></i></a>
</li>
<li class="nav-item" data-toggle="tooltip" data-placement="bottom" title="Zoom in">
<a id="logstreamZoomInButton" class="logstreamIcon nav-link"><i class="fas fa-search-plus"></i></a>
</li>
<li class="nav-item" data-toggle="tooltip" data-placement="bottom" title="Log levels">
<a id="logstreamLogLevelsButton" class="logstreamIcon nav-link" data-toggle="modal" data-target="#logstreamLogLevelsModal"><i class="fas fa-layer-group"></i></a>
</li>
<li class="nav-item" data-toggle="tooltip" data-placement="bottom" title="Columns">
<a id="logstreamColumnsButton" class="logstreamIcon nav-link" data-toggle="modal" data-target="#logstreamColumnsModal"><i class="fas fa-columns"></i></a>
</li>
<li class="nav-item" data-toggle="tooltip" data-placement="bottom" title="Filter">
<a id="logstreamFilterButton" class="logstreamIcon nav-link" data-toggle="modal" data-target="#logstreamFilterModal"><i class="fas fa-filter"></i></a>
</li>
<li id="logstreamCurrentFilter" class="navbar-text">
</li>
<li id="logstreamResizeButton" class="nav-item"><a class="nav-link"><i class="fas fa-arrows-alt-v"></i></a></li>
<li id="logstreamHideLogButton" class="nav-item" data-toggle="tooltip" data-placement="left" title="Hide Log"><a class="logstreamIcon nav-link" onclick="hideLog();"><i class="fas fa-caret-down fa-lg"></i></a></li>
</ul>
</div>
<span id="logstreamManagerNavAppInfo" class="navbar-text">
{applicationName} {applicationVersion} (powered by Quarkus {quarkusVersion})
</span>
</nav>
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,17 @@
{#insert body/}
</div>

{#include logmanager}{/include}
<div id="logstreamFooter" class="footer fixed-bottom">

<button id="logstreamViewLogButton" type="button" class="btn float-right" onclick="showLog();">
<i id="logstreamViewLogButtonIcon" class="fas fa-caret-up fa-lg" data-toggle='tooltip' data-placement='left' title='Show Log'></i>
</button>
<div id="logstreamManager">
{#include logmanagerNav}{/include}
{#include logmanagerLog}{/include}
</div>
</div>
{#include logmanagerModals}{/include}

<script src="{frameworkRootPath}/dev/resources/js/jquery.min.js"></script>
<script src="{frameworkRootPath}/dev/resources/js/bootstrap.bundle.min.js"></script>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package io.quarkus.vertx.http.runtime.logstream;

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.INFO;
import static java.util.logging.Level.OFF;
import static java.util.logging.Level.SEVERE;
import static java.util.logging.Level.WARNING;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.TreeMap;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.Logger;

import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;

/**
* Allow controlling to the log levels
*/
public class LogController {

public JsonArray getLevels() {
return new JsonArray()
.add(OFF.getName())
.add(SEVERE.getName())
.add(WARNING.getName())
.add(INFO.getName())
.add(CONFIG.getName())
.add(FINE.getName())
.add(FINER.getName())
.add(FINEST.getName())
.add(ALL.getName());
}

public JsonArray getLoggers() {
TreeMap<String, JsonObject> loggerMap = new TreeMap<>();
LogManager manager = LogManager.getLogManager();
Enumeration<String> loggerNames = manager.getLoggerNames();
while (loggerNames.hasMoreElements()) {
String loggerName = loggerNames.nextElement();
JsonObject jsonObject = getLogger(loggerName);
if (jsonObject != null) {
loggerMap.put(loggerName, jsonObject);
}
}

List<JsonObject> orderedLoggers = new ArrayList<>(loggerMap.values());
JsonArray jsonArray = new JsonArray(orderedLoggers);
return jsonArray;
}

public JsonObject getLogger(String loggerName) {
if (loggerName != null && !loggerName.isEmpty()) {
Logger logger = Logger.getLogger(loggerName);
JsonObject jsonObject = new JsonObject();
jsonObject.put("name", loggerName);
jsonObject.put("effectiveLevel", getEffectiveLogLevel(logger));
jsonObject.put("configuredLevel", getConfiguredLogLevel(logger));
return jsonObject;
}
return null;
}

public void updateLogLevel(String loggerName, String levelVal) {
Logger logger = Logger.getLogger(loggerName);
if (logger != null) {
Level level = Level.parse(levelVal);
logger.setLevel(level);
}
}

private String getConfiguredLogLevel(Logger logger) {
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());
}
}
Loading

0 comments on commit 9170b6f

Please sign in to comment.