mirror of
https://github.com/EDCD/EDDN.git
synced 2026-10-25 01:06:24 +03:00
Merge remote-tracking branch 'origin/EDDN-Monitor'
This commit is contained in:
commit
53dcc85d04
39 files changed
+1654
-261
No files matched your search
Binary file not shown.
@@ -0,0 +1,27 @@
|
||||
body {
|
||||
padding-top: 70px;
|
||||
}
|
||||
|
||||
section.container {
|
||||
margin-bottom: 20px;
|
||||
|
||||
/* FIX ANCHORS */
|
||||
padding-top:70px;
|
||||
margin-top:-70px;
|
||||
}
|
||||
|
||||
.container h2 {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.container .chart {
|
||||
height: 300px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
footer .navbar-default {
|
||||
border-width: 1px 0 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.highcharts-container{width:100% !important; height:100% !important;}
|
||||
@@ -0,0 +1,394 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>EDDN Status</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet" />
|
||||
<link href="./css/eddn.css" rel="stylesheet" />
|
||||
|
||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
|
||||
<script src="./js/date.js"></script>
|
||||
</head>
|
||||
<body data-spy="scroll" data-target="#header-nav" data-offset="70">
|
||||
<header>
|
||||
<nav class="navbar navbar-default navbar-fixed-top">
|
||||
<div class="container">
|
||||
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#header-nav">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="">EDDN Status</a>
|
||||
</div>
|
||||
|
||||
<div class="collapse navbar-collapse" id="header-nav">
|
||||
<ul class="nav navbar-nav">
|
||||
<li><a href="#gateways">Gateways</a></li>
|
||||
<li><a href="#relays">Relays</a></li>
|
||||
<li><a href="#softwares">Softwares</a></li>
|
||||
<li><a href="#uploaders">Uploaders</a></li>
|
||||
<li><a href="#schemas">Schemas</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<section class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<p>
|
||||
This page shows transaction information (messages sent/received) for key points of the EDDN, over a one-, five- and sixty-minute period.<br />
|
||||
Values automatically update every minute.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="gateways" class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h2>Gateways</h2>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="text-right form-inline">
|
||||
<select name="gateways" class="form-control"></select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 50%;"></th>
|
||||
<th>1 min</th>
|
||||
<th>5 min</th>
|
||||
<th>60 min</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Messages received</th>
|
||||
<td class="inbound_1min stat">-</td>
|
||||
<td class="inbound_5min stat">-</td>
|
||||
<td class="inbound_60min stat">-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Invalid messages</th>
|
||||
<td class="invalid_1min stat">-</td>
|
||||
<td class="invalid_5min stat">-</td>
|
||||
<td class="invalid_60min stat">-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Messages passed to relay</th>
|
||||
<td class="outbound_1min stat">-</td>
|
||||
<td class="outbound_5min stat">-</td>
|
||||
<td class="outbound_60min stat">-</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12 charts">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<p class="text-muted small">
|
||||
EDDN version: <strong><span class="version">N/A</span></strong>.
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<p class="text-muted small">
|
||||
Uptime: <strong><span class="uptime">N/A</span></strong>.
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<p class="text-muted small">
|
||||
Last updated: <strong><span class="update_timestamp">N/A</span></strong>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="relays" class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h2>Relays</h2>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="text-right form-inline">
|
||||
<select name="relays" class="form-control"></select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 50%;"></th>
|
||||
<th>1 min</th>
|
||||
<th>5 min</th>
|
||||
<th>60 min</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Messages received</th>
|
||||
<td class="inbound_1min stat">-</td>
|
||||
<td class="inbound_5min stat">-</td>
|
||||
<td class="inbound_60min stat">-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Messages duplicate</th>
|
||||
<td class="duplicate_1min stat">-</td>
|
||||
<td class="duplicate_5min stat">-</td>
|
||||
<td class="duplicate_60min stat">-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Messages passed to subscribers</th>
|
||||
<td class="outbound_1min stat">-</td>
|
||||
<td class="outbound_5min stat">-</td>
|
||||
<td class="outbound_60min stat">-</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12 charts">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<p class="text-muted small">
|
||||
EDDN version: <strong><span class="version">N/A</span></strong>.
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<p class="text-muted small">
|
||||
Uptime: <strong><span class="uptime">N/A</span></strong>.
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<p class="text-muted small">
|
||||
Last updated: <strong><span class="update_timestamp">N/A</span></strong>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="softwares" class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h2>Softwares</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-7">
|
||||
<div class="table-responsive">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 20px;"></th>
|
||||
<th style="width: 50%;"></th>
|
||||
<th>Today hits</th>
|
||||
<th>Yesterday hits</th>
|
||||
<th>Total hits</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
<div class="chart" style="height: 450px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-4 col-md-offset-8">
|
||||
<p class="text-muted small">
|
||||
Last updated: <strong><span class="update_timestamp">N/A</span></strong>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="uploaders" class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h2>Uploaders (Top 20)</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-7">
|
||||
<div class="table-responsive">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 20px;"></th>
|
||||
<th style="width: 50%;"></th>
|
||||
<th>Today hits</th>
|
||||
<th>Yesterday hits</th>
|
||||
<th>Total hits</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
<div class="chart" style="height: 450px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-4 col-md-offset-8">
|
||||
<p class="text-muted small">
|
||||
Last updated: <strong><span class="update_timestamp">N/A</span></strong>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="schemas" class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h2>Schemas</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-7">
|
||||
<div class="table-responsive">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 20px;"></th>
|
||||
<th style="width: 50%;"></th>
|
||||
<th>Today hits</th>
|
||||
<th>Yesterday hits</th>
|
||||
<th>Total hits</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
<div class="chart" style="height: 450px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-4 col-md-offset-8">
|
||||
<p class="text-muted small">
|
||||
Last updated: <strong><span class="update_timestamp">N/A</span></strong>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<footer>
|
||||
<nav class="navbar navbar-default">
|
||||
<div class="container">
|
||||
<p class="navbar-text">
|
||||
The <em>Elite: Dangerous Data Network</em> is volunteer-run and not affiliated with <a href="https://frontier.co.uk/" target="_blank">Frontier Developments</a>.
|
||||
|
|
||||
Charts by <a href="http://www.highcharts.com/" target="_blank">HighCharts</a>
|
||||
</p>
|
||||
</div>
|
||||
</nav>
|
||||
</footer>
|
||||
|
||||
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||
<!-- Include all compiled plugins (below), or include individual files as needed -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
|
||||
<script src="http://code.highcharts.com/4.1.5/highcharts.js"></script>
|
||||
<script src="./js/eddn.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,10 +1,10 @@
|
||||
/**
|
||||
* Version: 1.0 Alpha-1
|
||||
* Build Date: 13-Nov-2007
|
||||
* Copyright (c) 2006-2007, Coolite Inc. (http://www.coolite.com/). All rights reserved.
|
||||
* License: Licensed under The MIT License. See license.txt and http://www.datejs.com/license/.
|
||||
* Website: http://www.datejs.com/ or http://www.coolite.com/datejs/
|
||||
*/
|
||||
/**
|
||||
* Version: 1.0 Alpha-1
|
||||
* Build Date: 13-Nov-2007
|
||||
* Copyright (c) 2006-2007, Coolite Inc. (http://www.coolite.com/). All rights reserved.
|
||||
* License: Licensed under The MIT License. See license.txt and http://www.datejs.com/license/.
|
||||
* Website: http://www.datejs.com/ or http://www.coolite.com/datejs/
|
||||
*/
|
||||
Date.CultureInfo={name:"en-US",englishName:"English (United States)",nativeName:"English (United States)",dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],abbreviatedDayNames:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],shortestDayNames:["Su","Mo","Tu","We","Th","Fr","Sa"],firstLetterDayNames:["S","M","T","W","T","F","S"],monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],abbreviatedMonthNames:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],amDesignator:"AM",pmDesignator:"PM",firstDayOfWeek:0,twoDigitYearMax:2029,dateElementOrder:"mdy",formatPatterns:{shortDate:"M/d/yyyy",longDate:"dddd, MMMM dd, yyyy",shortTime:"h:mm tt",longTime:"h:mm:ss tt",fullDateTime:"dddd, MMMM dd, yyyy h:mm:ss tt",sortableDateTime:"yyyy-MM-ddTHH:mm:ss",universalSortableDateTime:"yyyy-MM-dd HH:mm:ssZ",rfc1123:"ddd, dd MMM yyyy HH:mm:ss GMT",monthDay:"MMMM dd",yearMonth:"MMMM, yyyy"},regexPatterns:{jan:/^jan(uary)?/i,feb:/^feb(ruary)?/i,mar:/^mar(ch)?/i,apr:/^apr(il)?/i,may:/^may/i,jun:/^jun(e)?/i,jul:/^jul(y)?/i,aug:/^aug(ust)?/i,sep:/^sep(t(ember)?)?/i,oct:/^oct(ober)?/i,nov:/^nov(ember)?/i,dec:/^dec(ember)?/i,sun:/^su(n(day)?)?/i,mon:/^mo(n(day)?)?/i,tue:/^tu(e(s(day)?)?)?/i,wed:/^we(d(nesday)?)?/i,thu:/^th(u(r(s(day)?)?)?)?/i,fri:/^fr(i(day)?)?/i,sat:/^sa(t(urday)?)?/i,future:/^next/i,past:/^last|past|prev(ious)?/i,add:/^(\+|after|from)/i,subtract:/^(\-|before|ago)/i,yesterday:/^yesterday/i,today:/^t(oday)?/i,tomorrow:/^tomorrow/i,now:/^n(ow)?/i,millisecond:/^ms|milli(second)?s?/i,second:/^sec(ond)?s?/i,minute:/^min(ute)?s?/i,hour:/^h(ou)?rs?/i,week:/^w(ee)?k/i,month:/^m(o(nth)?s?)?/i,day:/^d(ays?)?/i,year:/^y((ea)?rs?)?/i,shortMeridian:/^(a|p)/i,longMeridian:/^(a\.?m?\.?|p\.?m?\.?)/i,timezone:/^((e(s|d)t|c(s|d)t|m(s|d)t|p(s|d)t)|((gmt)?\s*(\+|\-)\s*\d\d\d\d?)|gmt)/i,ordinalSuffix:/^\s*(st|nd|rd|th)/i,timeContext:/^\s*(\:|a|p)/i},abbreviatedTimeZoneStandard:{GMT:"-000",EST:"-0400",CST:"-0500",MST:"-0600",PST:"-0700"},abbreviatedTimeZoneDST:{GMT:"-000",EDT:"-0500",CDT:"-0600",MDT:"-0700",PDT:"-0800"}};
|
||||
Date.getMonthNumberFromName=function(name){var n=Date.CultureInfo.monthNames,m=Date.CultureInfo.abbreviatedMonthNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s){return i;}}
|
||||
return-1;};Date.getDayNumberFromName=function(name){var n=Date.CultureInfo.dayNames,m=Date.CultureInfo.abbreviatedDayNames,o=Date.CultureInfo.shortestDayNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s){return i;}}
|
||||
@@ -101,4 +101,4 @@ return _.any.apply(null,rx);}else{return _get(fx);}};g._formats=g.formats(["yyyy
|
||||
return g._start.call({},s);};}());Date._parse=Date.parse;Date.parse=function(s){var r=null;if(!s){return null;}
|
||||
try{r=Date.Grammar.start.call({},s);}catch(e){return null;}
|
||||
return((r[1].length===0)?r[0]:null);};Date.getParseFunction=function(fx){var fn=Date.Grammar.formats(fx);return function(s){var r=null;try{r=fn.call({},s);}catch(e){return null;}
|
||||
return((r[1].length===0)?r[0]:null);};};Date.parseExact=function(s,fx){return Date.getParseFunction(fx)(s);};
|
||||
return((r[1].length===0)?r[0]:null);};};Date.parseExact=function(s,fx){return Date.getParseFunction(fx)(s);};
|
||||
@@ -0,0 +1,535 @@
|
||||
var updateInterval = 60000,
|
||||
|
||||
monitorEndPoint = 'http://eddn-monitor.ed-td.space:9091/',
|
||||
|
||||
gatewayBottlePort = 8080,
|
||||
relayBottlePort = 9090,
|
||||
|
||||
gateways = [
|
||||
'eddn-gateway.elite-markets.net',
|
||||
'eddn-gateway.ed-td.space'
|
||||
]; // Must find a way to bind them to monitor,
|
||||
|
||||
relays = [
|
||||
'eddn-relay.elite-markets.net',
|
||||
'eddn-relay.ed-td.space'
|
||||
]; // Must find a way to bind them to monitor
|
||||
|
||||
var stats = {
|
||||
'gateways' : {},
|
||||
'relays' : {}
|
||||
}; // Stats placeholder
|
||||
|
||||
formatNumber = function(num) {
|
||||
return num.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,")
|
||||
}
|
||||
|
||||
makeSlug = function(str) {
|
||||
var slugcontent_hyphens = str.replace(/\s/g,'-');
|
||||
var finishedslug = slugcontent_hyphens.replace(/[^a-zA-Z0-9\-]/g,'');
|
||||
return finishedslug.toLowerCase();
|
||||
}
|
||||
|
||||
secondsToDurationString = function(seconds) {
|
||||
var hours = Math.floor(seconds / 3600);
|
||||
var minutes = Math.floor((seconds - (hours * 3600)) / 60);
|
||||
var seconds = seconds - (hours * 3600) - (minutes * 60);
|
||||
var days = 0;
|
||||
|
||||
if (hours > 24) {
|
||||
days = Math.floor(hours / 24)
|
||||
hours = Math.floor((hours - days * 24) / 3600);
|
||||
}
|
||||
|
||||
if (hours < 10) {hours = "0" + hours;}
|
||||
if (minutes < 10) {minutes = "0" + minutes;}
|
||||
if (seconds < 10) {seconds = "0" + seconds;}
|
||||
|
||||
if (days > 0) {
|
||||
return days + "d " + hours + ":" + minutes + ":" + seconds;
|
||||
}
|
||||
else {
|
||||
return hours + ":" + minutes + ":" + seconds;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var doUpdateSoftwares = function()
|
||||
{
|
||||
var dToday = new Date(),
|
||||
dYesterday = new (function(d){ d.setDate(d.getDate()-1); return d})(new Date),
|
||||
|
||||
yesterday = dYesterday.getUTCFullYear() + '-' + ("0" + (dYesterday.getUTCMonth() + 1)).slice(-2) + '-' + ("0" + (dYesterday.getUTCDate())).slice(-2),
|
||||
today = dToday.getUTCFullYear() + '-' + ("0" + (dToday.getUTCMonth() + 1)).slice(-2) + '-' + ("0" + (dToday.getUTCDate())).slice(-2);
|
||||
|
||||
$.ajax({
|
||||
dataType: "json",
|
||||
url: monitorEndPoint + 'getSoftwares/?dateStart=' + yesterday + '&dateEnd = ' + today,
|
||||
success: function(softwares){
|
||||
$.ajax({
|
||||
dataType: "json",
|
||||
url: monitorEndPoint + 'getTotalSoftwares/',
|
||||
success: function(softwaresTotal){
|
||||
var chart = $('#softwares .chart').highcharts(),
|
||||
series = chart.get('softwares');
|
||||
|
||||
$('#softwares .table tbody').empty();
|
||||
|
||||
$.each(softwaresTotal, function(software, hits){
|
||||
$('#softwares .table tbody').append(
|
||||
newTr = $('<tr>').attr('data-name', software).on('mouseover', function(){
|
||||
chart.get('software-' + makeSlug(software)).setState('hover');
|
||||
chart.tooltip.refresh(chart.get('software-' + makeSlug(software)));
|
||||
}).on('mouseout', function(){
|
||||
chart.get('software-' + makeSlug(software)).setState('');
|
||||
chart.tooltip.hide();
|
||||
}).append(
|
||||
$('<td>').addClass('square')
|
||||
).append(
|
||||
$('<td>').html('<strong>' + software + '</strong>')
|
||||
)
|
||||
.append(
|
||||
$('<td>').addClass('stat today').html(formatNumber(softwares[today][software] || 0))
|
||||
)
|
||||
.append(
|
||||
$('<td>').addClass('stat yesterday').html(formatNumber(softwares[yesterday][software] || 0))
|
||||
)
|
||||
.append(
|
||||
$('<td>').addClass('stat total').html('<strong>' + formatNumber(hits) + '</strong>')
|
||||
)
|
||||
);
|
||||
|
||||
if(!chart.get('software-' + makeSlug(software)))
|
||||
series.addPoint({id: 'software-' + makeSlug(software), name: software, y: parseInt(hits)}, false);
|
||||
else
|
||||
chart.get('software-' + makeSlug(software)).update(parseInt(hits), false);
|
||||
|
||||
newTr.find('.square').css('background', chart.get('software-' + makeSlug(software)).color);
|
||||
});
|
||||
|
||||
chart.redraw();
|
||||
|
||||
$('#softwares').find(".stat").removeClass("warning").each(function() {
|
||||
if ($(this).html() == "0")
|
||||
$(this).addClass("warning");
|
||||
});
|
||||
|
||||
$('#softwares').find(".update_timestamp").html(d.toString("yyyy-MM-dd HH:mm:ss"));
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
var doUpdateUploaders = function()
|
||||
{
|
||||
var dToday = new Date(),
|
||||
dYesterday = new (function(d){ d.setDate(d.getDate()-1); return d})(new Date),
|
||||
|
||||
yesterday = dYesterday.getUTCFullYear() + '-' + ("0" + (dYesterday.getUTCMonth() + 1)).slice(-2) + '-' + ("0" + (dYesterday.getUTCDate())).slice(-2),
|
||||
today = dToday.getUTCFullYear() + '-' + ("0" + (dToday.getUTCMonth() + 1)).slice(-2) + '-' + ("0" + (dToday.getUTCDate())).slice(-2);
|
||||
|
||||
$.ajax({
|
||||
dataType: "json",
|
||||
url: monitorEndPoint + 'getUploaders/?dateStart=' + yesterday + '&dateEnd = ' + today,
|
||||
success: function(uploaders){
|
||||
$.ajax({
|
||||
dataType: "json",
|
||||
url: monitorEndPoint + 'getTotalUploaders/',
|
||||
success: function(uploadersTotal){
|
||||
var chart = $('#uploaders .chart').highcharts(),
|
||||
series = chart.get('uploaders');
|
||||
|
||||
$('#uploaders .table tbody').empty();
|
||||
|
||||
$.each(uploadersTotal, function(uploader, hits){
|
||||
if(uploader.length > 32)
|
||||
truncateUploader = jQuery.trim(uploader).substring(0, 32)/*.split(" ").slice(0, -1).join(" ")*/ + "..."
|
||||
else
|
||||
truncateUploader = uploader
|
||||
|
||||
$('#uploaders .table tbody').append(
|
||||
newTr = $('<tr>').attr('data-name', uploader).on('mouseover', function(){
|
||||
chart.get('uploader-' + makeSlug(uploader)).setState('hover');
|
||||
chart.tooltip.refresh(chart.get('uploader-' + makeSlug(uploader)));
|
||||
}).on('mouseout', function(){
|
||||
chart.get('uploader-' + makeSlug(uploader)).setState('');
|
||||
chart.tooltip.hide();
|
||||
}).append(
|
||||
$('<td>').addClass('square')
|
||||
).append(
|
||||
$('<td>').html('<strong>' + truncateUploader + '</strong>')
|
||||
)
|
||||
.append(
|
||||
$('<td>').addClass('stat today').html(formatNumber(uploaders[today][uploader] || 0))
|
||||
)
|
||||
.append(
|
||||
$('<td>').addClass('stat yesterday').html(formatNumber(uploaders[yesterday][uploader] || 0))
|
||||
)
|
||||
.append(
|
||||
$('<td>').addClass('stat total').html('<strong>' + formatNumber(hits) + '</strong>')
|
||||
)
|
||||
);
|
||||
|
||||
if(!chart.get('uploader-' + makeSlug(uploader)))
|
||||
series.addPoint({id: 'uploader-' + makeSlug(uploader), name: uploader, y: parseInt(hits)}, false);
|
||||
else
|
||||
chart.get('uploader-' + makeSlug(uploader)).update(parseInt(hits), false);
|
||||
|
||||
newTr.find('.square').css('background', chart.get('uploader-' + makeSlug(uploader)).color);
|
||||
});
|
||||
|
||||
chart.redraw();
|
||||
|
||||
$('#uploaders').find(".stat").removeClass("warning").each(function() {
|
||||
if ($(this).html() == "0")
|
||||
$(this).addClass("warning");
|
||||
});
|
||||
|
||||
$('#uploaders').find(".update_timestamp").html(d.toString("yyyy-MM-dd HH:mm:ss"));
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
var doUpdateSchemas = function()
|
||||
{
|
||||
var dToday = new Date(),
|
||||
dYesterday = new (function(d){ d.setDate(d.getDate()-1); return d})(new Date),
|
||||
|
||||
yesterday = dYesterday.getUTCFullYear() + '-' + ("0" + (dYesterday.getUTCMonth() + 1)).slice(-2) + '-' + ("0" + (dYesterday.getUTCDate())).slice(-2),
|
||||
today = dToday.getUTCFullYear() + '-' + ("0" + (dToday.getUTCMonth() + 1)).slice(-2) + '-' + ("0" + (dToday.getUTCDate())).slice(-2);
|
||||
|
||||
$.ajax({
|
||||
dataType: "json",
|
||||
url: monitorEndPoint + 'getSchemas/?dateStart=' + yesterday + '&dateEnd = ' + today,
|
||||
success: function(schemas){
|
||||
$.ajax({
|
||||
dataType: "json",
|
||||
url: monitorEndPoint + 'getTotalSchemas/',
|
||||
success: function(schemasTotal){
|
||||
var chart = $('#schemas .chart').highcharts(),
|
||||
series = chart.get('schemas');
|
||||
|
||||
$('#schemas .table tbody').empty();
|
||||
|
||||
$.each(schemasTotal, function(schema, hits){
|
||||
$('#schemas .table tbody').append(
|
||||
newTr = $('<tr>').attr('data-name', schema).on('mouseover', function(){
|
||||
chart.get('schema-' + makeSlug(schema)).setState('hover');
|
||||
chart.tooltip.refresh(chart.get('schema-' + makeSlug(schema)));
|
||||
}).on('mouseout', function(){
|
||||
chart.get('schema-' + makeSlug(schema)).setState('');
|
||||
chart.tooltip.hide();
|
||||
}).append(
|
||||
$('<td>').addClass('square')
|
||||
).append(
|
||||
$('<td>').html('<strong>' + schema + '</strong>')
|
||||
)
|
||||
.append(
|
||||
$('<td>').addClass('stat today').html(formatNumber(schemas[today][schema] || 0))
|
||||
)
|
||||
.append(
|
||||
$('<td>').addClass('stat yesterday').html(formatNumber(schemas[yesterday][schema] || 0))
|
||||
)
|
||||
.append(
|
||||
$('<td>').addClass('stat total').html('<strong>' + formatNumber(hits) + '</strong>')
|
||||
)
|
||||
);
|
||||
|
||||
if(!chart.get('schema-' + makeSlug(schema)))
|
||||
series.addPoint({id: 'schema-' + makeSlug(schema), name: schema, y: parseInt(hits)}, false);
|
||||
else
|
||||
chart.get('schema-' + makeSlug(schema)).update(parseInt(hits), false);
|
||||
|
||||
newTr.find('.square').css('background', chart.get('schema-' + makeSlug(schema)).color);
|
||||
});
|
||||
|
||||
chart.redraw();
|
||||
|
||||
$('#schemas').find(".stat").removeClass("warning").each(function() {
|
||||
if ($(this).html() == "0")
|
||||
$(this).addClass("warning");
|
||||
});
|
||||
|
||||
$('#schemas').find(".update_timestamp").html(d.toString("yyyy-MM-dd HH:mm:ss"));
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
var doUpdates = function(type){
|
||||
$("select[name=" + type + "] option").each(function(){
|
||||
var currentItem = $(this).html(),
|
||||
isSelected = $(this).is(':selected');
|
||||
|
||||
$.ajax({
|
||||
dataType: "json",
|
||||
url: $(this).val(),
|
||||
success: function(data){
|
||||
d = new Date();
|
||||
|
||||
stats[type][currentItem]['lastUpdate'] = d.toString("yyyy-MM-dd HH:mm:ss");
|
||||
stats[type][currentItem]['last'] = data;
|
||||
|
||||
if(isSelected)
|
||||
showStats(type, currentItem);
|
||||
|
||||
var chart = $("#" + type + " .chart[data-name='" + currentItem + "']").highcharts();
|
||||
|
||||
shift = chart.get('inbound').data.length > 60;
|
||||
chart.get('inbound').addPoint([d.getTime(), (data['inbound'] || {})['1min'] || 0], true, shift);
|
||||
|
||||
if(type == 'gateways')
|
||||
{
|
||||
shift = chart.get('invalid').data.length > 60;
|
||||
chart.get('invalid').addPoint([d.getTime(), (data['invalid'] || {})['1min'] || 0], true, shift);
|
||||
}
|
||||
|
||||
if(type == 'relays')
|
||||
{
|
||||
shift = chart.get('duplicate').data.length > 60;
|
||||
chart.get('duplicate').addPoint([d.getTime(), (data['duplicate'] || {})['1min'] || 0], true, shift);
|
||||
}
|
||||
|
||||
shift = chart.get('outbound').data.length > 60;
|
||||
chart.get('outbound').addPoint([d.getTime(), (data['outbound'] || {})['1min'] || 0], true, shift);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
var showStats = function(type, currentItem){
|
||||
var el = $('#' + type),
|
||||
currentItemStats = stats[type][currentItem]['last'];
|
||||
|
||||
el.find(".inbound_1min").html((currentItemStats['inbound'] || {})['1min'] || 0);
|
||||
el.find(".inbound_5min").html((currentItemStats["inbound"] || {})['5min'] || 0);
|
||||
el.find(".inbound_60min").html((currentItemStats["inbound"] || {})['60min'] || 0);
|
||||
|
||||
if(type == 'gateways')
|
||||
{
|
||||
el.find(".invalid_1min").html((currentItemStats["invalid"] || {})['1min'] || 0);
|
||||
el.find(".invalid_5min").html((currentItemStats["invalid"] || {})['5min'] || 0);
|
||||
el.find(".invalid_60min").html((currentItemStats["invalid"] || {})['60min'] || 0);
|
||||
}
|
||||
|
||||
if(type == 'relays')
|
||||
{
|
||||
el.find(".duplicate_1min").html((currentItemStats["duplicate"] || {})['1min'] || 0);
|
||||
el.find(".duplicate_5min").html((currentItemStats["duplicate"] || {})['5min'] || 0);
|
||||
el.find(".duplicate_60min").html((currentItemStats["duplicate"] || {})['60min'] || 0);
|
||||
}
|
||||
|
||||
el.find(".outbound_1min").html((currentItemStats["outbound"] || {})['1min'] || 0);
|
||||
el.find(".outbound_5min").html((currentItemStats["outbound"] || {})['5min'] || 0);
|
||||
el.find(".outbound_60min").html((currentItemStats["outbound"] || {})['60min'] || 0);
|
||||
|
||||
el.find(".update_timestamp").html(stats[type][currentItem]['lastUpdate']);
|
||||
el.find(".version").html(currentItemStats['version'] || 'N/A');
|
||||
|
||||
if (currentItemStats['uptime'])
|
||||
el.find(".uptime").html(secondsToDurationString(currentItemStats['uptime']));
|
||||
else
|
||||
el.find(".uptime").html('N/A');
|
||||
|
||||
el.find(".stat").removeClass("warning").each(function() {
|
||||
if ($(this).html() == "0")
|
||||
$(this).addClass("warning");
|
||||
});
|
||||
|
||||
el.find(".chart").hide();
|
||||
el.find(".chart[data-name='" + currentItem + "']").show();
|
||||
$(window).trigger('resize'); // Fix wrong size in chart
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Launch monitoring
|
||||
*/
|
||||
var start = function(){
|
||||
Highcharts.setOptions({global: {useUTC: false}});
|
||||
|
||||
// Grab gateways
|
||||
gateways = gateways.sort();
|
||||
$.each(gateways, function(k, gateway){
|
||||
gateway = gateway.replace('tcp://', '');
|
||||
gateway = gateway.replace(':8500', '');
|
||||
|
||||
$("select[name=gateways]").append($('<option>', {
|
||||
value: 'http://' + gateway + ':' + gatewayBottlePort + '/stats/',
|
||||
text : gateway
|
||||
}));
|
||||
|
||||
$('#gateways .charts').append(
|
||||
$('<div>').addClass('chart')
|
||||
.css('width', '100%')
|
||||
.attr('data-name', gateway)
|
||||
);
|
||||
|
||||
$("#gateways .chart[data-name='" + gateway + "']").highcharts({
|
||||
chart: {
|
||||
type: 'spline', animation: Highcharts.svg
|
||||
},
|
||||
title: { text: '', style: {display: 'none'} },
|
||||
xAxis: {
|
||||
type: 'datetime',
|
||||
tickPixelInterval: 150
|
||||
},
|
||||
yAxis: {
|
||||
title: {text: ''},
|
||||
plotLines: [{value: 0, width: 1, color: '#808080'}],
|
||||
min: 0
|
||||
},
|
||||
tooltip: { enabled: false },
|
||||
credits: { enabled: false },
|
||||
exporting: { enabled: false },
|
||||
series: [
|
||||
{id: 'inbound', data: [], name: 'Messages received', zIndex: 300},
|
||||
{id: 'invalid', data: [], name: 'Invalid messages', zIndex: 1},
|
||||
{id: 'outbound', data: [], name: 'Messages passed to relay', zIndex: 200}
|
||||
]
|
||||
}).hide();
|
||||
|
||||
stats['gateways'][gateway] = {};
|
||||
});
|
||||
|
||||
doUpdates('gateways');
|
||||
setInterval(function(){
|
||||
doUpdates('gateways');
|
||||
}, updateInterval);
|
||||
|
||||
// Grab relays
|
||||
relays = relays.sort();
|
||||
$.each(relays, function(k, relay){
|
||||
$("select[name=relays]").append($('<option>', {
|
||||
value: 'http://' + relay + ':' + relayBottlePort + '/stats/',
|
||||
text : relay
|
||||
}));
|
||||
|
||||
$('#relays .charts').append(
|
||||
$('<div>').addClass('chart')
|
||||
.css('width', '100%')
|
||||
.attr('data-name', relay)
|
||||
);
|
||||
|
||||
$("#relays .chart[data-name='" + relay + "']").highcharts({
|
||||
chart: {
|
||||
type: 'spline', animation: Highcharts.svg,
|
||||
events: {
|
||||
load: function(){ setTimeout(function(){$(window).trigger('resize');}, 250); }
|
||||
},
|
||||
marginRight: 10
|
||||
},
|
||||
title: { text: '', style: {display: 'none'} },
|
||||
xAxis: {
|
||||
type: 'datetime',
|
||||
tickPixelInterval: 150
|
||||
},
|
||||
yAxis: {
|
||||
title: {text: ''},
|
||||
plotLines: [{value: 0, width: 1, color: '#808080'}],
|
||||
min: 0
|
||||
},
|
||||
tooltip: { enabled: false },
|
||||
credits: { enabled: false },
|
||||
exporting: { enabled: false },
|
||||
series: [
|
||||
{id: 'inbound', data: [], name: 'Messages received', zIndex: 300},
|
||||
{id: 'duplicate', data: [], name: 'Messages duplicate', zIndex: 1},
|
||||
{id: 'outbound', data: [], name: 'Messages passed to subscribers', zIndex: 200}
|
||||
]
|
||||
}).hide();
|
||||
|
||||
stats['relays'][relay] = {};
|
||||
});
|
||||
|
||||
doUpdates('relays');
|
||||
setInterval(function(){
|
||||
doUpdates('relays');
|
||||
}, updateInterval);
|
||||
|
||||
// Grab software from monitor
|
||||
$('#softwares .chart').highcharts({
|
||||
chart: {
|
||||
type: 'pie', animation: Highcharts.svg
|
||||
},
|
||||
title: { text: '', style: {display: 'none'} },
|
||||
credits: { enabled: false },
|
||||
tooltip: { headerFormat: '', pointFormat: '{point.name}: <b>{point.percentage:.1f}%</b>' },
|
||||
legend: { enabled: false },
|
||||
plotOptions: {pie: {allowPointSelect: false,dataLabels: { enabled: false }}},
|
||||
series: [{
|
||||
id: 'softwares',
|
||||
type: 'pie',
|
||||
data: []
|
||||
}]
|
||||
});
|
||||
|
||||
doUpdateSoftwares();
|
||||
setInterval(function(){
|
||||
doUpdateSoftwares();
|
||||
}, updateInterval);
|
||||
|
||||
// Grab uploader from monitor
|
||||
$('#uploaders .chart').highcharts({
|
||||
chart: {
|
||||
type: 'pie', animation: Highcharts.svg
|
||||
},
|
||||
title: { text: '', style: {display: 'none'} },
|
||||
credits: { enabled: false },
|
||||
tooltip: { headerFormat: '', pointFormat: '{point.name}: <b>{point.percentage:.1f}%</b>' },
|
||||
legend: { enabled: false },
|
||||
plotOptions: {pie: {allowPointSelect: false,dataLabels: { enabled: false }}},
|
||||
series: [{
|
||||
id: 'uploaders',
|
||||
type: 'pie',
|
||||
data: []
|
||||
}]
|
||||
});
|
||||
|
||||
doUpdateUploaders();
|
||||
setInterval(function(){
|
||||
doUpdateUploaders();
|
||||
}, updateInterval);
|
||||
|
||||
// Grab schema from monitor
|
||||
$('#schemas .chart').highcharts({
|
||||
chart: {
|
||||
type: 'pie', animation: Highcharts.svg
|
||||
},
|
||||
title: { text: '', style: {display: 'none'} },
|
||||
credits: { enabled: false },
|
||||
tooltip: { headerFormat: '', pointFormat: '{point.name}: <b>{point.percentage:.1f}%</b>' },
|
||||
legend: { enabled: false },
|
||||
plotOptions: {pie: {allowPointSelect: false,dataLabels: { enabled: false }}},
|
||||
series: [{
|
||||
id: 'schemas',
|
||||
type: 'pie',
|
||||
data: []
|
||||
}]
|
||||
});
|
||||
|
||||
doUpdateSchemas();
|
||||
setInterval(function(){
|
||||
doUpdateSchemas();
|
||||
}, updateInterval);
|
||||
|
||||
// Attach events
|
||||
$("select[name=gateways]").change(function(){
|
||||
showStats('gateways', $(this).find('option:selected').html());
|
||||
});
|
||||
$("select[name=relays]").change(function(){
|
||||
showStats('relays', $(this).find('option:selected').html());
|
||||
});
|
||||
}
|
||||
|
||||
$(document).ready(function(){
|
||||
start();
|
||||
});
|
||||
Vendored
-5
@@ -1,5 +0,0 @@
|
||||
/*!
|
||||
* Bootstrap v3.3.2 (http://getbootstrap.com)
|
||||
* Copyright 2011-2015 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
*//*! normalize.css v3.0.2 | MIT License | git.io/normalize */html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,:after,:before{color:#000!important;text-shadow:none!important;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}select{background:#fff!important}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff2) format('woff2'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-eur:before,.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:befoLine truncated
|
||||
Vendored
-7
@@ -1,7 +0,0 @@
|
||||
/*!
|
||||
* Bootstrap v3.3.2 (http://getbootstrap.com)
|
||||
* Copyright 2011-2015 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
*/
|
||||
if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){return a(b.target).is(this)?b.handleObj.handler.apply(this,arguments):void 0}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.2",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a(f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.2",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")&&(c.prop("checked")&&this.$element.hasClass("active")?a=!1:b.find(".active").removeClass("active")),a&&c.prop("checked",!this.$element.hasClass("active")).trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active"));a&&this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target);d.hasClass("btn")||(d=d.closest(".btn")),b.call(d,"toggle"),c.preventDefault()}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.2",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".iteLine truncated
|
||||
}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=this.unpin=this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.2",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return c>e?"top":!1;if("bottom"==this.affixed)return null!=c?e+this.unpin<=f.top?!1:"bottom":a-d>=e+g?!1:"bottom";var h=null==this.affixed,i=h?e:f.top,j=h?g:b;return null!=c&&c>=e?"top":null!=d&&i+j>=a-d?"bottom":!1},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=a("body").height();"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery);
|
||||
@@ -1,95 +0,0 @@
|
||||
secondsToDurationString = function(seconds) {
|
||||
var hours = Math.floor(seconds / 3600);
|
||||
var minutes = Math.floor((seconds - (hours * 3600)) / 60);
|
||||
var seconds = seconds - (hours * 3600) - (minutes * 60);
|
||||
var days = 0;
|
||||
|
||||
if (hours > 24) {
|
||||
days = Math.floor(hours / 24)
|
||||
hours = Math.floor((seconds - days * 24) / 3600);
|
||||
}
|
||||
|
||||
if (hours < 10) {hours = "0" + hours;}
|
||||
if (minutes < 10) {minutes = "0" + minutes;}
|
||||
if (seconds < 10) {seconds = "0" + seconds;}
|
||||
|
||||
if (days > 0) {
|
||||
return days + "d " + hours + ":" + minutes + ":" + seconds;
|
||||
}
|
||||
else {
|
||||
return hours + ":" + minutes + ":" + seconds;
|
||||
}
|
||||
}
|
||||
|
||||
displayGatewayStats = function(stats) {
|
||||
$("#gateway_inbound_1min").html((stats["inbound"] || {})["1min"] || 0);
|
||||
$("#gateway_inbound_5min").html((stats["inbound"] || {})["5min"] || 0);
|
||||
$("#gateway_inbound_60min").html((stats["inbound"] || {})["60min"] || 0);
|
||||
|
||||
$("#gateway_invalid_1min").html((stats["invalid"] || {})["1min"] || 0);
|
||||
$("#gateway_invalid_5min").html((stats["invalid"] || {})["5min"] || 0);
|
||||
$("#gateway_invalid_60min").html((stats["invalid"] || {})["60min"] || 0);
|
||||
|
||||
$("#gateway_outbound_1min").html((stats["outbound"] || {})["1min"] || 0);
|
||||
$("#gateway_outbound_5min").html((stats["outbound"] || {})["5min"] || 0);
|
||||
$("#gateway_outbound_60min").html((stats["outbound"] || {})["60min"] || 0);
|
||||
d = new Date();
|
||||
$("#update_gateway_timestamp").html(d.toString("yyyy-MM-dd HH:mm:ss"));
|
||||
$("#gateway_version").html(stats['version'] || "N/A");
|
||||
if (stats['uptime']) {
|
||||
$("#gateway_uptime").html(secondsToDurationString(stats['uptime']));
|
||||
}
|
||||
formatStats();
|
||||
}
|
||||
|
||||
displayRelayStats = function(stats) {
|
||||
$("#relay_inbound_1min").html((stats["inbound"] || {})["1min"] || 0);
|
||||
$("#relay_inbound_5min").html((stats["inbound"] || {})["5min"] || 0);
|
||||
$("#relay_inbound_60min").html((stats["inbound"] || {})["60min"] || 0);
|
||||
|
||||
$("#relay_outbound_1min").html((stats["outbound"] || {})["1min"] || 0);
|
||||
$("#relay_outbound_5min").html((stats["outbound"] || {})["5min"] || 0);
|
||||
$("#relay_outbound_60min").html((stats["outbound"] || {})["60min"] || 0);
|
||||
d = new Date();
|
||||
$("#update_relay_timestamp").html(d.toString("yyyy-MM-dd HH:mm:ss"));
|
||||
$("#relay_version").html(stats['version'] || "N/A");
|
||||
if (stats['uptime']) {
|
||||
$("#relay_uptime").html(secondsToDurationString(stats['uptime']));
|
||||
}
|
||||
formatStats();
|
||||
}
|
||||
|
||||
formatStats = function() {
|
||||
$(".stat").each(function() {
|
||||
if ($(this).html() == "0") {
|
||||
$(this).addClass("warning");
|
||||
}
|
||||
else {
|
||||
$(this).removeClass("warning");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
doUpdate = function(url, success, failure) {
|
||||
$.ajax({
|
||||
dataType: "json",
|
||||
url: url,
|
||||
success: success,
|
||||
failure: failure
|
||||
});
|
||||
}
|
||||
|
||||
getGatewayUrl = function() {
|
||||
return $("#gateway").val();
|
||||
}
|
||||
|
||||
getRelayUrl = function() {
|
||||
return $("#relay").val();
|
||||
}
|
||||
|
||||
$("#gateway").change(function() {doUpdate(getGatewayUrl(), displayGatewayStats);})
|
||||
$("#relay").change(function() {doUpdate(getRelayUrl(), displayRelayStats);})
|
||||
|
||||
doUpdate(getGatewayUrl(), displayGatewayStats);
|
||||
doUpdate(getRelayUrl(), displayRelayStats);
|
||||
setInterval(function() {doUpdate(getGatewayUrl(), displayGatewayStats); doUpdate(getRelayUrl(), displayRelayStats)}, 60000);
|
||||
Vendored
-4
@@ -1,4 +0,0 @@
|
||||
/*! jQuery v1.11.2 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */
|
||||
!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l="1.11.2",m=function(a,b){return new m.fn.init(a,b)},n=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,o=/^-ms-/,p=/-([\da-z])/gi,q=function(a,b){return b.toUpperCase()};m.fn=m.prototype={jquery:l,constructor:m,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=m.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return m.each(this,a,b)},map:function(a){return this.pushStack(m.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},m.extend=m.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||m.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(m.isPlainObject(c)||(b=m.isArray(c)))?(b?(b=!1,f=a&&m.isArray(a)?a:[]):f=a&&m.isPlainObject(a)?a:{},g[d]=m.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},m.extend({expando:"jQuery"+(l+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===m.type(a)},isArray:Array.isArray||function(a){return"array"===m.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return!m.isArray(a)&&a-parseFloat(a)+1>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==m.type(a)||a.nodeType||m.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(k.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&m.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(o,"ms-").replace(p,q)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=r(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(n,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(r(Object(a))?m.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=r(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(f=a[b],b=a,a=f),m.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||m.guid++,e):void 0},now:function(){return+new Date},support:k}),m.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function r(a){var b=a.length,c=m.type(a);return"function"===c||m.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var s=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=hb(),z=hb(),A=hb(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N=M.replace("w","w#"),O="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(Line truncated
|
||||
return!0}function Q(a,b,d,e){if(m.acceptData(a)){var f,g,h=m.expando,i=a.nodeType,j=i?m.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||m.guid++:h),j[k]||(j[k]=i?{}:{toJSON:m.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=m.extend(j[k],b):j[k].data=m.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[m.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[m.camelCase(b)])):f=g,f}}function R(a,b,c){if(m.acceptData(a)){var d,e,f=a.nodeType,g=f?m.cache:a,h=f?a[m.expando]:m.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){m.isArray(b)?b=b.concat(m.map(b,m.camelCase)):b in d?b=[b]:(b=m.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!P(d):!m.isEmptyObject(d))return}(c||(delete g[h].data,P(g[h])))&&(f?m.cleanData([a],!0):k.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}m.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?m.cache[a[m.expando]]:a[m.expando],!!a&&!P(a)},data:function(a,b,c){return Q(a,b,c)},removeData:function(a,b){return R(a,b)},_data:function(a,b,c){return Q(a,b,c,!0)},_removeData:function(a,b){return R(a,b,!0)}}),m.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=m.data(f),1===f.nodeType&&!m._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=m.camelCase(d.slice(5)),O(f,d,e[d])));m._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){m.data(this,a)}):arguments.length>1?this.each(function(){m.data(this,a,b)}):f?O(f,a,m.data(f,a)):void 0},removeData:function(a){return this.each(function(){m.removeData(this,a)})}}),m.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=m._data(a,b),c&&(!d||m.isArray(c)?d=m._data(a,b,m.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=m.queue(a,b),d=c.length,e=c.shift(),f=m._queueHooks(a,b),g=function(){m.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return m._data(a,c)||m._data(a,c,{empty:m.Callbacks("once memory").add(function(){m._removeData(a,b+"queue"),m._removeData(a,c)})})}}),m.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?m.queue(this[0],a):void 0===b?this:this.each(function(){var c=m.queue(this,a,b);m._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&m.dequeue(this,a)})},dequeue:function(a){return this.each(function(){m.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=m.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=m._data(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}});var S=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,T=["Top","Right","Bottom","Left"],U=function(a,b){return a=b||a,"none"===m.css(a,"display")||!m.contains(a.ownerDocument,a)},V=m.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===m.type(c)){e=!0;for(h in c)m.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,m.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(m(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},W=/^(?:checkbox|radio)$/i;!function(){var a=y.createElement("input"),b=y.createElement("div"),c=y.createDocumentFragment();if(b.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",k.leadingWhitespace=3===b.firstChild.nodeType,k.tbody=!b.getElementsByTagName("tbody").length,k.htmlSerialize=!!b.getElementsByTagName("link").length,k.html5Clone="<:nav></:nav>"!==y.createElement("nav").cloneNode(!0).outerHTML,a.type="checkbox",a.checked=!0,c.appendChild(a),k.appendChecked=a.checked,b.innerHTML="<textarea>x</textarea>",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,c.appendChild(b),b.innerHTML="<input type='radio' checked='checked' name='t'/>",k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,k.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){k.noCloneEvent=!1}),b.cloneNode(!0).click()),null==k.deleteExpando){k.deleteExpando=!0;try{delete b.test}catch(d){k.deleteExpando=!1}}}(),function(){var b,c,d=y.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(k[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),k[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var X=/^(?:input|select|textarea)$/i,Y=/^key/,Z=/^(?:mouse|pointer|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=/^([^.]*)(?:\.(.+)|)$/;function ab(){return!0}function bb(){return!1}function cb(){try{return y.activeElement}catch(a){}}m.event={global:{},add:function(a,b,c,d,e){var
Line truncated
|
||||
}m.Tween=Zb,Zb.prototype={constructor:Zb,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||"swing",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(m.cssNumber[c]?"":"px")},cur:function(){var a=Zb.propHooks[this.prop];return a&&a.get?a.get(this):Zb.propHooks._default.get(this)},run:function(a){var b,c=Zb.propHooks[this.prop];return this.pos=b=this.options.duration?m.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Zb.propHooks._default.set(this),this}},Zb.prototype.init.prototype=Zb.prototype,Zb.propHooks={_default:{get:function(a){var b;return null==a.elem[a.prop]||a.elem.style&&null!=a.elem.style[a.prop]?(b=m.css(a.elem,a.prop,""),b&&"auto"!==b?b:0):a.elem[a.prop]},set:function(a){m.fx.step[a.prop]?m.fx.step[a.prop](a):a.elem.style&&(null!=a.elem.style[m.cssProps[a.prop]]||m.cssHooks[a.prop])?m.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},Zb.propHooks.scrollTop=Zb.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},m.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},m.fx=Zb.prototype.init,m.fx.step={};var $b,_b,ac=/^(?:toggle|show|hide)$/,bc=new RegExp("^(?:([+-])=|)("+S+")([a-z%]*)$","i"),cc=/queueHooks$/,dc=[ic],ec={"*":[function(a,b){var c=this.createTween(a,b),d=c.cur(),e=bc.exec(b),f=e&&e[3]||(m.cssNumber[a]?"":"px"),g=(m.cssNumber[a]||"px"!==f&&+d)&&bc.exec(m.css(c.elem,a)),h=1,i=20;if(g&&g[3]!==f){f=f||g[3],e=e||[],g=+d||1;do h=h||".5",g/=h,m.style(c.elem,a,g+f);while(h!==(h=c.cur()/d)&&1!==h&&--i)}return e&&(g=c.start=+g||+d||0,c.unit=f,c.end=e[1]?g+(e[1]+1)*e[2]:+e[2]),c}]};function fc(){return setTimeout(function(){$b=void 0}),$b=m.now()}function gc(a,b){var c,d={height:a},e=0;for(b=b?1:0;4>e;e+=2-b)c=T[e],d["margin"+c]=d["padding"+c]=a;return b&&(d.opacity=d.width=a),d}function hc(a,b,c){for(var d,e=(ec[b]||[]).concat(ec["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function ic(a,b,c){var d,e,f,g,h,i,j,l,n=this,o={},p=a.style,q=a.nodeType&&U(a),r=m._data(a,"fxshow");c.queue||(h=m._queueHooks(a,"fx"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,n.always(function(){n.always(function(){h.unqueued--,m.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[p.overflow,p.overflowX,p.overflowY],j=m.css(a,"display"),l="none"===j?m._data(a,"olddisplay")||Fb(a.nodeName):j,"inline"===l&&"none"===m.css(a,"float")&&(k.inlineBlockNeedsLayout&&"inline"!==Fb(a.nodeName)?p.zoom=1:p.display="inline-block")),c.overflow&&(p.overflow="hidden",k.shrinkWrapBlocks()||n.always(function(){p.overflow=c.overflow[0],p.overflowX=c.overflow[1],p.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],ac.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(q?"hide":"show")){if("show"!==e||!r||void 0===r[d])continue;q=!0}o[d]=r&&r[d]||m.style(a,d)}else j=void 0;if(m.isEmptyObject(o))"inline"===("none"===j?Fb(a.nodeName):j)&&(p.display=j);else{r?"hidden"in r&&(q=r.hidden):r=m._data(a,"fxshow",{}),f&&(r.hidden=!q),q?m(a).show():n.done(function(){m(a).hide()}),n.done(function(){var b;m._removeData(a,"fxshow");for(b in o)m.style(a,b,o[b])});for(d in o)g=hc(q?r[d]:0,d,n),d in r||(r[d]=g.start,q&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function jc(a,b){var c,d,e,f,g;for(c in a)if(d=m.camelCase(c),e=b[d],f=a[c],m.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=m.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function kc(a,b,c){var d,e,f=0,g=dc.length,h=m.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=$b||fc(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:m.extend({},b),opts:m.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:$b||fc(),duration:c.duration,tweens:[],createTween:function(b,c){var d=m.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;d>c;c++)j.tweens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;for(jc(k,j.opts.specialEasing);g>f;f++)if(d=dc[f].call(j,a,k,j.opts))return d;return m.map(k,hc,j),m.isFunction(j.opts.start)&&j.opts.start.call(a,j),m.fx.timer(m.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}m.Animation=m.extend(kc,{tweener:function(a,b){m.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");for(var c,d=0,e=a.length;e>d;d++)c=a[d],ec[c]=ec[c]||[],ec[c].unshift(b)},prefilter:function(aLine truncated
|
||||
@@ -1,109 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>EDDN Status</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link href="css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="css/eddn.css" rel="stylesheet">
|
||||
|
||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<script src="js/jquery.min.js"></script>
|
||||
<script src="js/date.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h1>EDDN Status</h1>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p>This page shows transaction information (messages sent/received) for key points of the EDDN, over a one-, five- and sixty-minute period. Values automatically update every minute.</p>
|
||||
<h2>Gateway</h2>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<td class="form-inline">
|
||||
<select id="gateway" class="form-control">
|
||||
<option value="http://eddn-gateway.elite-markets.net:8080/stats/">eddn-gateway.elite-markets.net</option>
|
||||
</select>
|
||||
</td>
|
||||
<th>1 min</th>
|
||||
<th>5 min</th>
|
||||
<th>60 min</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Messages received</th>
|
||||
<td id="gateway_inbound_1min" class="stat">-</td>
|
||||
<td id="gateway_inbound_5min" class="stat">-</td>
|
||||
<td id="gateway_inbound_60min" class="stat">-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Invalid messages</th>
|
||||
<td id="gateway_invalid_1min" class="stat">-</td>
|
||||
<td id="gateway_invalid_5min" class="stat">-</td>
|
||||
<td id="gateway_invalid_60min" class="stat">-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Messages passed to relay</th>
|
||||
<td id="gateway_outbound_1min" class="stat">-</td>
|
||||
<td id="gateway_outbound_5min" class="stat">-</td>
|
||||
<td id="gateway_outbound_60min" class="stat">-</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p class="text-muted small">EDDN version <span id="gateway_version">N/A</span>. Uptime: <span id="gateway_uptime">N/A</span>. Last updated <span id="update_gateway_timestamp">N/A</span></p>
|
||||
<h2>Relay</h2>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<td class="form-inline">
|
||||
<select id="relay" class="form-control">
|
||||
<option value="http://eddn-relay.elite-markets.net:9090/stats/">eddn-relay.elite-markets.net</option>
|
||||
</select>
|
||||
</td>
|
||||
<th>1 min</th>
|
||||
<th>5 min</th>
|
||||
<th>60 min</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Messages received</th>
|
||||
<td id="relay_inbound_1min" class="stat">-</td>
|
||||
<td id="relay_inbound_5min" class="stat">-</td>
|
||||
<td id="relay_inbound_60min" class="stat">-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Messages passed to subscribers</th>
|
||||
<td id="relay_outbound_1min" class="stat">-</td>
|
||||
<td id="relay_outbound_5min" class="stat">-</td>
|
||||
<td id="relay_outbound_60min" class="stat">-</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p class="text-muted small">EDDN version <span id="relay_version">N/A</span>. Uptime: <span id="relay_uptime">N/A</span>. Last updated <span id="update_relay_timestamp">N/A</span></p>
|
||||
</div>
|
||||
<div class="panel-footer">
|
||||
<p>The <em>Elite: Dangerous Data Network</em> is volunteer-run and not affiliated with Frontier Developments.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||
<!-- Include all compiled plugins (below), or include individual files as needed -->
|
||||
<script src="js/bootstrap.min.js"></script>
|
||||
<script src="js/eddn.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -103,6 +103,9 @@ while (true)
|
||||
try
|
||||
{
|
||||
$subscriber->connect($relayEDDN);
|
||||
echoLog('Connect to ' . $relayEDDN);
|
||||
echoLog('');
|
||||
echoLog('');
|
||||
|
||||
while (true)
|
||||
{
|
||||
@@ -111,6 +114,9 @@ while (true)
|
||||
if ($message === false)
|
||||
{
|
||||
$subscriber->disconnect($relayEDDN);
|
||||
echoLog('Disconnect from ' . $relayEDDN);
|
||||
echoLog('');
|
||||
echoLog('');
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
+20
-4
@@ -52,13 +52,14 @@
|
||||
|
||||
class EDDN
|
||||
{
|
||||
static private $_debug = true;
|
||||
private static $_debug = true;
|
||||
|
||||
static private $_gateways = array(
|
||||
'http://eddn-gateway.elite-markets.net:8080/upload/'
|
||||
private static $_gateways = array(
|
||||
'http://eddn-gateway.elite-markets.net:8080/upload/',
|
||||
'http://eddn-gateway.ed-td.space:8080/upload/'
|
||||
);
|
||||
|
||||
static private $_schemas = array(
|
||||
private static $_schemas = array(
|
||||
'commodity-v1' => array(
|
||||
'production' => 'http://schemas.elite-markets.net/eddn/commodity/1',
|
||||
'test' => 'http://schemas.elite-markets.net/eddn/commodity/1/test'
|
||||
@@ -176,6 +177,8 @@ class EDDN
|
||||
{
|
||||
return $this->_uploaderID;
|
||||
}
|
||||
|
||||
|
||||
public function setSoftwareName($value)
|
||||
{
|
||||
$this->_softwareName = $value;
|
||||
@@ -185,6 +188,8 @@ class EDDN
|
||||
{
|
||||
return $this->_softwareName;
|
||||
}
|
||||
|
||||
|
||||
public function setSoftwareVersion($value)
|
||||
{
|
||||
$this->_softwareVersion = $value;
|
||||
@@ -194,4 +199,15 @@ class EDDN
|
||||
{
|
||||
return $this->_softwareVersion;
|
||||
}
|
||||
|
||||
|
||||
public function setDebug($value)
|
||||
{
|
||||
self::$_debug = $value;
|
||||
}
|
||||
|
||||
public function getDebug()
|
||||
{
|
||||
return self::$_debug;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
"C:\Python27\python.exe" "%~dp0\Client_Complete.py"
|
||||
|
||||
pause
|
||||
@@ -1,5 +1,5 @@
|
||||
import zlib
|
||||
import zmq.green as zmq
|
||||
import zmq
|
||||
import simplejson
|
||||
import sys, os, datetime, time
|
||||
|
||||
@@ -96,12 +96,18 @@ def main():
|
||||
while True:
|
||||
try:
|
||||
subscriber.connect(__relayEDDN)
|
||||
echoLog('Connect to ' + __relayEDDN)
|
||||
echoLog('')
|
||||
echoLog('')
|
||||
|
||||
while True:
|
||||
__message = subscriber.recv()
|
||||
|
||||
if __message == False:
|
||||
subscriber.disconnect(__relayEDDN)
|
||||
echoLog('Disconnect from ' + __relayEDDN)
|
||||
echoLog('')
|
||||
echoLog('')
|
||||
break
|
||||
|
||||
__message = zlib.decompress(__message)
|
||||
@@ -112,8 +118,8 @@ def main():
|
||||
# Handle commodity v1
|
||||
if __json['$schemaRef'] == 'http://schemas.elite-markets.net/eddn/commodity/1' + ('/test' if (__debugEDDN == True) else ''):
|
||||
echoLogJSON(__message)
|
||||
echoLog('Receiving commodity-v1 message...');
|
||||
echoLog(' - Converting to v2...');
|
||||
echoLog('Receiving commodity-v1 message...')
|
||||
echoLog(' - Converting to v2...')
|
||||
|
||||
__temp = {}
|
||||
__temp['$schemaRef'] = 'http://schemas.elite-markets.net/eddn/commodity/2' + ('/test' if (__debugEDDN == True) else '')
|
||||
@@ -0,0 +1,3 @@
|
||||
"C:\Python27\python.exe" "%~dp0\Client_Simple.py"
|
||||
|
||||
pause
|
||||
@@ -1,5 +1,5 @@
|
||||
import zlib
|
||||
import zmq.green as zmq
|
||||
import zmq
|
||||
import simplejson
|
||||
import sys
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
"C:\Python34\python.exe" "%~dp0\Client_Complete.py"
|
||||
|
||||
pause
|
||||
@@ -0,0 +1,218 @@
|
||||
import zlib
|
||||
import zmq
|
||||
import simplejson
|
||||
import sys, os, datetime, time
|
||||
|
||||
"""
|
||||
" Configuration
|
||||
"""
|
||||
__relayEDDN = 'tcp://eddn-relay.elite-markets.net:9500'
|
||||
__timeoutEDDN = 600000
|
||||
|
||||
# Set False to listen to production stream
|
||||
__debugEDDN = True;
|
||||
|
||||
# Set to False if you do not want verbose logging
|
||||
__logVerboseFile = os.path.dirname(__file__) + '/Logs_Verbose_EDDN_%DATE%.htm'
|
||||
#__logVerboseFile = False
|
||||
|
||||
# Set to False if you do not want JSON logging
|
||||
__logJSONFile = os.path.dirname(__file__) + '/Logs_JSON_EDDN_%DATE%.log'
|
||||
#__logJSONFile = False
|
||||
|
||||
# A sample list of authorised softwares
|
||||
__authorisedSoftwares = [
|
||||
"EDCE",
|
||||
"ED-TD.SPACE",
|
||||
"EliteOCR",
|
||||
"Maddavo's Market Share",
|
||||
"RegulatedNoise",
|
||||
"RegulatedNoise__DJ"
|
||||
]
|
||||
|
||||
# Used this to excludes yourself for example has you don't want to handle your own messages ^^
|
||||
__excludedSoftwares = [
|
||||
'My Awesome Market Uploader'
|
||||
]
|
||||
|
||||
|
||||
|
||||
"""
|
||||
" Start
|
||||
"""
|
||||
def date(__format):
|
||||
d = datetime.datetime.utcnow()
|
||||
return d.strftime(__format)
|
||||
|
||||
|
||||
__oldTime = False
|
||||
def echoLog(__str):
|
||||
global __oldTime, __logVerboseFile
|
||||
|
||||
if __logVerboseFile != False:
|
||||
__logVerboseFileParsed = __logVerboseFile.replace('%DATE%', str(date('%Y-%m-%d')))
|
||||
|
||||
if __logVerboseFile != False and not os.path.exists(__logVerboseFileParsed):
|
||||
f = open(__logVerboseFileParsed, 'w')
|
||||
f.write('<style type="text/css">html { white-space: pre; font-family: Courier New,Courier,Lucida Sans Typewriter,Lucida Typewriter,monospace; }</style>')
|
||||
f.close()
|
||||
|
||||
if (__oldTime == False) or (__oldTime != date('%H:%M:%S')):
|
||||
__oldTime = date('%H:%M:%S')
|
||||
__str = str(__oldTime) + ' | ' + str(__str)
|
||||
else:
|
||||
__str = ' ' + ' | ' + str(__str)
|
||||
|
||||
print (__str)
|
||||
sys.stdout.flush()
|
||||
|
||||
if __logVerboseFile != False:
|
||||
f = open(__logVerboseFileParsed, 'a')
|
||||
f.write(__str + '\n')
|
||||
f.close()
|
||||
|
||||
|
||||
def echoLogJSON(__json):
|
||||
global __logJSONFile
|
||||
|
||||
if __logJSONFile != False:
|
||||
__logJSONFileParsed = __logJSONFile.replace('%DATE%', str(date('%Y-%m-%d')))
|
||||
|
||||
f = open(__logJSONFileParsed, 'a')
|
||||
f.write(str(__json) + '\n')
|
||||
f.close()
|
||||
|
||||
|
||||
def main():
|
||||
echoLog('Starting EDDN Subscriber')
|
||||
echoLog('')
|
||||
|
||||
context = zmq.Context()
|
||||
subscriber = context.socket(zmq.SUB)
|
||||
|
||||
subscriber.setsockopt(zmq.SUBSCRIBE, b"")
|
||||
subscriber.setsockopt(zmq.RCVTIMEO, __timeoutEDDN)
|
||||
|
||||
while True:
|
||||
try:
|
||||
subscriber.connect(__relayEDDN)
|
||||
echoLog('Connect to ' + __relayEDDN)
|
||||
echoLog('')
|
||||
echoLog('')
|
||||
|
||||
while True:
|
||||
__message = subscriber.recv()
|
||||
|
||||
if __message == False:
|
||||
subscriber.disconnect(__relayEDDN)
|
||||
echoLog('Disconnect from ' + __relayEDDN)
|
||||
echoLog('')
|
||||
echoLog('')
|
||||
break
|
||||
|
||||
__message = zlib.decompress(__message)
|
||||
__json = simplejson.loads(__message)
|
||||
__converted = False
|
||||
|
||||
|
||||
# Handle commodity v1
|
||||
if __json['$schemaRef'] == 'http://schemas.elite-markets.net/eddn/commodity/1' + ('/test' if (__debugEDDN == True) else ''):
|
||||
echoLogJSON(__message)
|
||||
echoLog('Receiving commodity-v1 message...')
|
||||
echoLog(' - Converting to v2...')
|
||||
|
||||
__temp = {}
|
||||
__temp['$schemaRef'] = 'http://schemas.elite-markets.net/eddn/commodity/2' + ('/test' if (__debugEDDN == True) else '')
|
||||
__temp['header'] = __json['header']
|
||||
|
||||
__temp['message'] = {}
|
||||
__temp['message']['systemName'] = __json['message']['systemName']
|
||||
__temp['message']['stationName'] = __json['message']['stationName']
|
||||
__temp['message']['timestamp'] = __json['message']['timestamp']
|
||||
|
||||
__temp['message']['commodities'] = []
|
||||
|
||||
__commodity = {}
|
||||
|
||||
if 'itemName' in __json['message']:
|
||||
__commodity['name'] = __json['message']['itemName']
|
||||
|
||||
if 'buyPrice' in __json['message']:
|
||||
__commodity['buyPrice'] = __json['message']['buyPrice']
|
||||
if 'stationStock' in __json['message']:
|
||||
__commodity['supply'] = __json['message']['stationStock']
|
||||
if 'supplyLevel' in __json['message']:
|
||||
__commodity['supplyLevel'] = __json['message']['supplyLevel']
|
||||
|
||||
if 'sellPrice' in __json['message']:
|
||||
__commodity['sellPrice'] = __json['message']['sellPrice']
|
||||
if 'demand' in __json['message']:
|
||||
__commodity['demand'] = __json['message']['demand']
|
||||
if'demandLevel' in __json['message']:
|
||||
__commodity['demandLevel'] = __json['message']['demandLevel']
|
||||
|
||||
__temp['message']['commodities'].append(__commodity)
|
||||
__json = __temp
|
||||
del __temp, __commodity
|
||||
|
||||
__converted = True
|
||||
|
||||
# Handle commodity v2
|
||||
if __json['$schemaRef'] == 'http://schemas.elite-markets.net/eddn/commodity/2' + ('/test' if (__debugEDDN == True) else ''):
|
||||
if __converted == False:
|
||||
echoLogJSON(__message)
|
||||
echoLog('Receiving commodity-v2 message...')
|
||||
|
||||
__authorised = False
|
||||
__excluded = False
|
||||
|
||||
if __json['header']['softwareName'] in __authorisedSoftwares:
|
||||
__authorised = True
|
||||
if __json['header']['softwareName'] in __excludedSoftwares:
|
||||
__excluded = True
|
||||
|
||||
echoLog(' - Software: ' + __json['header']['softwareName'] + ' / ' + __json['header']['softwareVersion'])
|
||||
echoLog(' - ' + 'AUTHORISED' if (__authorised == True) else
|
||||
('EXCLUDED' if (__excluded == True) else 'UNAUTHORISED')
|
||||
)
|
||||
|
||||
if __authorised == True and __excluded == False:
|
||||
# Do what you want with the data...
|
||||
# Have fun !
|
||||
|
||||
# For example
|
||||
echoLog(' - Timestamp: ' + __json['message']['timestamp'])
|
||||
echoLog(' - Uploader ID: ' + __json['header']['uploaderID'])
|
||||
echoLog(' - System Name: ' + __json['message']['systemName'])
|
||||
echoLog(' - Station Name: ' + __json['message']['stationName'])
|
||||
|
||||
for __commodity in __json['message']['commodities']:
|
||||
echoLog(' - Name: ' + __commodity['name'])
|
||||
echoLog(' - Buy Price: ' + str(__commodity['buyPrice']))
|
||||
echoLog(' - Supply: ' + str(__commodity['supply'])
|
||||
+ ((' (' + __commodity['supplyLevel'] + ')') if 'supplyLevel' in __commodity else '')
|
||||
)
|
||||
echoLog(' - Sell Price: ' + str(__commodity['sellPrice']))
|
||||
echoLog(' - Demand: ' + str(__commodity['demand'])
|
||||
+ ((' (' + __commodity['demandLevel'] + ')') if 'demandLevel' in __commodity else '')
|
||||
)
|
||||
# End example
|
||||
|
||||
del __authorised, __excluded
|
||||
|
||||
echoLog('')
|
||||
echoLog('')
|
||||
|
||||
del __converted
|
||||
|
||||
|
||||
except zmq.ZMQError as e:
|
||||
echoLog('')
|
||||
echoLog('ZMQSocketException: ' + str(e))
|
||||
echoLog('')
|
||||
time.sleep(10)
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,3 @@
|
||||
"C:\Python34\python.exe" "%~dp0\Client_Simple.py"
|
||||
|
||||
pause
|
||||
@@ -0,0 +1,50 @@
|
||||
import zlib
|
||||
import zmq
|
||||
import simplejson
|
||||
import sys
|
||||
|
||||
"""
|
||||
" Configuration
|
||||
"""
|
||||
__relayEDDN = 'tcp://eddn-relay.elite-markets.net:9500'
|
||||
__timeoutEDDN = 600000
|
||||
|
||||
|
||||
|
||||
"""
|
||||
" Start
|
||||
"""
|
||||
def main():
|
||||
context = zmq.Context()
|
||||
subscriber = context.socket(zmq.SUB)
|
||||
|
||||
subscriber.setsockopt(zmq.SUBSCRIBE, b"")
|
||||
subscriber.setsockopt(zmq.RCVTIMEO, __timeoutEDDN)
|
||||
|
||||
while True:
|
||||
try:
|
||||
subscriber.connect(__relayEDDN)
|
||||
|
||||
while True:
|
||||
__message = subscriber.recv()
|
||||
|
||||
if __message == False:
|
||||
subscriber.disconnect(__relayEDDN)
|
||||
break
|
||||
|
||||
__message = zlib.decompress(__message)
|
||||
__json = simplejson.loads(__message)
|
||||
|
||||
|
||||
print (__json)
|
||||
sys.stdout.flush()
|
||||
|
||||
except zmq.ZMQError as e:
|
||||
print ('ZMQSocketException: ' + str(e))
|
||||
sys.stdout.flush()
|
||||
time.sleep(10)
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,3 +0,0 @@
|
||||
"python" %~dp0\Client_Complete.py
|
||||
|
||||
pause
|
||||
@@ -1,3 +0,0 @@
|
||||
"python" %~dp0\Client_Simple.py
|
||||
|
||||
pause
|
||||
@@ -10,6 +10,7 @@
|
||||
"header" : {
|
||||
"type" : "object",
|
||||
"additionalProperties" : true,
|
||||
"required": [ "uploaderID", "softwareName", "softwareVersion" ],
|
||||
"properties" : {
|
||||
"uploaderID" : { "type": "string" },
|
||||
"softwareName" : { "type": "string" },
|
||||
|
||||
@@ -3,7 +3,7 @@ import re
|
||||
import glob
|
||||
|
||||
|
||||
VERSIONFILE = "src/eddn/_version.py"
|
||||
VERSIONFILE = "src/eddn/_Conf/Version.py"
|
||||
verstr = "unknown"
|
||||
try:
|
||||
verstrline = open(VERSIONFILE, "rt").read()
|
||||
@@ -34,6 +34,7 @@ setup(
|
||||
'console_scripts': [
|
||||
'eddn-gateway = eddn.Gateway:main',
|
||||
'eddn-relay = eddn.Relay:main',
|
||||
'eddn-monitor = eddn.Monitor:main',
|
||||
],
|
||||
}
|
||||
)
|
||||
+6
-7
@@ -14,7 +14,7 @@ from datetime import datetime
|
||||
import os
|
||||
|
||||
from eddn._Conf.Settings import Settings, loadConfig
|
||||
from eddn.Validator import Validator, ValidationSeverity
|
||||
from eddn._Core.Validator import Validator, ValidationSeverity
|
||||
|
||||
from gevent import monkey
|
||||
monkey.patch_all()
|
||||
@@ -29,7 +29,7 @@ sender = context.socket(zmq.PUB)
|
||||
validator = Validator()
|
||||
|
||||
# This import must be done post-monkey-patching!
|
||||
from eddn.StatsCollector import StatsCollector
|
||||
from eddn._Core.StatsCollector import StatsCollector
|
||||
statsCollector = StatsCollector()
|
||||
statsCollector.start()
|
||||
|
||||
@@ -42,11 +42,10 @@ def configure():
|
||||
sender.bind(binding)
|
||||
|
||||
for schemaRef, schemaFile in Settings.GATEWAY_JSON_SCHEMAS.iteritems():
|
||||
#filename = resource_filename(Requirement.parse("eddn"), schemaFile)
|
||||
validator.addSchemaResource(schemaRef, os.path.dirname(__file__) + '/' + schemaFile)
|
||||
|
||||
|
||||
def push_message(string_message):
|
||||
def push_message(string_message, topic):
|
||||
"""
|
||||
Spawned as a greenlet to push messages (strings) through ZeroMQ.
|
||||
This is a dumb method that just pushes strings; it assumes you've already validated
|
||||
@@ -54,9 +53,9 @@ def push_message(string_message):
|
||||
"""
|
||||
|
||||
# Push a zlib compressed JSON representation of the message to
|
||||
# announcers.
|
||||
# announcers with schema as topic
|
||||
compressed_msg = zlib.compress(string_message)
|
||||
sender.send(compressed_msg)
|
||||
sender.send("%s |-| %s" % (topic, compressed_msg))
|
||||
statsCollector.tally("outbound")
|
||||
|
||||
|
||||
@@ -143,7 +142,7 @@ def parse_and_error_handle(data):
|
||||
|
||||
# Sends the parsed MarketOrderList or MarketHistoryList to the Announcers
|
||||
# as compressed JSON.
|
||||
gevent.spawn(push_message, simplejson.dumps(parsed_message))
|
||||
gevent.spawn(push_message, simplejson.dumps(parsed_message), parsed_message['$schemaRef'])
|
||||
logger.info("Accepted %s upload from %s" % (
|
||||
parsed_message, get_remote_address()
|
||||
))
|
||||
|
||||
@@ -0,0 +1,251 @@
|
||||
"""
|
||||
Monitor sit below gateways, or another relay, and simply parse what it receives over SUB.
|
||||
"""
|
||||
from threading import Thread
|
||||
import zlib
|
||||
import gevent
|
||||
import simplejson
|
||||
import sqlite3
|
||||
import datetime
|
||||
import collections
|
||||
import zmq.green as zmq
|
||||
from bottle import get, request, response, run as bottle_run
|
||||
from eddn._Conf.Settings import Settings, loadConfig
|
||||
|
||||
from gevent import monkey
|
||||
monkey.patch_all()
|
||||
|
||||
if Settings.RELAY_DUPLICATE_MAX_MINUTES:
|
||||
from eddn._Core.DuplicateMessages import DuplicateMessages
|
||||
duplicateMessages = DuplicateMessages()
|
||||
duplicateMessages.start()
|
||||
|
||||
def date(__format):
|
||||
d = datetime.datetime.utcnow()
|
||||
return d.strftime(__format)
|
||||
|
||||
|
||||
@get('/getTotalSoftwares/')
|
||||
def getTotalSoftwares():
|
||||
response.set_header("Access-Control-Allow-Origin", "*")
|
||||
db = sqlite3.connect(Settings.MONITOR_DB)
|
||||
softwares = collections.OrderedDict()
|
||||
|
||||
maxDays = request.GET.get('maxDays', '31').strip()
|
||||
maxDays = int(maxDays) -1;
|
||||
|
||||
query = """SELECT name, SUM(hits) AS total, MAX(dateStats) AS maxDate
|
||||
FROM softwares
|
||||
GROUP BY name
|
||||
HAVING maxDate >= DATE('now', '""" + '-' + str(maxDays) + """ day')
|
||||
ORDER BY total DESC"""
|
||||
results = db.execute(query)
|
||||
|
||||
for row in results:
|
||||
softwares[str(row[0])] = str(row[1])
|
||||
|
||||
db.close()
|
||||
|
||||
return simplejson.dumps(softwares)
|
||||
|
||||
@get('/getSoftwares/')
|
||||
def getSoftwares():
|
||||
response.set_header("Access-Control-Allow-Origin", "*")
|
||||
db = sqlite3.connect(Settings.MONITOR_DB)
|
||||
softwares = collections.OrderedDict()
|
||||
|
||||
dateStart = request.GET.get('dateStart', str(date('%Y-%m-%d'))).strip()
|
||||
dateEnd = request.GET.get('dateEnd', str(date('%Y-%m-%d'))).strip()
|
||||
|
||||
query = """SELECT *
|
||||
FROM softwares
|
||||
WHERE dateStats BETWEEN ? AND ?
|
||||
ORDER BY hits DESC, dateStats ASC"""
|
||||
results = db.execute(query, (dateStart, dateEnd))
|
||||
|
||||
for row in results:
|
||||
if not str(row[2]) in softwares.keys():
|
||||
softwares[str(row[2])] = collections.OrderedDict()
|
||||
|
||||
softwares[str(row[2])][str(row[0])] = str(row[1])
|
||||
|
||||
db.close()
|
||||
|
||||
return simplejson.dumps(softwares)
|
||||
|
||||
@get('/getTotalUploaders/')
|
||||
def getTotalUploaders():
|
||||
response.set_header("Access-Control-Allow-Origin", "*")
|
||||
db = sqlite3.connect(Settings.MONITOR_DB)
|
||||
uploaders = collections.OrderedDict()
|
||||
|
||||
limit = request.GET.get('limit', '20').strip()
|
||||
|
||||
query = """SELECT name, SUM(hits) AS total
|
||||
FROM uploaders
|
||||
GROUP BY name
|
||||
ORDER BY total DESC
|
||||
LIMIT """ + limit
|
||||
results = db.execute(query)
|
||||
|
||||
for row in results:
|
||||
uploaders[str(row[0])] = str(row[1])
|
||||
|
||||
db.close()
|
||||
|
||||
return simplejson.dumps(uploaders)
|
||||
|
||||
@get('/getUploaders/')
|
||||
def getUploaders():
|
||||
response.set_header("Access-Control-Allow-Origin", "*")
|
||||
db = sqlite3.connect(Settings.MONITOR_DB)
|
||||
uploaders = collections.OrderedDict()
|
||||
|
||||
dateStart = request.GET.get('dateStart', str(date('%Y-%m-%d'))).strip()
|
||||
dateEnd = request.GET.get('dateEnd', str(date('%Y-%m-%d'))).strip()
|
||||
|
||||
query = """SELECT *
|
||||
FROM uploaders
|
||||
WHERE dateStats BETWEEN ? AND ?
|
||||
ORDER BY hits DESC, dateStats ASC"""
|
||||
results = db.execute(query, (dateStart, dateEnd))
|
||||
|
||||
for row in results:
|
||||
if not str(row[2]) in uploaders.keys():
|
||||
uploaders[str(row[2])] = collections.OrderedDict()
|
||||
|
||||
uploaders[str(row[2])][str(row[0])] = str(row[1])
|
||||
|
||||
db.close()
|
||||
|
||||
return simplejson.dumps(uploaders)
|
||||
|
||||
@get('/getTotalSchemas/')
|
||||
def getTotalSchemas():
|
||||
response.set_header("Access-Control-Allow-Origin", "*")
|
||||
db = sqlite3.connect(Settings.MONITOR_DB)
|
||||
schemas = collections.OrderedDict()
|
||||
|
||||
query = """SELECT name, SUM(hits) AS total
|
||||
FROM schemas
|
||||
GROUP BY name
|
||||
ORDER BY total DESC"""
|
||||
results = db.execute(query)
|
||||
|
||||
for row in results:
|
||||
schemas[str(row[0])] = str(row[1])
|
||||
|
||||
db.close()
|
||||
|
||||
return simplejson.dumps(schemas)
|
||||
|
||||
@get('/getSchemas/')
|
||||
def getSchemas():
|
||||
response.set_header("Access-Control-Allow-Origin", "*")
|
||||
db = sqlite3.connect(Settings.MONITOR_DB)
|
||||
schemas = collections.OrderedDict()
|
||||
|
||||
dateStart = request.GET.get('dateStart', str(date('%Y-%m-%d'))).strip()
|
||||
dateEnd = request.GET.get('dateEnd', str(date('%Y-%m-%d'))).strip()
|
||||
|
||||
query = """SELECT *
|
||||
FROM schemas
|
||||
WHERE dateStats BETWEEN ? AND ?
|
||||
ORDER BY hits DESC, dateStats ASC"""
|
||||
results = db.execute(query, (dateStart, dateEnd))
|
||||
|
||||
for row in results:
|
||||
if not str(row[2]) in schemas.keys():
|
||||
schemas[str(row[2])] = collections.OrderedDict()
|
||||
|
||||
schemas[str(row[2])][str(row[0])] = str(row[1])
|
||||
|
||||
db.close()
|
||||
|
||||
return simplejson.dumps(schemas)
|
||||
|
||||
|
||||
|
||||
class Monitor(Thread):
|
||||
|
||||
def run(self):
|
||||
context = zmq.Context()
|
||||
|
||||
receiver = context.socket(zmq.SUB)
|
||||
receiver.setsockopt(zmq.SUBSCRIBE, '')
|
||||
|
||||
for binding in Settings.MONITOR_RECEIVER_BINDINGS:
|
||||
receiver.connect(binding)
|
||||
|
||||
def monitor_worker(message):
|
||||
db = sqlite3.connect(Settings.MONITOR_DB)
|
||||
|
||||
# Separate topic from message
|
||||
message = message.split(' |-| ')
|
||||
|
||||
# Handle gateway not sending topic
|
||||
if len(message) > 1:
|
||||
message = message[1]
|
||||
else:
|
||||
message = message[0]
|
||||
|
||||
|
||||
if Settings.RELAY_DUPLICATE_MAX_MINUTES:
|
||||
if duplicateMessages.isDuplicated(message):
|
||||
schemaID = 'DUPLICATE MESSAGE'
|
||||
|
||||
c = db.cursor()
|
||||
c.execute('UPDATE schemas SET hits = hits + 1 WHERE `name` = ? AND `dateStats` = DATE("now", "utc")', (schemaID, ))
|
||||
c.execute('INSERT OR IGNORE INTO schemas (name, dateStats) VALUES (?, DATE("now", "utc"))', (schemaID, ))
|
||||
db.commit()
|
||||
|
||||
return
|
||||
|
||||
if Settings.MONITOR_DECOMPRESS_MESSAGES:
|
||||
message = zlib.decompress(message)
|
||||
|
||||
json = simplejson.loads(message)
|
||||
|
||||
# Update software count
|
||||
softwareID = json['header']['softwareName'] + ' | ' + json['header']['softwareVersion']
|
||||
|
||||
c = db.cursor()
|
||||
c.execute('UPDATE softwares SET hits = hits + 1 WHERE `name` = ? AND `dateStats` = DATE("now", "utc")', (softwareID, ))
|
||||
c.execute('INSERT OR IGNORE INTO softwares (name, dateStats) VALUES (?, DATE("now", "utc"))', (softwareID, ))
|
||||
db.commit()
|
||||
|
||||
|
||||
# Update uploader count
|
||||
uploaderID = json['header']['uploaderID']
|
||||
|
||||
if uploaderID: # Don't get empty uploaderID
|
||||
c = db.cursor()
|
||||
c.execute('UPDATE uploaders SET hits = hits + 1 WHERE `name` = ? AND `dateStats` = DATE("now", "utc")', (uploaderID, ))
|
||||
c.execute('INSERT OR IGNORE INTO uploaders (name, dateStats) VALUES (?, DATE("now", "utc"))', (uploaderID, ))
|
||||
db.commit()
|
||||
|
||||
|
||||
# Update schemas count
|
||||
schemaID = json['$schemaRef']
|
||||
|
||||
c = db.cursor()
|
||||
c.execute('UPDATE schemas SET hits = hits + 1 WHERE `name` = ? AND `dateStats` = DATE("now", "utc")', (schemaID, ))
|
||||
c.execute('INSERT OR IGNORE INTO schemas (name, dateStats) VALUES (?, DATE("now", "utc"))', (schemaID, ))
|
||||
db.commit()
|
||||
|
||||
db.close()
|
||||
|
||||
while True:
|
||||
inboundMessage = receiver.recv()
|
||||
gevent.spawn(monitor_worker, inboundMessage)
|
||||
|
||||
|
||||
def main():
|
||||
loadConfig()
|
||||
m = Monitor()
|
||||
m.start()
|
||||
bottle_run(host='0.0.0.0', port=9091, server='gevent')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
+33
-6
@@ -13,16 +13,21 @@ import gevent
|
||||
import simplejson
|
||||
import zmq.green as zmq
|
||||
from bottle import get, response, run as bottle_run
|
||||
from eddn.conf.Settings import Settings, loadConfig
|
||||
from eddn._Conf.Settings import Settings, loadConfig
|
||||
|
||||
from gevent import monkey
|
||||
monkey.patch_all()
|
||||
|
||||
from eddn.StatsCollector import StatsCollector
|
||||
from eddn._Core.StatsCollector import StatsCollector
|
||||
|
||||
statsCollector = StatsCollector()
|
||||
statsCollector.start()
|
||||
|
||||
if Settings.RELAY_DUPLICATE_MAX_MINUTES:
|
||||
from eddn._Core.DuplicateMessages import DuplicateMessages
|
||||
duplicateMessages = DuplicateMessages()
|
||||
duplicateMessages.start()
|
||||
|
||||
|
||||
@get('/stats/')
|
||||
def stats():
|
||||
@@ -42,12 +47,23 @@ class Relay(Thread):
|
||||
context = zmq.Context()
|
||||
|
||||
receiver = context.socket(zmq.SUB)
|
||||
receiver.setsockopt(zmq.SUBSCRIBE, '')
|
||||
|
||||
# Filters on topics or not...
|
||||
if Settings.RELAY_RECEIVE_ONLY_GATEWAY_EXTRA_JSON == True:
|
||||
for schemaRef, schemaFile in Settings.GATEWAY_JSON_SCHEMAS.iteritems():
|
||||
receiver.setsockopt(zmq.SUBSCRIBE, schemaRef)
|
||||
for schemaRef, schemaFile in Settings.RELAY_EXTRA_JSON_SCHEMAS.iteritems():
|
||||
receiver.setsockopt(zmq.SUBSCRIBE, schemaRef)
|
||||
else:
|
||||
receiver.setsockopt(zmq.SUBSCRIBE, '')
|
||||
|
||||
|
||||
for binding in Settings.RELAY_RECEIVER_BINDINGS:
|
||||
# Relays bind upstream to an Announcer, or another Relay.
|
||||
receiver.connect(binding)
|
||||
|
||||
sender = context.socket(zmq.PUB)
|
||||
|
||||
for binding in Settings.RELAY_SENDER_BINDINGS:
|
||||
# End users, or other relays, may attach here.
|
||||
sender.bind(binding)
|
||||
@@ -58,9 +74,20 @@ class Relay(Thread):
|
||||
to any subscribers.
|
||||
:param str message: A JSON string to re-broadcast.
|
||||
"""
|
||||
# if is_message_duped(message):
|
||||
# We've already seen this message recently. Discard it.
|
||||
# return
|
||||
# Separate topic from message
|
||||
message = message.split(' |-| ')
|
||||
|
||||
# Handle gateway not sending topic
|
||||
if len(message) > 1:
|
||||
message = message[1]
|
||||
else:
|
||||
message = message[0]
|
||||
|
||||
if Settings.RELAY_DUPLICATE_MAX_MINUTES:
|
||||
if duplicateMessages.isDuplicated(message):
|
||||
# We've already seen this message recently. Discard it.
|
||||
statsCollector.tally("duplicate")
|
||||
return
|
||||
|
||||
if Settings.RELAY_DECOMPRESS_MESSAGES:
|
||||
message = zlib.decompress(message)
|
||||
|
||||
@@ -6,7 +6,7 @@ Created on 15 Nov 2014
|
||||
|
||||
import argparse
|
||||
import simplejson
|
||||
from eddn._version import __version__ as version
|
||||
from eddn._Conf.Version import __version__ as version
|
||||
|
||||
|
||||
class _Settings(object):
|
||||
@@ -17,11 +17,22 @@ class _Settings(object):
|
||||
# Relay settings
|
||||
###############################################################################
|
||||
|
||||
RELAY_RECEIVER_BINDINGS = ["tcp://localhost:8500"]
|
||||
#RELAY_RECEIVER_BINDINGS = ["tcp://localhost:8500"]
|
||||
RELAY_RECEIVER_BINDINGS = ["tcp://eddn-gateway.elite-markets.net:8500", "tcp://eddn-gateway.ed-td.space:8500"]
|
||||
|
||||
RELAY_SENDER_BINDINGS = ["tcp://*:9500"]
|
||||
|
||||
RELAY_DECOMPRESS_MESSAGES = False
|
||||
|
||||
# If set to False, no deduplicate is made
|
||||
RELAY_DUPLICATE_MAX_MINUTES = 15
|
||||
|
||||
# If set to false, don't listen to topic and accept all incoming messages
|
||||
RELAY_RECEIVE_ONLY_GATEWAY_EXTRA_JSON = False
|
||||
|
||||
RELAY_EXTRA_JSON_SCHEMAS = {
|
||||
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Gateway settings
|
||||
@@ -36,10 +47,23 @@ class _Settings(object):
|
||||
GATEWAY_JSON_SCHEMAS = {
|
||||
"http://schemas.elite-markets.net/eddn/commodity/1": "schemas/commodity-v0.1.json",
|
||||
"http://schemas.elite-markets.net/eddn/commodity/1/test": "schemas/commodity-v0.1.json",
|
||||
"http://schemas.elite-markets.net/eddn/commodity/2": "schemas/commodity-v2.0-draft.json",
|
||||
"http://schemas.elite-markets.net/eddn/commodity/2/test": "schemas/commodity-v2.0-draft.json"
|
||||
|
||||
"http://schemas.elite-markets.net/eddn/commodity/2": "schemas/commodity-v2.0.json",
|
||||
"http://schemas.elite-markets.net/eddn/commodity/2/test": "schemas/commodity-v2.0.json"
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Monitor settings
|
||||
###############################################################################
|
||||
|
||||
MONITOR_RECEIVER_BINDINGS = ["tcp://eddn-gateway.elite-markets.net:8500", "tcp://eddn-gateway.ed-td.space:8500"]
|
||||
|
||||
MONITOR_DB = "/home/EDDN_Monitor.s3db"
|
||||
|
||||
MONITOR_DECOMPRESS_MESSAGES = True
|
||||
|
||||
|
||||
|
||||
def loadFrom(self, fileName):
|
||||
f = open(fileName, 'r')
|
||||
conf = simplejson.load(f)
|
||||
@@ -0,0 +1 @@
|
||||
__version__ = "0.4"
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,49 @@
|
||||
from datetime import datetime, timedelta
|
||||
from threading import Lock, Thread
|
||||
from time import sleep
|
||||
import hashlib
|
||||
import zlib
|
||||
import simplejson
|
||||
from eddn._Conf.Settings import Settings, loadConfig
|
||||
|
||||
|
||||
class DuplicateMessages(Thread):
|
||||
max_minutes = Settings.RELAY_DUPLICATE_MAX_MINUTES
|
||||
|
||||
caches = {}
|
||||
|
||||
lock = Lock()
|
||||
|
||||
def __init__(self):
|
||||
super(DuplicateMessages, self).__init__()
|
||||
self.daemon = True
|
||||
|
||||
def run(self):
|
||||
while True:
|
||||
sleep(60)
|
||||
with self.lock:
|
||||
maxTime = datetime.utcnow()
|
||||
|
||||
for key in self.caches.keys():
|
||||
if self.caches[key] + timedelta(minutes=self.max_minutes) < maxTime:
|
||||
del self.caches[key]
|
||||
|
||||
def isDuplicated(self, message):
|
||||
with self.lock:
|
||||
message = zlib.decompress(message)
|
||||
message = simplejson.loads(message)
|
||||
|
||||
if message['header']['gatewayTimestamp']:
|
||||
del message['header']['gatewayTimestamp'] # Prevent dupe with new timestamp ^^
|
||||
if message['message']['timestamp']:
|
||||
del message['message']['timestamp'] # Prevent dupe with new timestamp ^^
|
||||
|
||||
message = simplejson.dumps(message)
|
||||
key = hashlib.sha256(message).hexdigest()
|
||||
|
||||
if key not in self.caches:
|
||||
self.caches[key] = datetime.utcnow()
|
||||
return False
|
||||
else:
|
||||
self.caches[key] = datetime.utcnow()
|
||||
return True
|
||||
File renamed without changes.
File renamed without changes.
Whitespace-only changes.
@@ -1 +0,0 @@
|
||||
__version__ = "0.3"
|
||||
Reference in new issue
Block a user