mirror of
https://github.com/tobychui/zoraxy.git
synced 2025-06-03 06:07:20 +02:00
287 lines
9.7 KiB
HTML
287 lines
9.7 KiB
HTML
<!DOCTYPE html>
|
|
<html ng-app="App">
|
|
<head>
|
|
<title>System Logs</title>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0 user-scalable=no">
|
|
<link rel="stylesheet" href="../script/semantic/semantic.min.css">
|
|
<script type="text/javascript" src="../script/jquery-3.6.0.min.js"></script>
|
|
<script type="text/javascript" src="../script/semantic/semantic.min.js"></script>
|
|
<style>
|
|
.clickable{
|
|
cursor: pointer;
|
|
}
|
|
.clickable:hover{
|
|
opacity: 0.7;
|
|
}
|
|
.logfile{
|
|
padding-left: 1em !important;
|
|
position: relative;
|
|
padding-right: 1em !important;
|
|
}
|
|
|
|
.loglist{
|
|
background-color: rgb(250, 250, 250);
|
|
}
|
|
|
|
.logfile .showing{
|
|
position: absolute;
|
|
top: 0.18em;
|
|
right: 0em;
|
|
margin-right: -0.4em;
|
|
opacity: 0;
|
|
}
|
|
|
|
.logfile.active .showing{
|
|
opacity: 1;
|
|
}
|
|
|
|
#logrender{
|
|
width: 100% !important;
|
|
height: calc(100% - 1.2em);
|
|
min-height: calc(90vh - 1.2em) !important;
|
|
border: 0px solid transparent !important;
|
|
background-color: #252630;
|
|
color: white;
|
|
font-family: monospace;
|
|
overflow-x: scroll !important;
|
|
white-space: pre;
|
|
resize: none;
|
|
scrollbar-width: thin;
|
|
font-size: 1.2em;
|
|
}
|
|
|
|
#logrender::selection{
|
|
background:#3643bb;
|
|
color:white;
|
|
}
|
|
|
|
body.darkTheme .loglist {
|
|
background-color: #1b1c1d;
|
|
color: #ffffff;
|
|
}
|
|
|
|
body.darkTheme .loglist .ui.header .content .sub.header {
|
|
color: #bbbbbb;
|
|
}
|
|
|
|
body.darkTheme .loglist .ui.divider {
|
|
border-color: #333333;
|
|
}
|
|
|
|
body.darkTheme .loglist .ui.accordion .title,
|
|
body.darkTheme .loglist .ui.accordion .content {
|
|
background-color: #1b1c1d;
|
|
color: #ffffff;
|
|
}
|
|
|
|
body.darkTheme .loglist .ui.accordion .title:hover {
|
|
background-color: #333333;
|
|
}
|
|
|
|
body.darkTheme .loglist .ui.list .item {
|
|
color: #ffffff;
|
|
}
|
|
|
|
body.darkTheme .loglist .ui.list .item .content {
|
|
color: #ffffff;
|
|
}
|
|
|
|
body.darkTheme .loglist .ui.list .item .showing {
|
|
color: #ffffff;
|
|
}
|
|
|
|
body.darkTheme .loglist .ui.button.filterbtn {
|
|
background-color: #333333;
|
|
color: #ffffff;
|
|
}
|
|
|
|
body.darkTheme .loglist .ui.button.filterbtn:hover {
|
|
background-color: #555555;
|
|
}
|
|
|
|
body.darkTheme .loglist .ui.toggle.checkbox label {
|
|
color: #ffffff;
|
|
}
|
|
|
|
body.darkTheme .loglist small {
|
|
color: #bbbbbb;
|
|
}
|
|
</style>
|
|
</head>
|
|
|
|
<body>
|
|
<link rel="stylesheet" href="../darktheme.css">
|
|
<script src="../script/darktheme.js"></script>
|
|
<br>
|
|
<div class="ui container">
|
|
<div class="ui stackable grid">
|
|
<div class="four wide column loglist">
|
|
<h3 class="ui header" style="padding-top: 1em;">
|
|
<div class="content">
|
|
Log View
|
|
<div class="sub header">Check System Log in Real Time</div>
|
|
</div>
|
|
</h3>
|
|
<div class="ui divider"></div>
|
|
<div id="logList" class="ui accordion">
|
|
|
|
</div>
|
|
<div class="ui divider"></div>
|
|
<h5>Filters</h5>
|
|
<button style="margin-top: 0.4em;" filter="system" class="ui fluid basic small button filterbtn"><i class="ui blue info circle icon"></i> System</button>
|
|
<button style="margin-top: 0.4em;" filter="request" class="ui fluid basic small button filterbtn"><i class="green exchange icon"></i> Request</button>
|
|
<button style="margin-top: 0.4em;" filter="error" class="ui fluid basic small button filterbtn"><i class="red exclamation triangle icon"></i> Error</button>
|
|
<button style="margin-top: 0.4em;" filter="all" class="ui fluid basic active small button filterbtn">All</button>
|
|
<div class="ui divider"></div>
|
|
<div class="ui toggle checkbox">
|
|
<input type="checkbox" id="enableAutoScroll" onchange="handleAutoScrollTicker(event, this.checked);">
|
|
<label>Auto Refresh<br>
|
|
<small>Refresh the viewing log every 10 seconds</small></label>
|
|
</div>
|
|
<div class="ui divider"></div>
|
|
<small>Notes: Some log files might be huge. Make sure you have checked the log file size before opening</small>
|
|
</div>
|
|
<div class="twelve wide column">
|
|
<textarea id="logrender" spellcheck="false" readonly="true">
|
|
← Pick a log file from the left menu to start debugging
|
|
</textarea>
|
|
<a href="#" onclick="openLogInNewTab();">Open In New Tab</a>
|
|
<br><br>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<br>
|
|
</body>
|
|
<script>
|
|
var currentOpenedLogURL = "";
|
|
var currentFilter = "all";
|
|
var autoscroll = false;
|
|
|
|
$(".checkbox").checkbox();
|
|
|
|
function openLogInNewTab(){
|
|
if (currentOpenedLogURL != ""){
|
|
window.open(currentOpenedLogURL);
|
|
}
|
|
}
|
|
|
|
function openLog(object, catergory, filename){
|
|
$(".logfile.active").removeClass('active');
|
|
$(object).addClass("active");
|
|
currentOpenedLogURL = "/api/log/read?file=" + filename;
|
|
$.get(currentOpenedLogURL, function(data){
|
|
if (data.error !== undefined){
|
|
alert(data.error);
|
|
return;
|
|
}
|
|
renderLogWithCurrentFilter(data);
|
|
});
|
|
}
|
|
|
|
function initLogList(){
|
|
$("#logList").html("");
|
|
$.get("/api/log/list", function(data){
|
|
//console.log(data);
|
|
for (let [key, value] of Object.entries(data)) {
|
|
console.log(key, value);
|
|
value.reverse(); //Default value was from oldest to newest
|
|
var fileItemList = "";
|
|
value.forEach(file => {
|
|
fileItemList += `<div class="item clickable logfile" onclick="openLog(this, '${key}','${file.Filename}');">
|
|
<i class="file outline icon"></i>
|
|
<div class="content">
|
|
${file.Title} (${formatBytes(file.Filesize)})
|
|
<div class="showing"><i class="green chevron right icon"></i></div>
|
|
</div>
|
|
</div>`;
|
|
})
|
|
$("#logList").append(`<div class="title">
|
|
<i class="dropdown icon"></i>
|
|
${key}
|
|
</div>
|
|
<div class="content">
|
|
<div class="ui list">
|
|
${fileItemList}
|
|
</div>
|
|
</div>`);
|
|
}
|
|
|
|
$(".ui.accordion").accordion();
|
|
});
|
|
}
|
|
initLogList();
|
|
|
|
|
|
function formatBytes(x){
|
|
var units = ['bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
|
let l = 0, n = parseInt(x, 10) || 0;
|
|
while(n >= 1024 && ++l){
|
|
n = n/1024;
|
|
}
|
|
return(n.toFixed(n < 10 && l > 0 ? 1 : 0) + ' ' + units[l]);
|
|
}
|
|
|
|
//Filter the log and render it to text area based on current filter choice
|
|
function renderLogWithCurrentFilter(data){
|
|
if (currentFilter == "all"){
|
|
$("#logrender").val(data);
|
|
}else{
|
|
let filterLines = data.split("\n");
|
|
let filteredLogFile = "";
|
|
for (var i = 0; i < filterLines.length; i++){
|
|
const thisLine = filterLines[i];
|
|
if (currentFilter == "system" && thisLine.indexOf("[system:") >= 0){
|
|
filteredLogFile += thisLine + "\n";
|
|
}else if (currentFilter == "request" && thisLine.indexOf("[router:") >= 0){
|
|
filteredLogFile += thisLine + "\n";
|
|
}else if (currentFilter == "error" && thisLine.indexOf(":error]") >= 0){
|
|
filteredLogFile += thisLine + "\n";
|
|
}
|
|
}
|
|
$("#logrender").val(filteredLogFile);
|
|
}
|
|
var textarea = document.getElementById('logrender');
|
|
textarea.scrollTop = textarea.scrollHeight;
|
|
}
|
|
|
|
/* Filter related functions */
|
|
$(".filterbtn").on("click", function(evt){
|
|
//Set filter type
|
|
let filterType = $(this).attr("filter");
|
|
currentFilter = (filterType);
|
|
$(".filterbtn.active").removeClass("active");
|
|
$(this).addClass('active');
|
|
|
|
//Reload the log with filter
|
|
if (currentOpenedLogURL != ""){
|
|
$.get(currentOpenedLogURL, function(data){
|
|
if (data.error !== undefined){
|
|
alert(data.error);
|
|
return;
|
|
}
|
|
renderLogWithCurrentFilter(data);
|
|
});
|
|
}
|
|
});
|
|
|
|
/* Auto scroll function */
|
|
setInterval(function(){
|
|
if (autoscroll){
|
|
//Update the log and scroll to bottom
|
|
if (currentOpenedLogURL != ""){
|
|
$.get(currentOpenedLogURL, function(data){
|
|
if (data.error !== undefined){
|
|
console.log(data.error);
|
|
return;
|
|
}
|
|
renderLogWithCurrentFilter(data);
|
|
});
|
|
}
|
|
}
|
|
}, 10000);
|
|
function handleAutoScrollTicker(event, checked){
|
|
autoscroll = checked;
|
|
}
|
|
</script>
|
|
</html> |