minor code cleanups; updated the dashboard to fix inline charts
Costa Tsaousis (ktsaou) committed
Dec 1, 2015 at 01:36 UTC
f39384e8f93cd395b5c48c406f4ca53753abf7e8
10 files changed
+423
-269
src/daemon.c
+2
-21
@@ -25,19 +25,6 @@
25
#include "main.h"
26
#include "daemon.h"
27
28
-#define BACKTRACE_SIZE 4096
29
-
30
-void print_backtrace()
31
-{
32
- void *buffer[BACKTRACE_SIZE];
33
- int nptrs;
34
-
35
- nptrs = backtrace(buffer, BACKTRACE_SIZE);
36
- fprintf(stderr, "\n\nSTACK TRACE (%d addresses):\n\n", nptrs);
37
- backtrace_symbols_fd(buffer, nptrs, STDERR_FILENO);
38
- fprintf(stderr, "\n\n");
39
-}
40
-
28
void sig_handler(int signo)
29
{
30
switch(signo) {
@@ -51,7 +38,6 @@ void sig_handler(int signo)
38
case SIGXCPU:
39
case SIGXFSZ:
40
info("Death signaled exit (signal %d). Errno: %d (%s)", signo, errno, strerror(errno));
54
- print_backtrace();
41
signal(signo, SIG_DFL);
42
break;
43
@@ -63,18 +49,13 @@ void sig_handler(int signo)
49
case SIGUSR1:
50
case SIGUSR2:
51
info("Signaled exit (signal %d). Errno: %d (%s)", signo, errno, strerror(errno));
66
- print_backtrace();
52
signal(SIGPIPE, SIG_IGN);
53
signal(SIGTERM, SIG_IGN);
54
signal(SIGQUIT, SIG_IGN);
55
signal(SIGHUP, SIG_IGN);
56
signal(SIGINT, SIG_IGN);
57
signal(SIGCHLD, SIG_IGN);
73
- kill_childs();
74
- rrdset_free_all();
75
- //unlink("/var/run/netdata.pid");
76
- info("NetData exiting. Bye bye...");
77
- exit(1);
58
+ netdata_cleanup_and_exit(1);
59
break;
60
61
case SIGPIPE:
@@ -263,7 +244,7 @@ int become_daemon(int dont_fork, int close_all_files, const char *user, const ch
244
// close all files
245
if(close_all_files) {
246
int i;
266
- for(i = sysconf(_SC_OPEN_MAX); i > 0; i--)
247
+ for(i = sysconf(_SC_OPEN_MAX) - 1; i > 0; i--)
248
if(
249
((access_fd && i != *access_fd) || !access_fd)
250
&& i != dev_null
src/daemon.h
+2
@@ -9,4 +9,6 @@ extern int become_user(const char *username);
9
10
extern int become_daemon(int dont_fork, int close_all_files, const char *user, const char *input, const char *output, const char *error, const char *access, int *access_fd, FILE **access_fp);
11
12
+extern void netdata_cleanup_and_exit(int i);
13
+
14
#endif /* NETDATA_DAEMON_H */
src/main.c
+22
-1
@@ -35,6 +35,17 @@
35
36
#include "main.h"
37
38
+int netdata_exit = 0;
39
+
40
+void netdata_cleanup_and_exit(int ret)
41
+{
42
+ kill_childs();
43
+ rrdset_free_all();
44
+ //unlink("/var/run/netdata.pid");
45
+ info("NetData exiting. Bye bye...");
46
+ exit(ret);
47
+}
48
+
49
struct netdata_static_thread {
50
char *name;
51
@@ -445,7 +456,17 @@ int main(int argc, char **argv)
456
}
457
458
// for future use - the main thread
448
- while(1) sleep(60);
459
+ while(1) {
460
+ if(netdata_exit != 0) {
461
+ netdata_exit++;
462
+
463
+ if(netdata_exit > 5) {
464
+ netdata_cleanup_and_exit(0);
465
+ exit(0);
466
+ }
467
+ }
468
+ sleep(2);
469
+ }
470
471
exit(0);
472
}
src/main.h
+3
@@ -1,7 +1,10 @@
1
#ifndef NETDATA_MAIN_H
2
#define NETDATA_MAIN_H 1
3
4
+extern int netdata_exit;
5
+
6
extern void kill_childs(void);
7
extern int killpid(pid_t pid, int signal);
8
+extern void netdata_cleanup_and_exit(int ret);
9
10
#endif /* NETDATA_MAIN_H */
src/popen.c
+1
-1
@@ -78,7 +78,7 @@ FILE *mypopen(const char *command, pid_t *pidptr)
78
79
// close all files
80
int i;
81
- for(i = sysconf(_SC_OPEN_MAX); i > 0; i--)
81
+ for(i = sysconf(_SC_OPEN_MAX) - 1; i > 0; i--)
82
if(i != STDIN_FILENO && i != STDERR_FILENO && i != pipefd[PIPE_WRITE]) close(i);
83
84
// move the pipe to stdout
src/web_client.c
+12
-1
@@ -34,6 +34,8 @@
34
int web_client_timeout = DEFAULT_DISCONNECT_IDLE_WEB_CLIENTS_AFTER_SECONDS;
35
int web_enable_gzip = 1;
36
37
+extern int netdata_exit;
38
+
39
struct web_client *web_clients = NULL;
40
unsigned long long web_clients_count = 0;
41
@@ -975,7 +977,7 @@ void web_client_process(struct web_client *w) {
977
//if(strstr(w->response.data->buffer, "X-DataSource-Auth"))
978
// datasource_type = DATASOURCE_GOOGLE_JSON;
979
978
- char *buf = w->response.data->buffer;
980
+ char *buf = (char *)buffer_tostring(w->response.data);
981
char *tok = strsep(&buf, " \r\n");
982
char *url = NULL;
983
char *pointer_to_free = NULL; // keep url_decode() allocated buffer
@@ -1007,6 +1009,15 @@ void web_client_process(struct web_client *w) {
1009
datasource_type = DATASOURCE_JSON;
1010
code = web_client_api_request(w, url);
1011
}
1012
+#ifdef WEB_EXIT
1013
+ else if(strcmp(tok, "exit") == 0) {
1014
+ netdata_exit = 1;
1015
+ code = 200;
1016
+ w->response.data->contenttype = CT_TEXT_PLAIN;
1017
+ buffer_flush(w->response.data);
1018
+ buffer_strcat(w->response.data, "will do");
1019
+ }
1020
+#endif
1021
else if(strcmp(tok, WEB_PATH_DATA) == 0) { // "data"
1022
// the client is requesting rrd data
1023
datasource_type = DATASOURCE_JSON;
web/Makefile.am
+1
@@ -25,4 +25,5 @@ dist_weblib_DATA = \
25
lib/jquery.sparkline.min.js \
26
lib/morris.min.js \
27
lib/raphael-min.js \
28
+ lib/visible.js \
29
$(NULL)
web/dashboard.html
+54
-57
@@ -19,7 +19,7 @@ This is a template for building custom dashboards. To build a dashboard you just
19
data-width="600"
20
data-height="200"
21
data-after="-600"
22
- </div>
22
+ ></div>
23
</body>
24
<script type="text/javascript" src="http://netdata.server:19999/dashboard.js"></script>
25
</html>
@@ -47,15 +47,15 @@ This is a template for building custom dashboards. To build a dashboard you just
47
System CPU - Stacked Area Chart
48
</th>
49
</tr>
50
- <tr><td colspan="3" align="center"> </td></tr>
51
- <tr><th colspan="3" align="center"><hr>Peity Charts</th></tr>
52
- <tr><td colspan="3" align="center">
50
+ <tr><td colspan="3"> </td></tr>
51
+ <tr><th colspan="3"><hr>Peity Charts</th></tr>
52
+ <tr><td colspan="3">
53
Peity charts do not support 'NULL' values, so the charts cannot indicate that values are missing.
54
Peity charts cannot have multiple dimensions on the charts - so netdata will use 'min2max' to show
55
the total of all dimensions.
56
</td></tr>
57
<tr>
58
- <td width="600" align="center">
58
+ <td width="600">
59
<div data-netdata="system.processes"
60
data-chart-library="peity"
61
data-width="600"
@@ -64,7 +64,7 @@ This is a template for building custom dashboards. To build a dashboard you just
64
data-dt-element-name="time11"
65
</div>
66
</td>
67
- <td width="600" align="center">
67
+ <td width="600">
68
<div data-netdata="system.ipv4"
69
data-chart-library="peity"
70
data-width="600"
@@ -73,7 +73,7 @@ This is a template for building custom dashboards. To build a dashboard you just
73
data-dt-element-name="time12"
74
</div>
75
</td>
76
- <td width="600" align="center">
76
+ <td width="600">
77
<div data-netdata="system.cpu"
78
data-chart-library="peity"
79
data-width="600"
@@ -88,67 +88,64 @@ This is a template for building custom dashboards. To build a dashboard you just
88
<td>rendered in <span id="time12">X</span> ms</td>
89
<td>rendered in <span id="time13">X</span> ms</td>
90
</tr>
91
- <tr><td colspan="3" align="center"> </td></tr>
92
- <tr><th colspan="3" align="center"><hr>Sparkline Charts</th></tr>
93
- <tr><td colspan="3" align="center">
91
+ <tr><td colspan="3"> </td></tr>
92
+ <tr><th colspan="3"><hr>Sparkline Charts</th></tr>
93
+ <tr><td colspan="3">
94
Sparkline charts support 'NULL' values, so the charts can indicate that values are missing.
95
Sparkline charts stretch the values to show the variations between values in more detail.
96
They also have mouse-hover support.
97
<br/>
98
Sparklines are fantastic. You can inline charts in text. For example this
99
- <div style="display: inline; position: relative;"
100
- data-netdata="system.cpu"
99
+ <div data-netdata="system.cpu"
100
data-chart-library="sparkline"
101
data-width="60"
103
- data-height="15"
102
+ data-height="20"
103
data-after="-30"
105
- </div> is my current cpu usage,
104
+ ></div> is my current cpu usage,
105
<br/>
106
while this
108
- <div style="display: inline; position: relative;"
109
- data-netdata="netdata.net"
107
+ <div data-netdata="netdata.net"
108
data-dimensions="out"
109
data-chart-library="sparkline"
110
data-width="60"
113
- data-height="15"
111
+ data-height="20"
112
data-after="-30"
115
- </div> is the bandwidth my netdata server is currently transmitting and this
113
+ ></div> is the bandwidth my netdata server is currently transmitting and this
114
117
- <div style="display: inline; position: relative;"
118
- data-netdata="netdata.requests"
115
+ <div data-netdata="netdata.requests"
116
data-chart-library="sparkline"
120
- data-width="60"
121
- data-height="15"
122
- data-after="-30"
123
- </div> is the requests/sec it serves.
117
+ data-width="360"
118
+ data-height="20"
119
+ data-after="-180"
120
+ ></div> is the requests/sec it serves.
121
</td></tr>
122
<tr>
126
- <td width="600" align="center">
123
+ <td width="600">
124
<div data-netdata="system.processes"
125
data-chart-library="sparkline"
126
data-width="600"
127
data-height="30"
128
data-after="-600"
129
data-dt-element-name="time21"
133
- </div>
130
+ ></div>
131
</td>
135
- <td width="600" align="center">
132
+ <td width="600">
133
<div data-netdata="system.ipv4"
134
data-chart-library="sparkline"
135
data-width="600"
136
data-height="30"
137
data-after="-600"
138
data-dt-element-name="time22"
142
- </div>
139
+ ></div>
140
</td>
144
- <td width="600" align="center">
141
+ <td width="600">
142
<div data-netdata="system.cpu"
143
data-chart-library="sparkline"
144
data-width="600"
145
data-height="30"
146
data-after="-600"
147
data-dt-element-name="time23"
151
- </div>
148
+ ></div>
149
</td>
150
</tr>
151
<tr>
@@ -156,40 +153,40 @@ This is a template for building custom dashboards. To build a dashboard you just
153
<td>rendered in <span id="time22">X</span> ms</td>
154
<td>rendered in <span id="time23">X</span> ms</td>
155
</tr>
159
- <tr><td colspan="3" align="center"> </td></tr>
160
- <tr><th colspan="3" align="center"><hr>Dygraph Charts</th></tr>
161
- <tr><td colspan="3" align="center">
156
+ <tr><td colspan="3"> </td></tr>
157
+ <tr><th colspan="3"><hr>Dygraph Charts</th></tr>
158
+ <tr><td colspan="3">
159
The fastest charting engine that can chart complete charts (not just sparklines).
160
The charts are zoomable (drag their contents to zoom-in, double click to zoom-out).
161
For the moment zooming is just on the presentation layer (the data do not become more detailed when you zoom).
162
</td></tr>
163
<tr>
167
- <td width="600" align="center">
164
+ <td width="600">
165
<div data-netdata="system.processes"
166
data-chart-library="dygraph"
167
data-width="600"
168
data-height="200"
169
data-after="-600"
170
data-dt-element-name="time31"
174
- </div>
171
+ ></div>
172
</td>
176
- <td width="600" align="center">
173
+ <td width="600">
174
<div data-netdata="system.ipv4"
175
data-chart-library="dygraph"
176
data-width="600"
177
data-height="200"
178
data-after="-600"
179
data-dt-element-name="time32"
183
- </div>
180
+ ></div>
181
</td>
185
- <td width="600" align="center">
182
+ <td width="600">
183
<div data-netdata="system.cpu"
184
data-chart-library="dygraph"
185
data-width="600"
186
data-height="200"
187
data-after="-600"
188
data-dt-element-name="time33"
192
- </div>
189
+ ></div>
190
</td>
191
</tr>
192
<tr>
@@ -197,39 +194,39 @@ This is a template for building custom dashboards. To build a dashboard you just
194
<td>rendered in <span id="time32">X</span> ms</td>
195
<td>rendered in <span id="time33">X</span> ms</td>
196
</tr>
200
- <tr><td colspan="3" align="center"> </td></tr>
201
- <tr><th colspan="3" align="center"><hr>Google Charts</th></tr>
202
- <tr><td colspan="3" align="center">
197
+ <tr><td colspan="3"> </td></tr>
198
+ <tr><th colspan="3"><hr>Google Charts</th></tr>
199
+ <tr><td colspan="3">
200
NetData was originaly developed with Google Charts.
201
NetData is a complete Google Visualization API provider.
202
</td></tr>
203
<tr>
207
- <td width="600" align="center">
204
+ <td width="600">
205
<div data-netdata="system.processes"
206
data-chart-library="google"
207
data-width="600"
208
data-height="200"
209
data-after="-600"
210
data-dt-element-name="time51"
214
- </div>
211
+ ></div>
212
</td>
216
- <td width="600" align="center">
213
+ <td width="600">
214
<div data-netdata="system.ipv4"
215
data-chart-library="google"
216
data-width="600"
217
data-height="200"
218
data-after="-600"
219
data-dt-element-name="time52"
223
- </div>
220
+ ></div>
221
</td>
225
- <td width="600" align="center">
222
+ <td width="600">
223
<div data-netdata="system.cpu"
224
data-chart-library="google"
225
data-width="600"
226
data-height="200"
227
data-after="-600"
228
data-dt-element-name="time53"
232
- </div>
229
+ ></div>
230
</td>
231
</tr>
232
<tr>
@@ -237,39 +234,39 @@ This is a template for building custom dashboards. To build a dashboard you just
234
<td>rendered in <span id="time52">X</span> ms</td>
235
<td>rendered in <span id="time53">X</span> ms</td>
236
</tr>
240
- <tr><td colspan="3" align="center"> </td></tr>
241
- <tr><th colspan="3" align="center"><hr>Morris Charts</th></tr>
242
- <tr><td colspan="3" align="center">
237
+ <tr><td colspan="3"> </td></tr>
238
+ <tr><th colspan="3"><hr>Morris Charts</th></tr>
239
+ <tr><td colspan="3">
240
Unfortunatelly, Morris Charts are veeeeeeeeeeeeeeeery slow! We force them to lower their detail to get acceptable results.
241
And they have issues with negative numbers in area charts...
242
</td></tr>
243
<tr>
247
- <td width="600" align="center">
244
+ <td width="600">
245
<div data-netdata="system.processes"
246
data-chart-library="morris"
247
data-width="600"
248
data-height="200"
249
data-after="-600"
250
data-dt-element-name="time41"
254
- </div>
251
+ ></div>
252
</td>
256
- <td width="600" align="center">
253
+ <td width="600">
254
<div data-netdata="system.ipv4"
255
data-chart-library="morris"
256
data-width="600"
257
data-height="200"
258
data-after="-600"
259
data-dt-element-name="time42"
263
- </div>
260
+ ></div>
261
</td>
265
- <td width="600" align="center">
262
+ <td width="600">
263
<div data-netdata="system.cpu"
264
data-chart-library="morris"
265
data-width="600"
266
data-height="200"
267
data-after="-600"
268
data-dt-element-name="time43"
272
- </div>
269
+ ></div>
270
</td>
271
</tr>
272
<tr>
web/dashboard.js
+300
-188
@@ -67,9 +67,9 @@
67
NETDATA.morris_js = NETDATA.serverDefault + 'lib/morris.min.js';
68
NETDATA.morris_css = NETDATA.serverDefault + 'css/morris.css';
69
NETDATA.google_js = 'https://www.google.com/jsapi';
70
- NETDATA.colors = [ '#3366CC', '#DC3912', '#FF9900', '#109618', '#990099', '#3B3EAC', '#0099C6', '#DD4477',
71
- '#66AA00', '#B82E2E', '#316395', '#994499', '#22AA99', '#AAAA11', '#6633CC', '#E67300', '#8B0707',
72
- '#329262', '#5574A6', '#3B3EAC' ];
70
+ NETDATA.colors = [ '#3366CC', '#DC3912', '#FF9900', '#109618', '#990099', '#3B3EAC', '#0099C6',
71
+ '#DD4477', '#66AA00', '#B82E2E', '#316395', '#994499', '#22AA99', '#AAAA11',
72
+ '#6633CC', '#E67300', '#8B0707', '#329262', '#5574A6', '#3B3EAC' ];
73
74
// ----------------------------------------------------------------------------------------------------------------
75
// the defaults for all charts
@@ -82,15 +82,23 @@
82
method: 'average', // the grouping method
83
before: 0, // panning
84
after: -600, // panning
85
- point_width: 1, // the detail of the chart
85
+ pixels_per_point: 1, // the detail of the chart
86
}
87
88
- NETDATA.all_url = 'all2.js';
89
- NETDATA.idle_between_charts = 50;
90
- NETDATA.idle_between_loops = 100;
91
- NETDATA.debug = 1;
88
+ NETDATA.options = {
89
+ targets: null,
90
+ updated_dom: 1,
91
+ debug: 1,
92
93
- if(NETDATA.debug) console.log('welcome to NETDATA');
93
+ current: {
94
+ pixels_per_point: 1,
95
+ idle_between_charts: 50,
96
+ idle_between_loops: 100,
97
+ debug: 1
98
+ }
99
+ }
100
+
101
+ if(NETDATA.options.debug) console.log('welcome to NETDATA');
102
103
104
// ----------------------------------------------------------------------------------------------------------------
@@ -125,11 +133,19 @@
133
NETDATA.errorLast.datetime = 0;
134
}
135
128
- NETDATA.messageInABox = function(div, width, height, message) {
129
- div.innerHTML = '<table border="0"><tr><td width="' + width + '" height="' + height
130
- + '" valign="middle" align="center">'
136
+ NETDATA.chartContainer = function(element, width, height) {
137
+ self = $(element);
138
+ self.css('width', width)
139
+ .css('height', height)
140
+ .css('display', 'inline-block')
141
+ .css('overflow', 'hidden');
142
+ }
143
+
144
+ NETDATA.messageInABox = function(element, width, height, message) {
145
+ NETDATA.chartContainer(element, width, height);
146
+ element.innerHTML = '<div style="overflow: hidden; border: 0px; background-color: lightgrey; width: ' + width + '; height: ' + height + ';"><small>'
147
+ message
132
- + '</td></tr></table>';
148
+ + '</small></div>';
149
}
150
151
// ----------------------------------------------------------------------------------------------------------------
@@ -155,58 +171,63 @@
171
callback();
172
}
173
158
- NETDATA.generateDataURL = function(args) {
174
+ NETDATA.generateChartDataURL = function(options) {
175
// build the data URL
160
- var url = args.host + args.url;
176
+ var url = options.host + options.url;
177
url += "&points=";
162
- url += args.points.toString();
178
+ url += options.points.toString();
179
url += "&group=";
164
- url += args.method;
180
+ url += options.method;
181
url += "&after=";
166
- url += args.after || "0";
182
+ url += options.after || "0";
183
url += "&before=";
168
- url += args.before || "0";
169
- url += "&options=" + NETDATA.chartLibraries[args.library].options + '|';
170
- url += (args.non_zero)?"nonzero":"";
171
- url += "&format=" + NETDATA.chartLibraries[args.library].format;
184
+ url += options.before || "0";
185
+ url += "&options=" + NETDATA.chartLibraries[options.library].options + '|';
186
+ url += (options.non_zero)?"nonzero":"";
187
+ url += "&format=" + NETDATA.chartLibraries[options.library].format;
188
173
- if(args.dimensions)
174
- url += "&dimensions=" + args.dimensions;
189
+ if(options.dimensions)
190
+ url += "&dimensions=" + options.dimensions;
191
176
- if(NETDATA.debug) console.log('generateDataURL(' + args + ') = ' + url );
192
+ if(NETDATA.options.debug) console.log('generateChartDataURL(' + options + ') = ' + url );
193
return url;
194
}
195
180
- NETDATA.loadCharts = function(targets, index, callback) {
181
- if(NETDATA.debug) console.log('loadCharts(<targets, ' + index + ')');
196
+ NETDATA.parseDomCharts = function(targets, index, callback) {
197
+ if(NETDATA.options.debug) console.log('parseDomCharts() working on ' + index);
198
199
var target = targets.get(index);
184
-
200
if(target == null) {
186
- console.log('loaded all charts');
187
- callback();
201
+ if(NETDATA.options.debug) console.log('parseDomCharts(): all ' + (index - 1) + ' charts parsed.');
202
+ if(typeof callback == 'function') callback();
203
}
204
else {
205
var self = $(target);
206
+ if(!self.data('prepared')) {
207
+ self.data('prepared', true);
208
192
- if(!self.data('loaded')) {
209
var id = self.data('netdata');
194
-
210
var host = self.data('host') || NETDATA.chartDefaults.host;
211
var width = self.data('width') || NETDATA.chartDefaults.width;
212
var height = self.data('height') || NETDATA.chartDefaults.height;
213
var method = self.data('method') || NETDATA.chartDefaults.method;
214
var after = self.data('after') || NETDATA.chartDefaults.after;
215
var before = self.data('before') || NETDATA.chartDefaults.before;
201
- var host = self.data('host') || NETDATA.chartDefaults.host;
216
var library = self.data('chart-library') || NETDATA.chartDefaults.library;
217
var dimensions = self.data('dimensions') || null;
218
219
+ NETDATA.chartContainer(target, width, height);
220
+ if(NETDATA.options.debug) console.log('parseDomCharts() parsing ' + id + ' of type ' + library);
221
+
222
if(typeof NETDATA.chartLibraries[library] == 'undefined') {
223
+ self.data('created', false)
224
+ .data('updated', 0)
225
+ .data('enabled', false);
226
+
227
NETDATA.error(402, library);
228
NETDATA.messageInABox(target, width, height, 'chart library "' + library + '" is not found');
208
- self.data('enabled', false);
209
- NETDATA.loadCharts(targets, ++index, callback);
229
+
230
+ NETDATA.parseDomCharts(targets, ++index, callback);
231
}
232
else {
233
var url = host + "/api/v1/chart?chart=" + id;
@@ -216,11 +237,10 @@
237
crossDomain: true
238
})
239
.done(function(chart) {
240
+ var pixels_per_point = self.data('point-width') || NETDATA.chartLibraries[library].pixels_per_point;
241
+ var points = self.data('points') || Math.round(width / pixels_per_point);
242
220
- var point_width = self.data('point-width') || NETDATA.chartLibraries[library].pixels;
221
- var points = self.data('points') || Math.round(width / point_width);
222
-
223
- var url = NETDATA.generateDataURL({
243
+ var url = NETDATA.generateChartDataURL({
244
host: host,
245
url: chart.data_url,
246
dimensions: dimensions,
@@ -235,74 +255,77 @@
255
// done processing of this DIV
256
// store the processing result, in
257
// 'data' sections in the DIV
238
- self
239
- .data('chart', chart)
258
+ self.data('chart', chart)
259
.data('chart-url', url)
241
- .data('last-updated', 0)
260
.data('update-every', chart.update_every * 1000)
243
- .data('enabled', true);
261
+ .data('created', false)
262
+ .data('updated', 0)
263
+ .data('enabled', true)
264
+ .data('host', host)
265
+ .data('width', width)
266
+ .data('height', height)
267
+ .data('method', method)
268
+ .data('after', after)
269
+ .data('before', before)
270
+ .data('chart-library', library)
271
+ .data('dimensions', dimensions)
272
+ ;
273
+
274
+ NETDATA.messageInABox(target, width, height, 'chart "' + id + '" is loading...');
275
})
276
.fail(function() {
277
+ self.data('created', false)
278
+ .data('enabled', false);
279
+
280
NETDATA.error(404, url);
281
NETDATA.messageInABox(target, width, height, 'chart "' + id + '" not found on url "' + url + '"');
248
- self.data('enabled', false);
282
})
283
.always(function() {
251
- NETDATA.loadCharts(targets, ++index, callback);
284
+ self.data('updated', 0);
285
+ NETDATA.parseDomCharts(targets, ++index, callback);
286
});
287
}
288
}
289
}
290
}
291
258
- function netdataParsePageCharts() {
259
- if(NETDATA.debug) console.log('processing web page defined charts');
292
+ NETDATA.domUpdated = function(callback) {
293
+ NETDATA.options.updated_dom = 0;
294
261
- // targets
262
- // a list of all DIVs containing netdata charts
263
-
264
- var targets = $('div[data-netdata]')
265
- .bind('create', function(event, data) {
266
- var self = $(this);
267
- var lib = self.data('chart-library') || 'dygraph';
268
- var method = lib + 'ChartCreate';
295
+ NETDATA.options.targets = $('div[data-netdata]') // .filter(':visible')
296
+ .bind('create', function(event, data) {
297
+ var self = $(this);
298
+ try {
299
+ NETDATA.chartLibraries[self.data('chart-library')].create(this, data);
300
+ }
301
+ catch(err) {
302
+ NETDATA.messageInABox(this, self.data('width'), self.data('height'), 'chart "' + id + '" failed to be created as ' + self.data('chart-library'));
303
+ }
304
+ })
305
+ .bind('update', function(event, data) {
306
+ var self = $(this);
307
+ try {
308
+ NETDATA.chartLibraries[self.data('chart-library')].update(this, data);
309
+ }
310
+ catch(err) {
311
+ NETDATA.messageInABox(this, self.data('width'), self.data('height'), 'chart "' + id + '" failed to be updated as ' + self.data('chart-library'));
312
+ }
313
+ });
314
270
- console.log('Calling ' + method + '()');
271
- NETDATA[method].apply(this, arguments);
272
- })
273
- .bind('update', function() {
274
- var self = $(this);
275
- var lib = self.data('chart-library') || 'dygraph';
276
- var method = lib + 'ChartUpdate';
315
+ if(NETDATA.options.debug)
316
+ console.log('DOM updated - there are ' + NETDATA.options.targets.length + ' charts on page.');
317
278
- console.log('Calling ' + method + '()');
279
- NETDATA[method].apply(this, arguments);
280
- });
318
+ NETDATA.parseDomCharts(NETDATA.options.targets, 0, callback);
319
+ }
320
282
- NETDATA.loadCharts(targets, 0, function() {
321
+ NETDATA.init = function() {
322
+ NETDATA.domUpdated(function() {
323
// done processing all netdata DIVs in this page
324
// call the refresh handler
285
- netdataRefreshTargets(targets, 0);
286
- });
287
- }
325
289
- // ----------------------------------------------------------------------------------------------------------------
290
- // Charts Libraries Registration
291
-
292
- NETDATA.chartLibraries = {};
293
-
294
- NETDATA.registerChartLibrary = function(library, url, format, options, min_pixels_per_point) {
295
- console.log("registering chart library: " + library);
296
-
297
- NETDATA.chartLibraries[library] = {
298
- initialized: new Date().getTime(),
299
- url: url,
300
- format: format,
301
- options: options,
302
- pixels: min_pixels_per_point
303
- };
304
-
305
- console.log(NETDATA.chartLibraries);
326
+ // FIXME
327
+ NETDATA.chartRefresher(0);
328
+ });
329
}
330
331
// ----------------------------------------------------------------------------------------------------------------
@@ -317,50 +340,48 @@
340
//var c = new chart();
341
//c.color();
342
320
- function netdataDownloadChartData(callback) {
321
- var self = $(this);
322
- var last = self.data('last-updated') || 0;
343
+ NETDATA.chartValuesDownloader = function(element, callback) {
344
+ var self = $(element);
345
+ var last = self.data('updated') || 0;
346
var every = self.data('update-every') || 1;
347
348
// check if this chart has to be refreshed now
349
var now = new Date().getTime();
350
if(last + every > now) {
328
- if(typeof callback == 'function')
329
- callback();
351
+ console.log(self.data('netdata') + ' too soon - skipping.');
352
+ if(typeof callback == 'function') callback();
353
+ }
354
+ else if(!self.visible(true)) {
355
+ console.log(self.data('netdata') + ' is NOT visible.');
356
+ if(typeof callback == 'function') callback();
357
}
358
else {
332
- var url = self.data('chart-url');
333
-
334
- if(NETDATA.debug) console.log('netdataDownloadChartData(): downloading ' + url);
335
-
359
+ console.log(self.data('netdata') + ' is visible, downloading data...');
360
$.ajax( {
337
- url: url,
361
+ url: self.data('chart-url'),
362
crossDomain: true
363
})
364
.then(function(data) {
341
- //var result = $.map(data.rows, function(item) {
342
- // get from the 3rd column the 'v' member
343
- //return item.c[3].v;
344
- //});
345
-
346
- // since we downloaded the data
347
- // update the last-updated time to prevent
348
- // another download too soon
349
- self.data('last-updated', new Date().getTime());
350
-
351
- // render it
352
- var created = self.data('created');
353
- self.trigger((created ? 'update' : 'create'), [data]).data('created', true)
354
- })
355
- .fail(function() {
356
- console.log('failed to download chart data');
357
- })
358
- .always(function() {
359
- var last = self.data('last-updated');
360
- var now = new Date().getTime();
361
- var dt = now - last;
362
- self.data('refresh-dt', dt);
365
+ var started = new Date().getTime();
366
+
367
+ if(self.data('created')) {
368
+ console.log('updating ' + self.data('chart-library') + ' chart ' + self.data('netdata'));
369
+ self.trigger('update', [data]);
370
+ // NETDATA.chartLibraries[self.data('chart-library')].update(element, data);
371
+ }
372
+ else {
373
+ console.log('creating ' + self.data('chart-library') + ' chart ' + self.data('netdata'));
374
+ self.trigger('create', [data]);
375
+ //NETDATA.chartLibraries[self.data('chart-library')].create(element, data);
376
+ self.data('created', true);
377
+ }
378
379
+ var ended = new Date().getTime();
380
+ self.data('updated', ended);
381
+
382
+ var dt = ended - started;
383
+
384
+ self.data('refresh-dt', dt);
385
var element_name = self.data('dt-element-name') || null;
386
if(element_name) {
387
var element = document.getElementById(element_name) || null;
@@ -368,38 +389,46 @@
389
element.innerHTML = dt.toString();
390
}
391
}
371
-
372
- if(typeof callback == 'function')
373
- callback();
392
+ })
393
+ .fail(function() {
394
+ NETDATA.messageInABox(element, width, height, 'chart "' + id + '" not found on url "' + url + '"');
395
+ })
396
+ .always(function() {
397
+ if(typeof callback == 'function') callback();
398
});
399
}
400
};
401
378
- function netdataRefreshTargets(targets, index) {
379
- // if(NETDATA.debug) console.log('netdataRefreshTargets(<targets, ' + index + ')');
380
-
381
- var target = targets.get(index);
382
-
383
- if(target == null) {
384
- console.log('restart');
402
+ NETDATA.chartRefresher = function(index) {
403
+ // if(NETDATA.options.debug) console.log('NETDATA.chartRefresher(<targets, ' + index + ')');
404
386
- // finished, restart
387
- setTimeout(function() {
388
- netdataRefreshTargets(targets, 0);
389
- }, NETDATA.idle_between_loops);
405
+ if(NETDATA.options.updated_dom) {
406
+ NETDATA.domUpdated(function() {
407
+ NETDATA.chartRefresher(0);
408
+ });
409
}
410
else {
392
- var self = $(target);
411
+ var target = NETDATA.options.targets.get(index);
412
+ if(target == null) {
413
+ console.log('waiting to restart main loop...');
414
394
- if(!self.data('enabled')) {
395
- netdataRefreshTargets(targets, ++index);
415
+ // finished, restart
416
+ setTimeout(function() {
417
+ NETDATA.chartRefresher(0);
418
+ }, NETDATA.options.current.idle_between_loops);
419
}
420
else {
398
- setTimeout(function() {
399
- netdataDownloadChartData.call(target, function() {
400
- netdataRefreshTargets(targets, ++index);
401
- });
402
- }, NETDATA.idle_between_charts);
421
+ var self = $(target);
422
+ if(!self.data('enabled')) {
423
+ NETDATA.chartRefresher(++index);
424
+ }
425
+ else {
426
+ setTimeout(function() {
427
+ NETDATA.chartValuesDownloader(target, function() {
428
+ NETDATA.chartRefresher(++index);
429
+ });
430
+ }, NETDATA.options.current.idle_between_charts);
431
+ }
432
}
433
}
434
}
@@ -421,7 +450,7 @@
450
if(typeof netdataStopPeity == 'undefined') {
451
$.getScript(NETDATA.peity_js)
452
.done(function() {
424
- NETDATA.registerChartLibrary('peity', NETDATA.peity_js, 'ssvcomma', 'null2zero|flip|min2max', 2);
453
+ NETDATA.registerChartLibrary('peity', NETDATA.peity_js);
454
})
455
.fail(function() {
456
NETDATA.error(100, NETDATA.peity_js);
@@ -435,14 +464,14 @@
464
callback();
465
};
466
438
- NETDATA.peityChartUpdate = function(event, data) {
439
- var self = $(this);
467
+ NETDATA.peityChartUpdate = function(element, data) {
468
+ var self = $(element);
469
var instance = self.html(data).not('[data-created]');
470
instance.change();
471
}
472
444
- NETDATA.peityChartCreate = function(event, data) {
445
- var self = $(this);
473
+ NETDATA.peityChartCreate = function(element, data) {
474
+ var self = $(element);
475
var width = self.data('width') || NETDATA.chartDefaults.width;
476
var height = self.data('height') || NETDATA.chartDefaults.height;
477
var instance = self.html(data).not('[data-created]');
@@ -461,7 +490,7 @@
490
if(typeof netdataStopSparkline == 'undefined') {
491
$.getScript(NETDATA.sparkline_js)
492
.done(function() {
464
- NETDATA.registerChartLibrary('sparkline', NETDATA.sparkline_js, 'array', 'flip|min2max', 2);
493
+ NETDATA.registerChartLibrary('sparkline', NETDATA.sparkline_js);
494
})
495
.fail(function() {
496
NETDATA.error(100, NETDATA.sparkline_js);
@@ -475,14 +504,14 @@
504
callback();
505
};
506
478
- NETDATA.sparklineChartUpdate = function(event, data) {
479
- var self = $(this);
507
+ NETDATA.sparklineChartUpdate = function(element, data) {
508
+ var self = $(element);
509
var options = self.data('sparkline-options');
510
self.sparkline(data, options);
511
}
512
484
- NETDATA.sparklineChartCreate = function(event, data) {
485
- var self = $(this);
513
+ NETDATA.sparklineChartCreate = function(element, data) {
514
+ var self = $(element);
515
var chart = self.data('chart');
516
var width = self.data('width') || NETDATA.chartDefaults.width;
517
var height = self.data('height') || NETDATA.chartDefaults.height;
@@ -585,7 +614,7 @@
614
};
615
616
var uuid = NETDATA.guid();
588
- this.innerHTML = '<div style="display: inline-block; position: relative;" id="' + uuid + '"></div>';
617
+ element.innerHTML = '<div style="display: inline-block; position: relative;" id="' + uuid + '"></div>';
618
var div = document.getElementById(uuid);
619
620
self.sparkline(data, options);
@@ -623,7 +652,7 @@
652
if(typeof netdataStopDygraph == 'undefined') {
653
$.getScript(NETDATA.dygraph_js)
654
.done(function() {
626
- NETDATA.registerChartLibrary('dygraph', NETDATA.dygraph_js, 'json', 'ms|flip', 2);
655
+ NETDATA.registerChartLibrary('dygraph', NETDATA.dygraph_js);
656
})
657
.fail(function() {
658
NETDATA.error(100, NETDATA.dygraph_js);
@@ -636,8 +665,8 @@
665
callback();
666
};
667
639
- NETDATA.dygraphChartUpdate = function(event, data) {
640
- var self = $(this);
668
+ NETDATA.dygraphChartUpdate = function(element, data) {
669
+ var self = $(element);
670
var dygraph = self.data('dygraph-instance');
671
672
if(typeof data.update_every != 'undefined')
@@ -651,8 +680,8 @@
680
console.log('not updating dygraphs');
681
};
682
654
- NETDATA.dygraphChartCreate = function(event, data) {
655
- var self = $(this);
683
+ NETDATA.dygraphChartCreate = function(element, data) {
684
+ var self = $(element);
685
var width = self.data('width') || NETDATA.chartDefaults.width;
686
var height = self.data('height') || NETDATA.chartDefaults.height;
687
var chart = self.data('chart');
@@ -803,7 +832,7 @@
832
833
$.getScript(NETDATA.morris_js)
834
.done(function() {
806
- NETDATA.registerChartLibrary('morris', NETDATA.morris_js, 'json', 'objectrows|ms', 10);
835
+ NETDATA.registerChartLibrary('morris', NETDATA.morris_js);
836
})
837
.fail(function() {
838
NETDATA.error(100, NETDATA.morris_js);
@@ -817,8 +846,8 @@
846
callback();
847
};
848
820
- NETDATA.morrisChartUpdate = function(event, data) {
821
- var self = $(this);
849
+ NETDATA.morrisChartUpdate = function(element, data) {
850
+ var self = $(element);
851
var width = self.data('width') || NETDATA.chartDefaults.width;
852
var height = self.data('height') || NETDATA.chartDefaults.height;
853
var morris = self.data('morris-instance');
@@ -834,8 +863,8 @@
863
console.log('not updating morris');
864
};
865
837
- NETDATA.morrisChartCreate = function(event, data) {
838
- var self = $(this);
866
+ NETDATA.morrisChartCreate = function(element, data) {
867
+ var self = $(element);
868
var width = self.data('width') || NETDATA.chartDefaults.width;
869
var height = self.data('height') || NETDATA.chartDefaults.height;
870
var chart = self.data('chart');
@@ -884,7 +913,7 @@
913
if(typeof netdataStopRaphael == 'undefined') {
914
$.getScript(NETDATA.raphael_js)
915
.done(function() {
887
- NETDATA.registerChartLibrary('raphael', NETDATA.raphael_js, 'json', 'flip|min2max', 1);
916
+ NETDATA.registerChartLibrary('raphael', NETDATA.raphael_js);
917
})
918
.fail(function() {
919
NETDATA.error(100, NETDATA.raphael_js);
@@ -898,8 +927,8 @@
927
callback();
928
};
929
901
- NETDATA.raphaelChartUpdate = function(event, data) {
902
- var self = $(this);
930
+ NETDATA.raphaelChartUpdate = function(element, data) {
931
+ var self = $(element);
932
var width = self.data('width') || NETDATA.chartDefaults.width;
933
var height = self.data('height') || NETDATA.chartDefaults.height;
934
@@ -909,8 +938,8 @@
938
})
939
};
940
912
- NETDATA.raphaelChartCreate = function(event, data) {
913
- var self = $(this);
941
+ NETDATA.raphaelChartCreate = function(element, data) {
942
+ var self = $(element);
943
var width = self.data('width') || NETDATA.chartDefaults.width;
944
var height = self.data('height') || NETDATA.chartDefaults.height;
945
@@ -926,7 +955,7 @@
955
956
NETDATA.googleInitialize = function(callback) {
957
if(typeof netdataStopGoogleCharts == 'undefined' && typeof google != 'undefined') {
929
- NETDATA.registerChartLibrary('google', NETDATA.google_js, 'datatable', '', 3);
958
+ NETDATA.registerChartLibrary('google', NETDATA.google_js);
959
if(typeof callback == "function")
960
callback();
961
}
@@ -934,8 +963,8 @@
963
callback();
964
};
965
937
- NETDATA.googleChartUpdate = function(event, data) {
938
- var self = $(this);
966
+ NETDATA.googleChartUpdate = function(element, data) {
967
+ var self = $(element);
968
var width = self.data('width') || NETDATA.chartDefaults.width;
969
var height = self.data('height') || NETDATA.chartDefaults.height;
970
var gchart = self.data('google-instance');
@@ -949,8 +978,8 @@
978
gchart.draw(datatable, options);
979
};
980
952
- NETDATA.googleChartCreate = function(event, data) {
953
- var self = $(this);
981
+ NETDATA.googleChartCreate = function(element, data) {
982
+ var self = $(element);
983
var width = self.data('width') || NETDATA.chartDefaults.width;
984
var height = self.data('height') || NETDATA.chartDefaults.height;
985
var chart = self.data('chart');
@@ -1020,7 +1049,7 @@
1049
switch(chart.chart_type) {
1050
case "area":
1051
options.vAxis.viewWindowMode = 'maximized';
1023
- gchart = new google.visualization.AreaChart(this);
1052
+ gchart = new google.visualization.AreaChart(element);
1053
break;
1054
1055
case "stacked":
@@ -1029,13 +1058,13 @@
1058
options.vAxis.viewWindowMode = 'maximized';
1059
options.vAxis.minValue = null;
1060
options.vAxis.maxValue = null;
1032
- gchart = new google.visualization.AreaChart(this);
1061
+ gchart = new google.visualization.AreaChart(element);
1062
break;
1063
1064
default:
1065
case "line":
1066
options.lineWidth = 2;
1038
- gchart = new google.visualization.LineChart(this);
1067
+ gchart = new google.visualization.LineChart(element);
1068
break;
1069
}
1070
@@ -1046,26 +1075,109 @@
1075
.data('created', true);
1076
};
1077
1078
+ // ----------------------------------------------------------------------------------------------------------------
1079
+ // Charts Libraries Registration
1080
+
1081
+ NETDATA.chartLibraries = {
1082
+ "dygraph": {
1083
+ initialize: NETDATA.dygraphInitialize,
1084
+ create: NETDATA.dygraphChartCreate,
1085
+ update: NETDATA.dygraphChartUpdate,
1086
+ initialized: false,
1087
+ enabled: true,
1088
+ format: 'json',
1089
+ options: 'ms|flip',
1090
+ pixels_per_point: 2,
1091
+ detects_dimensions_on_update: false
1092
+ },
1093
+ "sparkline": {
1094
+ initialize: NETDATA.sparklineInitialize,
1095
+ create: NETDATA.sparklineChartCreate,
1096
+ update: NETDATA.sparklineChartUpdate,
1097
+ initialized: false,
1098
+ enabled: true,
1099
+ format: 'array',
1100
+ options: 'flip|min2max',
1101
+ pixels_per_point: 2,
1102
+ detects_dimensions_on_update: false
1103
+ },
1104
+ "peity": {
1105
+ initialize: NETDATA.peityInitialize,
1106
+ create: NETDATA.peityChartCreate,
1107
+ update: NETDATA.peityChartUpdate,
1108
+ initialized: false,
1109
+ enabled: true,
1110
+ format: 'ssvcomma',
1111
+ options: 'null2zero|flip|min2max',
1112
+ pixels_per_point: 2,
1113
+ detects_dimensions_on_update: false
1114
+ },
1115
+ "morris": {
1116
+ initialize: NETDATA.morrisInitialize,
1117
+ create: NETDATA.morrisChartCreate,
1118
+ update: NETDATA.morrisChartUpdate,
1119
+ initialized: false,
1120
+ enabled: true,
1121
+ format: 'json',
1122
+ options: 'objectrows|ms',
1123
+ pixels_per_point: 10,
1124
+ detects_dimensions_on_update: false
1125
+ },
1126
+ "google": {
1127
+ initialize: NETDATA.googleInitialize,
1128
+ create: NETDATA.googleChartCreate,
1129
+ update: NETDATA.googleChartUpdate,
1130
+ initialized: false,
1131
+ enabled: true,
1132
+ format: 'datatable',
1133
+ options: '',
1134
+ pixels_per_point: 2,
1135
+ detects_dimensions_on_update: true
1136
+ },
1137
+ "raphael": {
1138
+ initialize: NETDATA.raphaelInitialize,
1139
+ create: NETDATA.raphaelChartCreate,
1140
+ update: NETDATA.raphaelChartUpdate,
1141
+ initialized: false,
1142
+ enabled: true,
1143
+ format: 'json',
1144
+ options: '',
1145
+ pixels_per_point: 1,
1146
+ detects_dimensions_on_update: false
1147
+ }
1148
+ };
1149
+
1150
+ NETDATA.registerChartLibrary = function(library, url) {
1151
+ console.log("registering chart library: " + library);
1152
+
1153
+ NETDATA.chartLibraries[library]
1154
+ .url = url
1155
+ .initialized = new Date().getTime();
1156
+
1157
+ console.log(NETDATA.chartLibraries);
1158
+ }
1159
+
1160
// ----------------------------------------------------------------------------------------------------------------
1161
// load all libraries and initialize
1162
1163
NETDATA.errorReset();
1164
1165
NETDATA._loadjQuery(function() {
1055
- NETDATA.raphaelInitialize(function() {
1056
- NETDATA.morrisInitialize(function() {
1057
- NETDATA.peityInitialize(function() {
1058
- NETDATA.sparklineInitialize(function() {
1059
- NETDATA.dygraphInitialize(function() {
1060
- NETDATA.googleInitialize(function() {
1061
- netdataParsePageCharts();
1062
- }) // google
1063
- }) // dygraph.js
1064
- }) // sparkline.js
1065
- }) // piety.js
1066
- }) // morris.js
1067
- }) // raphael.js
1166
+ $.getScript(NETDATA.serverDefault + 'lib/visible.js').then(function() {
1167
+ NETDATA.raphaelInitialize(function() {
1168
+ NETDATA.morrisInitialize(function() {
1169
+ NETDATA.peityInitialize(function() {
1170
+ NETDATA.sparklineInitialize(function() {
1171
+ NETDATA.dygraphInitialize(function() {
1172
+ NETDATA.googleInitialize(function() {
1173
+ NETDATA.init();
1174
+ }) // google
1175
+ }) // dygraph.js
1176
+ }) // sparkline.js
1177
+ }) // piety.js
1178
+ }) // morris.js
1179
+ }) // raphael.js
1180
+ })
1181
});
1182
1183
})(window);
1071
-
web/lib/visible.js
new
+26
@@ -0,0 +1,26 @@
1
+(function($){
2
+
3
+ /**
4
+ * Copyright 2012, Digital Fusion
5
+ * Licensed under the MIT license.
6
+ * http://teamdf.com/jquery-plugins/license/
7
+ *
8
+ * @author Sam Sehnert
9
+ * @desc A small plugin that checks whether elements are within
10
+ * the user visible viewport of a web browser.
11
+ * only accounts for vertical position, not horizontal.
12
+ */
13
+ $.fn.visible = function(partial){
14
+
15
+ var $t = $(this),
16
+ $w = $(window),
17
+ viewTop = $w.scrollTop(),
18
+ viewBottom = viewTop + $w.height(),
19
+ _top = $t.offset().top,
20
+ _bottom = _top + $t.height(),
21
+ compareTop = partial === true ? _bottom : _top,
22
+ compareBottom = partial === true ? _top : _bottom;
23
+
24
+ return ((compareBottom <= viewBottom) && (compareTop >= viewTop));
25
+ };
26
+})(jQuery);