diff --git a/lib/galaxy/webapps/reports/controllers/jobs.py b/lib/galaxy/webapps/reports/controllers/jobs.py
index de3edcb1ead..848d38829f0 100644
--- a/lib/galaxy/webapps/reports/controllers/jobs.py
+++ b/lib/galaxy/webapps/reports/controllers/jobs.py
@@ -1,3 +1,4 @@
+from __future__ import print_function
import calendar
from collections import namedtuple
from datetime import datetime, date, timedelta
@@ -7,6 +8,7 @@ from galaxy.web.framework.helpers import grids
from galaxy.model.orm import and_, not_, or_
import pkg_resources
pkg_resources.require( "SQLAlchemy >= 0.4" )
+import re
import sqlalchemy as sa
from galaxy.webapps.reports.controllers.query import ReportQueryBuilder
@@ -271,6 +273,7 @@ class Jobs( BaseUIController, ReportQueryBuilder ):
month_label = start_date.strftime( "%B" )
year_label = start_date.strftime( "%Y" )
+ # Use to make the page table
month_jobs = sa.select( ( sa.func.date( model.Job.table.c.create_time ).label( 'date' ),
sa.func.count( model.Job.table.c.id ).label( 'total_jobs' ) ),
whereclause=sa.and_( model.Job.table.c.user_id != monitor_user_id,
@@ -280,13 +283,32 @@ class Jobs( BaseUIController, ReportQueryBuilder ):
group_by=[ 'date' ],
order_by=[ _order ] )
+ # Use to make trendline
+ all_jobs = sa.select( ( model.Job.table.c.create_time.label('date'), model.Job.table.c.id.label('id') ),
+ whereclause=sa.and_( model.Job.table.c.user_id != monitor_user_id,
+ model.Job.table.c.create_time >= start_date,
+ model.Job.table.c.create_time < end_date ) )
+
+ trend = [0] * 24
jobs = []
for row in month_jobs.execute():
- jobs.append( ( row.date.strftime( "%A" ),
- row.date.strftime( "%d" ),
+ trend = [0] * 24
+
+ row_dayname = row.date.strftime( "%A" )
+ row_day = row.date.strftime( "%d" )
+
+ for job in all_jobs.execute():
+ if row_day == job.date.strftime( "%d" ):
+ hour = int( job.date.strftime( "%-H" ) ) - 1
+ trend[hour] += 1
+
+ jobs.append( ( row_dayname,
+ row_day,
row.total_jobs,
- row.date
+ row.date,
+ trend
) )
+
return trans.fill_template( '/webapps/reports/jobs_specified_month_all.mako',
order=order,
arrow=arrow,
@@ -334,12 +356,33 @@ class Jobs( BaseUIController, ReportQueryBuilder ):
group_by=[ 'date' ],
order_by=[ _order ] )
+ # Use to make trendline
+ all_jobs_in_error = sa.select( ( model.Job.table.c.create_time.label('date'), model.Job.table.c.id.label('id') ),
+ whereclause=sa.and_( model.Job.table.c.user_id != monitor_user_id,
+ model.Job.table.c.state == 'error',
+ model.Job.table.c.create_time >= start_date,
+ model.Job.table.c.create_time < end_date ) )
+
+ trend = [0] * 24
jobs = []
for row in month_jobs_in_error.execute():
- jobs.append( ( row.date.strftime( "%A" ),
- row.date,
+ trend = [0] * 24
+
+ row_dayname = row.date.strftime( "%A" )
+ row_day = row.date.strftime( "%d" )
+
+ for job in all_jobs_in_error.execute():
+ if row_day == job.date.strftime( "%d" ):
+ hour = int( job.date.strftime( "%-H" ) ) - 1
+ trend[hour] += 1
+
+ jobs.append( ( row_dayname,
+ row_day,
row.total_jobs,
- row.date.strftime( "%d" ) ) )
+ row.date,
+ trend
+ ) )
+
return trans.fill_template( '/webapps/reports/jobs_specified_month_in_error.mako',
order=order,
arrow=arrow,
@@ -369,26 +412,52 @@ class Jobs( BaseUIController, ReportQueryBuilder ):
# In case we don't know which is the monitor user we will query for all jobs
monitor_user_id = get_monitor_id( trans, monitor_email )
+ # Use to make the page table
jobs_by_month = sa.select( ( self.select_month( model.Job.table.c.create_time ).label( 'date' ),
- sa.func.count( model.Job.table.c.id ).label( 'total_jobs' ) ),
+ sa.func.count( model.Job.table.c.id ).label( 'total_jobs' ) ),
whereclause=model.Job.table.c.user_id != monitor_user_id,
from_obj=[ model.Job.table ],
group_by=self.group_by_month( model.Job.table.c.create_time ),
order_by=[ _order ] )
+ # Use to make sparkline
+ all_jobs = sa.select( ( self.select_month(model.Job.table.c.create_time).label('date'), model.Job.table.c.id.label('id') ) )
+
+ trends = dict()
+ for job in all_jobs.execute():
+ job_day = int(job.date.strftime("%-d")) - 1
+ job_month = int(job.date.strftime("%-m"))
+ job_month_name = job.date.strftime("%B")
+ job_year = job.date.strftime("%Y")
+ key = str( job_month_name + job_year)
+
+ try:
+ trends[key][job_day] += 1
+ except KeyError:
+ job_year = int(job_year)
+ wday, day_range = calendar.monthrange(job_year, job_month)
+ trends[key] = [0] * day_range
+ trends[key][job_day] += 1
+
jobs = []
for row in jobs_by_month.execute():
+ month = int(row.date.strftime("%-m"))
+ month_name = row.date.strftime("%B")
+ year = int(row.date.strftime("%Y"))
+ wday, day_range = calendar.monthrange(year, month)
+
jobs.append( (
row.date.strftime( "%Y-%m" ),
row.total_jobs,
- row.date.strftime( "%B" ),
- row.date.strftime( "%y" )
+ month_name,
+ year
) )
return trans.fill_template( '/webapps/reports/jobs_per_month_all.mako',
order=order,
arrow=arrow,
sort_id=sort_id,
+ trends=trends,
jobs=jobs,
is_user_jobs_only=monitor_user_id,
message=message )
@@ -411,6 +480,7 @@ class Jobs( BaseUIController, ReportQueryBuilder ):
# In case we don't know which is the monitor user we will query for all jobs
monitor_user_id = get_monitor_id( trans, monitor_email )
+ # Use to make the page table
jobs_in_error_by_month = sa.select( ( self.select_month( model.Job.table.c.create_time ).label( 'date' ),
sa.func.count( model.Job.table.c.id ).label( 'total_jobs' ) ),
whereclause=sa.and_( model.Job.table.c.state == 'error',
@@ -419,12 +489,40 @@ class Jobs( BaseUIController, ReportQueryBuilder ):
group_by=self.group_by_month( model.Job.table.c.create_time ),
order_by=[ _order ] )
+ # Use to make trendline
+ all_jobs = sa.select( ( self.select_month(model.Job.table.c.create_time).label('date'), model.Job.table.c.id.label('id') ),
+ whereclause=sa.and_( model.Job.table.c.state == 'error',
+ model.Job.table.c.user_id != monitor_user_id ))
+
+ trends = dict()
+ for job in all_jobs.execute():
+ job_day = int(job.date.strftime("%-d")) - 1
+ job_month = int(job.date.strftime("%-m"))
+ job_month_name = job.date.strftime("%B")
+ job_year = job.date.strftime("%Y")
+ key = str( job_month_name + job_year)
+
+ try:
+ trends[key][job_day] += 1
+ except KeyError:
+ job_year = int(job_year)
+ wday, day_range = calendar.monthrange(job_year, job_month)
+ trends[key] = [0] * day_range
+ trends[key][job_day] += 1
+
jobs = []
for row in jobs_in_error_by_month.execute():
- jobs.append( ( row.date.strftime( "%Y-%m" ),
- row.total_jobs,
- row.date.strftime( "%B" ),
- row.date.strftime( "%y" ) ) )
+ month = int(row.date.strftime("%-m"))
+ month_name = row.date.strftime("%B")
+ year = int(row.date.strftime("%Y"))
+ wday, day_range = calendar.monthrange(year, month)
+
+ jobs.append( (
+ row.date.strftime( "%Y-%m" ),
+ row.total_jobs,
+ month_name,
+ year
+ ) )
return trans.fill_template( '/webapps/reports/jobs_per_month_in_error.mako',
order=order,
arrow=arrow,
@@ -443,6 +541,7 @@ class Jobs( BaseUIController, ReportQueryBuilder ):
order = specs.order
arrow = specs.arrow
_order = specs.exc_order
+ day_limit = 50
jobs = []
jobs_per_user = sa.select( ( model.User.table.c.email.label( 'user_email' ),
@@ -450,6 +549,28 @@ class Jobs( BaseUIController, ReportQueryBuilder ):
from_obj=[ sa.outerjoin( model.Job.table, model.User.table ) ],
group_by=[ 'user_email' ],
order_by=[ _order ] )
+
+ all_jobs_per_user = sa.select( ( self.select_month( model.Job.table.c.create_time ).label( 'date' ),
+ model.Job.table.c.id.label( 'id' ),
+ model.User.table.c.email.label( 'user_email' ) ),
+ from_obj=[ sa.outerjoin( model.Job.table, model.User.table ) ] )
+
+ currday = datetime.today().date()
+ trends = dict()
+ for job in all_jobs_per_user.execute():
+ curr_user = re.sub(r'\W+', '', job.user_email)
+ try:
+ day = currday - job.date
+ day = day.days
+ if day < day_limit:
+ trends[curr_user][day] += 1
+ except KeyError:
+ trends[curr_user] = [0] * day_limit
+ day = currday - job.date
+ day = day.days
+ if day < day_limit:
+ trends[curr_user][day] += 1
+
for row in jobs_per_user.execute():
if ( row.user_email is None ):
jobs.append( ( 'Anonymous',
@@ -459,10 +580,13 @@ class Jobs( BaseUIController, ReportQueryBuilder ):
else:
jobs.append( ( row.user_email,
row.total_jobs ) )
+
return trans.fill_template( '/webapps/reports/jobs_per_user.mako',
order=order,
arrow=arrow,
sort_id=sort_id,
+ day_limit=day_limit,
+ trends=trends,
jobs=jobs,
message=message )
@@ -477,6 +601,7 @@ class Jobs( BaseUIController, ReportQueryBuilder ):
order = specs.order
arrow = specs.arrow
_order = specs.exc_order
+
q = sa.select( ( self.select_month( model.Job.table.c.create_time ).label( 'date' ),
sa.func.count( model.Job.table.c.id ).label( 'total_jobs' ) ),
whereclause=sa.and_( model.Job.table.c.session_id == model.GalaxySession.table.c.id,
@@ -485,6 +610,30 @@ class Jobs( BaseUIController, ReportQueryBuilder ):
from_obj=[ sa.join( model.Job.table, model.User.table ) ],
group_by=self.group_by_month( model.Job.table.c.create_time ),
order_by=[ _order ] )
+
+ all_jobs_per_user = sa.select( ( model.Job.table.c.create_time.label( 'date' ),
+ model.Job.table.c.id.label( 'job_id' ) ),
+ whereclause=sa.and_( model.Job.table.c.session_id == model.GalaxySession.table.c.id,
+ model.GalaxySession.table.c.user_id == model.User.table.c.id,
+ model.User.table.c.email == email),
+ from_obj=[ sa.join( model.Job.table, model.User.table ) ] )
+
+ trends = dict()
+ for job in all_jobs_per_user.execute():
+ job_day = int(job.date.strftime("%-d")) - 1
+ job_month = int(job.date.strftime("%-m"))
+ job_month_name = job.date.strftime("%B")
+ job_year = job.date.strftime("%Y")
+ key = str( job_month_name + job_year)
+
+ try:
+ trends[key][job_day] += 1
+ except KeyError:
+ job_year = int(job_year)
+ wday, day_range = calendar.monthrange(job_year, job_month)
+ trends[key] = [0] * day_range
+ trends[key][job_day] += 1
+
jobs = []
for row in q.execute():
jobs.append( ( row.date.strftime( "%Y-%m" ),
@@ -496,6 +645,7 @@ class Jobs( BaseUIController, ReportQueryBuilder ):
arrow=arrow,
sort_id=sort_id,
id=kwd.get('id'),
+ trends=trends,
email=util.sanitize_text( email ),
jobs=jobs, message=message )
@@ -510,6 +660,8 @@ class Jobs( BaseUIController, ReportQueryBuilder ):
order = specs.order
arrow = specs.arrow
_order = specs.exc_order
+ day_limit = 50
+
# In case we don't know which is the monitor user we will query for all jobs
monitor_user_id = get_monitor_id( trans, monitor_email )
@@ -520,13 +672,38 @@ class Jobs( BaseUIController, ReportQueryBuilder ):
from_obj=[ model.Job.table ],
group_by=[ 'tool_id' ],
order_by=[ _order ] )
+
+ all_jobs_per_tool = sa.select( ( self.select_month( model.Job.table.c.create_time ).label( 'date' ),
+ model.Job.table.c.id.label( 'id' ),
+ model.Job.table.c.tool_id.label( 'tool_id' ) ),
+ from_obj=[ model.Job.table ] )
+
+ currday = datetime.today().date()
+ trends = dict()
+ for job in all_jobs_per_tool.execute():
+ curr_tool = re.sub(r'\W+', '', job.tool_id)
+ try:
+ day = currday - job.date
+ day = day.days
+ if day < day_limit:
+ trends[curr_tool][day] += 1
+ except KeyError:
+ trends[curr_tool] = [0] * day_limit
+ day = currday - job.date
+ day = day.days
+ if day < day_limit:
+ trends[curr_tool][day] += 1
+
for row in q.execute():
jobs.append( ( row.tool_id,
row.total_jobs ) )
+
return trans.fill_template( '/webapps/reports/jobs_per_tool.mako',
order=order,
arrow=arrow,
sort_id=sort_id,
+ day_limit=day_limit,
+ trends=trends,
jobs=jobs,
message=message,
is_user_jobs_only=monitor_user_id)
@@ -545,6 +722,7 @@ class Jobs( BaseUIController, ReportQueryBuilder ):
order = specs.order
arrow = specs.arrow
_order = specs.exc_order
+ day_limit = 50
# In case we don't know which is the monitor user we will query for all jobs
monitor_user_id = get_monitor_id( trans, monitor_email )
@@ -555,6 +733,31 @@ class Jobs( BaseUIController, ReportQueryBuilder ):
from_obj=[ model.Job.table ],
group_by=[ 'tool_id' ],
order_by=[ _order ] )
+
+ all_jobs_per_tool_errors = sa.select( ( self.select_month( model.Job.table.c.create_time ).label( 'date' ),
+ model.Job.table.c.id.label( 'id' ),
+ model.Job.table.c.tool_id.label( 'tool_id' ) ),
+ whereclause=sa.and_( model.Job.table.c.state == 'error',
+ model.Job.table.c.user_id != monitor_user_id ),
+ from_obj=[ model.Job.table ]
+ )
+
+ currday = datetime.today().date()
+ trends = dict()
+ for job in all_jobs_per_tool_errors.execute():
+ curr_tool = re.sub(r'\W+', '', job.tool_id)
+ try:
+ day = currday - job.date
+ day = day.days
+ if day < day_limit:
+ trends[curr_tool][day] += 1
+ except KeyError:
+ trends[curr_tool] = [0] * day_limit
+ day = currday - job.date
+ day = day.days
+ if day < day_limit:
+ trends[curr_tool][day] += 1
+
jobs = []
for row in jobs_in_error_per_tool.execute():
jobs.append( ( row.total_jobs, row.tool_id ) )
@@ -562,6 +765,8 @@ class Jobs( BaseUIController, ReportQueryBuilder ):
order=order,
arrow=arrow,
sort_id=sort_id,
+ day_limit=day_limit,
+ trends=trends,
jobs=jobs,
message=message,
is_user_jobs_only=monitor_user_id )
@@ -589,6 +794,28 @@ class Jobs( BaseUIController, ReportQueryBuilder ):
from_obj=[ model.Job.table ],
group_by=self.group_by_month( model.Job.table.c.create_time ),
order_by=[ _order ] )
+
+ # Use to make sparkline
+ all_jobs_for_tool = sa.select( ( self.select_month(model.Job.table.c.create_time).label('date'), model.Job.table.c.id.label('id') ),
+ whereclause=sa.and_( model.Job.table.c.tool_id == tool_id,
+ model.Job.table.c.user_id != monitor_user_id ),
+ from_obj=[ model.Job.table ] )
+ trends = dict()
+ for job in all_jobs_for_tool.execute():
+ job_day = int(job.date.strftime("%-d")) - 1
+ job_month = int(job.date.strftime("%-m"))
+ job_month_name = job.date.strftime("%B")
+ job_year = job.date.strftime("%Y")
+ key = str( job_month_name + job_year)
+
+ try:
+ trends[key][job_day] += 1
+ except KeyError:
+ job_year = int(job_year)
+ wday, day_range = calendar.monthrange(job_year, job_month)
+ trends[key] = [0] * day_range
+ trends[key][job_day] += 1
+
jobs = []
for row in q.execute():
jobs.append( ( row.date.strftime( "%Y-%m" ),
@@ -601,6 +828,7 @@ class Jobs( BaseUIController, ReportQueryBuilder ):
sort_id=sort_id,
specified_date=specified_date,
tool_id=tool_id,
+ trends=trends,
jobs=jobs,
message=message,
is_user_jobs_only=monitor_user_id )
diff --git a/templates/base.mako b/templates/base.mako
index dba96d2d483..0752855bd95 100644
--- a/templates/base.mako
+++ b/templates/base.mako
@@ -48,6 +48,7 @@
"libs/jquery/jquery",
"libs/jquery/jquery.migrate",
"libs/jquery/select2",
+ "libs/jquery.sparklines",
"libs/bootstrap",
"libs/underscore",
"libs/backbone/backbone",
diff --git a/templates/webapps/reports/jobs_errors_per_tool.mako b/templates/webapps/reports/jobs_errors_per_tool.mako
index 6977be38960..6ce25222959 100644
--- a/templates/webapps/reports/jobs_errors_per_tool.mako
+++ b/templates/webapps/reports/jobs_errors_per_tool.mako
@@ -1,18 +1,26 @@
<%inherit file="/base.mako"/>
<%namespace file="/message.mako" import="render_msg" />
+<%namespace file="/spark_base.mako" import="jqs_style, make_sparkline" />
<%namespace file="/sorting_base.mako" import="get_sort_url, get_css" />
+<%!
+ import re
+%>
%if message:
${render_msg( message, 'done' )}
%endif
+${jqs_style()}
${get_css()}