Add simple visualization

This commit is contained in:
Peter J. Holzer 2022-11-20 18:43:45 +01:00
parent a79aac5cfd
commit 81fa412202
4 changed files with 159 additions and 1 deletions

11
app.py
View File

@ -4,7 +4,7 @@ import json
import logging
import os
from flask import (Flask, request, jsonify, abort)
from flask import (Flask, request, jsonify, abort, render_template)
from ltsdb_json import LTS
@ -108,3 +108,12 @@ def verify_node(d):
else:
abort(409, "timestamp out of sync")
abort(401, "auth failed")
@app.get("/v")
def visualize():
timeseries_ids = request.args.getlist("ts")
timeseries_data = []
for id in timeseries_ids:
ts = LTS(id=id)
timeseries_data.append(ts)
return render_template("visualize.html", ts=timeseries_data)

75
clients/report_tlscert Executable file
View File

@ -0,0 +1,75 @@
#!/usr/bin/python3
import argparse
import hmac
import json
import os
import socket
import ssl
import time
import requests
ap = argparse.ArgumentParser()
ap.add_argument("hostname")
ap.add_argument("port", type=int, default=443, nargs="?")
args = ap.parse_args()
# It's a bit weird that this works.
myhostname = socket.gethostbyaddr(socket.gethostname())[0]
now = time.time()
report0 = []
with socket.create_connection((args.hostname, args.port)) as sock:
context = ssl.create_default_context()
with context.wrap_socket(sock, server_hostname=args.hostname) as ssock:
cert = ssock.getpeercert()
not_after = ssl.cert_time_to_seconds(cert["notAfter"])
delta = not_after - now
report0.append({ "measure": "tls_cert_ttl", "unit": "s", "value": delta })
report = [
{
"description": {
"hostname": args.hostname,
"port": args.port,
"measure": r["measure"],
"unit": r["unit"]
},
"data": [
[now, r["value"]]
]
}
for r in report0
]
for dir in (".", os.environ["HOME"] + "/.config/ltsdb", "/etc/ltsdb"):
try:
with open(dir + "/config.json") as fh:
client_config = json.load(fh)
baseurl = client_config["server"]
break
except FileNotFoundError:
pass
while True:
for r in report:
node = myhostname
timestamp = time.time()
msg = (node + " " + str(timestamp)).encode("UTF-8")
digest = hmac.new(client_config["key"].encode("UTF-8"), msg, "SHA256").hexdigest()
r["auth"] = {
"node": node,
"timestamp": timestamp,
"hmac": digest,
}
#pprint.pp(report)
r = requests.post(baseurl + "report", json=report)
print(r)
if r.status_code == 200:
exit(0)
elif r.status_code == 409:
time.sleep(0.5 + random.random())
continue
else:
exit(1)

View File

@ -90,3 +90,12 @@ class LTS:
result &= ts
return result
def data_json_by_row(self):
d = []
for dp in self.data:
d.append({
"t": dp[0],
"v": dp[1],
"utc": time.strftime("%Y-%m-%dT%H:%M:%S", time.gmtime(dp[0])),
})
return json.dumps(d)

65
templates/visualize.html Normal file
View File

@ -0,0 +1,65 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width; initial-scale=1">
<meta charset="utf-8">
<script src="https://cdn.jsdelivr.net/npm/vega@5.22.1"></script>
<script src="https://cdn.jsdelivr.net/npm/vega-lite@5.6.0"></script>
<script src="https://cdn.jsdelivr.net/npm/vega-embed@6.21.0"></script>
<style>
body {
font-family: sans-serif;
}
.vega {
width: min(90vw, 1000px);
}
th {
text-align: left;
}
</style>
</head>
<body>
{% for t in ts %}
<table>
{% for k, v in t.description.items() %}
<tr>
<th> {{ k }} </th>
<td> {{ v }} </td>
</tr>
{% endfor %}
<tr>
<th> period </th>
<td>
{{ t.data[0][0] }} .. {{ t.data[-1][0] }}
</td>
</tr>
</table>
<div id="vis{{loop.index}}" class="vega">
</div>
<script>
{
const d = {
width: "container",
data: {
values: {{ t.data_json_by_row() | safe }}
},
mark: "point",
encoding: {
x: {
field: "utc",
// type: "quantitative",
type: "temporal",
//scale: { domain: [{{t.data[0][0]}}, {{t.data[-1][0]}}] },
},
y: { field: "v", type: "quantitative" },
},
}
vegaEmbed("#vis{{loop.index}}", d)
}
</script>
{% endfor %}
</body>
</html>