First charts for ping rendering
This commit is contained in:
		
							parent
							
								
									abb91f7baf
								
							
						
					
					
						commit
						56a412108f
					
				| @ -45,9 +45,9 @@ namespace ISPChk.Controllers | ||||
| 
 | ||||
|         // GET: api/Host/5 | ||||
|         [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); | ||||
| 
 | ||||
|             if (host == null) | ||||
| @ -55,7 +55,13 @@ namespace ISPChk.Controllers | ||||
|                 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 | ||||
|  | ||||
| @ -10,6 +10,8 @@ namespace ISPChk.Models | ||||
|         public long HostId { get; set; } | ||||
|         public string Name { get; set; } | ||||
|         public string HostName { get; set; } | ||||
|         public bool Ping { get; set; } | ||||
|         public bool TCP { get; set; } | ||||
| 
 | ||||
|         public List<PingItem> PingItems { get; set; } | ||||
|     } | ||||
|  | ||||
| @ -10,11 +10,11 @@ namespace ISPChk.Models | ||||
|     { | ||||
|         [Key] | ||||
|         public long PingId { get; set; } | ||||
|         public DateTime Date { get; set; } | ||||
|         public DateTimeOffset Date { get; set; } | ||||
|         public float Min { get; set; } | ||||
|         public float Max { get; set; } | ||||
|         public float Avg { get; set; } | ||||
|         public int Failures { get; set; } | ||||
|         public long HostId { get; set; } | ||||
|         public Host Host { get; set; } | ||||
|     } | ||||
| } | ||||
| @ -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 () => { | ||||
|                  | ||||
| 
 | ||||
|                 Ping pingSender = new Ping(); | ||||
| 
 | ||||
|                 // Create a buffer of 32 bytes of data to be transmitted. | ||||
| @ -55,11 +54,12 @@ namespace ISPChk | ||||
| 
 | ||||
|                 while (true) | ||||
|                 { | ||||
|                     long min = timeout+1; | ||||
|                     long min = timeout + 1; | ||||
|                     long max = 0; | ||||
|                     long avg = 0; | ||||
|                     int successes = 0; | ||||
|                     for(var i=0;i<5;++i) | ||||
|                     int failures = 0; | ||||
|                     for (var i = 0; i < 5; ++i) | ||||
|                     { | ||||
|                         // Send the request. | ||||
|                         PingReply reply = pingSender.Send(host.HostName, timeout, buffer, options); | ||||
| @ -71,33 +71,41 @@ namespace ISPChk | ||||
|                                 ": bytes=" + reply.Buffer.Length + | ||||
|                                 " time=" + reply.RoundtripTime + "ms"); | ||||
|                             avg += reply.RoundtripTime; | ||||
|                             if(reply.RoundtripTime < min) | ||||
|                             if (reply.RoundtripTime < min) | ||||
|                             { | ||||
|                                 min = reply.RoundtripTime; | ||||
|                             } | ||||
|                             if(reply.RoundtripTime > max) | ||||
|                             if (reply.RoundtripTime > max) | ||||
|                             { | ||||
|                                 max = reply.RoundtripTime; | ||||
|                             } | ||||
|                             //System.Diagnostics.Debug.WriteLine("Time to live: {0}", reply.Options.Ttl); | ||||
|                             //System.Diagnostics.Debug.WriteLine("Don't fragment: {0}", reply.Options.DontFragment); | ||||
|         } | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|                             System.Diagnostics.Debug.WriteLine(reply.Status); | ||||
|                             failures++; | ||||
|                         } | ||||
|                         Thread.Sleep(500); | ||||
|                     } | ||||
|                     avg = avg / successes; | ||||
|                     System.Diagnostics.Debug.WriteLine("min:" + min + " max:" + max + " avg:" + avg); | ||||
|                     PingItem pi = new PingItem { Date = DateTime.UtcNow, Min = min, Max = max, Avg = avg }; | ||||
|                     if(host.PingItems == null) | ||||
|                         host = _context.Hosts.Include(host => host.PingItems).Where(h => h.HostId == host.HostId).Single(); | ||||
|                     PingItem pi = new PingItem { Date = DateTimeOffset.UtcNow, Min = min, Max = max, Avg = avg, Failures = failures }; | ||||
|                     host.PingItems.Add(pi); | ||||
|                     _context.SaveChanges(); | ||||
|                     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); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -4,7 +4,7 @@ | ||||
|     "windowsAuthentication": false, | ||||
|     "anonymousAuthentication": true, | ||||
|     "iisExpress": { | ||||
|       "applicationUrl": "http://localhost:65025", | ||||
|       "applicationUrl": "http://localhost:4223", | ||||
|       "sslPort": 0 | ||||
|     } | ||||
|   }, | ||||
| @ -12,7 +12,7 @@ | ||||
|     "IIS Express": { | ||||
|       "commandName": "IISExpress", | ||||
|       "launchBrowser": true, | ||||
|       "launchUrl": "/", | ||||
|       "launchUrl": "", | ||||
|       "environmentVariables": { | ||||
|         "ASPNETCORE_ENVIRONMENT": "Development" | ||||
|       } | ||||
| @ -22,7 +22,7 @@ | ||||
|       "dotnetRunMessages": "true", | ||||
|       "launchBrowser": true, | ||||
|       "launchUrl": "/", | ||||
|       "applicationUrl": "http://localhost:5000", | ||||
|       "applicationUrl": "http://localhost:4223", | ||||
|       "environmentVariables": { | ||||
|         "ASPNETCORE_ENVIRONMENT": "Development" | ||||
|       } | ||||
|  | ||||
							
								
								
									
										
											BIN
										
									
								
								ISPChk/ispchk.db
									
									
									
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								ISPChk/ispchk.db
									
									
									
									
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							| @ -10,6 +10,10 @@ | ||||
|       "provider": "jsdelivr", | ||||
|       "library": "bootstrap@4.6.0", | ||||
|       "destination": "wwwroot/bootstrap/" | ||||
|     }, | ||||
|     { | ||||
|       "library": "Chart.js@2.9.4", | ||||
|       "destination": "wwwroot/Chart.js/" | ||||
|     } | ||||
|   ] | ||||
| } | ||||
							
								
								
									
										20776
									
								
								ISPChk/wwwroot/Chart.js/Chart.bundle.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20776
									
								
								ISPChk/wwwroot/Chart.js/Chart.bundle.js
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										7
									
								
								ISPChk/wwwroot/Chart.js/Chart.bundle.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								ISPChk/wwwroot/Chart.js/Chart.bundle.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										47
									
								
								ISPChk/wwwroot/Chart.js/Chart.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								ISPChk/wwwroot/Chart.js/Chart.css
									
									
									
									
									
										Normal file
									
								
							| @ -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
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										16172
									
								
								ISPChk/wwwroot/Chart.js/Chart.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1
									
								
								ISPChk/wwwroot/Chart.js/Chart.min.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								ISPChk/wwwroot/Chart.js/Chart.min.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -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
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								ISPChk/wwwroot/Chart.js/Chart.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @ -5,6 +5,7 @@ | ||||
|     <title>ISPChk</title> | ||||
|     <link href="bootstrap/dist/css/bootstrap.min.css" rel="stylesheet"> | ||||
|     <script src="jquery/jquery.js"></script> | ||||
|     <script src="Chart.js/Chart.min.js"></script> | ||||
| </head> | ||||
| <body> | ||||
|     <div class="container"> | ||||
| @ -37,14 +38,38 @@ | ||||
|         </div> | ||||
|         <div class="row"> | ||||
|             <div class="col-sm"> | ||||
|                 <label>Name: <input id="inpNameAdd" /></label><br /> | ||||
|                 <label>Host: <input id="inpHostNameAdd" /></label><br /> | ||||
|                 <button id="btnHostAdd">Add Host</button> | ||||
|                 <form id="frmHostAdd"> | ||||
|                     <div> | ||||
|                         <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 class="col-sm"> | ||||
|                 Testlel | ||||
|             </div> | ||||
|             <div class="col-sm"> | ||||
|                 Testlel | ||||
|             </div> | ||||
|         </div> | ||||
|         <div id="charts" class="row"> | ||||
|         </div> | ||||
|     </div> | ||||
|      | ||||
|     <script src="bootstrap/dist/js/bootstrap.bundle.min.js"></script> | ||||
|     <script src="ispchk.js"></script> | ||||
| <script src="bootstrap/dist/js/bootstrap.bundle.min.js"></script> | ||||
| <script src="ispchk.js"></script> | ||||
| </body> | ||||
| </html> | ||||
| @ -1,6 +1,7 @@ | ||||
| var hosts = []; | ||||
| var charts = {}; | ||||
| 
 | ||||
| function createHost(host) { | ||||
| async function createHost(host) { | ||||
|     $.postJSON("/api/host", host).then((res, status) => { | ||||
|         console.log("POSTED" + status, res); | ||||
|         if (status === "success") { | ||||
| @ -9,46 +10,139 @@ function createHost(host) { | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| function deleteHost(hostId) { | ||||
|     $.ajax({ | ||||
|         url: "/api/host/"+hostId, | ||||
| async function deleteHost(hostId) { | ||||
|     var res = await $.ajax({ | ||||
|         url: "/api/host/" + hostId, | ||||
|         type: "DELETE" | ||||
|     }).then(() => { | ||||
|         console.log("DELETED"); | ||||
|         fetchHosts(); | ||||
|     }); | ||||
|     console.log("DELETED"); | ||||
|     fetchHosts(); | ||||
| } | ||||
| 
 | ||||
| function fetchHosts() { | ||||
| async function fetchHosts() { | ||||
|     var tbody = $("#tblHosts > tbody"); | ||||
|     tbody.empty(); | ||||
|     $.getJSON("/api/host").then((res) => { | ||||
|         console.log("Got hosts: ", res); | ||||
|         for (let host of res) { | ||||
|             var row = $("<tr>",).appendTo(tbody); | ||||
|             $("<td>").text(host.hostId).appendTo(row); | ||||
|             $("<td>").text(host.name).appendTo(row); | ||||
|             $("<td>").text(host.hostName).appendTo(row); | ||||
|             $("<td>").text("Delete").click(() => { | ||||
|                 deleteHost(host.hostId); | ||||
|                 }).appendTo(row); | ||||
|         } | ||||
|     }); | ||||
|     var res = await $.getJSON("/api/host"); | ||||
|     console.log("Got hosts: ", res); | ||||
|     for (let host of res) { | ||||
|         var row = $("<tr>",).appendTo(tbody); | ||||
|         $("<td>").text(host.hostId).appendTo(row); | ||||
|         $("<td>").text(host.name).appendTo(row); | ||||
|         $("<td>").text(host.hostName).appendTo(row); | ||||
|         $("<td>").text("Delete").click(() => { | ||||
|             deleteHost(host.hostId); | ||||
|             }).appendTo(row); | ||||
|     } | ||||
|     updateGraphs(res); | ||||
| } | ||||
| 
 | ||||
| $('#btnDebug').click(function () { | ||||
| 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(async () => { | ||||
|     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 hostname = $("#inpHostNameAdd").val(); | ||||
|     var ping = $('#chkPing').prop('checked') | ||||
|     var tcp = $('#chkPing').prop('checked') | ||||
|     var host = { | ||||
|         name: name, | ||||
|         hostname: hostname | ||||
|         hostname: hostname, | ||||
|         ping: ping, | ||||
|         tcp: tcp | ||||
|     } | ||||
|     createHost(host); | ||||
| }); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user