Skip to content

Commit 52bbcdd

Browse files
committed
LIU-470: Add table rendering and filter by Error Level
1 parent 0a60da2 commit 52bbcdd

File tree

6 files changed

+81
-22
lines changed

6 files changed

+81
-22
lines changed

daliuge-engine/dlg/apps/app_base.py

+22-6
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,23 @@ def __init__(self, log_storage):
8181
self.log_storage = log_storage
8282

8383
def emit(self, record):
84-
"""Store log messages in the instance's log storage."""
85-
log_entry = self.format(record)
86-
self.log_storage.append(log_entry)
84+
"""Store log messages in the instance's log storage.
85+
86+
:param record: The log string we want to add to the log storage
87+
88+
.. note: We are not interested in actually emitting the log;
89+
we are just interested in extracting and storing Record metadata
90+
"""
91+
92+
exc = (str(record.exc_text if record.exc_text else ""))
93+
exc = f"<pre>{exc}</pre>"
94+
self.log_storage.append({ "time":record.asctime,
95+
"Level": record.levelname,
96+
"Module": record.name,
97+
"Function/Method": record.funcName,
98+
"Line #": record.lineno,
99+
"Message": f"{str(record.message)}\n{exc}"
100+
})
87101

88102
class DROPLogFilter(logging.Filter):
89103
def __init__(self, uid: str, humanKey: str):
@@ -93,6 +107,9 @@ def __init__(self, uid: str, humanKey: str):
93107
def filter(self, record):
94108
uid = getattr(record, "drop_uid", None)
95109
return uid == self.uid or uid == self.humanKey
110+
111+
112+
96113
# ===============================================================================
97114
# AppDROP classes follow
98115
# ===============================================================================
@@ -165,9 +182,8 @@ def initialize(self, **kwargs):
165182
self.logger = logging.getLogger(f"{__class__}.{self.uid}")
166183
instance_handler = InstanceLogHandler(self.log_storage)
167184
instance_handler.addFilter(DROPLogFilter(self.uid, self._humanKey))
168-
fmt = "%(asctime)-15s [%(levelname)5.5s] [%(threadName)15.15s] "
169-
fmt += "[%(drop_uid)10.10s] "
170-
fmt += "%(name)s#%(funcName)s:%(lineno)s %(message)s"
185+
fmt = ("%(asctime)-15s [%(levelname)5.5s] "
186+
"%(name)s#%(funcName)s:%(lineno)s %(message)s")
171187
fmt = logging.Formatter(fmt)
172188
instance_handler.setFormatter(fmt)
173189

daliuge-engine/dlg/manager/rest.py

+7-5
Original file line numberDiff line numberDiff line change
@@ -399,16 +399,18 @@ def getDropStatus(self, sessionId, dropId):
399399
urlparts = bottle.request.urlparts
400400
serverUrl = urlparts.scheme + "://" + urlparts.netloc
401401

402-
# import requests
403-
# api_url = f"{serverUrl}/api/sessions/{sessionId}/graph/drop/{dropId}"
404-
# data = requests.get(api_url)
405-
# data_alt = json.loads(data.text)
406402
data = self._getDropStatus(sessionId, dropId)
407403

404+
columns = [col for col in data["logs"][-1].keys()]
405+
filter_column = "Level"
406+
filter_column_index = columns.index(filter_column)
407+
408408
tpl = file_as_string("web/drop_log.html")
409409
return bottle.template(
410410
tpl,
411-
node=data,
411+
data=data,
412+
columns=columns,
413+
filter_index=filter_column_index,
412414
sessionId=sessionId,
413415
serverUrl=serverUrl,
414416
dmType=self.dm.__class__.__name__,

daliuge-engine/dlg/manager/session.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -652,7 +652,9 @@ def getDropLogs(self, drop_oid: str):
652652
return {"session": self.sessionId,
653653
"status": self.status,
654654
"oid": drop_oid,
655-
"logs": self._drops[drop_oid].getLogs() }
655+
"logs": self._drops[drop_oid].getLogs()}
656+
# "stderr": self._drops[drop_oid].getStdError(),
657+
# "stdout": self._drops[drop_oid].getStdOut()}
656658

657659

658660
@track_current_session

daliuge-engine/dlg/manager/web/drop_log.html

+47-8
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
<link href="/static/css/bootstrap.min.css" rel="stylesheet" type="text/css"/>
1111
<link href="/static/css/dm.css" rel="stylesheet" type="text/css"/>
1212
<link href="/static/css/progressBar.css" rel="stylesheet" type="text/css"/>
13+
<link rel="stylesheet" href="https://cdn.datatables.net/1.13.6/css/jquery.dataTables.min.css">
14+
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
15+
<script src="https://cdn.datatables.net/1.13.6/js/jquery.dataTables.min.js"></script>
1316
<style>
1417
@import "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.4.0/css/font-awesome.css";
1518
</style></head>
@@ -42,24 +45,60 @@
4245
</nav>
4346
<div id="graphNameWrapper">
4447
<ul id="graphName">
45-
<li>Session:{{node.get("session")}}</li>
48+
<li>Session:{{data.get("session")}}</li>
4649
<li></li>
47-
<li>DROP: {{node.get("uid")}}</li>
50+
<li>DROP: {{data.get("uid")}}</li>
4851
</ul>
4952
</div>
5053
<div id="dimContentWrapper">
5154
</div>
5255
<div id="listContainer" class="container">
5356
<div>
5457
<h3>Log Entries</h3>
55-
<ul>
56-
% for log in node["logs"]:
57-
<li>{{log}}</li>
58-
% end
59-
</ul>
58+
<label for="levelFilter">Filter by Log Level:</label>
59+
<select id="levelFilter" class="form-select" style="width: 200px; display: inline-block; margin-bottom: 10px;">
60+
<option value="">Show All</option>
61+
</select>
62+
<table id="logentries" align="left" class="table table-striped table-hover">
63+
<thead>
64+
<tr>
65+
% for col in columns:
66+
<th class="text-start">{{ col }} </th>
67+
% end
68+
</tr>
69+
</thead>
70+
<tbody>
71+
%for row in data["logs"]:
72+
<tr>
73+
% for col in columns:
74+
<td class="text-start"> {{! row.get(col, '') }} </td>
75+
% end
76+
</tr>
77+
%end
78+
</tbody>
79+
</table>
6080
</div>
61-
6281
</div>
6382

83+
<script>
84+
$(document).ready(function() {
85+
var table = $('#logentries').DataTable();
86+
87+
// Get unique values for the column (City)
88+
table.column({{filter_index}}).data().unique().sort().each(function(d, j) {
89+
$('#levelFilter').append('<option value="' + d + '">' + d + '</option>');
90+
});
91+
92+
// Filter the table when a selection is made
93+
$('#levelFilter').on('change', function() {
94+
var selected = $(this).val();
95+
if (selected) {
96+
table.column({{filter_index}}).search('^' + selected + '$', true, false).draw();
97+
} else {
98+
table.column({{filter_index}}).search('').draw();
99+
}
100+
});
101+
});
102+
</script>
64103
</body>
65104
</html>

daliuge-engine/dlg/manager/web/static/js/dm.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -627,7 +627,7 @@ function _addNode(g, doSpec, url) {
627627
notes += 'storage: ' + doSpec.storage;
628628
}
629629
url = url.replace("api/","") + "/graph/drop/" + doSpec.oid;
630-
let link = "<a href=" + url + " target='_blank'>Click Me</a>";
630+
let link = "<a href=" + url + " target='_blank'>Details</a>";
631631
var oid = doSpec.oid;
632632
var html = '<div class="drop-label ' + typeShape + '" id="id_' + oid + '">';
633633
html += '<span class="notes">' + notes + '</span>';

docs/conf.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ def __getattr__(cls, _):
7575
extensions = [
7676
"sphinx.ext.autodoc",
7777
"sphinx.ext.todo",
78-
"sphinx.ext.coverage",
78+
# "sphinx.ext.coverage",
7979
"sphinx.ext.imgmath",
8080
"sphinx_rtd_theme",
8181
]

0 commit comments

Comments
 (0)