-#!/bin/sh
+#!/bin/bash
+
+# default time function
+now_ms=
+current_time_ms() {
+ now_ms="$(date +'%s')000"
+}
# default sleep function
+LOOPSLEEPMS_LASTWORK=0
loopsleepms() {
+ [ "$1" = "tellwork" ] && shift
sleep $1
}
+
# if found and included, this file overwrites loopsleepms()
# with a high resolution timer function for precise looping.
-. "`dirname $0`/loopsleepms.sh.inc"
+. "$NETDATA_PLUGINS_DIR/loopsleepms.sh.inc"
# check if we have a valid number for interval
t=$1
-sleep_time=$(( t + 1 - 1 ))
-if [ "$sleep_time" -eq 0 ]
+sleep_time=$((t))
+[ $((sleep_time)) -lt 1 ] && $NETDATA_UPDATE_EVERY
+[ $((sleep_time)) -lt 1 ] && sleep_time=1
+
+tc_cmd="$(which tc)"
+if [ -z "$tc_cmd" ]
then
- sleep_time=1
+ echo >&2 "tc: Cannot find a 'tc' command in this system."
+ exit 1
fi
devices=
echo "BEGIN $x"
- /sbin/tc -s class show dev $x
+ $tc_cmd -s class show dev $x
# check FireQOS names for classes
if [ ! -z "$fix_names" -a -f /var/run/fireqos/ifaces/$x ]
then
- name="`cat /var/run/fireqos/ifaces/$x`"
+ name="$(cat /var/run/fireqos/ifaces/$x)"
echo "SETDEVICENAME $name"
interface_classes=
. /var/run/fireqos/$name.conf
for n in $interface_classes_monitor
do
- setclassname `echo $n | tr '|' ' '`
+ setclassname $(echo $n | tr '|' ' ')
done
echo "SETDEVICEGROUP $interface_dev"
all_devices() {
cat /proc/net/dev | grep ":" | cut -d ':' -f 1 | while read dev
do
- l=`/sbin/tc class show dev $dev | wc -l`
+ l=$($tc_cmd class show dev $dev | wc -l)
[ $l -ne 0 ] && echo $dev
done
}
then
c=1
fix_names="YES"
- devices="`all_devices`"
+ devices="$( all_devices )"
fi
for d in $devices
show_tc $d
done
- loopsleepms $sleep_time
+ echo "WORKTIME $LOOPSLEEPMS_LASTWORK"
+
+ loopsleepms tellwork $sleep_time
- test $gc -gt $exit_after && exit 0
+ [ $gc -gt $exit_after ] && exit 0
done
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
+#include <sys/resource.h>
#include "avl.h"
#include "log.h"
if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
error("Cannot set pthread cancel state to ENABLE.");
+ struct rusage thread;
+ RRDSET *stcpu = NULL, *sttime = NULL;
+
char buffer[TC_LINE_MAX+1] = "";
char *words[MAX_WORDS] = { NULL };
uint32_t SETDEVICENAME_HASH = simple_hash("SETDEVICENAME");
uint32_t SETDEVICEGROUP_HASH = simple_hash("SETDEVICEGROUP");
uint32_t SETCLASSNAME_HASH = simple_hash("SETCLASSNAME");
+ uint32_t WORKTIME_HASH = simple_hash("WORKTIME");
#ifdef DETACH_PLUGINS_FROM_NETDATA
uint32_t MYPID_HASH = simple_hash("MYPID");
#endif
char *path = words[2];
if(id && *id && path && *path) tc_device_set_class_name(device, id, path);
}
+ else if(first_hash == WORKTIME_HASH && strcmp(words[0], "WORKTIME") == 0) {
+ // debug(D_TC_LOOP, "WORKTIME line '%s' '%s'", words[1], words[2]);
+ getrusage(RUSAGE_THREAD, &thread);
+
+ if(!stcpu) stcpu = rrdset_find("netdata.plugin_tc_cpu");
+ if(!stcpu) {
+ stcpu = rrdset_create("netdata", "plugin_tc_cpu", NULL, "netdata", "NetData TC CPU usage", "milliseconds/s", 10000, rrd_update_every, RRDSET_TYPE_STACKED);
+ rrddim_add(stcpu, "user", NULL, 1, 1000 * rrd_update_every, RRDDIM_INCREMENTAL);
+ rrddim_add(stcpu, "system", NULL, 1, 1000 * rrd_update_every, RRDDIM_INCREMENTAL);
+ }
+ else rrdset_next(stcpu);
+
+ rrddim_set(stcpu, "user" , thread.ru_utime.tv_sec * 1000000ULL + thread.ru_utime.tv_usec);
+ rrddim_set(stcpu, "system", thread.ru_stime.tv_sec * 1000000ULL + thread.ru_stime.tv_usec);
+ rrdset_done(stcpu);
+
+ if(!sttime) stcpu = rrdset_find("netdata.plugin_tc_time");
+ if(!sttime) {
+ sttime = rrdset_create("netdata", "plugin_tc_time", NULL, "netdata", "NetData TC script execution", "milliseconds/run", 10001, rrd_update_every, RRDSET_TYPE_AREA);
+ rrddim_add(sttime, "run_time", "run time", 1, 1, RRDDIM_ABSOLUTE);
+ }
+ else rrdset_next(sttime);
+
+ rrddim_set(sttime, "run_time", atoll(words[1]));
+ rrdset_done(sttime);
+
+ }
#ifdef DETACH_PLUGINS_FROM_NETDATA
else if(first_hash == MYPID_HASH && (strcmp(words[0], "MYPID") == 0)) {
// debug(D_TC_LOOP, "MYPID line '%s'", words[1]);