modified: .gitignore modified: app.py modified: templates/base.html.j2 modified: templates/view_namespace_logs.html.j2 modified: test_agent.sh
100 lines
3.6 KiB
Django/Jinja
100 lines
3.6 KiB
Django/Jinja
{% extends 'base.html.j2' %}
|
|
|
|
{% block title %}Logs for {{ namespace.name }}{% endblock %}
|
|
|
|
{% block content %}
|
|
<h1>Logs for Namespace: {{ namespace.name }}</h1>
|
|
|
|
<!-- Search Form -->
|
|
<form method="get" action="{{ request.current_route_url() }}">
|
|
<input type="text" name="q" value="{{ search_query }}" placeholder="Search logs">
|
|
<button type="submit">Search</button>
|
|
{% if search_query %}
|
|
<a href="{{ request.route_url('view_namespace_logs', namespace_short_id=namespace.short_id) }}">Clear Search</a>
|
|
{% endif %}
|
|
</form>
|
|
|
|
<!-- Logs Table -->
|
|
<div class="logs-container">
|
|
{% if logs %}
|
|
<table class="logs-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Timestamp</th>
|
|
<th>Level</th>
|
|
<th>Message</th>
|
|
<th>Metadata</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for log in logs %}
|
|
<tr class="log-entry">
|
|
<td class="log-timestamp">{{ log.timestamp.strftime('%Y-%m-%d %H:%M:%S') }}</td>
|
|
<td class="log-level">{{ log.level }}</td>
|
|
<td class="log-message">{{ log.message }}</td>
|
|
<td class="log-metadata">
|
|
{% if log.log_metadata %}
|
|
<pre>{{ log.log_metadata }}</pre>
|
|
{% else %}
|
|
N/A
|
|
{% endif %}
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
{% else %}
|
|
<p>No logs found.</p>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<!-- Include JavaScript for highlighting -->
|
|
{% if search_query %}
|
|
<script>
|
|
(function() {
|
|
// Function to escape special characters in regex
|
|
function escapeRegExp(string) {
|
|
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
}
|
|
|
|
var searchQuery = {{ search_query|tojson }};
|
|
|
|
if (!searchQuery) {
|
|
return;
|
|
}
|
|
|
|
var regex = new RegExp(escapeRegExp(searchQuery), 'gi');
|
|
|
|
// Function to highlight text
|
|
function highlightText(element) {
|
|
element.childNodes.forEach(function(node) {
|
|
if (node.nodeType === Node.TEXT_NODE && node.parentNode.nodeName !== 'MARK') {
|
|
var text = node.textContent;
|
|
var html = text.replace(regex, function(match) {
|
|
return '<mark>' + match + '</mark>';
|
|
});
|
|
if (html !== text) {
|
|
var temp = document.createElement('span');
|
|
temp.innerHTML = html;
|
|
// Replace the text node with the new HTML
|
|
var fragment = document.createDocumentFragment();
|
|
while (temp.firstChild) {
|
|
fragment.appendChild(temp.firstChild);
|
|
}
|
|
node.parentNode.replaceChild(fragment, node);
|
|
}
|
|
} else if (node.nodeType === Node.ELEMENT_NODE && node.nodeName !== 'SCRIPT') {
|
|
highlightText(node);
|
|
}
|
|
});
|
|
}
|
|
|
|
// Highlight search terms in log entries
|
|
document.querySelectorAll('.log-entry td').forEach(function(element) {
|
|
highlightText(element);
|
|
});
|
|
})();
|
|
</script>
|
|
{% endif %}
|
|
|
|
{% endblock %}
|