28 Commits

Author SHA1 Message Date
Patrick Stadler
4f28c79906 Merge pull request #7 from grimeyCH/systemd-compatibility
Systemd compatibility
2019-03-11 12:34:55 +01:00
Andreas Grimm
3fccd9615d Review part 2. 2019-03-11 09:27:09 +01:00
Andreas Grimm
2cca88ed8d Update from review. 2019-03-11 09:00:45 +01:00
Andreas Grimm
bc23216756 Link to systemd instruction 2019-02-25 14:13:19 +01:00
Andreas Grimm
8c5131c6ef chmod not necessary 2019-02-25 13:54:55 +01:00
Andreas Grimm
0533eb0ac8 Typos 2019-02-25 13:23:27 +01:00
Andreas Grimm
9023954f3f Readme update for systemd 2019-02-25 13:23:14 +01:00
Andreas Grimm
4f5ed15b98 Restart on exit/failure. 2019-02-25 13:22:53 +01:00
Andreas Grimm
2ed7792a20 Readme and nicer Unit 2019-02-21 18:17:45 +01:00
Andreas Grimm
3a2fff387d Systemd compatibility. 2019-02-20 17:27:02 +01:00
Patrick Stadler
be4039d647 Fix memory metric on *NIX 2017-10-09 14:54:57 +02:00
Patrick Stadler
636feccd7c update readme 2017-01-04 09:17:38 +01:00
Patrick Stadler
697b978d95 rename logentries.com reporter 2017-01-04 09:14:37 +01:00
Patrick Stadler
d8cd496543 Merge pull request #4 from seamusc/master
Logentries.com reporter
2017-01-04 09:14:08 +01:00
Seamus Cawley
215e50ecea Logentries.com reporter 2016-08-09 09:39:01 +01:00
Patrick Stadler
5c0962e12b remove unneeded variable 2016-02-23 09:39:15 +01:00
Patrick Stadler
85ee93aec3 fix update check 2015-12-02 10:20:16 +01:00
Patrick Stadler
3a9c155b7e fix potential word splitting problem 2015-12-02 10:16:06 +01:00
Patrick Stadler
81ca6e0e57 fix missing git error message 2015-12-02 10:11:10 +01:00
Patrick Stadler
b21a7c1269 Merge branch 'master' of github.com:pstadler/metrics.sh 2015-11-17 00:32:34 +01:00
Patrick Stadler
129ece3e0b add generic UDP reporter 2015-11-17 00:32:16 +01:00
Patrick Stadler
817a19d4d8 Merge pull request #1 from mweibel/feature/influxdb-0.9
Update influxdb reporter to syntax of 0.9
2015-08-04 17:20:11 +02:00
Michael Weibel
d5fbece5ae Update influxdb reporter to syntax of 0.9
They completely changed their API.
2015-07-29 07:59:44 +02:00
Patrick Stadler
8882f19ab3 fix is_linux() helper function 2015-06-12 16:14:38 +02:00
Patrick Stadler
a0f29e6106 add project philosophy to readme 2015-03-29 17:27:00 +02:00
Patrick Stadler
8623398d7d add logo to README 2015-03-29 15:05:29 +02:00
Patrick Stadler
6544ba03a0 disk_io now checks if iostat is available. "done" is now always printed before exiting 2015-03-29 01:04:15 +01:00
Patrick Stadler
c956283fbe improve init.d docs 2015-03-29 00:05:46 +01:00
13 changed files with 182 additions and 59 deletions

View File

@@ -1,12 +1,22 @@
# metrics.sh
![metrics.sh](https://raw.githubusercontent.com/pstadler/metrics.sh/assets/logo.png)
metrics.sh is a lightweight metrics collection and forwarding daemon implemented in portable POSIX compliant shell scripts. A transparent interface based on hooks enables writing custom collectors and reporters in an elegant way.
**Project philosophy**
- Flat learning curve
- Easily extensible
- Low impact on system resources
- No compilation, custom interpreters and runtimes required
- Freedom to choose any service for storage, charting and alerting
- Open source, no proprietary parts
- Community-driven development, growing number of included metrics over time
## Usage
```
$ ./metrics.sh --help
Usage: ./metrics.sh [-d] [-h] [-v] [-c] [-m] [-r] [-i] [-C] [-u]
Options:
@@ -29,6 +39,7 @@ $ git clone https://github.com/pstadler/metrics.sh.git
```
See this [guide](init.d/README.md) how to run metrics.sh as a service on Linux.
Or [here](systemd/README.md) for instructions to set metrics.sh up for systemd.
### Requirements
@@ -49,15 +60,17 @@ Metric | Description
## Reporters
Reporter | Description
--------------- | -------------
`stdout` | Write to standard out (default)
`file` | Write to a file or named pipe
`statsd` | Send data to [StatsD](https://github.com/etsy/statsd)
`influxdb` | Send data to [InfluxDB](http://influxdb.com/)
`prometheus` | Provide HTTP endpoint for [Prometheus](http://prometheus.io/)
`keen_io` | Send data to [Keen IO](https://keen.io)
`stathat` | Send data to [StatHat](https://www.stathat.com)
Reporter | Description
---------------- | -------------
`stdout` | Write to standard out (default)
`file` | Write to a file or named pipe
`udp` | Send data to any service via UDP
`statsd` | Send data to [StatsD](https://github.com/etsy/statsd)
`influxdb` | Send data to [InfluxDB](http://influxdb.com/)
`prometheus` | Provide HTTP endpoint for [Prometheus](http://prometheus.io/)
`keen_io` | Send data to [Keen IO](https://keen.io)
`stathat` | Send data to [StatHat](https://www.stathat.com)
`logentries_com` | Send data to [Logentries](https://logentries.com/)
## Configuration
@@ -83,7 +96,7 @@ $ DISK_USAGE_MOUNTPOINT=/dev/vdb ./metrics.sh -m disk_usage
### Configuration files
Maintaing all these options can become a cumbersome job, but metrics.sh provides functionality for creating and reading configuration files.
Maintaining all these options can become a cumbersome job, but metrics.sh provides functionality for creating and reading configuration files.
```sh
$ ./metrics.sh -C > metrics.ini # write configuration to metrics.ini
@@ -140,7 +153,7 @@ defaults () {} # setting default variables
start () {} # called at the beginning
collect () {} # collect the actual metric
stop () {} # called before exiting
docs () {} # used for priting docs and creating output for configuration
docs () {} # used for printing docs and creating output for configuration
```
Metrics run within an isolated scope. It's generally safe to create variables and helper functions within metrics.
@@ -178,7 +191,7 @@ collect () {
report $(du $DU_ARGS | awk '{ print $1 }')
# If report is called with two arguments, the first one will be appended
# to the metric name, for example `report "foo" $val` would be reported as
# "dir_size.foo: $val". This is helpful when a metric is collecting multiple
# "dir_size.foo: $val". This is helpful when a metric is collecting multiple
# values like `network_io`, which reports "network_io.in" / "network_io.out".
}
@@ -203,7 +216,7 @@ defaults () {} # setting default variables
start () {} # called at the beginning
report () {} # report the actual metric
stop () {} # called before exiting
docs () {} # used for priting docs and creating output for configuration
docs () {} # used for printing docs and creating output for configuration
```
Below is an example script for sending metrics as JSON data to an API endpoint. Assuming this script is located at `./reporters/custom/json_api.sh`, it can be invoked by calling `./metrics.sh -r json_api`.
@@ -219,7 +232,7 @@ defaults () {
}
# Prepare the reporter. Create helper functions to be used during collection
# if needed. Returning 1 will result in an error and exection will be stopped.
# if needed. Returning 1 will result in an error and execution will be stopped.
start () {
if [ -z $JSON_API_ENDPOINT ]; then
echo "Error: json_api requires \$JSON_API_ENDPOINT to be specified"
@@ -229,7 +242,7 @@ start () {
# Report metric. This function is called whenever there's a new value
# to report. It's important to know that metrics don't call this function
# directly, as there's some more work to be done before. You can safely assume
# directly, as there's some more work to be done before. You can safely assume
# that arguments passed to this function are sanitized and valid.
report () {
local metric=$1 # the name of the metric, e.g. "cpu", "cpu_alias", "cpu.foo"

View File

@@ -3,31 +3,35 @@
Run the following commands as root:
```sh
# Install at /opt/metrics.sh
$ mkdir /opt && cd /opt
# Install metrics.sh at /opt/metrics.sh
$ mkdir /opt; cd /opt
$ git clone https://github.com/pstadler/metrics.sh.git
$ cd metrics.sh
# Install service
# Install the service
$ ln -s $PWD/init.d/metrics.sh /etc/init.d/metrics.sh
# Create config file
# Create a config file
$ mkdir /etc/metrics.sh && chmod 600 /etc/metrics.sh
$ ./metrics.sh -C > /etc/metrics.sh/metrics.ini
# At this point you should edit your config file
# at /etc/metrics.sh/metrics.ini
# At this point you should edit your config file at
# /etc/metrics.sh/metrics.ini
# Start service
$ service metrics.sh start
# If run with the default configuration where reporter is 'stdout', metrics
# will be written to /var/log/metrics.sh.log. Be aware that this file will
# grow fast.
$ tail -f /var/log/metrics.sh.log
# Stop service
$ service metrics.sh stop
# Check servie status
# Check service status
$ service metrics.sh status
# Check log file
$ tail /var/log/metrics.sh.log
# Automatically start/stop service when (re-)booting
# Automatically start service when booting and stop when shutting down
$ update-rc.d metrics.sh defaults
# Uninstall automatic start/stop
# Disable automatic starting/stopping
$ update-rc.d -f metrics.sh remove
```

View File

@@ -1,7 +1,7 @@
#!/bin/sh
# load utils
for util in ./lib/utils/*.sh; do
for util in ${DIR}/lib/utils/*.sh; do
. $util
done
@@ -16,10 +16,10 @@ main_defaults () {
DEFAULT_REPORTER=stdout
fi
if [ -z $CUSTOM_REPORTERS_PATH ]; then
CUSTOM_REPORTERS_PATH=./reporters/custom
CUSTOM_REPORTERS_PATH=${DIR}/reporters/custom
fi
if [ -z $CUSTOM_METRICS_PATH ]; then
CUSTOM_METRICS_PATH=./metrics/custom
CUSTOM_METRICS_PATH=${DIR}/metrics/custom
fi
}
@@ -178,7 +178,8 @@ main_terminate () {
if [ -d $TEMP_DIR ]; then
rmdir $TEMP_DIR
fi
verbose "done"
echo "done"
}
main_print_docs () {

View File

@@ -2,7 +2,7 @@
get_available_reporters () {
local result
for file in `ls ./reporters/*.sh $CUSTOM_REPORTERS_PATH/*.sh 2> /dev/null`; do
for file in `ls ${DIR}/reporters/*.sh $CUSTOM_REPORTERS_PATH/*.sh 2> /dev/null`; do
local filename=$(basename $file)
local reporter=${filename%.*}
result=$(echo "$result $reporter")
@@ -12,7 +12,7 @@ get_available_reporters () {
get_available_metrics () {
local result
for file in `ls ./metrics/*.sh $CUSTOM_METRICS_PATH/*.sh 2> /dev/null`; do
for file in `ls ${DIR}/metrics/*.sh $CUSTOM_METRICS_PATH/*.sh 2> /dev/null`; do
local filename=$(basename $file)
local metric=${filename%.*}
# register metric
@@ -26,7 +26,7 @@ load_reporter_with_prefix () {
local name=$2
local file
for dir in $CUSTOM_REPORTERS_PATH ./reporters; do
for dir in $CUSTOM_REPORTERS_PATH ${DIR}/reporters; do
if [ -f $dir/$name.sh ]; then
file=$dir/$name.sh
break
@@ -53,7 +53,7 @@ load_metric_with_prefix () {
local name=$2
local file
for dir in $CUSTOM_METRICS_PATH ./metrics; do
for dir in $CUSTOM_METRICS_PATH ${DIR}/metrics; do
if [ -f $dir/$name.sh ]; then
file=$dir/$name.sh
break

View File

@@ -15,7 +15,7 @@ esac)
is_solaris () { [ $OS_TYPE = 'solaris' ]; }
is_osx () { [ $OS_TYPE = 'osx' ]; }
is_linux () { [ $OS_TYPE = 'solaris' ]; }
is_linux () { [ $OS_TYPE = 'linux' ]; }
is_bsd () { [ $OS_TYPE = 'bsd']; }
is_unknown () { [ $OS_TYPE = 'unknown' ]; }
@@ -28,4 +28,4 @@ else
make_temp_dir () {
mktemp -d
}
fi
fi

View File

@@ -4,6 +4,7 @@
LC_ALL=en_US.UTF-8
LANG=en_US.UTF-8
LANGUAGE=en_US.UTF-8
DIR=$(dirname "$0")
usage () {
echo " Usage: $0 [-d] [-h] [-v] [-c] [-m] [-r] [-i] [-C] [-u]"
@@ -90,11 +91,11 @@ while [ $# -gt 0 ]; do
done
# run
. ./lib/main.sh
. ${DIR}/lib/main.sh
if [ $opt_do_update = true ]; then
if ! command_exists git; then
echo "Error: --update requires `git` to be in the PATH"
echo "Error: --update requires 'git' to be in the PATH"
exit 1
fi
echo "Fetching latest version..."
@@ -125,7 +126,7 @@ fi
if [ -n "$opt_config_file" ]; then
verbose "Loading configuration file: $opt_config_file"
parse_config $opt_config_file
parse_config "$opt_config_file"
if [ $? -ne 0 ]; then
exit 1
fi
@@ -162,4 +163,4 @@ verbose "Using reporter: $__REPORTER"
echo "metrics.sh started with PID: $$"
verbose "Collecting metrics every $INTERVAL second(s)"
main_collect
main_collect

View File

@@ -11,6 +11,11 @@ defaults () {
}
start () {
if ! command_exists iostat; then
echo "Warning: disk_io requires the command 'iostat' to be available"
return 1
fi
readonly fifo=$TEMP_DIR/$(unique_id)_disk_io
mkfifo $fifo

View File

@@ -13,11 +13,11 @@ if is_osx; then
}
else
collect () {
report $(free | awk '/buffers\/cache/ {
printf "%.1f", 100 - $4 / ($3 + $4) * 100.0 }')
report $(free | awk '/Mem:/ {
printf "%.1f", 100 - $4 / ($3 + $4) * 100}')
}
fi
docs () {
echo "Percentage of used memory."
}
}

View File

@@ -13,28 +13,19 @@ start () {
fi
if [ "$INFLUXDB_SEND_HOSTNAME" = true ]; then
__influxdb_columns="[\"value\",\"host\"]"
__influxdb_hostname=$(hostname)
else
__influxdb_columns="[\"value\"]"
__influxdb_hostname="host=$(hostname)"
fi
}
report () {
local metric=$1
local value=$2
local points
if [ "$INFLUXDB_SEND_HOSTNAME" = true ]; then
points="[$value,\"$__influxdb_hostname\"]"
else
points="[$value]"
fi
local data="[{\"name\":\"$metric\",\"columns\":$__influxdb_columns,\"points\":[$points]}]"
curl -s -X POST $INFLUXDB_API_ENDPOINT -d $data
local data="$metric,$__influxdb_hostname value=$value"
curl -s -X POST $INFLUXDB_API_ENDPOINT --data-binary "$data"
}
docs () {
echo "Send data to InfluxDB."
echo "INFLUXDB_API_ENDPOINT=$INFLUXDB_API_ENDPOINT"
echo "INFLUXDB_SEND_HOSTNAME=$INFLUXDB_SEND_HOSTNAME"
}
}

View File

@@ -0,0 +1,19 @@
#!/bin/sh
start () {
if [ -z $LOGENTRIES_TOKEN ]; then
echo "Error: logentries.com requires \$LOGENTRIES_TOKEN to be specified"
return 1
fi
}
report () {
local metric=$1 # the name of the metric, e.g. "cpu", "cpu_alias", "cpu.foo"
local value=$2 # int or float
echo "$LOGENTRIES_TOKEN $metric=$value" | nc data.logentries.com 10000
}
docs () {
echo "Send data to Logentries.com using token TCP (https://docs.logentries.com/docs/input-token)"
echo "LOGENTRIES_TOKEN=$LOGENTRIES_TOKEN"
}

38
reporters/udp.sh Normal file
View File

@@ -0,0 +1,38 @@
#!/bin/sh
defaults () {
if [ -z $UDP_HOST ]; then
UDP_HOST="127.0.0.1"
fi
if [ -z $UDP_DELIMITER ]; then
UDP_DELIMITER="="
fi
}
start () {
if [ -z $UDP_PORT ]; then
echo "Error: udp requires \$UDP_PORT to be specified"
return 1
fi
if [ -n "$UDP_PREFIX" ]; then
prefix="$UDP_PREFIX."
fi
if [ -n "$UDP_DELIMITER" ]; then
delimiter="$UDP_DELIMITER"
fi
}
report () {
local metric=$1
local value=$2
echo "$prefix$metric$delimiter$value" | nc -u -w0 $UDP_HOST $UDP_PORT
}
docs () {
echo "Send data to any service using UDP."
echo "UDP_HOST=$UDP_HOST"
echo "UDP_PORT=$UDP_PORT"
echo "UDP_PREFIX=$UDP_PREFIX"
echo "UDP_DELIMITER=\"$UDP_DELIMITER\""
}

40
systemd/README.md Normal file
View File

@@ -0,0 +1,40 @@
# Running metrics.sh as a systemd service on Linux
Run the following commands as root:
```sh
# Install metrics.sh at /opt/metrics.sh
$ mkdir /opt; cd /opt
$ git clone https://github.com/pstadler/metrics.sh.git
$ cd metrics.sh
# Install the service
$ cp -p $PWD/systemd/metrics.sh.service /etc/systemd/system/metrics.sh.service
# Create a config file
$ mkdir /etc/metrics.sh && chmod 600 /etc/metrics.sh
$ ./metrics.sh -C > /etc/metrics.sh/metrics.ini
# At this point you should edit your config file at
# /etc/metrics.sh/metrics.ini
# Reload systemd daemon
$ systemctl daemon-reload
# Start service
$ systemctl start metrics.sh.service
# If run with the default configuration where reporter is 'stdout', metrics
# will be written to the journal. See the log using `journalctl -u metrics.sh`
# or follow it with:
$ journalctl -f -u metrics.sh
# Stop service
$ systemctl stop metrics.sh.service
# Check service status
$ systemctl status metrics.sh.service
# Automatically start service when booting and stop when shutting down
$ systemctl enable metrics.sh.service
# Disable automatic starting/stopping
$ systemctl disable metrics.sh.service
```

View File

@@ -0,0 +1,11 @@
[Unit]
Description=Controls the metrics daemon "metrics.sh"
Documentation=https://github.com/pstadler/metrics.sh
After=network.target
[Service]
ExecStart=/opt/metrics.sh/metrics.sh -c /etc/metrics.sh/metrics.ini
Restart=always
[Install]
WantedBy=multi-user.target