Browse Source

First charts for ping rendering

master
amki 4 years ago
parent
commit
56a412108f
  1. 12
      ISPChk/Controllers/HostController.cs
  2. 2
      ISPChk/Models/Host.cs
  3. 4
      ISPChk/Models/PingItem.cs
  4. 30
      ISPChk/NetworkTest.cs
  5. 6
      ISPChk/Properties/launchSettings.json
  6. BIN
      ISPChk/ispchk.db
  7. BIN
      ISPChk/ispchk.db-shm
  8. BIN
      ISPChk/ispchk.db-wal
  9. 4
      ISPChk/libman.json
  10. 20776
      ISPChk/wwwroot/Chart.js/Chart.bundle.js
  11. 7
      ISPChk/wwwroot/Chart.js/Chart.bundle.min.js
  12. 47
      ISPChk/wwwroot/Chart.js/Chart.css
  13. 16172
      ISPChk/wwwroot/Chart.js/Chart.js
  14. 1
      ISPChk/wwwroot/Chart.js/Chart.min.css
  15. 7
      ISPChk/wwwroot/Chart.js/Chart.min.js
  16. 37
      ISPChk/wwwroot/index.html
  17. 146
      ISPChk/wwwroot/ispchk.js

12
ISPChk/Controllers/HostController.cs

@ -45,9 +45,9 @@ namespace ISPChk.Controllers
// GET: api/Host/5 // GET: api/Host/5
[HttpGet("{id}/pings/{start}/{end?}")] [HttpGet("{id}/pings/{start}/{end?}")]
public async Task<ActionResult<Host>> GetPingsByTimeSpan(long id, long start, long end) public async Task<ActionResult<IEnumerable<PingItem>>> GetPingsByTimeSpan(long id, long start, long end)
{ {
System.Diagnostics.Debug.WriteLine("called"); System.Diagnostics.Debug.WriteLine("called id:" + id + " start:" + start + " end:" + end);
var host = await _context.Hosts.FindAsync(id); var host = await _context.Hosts.FindAsync(id);
if (host == null) if (host == null)
@ -55,7 +55,13 @@ namespace ISPChk.Controllers
return NotFound(); return NotFound();
} }
return host; var startTime = DateTimeOffset.FromUnixTimeMilliseconds(start);
var endTime = DateTimeOffset.FromUnixTimeMilliseconds(end);
_context.Entry(host).Collection(h => h.PingItems).Load();
var pis = host.PingItems.Where(p => p.Date > startTime).ToList();
return pis;
} }
// PUT: api/Host/5 // PUT: api/Host/5

2
ISPChk/Models/Host.cs

@ -10,6 +10,8 @@ namespace ISPChk.Models
public long HostId { get; set; } public long HostId { get; set; }
public string Name { get; set; } public string Name { get; set; }
public string HostName { get; set; } public string HostName { get; set; }
public bool Ping { get; set; }
public bool TCP { get; set; }
public List<PingItem> PingItems { get; set; } public List<PingItem> PingItems { get; set; }
} }

4
ISPChk/Models/PingItem.cs

@ -10,11 +10,11 @@ namespace ISPChk.Models
{ {
[Key] [Key]
public long PingId { get; set; } public long PingId { get; set; }
public DateTime Date { get; set; } public DateTimeOffset Date { get; set; }
public float Min { get; set; } public float Min { get; set; }
public float Max { get; set; } public float Max { get; set; }
public float Avg { get; set; } public float Avg { get; set; }
public int Failures { get; set; }
public long HostId { get; set; } public long HostId { get; set; }
public Host Host { get; set; }
} }
} }

30
ISPChk/NetworkTest.cs

@ -31,11 +31,10 @@ namespace ISPChk
} }
} }
public void AddHost(Host host) private void StartPing(Host host)
{ {
System.Diagnostics.Debug.WriteLine("Host added!");
var t = Task.Run(async () => { var t = Task.Run(async () => {
Ping pingSender = new Ping(); Ping pingSender = new Ping();
// Create a buffer of 32 bytes of data to be transmitted. // Create a buffer of 32 bytes of data to be transmitted.
@ -55,11 +54,12 @@ namespace ISPChk
while (true) while (true)
{ {
long min = timeout+1; long min = timeout + 1;
long max = 0; long max = 0;
long avg = 0; long avg = 0;
int successes = 0; int successes = 0;
for(var i=0;i<5;++i) int failures = 0;
for (var i = 0; i < 5; ++i)
{ {
// Send the request. // Send the request.
PingReply reply = pingSender.Send(host.HostName, timeout, buffer, options); PingReply reply = pingSender.Send(host.HostName, timeout, buffer, options);
@ -71,33 +71,41 @@ namespace ISPChk
": bytes=" + reply.Buffer.Length + ": bytes=" + reply.Buffer.Length +
" time=" + reply.RoundtripTime + "ms"); " time=" + reply.RoundtripTime + "ms");
avg += reply.RoundtripTime; avg += reply.RoundtripTime;
if(reply.RoundtripTime < min) if (reply.RoundtripTime < min)
{ {
min = reply.RoundtripTime; min = reply.RoundtripTime;
} }
if(reply.RoundtripTime > max) if (reply.RoundtripTime > max)
{ {
max = reply.RoundtripTime; max = reply.RoundtripTime;
} }
//System.Diagnostics.Debug.WriteLine("Time to live: {0}", reply.Options.Ttl); //System.Diagnostics.Debug.WriteLine("Time to live: {0}", reply.Options.Ttl);
//System.Diagnostics.Debug.WriteLine("Don't fragment: {0}", reply.Options.DontFragment); //System.Diagnostics.Debug.WriteLine("Don't fragment: {0}", reply.Options.DontFragment);
} }
else else
{ {
System.Diagnostics.Debug.WriteLine(reply.Status); System.Diagnostics.Debug.WriteLine(reply.Status);
failures++;
} }
Thread.Sleep(500); Thread.Sleep(500);
} }
avg = avg / successes; avg = avg / successes;
System.Diagnostics.Debug.WriteLine("min:" + min + " max:" + max + " avg:" + avg); System.Diagnostics.Debug.WriteLine("min:" + min + " max:" + max + " avg:" + avg);
PingItem pi = new PingItem { Date = DateTime.UtcNow, Min = min, Max = max, Avg = avg }; PingItem pi = new PingItem { Date = DateTimeOffset.UtcNow, Min = min, Max = max, Avg = avg, Failures = failures };
if(host.PingItems == null)
host = _context.Hosts.Include(host => host.PingItems).Where(h => h.HostId == host.HostId).Single();
host.PingItems.Add(pi); host.PingItems.Add(pi);
_context.SaveChanges(); _context.SaveChanges();
Thread.Sleep(5000); Thread.Sleep(5000);
} }
}); });
} }
public void AddHost(Host host)
{
System.Diagnostics.Debug.WriteLine("Host added!");
if (host.PingItems == null)
host = _context.Hosts.Include(host => host.PingItems).Where(h => h.HostId == host.HostId).Single();
if(host.Ping)
StartPing(host);
}
} }
} }

6
ISPChk/Properties/launchSettings.json

@ -4,7 +4,7 @@
"windowsAuthentication": false, "windowsAuthentication": false,
"anonymousAuthentication": true, "anonymousAuthentication": true,
"iisExpress": { "iisExpress": {
"applicationUrl": "http://localhost:65025", "applicationUrl": "http://localhost:4223",
"sslPort": 0 "sslPort": 0
} }
}, },
@ -12,7 +12,7 @@
"IIS Express": { "IIS Express": {
"commandName": "IISExpress", "commandName": "IISExpress",
"launchBrowser": true, "launchBrowser": true,
"launchUrl": "/", "launchUrl": "",
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
} }
@ -22,7 +22,7 @@
"dotnetRunMessages": "true", "dotnetRunMessages": "true",
"launchBrowser": true, "launchBrowser": true,
"launchUrl": "/", "launchUrl": "/",
"applicationUrl": "http://localhost:5000", "applicationUrl": "http://localhost:4223",
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
} }

BIN
ISPChk/ispchk.db

Binary file not shown.

BIN
ISPChk/ispchk.db-shm

Binary file not shown.

BIN
ISPChk/ispchk.db-wal

Binary file not shown.

4
ISPChk/libman.json

@ -10,6 +10,10 @@
"provider": "jsdelivr", "provider": "jsdelivr",
"library": "bootstrap@4.6.0", "library": "bootstrap@4.6.0",
"destination": "wwwroot/bootstrap/" "destination": "wwwroot/bootstrap/"
},
{
"library": "Chart.js@2.9.4",
"destination": "wwwroot/Chart.js/"
} }
] ]
} }

20776
ISPChk/wwwroot/Chart.js/Chart.bundle.js

File diff suppressed because it is too large

7
ISPChk/wwwroot/Chart.js/Chart.bundle.min.js

File diff suppressed because one or more lines are too long

47
ISPChk/wwwroot/Chart.js/Chart.css

@ -0,0 +1,47 @@
/*
* DOM element rendering detection
* https://davidwalsh.name/detect-node-insertion
*/
@keyframes chartjs-render-animation {
from { opacity: 0.99; }
to { opacity: 1; }
}
.chartjs-render-monitor {
animation: chartjs-render-animation 0.001s;
}
/*
* DOM element resizing detection
* https://github.com/marcj/css-element-queries
*/
.chartjs-size-monitor,
.chartjs-size-monitor-expand,
.chartjs-size-monitor-shrink {
position: absolute;
direction: ltr;
left: 0;
top: 0;
right: 0;
bottom: 0;
overflow: hidden;
pointer-events: none;
visibility: hidden;
z-index: -1;
}
.chartjs-size-monitor-expand > div {
position: absolute;
width: 1000000px;
height: 1000000px;
left: 0;
top: 0;
}
.chartjs-size-monitor-shrink > div {
position: absolute;
width: 200%;
height: 200%;
left: 0;
top: 0;
}

16172
ISPChk/wwwroot/Chart.js/Chart.js

File diff suppressed because it is too large

1
ISPChk/wwwroot/Chart.js/Chart.min.css

@ -0,0 +1 @@
@keyframes chartjs-render-animation{from{opacity:.99}to{opacity:1}}.chartjs-render-monitor{animation:chartjs-render-animation 1ms}.chartjs-size-monitor,.chartjs-size-monitor-expand,.chartjs-size-monitor-shrink{position:absolute;direction:ltr;left:0;top:0;right:0;bottom:0;overflow:hidden;pointer-events:none;visibility:hidden;z-index:-1}.chartjs-size-monitor-expand>div{position:absolute;width:1000000px;height:1000000px;left:0;top:0}.chartjs-size-monitor-shrink>div{position:absolute;width:200%;height:200%;left:0;top:0}

7
ISPChk/wwwroot/Chart.js/Chart.min.js

File diff suppressed because one or more lines are too long

37
ISPChk/wwwroot/index.html

@ -5,6 +5,7 @@
<title>ISPChk</title> <title>ISPChk</title>
<link href="bootstrap/dist/css/bootstrap.min.css" rel="stylesheet"> <link href="bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="jquery/jquery.js"></script> <script src="jquery/jquery.js"></script>
<script src="Chart.js/Chart.min.js"></script>
</head> </head>
<body> <body>
<div class="container"> <div class="container">
@ -37,14 +38,38 @@
</div> </div>
<div class="row"> <div class="row">
<div class="col-sm"> <div class="col-sm">
<label>Name: <input id="inpNameAdd" /></label><br /> <form id="frmHostAdd">
<label>Host: <input id="inpHostNameAdd" /></label><br /> <div>
<button id="btnHostAdd">Add Host</button> <label for="inpNameAdd" class="form-label">Name</label>
<input type="text" class="form-control" id="inpNameAdd" aria-describedby="inpNameAddHelp">
<div id="inpNameAddHelp" class="form-text">This can be anything.</div>
</div>
<div>
<label for="inpHostNameAdd" class="form-label">Hostname</label>
<input type="text" class="form-control" id="inpHostNameAdd">
</div>
<div class="form-check">
<input type="checkbox" class="form-check-input" id="chkPing">
<label class="form-check-label" for="chkPing">Ping</label>
</div>
<div class="form-check">
<input type="checkbox" class="form-check-input" id="chkTCP">
<label class="form-check-label" for="chkTCP">TCP</label>
</div>
<button type="submit" class="btn btn-primary">Add Host</button>
</form>
</div> </div>
<div class="col-sm">
Testlel
</div>
<div class="col-sm">
Testlel
</div>
</div>
<div id="charts" class="row">
</div> </div>
</div> </div>
<script src="bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<script src="bootstrap/dist/js/bootstrap.bundle.min.js"></script> <script src="ispchk.js"></script>
<script src="ispchk.js"></script>
</body> </body>
</html> </html>

146
ISPChk/wwwroot/ispchk.js

@ -1,6 +1,7 @@
var hosts = []; var hosts = [];
var charts = {};
function createHost(host) { async function createHost(host) {
$.postJSON("/api/host", host).then((res, status) => { $.postJSON("/api/host", host).then((res, status) => {
console.log("POSTED" + status, res); console.log("POSTED" + status, res);
if (status === "success") { if (status === "success") {
@ -9,46 +10,139 @@ function createHost(host) {
}); });
} }
function deleteHost(hostId) { async function deleteHost(hostId) {
$.ajax({ var res = await $.ajax({
url: "/api/host/"+hostId, url: "/api/host/" + hostId,
type: "DELETE" type: "DELETE"
}).then(() => {
console.log("DELETED");
fetchHosts();
}); });
console.log("DELETED");
fetchHosts();
} }
function fetchHosts() { async function fetchHosts() {
var tbody = $("#tblHosts > tbody"); var tbody = $("#tblHosts > tbody");
tbody.empty(); tbody.empty();
$.getJSON("/api/host").then((res) => { var res = await $.getJSON("/api/host");
console.log("Got hosts: ", res); console.log("Got hosts: ", res);
for (let host of res) { for (let host of res) {
var row = $("<tr>",).appendTo(tbody); var row = $("<tr>",).appendTo(tbody);
$("<td>").text(host.hostId).appendTo(row); $("<td>").text(host.hostId).appendTo(row);
$("<td>").text(host.name).appendTo(row); $("<td>").text(host.name).appendTo(row);
$("<td>").text(host.hostName).appendTo(row); $("<td>").text(host.hostName).appendTo(row);
$("<td>").text("Delete").click(() => { $("<td>").text("Delete").click(() => {
deleteHost(host.hostId); deleteHost(host.hostId);
}).appendTo(row); }).appendTo(row);
} }
}); updateGraphs(res);
}
async function fetchPings(hostId, start, end) {
var res = await $.getJSON("/api/host/" + hostId + "/pings/" + start + "/" + end);
console.log("Fetched pings: ", res);
return res;
}
async function transformChartData(pings) {
var res = { date: [], min: [], avg: [], max: [], failures: []};
for (let ping of pings) {
res.date.push(ping.date);
res.min.push(ping.min);
res.avg.push(ping.avg);
res.max.push(ping.max);
res.failures.push(ping.failures);
}
return res;
}
async function updateGraphs(hosts) {
var charts = $("#charts");
for (let host of hosts) {
console.log("Appending ", host);
var before = Date.now() - 300000;
var val = await transformChartData(await fetchPings(host.hostId, before, Date.now()));
$("<canvas>", { id: "chart_" + host.hostId, width: 200, height: 200 }).appendTo(charts);
var ctx = document.getElementById('chart_' + host.hostId).getContext('2d');
charts[host.hostId] = new Chart(ctx, {
type: 'line',
data: {
labels: val.date,
datasets: [
{
label: 'min',
backgroundColor: 'rgba(255, 99, 132, 0.3)',
borderColor: 'rgb(255, 99, 132)',
yAxisID: "y-latency",
data: val.min
},
{
label: 'avg',
backgroundColor: 'rgba(99, 255, 132, 0.3)',
borderColor: 'rgb(99, 255, 132)',
yAxisID: "y-latency",
data: val.avg
},
{
label: 'max',
backgroundColor: 'rgba(132, 99, 255, 0.3)',
borderColor: 'rgb(132, 99, 255)',
yAxisID: "y-latency",
data: val.max
},
]
},
options: {
title: {
display: true,
text: host.name
},
scales: {
yAxes: [
{
id: "y-latency",
position: "left",
ticks: {
suggestedMin: 10,
suggestedMax: 40
}
},/*
{
id: "y-avg",
position: "left",
ticks: {
suggestedMin: 950,
suggestedMax: 1050
}
},
{
id: "y-max",
position: "right",
ticks: {
suggestedMin: 0,
suggestedMax: 100
}
},*/
]
}
}
});
}
} }
$('#btnDebug').click(function () { $('#btnDebug').click(async () => {
console.log("DEBUG"); console.log("DEBUG");
$.getJSON("/api/host/" + id + "/pings/" + Date.now + "/" + Date.now).then((res) => {
console.log("CALLED: res ", res);
});
}); });
$('#btnHostAdd').click(function () { $("#frmHostAdd").submit((event) => {
event.preventDefault();
var name = $("#inpNameAdd").val(); var name = $("#inpNameAdd").val();
var hostname = $("#inpHostNameAdd").val(); var hostname = $("#inpHostNameAdd").val();
var ping = $('#chkPing').prop('checked')
var tcp = $('#chkPing').prop('checked')
var host = { var host = {
name: name, name: name,
hostname: hostname hostname: hostname,
ping: ping,
tcp: tcp
} }
createHost(host); createHost(host);
}); });

Loading…
Cancel
Save