|  | @@ -33,7 +33,7 @@ import tornado.websocket
 | 
	
		
			
				|  |  |  from tornado.gen import sleep
 | 
	
		
			
				|  |  |  import asyncio
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -VERSION = '0.9.11'
 | 
	
		
			
				|  |  | +VERSION = '0.9.12'
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  konfig_file = 'config.cfg'
 | 
	
		
			
				|  |  |  s_certfile = 'server.crt'
 | 
	
	
		
			
				|  | @@ -44,10 +44,15 @@ failed_pingc = dict()
 | 
	
		
			
				|  |  |  g_since  = dict()
 | 
	
		
			
				|  |  |  y_since  = dict()
 | 
	
		
			
				|  |  |  r_since  = dict()
 | 
	
		
			
				|  |  | +g_timbar  = dict()
 | 
	
		
			
				|  |  | +y_timbar  = dict()
 | 
	
		
			
				|  |  | +r_timbar  = dict()
 | 
	
		
			
				|  |  |  loop_interval = 3
 | 
	
		
			
				|  |  |  listen_port = 8888
 | 
	
		
			
				|  |  |  listen_addr = '0.0.0.0'
 | 
	
		
			
				|  |  |  anz_hosts = 0
 | 
	
		
			
				|  |  | +bar_duration = 3600
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  fping_parameter = []
 | 
	
		
			
				|  |  |  fping_cmd = 'fping'
 | 
	
	
		
			
				|  | @@ -115,6 +120,11 @@ def read_config():
 | 
	
		
			
				|  |  |  							sys.exit()
 | 
	
		
			
				|  |  |  				except KeyError:
 | 
	
		
			
				|  |  |  					pass
 | 
	
		
			
				|  |  | +				try:
 | 
	
		
			
				|  |  | +					global bar_duration
 | 
	
		
			
				|  |  | +					bar_duration = restrict(int(config["Main"]["DurationBarSpan"]), 1, 5184000)
 | 
	
		
			
				|  |  | +				except KeyError:
 | 
	
		
			
				|  |  | +					pass
 | 
	
		
			
				|  |  |  			else:
 | 
	
		
			
				|  |  |  				#host_dict[key] = config[sect][key]
 | 
	
		
			
				|  |  |  				host_dict[key] = sect.replace(' ','_')
 | 
	
	
		
			
				|  | @@ -148,6 +158,9 @@ def set_since(host,now,set,unset1,unset2):
 | 
	
		
			
				|  |  |  	else:
 | 
	
		
			
				|  |  |  		set[host] = now
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +def restrict(value, lower, upper):
 | 
	
		
			
				|  |  | +    return lower if value < lower else upper if value > upper else value
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  |  def create_fpingparam():
 | 
	
		
			
				|  |  |  	global fping_parameter
 | 
	
		
			
				|  |  |  	global fping_cmd
 | 
	
	
		
			
				|  | @@ -171,6 +184,7 @@ def create_fpingparam():
 | 
	
		
			
				|  |  |  	try:
 | 
	
		
			
				|  |  |  		fping_parameter.append('--size=' + config["Main"]["Fping-size"])
 | 
	
		
			
				|  |  |  	except KeyError:
 | 
	
		
			
				|  |  | +		fping_parameter.append('--size=56')
 | 
	
		
			
				|  |  |  		pass
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -237,7 +251,7 @@ async def FpingLoop():
 | 
	
		
			
				|  |  |  			comd_out = ' '.join(tmp_cmd)
 | 
	
		
			
				|  |  |  			comd_out.replace("'", "")
 | 
	
		
			
				|  |  |  			print('ping command used: "' + comd_out + '"')
 | 
	
		
			
				|  |  | -		
 | 
	
		
			
				|  |  | +			
 | 
	
		
			
				|  |  |  		# The Loop
 | 
	
		
			
				|  |  |  		while True:
 | 
	
		
			
				|  |  |  			
 | 
	
	
		
			
				|  | @@ -249,6 +263,8 @@ async def FpingLoop():
 | 
	
		
			
				|  |  |  			ac_now = datetime.now()
 | 
	
		
			
				|  |  |  			ac_time = ac_now.strftime("%H:%M:%S")
 | 
	
		
			
				|  |  |  			ac_timed = ac_now.strftime("%a %d %H:%M:%S")
 | 
	
		
			
				|  |  | +			tnow = int(ac_now.timestamp())
 | 
	
		
			
				|  |  | +			
 | 
	
		
			
				|  |  |  			if args.v: print("call fping: " + ac_time)
 | 
	
		
			
				|  |  |  			ret = fping(ip_list)
 | 
	
		
			
				|  |  |  			rl = ret.splitlines()
 | 
	
	
		
			
				|  | @@ -270,8 +286,11 @@ async def FpingLoop():
 | 
	
		
			
				|  |  |  					#print(host+" OK")
 | 
	
		
			
				|  |  |  					cnt_ok += 1
 | 
	
		
			
				|  |  |  					set_since(host, ac_timed, set=g_since,unset1=y_since,unset2=r_since)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +					set_since(host, tnow, set=g_timbar,unset1=y_timbar,unset2=r_timbar)
 | 
	
		
			
				|  |  | +					g_timb = restrict(int(100-(100 * ( (tnow - g_timbar[host]) / bar_duration))+1), 0, 100)
 | 
	
		
			
				|  |  |  					json_bc.append({
 | 
	
		
			
				|  |  | -						"host": host, "status": "OK", "rtt": rtims, "actime": ac_time, "sect": ux_sect, "since": g_since[host]
 | 
	
		
			
				|  |  | +						"host": host, "status": "OK", "rtt": rtims, "actime": ac_time, "sect": ux_sect, "since": g_since[host], "timbar": g_timb
 | 
	
		
			
				|  |  |  					})
 | 
	
		
			
				|  |  |  					failed_pingc[host] = 0
 | 
	
		
			
				|  |  |  					#BroadcastHandler.broadcast(line)
 | 
	
	
		
			
				|  | @@ -279,8 +298,11 @@ async def FpingLoop():
 | 
	
		
			
				|  |  |  					#print(host+" OK")
 | 
	
		
			
				|  |  |  					cnt_ok += 1
 | 
	
		
			
				|  |  |  					set_since(host, ac_timed, set=g_since,unset1=y_since,unset2=r_since)
 | 
	
		
			
				|  |  | +					
 | 
	
		
			
				|  |  | +					set_since(host, tnow, set=g_timbar,unset1=y_timbar,unset2=r_timbar)
 | 
	
		
			
				|  |  | +					g_timb = restrict(int(100-(100 * ( (tnow - g_timbar[host]) / bar_duration))+1), 0, 100)
 | 
	
		
			
				|  |  |  					json_bc.append({
 | 
	
		
			
				|  |  | -						"host": host, "status": "OK", "rtt": rtims, "actime": ac_time, "sect": ux_sect, "since": g_since[host]
 | 
	
		
			
				|  |  | +						"host": host, "status": "OK", "rtt": rtims, "actime": ac_time, "sect": ux_sect, "since": g_since[host], "timbar": g_timb
 | 
	
		
			
				|  |  |  					})
 | 
	
		
			
				|  |  |  					failed_pingc[host] = 0
 | 
	
		
			
				|  |  |  					#BroadcastHandler.broadcast(line)
 | 
	
	
		
			
				|  | @@ -288,14 +310,17 @@ async def FpingLoop():
 | 
	
		
			
				|  |  |  					#print(host+" FAILED")
 | 
	
		
			
				|  |  |  					cnt_fail += 1
 | 
	
		
			
				|  |  |  					set_since(host, ac_timed, set=r_since,unset1=y_since,unset2=g_since)
 | 
	
		
			
				|  |  | +					
 | 
	
		
			
				|  |  | +					set_since(host, tnow, set=r_timbar,unset1=y_timbar,unset2=g_timbar)
 | 
	
		
			
				|  |  | +					r_timb = restrict(int(100-(100 * ( (tnow - r_timbar[host]) / bar_duration))+1), 0, 100)
 | 
	
		
			
				|  |  |  					if failed_pingc[host] < int(config["Main"]["FlashThreshold"]):
 | 
	
		
			
				|  |  |  						json_bc.append({
 | 
	
		
			
				|  |  | -							"host": host, "status": "NEWFAIL", "rtt": rtims, "actime": ac_time, "sect": ux_sect, "since": r_since[host]
 | 
	
		
			
				|  |  | +							"host": host, "status": "NEWFAIL", "rtt": rtims, "actime": ac_time, "sect": ux_sect, "since": r_since[host], "timbar": r_timb
 | 
	
		
			
				|  |  |  						})
 | 
	
		
			
				|  |  |  						failed_pingc[host] += 1
 | 
	
		
			
				|  |  |  					else:
 | 
	
		
			
				|  |  |  						json_bc.append({
 | 
	
		
			
				|  |  | -							"host": host, "status": "FAILED", "rtt": rtims, "actime": ac_time, "sect": ux_sect, "since": r_since[host]
 | 
	
		
			
				|  |  | +							"host": host, "status": "FAILED", "rtt": rtims, "actime": ac_time, "sect": ux_sect, "since": r_since[host], "timbar": r_timb
 | 
	
		
			
				|  |  |  						})
 | 
	
		
			
				|  |  |  						failed_pingc[host] = int(config["Main"]["FlashThreshold"]) + 1
 | 
	
		
			
				|  |  |  					#BroadcastHandler.broadcast(line)
 | 
	
	
		
			
				|  | @@ -303,8 +328,11 @@ async def FpingLoop():
 | 
	
		
			
				|  |  |  					#print(host+" HALB")
 | 
	
		
			
				|  |  |  					cnt_halb += 1
 | 
	
		
			
				|  |  |  					set_since(host, ac_timed, set=y_since,unset1=r_since,unset2=g_since)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +					set_since(host, tnow, set=y_timbar,unset1=r_timbar,unset2=g_timbar)
 | 
	
		
			
				|  |  | +					y_timb = restrict(int(100-(100 * ( (tnow - y_timbar[host]) / bar_duration))+1), 0, 100)
 | 
	
		
			
				|  |  |  					json_bc.append({
 | 
	
		
			
				|  |  | -						"host": host, "status": "HALB", "rtt": rtims, "actime": ac_time, "sect": ux_sect, "since": y_since[host]
 | 
	
		
			
				|  |  | +						"host": host, "status": "HALB", "rtt": rtims, "actime": ac_time, "sect": ux_sect, "since": y_since[host], "timbar": y_timb
 | 
	
		
			
				|  |  |  					})
 | 
	
		
			
				|  |  |  					failed_pingc[host] = 0
 | 
	
		
			
				|  |  |  					#BroadcastHandler.broadcast(line)
 | 
	
	
		
			
				|  | @@ -312,9 +340,9 @@ async def FpingLoop():
 | 
	
		
			
				|  |  |  					print(host+" ???????????????????")
 | 
	
		
			
				|  |  |  			
 | 
	
		
			
				|  |  |  			if args.v: print("STAT(%d hosts, interval:%s ms, period:%s ms): green=%d / yellow=%d / red=%d / ping-round: %d sec" % (anz_hosts, config["Main"]["Fping-interval"], config["Main"]["Fping-period"], cnt_ok, cnt_halb, cnt_fail, int(datetime.now().timestamp()) - int(ac_now.timestamp())) )
 | 
	
		
			
				|  |  | -			#print(g_since)
 | 
	
		
			
				|  |  | -			#print(y_since)
 | 
	
		
			
				|  |  | -			#print(r_since)
 | 
	
		
			
				|  |  | +			#print(g_timbar)
 | 
	
		
			
				|  |  | +			#print(y_timbar)
 | 
	
		
			
				|  |  | +			#print(r_timbar)
 | 
	
		
			
				|  |  |  			#print(json.dumps(json_bc, separators=(',', ':'), ensure_ascii=False))
 | 
	
		
			
				|  |  |  			BroadcastHandler.broadcast(json_bc)
 | 
	
		
			
				|  |  |  			
 | 
	
	
		
			
				|  | @@ -459,6 +487,7 @@ def create_html_table():
 | 
	
		
			
				|  |  |  		for key in config[sect]:
 | 
	
		
			
				|  |  |  			tkey = key.replace('.', '_')
 | 
	
		
			
				|  |  |  			html_tab += '<div class="w3-left si3-dark-grey w3-border w3-border-teal tooltip" style="text-align: center;margin: 1px; min-width: 13ch; padding: 4px min(3px, 1vw) !important;box-shadow:3px 2px 4px #000 !important;">'
 | 
	
		
			
				|  |  | +			html_tab += '<span id="tbar_' + tkey + '" class="time-bar-wrapper"><span class="time-bar"></span></span>'
 | 
	
		
			
				|  |  |  			html_tab += '<span class="w3-card-2 tooltiptext">'+config[sect][key]+'<br><span id="ttip_' + tkey + '" class="ttip_small"></span></span>'
 | 
	
		
			
				|  |  |  			html_tab += '<span id="' + tkey + '" class="ip_num">' + key + '</span><br><span id="stat_' + tkey + '" class="w3-center"></span></div>'
 | 
	
		
			
				|  |  |  		html_tab += '</div>\n</div>\n'
 | 
	
	
		
			
				|  | @@ -510,31 +539,44 @@ html_html = '''
 | 
	
		
			
				|  |  |              	   		var cur_sect_ux = data_obj.sect;
 | 
	
		
			
				|  |  |              	   		var cur_rtt = data_obj.rtt;
 | 
	
		
			
				|  |  |              	   		var cur_since = data_obj.since;
 | 
	
		
			
				|  |  | +            	   		var cur_timbar = data_obj.timbar;
 | 
	
		
			
				|  |  |              	   		cur_rtt = cur_rtt.replace(/ /g,' \/ ');
 | 
	
		
			
				|  |  |              	   		var uc_cur_host = cur_host.replace(/\./g,'_');
 | 
	
		
			
				|  |  |              	   		document.getElementById(uc_cur_host).textContent = cur_host;
 | 
	
		
			
				|  |  |              	   		var stat_id = 'stat_' + uc_cur_host;
 | 
	
		
			
				|  |  |              	   		var ttip_id = 'ttip_' + uc_cur_host;
 | 
	
		
			
				|  |  | +            	   		var tbar_id = 'tbar_' + uc_cur_host;
 | 
	
		
			
				|  |  | +            	   		var tbarsel = document.getElementById(tbar_id).querySelector('.time-bar');
 | 
	
		
			
				|  |  |              	   		if (cur_status == 'OK') {
 | 
	
		
			
				|  |  |              	   			M_green.set(cur_sect_ux, M_green.get(cur_sect_ux) + 1);
 | 
	
		
			
				|  |  |              	   			document.getElementById(stat_id).innerHTML = '<img src="/img/green_on.gif">';
 | 
	
		
			
				|  |  |              	   			document.getElementById(ttip_id).innerHTML = '<b>RTT</b>: '+cur_rtt+'<br><span style="color:#0f0;">since </span>: '+cur_since;
 | 
	
		
			
				|  |  | +            	   			tbarsel.style.width = cur_timbar+'%%';
 | 
	
		
			
				|  |  | +            	   			tbarsel.style.background = '#0f0';
 | 
	
		
			
				|  |  |              	   		} else if (cur_status == 'FAILED') {
 | 
	
		
			
				|  |  |              	   			M_red.set(cur_sect_ux, M_red.get(cur_sect_ux) + 1);
 | 
	
		
			
				|  |  |              	   			document.getElementById(stat_id).innerHTML = '<img src="/img/red_on.gif">';
 | 
	
		
			
				|  |  |              	   			document.getElementById(ttip_id).innerHTML = '<b>RTT</b>: '+cur_rtt+'<br><span style="color:red;">since </span>: '+cur_since;
 | 
	
		
			
				|  |  | +            	   			tbarsel.style.width = cur_timbar+'%%';
 | 
	
		
			
				|  |  | +            	   			tbarsel.style.background = 'red';
 | 
	
		
			
				|  |  |              	   		} else if (cur_status == 'NEWFAIL') {
 | 
	
		
			
				|  |  |              	   			M_red.set(cur_sect_ux, M_red.get(cur_sect_ux) + 1);
 | 
	
		
			
				|  |  |              	   			document.getElementById(stat_id).innerHTML = '<img src="/img/red_anim.gif">';
 | 
	
		
			
				|  |  |              	   			document.getElementById(ttip_id).innerHTML = '<b>RTT</b>: '+cur_rtt+'<br><span style="color:red;">since </span>: '+cur_since;
 | 
	
		
			
				|  |  | +            	   			tbarsel.style.width = cur_timbar+'%%';
 | 
	
		
			
				|  |  | +            	   			tbarsel.style.background = 'red';
 | 
	
		
			
				|  |  |              	   		} else {
 | 
	
		
			
				|  |  |              	   			M_yellow.set(cur_sect_ux, M_yellow.get(cur_sect_ux) + 1);
 | 
	
		
			
				|  |  |              	   			document.getElementById(stat_id).innerHTML = '<img src="/img/yellow_on.gif">';
 | 
	
		
			
				|  |  |              	   			document.getElementById(ttip_id).innerHTML = '<b>RTT</b>: '+cur_rtt+'<br><span style="color:yellow;">since </span>: '+cur_since;
 | 
	
		
			
				|  |  | +            	   			tbarsel.style.width = cur_timbar+'%%';
 | 
	
		
			
				|  |  | +            	   			tbarsel.style.background = 'yellow';
 | 
	
		
			
				|  |  |              	   		}
 | 
	
		
			
				|  |  |              	   	} // End for
 | 
	
		
			
				|  |  |              	   	document.getElementById('cur_actime').innerHTML = cur_actime;
 | 
	
		
			
				|  |  |              	   	
 | 
	
		
			
				|  |  | +            	   	//document.querySelector('.time-bar').style.width = "20px";
 | 
	
		
			
				|  |  | +            	   	
 | 
	
		
			
				|  |  |              	   	for (let [sect, val] of M_red) {
 | 
	
		
			
				|  |  |              	   		let tmp_r = '<span class="unreach_r">';
 | 
	
		
			
				|  |  |              	   		tmp_r += (M_red.get(sect) == 0) ? '<span class="red_r opaq_r">'+M_red.get(sect).toString().padStart(3, " ")+'</span> | ' 
 | 
	
	
		
			
				|  | @@ -746,6 +788,24 @@ body {
 | 
	
		
			
				|  |  |    padding-top: 50px;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +.time-bar-wrapper {
 | 
	
		
			
				|  |  | +  width: 100%;
 | 
	
		
			
				|  |  | +  height:2px;
 | 
	
		
			
				|  |  | +  position:absolute;
 | 
	
		
			
				|  |  | +  top:0;
 | 
	
		
			
				|  |  | +  left:0;
 | 
	
		
			
				|  |  | +  background-color: inherit;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +.time-bar { 
 | 
	
		
			
				|  |  | +  width:0;
 | 
	
		
			
				|  |  | +  height: inherit;
 | 
	
		
			
				|  |  | +  background-color: yellow;
 | 
	
		
			
				|  |  | +  display: block;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  '''
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  def create_html_modal01():
 | 
	
	
		
			
				|  | @@ -758,12 +818,16 @@ def create_html_modal01():
 | 
	
		
			
				|  |  |   	''' + str(loop_interval) + ''' s<br>
 | 
	
		
			
				|  |  |   FlashThreshold: 
 | 
	
		
			
				|  |  |   	''' + str(config["Main"]["FlashThreshold"]) + ''' rounds<br>
 | 
	
		
			
				|  |  | + DurationBarSpan: 
 | 
	
		
			
				|  |  | + 	''' + str(bar_duration) + ''' seconds<br>
 | 
	
		
			
				|  |  |   fping: 
 | 
	
		
			
				|  |  |  	''' + fping_parameter[2].replace('--','') + '''<br>
 | 
	
		
			
				|  |  |   fping: 
 | 
	
		
			
				|  |  |  	''' + fping_parameter[3].replace('--','') + ''' ms<br>
 | 
	
		
			
				|  |  |   fping: 
 | 
	
		
			
				|  |  |  	''' + fping_parameter[4].replace('--','') + ''' ms<br>
 | 
	
		
			
				|  |  | + fping: 
 | 
	
		
			
				|  |  | +	''' + fping_parameter[5].replace('--','') + ''' bytes<br>
 | 
	
		
			
				|  |  |  <br> 
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  <p style="font-size:1.2em;font-variant:small-caps;letter-spacing:3px;font-style:italic;text-decoration:underline">Help</p>
 |