mirror of
https://github.com/lubuntu-team/metrics.git
synced 2025-07-03 21:51:30 +00:00
Add a very crude web view.
This commit is contained in:
parent
25b9ecf7a9
commit
36ac2eb5fd
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
|||||||
__pycache__
|
__pycache__
|
||||||
*.sqlite
|
*.sqlite
|
||||||
|
output
|
||||||
|
28
metrics
28
metrics
@ -32,6 +32,7 @@ def sqlite_run(command, db, return_output=False):
|
|||||||
conn = sqlite3.connect(db)
|
conn = sqlite3.connect(db)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
for cmd in command:
|
for cmd in command:
|
||||||
|
log.debug("Executing: %s" % cmd)
|
||||||
c.execute(cmd)
|
c.execute(cmd)
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
|
||||||
@ -48,16 +49,25 @@ def sqlite_run(command, db, return_output=False):
|
|||||||
|
|
||||||
def main(module):
|
def main(module):
|
||||||
"""Given a specific module, set it up and insert recent values"""
|
"""Given a specific module, set it up and insert recent values"""
|
||||||
module = module()
|
|
||||||
run = []
|
|
||||||
run.append(module.sqlite_setup())
|
|
||||||
run.append(module.sqlite_add())
|
|
||||||
#run.append(module.sqlite_time_range(days=10))
|
|
||||||
log.debug("Commands to be ran: " + str(run))
|
|
||||||
|
|
||||||
# Use --db-location to pass to sqlite
|
# Initialize the module
|
||||||
log.info("Running SQLite commands")
|
module = module()
|
||||||
log.debug(sqlite_run(run, db=args.db_location, return_output=True))
|
|
||||||
|
# Stage the setup commands to be ran and run them
|
||||||
|
run = [module.sqlite_setup(), module.sqlite_add()]
|
||||||
|
log.debug(sqlite_run(run, db=args.db_location))
|
||||||
|
|
||||||
|
# Pull some useful data and have the module render a template
|
||||||
|
# The output is in MODULENAME_DAYday.html
|
||||||
|
# This generates a report for each of the given day windows
|
||||||
|
for day in (1, 7, 30, 90, 180):
|
||||||
|
# Fetch the data and log to debug
|
||||||
|
run = [module.sqlite_time_range(days=day)]
|
||||||
|
data = sqlite_run(run, db=args.db_location, return_output=True)
|
||||||
|
log.debug(data)
|
||||||
|
|
||||||
|
# Render the template
|
||||||
|
module.render_template(day, data)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
@ -20,7 +20,8 @@ import requests_cache
|
|||||||
import time
|
import time
|
||||||
from jenkinsapi.custom_exceptions import NoBuildData
|
from jenkinsapi.custom_exceptions import NoBuildData
|
||||||
from jenkinsapi.jenkins import Jenkins
|
from jenkinsapi.jenkins import Jenkins
|
||||||
from os import getenv
|
from jinja2 import Template
|
||||||
|
from os import getenv, makedirs, path
|
||||||
|
|
||||||
requests_cache.install_cache("jenkins", backend="sqlite", expire_after=300)
|
requests_cache.install_cache("jenkins", backend="sqlite", expire_after=300)
|
||||||
|
|
||||||
@ -131,3 +132,58 @@ class JenkinsModule:
|
|||||||
command = "SELECT * FROM jenkins WHERE date > %s;" % unix_time
|
command = "SELECT * FROM jenkins WHERE date > %s;" % unix_time
|
||||||
|
|
||||||
return command
|
return command
|
||||||
|
|
||||||
|
def render_template(self, days, data):
|
||||||
|
"""Render a template with days in the filename, given the data
|
||||||
|
|
||||||
|
The above function sqlite_time_range() is ran on the database with
|
||||||
|
some predetermined date ranges. This function actually interprets that
|
||||||
|
data, uses Jinja2 to magically render a template, and voila.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Initialize a (softly) ephemeral dict to store data
|
||||||
|
jenkins = {}
|
||||||
|
_data = {"date": [], "nonpassing": [], "failing": [], "total": []}
|
||||||
|
|
||||||
|
# Put the data from the DB query into _data
|
||||||
|
for row in data:
|
||||||
|
_data["date"].append(row[0])
|
||||||
|
_data["nonpassing"].append(row[1])
|
||||||
|
_data["failing"].append(row[2])
|
||||||
|
_data["total"].append(row[3])
|
||||||
|
|
||||||
|
# Get human-readable averages and throw it in a dict
|
||||||
|
_nonpassing = sum(_data["nonpassing"]) / len(_data["nonpassing"])
|
||||||
|
_nonpassing = format(_nonpassing, ".1f")
|
||||||
|
_failing = sum(_data["failing"]) / len(_data["failing"])
|
||||||
|
_failing = format(_failing, ".1f")
|
||||||
|
_total = sum(_data["total"]) / len(_data["total"])
|
||||||
|
_total = format(_total, ".1f")
|
||||||
|
average = {"nonpassing": _nonpassing,
|
||||||
|
"failing": _failing,
|
||||||
|
"total": _total}
|
||||||
|
|
||||||
|
# Assign data to the dict Jinja2 is actually going to use
|
||||||
|
jenkins = {"nonpassing": zip(_data["date"], _data["nonpassing"]),
|
||||||
|
"failing": zip(_data["date"], _data["failing"]),
|
||||||
|
"total": zip(_data["date"], _data["total"])}
|
||||||
|
|
||||||
|
# Grab our template from templates/ and store it as a Template
|
||||||
|
t_path = path.join("templates", "jenkins.html")
|
||||||
|
with open(t_path) as templatef:
|
||||||
|
template = ""
|
||||||
|
for text in templatef.readlines():
|
||||||
|
template += text
|
||||||
|
template = Template(template)
|
||||||
|
|
||||||
|
# Render the template
|
||||||
|
template = template.render(jenkins=jenkins, average=average, days=days)
|
||||||
|
|
||||||
|
# Make the output dir if it doesn't already exist
|
||||||
|
if not path.exists("output"):
|
||||||
|
makedirs("output")
|
||||||
|
|
||||||
|
# Write it back to the filename in the output dir
|
||||||
|
with open(path.join("output", "jenkins_%sdays.html" % days),
|
||||||
|
"w+") as f:
|
||||||
|
f.write(template)
|
||||||
|
92
templates/jenkins.html
Normal file
92
templates/jenkins.html
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<!-- HTML5 compliance -->
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
|
||||||
|
<!-- Import Chart.js 2.9.3 -->
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.js"></script>
|
||||||
|
|
||||||
|
<!-- Import Bootstrap 4.3.1 -->
|
||||||
|
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col" style="text-align: center;">
|
||||||
|
<h1>Jenkins data for the past {{ days }} day(s)</h1>
|
||||||
|
<canvas id="jenkinschart"></canvas>
|
||||||
|
<h2>Average number of failing jobs: {{ average.failing }}</h2>
|
||||||
|
<h2>Average number of non-passing jobs: {{ average.nonpassing }}</h2>
|
||||||
|
<h2>Average number of total jobs: {{ average.total }}</h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- This is the actual chart functionality -->
|
||||||
|
<script>
|
||||||
|
var ctx = document.getElementById("jenkinschart").getContext("2d");
|
||||||
|
|
||||||
|
var myChart = new Chart(ctx, {
|
||||||
|
type: 'line',
|
||||||
|
data: {
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: 'Failing Jobs',
|
||||||
|
backgroundColor: "#FF0000",
|
||||||
|
//borderColor: "#FF0000",
|
||||||
|
data: [
|
||||||
|
{% for timestamp, num in jenkins.failing %}
|
||||||
|
{
|
||||||
|
t: new Date({{ timestamp }} * 1000),
|
||||||
|
y: {{ num }}
|
||||||
|
},
|
||||||
|
{% endfor %}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Non-passing Jobs',
|
||||||
|
backgroundColor: "#FFFF00",
|
||||||
|
//borderColor: "#FFFF00",
|
||||||
|
data: [
|
||||||
|
{% for timestamp, num in jenkins.nonpassing %}
|
||||||
|
{
|
||||||
|
t: new Date({{ timestamp }} * 1000),
|
||||||
|
y: {{ num }}
|
||||||
|
},
|
||||||
|
{% endfor %}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Total Jobs',
|
||||||
|
backgroundColor: "#003A72",
|
||||||
|
//borderColor: "#003A72",
|
||||||
|
data: [
|
||||||
|
{% for timestamp, num in jenkins.total %}
|
||||||
|
{
|
||||||
|
t: new Date({{ timestamp }} * 1000),
|
||||||
|
y: {{ num }}
|
||||||
|
},
|
||||||
|
{% endfor %}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
scales: {
|
||||||
|
xAxes: [{
|
||||||
|
type: 'time',
|
||||||
|
time: {
|
||||||
|
unit: 'day'
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
x
Reference in New Issue
Block a user