moved xml to json, added syslog support, managed all signals
Costa Tsaousis (ktsaou) committed
Mar 29, 2014 at 02:52 UTC
f165a5e7f1824b3295b1e61e6522487e6ab4a958
2 files changed
+309
-202
netdata.c
+120
-57
@@ -27,6 +27,7 @@
27
#include <ctype.h>
28
#include <time.h>
29
#include <fcntl.h>
30
+#include <syslog.h>
31
32
#include <pthread.h>
33
@@ -171,6 +172,10 @@ void error_int( const char *file, const char *function, const unsigned long line
172
errno = 0;
173
}
174
else fprintf(stderr, "\n");
175
+
176
+ va_start( args, fmt );
177
+ vsyslog(LOG_ERR, fmt, args );
178
+ va_end( args );
179
}
180
181
#define fatal(args...) fatal_int(__FILE__, __FUNCTION__, __LINE__, ##args)
@@ -191,6 +196,10 @@ void fatal_int( const char *file, const char *function, const unsigned long line
196
perror(" # ");
197
fprintf(stderr, "\n");
198
199
+ va_start( args, fmt );
200
+ vsyslog(LOG_CRIT, fmt, args );
201
+ va_end( args );
202
+
203
exit(EXIT_FAILURE);
204
}
205
@@ -492,6 +501,8 @@ void rrd_stats_next(RRD_STATS *st)
501
now = &st->times[st->current_entry];
502
gettimeofday(now, NULL);
503
504
+ st->last_updated = now->tv_sec;
505
+
506
// leave mutex locked
507
}
508
@@ -563,47 +574,52 @@ void rrd_stats_dimension_set(RRD_STATS *st, const char *id, void *data)
574
#define GROUP_AVERAGE 0
575
#define GROUP_MAX 1
576
566
-size_t rrd_stats_one_xml(RRD_STATS *st, char *options, char *buffer, size_t len)
577
+size_t rrd_stats_one_json(RRD_STATS *st, char *options, char *buffer, size_t len)
578
{
579
size_t i = 0;
580
if(i + 200 > len) return(0);
581
571
- i += sprintf(&buffer[i], "\t<graph>\n");
572
- i += sprintf(&buffer[i], "\t\t<id>%s</id>\n", st->id);
573
- i += sprintf(&buffer[i], "\t\t<name>%s</name>\n", st->name);
574
- i += sprintf(&buffer[i], "\t\t<type>%s</type>\n", st->type);
575
- i += sprintf(&buffer[i], "\t\t<title>%s%s</title>\n", st->title, st->name);
576
- i += sprintf(&buffer[i], "\t\t<vtitle>%s</vtitle>\n", st->vtitle);
577
- i += sprintf(&buffer[i], "\t\t<dataurl>/data/%s/%s</dataurl>\n", st->name, options?options:"");
578
- i += sprintf(&buffer[i], "\t\t<entries>%ld</entries>\n", st->entries);
579
- i += sprintf(&buffer[i], "\t</graph>\n");
582
+ i += sprintf(&buffer[i], "\t\t{\n");
583
+ i += sprintf(&buffer[i], "\t\t\t\"id\" : \"%s\",\n", st->id);
584
+ i += sprintf(&buffer[i], "\t\t\t\"name\" : \"%s\",\n", st->name);
585
+ i += sprintf(&buffer[i], "\t\t\t\"type\" : \"%s\",\n", st->type);
586
+ i += sprintf(&buffer[i], "\t\t\t\"title\" : \"%s %s\",\n", st->title, st->name);
587
+ i += sprintf(&buffer[i], "\t\t\t\"vtitle\" : \"%s\",\n", st->vtitle);
588
+ i += sprintf(&buffer[i], "\t\t\t\"url\" : \"/data/%s/%s\",\n", st->name, options?options:"");
589
+ i += sprintf(&buffer[i], "\t\t\t\"entries\" : %ld,\n", st->entries);
590
+ i += sprintf(&buffer[i], "\t\t\t\"current\" : %ld,\n", st->current_entry);
591
+ i += sprintf(&buffer[i], "\t\t\t\"last_updated\" : %lu,\n", st->last_updated);
592
+ i += sprintf(&buffer[i], "\t\t\t\"last_updated_secs_ago\" : %lu\n", time(NULL) - st->last_updated);
593
+ i += sprintf(&buffer[i], "\t\t}");
594
595
return(i);
596
}
597
584
-#define RRD_GRAPH_XML_HEADER "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<?xml-stylesheet type=\"text/xsl\" href=\"/all.xsl\"?>\n\n<catalog>\n"
585
-#define RRD_GRAPH_XML_FOOTER "</catalog>\n"
598
+#define RRD_GRAPH_JSON_HEADER "{\n\t\"charts\": [\n"
599
+#define RRD_GRAPH_JSON_FOOTER "\n\t]\n}\n"
600
587
-size_t rrd_stats_graph_xml(RRD_STATS *st, char * options, char *buffer, size_t len)
601
+size_t rrd_stats_graph_json(RRD_STATS *st, char * options, char *buffer, size_t len)
602
{
603
size_t i = 0;
590
- i += sprintf(&buffer[i], RRD_GRAPH_XML_HEADER);
591
- i += rrd_stats_one_xml(st, options, &buffer[i], len - i);
592
- i += sprintf(&buffer[i], RRD_GRAPH_XML_FOOTER);
604
+ i += sprintf(&buffer[i], RRD_GRAPH_JSON_HEADER);
605
+ i += rrd_stats_one_json(st, options, &buffer[i], len - i);
606
+ i += sprintf(&buffer[i], RRD_GRAPH_JSON_FOOTER);
607
return(i);
608
}
609
596
-size_t rrd_stats_all_xml(char *buffer, size_t len)
610
+size_t rrd_stats_all_json(char *buffer, size_t len)
611
{
598
- size_t i = 0;
612
+ size_t i = 0, c;
613
RRD_STATS *st;
614
601
- i += sprintf(&buffer[i], RRD_GRAPH_XML_HEADER);
615
+ i += sprintf(&buffer[i], RRD_GRAPH_JSON_HEADER);
616
603
- for(st = root; st ; st = st->next)
604
- i += rrd_stats_one_xml(st, NULL, &buffer[i], len - i);
617
+ for(st = root, c = 0; st ; st = st->next, c++) {
618
+ if(c) i += sprintf(&buffer[i], "%s", ",\n");
619
+ i += rrd_stats_one_json(st, NULL, &buffer[i], len - i);
620
+ }
621
606
- i += sprintf(&buffer[i], RRD_GRAPH_XML_FOOTER);
622
+ i += sprintf(&buffer[i], RRD_GRAPH_JSON_FOOTER);
623
return(i);
624
}
625
@@ -831,6 +847,7 @@ void web_buffer_increase(struct web_buffer *b, size_t free_size_required)
847
848
struct web_client {
849
unsigned long long id;
850
+ char client_ip[101];
851
852
int mode;
853
int keepalive;
@@ -879,7 +896,11 @@ struct web_client *web_client_create(int listener)
896
}
897
w->ofd = w->ifd;
898
882
- debug(D_WEB_CLIENT_ACCESS, "%llu: New web client from %s on socket %d.", w->id, inet_ntoa(w->clientaddr.sin_addr), w->ifd);
899
+ strncpy(w->client_ip, inet_ntoa(w->clientaddr.sin_addr), 100);
900
+ w->client_ip[100] = '\0';
901
+
902
+ syslog(LOG_NOTICE, "%llu: New client from %s.", w->id, w->client_ip);
903
+ debug(D_WEB_CLIENT_ACCESS, "%llu: New web client from %s on socket %d.", w->id, w->client_ip, w->ifd);
904
905
{
906
int flag = 1;
@@ -979,6 +1000,8 @@ int mysendfile(struct web_client *w, char *filename)
1000
}
1001
}
1002
1003
+ syslog(LOG_NOTICE, "%llu: Sending file '%s' to client %s.", w->id, filename, w->client_ip);
1004
+
1005
// pick a Content-Type for the file
1006
if(strstr(filename, ".html") != NULL) w->data->contenttype = CT_TEXT_HTML;
1007
else if(strstr(filename, ".js") != NULL) w->data->contenttype = CT_APPLICATION_X_JAVASCRIPT;
@@ -1141,9 +1164,9 @@ void web_client_process(struct web_client *w)
1164
}
1165
else {
1166
code = 200;
1144
- debug(D_WEB_CLIENT_ACCESS, "%llu: Sending %s.xml of RRD_STATS...", w->id, st->name);
1145
- w->data->contenttype = CT_TEXT_XML;
1146
- w->data->bytes = rrd_stats_graph_xml(st, url, w->data->buffer, w->data->size);
1167
+ debug(D_WEB_CLIENT_ACCESS, "%llu: Sending %s.json of RRD_STATS...", w->id, st->name);
1168
+ w->data->contenttype = CT_APPLICATION_JSON;
1169
+ w->data->bytes = rrd_stats_graph_json(st, url, w->data->buffer, w->data->size);
1170
}
1171
}
1172
else if(strcmp(tok, "mirror") == 0) {
@@ -1165,11 +1188,11 @@ void web_client_process(struct web_client *w)
1188
for ( ; st ; st = st->next )
1189
w->data->bytes += sprintf(&w->data->buffer[w->data->bytes], "%s\n", st->name);
1190
}
1168
- else if(strcmp(tok, "all.xml") == 0) {
1191
+ else if(strcmp(tok, "all.json") == 0) {
1192
code = 200;
1170
- debug(D_WEB_CLIENT_ACCESS, "%llu: Sending all.xml of RRD_STATS...", w->id);
1171
- w->data->contenttype = CT_TEXT_XML;
1172
- w->data->bytes = rrd_stats_all_xml(w->data->buffer, w->data->size);
1193
+ debug(D_WEB_CLIENT_ACCESS, "%llu: Sending all.json of RRD_STATS...", w->id);
1194
+ w->data->contenttype = CT_APPLICATION_JSON;
1195
+ w->data->bytes = rrd_stats_all_json(w->data->buffer, w->data->size);
1196
}
1197
else if(strcmp(tok, WEB_PATH_FILE) == 0) { // "file"
1198
tok = mystrsep(&url, "/?&");
@@ -1507,7 +1530,7 @@ void *new_client(void *ptr)
1530
retval = select(fdmax+1, &ifds, &ofds, &efds, &tv);
1531
1532
if(retval == -1)
1510
- fatal("LISTENER: select() failed.");
1533
+ fatal("%llu: LISTENER: select() failed.", w->id);
1534
else if(!retval) {
1535
// timeout
1536
w->obsolete = 1;
@@ -1519,6 +1542,7 @@ void *new_client(void *ptr)
1542
w->obsolete = 1;
1543
return NULL;
1544
}
1545
+
1546
if(FD_ISSET(w->ofd, &efds)) {
1547
debug(D_WEB_CLIENT_ACCESS, "%llu: Received error on output socket (%s).", w->id, strerror(errno));
1548
w->obsolete = 1;
@@ -1545,6 +1569,7 @@ void *new_client(void *ptr)
1569
if(w->mode == WEB_CLIENT_MODE_NORMAL) web_client_process(w);
1570
}
1571
}
1572
+ debug(D_WEB_CLIENT, "%llu: done...", w->id);
1573
1574
return NULL;
1575
}
@@ -1590,10 +1615,15 @@ void *socket_listen_main(void *ptr)
1615
if(FD_ISSET(listener, &ifds)) {
1616
w = web_client_create(listener);
1617
1593
- w->thread = pthread_create(&w->thread, NULL, new_client, w);
1618
+ if(pthread_create(&w->thread, NULL, new_client, w) != 0)
1619
+ error("%llu: failed to create new thread.");
1620
+
1621
+ if(pthread_detach(w->thread) != 0)
1622
+ error("%llu: Cannot request detach of newly created thread.", w->id);
1623
}
1624
+ else debug(D_WEB_CLIENT, "LISTENER: select() didn't do anything.");
1625
}
1596
- // else timeout
1626
+ else debug(D_WEB_CLIENT, "LISTENER: select() timeout.");
1627
1628
// cleanup unused clients
1629
for(w = web_clients; w ; w = w?w->next:NULL) {
@@ -1604,6 +1634,8 @@ void *socket_listen_main(void *ptr)
1634
}
1635
}
1636
1637
+ error("LISTENER: exit!");
1638
+
1639
close(listener);
1640
exit(2);
1641
@@ -1794,7 +1826,7 @@ void *proc_main(void *ptr)
1826
1827
// calculate the time it took for a full loop
1828
usec = usecdiff(&now, &last);
1797
- debug(D_PROCNETDEV_LOOP, "PROCNETDEV: Last loop took %llu usec.", usec);
1829
+ debug(D_PROCNETDEV_LOOP, "PROCNETDEV: Last full loop took %llu usec.", usec);
1830
1831
// BEGIN -- the job to be done
1832
do_proc_net_dev(usec);
@@ -1804,7 +1836,7 @@ void *proc_main(void *ptr)
1836
// find the time to sleep in order to wait exactly update_every seconds
1837
gettimeofday(&tmp, NULL);
1838
usec = usecdiff(&tmp, &now);
1807
- debug(D_PROCNETDEV_LOOP, "PROCNETDEV: This loop took %llu usec.", usec);
1839
+ debug(D_PROCNETDEV_LOOP, "PROCNETDEV: This loop's work took %llu usec.", usec);
1840
1841
if(usec < (update_every * 1000000)) susec = (update_every * 1000000) - usec;
1842
else susec = 0;
@@ -2059,24 +2091,27 @@ void *tc_main(void *ptr)
2091
2092
void bye(void)
2093
{
2094
+ error("bye...");
2095
if(tc_child_pid) kill(tc_child_pid, SIGTERM);
2096
tc_child_pid = 0;
2097
}
2098
2099
void sig_handler(int signo)
2100
{
2068
- error("Signal %d received.", signo);
2069
-
2101
switch(signo) {
2102
case SIGTERM:
2103
case SIGQUIT:
2104
case SIGINT:
2105
case SIGHUP:
2075
- error("Cleanup.");
2106
+ error("Signaled cleanup (signal %d).", signo);
2107
if(tc_child_pid) kill(tc_child_pid, SIGTERM);
2108
tc_child_pid = 0;
2109
exit(1);
2110
break;
2111
+
2112
+ default:
2113
+ error("Signal %d received. Ignoring it.", signo);
2114
+ break;
2115
}
2116
}
2117
@@ -2107,6 +2142,44 @@ int become_user(const char *username)
2142
return(0);
2143
}
2144
2145
+void become_daemon()
2146
+{
2147
+ int i = fork();
2148
+ if(i == -1) {
2149
+ perror("cannot fork");
2150
+ exit(1);
2151
+ }
2152
+ if(i != 0) {
2153
+ exit(0); // the parent
2154
+ }
2155
+
2156
+ // become session leader
2157
+ if (setsid() < 0)
2158
+ exit(2);
2159
+
2160
+ signal(SIGCHLD, SIG_IGN);
2161
+ signal(SIGHUP, SIG_IGN);
2162
+
2163
+ // fork() again
2164
+ i = fork();
2165
+ if(i == -1) {
2166
+ perror("cannot fork");
2167
+ exit(1);
2168
+ }
2169
+ if(i != 0) {
2170
+ exit(0); // the parent
2171
+ }
2172
+
2173
+ // Set new file permissions
2174
+ umask(0);
2175
+
2176
+ // close all files
2177
+ for(i = sysconf(_SC_OPEN_MAX); i > 0; i--)
2178
+ close(i);
2179
+
2180
+ silent = 1;
2181
+}
2182
+
2183
int main(int argc, char **argv)
2184
{
2185
int i, daemon = 0;
@@ -2177,28 +2250,18 @@ int main(int argc, char **argv)
2250
fprintf(stderr, "Cannot lower my CPU priority. Error %s.\n", strerror(errno));
2251
}
2252
2180
- if(daemon) {
2181
- i = fork();
2182
- if(i == -1) {
2183
- perror("cannot fork");
2184
- exit(1);
2185
- }
2186
- if(i != 0) {
2187
- fprintf(stderr, "Running in the background...\n");
2188
- exit(0); // the parent
2189
- }
2190
- close(0);
2191
- close(1);
2192
- close(2);
2193
- silent = 1;
2194
- }
2253
+ if(daemon) become_daemon();
2254
+
2255
+ // open syslog
2256
+ openlog("netdata", LOG_PID, LOG_DAEMON);
2257
+ syslog(LOG_NOTICE, "netdata started.");
2258
2259
// make sure we cleanup correctly
2260
atexit(bye);
2198
- if(signal(SIGINT, sig_handler) == SIG_ERR) error("Can't catch SIGINT.");
2199
- if(signal(SIGTERM, sig_handler) == SIG_ERR) error("Can't catch SIGTERM.");
2200
- if(signal(SIGQUIT, sig_handler) == SIG_ERR) error("Can't catch SIGQUIT.");
2201
- if(signal(SIGHUP, sig_handler) == SIG_ERR) error("Can't catch SIGHUP.");
2261
+
2262
+ // catch all signals
2263
+ for (i = 1 ; i < 65 ;i++) signal(i, sig_handler);
2264
+
2265
2266
pthread_t p_proc, p_tc;
2267
int r_proc, r_tc;
web/netdata.js
+189
-145
@@ -1,161 +1,205 @@
1
- // fix old IE bug with console
2
- if(!window.console){ window.console = {log: function(){} }; }
3
-
4
- // Load the Visualization API and the piechart package.
5
- google.load('visualization', '1', {'packages':['corechart']});
6
-
7
- var charts = new Array();
1
+// fix old IE bug with console
2
+if(!window.console){ window.console = {log: function(){} }; }
3
9
- function refreshChart(index) {
10
- if(index >= charts.length) return;
11
-
12
- charts[index].refreshCount++;
13
-
14
- if(charts[index].chart != null) {
15
- if(charts[index].chart.getSelection()[0]) return;
16
-
17
- if(charts[index].refreshCount >= 9999999) {
18
- charts[index].jsondata = null;
19
- charts[index].datatable = null;
20
- charts[index].chart.clearChart();
21
- charts[index].chart = null;
22
- charts[index].refreshCount = 1;
23
- }
24
- }
25
-
26
- charts[index].jsondata = $.ajax({
27
- url: charts[index].url,
28
- dataType:"json",
29
- async: false,
30
- cache: false
31
- }).responseText;
32
-
33
- if(!charts[index].jsondata || charts[index].jsondata.length == 0) return;
34
-
35
- // Create our data table out of JSON data loaded from server.
36
- charts[index].datatable = new google.visualization.DataTable(charts[index].jsondata);
37
-
38
- // Instantiate and draw our chart, passing in some options.
39
- if(!charts[index].chart) {
40
- console.log('Creating new chart for ' + charts[index].url);
41
- charts[index].chart = new google.visualization.AreaChart(document.getElementById(charts[index].div));
42
- }
43
-
44
- var width = charts[index].width;
45
- var height = charts[index].height;
4
+// Load the Visualization API and the piechart package.
5
+google.load('visualization', '1', {'packages':['corechart']});
6
47
- var hAxisTitle = null;
48
- var vAxisTitle = null;
49
- if(height >= 250) hAxisTitle = "Time of Day";
50
- if(width >= 450) vAxisTitle = charts[index].vtitle;
7
+function refreshChart(chart) {
8
+ chart.refreshCount++;
9
+
10
+ if(chart.chart != null) {
11
+ if(chart.chart.getSelection()[0]) return;
12
52
- var title = charts[index].title;
53
-
54
- var isStacked = false;
55
- if(charts[index].name.substring(0, 3) == "tc.") {
56
- isStacked = true;
57
- title += " [stacked]";
13
+ if(chart.refreshCount >= 9999999) {
14
+ chart.jsondata = null;
15
+ chart.datatable = null;
16
+ chart.chart.clearChart();
17
+ chart.chart = null;
18
+ chart.refreshCount = 1;
19
}
20
+ }
21
+
22
+ chart.jsondata = $.ajax({
23
+ url: chart.url,
24
+ dataType:"json",
25
+ async: false,
26
+ cache: false
27
+ }).responseText;
28
+
29
+ if(!chart.jsondata || chart.jsondata.length == 0) return;
30
+
31
+ // Create our data table out of JSON data loaded from server.
32
+ chart.datatable = new google.visualization.DataTable(chart.jsondata);
33
+
34
+ // Instantiate and draw our chart, passing in some options.
35
+ if(!chart.chart) {
36
+ console.log('Creating new chart for ' + chart.url);
37
+ chart.chart = new google.visualization.AreaChart(document.getElementById(chart.div));
38
+ }
39
+
40
+ var width = chart.width;
41
+ var height = chart.height;
42
+
43
+ var hAxisTitle = null;
44
+ var vAxisTitle = null;
45
+ if(height >= 250) hAxisTitle = "Time of Day";
46
+ if(width >= 450) vAxisTitle = chart.vtitle;
47
+
48
+ var title = chart.title;
49
60
- var options = {
61
- width: width,
62
- height: height,
63
- title: title,
64
- isStacked: isStacked,
65
- hAxis: {title: hAxisTitle},
66
- vAxis: {title: vAxisTitle, minValue: 10},
67
- focusTarget: 'category',
68
- lineWidth: (isStacked)?1:2,
69
- areaOpacity: (isStacked)?1.0:0.3,
70
- // animation: {duration: 1000, easing: 'inAndOut'},
71
- };
72
-
73
- if(charts[index].chart) charts[index].chart.draw(charts[index].datatable, options);
74
- else console.log('Cannot create chart for ' + charts[index].url);
50
+ var isStacked = false;
51
+ if(chart.name.substring(0, 3) == "tc.") {
52
+ isStacked = true;
53
+ title += " [stacked]";
54
}
55
+
56
+ var options = {
57
+ width: width,
58
+ height: height,
59
+ title: title,
60
+ isStacked: isStacked,
61
+ hAxis: {title: hAxisTitle},
62
+ vAxis: {title: vAxisTitle, minValue: 10},
63
+ focusTarget: 'category',
64
+ lineWidth: (isStacked)?1:2,
65
+ areaOpacity: (isStacked)?1.0:0.3,
66
+ // animation: {duration: 1000, easing: 'inAndOut'},
67
+ };
68
+
69
+ if(chart.chart) chart.chart.draw(chart.datatable, options);
70
+ else console.log('Cannot create chart for ' + chart.url);
71
+}
72
+
73
+function cloneJSON(obj) {
74
+ // basic type deep copy
75
+ if (obj === null || obj === undefined || typeof obj !== 'object') {
76
+ return obj
77
+ }
78
+ // array deep copy
79
+ if (obj instanceof Array) {
80
+ var cloneA = [];
81
+ for (var i = 0; i < obj.length; ++i) {
82
+ cloneA[i] = cloneJSON(obj[i]);
83
+ }
84
+ return cloneA;
85
+ }
86
+ // object deep copy
87
+ var cloneO = {};
88
+ for (var i in obj) {
89
+ cloneO[i] = cloneJSON(obj[i]);
90
+ }
91
+ return cloneO;
92
+}
93
+
94
+function loadCharts() {
95
+ var mycharts = new Array();
96
+
97
+ $.getJSON('/all.json', function(json) {
98
+ $.each(json.charts, function(i, value) {
99
+ mycharts[i] = $.extend(true, {}, value);
100
+
101
+ mycharts[i].div = mycharts[i].name.replace(/\./g,"_");
102
+ mycharts[i].div = mycharts[i].div.replace(/\-/g,"_");
103
+ mycharts[i].div = mycharts[i].div + "_div";
104
+
105
+ mycharts[i].width = 0;
106
+ mycharts[i].height = 0;
107
+ mycharts[i].refreshCount = 0;
108
+
109
+ mycharts[i].chart = null;
110
+ mycharts[i].jsondata = null;
111
+ mycharts[i].datatable = null;
112
+ });
113
+ });
114
+
115
+ console.log("all: " + mycharts.length)
116
+ console.log(mycharts);
117
+ return mycharts;
118
+};
119
+
120
+var charts = new Array();
121
+function addChart(name, div, width, height, jsonurl, title, vtitle) {
122
+ var i = charts.length;
123
77
- function addChart(name, div, width, height, jsonurl, title, vtitle) {
78
- var i = charts.length;
79
-
80
- console.log('Creating new objects for chart ' + name);
81
- charts[i] = [];
82
- charts[i].chart = null;
83
- charts[i].jsondata = null;
84
- charts[i].datatable = null;
85
- charts[i].name = name;
86
- charts[i].div = div;
87
- charts[i].url = jsonurl;
88
- charts[i].title = title;
89
- charts[i].vtitle = vtitle;
90
- charts[i].width = width;
91
- charts[i].height = height;
92
- charts[i].refreshCount = 0;
124
+ console.log('Creating new objects for chart ' + name);
125
+ charts[i] = [];
126
+ charts[i].chart = null;
127
+ charts[i].jsondata = null;
128
+ charts[i].datatable = null;
129
+ charts[i].name = name;
130
+ charts[i].div = div;
131
+ charts[i].url = jsonurl;
132
+ charts[i].title = title;
133
+ charts[i].vtitle = vtitle;
134
+ charts[i].width = width;
135
+ charts[i].height = height;
136
+ charts[i].refreshCount = 0;
137
+}
138
+
139
+var charts_last_drawn = 999999999;
140
+function refreshCharts(howmany) {
141
+
142
+ if(charts.length == 0) return;
143
+
144
+ var h = howmany;
145
+ if(h == 0) h = charts.length;
146
+ if(h > charts.length) h = charts.length;
147
+ //console.log('Will run for ' + h + ' charts');
148
+
149
+ var width = Math.round(Math.sqrt(charts.length));
150
+ var height = Math.round(Math.sqrt(charts.length));
151
+ while((width * height) < charts.length) {
152
+ if((height + 1) <= width) height++;
153
+ else width++;
154
}
155
+ // console.log('all: ' + charts.length + ', optimal: width = ' + width + ', height = ' + height);
156
+
157
+ while(width > 1 && width >= height) {
158
+ width--;
159
+ height++;
160
+ }
161
+ if(width * height < charts.length) height++;
162
+ // console.log('final: width = ' + width + ', height = ' + height);
163
+
164
+ ww = (window.innerWidth < document.documentElement.clientWidth)?window.innerWidth:document.documentElement.clientWidth;
165
+ wh = (window.innerHeight < document.documentElement.clientHeight)?window.innerHeight:document.documentElement.clientHeight;
166
+
167
+ if(width == 0) width = (ww - 40) / 2;
168
+ if(width <= 10) width = (ww - 40) / width;
169
+ if(width < 200) width = 200;
170
95
- var charts_last_drawn = 999999999;
96
- function refreshCharts(howmany) {
97
-
98
- if(charts.length == 0) return;
99
-
100
- var h = howmany;
101
- if(h == 0) h = charts.length;
102
- if(h > charts.length) h = charts.length;
103
- //console.log('Will run for ' + h + ' charts');
171
+ if(height == 0) height = (wh - 20) / 2;
172
+ if(height <= 10) height = (wh - 20) / height;
173
+ if(height < 100) height = 100;
174
+
175
+ // console.log('width = ' + width + ', height = ' + height);
176
+
177
+ var i;
178
+ for(i = 0; i < h; i++) {
179
+ var zeroDimensions = 0;
180
+
181
+ charts_last_drawn++;
182
+ if(charts_last_drawn >= charts.length) charts_last_drawn = 0;
183
105
- var width = Math.round(Math.sqrt(charts.length));
106
- var height = Math.round(Math.sqrt(charts.length));
107
- while((width * height) < charts.length) {
108
- if((height + 1) <= width) height++;
109
- else width++;
184
+ if(charts[charts_last_drawn].width == 0 && charts[charts_last_drawn].height == 0) {
185
+ charts[charts_last_drawn].width = width;
186
+ charts[charts_last_drawn].height = height;
187
+ zeroDimensions = 1;
188
}
111
- // console.log('all: ' + charts.length + ', optimal: width = ' + width + ', height = ' + height);
189
113
- while(width > 1 && width >= height) {
114
- width--;
115
- height++;
116
- }
117
- if(width * height < charts.length) height++;
118
- // console.log('final: width = ' + width + ', height = ' + height);
190
+ try {
191
120
- ww = (window.innerWidth < document.documentElement.clientWidth)?window.innerWidth:document.documentElement.clientWidth;
121
- wh = (window.innerHeight < document.documentElement.clientHeight)?window.innerHeight:document.documentElement.clientHeight;
192
+ console.log('Refreshing chart ' + charts[charts_last_drawn].name);
193
+ refreshChart(charts[charts_last_drawn]);
194
+ }
195
+ catch(err) {
196
+ console.log('Cannot refresh chart for ' + charts[charts_last_drawn].url);
197
+ }
198
123
- if(width == 0) width = (ww - 40) / 2;
124
- if(width <= 10) width = (ww - 40) / width;
125
- if(width < 200) width = 200;
126
-
127
- if(height == 0) height = (wh - 20) / 2;
128
- if(height <= 10) height = (wh - 20) / height;
129
- if(height < 100) height = 100;
130
-
131
- // console.log('width = ' + width + ', height = ' + height);
132
-
133
- var i;
134
- for(i = 0; i < h; i++) {
135
- var zeroDimensions = 0;
136
-
137
- charts_last_drawn++;
138
- if(charts_last_drawn >= charts.length) charts_last_drawn = 0;
139
-
140
- if(charts[charts_last_drawn].width == 0 && charts[charts_last_drawn].height == 0) {
141
- charts[charts_last_drawn].width = width;
142
- charts[charts_last_drawn].height = height;
143
- zeroDimensions = 1;
144
- }
145
-
146
- try {
147
-
148
- console.log('Refreshing chart ' + charts[charts_last_drawn].name);
149
- refreshChart(charts_last_drawn);
150
- }
151
- catch(err) {
152
- console.log('Cannot refresh chart for ' + charts[charts_last_drawn].url);
153
- }
154
-
155
- if(zeroDimensions == 1) {
156
- charts[charts_last_drawn].width = 0;
157
- charts[charts_last_drawn].height = 0;
158
- }
199
+ if(zeroDimensions == 1) {
200
+ charts[charts_last_drawn].width = 0;
201
+ charts[charts_last_drawn].height = 0;
202
}
160
- return 0;
203
}
204
+ return 0;
205
+}