fix: system_all_log.html ReferenceError and other updates

This commit is contained in:
2026-01-17 14:06:27 +09:00
parent cf19d79ef8
commit 2681f5a096
24 changed files with 820 additions and 141 deletions

View File

@@ -3,6 +3,7 @@ import platform
import shutil
import sys
import threading
import time
import traceback
import zipfile
@@ -110,7 +111,8 @@ class PluginManager:
F.logger.debug(plugins)
for plugin_name in plugins:
F.logger.debug(f'[+] PLUGIN LOADING Start.. [{plugin_name}]')
F.logger.info(f'[+] PLUGIN IMPORT Start.. [{plugin_name}]')
import_start_time = time.time()
entity = cls.all_package_list[plugin_name]
try:
try:
@@ -129,6 +131,9 @@ class PluginManager:
F.app.register_blueprint(mod_blue_print)
except Exception as exception:
F.logger.warning(f'[!] BLUEPRINT not exist : [{plugin_name}]')
import_elapsed_time = time.time() - import_start_time
F.logger.info(f'[+] PLUGIN IMPORT End.. [{plugin_name}] ({import_elapsed_time:.3f}s)')
cls.plugin_list[plugin_name] = entity
except Exception as e:
F.logger.error(f"Exception:{str(e)}")
@@ -155,9 +160,11 @@ class PluginManager:
if mod_plugin_load:
def func(mod_plugin_load, key):
try:
#F.logger.debug(f'[!] plugin_load_celery threading start : [{key}]')
load_start_time = time.time()
F.logger.info(f'[!] plugin_load_celery threading start : [{key}]')
mod_plugin_load()
#F.logger.debug(f'[!] plugin_load_celery threading end : [{key}]')
load_elapsed_time = time.time() - load_start_time
F.logger.info(f'[!] plugin_load_celery threading end : [{key}] ({load_elapsed_time:.3f}s)')
except Exception as e:
F.logger.error(f"Exception:{str(e)}")
F.logger.error(traceback.format_exc())
@@ -177,9 +184,11 @@ class PluginManager:
if mod_plugin_load:
def func(mod_plugin_load, key):
try:
load_start_time = time.time()
F.logger.info(f'[!] plugin_load threading start : [{key}]')
mod_plugin_load()
F.logger.debug(f'[!] plugin_load threading end : [{key}]')
load_elapsed_time = time.time() - load_start_time
F.logger.info(f'[!] plugin_load threading end : [{key}] ({load_elapsed_time:.3f}s)')
except Exception as e:
F.logger.error('### plugin_load exception : %s', key)
F.logger.error(f"Exception:{str(e)}")

View File

@@ -107,4 +107,29 @@ background-color: #ffff0080 !important;
margin:-2px;
}
.modal { overflow: scroll !important; }
.modal { overflow: scroll !important; }
/* Mobile Navigation Tightening */
@media (max-width: 768px) {
#menu_module_div {
margin-bottom: 0 !important;
}
#menu_module_div .nav-pills {
margin-bottom: 0 !important;
border-bottom: 1px solid #dee2e6;
border-radius: 0 !important;
box-shadow: none !important;
}
#menu_page_div .nav-pills {
margin-top: 0 !important;
border-radius: 0 !important;
box-shadow: 0 .125rem .25rem rgba(0,0,0,.075) !important;
}
#main_container {
padding-top: 0 !important;
margin-top: 0 !important;
}
#main_container > .d-inline-block {
display: none !important;
}
}

View File

@@ -1,82 +1,208 @@
{% extends "base.html" %}
{% block content %}
<div>
<nav>
{{ macros.m_tab_head_start() }}
{{ macros.m_tab_head('old', '이전', true) }}
{{ macros.m_tab_head('new', '실시간', false) }}
{{ macros.m_tab_head_end() }}
</nav>
<div class="tab-content" id="nav-tabContent">
{{ macros.m_tab_content_start('old', true) }}
<div>
<textarea id="log" class="col-md-12" rows="30" charswidth="23" disabled style="background-color:#ffffff;visibility:hidden"></textarea>
</div>
{{ macros.m_tab_content_end() }}
<style>
/* Unified Log Page Design (matches gds_dviewer) */
.log-wrapper {
max-width: 1400px;
margin: 0 auto;
padding: 20px;
}
{{ macros.m_tab_content_start('new', false) }}
<div>
<textarea id="add" class="col-md-12" rows="30" charswidth="23" disabled style="background-color:#ffffff;visibility:visible"></textarea>
</div>
<div class="form-inline">
<label class="form-check-label" for="auto_scroll">자동 스크롤</label>
<input id="auto_scroll" name="auto_scroll" class="form-control form-control-sm" type="checkbox" data-toggle="toggle" checked>
<span class='text-left' style="padding-left:25px; padding-top:0px">
<button id="clear" class="btn btn-sm btn-outline-success">리셋</button>
</span>
</div>
{{ macros.m_tab_content_end() }}
.log-card {
background: linear-gradient(145deg, rgba(20, 30, 48, 0.95), rgba(36, 59, 85, 0.9));
border: 1px solid rgba(100, 150, 180, 0.25);
border-radius: 12px;
overflow: hidden;
}
</div>
.log-tabs {
border-bottom: 1px solid rgba(100, 150, 180, 0.2);
background: rgba(0, 0, 0, 0.2);
padding: 10px 10px 0 10px;
display: flex;
gap: 6px;
}
.log-tab {
color: #94a3b8;
border: none;
border-radius: 8px 8px 0 0;
padding: 10px 20px;
font-weight: 500;
background: transparent;
cursor: pointer;
transition: all 0.2s;
}
.log-tab:hover {
color: #e2e8f0;
background: rgba(255, 255, 255, 0.05);
}
.log-tab.active {
color: #7dd3fc;
background: rgba(20, 30, 48, 0.95);
border-bottom: 2px solid #7dd3fc;
}
.log-content {
display: none;
}
.log-content.active {
display: block;
}
.log-container {
height: calc(100vh - 200px);
min-height: 400px;
overflow-y: auto;
padding: 16px;
font-family: 'SF Mono', 'Consolas', 'Monaco', monospace;
font-size: 12px;
line-height: 1.6;
background: rgba(0, 0, 0, 0.3);
color: #94a3b8;
}
.log-line-error { color: #f87171; }
.log-line-warning { color: #fbbf24; }
.log-line-info { color: #5eead4; }
.log-line-debug { color: #94a3b8; }
.controls-bar {
display: flex;
align-items: center;
justify-content: flex-end;
padding: 12px 20px;
background: rgba(0, 0, 0, 0.2);
border-top: 1px solid rgba(100, 150, 180, 0.2);
gap: 12px;
}
.btn-log {
background: linear-gradient(180deg, rgba(45, 55, 72, 0.95), rgba(35, 45, 60, 0.98));
border: 1px solid rgba(100, 150, 180, 0.25);
color: #7dd3fc;
padding: 6px 14px;
font-size: 12px;
cursor: pointer;
border-radius: 6px;
}
.btn-log:hover {
background: linear-gradient(180deg, rgba(55, 65, 82, 0.95), rgba(45, 55, 70, 0.98));
color: #fff;
}
.log-switch {
display: flex;
align-items: center;
gap: 8px;
}
.log-switch label {
color: #94a3b8;
font-size: 12px;
font-weight: 500;
}
@media (max-width: 768px) {
.log-wrapper {
padding: 5px;
}
.log-container {
height: calc(100vh - 180px);
min-height: 300px;
padding: 12px;
}
}
</style>
<div class="log-wrapper">
<div class="log-card">
<div class="log-tabs">
<button class="log-tab active" data-tab="old">이전</button>
<button class="log-tab" data-tab="new">실시간</button>
</div>
<div class="log-content active" id="tab-old">
<div class="log-container" id="log-history"></div>
</div>
<div class="log-content" id="tab-new">
<div class="log-container" id="log-realtime"></div>
<div class="controls-bar">
<div class="log-switch">
<label for="auto_scroll">자동 스크롤</label>
<input id="auto_scroll" name="auto_scroll" type="checkbox" checked>
</div>
<button id="clear" class="btn-log">리셋</button>
</div>
</div>
</div>
</div>
<script type="text/javascript">
$(document).ready(function() {
setWide();
$('#loading').show();
ResizeTextAreaLog()
})
function ResizeTextAreaLog() {
ClientHeight = window.innerHeight
$("#log").height(ClientHeight-240);
$("#add").height(ClientHeight-260);
function escapeHtml(text) {
var div = document.createElement('div');
div.appendChild(document.createTextNode(text));
return div.innerHTML;
}
$(window).resize(function() {
ResizeTextAreaLog();
function formatLogLine(line) {
var className = '';
if (line.indexOf('ERROR') !== -1) className = 'log-line-error';
else if (line.indexOf('WARNING') !== -1) className = 'log-line-warning';
else if (line.indexOf('INFO') !== -1) className = 'log-line-info';
else if (line.indexOf('DEBUG') !== -1) className = 'log-line-debug';
return '<div class="' + className + '">' + escapeHtml(line) + '</div>';
}
// Tab switching
document.querySelectorAll('.log-tab').forEach(function(tab) {
tab.addEventListener('click', function() {
document.querySelectorAll('.log-tab').forEach(function(t) { t.classList.remove('active'); });
document.querySelectorAll('.log-content').forEach(function(c) { c.classList.remove('active'); });
this.classList.add('active');
document.getElementById('tab-' + this.dataset.tab).classList.add('active');
});
});
$(document).ready(function() {
setWide();
$('#loading').show();
});
var protocol = window.location.protocol;
var socket = io.connect(protocol + "//" + document.domain + ":" + location.port + "/log");
socket.emit("start", {'package':'{{package}}'} );
socket.on('on_start', function(data){
document.getElementById("log").innerHTML += data.data;
document.getElementById("log").scrollTop = document.getElementById("log").scrollHeight;
document.getElementById("log").style.visibility = 'visible';
$('#loading').hide();
socket.emit("start", {'package':'{{package}}'});
socket.on('on_start', function(data) {
var container = document.getElementById("log-history");
var lines = data.data.split('\n');
var html = '';
for (var i = 0; i < lines.length; i++) {
html += formatLogLine(lines[i]);
}
container.innerHTML = html || '<div style="text-align:center;color:#64748b;">로그가 비어 있습니다.</div>';
container.scrollTop = container.scrollHeight;
$('#loading').hide();
});
socket.on('add', function(data){
if (data.package == "{{package}}") {
var chk = $('#auto_scroll').is(":checked");
document.getElementById("add").innerHTML += data.data;
if (chk) document.getElementById("add").scrollTop = document.getElementById("add").scrollHeight;
}
socket.on('add', function(data) {
if (data.package == "{{package}}") {
var chk = $('#auto_scroll').is(":checked");
var container = document.getElementById("log-realtime");
container.innerHTML += formatLogLine(data.data);
if (chk) container.scrollTop = container.scrollHeight;
}
});
$("#clear").click(function(e) {
e.preventDefault();
document.getElementById("add").innerHTML = '';
e.preventDefault();
document.getElementById("log-realtime").innerHTML = '';
});
$("#auto_scroll").click(function(){
var chk = $(this).is(":checked");//.attr('checked');
});
</script>
</script>
{% endblock %}

View File

@@ -1 +1 @@
VERSION="4.1.40"
VERSION="4.1.40"

View File

@@ -132,14 +132,15 @@ def default_route(P):
@P.blueprint.route('/ajax/<module_name>/<cmd>', methods=['GET', 'POST'])
@login_required
def second_ajax(module_name, cmd):
# P.logger.debug(f"[CORE-DEBUG] second_ajax: package={P.package_name}, module={module_name}, cmd={cmd}")
try:
for module in P.module_list:
if cmd == 'scheduler':
go = request.form['scheduler']
if go == 'true':
P.logic.scheduler_start(module_name)
P.logic.scheduler_start(module_name)
else:
P.logic.scheduler_stop(module_name)
P.logic.scheduler_stop(module_name)
return jsonify(go)
elif cmd == 'db_delete':
day = request.form['day']

View File

@@ -53,11 +53,26 @@ $(window).resize(function() {
});
function escapeHtml(text) {
var div = document.createElement('div');
div.appendChild(document.createTextNode(text));
return div.innerHTML;
}
function formatLogLine(line) {
var className = '';
if (line.indexOf('ERROR') !== -1) className = 'text-danger';
else if (line.indexOf('WARNING') !== -1) className = 'text-warning';
else if (line.indexOf('INFO') !== -1) className = 'text-info';
else if (line.indexOf('DEBUG') !== -1) className = 'text-muted';
return '<div class="' + className + '" style="white-space: pre-wrap; font-family: monospace; font-size: 13px;">' + escapeHtml(line) + '</div>';
}
socket.on('on_start', function(data){
lines = splitLines(data.data);
var lines = data.data.split('\n');
var html = '';
for (i in lines) {
html += logline(lines[i]);
for (var i in lines) {
html += formatLogLine(lines[i]);
}
$('#log_div').html(html)
document.getElementById("log_div").scrollTop = document.getElementById("log_div").scrollHeight;
@@ -66,7 +81,7 @@ socket.on('on_start', function(data){
socket.on('add', function(data){
if (data.filename == current_filename) {
$('#log_div').append(logline(data.data.trim()));
$('#log_div').append(formatLogLine(data.data.trim()));
document.getElementById("log_div").scrollTop = document.getElementById("log_div").scrollHeight;
}
});