Skip to content
Snippets Groups Projects
Commit b79fc519 authored by Nathaniel Kofalt's avatar Nathaniel Kofalt Committed by GitHub
Browse files

Merge pull request #794 from scitran/log-endpoints

Add plaintext and html endpoints for job logs
parents e1869cbe 3ab337a4
No related branches found
No related tags found
No related merge requests found
......@@ -135,9 +135,11 @@ endpoints = [
route('/add', JobsHandler, h='add', m=['POST']),
route('/<:[^/]+>', JobHandler),
route('/<:[^/]+>/config.json', JobHandler, h='get_config'),
route('/<:[^/]+>/retry', JobHandler, h='retry', m=['POST']),
route('/<:[^/]+>/logs', JobHandler, h='get_logs', m=['GET']),
route('/<:[^/]+>/logs', JobHandler, h='add_logs', m=['POST']),
route('/<:[^/]+>/retry', JobHandler, h='retry', m=['POST']),
route('/<:[^/]+>/logs', JobHandler, h='get_logs', m=['GET']),
route('/<:[^/]+>/logs/text', JobHandler, h='get_logs_text', m=['GET']),
route('/<:[^/]+>/logs/html', JobHandler, h='get_logs_html', m=['GET']),
route('/<:[^/]+>/logs', JobHandler, h='add_logs', m=['POST']),
]),
route('/gears', GearsHandler),
prefix('/gears', [
......
......@@ -17,7 +17,7 @@ from . import batch
from ..validators import validate_data
from .gears import validate_gear_config, get_gears, get_gear, get_invocation_schema, remove_gear, upsert_gear, suggest_container
from .jobs import Job
from .jobs import Job, Logs
from .queue import Queue
......@@ -330,9 +330,7 @@ class JobHandler(base.RequestHandler):
Queue.mutate(j, mutation)
def get_logs(self, _id):
"""Get a job's logs"""
def _log_read_check(self, _id):
try:
job = Job.get(_id)
except Exception: # pylint: disable=broad-except
......@@ -344,12 +342,35 @@ class JobHandler(base.RequestHandler):
job.inputs[x].check_access(self.uid, 'ro')
# Unlike jobs-add, explicitly not checking write access to destination.
log = config.db.job_logs.find_one({'_id': _id})
if log is None:
return { '_id': _id, 'logs': [] }
else:
return log
def get_logs(self, _id):
"""Get a job's logs"""
self._log_read_check(_id)
return Logs.get(_id)
def get_logs_text(self, _id):
"""Get a job's logs in raw text"""
self._log_read_check(_id)
self.response.headers['Content-Type'] = 'application/octet-stream'
self.response.headers['Content-Disposition'] = 'attachment; filename="job-' + _id + '-logs.txt"'
for output in Logs.get_text_generator(_id):
self.response.write(output)
return
def get_logs_html(self, _id):
"""Get a job's logs in html"""
self._log_read_check(_id)
for output in Logs.get_html_generator(_id):
self.response.write(output)
return
def add_logs(self, _id):
"""Add to a job's logs"""
......@@ -364,14 +385,7 @@ class JobHandler(base.RequestHandler):
except Exception: # pylint: disable=broad-except
self.abort(404, 'Job not found')
log = config.db.job_logs.find_one({'_id': _id})
if log is None: # Race
config.db.job_logs.insert_one({'_id': _id, 'logs': []})
config.db.job_logs.update({'_id': _id}, {'$push':{'logs':{'$each':doc}}})
return
return Logs.add(_id, doc)
def retry(self, _id):
""" Retry a job.
......
......@@ -274,3 +274,62 @@ class Job(object):
self.request = r
return self.request
class Logs(object):
@staticmethod
def get(_id):
log = config.db.job_logs.find_one({'_id': _id})
if log is None:
return { '_id': _id, 'logs': [] }
else:
return log
@staticmethod
def get_text_generator(_id):
log = config.db.job_logs.find_one({'_id': _id})
if log is None:
yield '<span class="fd--1">No logs were found for this job.</span>'
else:
for stanza in log['logs']:
msg = stanza['msg']
yield msg
@staticmethod
def get_html_generator(_id):
log = config.db.job_logs.find_one({'_id': _id})
if log is None:
yield '<span class="fd--1">No logs were found for this job.</span>'
else:
open_span = False
last = None
for stanza in log['logs']:
fd = stanza['fd']
msg = stanza['msg']
if fd != last:
if open_span:
yield '</span>\n'
yield '<span class="fd-' + str(fd) + '">'
open_span = True
last = fd
yield msg.replace('\n', '<br/>\n')
if open_span:
yield '</span>\n'
@staticmethod
def add(_id, doc):
log = config.db.job_logs.find_one({'_id': _id})
if log is None: # Race
config.db.job_logs.insert_one({'_id': _id, 'logs': []})
config.db.job_logs.update({'_id': _id}, {'$push':{'logs':{'$each':doc}}})
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment