Copyright 2015, Joseph Huckaby
[MIT License](https://github.com/jhuckaby/pixl-xml)
+- [node-int64](https://github.com/broofa/node-int64)
+
+ Copyright 2014, Robert Kieffer
+ [MIT License](https://github.com/broofa/node-int64/blob/master/LICENSE)
+
EXTRA_DIST = \
.gitignore \
autogen.sh \
- README.md \
+ README \
LICENSE.md \
autogen.sh \
netdata-9999.ebuild \
web \
$(NULL)
+if GIT_TREE
+
+all-local: README
+
+README: README.md
+ sed -e '/^## Features$$/p' -e '/^## Git/,/^## Features$$/d' $< > $@
+
+endif
+
dist_noinst_DATA = netdata.spec
# until integrated within build
---
+## Git sources
+
+You are looking at a version of the sources extracted directly from git.
+If you want a version of the source package where `configure` and any
+documentation has been built for you, please get an official
+[netdata package download](https://firehol.org/download/netdata/).
+The `unsigned/master` folder tracks the head of the git tree and
+released packages are also available.
+
## Features
**netdata** is a highly optimized Linux daemon providing **real-time performance monitoring for Linux systems, Applications, SNMP devices, over the web**!
compile: cc1 cc1plus as gcc ld make automake autoconf git
rsync: rsync
media: mplayer vlc xine mediatomb omxplayer omxplayer.bin kodi kodi.bin xbmc xbmc.bin mediacenter eventlircd
-squid: squid squid2 squid3
+squid: squid squid2 squid3 c-icap
apache: apache apache2
mysql: mysqld mysql
asterisk: asterisk
AC_INIT([netdata], VERSION_NUMBER[]VERSION_SUFFIX)
+AM_CONDITIONAL([GIT_TREE], [test -f README.md])
+
AM_MAINTAINER_MODE([disable])
if test x"$USE_MAINTAINER_MODE" = xyes; then
AC_MSG_NOTICE(***************** MAINTAINER MODE *****************)
node_modules/pixl-xml.js \
node_modules/net-snmp.js \
node_modules/asn1.js \
+ node_modules/node-int64.js \
$(NULL)
nodemodulesberdir=$(nodedir)/node_modules/ber
var url = require('url');
var http = require('http');
var util = require('util');
+var Int64 = require('node-int64');
/*
var netdata = require('netdata');
if(typeof value === 'undefined' || value === null)
return false;
- if(this._current_chart._dimensions_count !== 0)
- this.queue('SET ' + dimension + ' = ' + value);
+ if(this._current_chart._dimensions_count !== 0) {
+ if (value instanceof Buffer) {
+ var value64 = new Int64(value);
+ this.queue('SET ' + dimension + ' = ' + value64.toString(10));
+ }
+ else
+ this.queue('SET ' + dimension + ' = ' + value.toString());
+ }
return true;
};
--- /dev/null
+// Int64.js
+//
+// Copyright (c) 2012 Robert Kieffer
+// MIT License - http://opensource.org/licenses/mit-license.php
+
+/**
+ * Support for handling 64-bit int numbers in Javascript (node.js)
+ *
+ * JS Numbers are IEEE-754 binary double-precision floats, which limits the
+ * range of values that can be represented with integer precision to:
+ *
+ * 2^^53 <= N <= 2^53
+ *
+ * Int64 objects wrap a node Buffer that holds the 8-bytes of int64 data. These
+ * objects operate directly on the buffer which means that if they are created
+ * using an existing buffer then setting the value will modify the Buffer, and
+ * vice-versa.
+ *
+ * Internal Representation
+ *
+ * The internal buffer format is Big Endian. I.e. the most-significant byte is
+ * at buffer[0], the least-significant at buffer[7]. For the purposes of
+ * converting to/from JS native numbers, the value is assumed to be a signed
+ * integer stored in 2's complement form.
+ *
+ * For details about IEEE-754 see:
+ * http://en.wikipedia.org/wiki/Double_precision_floating-point_format
+ */
+
+// Useful masks and values for bit twiddling
+var MASK31 = 0x7fffffff, VAL31 = 0x80000000;
+var MASK32 = 0xffffffff, VAL32 = 0x100000000;
+
+// Map for converting hex octets to strings
+var _HEX = [];
+for (var i = 0; i < 256; i++) {
+ _HEX[i] = (i > 0xF ? '' : '0') + i.toString(16);
+}
+
+//
+// Int64
+//
+
+/**
+ * Constructor accepts any of the following argument types:
+ *
+ * new Int64(buffer[, offset=0]) - Existing Buffer with byte offset
+ * new Int64(Uint8Array[, offset=0]) - Existing Uint8Array with a byte offset
+ * new Int64(string) - Hex string (throws if n is outside int64 range)
+ * new Int64(number) - Number (throws if n is outside int64 range)
+ * new Int64(hi, lo) - Raw bits as two 32-bit values
+ */
+var Int64 = module.exports = function(a1, a2) {
+ if (a1 instanceof Buffer) {
+ this.buffer = a1;
+ this.offset = a2 || 0;
+ } else if (Object.prototype.toString.call(a1) == '[object Uint8Array]') {
+ // Under Browserify, Buffers can extend Uint8Arrays rather than an
+ // instance of Buffer. We could assume the passed in Uint8Array is actually
+ // a buffer but that won't handle the case where a raw Uint8Array is passed
+ // in. We construct a new Buffer just in case.
+ this.buffer = new Buffer(a1);
+ this.offset = a2 || 0;
+ } else {
+ this.buffer = this.buffer || new Buffer(8);
+ this.offset = 0;
+ this.setValue.apply(this, arguments);
+ }
+};
+
+
+// Max integer value that JS can accurately represent
+Int64.MAX_INT = Math.pow(2, 53);
+
+// Min integer value that JS can accurately represent
+Int64.MIN_INT = -Math.pow(2, 53);
+
+Int64.prototype = {
+
+ constructor: Int64,
+
+ /**
+ * Do in-place 2's compliment. See
+ * http://en.wikipedia.org/wiki/Two's_complement
+ */
+ _2scomp: function() {
+ var b = this.buffer, o = this.offset, carry = 1;
+ for (var i = o + 7; i >= o; i--) {
+ var v = (b[i] ^ 0xff) + carry;
+ b[i] = v & 0xff;
+ carry = v >> 8;
+ }
+ },
+
+ /**
+ * Set the value. Takes any of the following arguments:
+ *
+ * setValue(string) - A hexidecimal string
+ * setValue(number) - Number (throws if n is outside int64 range)
+ * setValue(hi, lo) - Raw bits as two 32-bit values
+ */
+ setValue: function(hi, lo) {
+ var negate = false;
+ if (arguments.length == 1) {
+ if (typeof(hi) == 'number') {
+ // Simplify bitfield retrieval by using abs() value. We restore sign
+ // later
+ negate = hi < 0;
+ hi = Math.abs(hi);
+ lo = hi % VAL32;
+ hi = hi / VAL32;
+ if (hi > VAL32) throw new RangeError(hi + ' is outside Int64 range');
+ hi = hi | 0;
+ } else if (typeof(hi) == 'string') {
+ hi = (hi + '').replace(/^0x/, '');
+ lo = hi.substr(-8);
+ hi = hi.length > 8 ? hi.substr(0, hi.length - 8) : '';
+ hi = parseInt(hi, 16);
+ lo = parseInt(lo, 16);
+ } else {
+ throw new Error(hi + ' must be a Number or String');
+ }
+ }
+
+ // Technically we should throw if hi or lo is outside int32 range here, but
+ // it's not worth the effort. Anything past the 32'nd bit is ignored.
+
+ // Copy bytes to buffer
+ var b = this.buffer, o = this.offset;
+ for (var i = 7; i >= 0; i--) {
+ b[o+i] = lo & 0xff;
+ lo = i == 4 ? hi : lo >>> 8;
+ }
+
+ // Restore sign of passed argument
+ if (negate) this._2scomp();
+ },
+
+ /**
+ * Convert to a native JS number.
+ *
+ * WARNING: Do not expect this value to be accurate to integer precision for
+ * large (positive or negative) numbers!
+ *
+ * @param allowImprecise If true, no check is performed to verify the
+ * returned value is accurate to integer precision. If false, imprecise
+ * numbers (very large positive or negative numbers) will be forced to +/-
+ * Infinity.
+ */
+ toNumber: function(allowImprecise) {
+ var b = this.buffer, o = this.offset;
+
+ // Running sum of octets, doing a 2's complement
+ var negate = b[o] & 0x80, x = 0, carry = 1;
+ for (var i = 7, m = 1; i >= 0; i--, m *= 256) {
+ var v = b[o+i];
+
+ // 2's complement for negative numbers
+ if (negate) {
+ v = (v ^ 0xff) + carry;
+ carry = v >> 8;
+ v = v & 0xff;
+ }
+
+ x += v * m;
+ }
+
+ // Return Infinity if we've lost integer precision
+ if (!allowImprecise && x >= Int64.MAX_INT) {
+ return negate ? -Infinity : Infinity;
+ }
+
+ return negate ? -x : x;
+ },
+
+ /**
+ * Convert to a JS Number. Returns +/-Infinity for values that can't be
+ * represented to integer precision.
+ */
+ valueOf: function() {
+ return this.toNumber(false);
+ },
+
+ /**
+ * Return string value
+ *
+ * @param radix Just like Number#toString()'s radix
+ */
+ toString: function(radix) {
+ return this.valueOf().toString(radix || 10);
+ },
+
+ /**
+ * Return a string showing the buffer octets, with MSB on the left.
+ *
+ * @param sep separator string. default is '' (empty string)
+ */
+ toOctetString: function(sep) {
+ var out = new Array(8);
+ var b = this.buffer, o = this.offset;
+ for (var i = 0; i < 8; i++) {
+ out[i] = _HEX[b[o+i]];
+ }
+ return out.join(sep || '');
+ },
+
+ /**
+ * Returns the int64's 8 bytes in a buffer.
+ *
+ * @param {bool} [rawBuffer=false] If no offset and this is true, return the internal buffer. Should only be used if
+ * you're discarding the Int64 afterwards, as it breaks encapsulation.
+ */
+ toBuffer: function(rawBuffer) {
+ if (rawBuffer && this.offset === 0) return this.buffer;
+
+ var out = new Buffer(8);
+ this.buffer.copy(out, 0, this.offset, this.offset + 8);
+ return out;
+ },
+
+ /**
+ * Copy 8 bytes of int64 into target buffer at target offset.
+ *
+ * @param {Buffer} targetBuffer Buffer to copy into.
+ * @param {number} [targetOffset=0] Offset into target buffer.
+ */
+ copy: function(targetBuffer, targetOffset) {
+ this.buffer.copy(targetBuffer, targetOffset || 0, this.offset, this.offset + 8);
+ },
+
+ /**
+ * Returns a number indicating whether this comes before or after or is the
+ * same as the other in sort order.
+ *
+ * @param {Int64} other Other Int64 to compare.
+ */
+ compare: function(other) {
+
+ // If sign bits differ ...
+ if ((this.buffer[this.offset] & 0x80) != (other.buffer[other.offset] & 0x80)) {
+ return other.buffer[other.offset] - this.buffer[this.offset];
+ }
+
+ // otherwise, compare bytes lexicographically
+ for (var i = 0; i < 8; i++) {
+ if (this.buffer[this.offset+i] !== other.buffer[other.offset+i]) {
+ return this.buffer[this.offset+i] - other.buffer[other.offset+i];
+ }
+ }
+ return 0;
+ },
+
+ /**
+ * Returns a boolean indicating if this integer is equal to other.
+ *
+ * @param {Int64} other Other Int64 to compare.
+ */
+ equals: function(other) {
+ return this.compare(other) === 0;
+ },
+
+ /**
+ * Pretty output in console.log
+ */
+ inspect: function() {
+ return '[Int64 value:' + this + ' octets:' + this.toOctetString(' ') + ']';
+ }
+};
int *fds; // array of fds it uses
int fds_size; // the size of the fds array
- int childs; // number of processes directly referencing this
+ int children_count; // number of processes directly referencing this
int updated; // 1 when update
int merged; // 1 when it has been merged to its parent
int new_entry;
if(p) {
if(!p->updated) ret += 1;
if(ret) fprintf(stderr, "%s %s %d [%s, %s] c=%d u=%llu+%llu, s=%llu+%llu, cu=%llu+%llu, cs=%llu+%llu, n=%llu+%llu, j=%llu+%llu, cn=%llu+%llu, cj=%llu+%llu\n"
- , b, p->comm, p->pid, p->updated?"OK":"KILLED", p->target->name, p->childs
+ , b, p->comm, p->pid, p->updated?"OK":"KILLED", p->target->name, p->children_count
, p->utime, p->utime - p->old_utime
, p->stime, p->stime - p->old_stime
, p->cutime, p->cutime - p->old_cutime
all_pids_count++;
p->parent = NULL;
p->updated = 0;
- p->childs = 0;
+ p->children_count = 0;
p->merged = 0;
p->new_entry = 0;
}
int c;
struct pid_stat *p = NULL;
- // link all parents and update childs count
+
+ // link all children to their parents
+ // and update children count on parents
for(p = root_of_pids; p ; p = p->next) {
- if(p->ppid > 0 && p->ppid <= pid_max && all_pids[p->ppid]) {
- if(debug || (p->target && p->target->debug)) fprintf(stderr, "apps.plugin: \tparent of %d %s is %d %s\n", p->pid, p->comm, p->ppid, all_pids[p->ppid]->comm);
+ // for each process found running
+
+ if(p->ppid > 0
+ && p->ppid <= pid_max
+ && all_pids[p->ppid]
+ ) {
+ // for valid processes
+
+ if(debug || (p->target && p->target->debug))
+ fprintf(stderr, "apps.plugin: \tparent of %d (%s) is %d (%s)\n", p->pid, p->comm, p->ppid, all_pids[p->ppid]->comm);
p->parent = all_pids[p->ppid];
- p->parent->childs++;
+ p->parent->children_count++;
}
- else if(p->ppid != 0) error("pid %d %s states parent %d, but the later does not exist.", p->pid, p->comm, p->ppid);
+ else if(p->ppid != 0)
+ error("pid %d %s states parent %d, but the later does not exist.", p->pid, p->comm, p->ppid);
}
+
+ // children that do not have a target
+ // inherit their target from their parent
+ int found = 1;
+ while(found) {
+ found = 0;
+ for(p = root_of_pids; p ; p = p->next) {
+ // if this process does not have a target
+ // and it has a parent
+ // and its parent has a target
+ // then, set the parent's target to this process
+ if(unlikely(!p->target && p->parent && p->parent->target)) {
+ p->target = p->parent->target;
+ found++;
+
+ if(debug || (p->target && p->target->debug))
+ fprintf(stderr, "apps.plugin: \t\tTARGET INHERITANCE: %s is inherited by %d (%s) from its parent %d (%s).\n", p->target->name, p->pid, p->comm, p->parent->pid, p->parent->comm);
+ }
+ }
+ }
+
+
// find all the procs with 0 childs and merge them to their parents
// repeat, until nothing more can be done.
- int found = 1;
+ found = 1;
while(found) {
found = 0;
for(p = root_of_pids; p ; p = p->next) {
- // if this process does not have any childs, and
- // is not already merged, and
- // its parent has childs waiting to be merged, and
- // the target of this process and its parent is the same, or the parent does not have a target, or this process does not have a parent
+ // if this process does not have any children
+ // and is not already merged
+ // and has a parent
+ // and its parent has children
+ // and the target of this process and its parent is the same, or the parent does not have a target
// and its parent is not init
- // then... merge them!
- if(!p->childs && !p->merged && p->parent && p->parent->childs && (p->target == p->parent->target || !p->parent->target || !p->target) && p->ppid != 1) {
- p->parent->childs--;
+ // then, mark them as merged.
+ if(unlikely(
+ !p->children_count
+ && !p->merged
+ && p->parent
+ && p->parent->children_count
+ && (p->target == p->parent->target || !p->parent->target)
+ && p->ppid != 1
+ )) {
+ p->parent->children_count--;
p->merged = 1;
// the parent inherits the child's target, if it does not have a target itself
- if(p->target && !p->parent->target) {
+ if(unlikely(p->target && !p->parent->target)) {
p->parent->target = p->target;
- if(debug || (p->target && p->target->debug)) fprintf(stderr, "apps.plugin: \t\ttarget %s is inherited by %d %s from its child %d %s.\n", p->target->name, p->parent->pid, p->parent->comm, p->pid, p->comm);
+
+ if(debug || (p->target && p->target->debug))
+ fprintf(stderr, "apps.plugin: \t\tTARGET INHERITANCE: %s is inherited by %d (%s) from its child %d (%s).\n", p->target->name, p->parent->pid, p->parent->comm, p->pid, p->comm);
}
found++;
}
}
- if(debug) fprintf(stderr, "apps.plugin: merged %d processes\n", found);
+
+ if(debug)
+ fprintf(stderr, "apps.plugin: merged %d processes\n", found);
}
- // give a default target on all top level processes
// init goes always to default target
- if(all_pids[1]) all_pids[1]->target = default_target;
+ if(all_pids[1])
+ all_pids[1]->target = default_target;
+ // give a default target on all top level processes
for(p = root_of_pids; p ; p = p->next) {
// if the process is not merged itself
// then is is a top level process
- if(!p->merged && !p->target) p->target = default_target;
+ if(!p->merged && !p->target)
+ p->target = default_target;
#ifdef INCLUDE_CHILDS
// by the way, update the diffs
- // will be used later for substracting killed process times
+ // will be used later for subtracting killed process times
p->diff_cutime = p->utime - p->cutime;
p->diff_cstime = p->stime - p->cstime;
p->diff_cminflt = p->minflt - p->cminflt;
while(found) {
found = 0;
for(p = root_of_pids; p ; p = p->next) {
- if(!p->target && p->merged && p->parent && p->parent->target) {
+ if(unlikely(!p->target && p->merged && p->parent && p->parent->target)) {
p->target = p->parent->target;
found++;
+
+ if(debug || (p->target && p->target->debug))
+ fprintf(stderr, "apps.plugin: \t\tTARGET INHERITANCE: %s is inherited by %d (%s) from its parent %d (%s) at phase 2.\n", p->target->name, p->pid, p->comm, p->parent->pid, p->parent->comm);
}
}
}
break;
}
- if(unlikely(st->debug)) debug(D_PLUGINSD, "PLUGINSD: '%s' is requesting a END on chart %s", cd->fullfilename, st->id);
+ if(unlikely(st->debug)) debug(D_PLUGINSD, "PLUGINSD: '%s' is requesting an END on chart %s", cd->fullfilename, st->id);
rrdset_done(st);
st = NULL;
pthread_exit(NULL);
return NULL;
}
-
-
uint32_t lines = procfile_lines(ff), l;
uint32_t words = procfile_linewords(ff, 0), w;
+ if(!lines) {
+ error("Cannot read /proc/interrupts, zero lines reported.");
+ return 1;
+ }
+
// find how many CPUs are there
if(cpus == -1) {
cpus = 0;
uint32_t lines = procfile_lines(ff), l;
uint32_t words = procfile_linewords(ff, 0), w;
+ if(!lines) {
+ error("Cannot read /proc/softirqs, zero lines reported.");
+ return 1;
+ }
+
// find how many CPUs are there
if(cpus == -1) {
cpus = 0;
<i class="fa fa-circle"></i> <a href="http://D3js.org/" target="_blank">D3</a>,
<i class="fa fa-copyright"></i> Copyright 2015, Mike Bostock, <a href="http://opensource.org/licenses/BSD-3-Clause" target="_blank">BSD License</a>
+ <i class="fa fa-circle"></i> <a href="https://github.com/broofa/node-int64" target="_blank">node-int64</a>,
+ <i class="fa fa-copyright"></i> Copyright 2014, Robert Kieffer, <a href="https://github.com/broofa/node-int64/blob/master/LICENSE" target="_blank">MIT License</a>
+
</small>
</div>
</div>