Skip to content

Commit ef16074

Browse files
author
Jérémie SOLIGNY
committed
Log Files table is now a DataTable. Adding support of 'file' params in URL to directly load a file.
1 parent ee56cef commit ef16074

File tree

8 files changed

+106
-29
lines changed

8 files changed

+106
-29
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,5 @@ dist/
66
*.pyc
77
*.log
88
*backup*
9+
/venv/
10+
/.idea/

README.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ This project was modified from: https://bitbucket.org/inkalabsinc/django-log-vie
99

1010
-----------------
1111

12-
.. image:: https://i.imgur.com/IZQKm4T.png
12+
.. image:: https://i.imgur.com/kqxzIpX.png
1313

1414

1515
Quick start
@@ -48,6 +48,7 @@ Quick start
4848
LOG_VIEWER_FILES_DIR = 'logs/'
4949
LOG_VIEWER_PAGE_LENGTH = 25 # total log lines per-page
5050
LOG_VIEWER_MAX_READ_LINES = 1000 # total log lines will be read
51+
LOG_VIEWER_FILE_LIST_MAX_ITEMS_PER_PAGE = 25 # Max log files loaded in Datatable per page
5152
LOG_VIEWER_PATTERNS = ['[INFO]', '[DEBUG]', '[WARNING]', '[ERROR]', '[CRITICAL]']
5253

5354
# Optionally you can set the next variables in order to customize the admin:

log_viewer/settings.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,6 @@
1010
LOG_VIEWER_MAX_READ_LINES = getattr(settings, 'LOG_VIEWER_MAX_READ_LINES', 1000)
1111
LOG_VIEWER_FILE_LIST_TITLE = getattr(settings, 'LOG_VIEWER_FILE_LIST_TITLE', None)
1212
LOG_VIEWER_FILE_LIST_STYLES = getattr(settings, 'LOG_VIEWER_FILE_LIST_STYLES', None)
13+
LOG_VIEWER_FILE_LIST_MAX_ITEMS_PER_PAGE = getattr(settings, 'LOG_VIEWER_FILE_LIST_MAX_ITEMS_PER_PAGE', 25)
1314
LOG_VIEWER_PATTERNS = getattr(settings, 'LOG_VIEWER_PATTERNS', ['[INFO]', '[DEBUG]', '[WARNING]',
1415
'[ERROR]', '[CRITICAL]'])

log_viewer/static/log_viewer/css/log-viewer.css

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,31 @@ table#log-entries.no-footer {
4646
#log-entries_length, #log-entries_length {
4747
margin: .5em 0;
4848
}
49+
#log-files-list_length {
50+
width: 100%;
51+
text-align: center;
52+
float: none;
53+
}
54+
#log-files-list_filter {
55+
float: none;
56+
text-align: center;
57+
padding: 0.5em 0.2em;
58+
}
59+
#log-files-list td {
60+
font-size: 1em;
61+
padding: 1em;
62+
}
63+
#log-files-list_info {
64+
float: none;
65+
text-align: center;
66+
width: 100%;
67+
}
68+
#log-files-list_paginate {
69+
float: none;
70+
text-align: center;
71+
margin-top: 1em;
72+
width: 100%;
73+
}
74+
#log-files-list_paginate .paginate_button {
75+
display: inline-block;
76+
}

log_viewer/templates/log_viewer/logfile_viewer.html

Lines changed: 53 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,13 @@ <h1 class="pull-left">{% if custom_file_list_title %}{{ custom_file_list_title }
5555
</form>
5656
<div id="changelist-filter">
5757
<h2>{% trans 'Log Files' %}</h2>
58-
<div id="log-files-list">
59-
</div>
58+
{# <div id="log-files-list">#}
59+
{# </div>#}
60+
<table id="log-files-list" class="display" style="width:100%">
61+
<tbody>
62+
<tr><td colspan="2">{% trans 'No entries!' %}</td></tr>
63+
</tbody>
64+
</table>
6065
</div>
6166
</div>
6267
</div>
@@ -81,7 +86,7 @@ <h2>{% trans 'Log Files' %}</h2>
8186

8287
function loadDataTable(table_name, url_json) {
8388
$(table_name).DataTable({
84-
pageLength: {{ page_length }},
89+
pageLength: {{ files_per_page }},
8590
columns: [{data: 0}, {data: 1}],
8691
ajax: function (data, callback, settings) {
8792
$.ajax({
@@ -91,9 +96,46 @@ <h2>{% trans 'Log Files' %}</h2>
9196
const new_logs = [];
9297
var next_page = response.next_page || 1;
9398

94-
response.logs.forEach(function(text, numb, logs){
95-
text = escapeHtml(text);
96-
new_logs.push([numb+1, text]);
99+
try {
100+
response.logs.forEach(function(text, numb, logs){
101+
text = escapeHtml(text);
102+
new_logs.push([numb+1, text]);
103+
});
104+
} catch {
105+
console.warn("This log file doesn't exist");
106+
}
107+
108+
109+
callback({
110+
data: new_logs,
111+
recordsTotal: next_page,
112+
recordsFiltered: next_page
113+
});
114+
}
115+
});
116+
}
117+
});
118+
}
119+
120+
function loadDataTableFiles(table_name, url_json) {
121+
$(table_name).DataTable({
122+
pageLength: {{ files_per_page }},
123+
columns: [{data: 1}],
124+
ajax: function (data, callback, settings) {
125+
$.ajax({
126+
type: 'get',
127+
url: url_json,
128+
success:function(response){
129+
const new_logs = [];
130+
let next_page = response.next_page_files || 1;
131+
response.log_files.forEach(function(logs, numb){
132+
const keys = Object.keys(logs);
133+
Object.entries(logs).forEach(([file_name, xtra]) => {
134+
logs = '<a class="btn-load-json-log" href="javascript:;" '+
135+
'data-file-name="'+file_name+'" '+
136+
'data-href="'+url_json+file_name+'">'+xtra.display+'</a>'
137+
});
138+
new_logs.push([numb+1, logs]);
97139
});
98140

99141
callback({
@@ -121,19 +163,11 @@ <h2>{% trans 'Log Files' %}</h2>
121163
$(document).ready(function() {
122164
// just blank entry to get the `log_files`
123165
var url_json = "{% url 'log_viewer:log_json_view' xxxxx %}";
124-
$.getJSON(url_json, function(result){
125-
result.log_files.forEach(function(log) {
126-
const keys = Object.keys(log);
127-
Object.entries(log).forEach(([file_name, xtra]) => {
128-
// console.log(file_name);
129-
// console.log(xtra);
130-
var html = '<ul><li><a class="btn-load-json-log" href="javascript:;" '+
131-
'data-file-name="'+file_name+'" '+
132-
'data-href="'+url_json+file_name+'">'+xtra.display+'</a></li></ul>'
133-
$('div#log-files-list').append(html);
134-
});
135-
});
136-
});
166+
var table_name ='table#log-files-list';
167+
loadDataTableFiles(table_name, url_json);
168+
let params = new URLSearchParams(window.location.search);
169+
loadDataTableTrigger(params.get("file"))
170+
137171
});
138172

139173
$(document).on('click', '.btn-load-json-log', function(){

log_viewer/utils.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,24 @@
88
from log_viewer import settings
99

1010

11-
def get_log_files(directory):
11+
def get_log_files(directory, max_items_per_page, curr_page):
1212
result = {}
1313
for root, _, files in os.walk(directory):
1414
all_files = list(filter(lambda x: x.find('~') == -1, files))
1515

16-
log_files = []
17-
log_files.extend(list(filter(lambda x: x in settings.LOG_VIEWER_FILES, all_files)))
18-
log_files.extend([x for x in all_files if fnmatch(x, settings.LOG_VIEWER_FILES_PATTERN)])
19-
16+
all_log_files = []
17+
all_log_files.extend(list(filter(lambda x: x in settings.LOG_VIEWER_FILES, all_files)))
18+
all_log_files.extend([x for x in all_files if fnmatch(x, settings.LOG_VIEWER_FILES_PATTERN)])
2019
log_dir = os.path.relpath(root, directory)
2120
if log_dir == '.':
2221
log_dir = ''
2322

24-
result[log_dir] = list(set(log_files))
23+
result["logs"] = {
24+
log_dir: list(set(all_log_files))
25+
}
26+
result["next_page_files"] = curr_page + 1
27+
result["last_files"] = all_log_files.__len__() <= curr_page * max_items_per_page
28+
2529
return result
2630

2731

log_viewer/views.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,11 @@ def get_log_json(self, original_context={}):
4343
context['next_page'] = page + 1
4444
context['log_files'] = []
4545

46-
log_file_data = get_log_files(settings.LOG_VIEWER_FILES_DIR)
47-
for log_dir, log_files in log_file_data.items():
46+
log_file_data = get_log_files(settings.LOG_VIEWER_FILES_DIR, settings.LOG_VIEWER_FILE_LIST_MAX_ITEMS_PER_PAGE, 1)
47+
context['next_page_files'] = log_file_data["next_page_files"]
48+
context['last_files'] = log_file_data["last_files"]
49+
50+
for log_dir, log_files in log_file_data["logs"].items():
4851
for log_file in log_files:
4952
display = os.path.join(log_dir, log_file)
5053
uri = os.path.join(settings.LOG_VIEWER_FILES_DIR, display)
@@ -108,7 +111,8 @@ class LogDownloadView(TemplateView):
108111
def render_to_response(self, context, **response_kwargs):
109112
# file_name = context.get('file_name', None)
110113
file_name = self.request.GET.get('file_name', None)
111-
log_file_result = get_log_files(settings.LOG_VIEWER_FILES_DIR)
114+
log_file_result = get_log_files(settings.LOG_VIEWER_FILES_DIR,
115+
settings.LOG_VIEWER_FILE_LIST_MAX_ITEMS_PER_PAGE, 1)["logs"]
112116

113117
if file_name:
114118
file_path = unquote(file_name)
@@ -166,6 +170,7 @@ def get_context_data(self, file_name=None, page=1, **kwargs):
166170
context['custom_file_list_title'] = settings.LOG_VIEWER_FILE_LIST_TITLE
167171
context['custom_style_file'] = settings.LOG_VIEWER_FILE_LIST_STYLES
168172
context['page_length'] = settings.LOG_VIEWER_PAGE_LENGTH
173+
context['files_per_page'] = settings.LOG_VIEWER_FILE_LIST_MAX_ITEMS_PER_PAGE
169174
return context
170175

171176

setup.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
'Framework :: Django :: 2.0',
2929
'Framework :: Django :: 3.0',
3030
'Framework :: Django :: 3.1',
31+
'Framework :: Django :: 4.0',
3132
'Intended Audience :: Developers',
3233
'Operating System :: OS Independent',
3334
'Programming Language :: Python',
@@ -36,6 +37,7 @@
3637
'Programming Language :: Python :: 3.5',
3738
'Programming Language :: Python :: 3.6',
3839
'Programming Language :: Python :: 3.7',
40+
'Programming Language :: Python :: 3.9',
3941
'Development Status :: 5 - Production/Stable',
4042
'Topic :: Software Development :: Libraries :: Python Modules',
4143
'License :: OSI Approved :: MIT License',

0 commit comments

Comments
 (0)