Add mtime to generated indexes

It is valuable when looking for the most recent test run to know the mod
time of log files. Add this to the generated index files to provide that
information to our users.

Change-Id: I03669afd73d1f0ce14adce17a3136ce26377b403
This commit is contained in:
Clark Boylan 2015-10-08 11:49:37 -07:00
parent aab3f8b234
commit 8a0619c666
3 changed files with 71 additions and 48 deletions

View File

@ -17,6 +17,7 @@
# under the License.
import collections
import datetime
import fileinput
import os.path
import re
@ -223,7 +224,7 @@ class IndexIterableBuffer(collections.Iterable):
# Use sets here to dedup. We can have duplicates
# if disk and swift based paths have overlap.
file_set = self.disk_list() | self.swift_list()
# file_list is a list of tuples (relpath, name, size)
# file_list is a list of tuples (relpath, name, mtime, size)
self.file_list = sorted(file_set, key=lambda tup: tup[0])
def disk_list(self):
@ -233,11 +234,14 @@ class IndexIterableBuffer(collections.Iterable):
full_path = os.path.join(self.logpath, f)
stat_info = os.stat(full_path)
size = sizeof_fmt(stat_info.st_size)
mtime = datetime.datetime.utcfromtimestamp(
stat_info.st_mtime).isoformat()
if os.path.isdir(full_path):
f = f + '/' if f[-1] != '/' else f
file_set.add((
os.path.join('/', self.logname, f),
f,
mtime,
size
))
return file_set
@ -257,6 +261,7 @@ class IndexIterableBuffer(collections.Iterable):
for f in files:
size = sizeof_fmt(f.get('bytes', 0))
mtime = f.get('last_modified', 'unknown')
if 'subdir' in f:
fname = os.path.relpath(f['subdir'], self.logname)
fname = fname + '/' if f['subdir'][-1] == '/' else \
@ -266,6 +271,7 @@ class IndexIterableBuffer(collections.Iterable):
file_set.add((
os.path.join('/', self.logname, fname),
fname,
mtime,
size
))
except Exception:

View File

@ -5,9 +5,9 @@
</head>
<body>
<h1>Index of {{ logname }}</h1>
<table><tr><th>Name</th><th>Size</th></tr>
{% for link, title, size in file_list %}
<tr><td><a href="{{ link }}">{{ title }}</a></td><td style="text-align: right">{{ size }}</td></tr>
<table><tr><th>Name</th><th>Last Modified</th><th>Size</th></tr>
{% for link, title, mtime, size in file_list %}
<tr><td><a href="{{ link }}">{{ title }}</a></td><td>{{ mtime }}</td><td style="text-align: right">{{ size }}</td></tr>
{% endfor %}
</table>
</body>

View File

@ -23,6 +23,7 @@ import types
import mock
import swiftclient # noqa needed for monkeypatching
import testtools
from os_loganalyze.tests import base
import os_loganalyze.util
@ -41,6 +42,8 @@ SEVS = {
SEVS_SEQ = ['NONE', 'DEBUG', 'INFO', 'AUDIT', 'TRACE', 'WARNING', 'ERROR']
ISO8601RE = r'\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d(.\d+)?'
# add up all the counts from a generator
def count_types(gen):
@ -107,6 +110,7 @@ def fake_get_container_factory(_swift_index_items=None):
index_items.append({'subdir': os.path.join(prefix, i)})
else:
index_items.append({'name': os.path.join(prefix, i),
'last_modified': '2042-12-31T23:59:59',
'bytes': 4200})
elif _swift_index_items == []:
name = prefix[len('non-existent/'):]
@ -117,6 +121,7 @@ def fake_get_container_factory(_swift_index_items=None):
{'subdir': os.path.join(prefix, i + '/')})
else:
index_items.append({'name': os.path.join(prefix, i),
'last_modified': '2042-12-31T23:59:59',
'bytes': 4200})
else:
# No swift container data.
@ -303,16 +308,18 @@ class TestWsgiDisk(base.TestCase):
full_lines = full.split('\n')
self.assertEqual('<!DOCTYPE html>', full_lines[0])
self.assertIn('samples/</title>', full_lines[3])
self.assertEqual(
' <tr><td><a href="/samples/console.html.gz">'
'console.html.gz</a></td><td style="text-align: right">'
'277.4KB</td></tr>',
full_lines[9])
self.assertEqual(
' <tr><td><a href="/samples/wsgi_plain.conf">'
'wsgi_plain.conf</a></td><td style="text-align: right">'
'177.0B</td></tr>',
full_lines[-5])
self.assertThat(
full_lines[9],
testtools.matchers.MatchesRegex(
r' <tr><td><a href="/samples/console.html.gz">'
r'console.html.gz</a></td><td>' + ISO8601RE + r'</td>'
r'<td style="text-align: right">277.4KB</td></tr>'))
self.assertThat(
full_lines[-5],
testtools.matchers.MatchesRegex(
r' <tr><td><a href="/samples/wsgi_plain.conf">'
r'wsgi_plain.conf</a></td><td>' + ISO8601RE + r'</td>'
r'<td style="text-align: right">177.0B</td></tr>'))
self.assertEqual('</html>', full_lines[-1])
@ -415,16 +422,18 @@ class TestWsgiSwift(TestWsgiDisk):
full_lines = full.split('\n')
self.assertEqual('<!DOCTYPE html>', full_lines[0])
self.assertIn('non-existent/</title>', full_lines[3])
self.assertEqual(
' <tr><td><a href="/non-existent/console.html.gz">'
'console.html.gz</a></td><td style="text-align: right">'
'4.1KB</td></tr>',
full_lines[9])
self.assertEqual(
' <tr><td><a href="/non-existent/wsgi_plain.conf">'
'wsgi_plain.conf</a></td><td style="text-align: right">'
'4.1KB</td></tr>',
full_lines[-5])
self.assertThat(
full_lines[9],
testtools.matchers.MatchesRegex(
r' <tr><td><a href="/non-existent/console.html.gz">'
r'console.html.gz</a></td><td>' + ISO8601RE + r'</td>'
r'<td style="text-align: right">4.1KB</td></tr>'))
self.assertThat(
full_lines[-5],
testtools.matchers.MatchesRegex(
r' <tr><td><a href="/non-existent/wsgi_plain.conf">'
r'wsgi_plain.conf</a></td><td>' + ISO8601RE + r'</td>'
r'<td style="text-align: right">4.1KB</td></tr>'))
self.assertEqual('</html>', full_lines[-1])
@mock.patch.object(swiftclient.client.Connection, 'get_container',
@ -444,30 +453,38 @@ class TestWsgiSwift(TestWsgiDisk):
full_lines = full.split('\n')
self.assertEqual('<!DOCTYPE html>', full_lines[0])
self.assertIn('samples/</title>', full_lines[3])
self.assertThat(
full_lines[9],
testtools.matchers.MatchesRegex(
r' <tr><td><a href="/samples/a">a</a></td>'
r'<td>' + ISO8601RE + r'</td>'
r'<td style="text-align: right">4.1KB</td></tr>'))
self.assertThat(
full_lines[11],
testtools.matchers.MatchesRegex(
r' <tr><td><a href="/samples/b">b</a></td>'
r'<td>' + ISO8601RE + r'</td>'
r'<td style="text-align: right">4.1KB</td></tr>'))
self.assertThat(
full_lines[13],
testtools.matchers.MatchesRegex(
r' <tr><td><a href="/samples/console.html.gz">'
r'console.html.gz</a></td><td>' + ISO8601RE + r'</td>'
r'<td style="text-align: right">277.4KB</td></tr>'))
self.assertEqual(
' <tr><td><a href="/samples/a">a</a></td>'
'<td style="text-align: right">4.1KB</td></tr>',
full_lines[9])
self.assertEqual(
' <tr><td><a href="/samples/b">b</a></td>'
'<td style="text-align: right">4.1KB</td></tr>',
full_lines[11])
self.assertEqual(
' <tr><td><a href="/samples/console.html.gz">'
'console.html.gz</a></td><td style="text-align: right">'
'277.4KB</td></tr>',
full_lines[13])
self.assertEqual(
full_lines[17],
' <tr><td><a href="/samples/dir/">dir/</a></td>'
'<td style="text-align: right">0.0B</td></tr>',
full_lines[17])
self.assertEqual(
' <tr><td><a href="/samples/wsgi_plain.conf">'
'wsgi_plain.conf</a></td><td style="text-align: right">'
'177.0B</td></tr>',
full_lines[-7])
self.assertEqual(
' <tr><td><a href="/samples/z">z</a></td>'
'<td style="text-align: right">4.1KB</td></tr>',
full_lines[-5])
'<td>unknown</td><td style="text-align: right">0.0B</td></tr>')
self.assertThat(
full_lines[-7],
testtools.matchers.MatchesRegex(
r' <tr><td><a href="/samples/wsgi_plain.conf">'
r'wsgi_plain.conf</a></td><td>' + ISO8601RE + r'</td>'
r'<td style="text-align: right">177.0B</td></tr>'))
self.assertThat(
full_lines[-5],
testtools.matchers.MatchesRegex(
r' <tr><td><a href="/samples/z">z</a></td>'
r'<td>' + ISO8601RE + r'</td>'
r'<td style="text-align: right">4.1KB</td></tr>'))
self.assertEqual('</html>', full_lines[-1])