A Vagrantfile is provided with current OS targets.
vagrant up c7
CentOS 7.3.1611 x86_64vagrant up c6
CentOS 6.8 x86_64vagrant up u16
Ubuntu 16.04 (xenial) x86_64vagrant up u14
Ubuntu 14.04 (trusty) x86_64vagrant up o14
OmniOS r151014vagrant up bsd11
FreeBSD 11.0-RELEASE-p1vagrant up bsd10
FreeBSD 10.3-RELEASE
Deprecated, no longer supported/built:
- 3/31/2017 - CentOS 5 end of life
- 4/2017 - Ubuntu 12.04 (precise) end of life
Development host environment (at the time of this writing):
$ echo $(system_profiler SPSoftwareDataType | grep 'System Version' | cut -d ':' -f 2) ;\
vagrant -v ; vboxmanage --version ; node -v ; eslint -v
macOS 10.12.4 (16E195)
Vagrant 1.9.4
5.1.20r114629
v6.10.2
v3.19.0
If you plan to develop and contribute to NAD, fork the repository and clone your fork. If you want to build your own packages, you do not necessarily need to fork, simply clone the main repository.
e.g. cloning the master repository:
git clone https://github.com/circonus-labs/nad
cd nad
npm install
- Fork the NAD repository on github
- Clone fork on development host
vagrant up <target_os>
where<target_os>
is the desired OS from the list abovevagrant ssh <target_os>
cd /vagrant && make install
/opt/circonus/nad/sbin/nad
- In another terminal,
vagrant ssh <target_os> -c 'curl http://127.0.0.1:2609/'
For example:
Term 1:
$ vagrant up c7
$ vagrant ssh c7
[vagrant@centos7 ~]$ cd /vagrant
[vagrant@centos7 vagrant]$ sudo make install
--snip--
[vagrant@centos7 ~]$ /opt/circonus/nad/sbin/nad
{"pid":3171,"hostname":"centos7","name":"nad","level":30,"time":1493138697222,"msg":"initializing","module":"main","name":"nad","version":"2.0.0","v":1}
{"pid":3171,"hostname":"centos7","name":"nad","level":30,"time":1493138697226,"msg":"push receiver handler loaded","module":"main","v":1}
{"pid":3171,"hostname":"centos7","name":"nad","level":30,"time":1493138697231,"msg":"plugin scan start","module":"plugins","submodule":"scanner","dir":"/opt/circonus/nad/etc/node-agent.d","v":1}
{"pid":3171,"hostname":"centos7","name":"nad","level":30,"time":1493138697234,"msg":"plugin scan complete","module":"plugins","submodule":"scanner","active_plugins":0,"v":1}
{"pid":3171,"hostname":"centos7","name":"nad","level":30,"time":1493138697234,"msg":"installing SIGHUP handler for plugin rescans","module":"main","v":1}
{"pid":3171,"hostname":"centos7","name":"nad","level":30,"time":1493138697237,"msg":"listening","module":"main","server":{"address":null,"port":2609},"v":1}
{"pid":3171,"hostname":"centos7","name":"nad","level":30,"time":1493138697237,"msg":"http servers started","module":"main","v":1}
{"pid":3171,"hostname":"centos7","name":"nad","level":40,"time":1493138697238,"msg":"no https servers configured, skipping","module":"main","v":1}
{"pid":3171,"hostname":"centos7","name":"nad","level":40,"time":1493138697238,"msg":"reverse connector not enabled, skipping","module":"main","v":1}
{"pid":3171,"hostname":"centos7","name":"nad","level":30,"time":1493138697272,"msg":"initialized, no check id supplied","module":"nad-statsd","submodule":"circonus","submodule":"trap","type":"group","enabled":false,"v":1}
{"pid":3171,"hostname":"centos7","name":"nad","level":30,"time":1493138697272,"msg":"statsd listener loaded","module":"main","v":1}
{"pid":3171,"hostname":"centos7","name":"nad","level":30,"time":1493138697272,"msg":"initialized","module":"nad-statsd","submodule":"circonus","submodule":"trap","type":"host","enabled":true,"v":1}
{"pid":3171,"hostname":"centos7","name":"nad","level":30,"time":1493138697272,"msg":"dropping privileges","module":"main","gid":"nobody","uid":"nobody","v":1}
{"pid":3171,"hostname":"centos7","name":"nad","level":40,"time":1493138697272,"msg":"not running as root, skipping drop privileges","module":"main","v":1}
{"pid":3171,"hostname":"centos7","name":"nad","level":30,"time":1493138697273,"msg":"started","module":"nad-statsd","submodule":"circonus","enabled":true,"v":1}
{"pid":3171,"hostname":"centos7","name":"nad","level":30,"time":1493138697276,"msg":"listener up","module":"nad-statsd","v":1}
{"pid":3171,"hostname":"centos7","name":"nad","level":30,"time":1493138697276,"msg":"NAD bootstrap complete","module":"main","v":1}
{"pid":3171,"hostname":"centos7","name":"nad","level":30,"time":1493138723829,"msg":"responding with metrics","module":"plugins","est_metrics":17,"v":1}
Term 2:
$ vagrant ssh c7 -c 'curl 127.0.0.1:2609'
{"nad":{"memory":{"rss":26202112,"heapTotal":13668352,"heapUsed":8703872,"external":138886},"uptime":26.771,"cpu":{"user":258921,"system":26636}},"statsd":{"open_req_count":{"_type":"n","_value":[0,0]},"open_handle_count":{"_type":"n","_value":[5,5]},"uptime_seconds":{"_type":"n","_value":[10.221,20.169]},"bad_lines_seen":{"_type":"n","_value":[0,0]},"last_packet_seen":{"_type":"n","_value":[1493138697.218,1493138697.218]},"metrics_received":{"_type":"n","_value":[0,0]},"packets_received":{"_type":"n","_value":[0,0]},"host_last_flush":{"_type":"n","_value":[0,1493138707]},"host_last_exception":{"_type":"n","_value":[0,0]},"host_flush_time_ms":{"_type":"n","_value":[0,19]},"host_flush_length_bytes":{"_type":"n","_value":[0,606]},"calculation_time_ms":{"_type":"n","_value":[1.315842,0.796727]},"host_num_stats":{"_type":"n","_value":[13,14]},"timestamp_lag_ms":{"_type":"n","_value":[-52]}}}Connection to 127.0.0.1 closed.
$
The packaging/make-omnibus
shell script is used to build the omnibus packages (.rpm, .deb, or .tar.gz). The build can be customized by copying example-omnibus.conf
to omnibus.conf
and setting the applicable variables. make-omnibus
will clone its own copy of the repository so, ensure any changes are committed and pushed to the fork represented in NAD_REPO
.
- Clone fork
- Copy
packaging/example-omnibus.conf
topackaging/omnibus.conf
and customize- Ensure
NAD_REPO
is set to the fork's clone URL inpackaging/omnibus.conf
- If working on a custom feature branch, ensure
NAD_BRANCH
is set to the correct branch inpackaging/omnibus.conf
- Ensure
vagrant up <target_os>
vagrant ssh <target_os>
cd /vagrant/packaging && ./make-omnibus
- The result should be an installable omnibus package in
PUBLISHDIR
(as set inomnibus.conf
)
- Live testing can be performed by developing on host and running
make install
ormake install-(rhel|ubuntu|illumos|etc.)
in the guest VM. - Run NAD in the foreground with debugging.
/opt/circonus/nad/sbin/nad --debug
- Leverage
curl
to simulate requests.curl 'http://127.0.0.1:2609/'
- If working on an executable plugin, ensure the plugin works from the command line first, then integrate the plugin with NAD.
NAD uses a plugin system for gathering metrics. NAD supports two primary types of plugins - executable and native. Each type of plugin produces output that NAD consumes and makes available to Circonus. Minimal examples of both, native and executable plugins can be found in the plugins/example
directory.
NAD/Circonus support the following types of metrics:
i
- a signed 32bit integer valueI
- an unsigned 32bit integer valuel
- a signed 64bit integer valueL
- an unsigned 64bit integer valuen
- a value to be represented as a doubles
- the the value is a string
An executable can be a shell script, perl/python/ruby/etc. script, a compiled binary, etc. Anything that one can run from the command line. See the examples/plugins and plugins directory for examples of several types of executable plugins. Executables must produce metrics to standard output. They may produce JSON or tab-delimited output.
<metric_name>\t<metric_type>
- the specified metric has a null value.<metric_name>\t<metric_type>\t<value>
- the specified metric has a value.
{ "<metric_name>": { "_type": "<metric_type>", "_value": <value> } }
The JSON form allows for histogram input in the following format:
- List of values
[<val1>, <val2>, ... ]
- Pre-bucketed histograms
["H[12]=3", "H[3.1]=4"]
Example:
{ "my_metric": { "_type": "i", "_value": 10 }, "cherry`pi": { "_type": "n", "_value": 3.14 } }
Place a file (with a .js
extension) into plugin_dir. See example.
NAD also provides a push receiver to accept metrics from daemons and other external processes/jobs which do not fit into the plugin model. Metrics can be pushed to NAD via HTTP PUT
or POST
to http://127.0.0.1:2609/write
with body as valid JSON (see above).
An executable plugin may provide control information in a line starting with a #
character followed by a JSON block. Currently, timeout
is the only parameter accepted and the argument is interpreted as seconds. For example, to indicate that the script should be aborted if a set of output metrics cannot be completed in 1.12 seconds, the plugin would emit:
# { "timeout": 1.12 }
Continuous output is supported for long-running executables. After a set of metrics is emitted to standard output, emit a single empty line. NAD will accept the previous output into a result set and return them on the next request for metrics. The executable can then pause for some ad-hoc amount of time and produce more output followed by another empty line. This mode can be useful for collection of information from tools such as mpstat
or vmstat
.
Note: in most cases if you can get raw accumulated counters (instead of averages over some amount of time), that the output can be more useful to monitoring applications as a derivative can be applied after the fact without the risk of data loss.
A native plugin is a NodeJS module which will be loaded into NAD. See native example, additionally, there are several native plugins in the plugins directory.
- Written as a module
- Expose a
run()
method which will be passed five arguments.- The plugin definition object
- A callback function
- The incoming request object that fired the plugin
- The plugin arguments (as an object), if there are any
- The plugin instance ID
- The
run()
method is responsible for calling the callback with three arguments- The plugin definition object (which was passed to the
run()
method) - The metrics (as an object)
- The instance ID (which was passed to the
run()
method)
- The plugin definition object (which was passed to the
- Additionally, the
run()
method should set its plugin definition object propertyrunning
to false when done. (def.running = false;
)
{
<metric_name>: {
_type: "<metric_type>",
_value: <metric_value>
}
}
Example:
{
my_metric: {
_type: "i",
_value: 10
}
}
- Create a directory for the plugin -
mkdir /opt/circonus/nad/etc/node-agent.d/my_plugin && cd /opt/circonus/nad/etc/node-agent.d/my_plugin
- Write the plugin - running from command line during development
- When ready to test the plugin - create symlink in parent directory
ln -s my_plugin.sh ..