src/avl.h
src/backends.c
src/backends.h
+ src/clocks.c
+ src/clocks.h
src/common.c
src/common.h
src/daemon.c
# This file is a BASH script itself.
#
#
-###############################################################################
+#------------------------------------------------------------------------------
# proxy configuration
#
# If you need to send curl based notifications (pushover, pushbullet, slack,
#export https_proxy="http://10.0.0.1:3128/"
-###############################################################################
+#------------------------------------------------------------------------------
# notifications images
#
# Images in notifications need to be downloaded from an Internet facing site.
#images_base_url="http://my.public.netdata.server:19999"
-###############################################################################
+#------------------------------------------------------------------------------
# external commands
# The full path to the sendmail command.
curl=""
-###############################################################################
+#------------------------------------------------------------------------------
# NOTE ABOUT RECIPIENTS
#
# When you define recipients (all types):
# This works for all notification methods (including the default recipients).
-###############################################################################
+#------------------------------------------------------------------------------
# email global notification options
# multiple recipients can be given like this:
# to receive only critical alarms, set it to "root|critical"
-###############################################################################
+#------------------------------------------------------------------------------
# pushover (pushover.net) global notification options
# multiple recipients can be given like this:
DEFAULT_RECIPIENT_PUSHOVER=""
-###############################################################################
+#------------------------------------------------------------------------------
# pushbullet (pushbullet.com) push notification options
# multiple recipients can be given like this:
PUSHBULLET_ACCESS_TOKEN=""
DEFAULT_RECIPIENT_PUSHBULLET=""
-###############################################################################
+#------------------------------------------------------------------------------
# Twilio (twilio.com) SMS options
# multiple recipients can be given like this:
TWILIO_NUMBER=""
DEFAULT_RECIPIENT_TWILIO=""
-###############################################################################
+#------------------------------------------------------------------------------
# telegram (telegram.org) global notification options
# To get your chat ID send the command /my_id to telegram bot @get_id.
DEFAULT_RECIPIENT_TELEGRAM=""
-###############################################################################
+#------------------------------------------------------------------------------
# slack (slack.com) global notification options
# multiple recipients can be given like this:
DEFAULT_RECIPIENT_SLACK=""
+#------------------------------------------------------------------------------
+# kafka notification options
+
+# enable/disable sending kafka notifications
+SEND_KAFKA="YES"
+
+# The URL to POST kafka alarm data to. It should be the full URL.
+KAFKA_URL=""
+
+# The IP to be used in the kafka message as the sender.
+KAFKA_SENDER_IP=""
+
+
###############################################################################
# RECIPIENTS PER ROLE
name : 'local'
# user : ''
# pass : ''
- socket : '/var/lib/mysql/mysql.sock'
+ socket : '/var/run/mysqld/mysql.sock'
socket3:
+ name : 'local'
+ # user : ''
+ # pass : ''
+ socket : '/var/lib/mysql/mysql.sock'
+
+socket4:
name : 'local'
# user : ''
# pass : ''
name : 'local'
user : 'root'
# pass : ''
- socket : '/var/lib/mysql/mysql.sock'
+ socket : '/var/run/mysqld/mysql.sock'
socket3_root:
+ name : 'local'
+ user : 'root'
+ # pass : ''
+ socket : '/var/lib/mysql/mysql.sock'
+
+socket4_root:
name : 'local'
user : 'root'
# pass : ''
['2ad55a5d1e885cf142849a78d4b00401']='health.d/net.conf'
['2bbbebf52f84fd27fbefecd2a8a8076f']='health.d/memcached.conf'
['2d1d7498c72f4245cf32902c2b7e71e0']='health.d/entropy.conf'
+ ['2f3a8e33df83f14e0af8ca2465697215']='python.d/exim.conf'
['2f4a85fedecce1bf425fa1039f6b021e']='apps_groups.conf'
['2fa8fb929fd597f2ab97b6efc540a043']='health_alarm_notify.conf'
['312b4b8e2805e19cf9be554b319567d6']='health.d/softnet.conf'
['7a21ccc76be2968ce5d0b52ec1166788']='python.d.conf'
['7a985528cc9176564640001aa73e3492']='health.d/nginx.conf'
['7aa209fa287c95b3ca04c23681b40770']='health.d/disks.conf'
+ ['7bac18d8d5ff8f117be8d489a21c0c65']='python.d/mysql.conf'
['7cf6402b51e5070f2be3ad6fe059ff89']='charts.d.conf'
['7d8bd884ec26cb35d16c4fc05f969799']='python.d/squid.conf'
['7deb236ec68a512b9bdd18e6a51d76f7']='python.d/mysql.conf'
['eb5168f0b516bc982aac45e59da6e52e']='health.d/nginx.conf'
['eb748d6fb69d11b0d29c5794657e206c']='health.d/qos.conf'
['ebd0612ccc5807524ebb2b647e3e56c9']='apps_groups.conf'
+ ['ec490e037c1e53daa44a55a941381d6d']='python.d/gunicorn_log.conf'
['ecd3aa97e2581f88eb466d6612690ef2']='charts.d/nginx.conf'
['ee5343881744e6a97e6ee5cdd329cfb8']='health.d/retroshare.conf'
['ef9916ea144878a9f37cbb6b1b29da10']='health.d/squid.conf'
PKG_PROG_PKG_CONFIG
AC_USE_SYSTEM_EXTENSIONS
AC_CHECK_FUNCS_ONCE(accept4)
+AC_CHECK_TYPES([struct timespec, clockid_t], [], [], [[#include <time.h>]])
+AC_SEARCH_LIBS([clock_gettime], [rt posix4])
+AC_CHECK_FUNCS([clock_gettime])
# Check system type
case "$host_os" in
# - pushover.net notifications
# - pushbullet.com push notifications by Tiago Peralta @tperalta82 PR #1070
# - telegram.org notifications by @hashworks PR #1002
-#
+# - twilio.com notifications by Levi Blaney @shadycuz PR #1211
+# - kafka notifications
# -----------------------------------------------------------------------------
# testing notifications
SEND_TELEGRAM="YES"
SEND_EMAIL="YES"
SEND_PUSHBULLET="YES"
+SEND_KAFKA="YES"
# slack configs
SLACK_WEBHOOK_URL=
DEFAULT_RECIPIENT_TELEGRAM=
declare -A role_recipients_telegram=()
+# kafka configs
+KAFKA_URL=
+KAFKA_SENDER_IP=
+
# email configs
DEFAULT_RECIPIENT_EMAIL="root"
declare -A role_recipients_email=()
[ -z "${PUSHOVER_APP_TOKEN}" ] && SEND_PUSHOVER="NO"
# check pushbullet
-[ -z "${DEFAULT_RECIPIENT_PUSHBULLET}" ] && SEND_PUSHBULLET="NO"
+[ -z "${PUSHBULLET_ACCESS_TOKEN}" ] && SEND_PUSHBULLET="NO"
# check twilio
-[ -z "${DEFAULT_RECIPIENT_TWILIO}" ] && SEND_TWILIO="NO"
+[ -z "${TWILIO_ACCOUNT_TOKEN}" -o -z "${TWILIO_ACCOUNT_SID}" -o -z "${TWILIO_NUMBER}" ] && SEND_TWILIO="NO"
# check telegram
[ -z "${TELEGRAM_BOT_TOKEN}" ] && SEND_TELEGRAM="NO"
-if [ \( "${SEND_PUSHOVER}" = "YES" -o "${SEND_SLACK}" = "YES" -o "${SEND_TWILIO}" = "YES" -o "${SEND_TELEGRAM}" = "YES" -o "${SEND_PUSHBULLET}" = "YES" \) -a -z "${curl}" ]
+# check kafka
+[ -z "${KAFKA_URL}" -o -z "${KAFKA_SENDER_IP}" ] && SEND_KAFKA="NO"
+
+# if we need curl, check for the curl command
+if [ \( "${SEND_PUSHOVER}" = "YES" -o "${SEND_SLACK}" = "YES" -o "${SEND_TWILIO}" = "YES" -o "${SEND_TELEGRAM}" = "YES" -o "${SEND_PUSHBULLET}" = "YES" -o "${SEND_KAFKA}" = "YES" \) -a -z "${curl}" ]
then
curl="$(which curl 2>/dev/null || command -v curl 2>/dev/null)"
if [ -z "${curl}" ]
then
+ # no curl available
+ # disable all curl based methods
SEND_PUSHOVER="NO"
SEND_PUSHBULLET="NO"
SEND_TELEGRAM="NO"
SEND_SLACK="NO"
SEND_TWILIO="NO"
+ SEND_KAFKA="NO"
fi
fi
+# if we need sendmail, check for the sendmail command
if [ "${SEND_EMAIL}" = "YES" -a -z "${sendmail}" ]
then
sendmail="$(which sendmail 2>/dev/null || command -v sendmail 2>/dev/null)"
fi
# check that we have at least a method enabled
-if [ "${SEND_EMAIL}" != "YES" -a "${SEND_PUSHOVER}" != "YES" -a "${SEND_TELEGRAM}" != "YES" -a "${SEND_SLACK}" != "YES" -a "${SEND_TWILIO}" != "YES" -a "${SEND_PUSHBULLET}" != "YES" ]
+if [ "${SEND_EMAIL}" != "YES" \
+ -a "${SEND_PUSHOVER}" != "YES" \
+ -a "${SEND_TELEGRAM}" != "YES" \
+ -a "${SEND_SLACK}" != "YES" \
+ -a "${SEND_TWILIO}" != "YES" \
+ -a "${SEND_PUSHBULLET}" != "YES" \
+ -a "${SEND_KAFKA}" != "YES" \
+ ]
then
fatal "All notification methods are disabled. Not sending notification to '${role}' for '${name}' = '${value}' of chart '${chart}' for status '${status}'."
fi
# -----------------------------------------------------------------------------
-# get the system hostname
+# find a suitable hostname to use, if netdata did not supply a hostname
[ -z "${host}" ] && host="${NETDATA_HOSTNAME}"
[ -z "${host}" ] && host="${NETDATA_REGISTRY_HOSTNAME}"
[ -z "${date}" ] && date="$(date 2>/dev/null)"
# -----------------------------------------------------------------------------
-# URL encode a string
+# function to URL encode a string
urlencode() {
local string="${1}" strlen encoded pos c o
}
# -----------------------------------------------------------------------------
-# convert a duration in seconds, to a human readable duration
+# function to convert a duration in seconds, to a human readable duration
# using DAYS, MINUTES, SECONDS
duration4human() {
return 1
}
+# -----------------------------------------------------------------------------
+# kafka sender
+
+send_kafka() {
+ local httpcode sent=0
+ if [ "${SEND_KAFKA}" = "YES" ]
+ then
+ httpcode=$(${curl} -X POST --write-out %{http_code} --silent --output /dev/null \
+ --data "{host_ip:\"${KAFKA_SENDER_IP}\",when:${when},name:\"${name}\",chart:\"${chart}\",family:\"${family}\",status:\"${status}\",old_status:\"${old_status}\",value:${value},old_value:${old_value},duration:${duration},non_clear_duration:${non_clear_duration},units:\"${units}\",info:\"${info}\"}" \
+ "${KAFKA_URL}")
+
+ if [ "${httpcode}" == "204" ]
+ then
+ info "sent kafka data for: ${host} ${chart}.${name} is ${status} and ip '${KAFKA_SENDER_IP}'"
+ sent=$((sent + 1))
+ else
+ error "failed to send kafka data for: ${host} ${chart}.${name} is ${status} and ip '${KAFKA_SENDER_IP}' with HTTP error code ${httpcode}."
+ fi
+
+ [ ${sent} -gt 0 ] && return 0
+ fi
+
+ return 1
+}
+
# -----------------------------------------------------------------------------
# twilio sender
SENT_TELEGRAM=$?
+
+# -----------------------------------------------------------------------------
+# send the kafka message
+
+send_kafka
+SENT_KAFKA=$?
+
+
# -----------------------------------------------------------------------------
# send the email
# -----------------------------------------------------------------------------
# let netdata know
-# we did send something
-[ ${SENT_EMAIL} -eq 0 -o ${SENT_PUSHOVER} -eq 0 -o ${SENT_TELEGRAM} -eq 0 -o ${SENT_SLACK} -eq 0 -o ${SENT_TWILIO} -eq 0 -o ${SENT_PUSHBULLET} -eq 0 ] && exit 0
+if [ ${SENT_EMAIL} -eq 0 \
+ -o ${SENT_PUSHOVER} -eq 0 \
+ -o ${SENT_TELEGRAM} -eq 0 \
+ -o ${SENT_SLACK} -eq 0 \
+ -o ${SENT_TWILIO} -eq 0 \
+ -o ${SENT_PUSHBULLET} -eq 0 \
+ -o ${SENT_KAFKA} -eq 0 \
+ ]
+ then
+ # we did send something
+ exit 0
+fi
# we did not send anything
exit 1
appconfig.c appconfig.h \
avl.c avl.h \
backends.c backends.h \
+ clocks.c clocks.h \
common.c common.h \
daemon.c daemon.h \
dictionary.c dictionary.h \
apps_plugin_SOURCES = \
apps_plugin.c \
avl.c avl.h \
+ clocks.c clocks.h \
common.c common.h \
log.c log.h \
procfile.c procfile.h \
if(unlikely(!ff)) goto cleanup;
p->last_stat_collected_usec = p->stat_collected_usec;
- p->stat_collected_usec = time_usec();
+ p->stat_collected_usec = now_realtime_usec();
file_counter++;
// p->pid = atol(procfile_lineword(ff, 0, 0+i));
last = p->minflt_raw;
p->minflt_raw = strtoull(procfile_lineword(ff, 0, 9), NULL, 10);
- p->minflt = (p->minflt_raw - last) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
+ p->minflt = (p->minflt_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
last = p->cminflt_raw;
p->cminflt_raw = strtoull(procfile_lineword(ff, 0, 10), NULL, 10);
- p->cminflt = (p->cminflt_raw - last) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
+ p->cminflt = (p->cminflt_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
last = p->majflt_raw;
p->majflt_raw = strtoull(procfile_lineword(ff, 0, 11), NULL, 10);
- p->majflt = (p->majflt_raw - last) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
+ p->majflt = (p->majflt_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
last = p->cmajflt_raw;
p->cmajflt_raw = strtoull(procfile_lineword(ff, 0, 12), NULL, 10);
- p->cmajflt = (p->cmajflt_raw - last) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
+ p->cmajflt = (p->cmajflt_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
last = p->utime_raw;
p->utime_raw = strtoull(procfile_lineword(ff, 0, 13), NULL, 10);
- p->utime = (p->utime_raw - last) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
+ p->utime = (p->utime_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
last = p->stime_raw;
p->stime_raw = strtoull(procfile_lineword(ff, 0, 14), NULL, 10);
- p->stime = (p->stime_raw - last) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
+ p->stime = (p->stime_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
last = p->cutime_raw;
p->cutime_raw = strtoull(procfile_lineword(ff, 0, 15), NULL, 10);
- p->cutime = (p->cutime_raw - last) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
+ p->cutime = (p->cutime_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
last = p->cstime_raw;
p->cstime_raw = strtoull(procfile_lineword(ff, 0, 16), NULL, 10);
- p->cstime = (p->cstime_raw - last) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
+ p->cstime = (p->cstime_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
// p->priority = strtoull(procfile_lineword(ff, 0, 17), NULL, 10);
// p->nice = strtoull(procfile_lineword(ff, 0, 18), NULL, 10);
if(enable_guest_charts) {
last = p->gtime_raw;
p->gtime_raw = strtoull(procfile_lineword(ff, 0, 42), NULL, 10);
- p->gtime = (p->gtime_raw - last) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
+ p->gtime = (p->gtime_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
last = p->cgtime_raw;
p->cgtime_raw = strtoull(procfile_lineword(ff, 0, 43), NULL, 10);
- p->cgtime = (p->cgtime_raw - last) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
+ p->cgtime = (p->cgtime_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
if (show_guest_time || p->gtime || p->cgtime) {
p->utime -= (p->utime >= p->gtime) ? p->gtime : p->utime;
file_counter++;
p->last_io_collected_usec = p->io_collected_usec;
- p->io_collected_usec = time_usec();
+ p->io_collected_usec = now_realtime_usec();
unsigned long long last;
last = p->io_logical_bytes_read_raw;
p->io_logical_bytes_read_raw = strtoull(procfile_lineword(ff, 0, 1), NULL, 10);
- p->io_logical_bytes_read = (p->io_logical_bytes_read_raw - last) * (1000000ULL * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
+ p->io_logical_bytes_read = (p->io_logical_bytes_read_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
last = p->io_logical_bytes_written_raw;
p->io_logical_bytes_written_raw = strtoull(procfile_lineword(ff, 1, 1), NULL, 10);
- p->io_logical_bytes_written = (p->io_logical_bytes_written_raw - last) * (1000000ULL * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
+ p->io_logical_bytes_written = (p->io_logical_bytes_written_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
// last = p->io_read_calls_raw;
// p->io_read_calls_raw = strtoull(procfile_lineword(ff, 2, 1), NULL, 10);
- // p->io_read_calls = (p->io_read_calls_raw - last) * (1000000ULL * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
+ // p->io_read_calls = (p->io_read_calls_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
// last = p->io_write_calls_raw;
// p->io_write_calls_raw = strtoull(procfile_lineword(ff, 3, 1), NULL, 10);
- // p->io_write_calls = (p->io_write_calls_raw - last) * (1000000ULL * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
+ // p->io_write_calls = (p->io_write_calls_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
last = p->io_storage_bytes_read_raw;
p->io_storage_bytes_read_raw = strtoull(procfile_lineword(ff, 4, 1), NULL, 10);
- p->io_storage_bytes_read = (p->io_storage_bytes_read_raw - last) * (1000000ULL * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
+ p->io_storage_bytes_read = (p->io_storage_bytes_read_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
last = p->io_storage_bytes_written_raw;
p->io_storage_bytes_written_raw = strtoull(procfile_lineword(ff, 5, 1), NULL, 10);
- p->io_storage_bytes_written = (p->io_storage_bytes_written_raw - last) * (1000000ULL * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
+ p->io_storage_bytes_written = (p->io_storage_bytes_written_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
// last = p->io_cancelled_write_bytes_raw;
// p->io_cancelled_write_bytes_raw = strtoull(procfile_lineword(ff, 6, 1), NULL, 10);
- // p->io_cancelled_write_bytes = (p->io_cancelled_write_bytes_raw - last) * (1000000ULL * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
+ // p->io_cancelled_write_bytes = (p->io_cancelled_write_bytes_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
if(unlikely(global_iterations_counter == 1)) {
p->io_logical_bytes_read = 0;
int read_proc_stat() {
static char filename[FILENAME_MAX + 1] = "";
static procfile *ff = NULL;
- static unsigned long long utime_raw = 0, stime_raw = 0, gtime_raw = 0, gntime_raw = 0, ntime_raw = 0, collected_usec = 0, last_collected_usec = 0;
+ static unsigned long long utime_raw = 0, stime_raw = 0, gtime_raw = 0, gntime_raw = 0, ntime_raw = 0;
+ static usec_t collected_usec = 0, last_collected_usec = 0;
if(unlikely(!ff)) {
snprintfz(filename, FILENAME_MAX, "%s/proc/stat", global_host_prefix);
if(unlikely(!ff)) goto cleanup;
last_collected_usec = collected_usec;
- collected_usec = time_usec();
+ collected_usec = now_realtime_usec();
file_counter++;
last = utime_raw;
utime_raw = strtoull(procfile_lineword(ff, 0, 1), NULL, 10);
- global_utime = (utime_raw - last) * (1000000ULL * RATES_DETAIL) / (collected_usec - last_collected_usec);
+ global_utime = (utime_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (collected_usec - last_collected_usec);
// nice time, on user time
last = ntime_raw;
ntime_raw = strtoull(procfile_lineword(ff, 0, 2), NULL, 10);
- global_utime += (ntime_raw - last) * (1000000ULL * RATES_DETAIL) / (collected_usec - last_collected_usec);
+ global_utime += (ntime_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (collected_usec - last_collected_usec);
last = stime_raw;
stime_raw = strtoull(procfile_lineword(ff, 0, 3), NULL, 10);
- global_stime = (stime_raw - last) * (1000000ULL * RATES_DETAIL) / (collected_usec - last_collected_usec);
+ global_stime = (stime_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (collected_usec - last_collected_usec);
last = gtime_raw;
gtime_raw = strtoull(procfile_lineword(ff, 0, 10), NULL, 10);
- global_gtime = (gtime_raw - last) * (1000000ULL * RATES_DETAIL) / (collected_usec - last_collected_usec);
+ global_gtime = (gtime_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (collected_usec - last_collected_usec);
if(enable_guest_charts) {
// guest nice time, on guest time
last = gntime_raw;
gntime_raw = strtoull(procfile_lineword(ff, 0, 11), NULL, 10);
- global_gtime += (gntime_raw - last) * (1000000ULL * RATES_DETAIL) / (collected_usec - last_collected_usec);
+ global_gtime += (gntime_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (collected_usec - last_collected_usec);
// remove guest time from user time
global_utime -= (global_utime > global_gtime) ? global_gtime : global_utime;
);
}
- p->utime_raw = utime * (p->stat_collected_usec - p->last_stat_collected_usec) / (1000000ULL * RATES_DETAIL);
- p->stime_raw = stime * (p->stat_collected_usec - p->last_stat_collected_usec) / (1000000ULL * RATES_DETAIL);
- p->gtime_raw = gtime * (p->stat_collected_usec - p->last_stat_collected_usec) / (1000000ULL * RATES_DETAIL);
- p->minflt_raw = minflt * (p->stat_collected_usec - p->last_stat_collected_usec) / (1000000ULL * RATES_DETAIL);
- p->majflt_raw = majflt * (p->stat_collected_usec - p->last_stat_collected_usec) / (1000000ULL * RATES_DETAIL);
+ p->utime_raw = utime * (p->stat_collected_usec - p->last_stat_collected_usec) / (USEC_PER_SEC * RATES_DETAIL);
+ p->stime_raw = stime * (p->stat_collected_usec - p->last_stat_collected_usec) / (USEC_PER_SEC * RATES_DETAIL);
+ p->gtime_raw = gtime * (p->stat_collected_usec - p->last_stat_collected_usec) / (USEC_PER_SEC * RATES_DETAIL);
+ p->minflt_raw = minflt * (p->stat_collected_usec - p->last_stat_collected_usec) / (USEC_PER_SEC * RATES_DETAIL);
+ p->majflt_raw = majflt * (p->stat_collected_usec - p->last_stat_collected_usec) / (USEC_PER_SEC * RATES_DETAIL);
p->cutime_raw = p->cstime_raw = p->cgtime_raw = p->cminflt_raw = p->cmajflt_raw = 0;
if(unlikely(debug))
double utime_fix_ratio = 1.0, stime_fix_ratio = 1.0, gtime_fix_ratio = 1.0, cutime_fix_ratio = 1.0, cstime_fix_ratio = 1.0, cgtime_fix_ratio = 1.0;
double minflt_fix_ratio = 1.0, majflt_fix_ratio = 1.0, cminflt_fix_ratio = 1.0, cmajflt_fix_ratio = 1.0;
-unsigned long long send_resource_usage_to_netdata() {
+usec_t send_resource_usage_to_netdata() {
static struct timeval last = { 0, 0 };
static struct rusage me_last;
struct timeval now;
struct rusage me;
- unsigned long long usec;
- unsigned long long cpuuser;
- unsigned long long cpusyst;
+ usec_t usec;
+ usec_t cpuuser;
+ usec_t cpusyst;
if(!last.tv_sec) {
- gettimeofday(&last, NULL);
+ now_realtime_timeval(&last);
getrusage(RUSAGE_SELF, &me_last);
// the first time, give a zero to allow
// netdata calibrate to the current time
- // usec = update_every * 1000000ULL;
+ // usec = update_every * USEC_PER_SEC;
usec = 0ULL;
cpuuser = 0;
cpusyst = 0;
}
else {
- gettimeofday(&now, NULL);
+ now_realtime_timeval(&now);
getrusage(RUSAGE_SELF, &me);
- usec = usec_dt(&now, &last);
- cpuuser = me.ru_utime.tv_sec * 1000000ULL + me.ru_utime.tv_usec;
- cpusyst = me.ru_stime.tv_sec * 1000000ULL + me.ru_stime.tv_usec;
+ usec = dt_usec(&now, &last);
+ cpuuser = me.ru_utime.tv_sec * USEC_PER_SEC + me.ru_utime.tv_usec;
+ cpusyst = me.ru_stime.tv_sec * USEC_PER_SEC + me.ru_stime.tv_usec;
memmove(&last, &now, sizeof(struct timeval));
memmove(&me_last, &me, sizeof(struct rusage));
}
}
-void send_collected_data_to_netdata(struct target *root, const char *type, unsigned long long usec) {
+void send_collected_data_to_netdata(struct target *root, const char *type, usec_t usec) {
struct target *w;
send_BEGIN(type, "cpu", usec);
procfile_adaptive_initial_allocation = 1;
- time_t started_t = time(NULL);
+ time_t started_t = now_realtime_sec();
get_system_HZ();
get_system_pid_max();
get_system_cpus();
, RATES_DETAIL
);
- unsigned long long step = update_every * 1000000ULL;
+ usec_t step = update_every * USEC_PER_SEC;
global_iterations_counter = 1;
for(;1; global_iterations_counter++) {
- unsigned long long now = time_usec();
- unsigned long long next = now - (now % step) + step;
+ usec_t now = now_realtime_usec();
+ usec_t next = now - (now % step) + step;
while(now < next) {
sleep_usec(next - now);
- now = time_usec();
+ now = now_realtime_usec();
}
if(!collect_data_for_all_processes_from_proc()) {
calculate_netdata_statistics();
normalize_data(apps_groups_root_target);
- unsigned long long dt = send_resource_usage_to_netdata();
+ usec_t dt = send_resource_usage_to_netdata();
// this is smart enough to show only newly added apps, when needed
send_charts_updates_to_netdata(apps_groups_root_target, "apps", "Apps");
if(unlikely(debug))
fprintf(stderr, "apps.plugin: done Loop No %llu\n", global_iterations_counter);
- time_t current_t = time(NULL);
+ time_t current_t = now_realtime_sec();
// restart check (14400 seconds)
if(current_t - started_t > 14400) exit(0);
info("BACKEND configured ('%s' on '%s' sending '%s' data, every %d seconds, as host '%s', with prefix '%s')", type, destination, source, frequency, hostname, prefix);
- unsigned long long step_ut = frequency * 1000000ULL;
- unsigned long long random_ut = time_usec() % (step_ut / 2);
- time_t before = (time_t)((time_usec() - step_ut) / 10000000ULL);
+ usec_t step_ut = frequency * USEC_PER_SEC;
+ usec_t random_ut = now_realtime_usec() % (step_ut / 2);
+ time_t before = (time_t)((now_realtime_usec() - step_ut) / USEC_PER_SEC);
time_t after = before;
int failures = 0;
// ------------------------------------------------------------------------
// wait for the next iteration point
- unsigned long long now_ut = time_usec();
- unsigned long long next_ut = now_ut - (now_ut % step_ut) + step_ut;
- before = (time_t)(next_ut / 1000000ULL);
+ usec_t now_ut = now_realtime_usec();
+ usec_t next_ut = now_ut - (now_ut % step_ut) + step_ut;
+ before = (time_t)(next_ut / USEC_PER_SEC);
// add a little delay (1/4 of the step) plus some randomness
next_ut += (step_ut / 4) + random_ut;
while(now_ut < next_ut) {
sleep_usec(next_ut - now_ut);
- now_ut = time_usec();
+ now_ut = now_realtime_usec();
}
// ------------------------------------------------------------------------
// connect to a backend server
if(unlikely(sock == -1)) {
- unsigned long long start_ut = time_usec();
+ usec_t start_ut = now_realtime_usec();
const char *s = destination;
while(*s) {
const char *e = s;
if(sock != -1) break;
s = e;
}
- chart_backend_latency += time_usec() - start_ut;
+ chart_backend_latency += now_realtime_usec() - start_ut;
}
if(unlikely(netdata_exit)) break;
if(likely(sock != -1)) {
size_t len = buffer_strlen(b);
- unsigned long long start_ut = time_usec();
+ usec_t start_ut = now_realtime_usec();
int flags = 0;
#ifdef MSG_NOSIGNAL
flags += MSG_NOSIGNAL;
#endif
ssize_t written = send(sock, buffer_tostring(b), len, flags);
- chart_backend_latency += time_usec() - start_ut;
+ chart_backend_latency += now_realtime_usec() - start_ut;
if(written != -1 && (size_t)written == len) {
// we sent the data successfully
chart_transmission_successes++;
--- /dev/null
+#include "common.h"
+
+#ifndef HAVE_CLOCK_GETTIME
+inline int clock_gettime(clockid_t clk_id, struct timespec *ts) {
+ struct timeval tv;
+ if(unlikely(gettimeofday(&tv, NULL) == -1))
+ return -1;
+ ts->tv_sec = tv.tv_sec;
+ ts->tv_nsec = tv.tv_usec * NSEC_PER_USEC;
+ return 0;
+}
+#endif
+
+inline time_t now_realtime_sec(void) {
+ struct timespec ts;
+ if(unlikely(clock_gettime(CLOCK_REALTIME, &ts) == -1))
+ return 0;
+ return ts.tv_sec;
+}
+
+inline int now_realtime_timeval(struct timeval *tv) {
+ struct timespec ts;
+ if(unlikely(clock_gettime(CLOCK_REALTIME, &ts) == -1))
+ return -1;
+ tv->tv_sec = ts.tv_sec;
+ tv->tv_usec = ts.tv_nsec / NSEC_PER_USEC;
+ return 0;
+}
+
+inline usec_t now_realtime_usec(void) {
+ struct timespec ts;
+ if(unlikely(clock_gettime(CLOCK_REALTIME, &ts) == -1))
+ return 0;
+ return (usec_t)ts.tv_sec * USEC_PER_SEC + ts.tv_nsec / NSEC_PER_USEC;
+}
+
+inline time_t now_monotonic_sec(void) {
+ struct timespec ts;
+ if(unlikely(clock_gettime(CLOCK_MONOTONIC, &ts) == -1))
+ return 0;
+ return ts.tv_sec;
+}
+
+inline usec_t now_monotonic_usec(void) {
+ struct timespec ts;
+ if(unlikely(clock_gettime(CLOCK_MONOTONIC, &ts) == -1))
+ return 0;
+ return (usec_t)ts.tv_sec * USEC_PER_SEC + ts.tv_nsec / NSEC_PER_USEC;
+}
+
+inline time_t now_boottime_sec(void) {
+ struct timespec ts;
+ if(unlikely(clock_gettime(CLOCK_BOOTTIME, &ts) == -1))
+ return 0;
+ return ts.tv_sec;
+}
+
+inline usec_t now_boottime_usec(void) {
+ struct timespec ts;
+ if(unlikely(clock_gettime(CLOCK_BOOTTIME, &ts) == -1))
+ return 0;
+ return (usec_t)ts.tv_sec * USEC_PER_SEC + ts.tv_nsec / NSEC_PER_USEC;
+}
+
+inline usec_t timeval_usec(struct timeval *tv) {
+ return (usec_t)tv->tv_sec * USEC_PER_SEC + tv->tv_usec;
+}
+
+inline usec_t dt_usec(struct timeval *now, struct timeval *old) {
+ usec_t ts1 = timeval_usec(now);
+ usec_t ts2 = timeval_usec(old);
+ return (ts1 > ts2) ? (ts1 - ts2) : (ts2 - ts1);
+}
--- /dev/null
+#ifndef NETDATA_CLOCKS_H
+#define NETDATA_CLOCKS_H 1
+
+#ifndef HAVE_STRUCT_TIMESPEC
+struct timespec {
+ time_t tv_sec; /* seconds */
+ long tv_nsec; /* nanoseconds */
+};
+#endif
+
+#ifndef HAVE_CLOCKID_T
+typedef int clockid_t;
+#endif
+
+#ifndef HAVE_CLOCK_GETTIME
+int clock_gettime(clockid_t clk_id, struct timespec *ts);
+#endif
+
+/* Linux value is as good as any other */
+#ifndef CLOCK_REALTIME
+#define CLOCK_REALTIME 0
+#endif
+
+#ifndef CLOCK_MONOTONIC
+/* fallback to CLOCK_REALTIME if not available */
+#define CLOCK_MONOTONIC CLOCK_REALTIME
+#endif
+
+#ifndef CLOCK_BOOTTIME
+/* fallback to CLOCK_MONOTONIC if not available */
+#define CLOCK_BOOTTIME CLOCK_MONOTONIC
+#endif
+
+typedef unsigned long long usec_t;
+
+#define NSEC_PER_SEC 1000000000ULL
+#define NSEC_PER_MSEC 1000000ULL
+#define NSEC_PER_USEC 1000ULL
+#define USEC_PER_SEC 1000000ULL
+
+#ifndef HAVE_CLOCK_GETTIME
+/* Fallback function for POSIX.1-2001 clock_gettime() function.
+ *
+ * We use a realtime clock from gettimeofday(), this will
+ * make systems without clock_gettime() support sensitive
+ * to time jumps or hibernation/suspend side effects.
+ */
+extern int clock_gettime(clockid_t clk_id, struct timespec *ts);
+#endif
+
+/* Fills struct timeval with time since EPOCH from real-time clock (i.e. wall-clock).
+ * - Hibernation/suspend time is included
+ * - adjtime()/NTP adjustments affect this clock
+ * Return 0 on succes, -1 else with errno set appropriately.
+ */
+extern int now_realtime_timeval(struct timeval *tv);
+
+/* Returns time since EPOCH from real-time clock (i.e. wall-clock).
+ * - Hibernation/suspend time is included
+ * - adjtime()/NTP adjustments affect this clock
+ */
+extern time_t now_realtime_sec(void);
+extern usec_t now_realtime_usec(void);
+
+/* Returns time from monotonic clock if available, real-time clock else.
+ * If monotonic clock is available:
+ * - hibernation/suspend time is not included
+ * - adjtime()/NTP adjusments affect this clock
+ * If monotonic clock is not available, this fallbacks to now_realtime().
+ */
+extern time_t now_monotonic_sec(void);
+extern usec_t now_monotonic_usec(void);
+
+/* Returns time from boottime clock if available,
+ * monotonic clock else if available, real-time clock else.
+ * If boottime clock is available:
+ * - hibernation/suspend time is included
+ * - adjtime()/NTP adjusments affect this clock
+ * If boottime clock is not available, this fallbacks to now_monotonic().
+ * If monotonic clock is not available, this fallbacks to now_realtime().
+ */
+extern time_t now_boottime_sec(void);
+extern usec_t now_boottime_usec(void);
+
+extern usec_t timeval_usec(struct timeval *ts);
+extern usec_t dt_usec(struct timeval *now, struct timeval *old);
+
+#endif /* NETDATA_CLOCKS_H */
free(ptr);
}
-// ----------------------------------------------------------------------------
-// time functions
-
-inline unsigned long long timeval_usec(struct timeval *tv) {
- return tv->tv_sec * 1000000ULL + tv->tv_usec;
-}
-
-// time(NULL) in nanoseconds
-inline unsigned long long time_usec(void) {
- struct timeval now;
- gettimeofday(&now, NULL);
- return timeval_usec(&now);
-}
-
-inline unsigned long long usec_dt(struct timeval *now, struct timeval *old) {
- unsigned long long tv1 = timeval_usec(now);
- unsigned long long tv2 = timeval_usec(old);
- return (tv1 > tv2) ? (tv1 - tv2) : (tv2 - tv1);
-}
-
-int sleep_usec(unsigned long long usec) {
+int sleep_usec(usec_t usec) {
#ifndef NETDATA_WITH_USLEEP
// we expect microseconds (1.000.000 per second)
#endif // __GNUC__
#include "avl.h"
+#include "clocks.h"
#include "log.h"
#include "global_statistics.h"
#include "storage_number.h"
#endif
#define abs(x) ((x < 0)? -x : x)
-extern unsigned long long usec_dt(struct timeval *now, struct timeval *old);
-extern unsigned long long timeval_usec(struct timeval *tv);
-
-// #define usec_dt(now, last) (((((now)->tv_sec * 1000000ULL) + (now)->tv_usec) - (((last)->tv_sec * 1000000ULL) + (last)->tv_usec)))
-
extern void netdata_fix_chart_id(char *s);
extern void netdata_fix_chart_name(char *s);
extern pid_t gettid(void);
-extern unsigned long long time_usec(void);
-extern int sleep_usec(unsigned long long usec);
+extern int sleep_usec(usec_t usec);
extern char *fgets_trim_len(char *buf, size_t buf_size, FILE *fp, size_t *len);
}
if(unlikely(v->hash == now_hash && !strcmp(v->name, "now"))) {
- n = time(NULL);
+ n = now_realtime_sec();
buffer_strcat(exp->error_msg, "[ $now = ");
print_parsed_as_constant(exp->error_msg, n);
buffer_strcat(exp->error_msg, " ] ");
#include "common.h"
-// NEEDED BY: struct vmstat
+// NEEDED BY: struct vmtotal, struct vmmeter
#include <sys/vmmeter.h>
+// NEEDED BY: struct devstat
+#include <sys/devicestat.h>
+// NEEDED BY: struct xswdev
+#include <vm/vm_param.h>
+// NEEDED BY: struct semid_kernel, struct shmid_kernel, struct msqid_kernel
+#define _KERNEL
+#include <sys/sem.h>
+#include <sys/shm.h>
+#include <sys/msg.h>
+#undef _KERNEL
+// NEEDED BY: do_disk_io
+#define RRD_TYPE_DISK "disk"
// FreeBSD calculates load averages once every 5 seconds
#define MIN_LOADAVG_UPDATE_EVERY 5
-int do_freebsd_sysctl(int update_every, unsigned long long dt) {
+int do_freebsd_sysctl(int update_every, usec_t dt) {
(void)dt;
static int do_cpu = -1, do_cpu_cores = -1, do_interrupts = -1, do_context = -1, do_forks = -1, do_processes = -1,
- do_loadavg = -1, do_all_processes = -1;
+ do_loadavg = -1, do_all_processes = -1, do_disk_io = -1, do_swap = -1, do_ram = -1, do_swapio = -1,
+ do_pgfaults = -1, do_committed = -1, do_ipc_semaphores = -1, do_ipc_shared_mem = -1, do_ipc_msg_queues = -1;
- if(unlikely(do_cpu == -1)) {
+ if (unlikely(do_cpu == -1)) {
do_cpu = config_get_boolean("plugin:freebsd:sysctl", "cpu utilization", 1);
do_cpu_cores = config_get_boolean("plugin:freebsd:sysctl", "per cpu core utilization", 1);
do_interrupts = config_get_boolean("plugin:freebsd:sysctl", "cpu interrupts", 1);
do_processes = config_get_boolean("plugin:freebsd:sysctl", "processes running", 1);
do_loadavg = config_get_boolean("plugin:freebsd:sysctl", "enable load average", 1);
do_all_processes = config_get_boolean("plugin:freebsd:sysctl", "enable total processes", 1);
+ do_disk_io = config_get_boolean("plugin:freebsd:sysctl", "stats for all disks", 1);
+ do_swap = config_get_boolean("plugin:freebsd:sysctl", "system swap", 1);
+ do_ram = config_get_boolean("plugin:freebsd:sysctl", "system ram", 1);
+ do_swapio = config_get_boolean("plugin:freebsd:sysctl", "swap i/o", 1);
+ do_pgfaults = config_get_boolean("plugin:freebsd:sysctl", "memory page faults", 1);
+ do_committed = config_get_boolean("plugin:freebsd:sysctl", "committed memory", 1);
+ do_ipc_semaphores = config_get_boolean("plugin:freebsd:sysctl", "ipc semaphores", 1);
+ do_ipc_shared_mem = config_get_boolean("plugin:freebsd:sysctl", "ipc shared memory", 1);
+ do_ipc_msg_queues = config_get_boolean("plugin:freebsd:sysctl", "ipc message queues", 1);
}
RRDSET *st;
+ int system_pagesize = getpagesize(); // wouldn't it be better to get value directly from hw.pagesize?
int i;
// NEEDED BY: do_loadavg
- static unsigned long long last_loadavg_usec = 0;
+ static usec_t last_loadavg_usec = 0;
struct loadavg sysload;
// NEEDED BY: do_cpu, do_cpu_cores
static unsigned long *intrcnt = NULL;
unsigned long long totalintr = 0;
+// NEEDED BY: do_disk_io
+ #define BINTIME_SCALE 5.42101086242752217003726400434970855712890625e-17 // this is 1000/2^64
+ int numdevs;
+ static void *devstat_data = NULL;
+ struct devstat *dstat;
+ struct cur_dstat {
+ collected_number duration_read_ms;
+ collected_number duration_write_ms;
+ collected_number busy_time_ms;
+ } cur_dstat;
+ struct prev_dstat {
+ collected_number bytes_read;
+ collected_number bytes_write;
+ collected_number operations_read;
+ collected_number operations_write;
+ collected_number duration_read_ms;
+ collected_number duration_write_ms;
+ collected_number busy_time_ms;
+ } prev_dstat;
+
+ // NEEDED BY: do_swap
+ size_t mibsize, size;
+ int mib[3]; // CTL_MAXNAME = 24 maximum mib components (sysctl.h)
+ struct xswdev xsw;
+ struct total_xsw {
+ collected_number bytes_used;
+ collected_number bytes_total;
+ } total_xsw = {0, 0};
+
+ // NEEDED BY: do_swapio, do_ram
+ struct vmmeter vmmeter_data;
+
+ // NEEDED BY: do_ram
+ int vfs_bufspace_count;
+
+ // NEEDED BY: do_ipc_semaphores
+ struct ipc_sem {
+ int semmni;
+ collected_number sets;
+ collected_number semaphores;
+ } ipc_sem = {0, 0, 0};
+ static struct semid_kernel *ipc_sem_data = NULL;
+
+ // NEEDED BY: do_ipc_shared_mem
+ struct ipc_shm {
+ u_long shmmni;
+ collected_number segs;
+ collected_number segsize;
+ } ipc_shm = {0, 0, 0};
+ static struct shmid_kernel *ipc_shm_data = NULL;
+
+ // NEEDED BY: do_ipc_msg_queues
+ struct ipc_msq {
+ int msgmni;
+ collected_number queues;
+ collected_number messages;
+ collected_number usedsize;
+ collected_number allocsize;
+ } ipc_msq = {0, 0, 0, 0, 0};
+ static struct msqid_kernel *ipc_msq_data = NULL;
+
// --------------------------------------------------------------------
- if(last_loadavg_usec <= dt) {
- if(likely(do_loadavg)) {
+ if (last_loadavg_usec <= dt) {
+ if (likely(do_loadavg)) {
if (unlikely(GETSYSCTL("vm.loadavg", sysload))) {
do_loadavg = 0;
error("DISABLED: system.load");
} else {
st = rrdset_find_bytype("system", "load");
- if(unlikely(!st)) {
+ if (unlikely(!st)) {
st = rrdset_create("system", "load", NULL, "load", NULL, "System Load Average", "load", 100, (update_every < MIN_LOADAVG_UPDATE_EVERY) ? MIN_LOADAVG_UPDATE_EVERY : update_every, RRDSET_TYPE_LINE);
rrddim_add(st, "load1", NULL, 1, 1000, RRDDIM_ABSOLUTE);
rrddim_add(st, "load5", NULL, 1, 1000, RRDDIM_ABSOLUTE);
}
}
- last_loadavg_usec = st->update_every * 1000000ULL;
+ last_loadavg_usec = st->update_every * USEC_PER_SEC;
}
else last_loadavg_usec -= dt;
// --------------------------------------------------------------------
- if(likely(do_all_processes | do_processes)) {
+ if (likely(do_all_processes | do_processes | do_committed)) {
if (unlikely(GETSYSCTL("vm.vmtotal", vmtotal_data))) {
do_all_processes = 0;
error("DISABLED: system.active_processes");
do_processes = 0;
error("DISABLED: system.processes");
+ do_committed = 0;
+ error("DISABLED: mem.committed");
} else {
- if(likely(do_processes)) {
+ if (likely(do_all_processes)) {
st = rrdset_find_bytype("system", "active_processes");
- if(unlikely(!st)) {
+ if (unlikely(!st)) {
st = rrdset_create("system", "active_processes", NULL, "processes", NULL, "System Active Processes", "processes", 750, update_every, RRDSET_TYPE_LINE);
rrddim_add(st, "active", NULL, 1, 1, RRDDIM_ABSOLUTE);
}
rrddim_set(st, "active", (vmtotal_data.t_rq + vmtotal_data.t_dw + vmtotal_data.t_pw + vmtotal_data.t_sl + vmtotal_data.t_sw));
rrdset_done(st);
}
- if(likely(do_processes)) {
+
+ // --------------------------------------------------------------------
+
+ if (likely(do_processes)) {
st = rrdset_find_bytype("system", "processes");
- if(unlikely(!st)) {
+ if (unlikely(!st)) {
st = rrdset_create("system", "processes", NULL, "processes", NULL, "System Processes", "processes", 600, update_every, RRDSET_TYPE_LINE);
rrddim_add(st, "running", NULL, 1, 1, RRDDIM_ABSOLUTE);
rrdset_done(st);
}
- }
- }
+ // --------------------------------------------------------------------
- // --------------------------------------------------------------------
-
- if(likely(do_processes)) {
+ if (likely(do_committed)) {
+ st = rrdset_find("mem.committed");
+ if (unlikely(!st)) {
+ st = rrdset_create("mem", "committed", NULL, "system", NULL, "Committed (Allocated) Memory", "MB", 5000, update_every, RRDSET_TYPE_AREA);
+ st->isdetail = 1;
- st = rrdset_find_bytype("system", "processes");
- if(unlikely(!st)) {
- st = rrdset_create("system", "processes", NULL, "processes", NULL, "System Processes", "processes", 600, update_every, RRDSET_TYPE_LINE);
+ rrddim_add(st, "Committed_AS", NULL, system_pagesize, 1024, RRDDIM_ABSOLUTE);
+ }
+ else rrdset_next(st);
- rrddim_add(st, "running", NULL, 1, 1, RRDDIM_ABSOLUTE);
- rrddim_add(st, "blocked", NULL, -1, 1, RRDDIM_ABSOLUTE);
+ rrddim_set(st, "Committed_AS", vmtotal_data.t_rm);
+ rrdset_done(st);
}
- else rrdset_next(st);
-
- rrddim_set(st, "running", vmtotal_data.t_rq);
- rrddim_set(st, "blocked", (vmtotal_data.t_dw + vmtotal_data.t_pw));
- rrdset_done(st);
}
+ }
// --------------------------------------------------------------------
- if(likely(do_cpu)) {
+ if (likely(do_cpu)) {
if (unlikely(CPUSTATES != 5)) {
error("FREEBSD: There are %d CPU states (5 was expected)", CPUSTATES);
do_cpu = 0;
} else {
st = rrdset_find_bytype("system", "cpu");
- if(unlikely(!st)) {
+ if (unlikely(!st)) {
st = rrdset_create("system", "cpu", NULL, "cpu", "system.cpu", "Total CPU utilization", "percentage", 100, update_every, RRDSET_TYPE_STACKED);
rrddim_add(st, "user", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL);
// --------------------------------------------------------------------
- if(likely(do_cpu_cores)) {
+ if (likely(do_cpu_cores)) {
if (unlikely(CPUSTATES != 5)) {
error("FREEBSD: There are %d CPU states (5 was expected)", CPUSTATES);
do_cpu_cores = 0;
snprintfz(cpuid, 8, "cpu%d", i);
st = rrdset_find_bytype("cpu", cpuid);
- if(unlikely(!st)) {
+ if (unlikely(!st)) {
st = rrdset_create("cpu", cpuid, NULL, "utilization", "cpu.cpu", "Core utilization", "percentage", 1000, update_every, RRDSET_TYPE_STACKED);
rrddim_add(st, "user", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL);
// --------------------------------------------------------------------
- if(likely(do_interrupts)) {
+ if (likely(do_interrupts)) {
if (unlikely(sysctlbyname("hw.intrcnt", NULL, &intrcnt_size, NULL, 0) == -1)) {
error("FREEBSD: sysctl(hw.intrcnt...) failed: %s", strerror(errno));
do_interrupts = 0;
totalintr += intrcnt[i];
st = rrdset_find_bytype("system", "intr");
- if(unlikely(!st)) {
+ if (unlikely(!st)) {
st = rrdset_create("system", "intr", NULL, "interrupts", NULL, "Total Device Interrupts", "interrupts/s", 900, update_every, RRDSET_TYPE_LINE);
st->isdetail = 1;
// --------------------------------------------------------------------
- if(likely(do_context)) {
+ if (likely(do_context)) {
if (unlikely(GETSYSCTL("vm.stats.sys.v_swtch", u_int_data))) {
do_context = 0;
error("DISABLED: system.ctxt");
} else {
st = rrdset_find_bytype("system", "ctxt");
- if(unlikely(!st)) {
+ if (unlikely(!st)) {
st = rrdset_create("system", "ctxt", NULL, "processes", NULL, "CPU Context Switches", "context switches/s", 800, update_every, RRDSET_TYPE_LINE);
rrddim_add(st, "switches", NULL, 1, 1, RRDDIM_INCREMENTAL);
// --------------------------------------------------------------------
- if(likely(do_forks)) {
+ if (likely(do_forks)) {
if (unlikely(GETSYSCTL("vm.stats.vm.v_forks", u_int_data))) {
do_forks = 0;
error("DISABLED: system.forks");
} else {
st = rrdset_find_bytype("system", "forks");
- if(unlikely(!st)) {
+ if (unlikely(!st)) {
st = rrdset_create("system", "forks", NULL, "processes", NULL, "Started Processes", "processes/s", 700, update_every, RRDSET_TYPE_LINE);
st->isdetail = 1;
}
}
+ // --------------------------------------------------------------------
+
+ if (likely(do_disk_io)) {
+ if (unlikely(GETSYSCTL("kern.devstat.numdevs", numdevs))) {
+ do_disk_io = 0;
+ error("DISABLED: disk.io");
+ } else {
+ devstat_data = reallocz(devstat_data, sizeof(long) + sizeof(struct devstat) * numdevs); // there is generation number before devstat structures
+ if (unlikely(getsysctl("kern.devstat.all", devstat_data, sizeof(long) + sizeof(struct devstat) * numdevs))) {
+ do_disk_io = 0;
+ error("DISABLED: disk.io");
+ } else {
+ dstat = devstat_data + sizeof(long); // skip generation number
+ collected_number total_disk_reads = 0;
+ collected_number total_disk_writes = 0;
+
+ for (i = 0; i < numdevs; i++) {
+ if ((dstat[i].device_type == (DEVSTAT_TYPE_IF_SCSI | DEVSTAT_TYPE_DIRECT)) || (dstat[i].device_type == (DEVSTAT_TYPE_IF_IDE | DEVSTAT_TYPE_DIRECT))) {
+
+ // --------------------------------------------------------------------
+
+ st = rrdset_find_bytype(RRD_TYPE_DISK, dstat[i].device_name);
+ if (unlikely(!st)) {
+ st = rrdset_create(RRD_TYPE_DISK, dstat[i].device_name, NULL, dstat[i].device_name, "disk.io", "Disk I/O Bandwidth", "kilobytes/s", 2000, update_every, RRDSET_TYPE_AREA);
+
+ rrddim_add(st, "reads", NULL, 1, 1024, RRDDIM_INCREMENTAL);
+ rrddim_add(st, "writes", NULL, -1, 1024, RRDDIM_INCREMENTAL);
+ }
+ else rrdset_next(st);
+
+ total_disk_reads += dstat[i].bytes[DEVSTAT_READ];
+ total_disk_writes += dstat[i].bytes[DEVSTAT_WRITE];
+ prev_dstat.bytes_read = rrddim_set(st, "reads", dstat[i].bytes[DEVSTAT_READ]);
+ prev_dstat.bytes_write = rrddim_set(st, "writes", dstat[i].bytes[DEVSTAT_WRITE]);
+ rrdset_done(st);
+
+ // --------------------------------------------------------------------
+
+ st = rrdset_find_bytype("disk_ops", dstat[i].device_name);
+ if (unlikely(!st)) {
+ st = rrdset_create("disk_ops", dstat[i].device_name, NULL, dstat[i].device_name, "disk.ops", "Disk Completed I/O Operations", "operations/s", 2001, update_every, RRDSET_TYPE_LINE);
+ st->isdetail = 1;
+
+ rrddim_add(st, "reads", NULL, 1, 1, RRDDIM_INCREMENTAL);
+ rrddim_add(st, "writes", NULL, -1, 1, RRDDIM_INCREMENTAL);
+ }
+ else rrdset_next(st);
+
+ prev_dstat.operations_read = rrddim_set(st, "reads", dstat[i].operations[DEVSTAT_READ]);
+ prev_dstat.operations_write = rrddim_set(st, "writes", dstat[i].operations[DEVSTAT_WRITE]);
+ rrdset_done(st);
+
+ // --------------------------------------------------------------------
+
+ st = rrdset_find_bytype("disk_qops", dstat[i].device_name);
+ if (unlikely(!st)) {
+ st = rrdset_create("disk_qops", dstat[i].device_name, NULL, dstat[i].device_name, "disk.qops", "Disk Current I/O Operations", "operations", 2002, update_every, RRDSET_TYPE_LINE);
+ st->isdetail = 1;
+
+ rrddim_add(st, "operations", NULL, 1, 1, RRDDIM_ABSOLUTE);
+ }
+ else rrdset_next(st);
+
+ rrddim_set(st, "operations", dstat[i].start_count - dstat[i].end_count);
+ rrdset_done(st);
+
+ // --------------------------------------------------------------------
+
+ st = rrdset_find_bytype("disk_util", dstat[i].device_name);
+ if (unlikely(!st)) {
+ st = rrdset_create("disk_util", dstat[i].device_name, NULL, dstat[i].device_name, "disk.util", "Disk Utilization Time", "% of time working", 2004, update_every, RRDSET_TYPE_AREA);
+ st->isdetail = 1;
+
+ rrddim_add(st, "utilization", NULL, 1, 10, RRDDIM_INCREMENTAL);
+ }
+ else rrdset_next(st);
+
+ cur_dstat.busy_time_ms = dstat[i].busy_time.sec * 1000 + dstat[i].busy_time.frac * BINTIME_SCALE;
+ prev_dstat.busy_time_ms = rrddim_set(st, "utilization", cur_dstat.busy_time_ms);
+ rrdset_done(st);
+
+ // --------------------------------------------------------------------
+
+ st = rrdset_find_bytype("disk_iotime", dstat[i].device_name);
+ if (unlikely(!st)) {
+ st = rrdset_create("disk_iotime", dstat[i].device_name, NULL, dstat[i].device_name, "disk.iotime", "Disk Total I/O Time", "milliseconds/s", 2022, update_every, RRDSET_TYPE_LINE);
+ st->isdetail = 1;
+
+ rrddim_add(st, "reads", NULL, 1, 1, RRDDIM_INCREMENTAL);
+ rrddim_add(st, "writes", NULL, -1, 1, RRDDIM_INCREMENTAL);
+ }
+ else rrdset_next(st);
+
+ cur_dstat.duration_read_ms = dstat[i].duration[DEVSTAT_READ].sec * 1000 + dstat[i].duration[DEVSTAT_READ].frac * BINTIME_SCALE;
+ cur_dstat.duration_write_ms = dstat[i].duration[DEVSTAT_WRITE].sec * 1000 + dstat[i].duration[DEVSTAT_READ].frac * BINTIME_SCALE;
+ prev_dstat.duration_read_ms = rrddim_set(st, "reads", cur_dstat.duration_read_ms);
+ prev_dstat.duration_write_ms = rrddim_set(st, "writes", cur_dstat.duration_write_ms);
+ rrdset_done(st);
+
+ // --------------------------------------------------------------------
+ // calculate differential charts
+ // only if this is not the first time we run
+
+ if (likely(dt)) {
+
+ // --------------------------------------------------------------------
+
+ st = rrdset_find_bytype("disk_await", dstat[i].device_name);
+ if (unlikely(!st)) {
+ st = rrdset_create("disk_await", dstat[i].device_name, NULL, dstat[i].device_name, "disk.await", "Average Completed I/O Operation Time", "ms per operation", 2005, update_every, RRDSET_TYPE_LINE);
+ st->isdetail = 1;
+
+ rrddim_add(st, "reads", NULL, 1, 1, RRDDIM_ABSOLUTE);
+ rrddim_add(st, "writes", NULL, -1, 1, RRDDIM_ABSOLUTE);
+ }
+ else rrdset_next(st);
+
+ rrddim_set(st, "reads", (dstat[i].operations[DEVSTAT_READ] - prev_dstat.operations_read) ?
+ (cur_dstat.duration_read_ms - prev_dstat.duration_read_ms) / (dstat[i].operations[DEVSTAT_READ] - prev_dstat.operations_read) : 0);
+ rrddim_set(st, "writes", (dstat[i].operations[DEVSTAT_WRITE] - prev_dstat.operations_write) ?
+ (cur_dstat.duration_write_ms - prev_dstat.duration_write_ms) / (dstat[i].operations[DEVSTAT_WRITE] - prev_dstat.operations_write) : 0);
+ rrdset_done(st);
+
+ // --------------------------------------------------------------------
+
+ st = rrdset_find_bytype("disk_avgsz", dstat[i].device_name);
+ if (unlikely(!st)) {
+ st = rrdset_create("disk_avgsz", dstat[i].device_name, NULL, dstat[i].device_name, "disk.avgsz", "Average Completed I/O Operation Bandwidth", "kilobytes per operation", 2006, update_every, RRDSET_TYPE_AREA);
+ st->isdetail = 1;
+
+ rrddim_add(st, "reads", NULL, 1, 1024, RRDDIM_ABSOLUTE);
+ rrddim_add(st, "writes", NULL, -1, 1024, RRDDIM_ABSOLUTE);
+ }
+ else rrdset_next(st);
+
+ rrddim_set(st, "reads", (dstat[i].operations[DEVSTAT_READ] - prev_dstat.operations_read) ?
+ (dstat[i].bytes[DEVSTAT_READ] - prev_dstat.bytes_read) / (dstat[i].operations[DEVSTAT_READ] - prev_dstat.operations_read) : 0);
+ rrddim_set(st, "writes", (dstat[i].operations[DEVSTAT_WRITE] - prev_dstat.operations_write) ?
+ (dstat[i].bytes[DEVSTAT_WRITE] - prev_dstat.bytes_write) / (dstat[i].operations[DEVSTAT_WRITE] - prev_dstat.operations_write) : 0);
+ rrdset_done(st);
+
+ // --------------------------------------------------------------------
+
+ st = rrdset_find_bytype("disk_svctm", dstat[i].device_name);
+ if (unlikely(!st)) {
+ st = rrdset_create("disk_svctm", dstat[i].device_name, NULL, dstat[i].device_name, "disk.svctm", "Average Service Time", "ms per operation", 2007, update_every, RRDSET_TYPE_LINE);
+ st->isdetail = 1;
+
+ rrddim_add(st, "svctm", NULL, 1, 1, RRDDIM_ABSOLUTE);
+ }
+ else rrdset_next(st);
+
+ rrddim_set(st, "svctm", ((dstat[i].operations[DEVSTAT_READ] - prev_dstat.operations_read) + (dstat[i].operations[DEVSTAT_WRITE] - prev_dstat.operations_write)) ?
+ (cur_dstat.busy_time_ms - prev_dstat.busy_time_ms) / ((dstat[i].operations[DEVSTAT_READ] - prev_dstat.operations_read) + (dstat[i].operations[DEVSTAT_WRITE] - prev_dstat.operations_write)) : 0);
+ rrdset_done(st);
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ st = rrdset_find_bytype("system", "io");
+ if (unlikely(!st)) {
+ st = rrdset_create("system", "io", NULL, "disk", NULL, "Disk I/O", "kilobytes/s", 150, update_every, RRDSET_TYPE_AREA);
+ rrddim_add(st, "in", NULL, 1, 1024, RRDDIM_INCREMENTAL);
+ rrddim_add(st, "out", NULL, -1, 1024, RRDDIM_INCREMENTAL);
+ }
+ else rrdset_next(st);
+
+ rrddim_set(st, "in", total_disk_reads);
+ rrddim_set(st, "out", total_disk_writes);
+ rrdset_done(st);
+ }
+ }
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+
+ if (likely(do_swap)) {
+ mibsize = sizeof mib / sizeof mib[0];
+ if (unlikely(sysctlnametomib("vm.swap_info", mib, &mibsize) == -1)) {
+ error("FREEBSD: sysctl(%s...) failed: %s", "vm.swap_info", strerror(errno));
+ do_swap = 0;
+ error("DISABLED: disk.io");
+ } else {
+ for (i = 0; ; i++) {
+ mib[mibsize] = i;
+ size = sizeof(xsw);
+ if (unlikely(sysctl(mib, mibsize + 1, &xsw, &size, NULL, 0) == -1 )) {
+ if (unlikely(errno != ENOENT)) {
+ error("FREEBSD: sysctl(%s...) failed: %s", "vm.swap_info", strerror(errno));
+ do_swap = 0;
+ error("DISABLED: disk.io");
+ } else {
+ if (unlikely(size != sizeof(xsw))) {
+ error("FREEBSD: sysctl(%s...) expected %lu, got %lu", "vm.swap_info", (unsigned long)sizeof(xsw), (unsigned long)size);
+ do_swap = 0;
+ error("DISABLED: disk.io");
+ } else break;
+ }
+ }
+ total_xsw.bytes_used += xsw.xsw_used * system_pagesize;
+ total_xsw.bytes_total += xsw.xsw_nblks * system_pagesize;
+ }
+
+ if (likely(do_swap)) {
+ st = rrdset_find("system.swap");
+ if (unlikely(!st)) {
+ st = rrdset_create("system", "swap", NULL, "swap", NULL, "System Swap", "MB", 201, update_every, RRDSET_TYPE_STACKED);
+ st->isdetail = 1;
+
+ rrddim_add(st, "free", NULL, 1, 1048576, RRDDIM_ABSOLUTE);
+ rrddim_add(st, "used", NULL, 1, 1048576, RRDDIM_ABSOLUTE);
+ }
+ else rrdset_next(st);
+
+ rrddim_set(st, "used", total_xsw.bytes_used);
+ rrddim_set(st, "free", total_xsw.bytes_total - total_xsw.bytes_used);
+ rrdset_done(st);
+ }
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ if (likely(do_ram)) {
+ if (unlikely(GETSYSCTL("vm.stats.vm.v_active_count", vmmeter_data.v_active_count) ||
+ GETSYSCTL("vm.stats.vm.v_inactive_count", vmmeter_data.v_inactive_count) ||
+ GETSYSCTL("vm.stats.vm.v_wire_count", vmmeter_data.v_wire_count) ||
+ GETSYSCTL("vm.stats.vm.v_cache_count", vmmeter_data.v_cache_count) ||
+ GETSYSCTL("vfs.bufspace", vfs_bufspace_count) ||
+ GETSYSCTL("vm.stats.vm.v_free_count", vmmeter_data.v_free_count))) {
+ do_swapio = 0;
+ error("DISABLED: system.swapio");
+ } else {
+ st = rrdset_find("system.ram");
+ if (unlikely(!st)) {
+ st = rrdset_create("system", "ram", NULL, "ram", NULL, "System RAM", "MB", 200, update_every, RRDSET_TYPE_STACKED);
+
+ rrddim_add(st, "active", NULL, system_pagesize, 1024, RRDDIM_ABSOLUTE);
+ rrddim_add(st, "inactive", NULL, system_pagesize, 1024, RRDDIM_ABSOLUTE);
+ rrddim_add(st, "wired", NULL, system_pagesize, 1024, RRDDIM_ABSOLUTE);
+ rrddim_add(st, "cache", NULL, system_pagesize, 1024, RRDDIM_ABSOLUTE);
+ rrddim_add(st, "buffers", NULL, 1, 1024, RRDDIM_ABSOLUTE);
+ rrddim_add(st, "free", NULL, system_pagesize, 1024, RRDDIM_ABSOLUTE);
+ }
+ else rrdset_next(st);
+
+ rrddim_set(st, "active", vmmeter_data.v_active_count);
+ rrddim_set(st, "inactive", vmmeter_data.v_inactive_count);
+ rrddim_set(st, "wired", vmmeter_data.v_wire_count);
+ rrddim_set(st, "cache", vmmeter_data.v_cache_count);
+ rrddim_set(st, "buffers", vfs_bufspace_count);
+ rrddim_set(st, "free", vmmeter_data.v_free_count);
+ rrdset_done(st);
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ if (likely(do_swapio)) {
+ if (unlikely(GETSYSCTL("vm.stats.vm.v_swappgsin", vmmeter_data.v_swappgsin) || GETSYSCTL("vm.stats.vm.v_vnodepgsout", vmmeter_data.v_swappgsout))) {
+ do_swapio = 0;
+ error("DISABLED: system.swapio");
+ } else {
+ st = rrdset_find("system.swapio");
+ if (unlikely(!st)) {
+ st = rrdset_create("system", "swapio", NULL, "swap", NULL, "Swap I/O", "kilobytes/s", 250, update_every, RRDSET_TYPE_AREA);
+
+ rrddim_add(st, "in", NULL, system_pagesize, 1024, RRDDIM_INCREMENTAL);
+ rrddim_add(st, "out", NULL, -system_pagesize, 1024, RRDDIM_INCREMENTAL);
+ }
+ else rrdset_next(st);
+
+ rrddim_set(st, "in", vmmeter_data.v_swappgsin);
+ rrddim_set(st, "out", vmmeter_data.v_swappgsout);
+ rrdset_done(st);
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ if (likely(do_pgfaults)) {
+ if (unlikely(GETSYSCTL("vm.stats.vm.v_vm_faults", vmmeter_data.v_vm_faults) ||
+ GETSYSCTL("vm.stats.vm.v_io_faults", vmmeter_data.v_io_faults) ||
+ GETSYSCTL("vm.stats.vm.v_cow_faults", vmmeter_data.v_cow_faults) ||
+ GETSYSCTL("vm.stats.vm.v_cow_optim", vmmeter_data.v_cow_optim) ||
+ GETSYSCTL("vm.stats.vm.v_intrans", vmmeter_data.v_intrans))) {
+ do_pgfaults = 0;
+ error("DISABLED: mem.pgfaults");
+ } else {
+ st = rrdset_find("mem.pgfaults");
+ if (unlikely(!st)) {
+ st = rrdset_create("mem", "pgfaults", NULL, "system", NULL, "Memory Page Faults", "page faults/s", 500, update_every, RRDSET_TYPE_LINE);
+ st->isdetail = 1;
+
+ rrddim_add(st, "memory", NULL, 1, 1, RRDDIM_INCREMENTAL);
+ rrddim_add(st, "io_requiring", NULL, 1, 1, RRDDIM_INCREMENTAL);
+ rrddim_add(st, "cow", NULL, 1, 1, RRDDIM_INCREMENTAL);
+ rrddim_add(st, "cow_optimized", NULL, 1, 1, RRDDIM_INCREMENTAL);
+ rrddim_add(st, "in_transit", NULL, 1, 1, RRDDIM_INCREMENTAL);
+ }
+ else rrdset_next(st);
+
+ rrddim_set(st, "memory", vmmeter_data.v_vm_faults);
+ rrddim_set(st, "io_requiring", vmmeter_data.v_io_faults);
+ rrddim_set(st, "cow", vmmeter_data.v_cow_faults);
+ rrddim_set(st, "cow_optimized", vmmeter_data.v_cow_optim);
+ rrddim_set(st, "in_transit", vmmeter_data.v_intrans);
+ rrdset_done(st);
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ if (likely(do_ipc_semaphores)) {
+ if (unlikely(GETSYSCTL("kern.ipc.semmni", ipc_sem.semmni))) {
+ do_ipc_semaphores = 0;
+ error("DISABLED: system.ipc_semaphores");
+ error("DISABLED: system.ipc_semaphore_arrays");
+ } else {
+ ipc_sem_data = reallocz(ipc_sem_data, sizeof(struct semid_kernel) * ipc_sem.semmni);
+ if (unlikely(getsysctl("kern.ipc.sema", ipc_sem_data, sizeof(struct semid_kernel) * ipc_sem.semmni))) {
+ do_ipc_semaphores = 0;
+ error("DISABLED: system.ipc_semaphores");
+ error("DISABLED: system.ipc_semaphore_arrays");
+ } else {
+ for (i = 0; i < ipc_sem.semmni; i++) {
+ if (unlikely(ipc_sem_data[i].u.sem_perm.mode & SEM_ALLOC)) {
+ ipc_sem.sets += 1;
+ ipc_sem.semaphores += ipc_sem_data[i].u.sem_nsems;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ st = rrdset_find("system.ipc_semaphores");
+ if (unlikely(!st)) {
+ st = rrdset_create("system", "ipc_semaphores", NULL, "ipc semaphores", NULL, "IPC Semaphores", "semaphores", 1000, rrd_update_every, RRDSET_TYPE_AREA);
+ rrddim_add(st, "semaphores", NULL, 1, 1, RRDDIM_ABSOLUTE);
+ }
+ else rrdset_next(st);
+
+ rrddim_set(st, "semaphores", ipc_sem.semaphores);
+ rrdset_done(st);
+
+ // --------------------------------------------------------------------
+
+ st = rrdset_find("system.ipc_semaphore_arrays");
+ if (unlikely(!st)) {
+ st = rrdset_create("system", "ipc_semaphore_arrays", NULL, "ipc semaphores", NULL, "IPC Semaphore Arrays", "arrays", 1000, rrd_update_every, RRDSET_TYPE_AREA);
+ rrddim_add(st, "arrays", NULL, 1, 1, RRDDIM_ABSOLUTE);
+ }
+ else rrdset_next(st);
+
+ rrddim_set(st, "arrays", ipc_sem.sets);
+ rrdset_done(st);
+ }
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ if (likely(do_ipc_shared_mem)) {
+ if (unlikely(GETSYSCTL("kern.ipc.shmmni", ipc_shm.shmmni))) {
+ do_ipc_shared_mem = 0;
+ error("DISABLED: system.ipc_shared_mem_segs");
+ error("DISABLED: system.ipc_shared_mem_size");
+ } else {
+ ipc_shm_data = reallocz(ipc_shm_data, sizeof(struct shmid_kernel) * ipc_shm.shmmni);
+ if (unlikely(getsysctl("kern.ipc.shmsegs", ipc_shm_data, sizeof(struct shmid_kernel) * ipc_shm.shmmni))) {
+ do_ipc_shared_mem = 0;
+ error("DISABLED: system.ipc_shared_mem_segs");
+ error("DISABLED: system.ipc_shared_mem_size");
+ } else {
+ for (i = 0; i < ipc_shm.shmmni; i++) {
+ if (unlikely(ipc_shm_data[i].u.shm_perm.mode & 0x0800)) {
+ ipc_shm.segs += 1;
+ ipc_shm.segsize += ipc_shm_data[i].u.shm_segsz;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ st = rrdset_find("system.ipc_shared_mem_segs");
+ if (unlikely(!st)) {
+ st = rrdset_create("system", "ipc_shared_mem_segs", NULL, "ipc shared memory", NULL, "IPC Shared Memory Segments", "segments", 1000, rrd_update_every, RRDSET_TYPE_AREA);
+ rrddim_add(st, "segments", NULL, 1, 1, RRDDIM_ABSOLUTE);
+ }
+ else rrdset_next(st);
+
+ rrddim_set(st, "segments", ipc_shm.segs);
+ rrdset_done(st);
+
+ // --------------------------------------------------------------------
+
+ st = rrdset_find("system.ipc_shared_mem_size");
+ if (unlikely(!st)) {
+ st = rrdset_create("system", "ipc_shared_mem_size", NULL, "ipc shared memory", NULL, "IPC Shared Memory Segments Size", "kilobytes", 1000, rrd_update_every, RRDSET_TYPE_AREA);
+ rrddim_add(st, "allocated", NULL, 1, 1024, RRDDIM_ABSOLUTE);
+ }
+ else rrdset_next(st);
+
+ rrddim_set(st, "allocated", ipc_shm.segsize);
+ rrdset_done(st);
+ }
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ if (likely(do_ipc_msg_queues)) {
+ if (unlikely(GETSYSCTL("kern.ipc.msgmni", ipc_msq.msgmni))) {
+ do_ipc_msg_queues = 0;
+ error("DISABLED: system.ipc_msq_queues");
+ error("DISABLED: system.ipc_msq_messages");
+ error("DISABLED: system.ipc_msq_used_size");
+ error("DISABLED: system.ipc_msq_allocated_size");
+ } else {
+ ipc_msq_data = reallocz(ipc_msq_data, sizeof(struct msqid_kernel) * ipc_msq.msgmni);
+ if (unlikely(getsysctl("kern.ipc.msqids", ipc_msq_data, sizeof(struct msqid_kernel) * ipc_msq.msgmni))) {
+ do_ipc_msg_queues = 0;
+ error("DISABLED: system.ipc_msq_queues");
+ error("DISABLED: system.ipc_msq_messages");
+ error("DISABLED: system.ipc_msq_used_size");
+ error("DISABLED: system.ipc_msq_allocated_size");
+ } else {
+ for (i = 0; i < ipc_msq.msgmni; i++) {
+ if (unlikely(ipc_msq_data[i].u.msg_qbytes != 0)) {
+ ipc_msq.queues += 1;
+ ipc_msq.messages += ipc_msq_data[i].u.msg_qnum;
+ ipc_msq.usedsize += ipc_msq_data[i].u.msg_cbytes;
+ ipc_msq.allocsize += ipc_msq_data[i].u.msg_qbytes;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ st = rrdset_find("system.ipc_msq_queues");
+ if (unlikely(!st)) {
+ st = rrdset_create("system", "ipc_msq_queues", NULL, "ipc message queues", NULL, "Number of IPC Message Queues", "queues", 1000, rrd_update_every, RRDSET_TYPE_AREA);
+ rrddim_add(st, "queues", NULL, 1, 1, RRDDIM_ABSOLUTE);
+ }
+ else rrdset_next(st);
+
+ rrddim_set(st, "queues", ipc_msq.queues);
+ rrdset_done(st);
+
+ // --------------------------------------------------------------------
+
+ st = rrdset_find("system.ipc_msq_messages");
+ if (unlikely(!st)) {
+ st = rrdset_create("system", "ipc_msq_messages", NULL, "ipc message queues", NULL, "Number of Messages in IPC Message Queues", "messages", 1000, rrd_update_every, RRDSET_TYPE_AREA);
+ rrddim_add(st, "messages", NULL, 1, 1, RRDDIM_ABSOLUTE);
+ }
+ else rrdset_next(st);
+
+ rrddim_set(st, "messages", ipc_msq.messages);
+ rrdset_done(st);
+
+ // --------------------------------------------------------------------
+
+ st = rrdset_find("system.ipc_msq_used_size");
+ if (unlikely(!st)) {
+ st = rrdset_create("system", "ipc_msq_used_size", NULL, "ipc message queues", NULL, "Number of used bytes in IPC Message Queues", "bytes", 1000, rrd_update_every, RRDSET_TYPE_AREA);
+ rrddim_add(st, "used", NULL, 1, 1, RRDDIM_ABSOLUTE);
+ }
+ else rrdset_next(st);
+
+ rrddim_set(st, "used", ipc_msq.usedsize);
+ rrdset_done(st);
+
+
+ // --------------------------------------------------------------------
+
+ st = rrdset_find("system.ipc_msq_allocated_size");
+ if (unlikely(!st)) {
+ st = rrdset_create("system", "ipc_msq_allocated_size", NULL, "ipc message queues", NULL, "Maximum size of IPC Message Queues", "bytes", 1000, rrd_update_every, RRDSET_TYPE_AREA);
+ rrddim_add(st, "allocated", NULL, 1, 1, RRDDIM_ABSOLUTE);
+ }
+ else rrdset_next(st);
+
+ rrddim_set(st, "allocated", ipc_msq.allocsize);
+ rrdset_done(st);
+ }
+ }
+ }
+
return 0;
}
freez(buf);
- if(!max_unique_id) max_unique_id = (uint32_t)time(NULL);
- if(!max_alarm_id) max_alarm_id = (uint32_t)time(NULL);
+ if(!max_unique_id) max_unique_id = (uint32_t)now_realtime_sec();
+ if(!max_alarm_id) max_alarm_id = (uint32_t)now_realtime_sec();
host->health_log.next_log_id = max_unique_id + 1;
host->health_log.next_alarm_id = max_alarm_id + 1;
static void rrdsetcalc_link(RRDSET *st, RRDCALC *rc) {
debug(D_HEALTH, "Health linking alarm '%s.%s' to chart '%s' of host '%s'", rc->chart?rc->chart:"NOCHART", rc->name, st->id, st->rrdhost->hostname);
- rc->last_status_change = time(NULL);
+ rc->last_status_change = now_realtime_sec();
rc->rrdset = st;
rc->rrdset_next = st->alarms;
if(!rc->units) rc->units = strdupz(st->units);
{
- time_t now = time(NULL);
+ time_t now = now_realtime_sec();
health_alarm_log(st->rrdhost, rc->id, rc->next_event_id++, now, rc->name, rc->rrdset->id, rc->rrdset->family, rc->exec, rc->recipient, now - rc->last_status_change, rc->old_value, rc->value, rc->status, RRDCALC_STATUS_UNINITIALIZED, rc->source, rc->units, rc->info, 0);
}
}
}
{
- time_t now = time(NULL);
+ time_t now = now_realtime_sec();
health_alarm_log(st->rrdhost, rc->id, rc->next_event_id++, now, rc->name, rc->rrdset->id, rc->rrdset->family, rc->exec, rc->recipient, now - rc->last_status_change, rc->old_value, rc->value, rc->status, RRDCALC_STATUS_REMOVED, rc->source, rc->units, rc->info, 0);
}
host->hostname,
(host->health_log.next_log_id > 0)?(host->health_log.next_log_id - 1):0,
health_enabled?"true":"false",
- (unsigned long)time(NULL));
+ (unsigned long)now_realtime_sec());
RRDCALC *rc;
for(i = 0, rc = host->alarms; rc ; rc = rc->next) {
);
ae->flags |= HEALTH_ENTRY_FLAG_EXEC_RUN;
- ae->exec_run_timestamp = time(NULL);
+ ae->exec_run_timestamp = now_realtime_sec();
debug(D_HEALTH, "executing command '%s'", command_to_run);
FILE *fp = mypopen(command_to_run, &command_pid);
static inline void health_alarm_log_process(RRDHOST *host) {
static uint32_t stop_at_id = 0;
uint32_t first_waiting = (host->health_log.alarms)?host->health_log.alarms->unique_id:0;
- time_t now = time(NULL);
+ time_t now = now_realtime_sec();
pthread_rwlock_rdlock(&host->health_log.alarm_log_rwlock);
debug(D_HEALTH, "Health monitoring iteration no %u started", loop);
int oldstate, runnable = 0;
- time_t now = time(NULL);
+ time_t now = now_realtime_sec();
time_t next_run = now + min_run_every;
RRDCALC *rc;
if(unlikely(netdata_exit))
break;
- now = time(NULL);
+ now = now_realtime_sec();
if(now < next_run) {
debug(D_HEALTH, "Health monitoring iteration no %u done. Next iteration in %d secs",
loop, (int) (next_run - now));
- sleep_usec(1000000 * (unsigned long long) (next_run - now));
+ sleep_usec(USEC_PER_SEC * (usec_t) (next_run - now));
}
else {
debug(D_HEALTH, "Health monitoring iteration no %u done. Next iteration now", loop);
return 0;
}
-int do_ipc(int update_every, unsigned long long dt) {
+int do_ipc(int update_every, usec_t dt) {
(void)dt;
static int initialized = 0, read_limits_next = 0;
#ifndef NETDATA_PLUGIN_IPC_H
#define NETDATA_PLUGIN_IPC_H 1
-extern int do_ipc(int update_every, unsigned long long dt);
+extern int do_ipc(int update_every, usec_t dt);
#endif /* NETDATA_PLUGIN_IPC_H */
return 1;
#endif
- time_t now = time(NULL);
+ time_t now = now_monotonic_sec();
if(!start) start = now;
if(reset) {
time_t t;
struct tm *tmp, tmbuf;
- t = time(NULL);
+ t = now_realtime_sec();
tmp = localtime_r(&t, &tmbuf);
if (tmp == NULL) return;
if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
error("Cannot set pthread cancel state to ENABLE.");
- unsigned long long usec = 0, susec = rrd_update_every * 1000000ULL, loop_usec = 0, total_susec = 0;
+ usec_t usec = 0, susec = rrd_update_every * USEC_PER_SEC, loop_usec = 0, total_susec = 0;
struct timeval now, last, loop;
RRDSET *check1, *check2, *check3, *apps_cpu = NULL;
rrddim_add(check3, "netdata", NULL, 1, 1, RRDDIM_ABSOLUTE);
rrddim_add(check3, "apps.plugin", NULL, 1, 1, RRDDIM_ABSOLUTE);
- gettimeofday(&last, NULL);
+ now_realtime_timeval(&last);
while(1) {
usleep(susec);
// find the time to sleep in order to wait exactly update_every seconds
- gettimeofday(&now, NULL);
- loop_usec = usec_dt(&now, &last);
+ now_realtime_timeval(&now);
+ loop_usec = dt_usec(&now, &last);
usec = loop_usec - susec;
debug(D_PROCNETDEV_LOOP, "CHECK: last loop took %llu usec (worked for %llu, sleeped for %llu).", loop_usec, usec, susec);
- if(usec < (rrd_update_every * 1000000ULL / 2ULL)) susec = (rrd_update_every * 1000000ULL) - usec;
- else susec = rrd_update_every * 1000000ULL / 2ULL;
+ if(usec < (rrd_update_every * USEC_PER_SEC / 2ULL)) susec = (rrd_update_every * USEC_PER_SEC) - usec;
+ else susec = rrd_update_every * USEC_PER_SEC / 2ULL;
// --------------------------------------------------------------------
// Calculate loop time
if(!apps_cpu) apps_cpu = rrdset_find("apps.cpu");
if(check3->counter_done) rrdset_next_usec(check3, loop_usec);
- gettimeofday(&loop, NULL);
- rrddim_set(check3, "caller", (long long) usec_dt(&loop, &check1->last_collected_time));
- rrddim_set(check3, "netdata", (long long) usec_dt(&loop, &check2->last_collected_time));
- if(apps_cpu) rrddim_set(check3, "apps.plugin", (long long) usec_dt(&loop, &apps_cpu->last_collected_time));
+ now_realtime_timeval(&loop);
+ rrddim_set(check3, "caller", (long long) dt_usec(&loop, &check1->last_collected_time));
+ rrddim_set(check3, "netdata", (long long) dt_usec(&loop, &check2->last_collected_time));
+ if(apps_cpu) rrddim_set(check3, "apps.plugin", (long long) dt_usec(&loop, &apps_cpu->last_collected_time));
rrdset_done(check3);
}
// keep track of the time each module was called
unsigned long long sutime_freebsd_sysctl = 0ULL;
- unsigned long long step = rrd_update_every * 1000000ULL;
+ usec_t step = rrd_update_every * USEC_PER_SEC;
for(;;) {
- unsigned long long now = time_usec();
- unsigned long long next = now - (now % step) + step;
+ usec_t now = now_realtime_usec();
+ usec_t next = now - (now % step) + step;
while(now < next) {
sleep_usec(next - now);
- now = time_usec();
+ now = now_realtime_usec();
}
if(unlikely(netdata_exit)) break;
if(!vdo_freebsd_sysctl) {
debug(D_PROCNETDEV_LOOP, "FREEBSD: calling do_freebsd_sysctl().");
- now = time_usec();
+ now = now_realtime_usec();
vdo_freebsd_sysctl = do_freebsd_sysctl(rrd_update_every, (sutime_freebsd_sysctl > 0)?now - sutime_freebsd_sysctl:0ULL);
sutime_freebsd_sysctl = now;
}
int getsysctl(const char *name, void *ptr, size_t len);
-extern int do_freebsd_sysctl(int update_every, unsigned long long dt);
+extern int do_freebsd_sysctl(int update_every, usec_t dt);
#endif /* NETDATA_PLUGIN_FREEBSD_H */
struct timeval before, after;
unsigned long long counter;
for(counter = 0; 1 ;counter++) {
- unsigned long long usec = 0, susec = 0;
+ usec_t usec = 0, susec = 0;
- while(susec < (rrd_update_every * 1000000ULL)) {
+ while(susec < (rrd_update_every * USEC_PER_SEC)) {
- gettimeofday(&before, NULL);
+ now_realtime_timeval(&before);
sleep_usec(sleep_ms * 1000);
- gettimeofday(&after, NULL);
+ now_realtime_timeval(&after);
// calculate the time it took for a full loop
- usec = usec_dt(&after, &before);
+ usec = dt_usec(&after, &before);
susec += usec;
}
usec -= (sleep_ms * 1000);
struct nlmsghdr *nlh = NULL;
unsigned int seq = 0, portid = 0;
- seq = time(NULL) - 1;
+ seq = now_realtime_sec() - 1;
nl = mnl_socket_open(NETLINK_NETFILTER);
if(!nl) {
// ------------------------------------------------------------------------
struct timeval last, now;
- unsigned long long usec = 0, susec = 0;
+ usec_t usec = 0, susec = 0;
RRDSET *st = NULL;
- gettimeofday(&last, NULL);
+ now_realtime_timeval(&last);
// ------------------------------------------------------------------------
// --------------------------------------------------------------------
- gettimeofday(&now, NULL);
- usec = usec_dt(&now, &last) - susec;
+ now_realtime_timeval(&now);
+ usec = dt_usec(&now, &last) - susec;
debug(D_NFACCT_LOOP, "nfacct.plugin: last loop took %llu usec (worked for %llu, sleeped for %llu).", usec + susec, usec, susec);
if(usec < (rrd_update_every * 1000000ULL / 2ULL)) susec = (rrd_update_every * 1000000ULL) - usec;
int vdo_cpu_netdata = !config_get_boolean("plugin:proc", "netdata server resources", 1);
// keep track of the time each module was called
- unsigned long long sutime_proc_net_dev = 0ULL;
- unsigned long long sutime_proc_diskstats = 0ULL;
- unsigned long long sutime_proc_net_snmp = 0ULL;
- unsigned long long sutime_proc_net_snmp6 = 0ULL;
- unsigned long long sutime_proc_net_netstat = 0ULL;
- unsigned long long sutime_proc_net_stat_conntrack = 0ULL;
- unsigned long long sutime_proc_net_ip_vs_stats = 0ULL;
- unsigned long long sutime_proc_net_stat_synproxy = 0ULL;
- unsigned long long sutime_proc_stat = 0ULL;
- unsigned long long sutime_proc_meminfo = 0ULL;
- unsigned long long sutime_proc_vmstat = 0ULL;
- unsigned long long sutime_proc_net_rpc_nfs = 0ULL;
- unsigned long long sutime_proc_net_rpc_nfsd = 0ULL;
- unsigned long long sutime_proc_sys_kernel_random_entropy_avail = 0ULL;
- unsigned long long sutime_proc_interrupts = 0ULL;
- unsigned long long sutime_proc_softirqs = 0ULL;
- unsigned long long sutime_proc_net_softnet_stat = 0ULL;
- unsigned long long sutime_proc_loadavg = 0ULL;
- unsigned long long sutime_ipc = 0ULL;
- unsigned long long sutime_sys_kernel_mm_ksm = 0ULL;
-
- unsigned long long step = rrd_update_every * 1000000ULL;
+ usec_t sutime_proc_net_dev = 0ULL;
+ usec_t sutime_proc_diskstats = 0ULL;
+ usec_t sutime_proc_net_snmp = 0ULL;
+ usec_t sutime_proc_net_snmp6 = 0ULL;
+ usec_t sutime_proc_net_netstat = 0ULL;
+ usec_t sutime_proc_net_stat_conntrack = 0ULL;
+ usec_t sutime_proc_net_ip_vs_stats = 0ULL;
+ usec_t sutime_proc_net_stat_synproxy = 0ULL;
+ usec_t sutime_proc_stat = 0ULL;
+ usec_t sutime_proc_meminfo = 0ULL;
+ usec_t sutime_proc_vmstat = 0ULL;
+ usec_t sutime_proc_net_rpc_nfs = 0ULL;
+ usec_t sutime_proc_net_rpc_nfsd = 0ULL;
+ usec_t sutime_proc_sys_kernel_random_entropy_avail = 0ULL;
+ usec_t sutime_proc_interrupts = 0ULL;
+ usec_t sutime_proc_softirqs = 0ULL;
+ usec_t sutime_proc_net_softnet_stat = 0ULL;
+ usec_t sutime_proc_loadavg = 0ULL;
+ usec_t sutime_ipc = 0ULL;
+ usec_t sutime_sys_kernel_mm_ksm = 0ULL;
+
+ usec_t step = rrd_update_every * USEC_PER_SEC;
for(;;) {
- unsigned long long now = time_usec();
- unsigned long long next = now - (now % step) + step;
+ usec_t now = now_realtime_usec();
+ usec_t next = now - (now % step) + step;
while(now < next) {
sleep_usec(next - now);
- now = time_usec();
+ now = now_realtime_usec();
}
if(unlikely(netdata_exit)) break;
if(!vdo_sys_kernel_mm_ksm) {
debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_sys_kernel_mm_ksm().");
- now = time_usec();
+ now = now_realtime_usec();
vdo_sys_kernel_mm_ksm = do_sys_kernel_mm_ksm(rrd_update_every, (sutime_sys_kernel_mm_ksm > 0)?now - sutime_sys_kernel_mm_ksm:0ULL);
sutime_sys_kernel_mm_ksm = now;
}
if(!vdo_proc_loadavg) {
debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_loadavg().");
- now = time_usec();
+ now = now_realtime_usec();
vdo_proc_loadavg = do_proc_loadavg(rrd_update_every, (sutime_proc_loadavg > 0)?now - sutime_proc_loadavg:0ULL);
sutime_proc_loadavg = now;
}
if(!vdo_ipc) {
debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_ipc().");
- now = time_usec();
+ now = now_realtime_usec();
vdo_ipc = do_ipc(rrd_update_every, (sutime_ipc > 0)?now - sutime_ipc:0ULL);
sutime_ipc = now;
}
if(!vdo_proc_interrupts) {
debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_interrupts().");
- now = time_usec();
+ now = now_realtime_usec();
vdo_proc_interrupts = do_proc_interrupts(rrd_update_every, (sutime_proc_interrupts > 0)?now - sutime_proc_interrupts:0ULL);
sutime_proc_interrupts = now;
}
if(!vdo_proc_softirqs) {
debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_softirqs().");
- now = time_usec();
+ now = now_realtime_usec();
vdo_proc_softirqs = do_proc_softirqs(rrd_update_every, (sutime_proc_softirqs > 0)?now - sutime_proc_softirqs:0ULL);
sutime_proc_softirqs = now;
}
if(!vdo_proc_net_softnet_stat) {
debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_softnet_stat().");
- now = time_usec();
+ now = now_realtime_usec();
vdo_proc_net_softnet_stat = do_proc_net_softnet_stat(rrd_update_every, (sutime_proc_net_softnet_stat > 0)?now - sutime_proc_net_softnet_stat:0ULL);
sutime_proc_net_softnet_stat = now;
}
if(!vdo_proc_sys_kernel_random_entropy_avail) {
debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_sys_kernel_random_entropy_avail().");
- now = time_usec();
+ now = now_realtime_usec();
vdo_proc_sys_kernel_random_entropy_avail = do_proc_sys_kernel_random_entropy_avail(rrd_update_every, (sutime_proc_sys_kernel_random_entropy_avail > 0)?now - sutime_proc_sys_kernel_random_entropy_avail:0ULL);
sutime_proc_sys_kernel_random_entropy_avail = now;
}
if(!vdo_proc_net_dev) {
debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_dev().");
- now = time_usec();
+ now = now_realtime_usec();
vdo_proc_net_dev = do_proc_net_dev(rrd_update_every, (sutime_proc_net_dev > 0)?now - sutime_proc_net_dev:0ULL);
sutime_proc_net_dev = now;
}
if(!vdo_proc_diskstats) {
debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_diskstats().");
- now = time_usec();
+ now = now_realtime_usec();
vdo_proc_diskstats = do_proc_diskstats(rrd_update_every, (sutime_proc_diskstats > 0)?now - sutime_proc_diskstats:0ULL);
sutime_proc_diskstats = now;
}
if(!vdo_proc_net_snmp) {
debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_snmp().");
- now = time_usec();
+ now = now_realtime_usec();
vdo_proc_net_snmp = do_proc_net_snmp(rrd_update_every, (sutime_proc_net_snmp > 0)?now - sutime_proc_net_snmp:0ULL);
sutime_proc_net_snmp = now;
}
if(!vdo_proc_net_snmp6) {
debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_snmp6().");
- now = time_usec();
+ now = now_realtime_usec();
vdo_proc_net_snmp6 = do_proc_net_snmp6(rrd_update_every, (sutime_proc_net_snmp6 > 0)?now - sutime_proc_net_snmp6:0ULL);
sutime_proc_net_snmp6 = now;
}
if(!vdo_proc_net_netstat) {
debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_netstat().");
- now = time_usec();
+ now = now_realtime_usec();
vdo_proc_net_netstat = do_proc_net_netstat(rrd_update_every, (sutime_proc_net_netstat > 0)?now - sutime_proc_net_netstat:0ULL);
sutime_proc_net_netstat = now;
}
if(!vdo_proc_net_stat_conntrack) {
debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_stat_conntrack().");
- now = time_usec();
+ now = now_realtime_usec();
vdo_proc_net_stat_conntrack = do_proc_net_stat_conntrack(rrd_update_every, (sutime_proc_net_stat_conntrack > 0)?now - sutime_proc_net_stat_conntrack:0ULL);
sutime_proc_net_stat_conntrack = now;
}
if(!vdo_proc_net_ip_vs_stats) {
debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling vdo_proc_net_ip_vs_stats().");
- now = time_usec();
+ now = now_realtime_usec();
vdo_proc_net_ip_vs_stats = do_proc_net_ip_vs_stats(rrd_update_every, (sutime_proc_net_ip_vs_stats > 0)?now - sutime_proc_net_ip_vs_stats:0ULL);
sutime_proc_net_ip_vs_stats = now;
}
if(!vdo_proc_net_stat_synproxy) {
debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling vdo_proc_net_stat_synproxy().");
- now = time_usec();
+ now = now_realtime_usec();
vdo_proc_net_stat_synproxy = do_proc_net_stat_synproxy(rrd_update_every, (sutime_proc_net_stat_synproxy > 0)?now - sutime_proc_net_stat_synproxy:0ULL);
sutime_proc_net_stat_synproxy = now;
}
if(!vdo_proc_stat) {
debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_stat().");
- now = time_usec();
+ now = now_realtime_usec();
vdo_proc_stat = do_proc_stat(rrd_update_every, (sutime_proc_stat > 0)?now - sutime_proc_stat:0ULL);
sutime_proc_stat = now;
}
if(!vdo_proc_meminfo) {
debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling vdo_proc_meminfo().");
- now = time_usec();
+ now = now_realtime_usec();
vdo_proc_meminfo = do_proc_meminfo(rrd_update_every, (sutime_proc_meminfo > 0)?now - sutime_proc_meminfo:0ULL);
sutime_proc_meminfo = now;
}
if(!vdo_proc_vmstat) {
debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling vdo_proc_vmstat().");
- now = time_usec();
+ now = now_realtime_usec();
vdo_proc_vmstat = do_proc_vmstat(rrd_update_every, (sutime_proc_vmstat > 0)?now - sutime_proc_vmstat:0ULL);
sutime_proc_vmstat = now;
}
if(!vdo_proc_net_rpc_nfsd) {
debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_rpc_nfsd().");
- now = time_usec();
+ now = now_realtime_usec();
vdo_proc_net_rpc_nfsd = do_proc_net_rpc_nfsd(rrd_update_every, (sutime_proc_net_rpc_nfsd > 0)?now - sutime_proc_net_rpc_nfsd:0ULL);
sutime_proc_net_rpc_nfsd = now;
}
if(!vdo_proc_net_rpc_nfs) {
debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_rpc_nfs().");
- now = time_usec();
+ now = now_realtime_usec();
vdo_proc_net_rpc_nfs = do_proc_net_rpc_nfs(rrd_update_every, (sutime_proc_net_rpc_nfs > 0)?now - sutime_proc_net_rpc_nfs:0ULL);
sutime_proc_net_rpc_nfs = now;
}
void *proc_main(void *ptr);
-extern int do_proc_net_dev(int update_every, unsigned long long dt);
-extern int do_proc_diskstats(int update_every, unsigned long long dt);
-extern int do_proc_net_snmp(int update_every, unsigned long long dt);
-extern int do_proc_net_snmp6(int update_every, unsigned long long dt);
-extern int do_proc_net_netstat(int update_every, unsigned long long dt);
-extern int do_proc_net_stat_conntrack(int update_every, unsigned long long dt);
-extern int do_proc_net_ip_vs_stats(int update_every, unsigned long long dt);
-extern int do_proc_stat(int update_every, unsigned long long dt);
-extern int do_proc_meminfo(int update_every, unsigned long long dt);
-extern int do_proc_vmstat(int update_every, unsigned long long dt);
-extern int do_proc_net_rpc_nfs(int update_every, unsigned long long dt);
-extern int do_proc_net_rpc_nfsd(int update_every, unsigned long long dt);
-extern int do_proc_sys_kernel_random_entropy_avail(int update_every, unsigned long long dt);
-extern int do_proc_interrupts(int update_every, unsigned long long dt);
-extern int do_proc_softirqs(int update_every, unsigned long long dt);
-extern int do_sys_kernel_mm_ksm(int update_every, unsigned long long dt);
-extern int do_proc_loadavg(int update_every, unsigned long long dt);
-extern int do_proc_net_stat_synproxy(int update_every, unsigned long long dt);
-extern int do_proc_net_softnet_stat(int update_every, unsigned long long dt);
+extern int do_proc_net_dev(int update_every, usec_t dt);
+extern int do_proc_diskstats(int update_every, usec_t dt);
+extern int do_proc_net_snmp(int update_every, usec_t dt);
+extern int do_proc_net_snmp6(int update_every, usec_t dt);
+extern int do_proc_net_netstat(int update_every, usec_t dt);
+extern int do_proc_net_stat_conntrack(int update_every, usec_t dt);
+extern int do_proc_net_ip_vs_stats(int update_every, usec_t dt);
+extern int do_proc_stat(int update_every, usec_t dt);
+extern int do_proc_meminfo(int update_every, usec_t dt);
+extern int do_proc_vmstat(int update_every, usec_t dt);
+extern int do_proc_net_rpc_nfs(int update_every, usec_t dt);
+extern int do_proc_net_rpc_nfsd(int update_every, usec_t dt);
+extern int do_proc_sys_kernel_random_entropy_avail(int update_every, usec_t dt);
+extern int do_proc_interrupts(int update_every, usec_t dt);
+extern int do_proc_softirqs(int update_every, usec_t dt);
+extern int do_sys_kernel_mm_ksm(int update_every, usec_t dt);
+extern int do_proc_loadavg(int update_every, usec_t dt);
+extern int do_proc_net_stat_synproxy(int update_every, usec_t dt);
+extern int do_proc_net_softnet_stat(int update_every, usec_t dt);
#endif /* NETDATA_PLUGIN_PROC_H */
char line[PLUGINSD_LINE_MAX + 1];
#ifdef DETACH_PLUGINS_FROM_NETDATA
- unsigned long long usec = 0, susec = 0;
+ usec_t usec = 0, susec = 0;
struct timeval last = {0, 0} , now = {0, 0};
#endif
}
if(likely(st->counter_done)) {
- unsigned long long microseconds = 0;
+ usec_t microseconds = 0;
if(microseconds_txt && *microseconds_txt) microseconds = strtoull(microseconds_txt, NULL, 10);
if(microseconds) rrdset_next_usec(st, microseconds);
else rrdset_next(st);
else if(likely(hash == STOPPING_WAKE_ME_UP_PLEASE_HASH && !strcmp(s, "STOPPING_WAKE_ME_UP_PLEASE"))) {
error("PLUGINSD: '%s' (pid %d) called STOPPING_WAKE_ME_UP_PLEASE.", cd->fullfilename, cd->pid);
- gettimeofday(&now, NULL);
+ now_realtime_timeval(&now);
if(unlikely(!usec && !susec)) {
// our first run
- susec = cd->rrd_update_every * 1000000ULL;
+ susec = cd->rrd_update_every * USEC_PER_SEC;
}
else {
// second+ run
- usec = usec_dt(&now, &last) - susec;
+ usec = dt_usec(&now, &last) - susec;
error("PLUGINSD: %s last loop took %llu usec (worked for %llu, sleeped for %llu).\n", cd->fullfilename, usec + susec, usec, susec);
- if(unlikely(usec < (rrd_update_every * 1000000ULL / 2ULL))) susec = (rrd_update_every * 1000000ULL) - usec;
- else susec = rrd_update_every * 1000000ULL / 2ULL;
+ if(unlikely(usec < (rrd_update_every * USEC_PER_SEC / 2ULL))) susec = (rrd_update_every * USEC_PER_SEC) - usec;
+ else susec = rrd_update_every * USEC_PER_SEC / 2ULL;
}
error("PLUGINSD: %s sleeping for %llu. Will kill with SIGCONT pid %d to wake it up.\n", cd->fullfilename, susec, cd->pid);
cd->enabled = enabled;
cd->update_every = (int) config_get_number(cd->id, "update every", rrd_update_every);
- cd->started_t = time(NULL);
+ cd->started_t = now_realtime_sec();
char *def = "";
snprintfz(cd->cmd, PLUGINSD_CMD_MAX, "exec %s %d %s", cd->fullfilename, cd->update_every, config_get(cd->id, "command options", def));
static inline void mountinfo_reload(int force) {
static time_t last_loaded = 0;
- time_t now = time(NULL);
+ time_t now = now_realtime_sec();
if(force || now - last_loaded >= NETDATA_RELOAD_MOUNTINFO_EVERY) {
//#ifdef NETDATA_INTERNAL_CHECKS
int do_inodes;
};
-static inline void do_disk_space_stats(struct disk *d, const char *mount_point, const char *mount_source, const char *disk, const char *family, int update_every, unsigned long long dt) {
+static inline void do_disk_space_stats(struct mountinfo *mi, int update_every, usec_t dt) {
(void)dt;
+ const char *family = mi->mount_point;
+ const char *disk = mi->persistent_id;
+
static DICTIONARY *mount_points = NULL;
int do_space, do_inodes;
mount_points = dictionary_create(DICTIONARY_FLAG_SINGLE_THREADED);
}
- if(unlikely(d)) {
- // verify we collected the metrics for the right disk.
- // if not the mountpoint has changed.
-
- struct stat buff_stat;
- if(unlikely(stat(mount_point, &buff_stat) == -1)) {
- error("Failed to stat() for '%s' (disk '%s')", mount_point, disk);
- return;
- }
- else if(unlikely(major(buff_stat.st_dev) != d->major || minor(buff_stat.st_dev) != d->minor)) {
- error("Disk '%s' (disk '%s') switched major:minor", mount_point, disk);
- freez(d->mount_point);
- d->mount_point = NULL;
- d->mount_point_hash = 0;
- return;
- }
-
- do_space = d->do_space;
- do_inodes = d->do_inodes;
- }
- else {
- struct mount_point_metadata *m = dictionary_get(mount_points, mount_point);
- if(unlikely(!m)) {
- char var_name[4096 + 1];
- snprintfz(var_name, 4096, "plugin:proc:/proc/diskstats:%s", mount_point);
+ struct mount_point_metadata *m = dictionary_get(mount_points, mi->mount_point);
+ if(unlikely(!m)) {
+ char var_name[4096 + 1];
+ snprintfz(var_name, 4096, "plugin:proc:/proc/diskstats:%s", mi->mount_point);
- int def_space = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "space usage for all disks", CONFIG_ONDEMAND_ONDEMAND);
- int def_inodes = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "inodes usage for all disks", CONFIG_ONDEMAND_ONDEMAND);
+ int def_space = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "space usage for all disks", CONFIG_ONDEMAND_ONDEMAND);
+ int def_inodes = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "inodes usage for all disks", CONFIG_ONDEMAND_ONDEMAND);
- if(unlikely(is_mount_point_excluded(mount_point))) {
- def_space = CONFIG_ONDEMAND_NO;
- def_inodes = CONFIG_ONDEMAND_NO;
- }
+ if(unlikely(is_mount_point_excluded(mi->mount_point))) {
+ def_space = CONFIG_ONDEMAND_NO;
+ def_inodes = CONFIG_ONDEMAND_NO;
+ }
- do_space = config_get_boolean_ondemand(var_name, "space usage", def_space);
- do_inodes = config_get_boolean_ondemand(var_name, "inodes usage", def_inodes);
+ do_space = config_get_boolean_ondemand(var_name, "space usage", def_space);
+ do_inodes = config_get_boolean_ondemand(var_name, "inodes usage", def_inodes);
- struct mount_point_metadata mp = {
- .do_space = do_space,
- .do_inodes = do_inodes
- };
+ struct mount_point_metadata mp = {
+ .do_space = do_space,
+ .do_inodes = do_inodes
+ };
- dictionary_set(mount_points, mount_point, &mp, sizeof(struct mount_point_metadata));
- }
- else {
- do_space = m->do_space;
- do_inodes = m->do_inodes;
- }
+ dictionary_set(mount_points, mi->mount_point, &mp, sizeof(struct mount_point_metadata));
+ }
+ else {
+ do_space = m->do_space;
+ do_inodes = m->do_inodes;
}
if(unlikely(do_space == CONFIG_ONDEMAND_NO && do_inodes == CONFIG_ONDEMAND_NO))
return;
struct statvfs buff_statvfs;
- if (statvfs(mount_point, &buff_statvfs) < 0) {
- error("Failed statvfs() for '%s' (disk '%s')", mount_point, disk);
+ if (statvfs(mi->mount_point, &buff_statvfs) < 0) {
+ error("Failed statvfs() for '%s' (disk '%s')", mi->mount_point, disk);
return;
}
#ifdef NETDATA_INTERNAL_CHECKS
if(unlikely(btotal != bavail + breserved_root + bused))
- error("Disk block statistics for '%s' (disk '%s') do not sum up: total = %llu, available = %llu, reserved = %llu, used = %llu", mount_point, disk, (unsigned long long)btotal, (unsigned long long)bavail, (unsigned long long)breserved_root, (unsigned long long)bused);
+ error("Disk block statistics for '%s' (disk '%s') do not sum up: total = %llu, available = %llu, reserved = %llu, used = %llu", mi->mount_point, disk, (unsigned long long)btotal, (unsigned long long)bavail, (unsigned long long)breserved_root, (unsigned long long)bused);
#endif
// --------------------------------------------------------------------------
#ifdef NETDATA_INTERNAL_CHECKS
if(unlikely(btotal != bavail + breserved_root + bused))
- error("Disk inode statistics for '%s' (disk '%s') do not sum up: total = %llu, available = %llu, reserved = %llu, used = %llu", mount_point, disk, (unsigned long long)ftotal, (unsigned long long)favail, (unsigned long long)freserved_root, (unsigned long long)fused);
+ error("Disk inode statistics for '%s' (disk '%s') do not sum up: total = %llu, available = %llu, reserved = %llu, used = %llu", mi->mount_point, disk, (unsigned long long)ftotal, (unsigned long long)favail, (unsigned long long)freserved_root, (unsigned long long)fused);
#endif
// --------------------------------------------------------------------------
st = rrdset_find_bytype("disk_space", disk);
if(unlikely(!st)) {
char title[4096 + 1];
- snprintfz(title, 4096, "Disk Space Usage for %s [%s]", family, mount_source);
+ snprintfz(title, 4096, "Disk Space Usage for %s [%s]", family, mi->mount_source);
st = rrdset_create("disk_space", disk, NULL, family, "disk.space", title, "GB", 2023, update_every, RRDSET_TYPE_STACKED);
rrddim_add(st, "avail", NULL, bsize, 1024*1024*1024, RRDDIM_ABSOLUTE);
}
else rrdset_next(st);
- rrddim_set(st, "avail", bavail);
- rrddim_set(st, "used", bused);
- rrddim_set(st, "reserved_for_root", breserved_root);
+ rrddim_set(st, "avail", (collected_number)bavail);
+ rrddim_set(st, "used", (collected_number)bused);
+ rrddim_set(st, "reserved_for_root", (collected_number)breserved_root);
rrdset_done(st);
}
st = rrdset_find_bytype("disk_inodes", disk);
if(unlikely(!st)) {
char title[4096 + 1];
- snprintfz(title, 4096, "Disk Files (inodes) Usage for %s [%s]", family, mount_source);
+ snprintfz(title, 4096, "Disk Files (inodes) Usage for %s [%s]", family, mi->mount_source);
st = rrdset_create("disk_inodes", disk, NULL, family, "disk.inodes", title, "Inodes", 2024, update_every, RRDSET_TYPE_STACKED);
rrddim_add(st, "avail", NULL, 1, 1, RRDDIM_ABSOLUTE);
}
else rrdset_next(st);
- rrddim_set(st, "avail", favail);
- rrddim_set(st, "used", fused);
- rrddim_set(st, "reserved_for_root", freserved_root);
+ rrddim_set(st, "avail", (collected_number)favail);
+ rrddim_set(st, "used", (collected_number)fused);
+ rrddim_set(st, "reserved_for_root", (collected_number)freserved_root);
rrdset_done(st);
}
}
return CONFIG_ONDEMAND_NO;
}
-int do_proc_diskstats(int update_every, unsigned long long dt) {
+int do_proc_diskstats(int update_every, usec_t dt) {
(void)dt;
static procfile *ff = NULL;
rrdset_done(st);
}
}
-
-/*
- // --------------------------------------------------------------------------
- // space metrics
-
- if(unlikely( d->mount_point && (d->do_space || d->do_inodes) )) {
- do_disk_space_stats(d, d->mount_point, disk, disk, family, update_every, dt);
- }
-*/
}
// --------------------------------------------------------------------------
struct mountinfo *mi;
for(mi = disk_mountinfo_root; mi ;mi = mi->next) {
- if(unlikely(mi->flags & (MOUNTINFO_IS_DUMMY|MOUNTINFO_IS_BIND|MOUNTINFO_IS_SAME_DEV|MOUNTINFO_NO_STAT|MOUNTINFO_NO_SIZE)))
+ if(unlikely(mi->flags & (MOUNTINFO_IS_DUMMY|MOUNTINFO_IS_BIND|MOUNTINFO_IS_SAME_DEV|MOUNTINFO_NO_STAT|MOUNTINFO_NO_SIZE|MOUNTINFO_READONLY)))
continue;
-/*
- // skip the ones with block devices
- int skip = 0;
- struct disk *d;
- for(d = disk_root; d ;d = d->next) {
- if(unlikely(d->mount_point && mi->mount_point_hash == d->mount_point_hash && strcmp(mi->mount_point, d->mount_point))) {
- skip = 1;
- break;
- }
- }
-
- if(unlikely(skip))
- continue;
-
- // fprintf(stderr, "Will process mount point '%s', source '%s', filesystem '%s'\n", mi->mount_point, mi->mount_source, mi->filesystem);
-*/
-
- do_disk_space_stats(NULL, mi->mount_point, mi->mount_source, mi->persistent_id, mi->mount_point , update_every, dt);
+ do_disk_space_stats(mi, update_every, dt);
}
return 0;
#define MAX_INTERRUPT_NAME 50
+struct cpu_interrupt {
+ unsigned long long value;
+ RRDDIM *rd;
+};
+
struct interrupt {
int used;
char *id;
char name[MAX_INTERRUPT_NAME + 1];
+ RRDDIM *rd;
unsigned long long total;
- unsigned long long value[];
+ struct cpu_interrupt cpu[];
};
// since each interrupt is variable in size
// we use this to calculate its record size
-#define recordsize(cpus) (sizeof(struct interrupt) + (cpus * sizeof(unsigned long long)))
+#define recordsize(cpus) (sizeof(struct interrupt) + (cpus * sizeof(struct cpu_interrupt)))
// given a base, get a pointer to each record
#define irrindex(base, line, cpus) ((struct interrupt *)&((char *)(base))[line * recordsize(cpus)])
-static inline struct interrupt *get_interrupts_array(int lines, int cpus) {
+static inline struct interrupt *get_interrupts_array(uint32_t lines, int cpus) {
static struct interrupt *irrs = NULL;
- static int allocated = 0;
+ static uint32_t allocated = 0;
+
+ if(unlikely(lines != allocated)) {
+ uint32_t l;
+ int c;
- if(unlikely(lines > allocated)) {
irrs = (struct interrupt *)reallocz(irrs, lines * recordsize(cpus));
+
+ // reset all interrupt RRDDIM pointers as any line could have shifted
+ for(l = 0; l < lines ;l++) {
+ struct interrupt *irr = irrindex(irrs, l, cpus);
+ irr->rd = NULL;
+ irr->name[0] = '\0';
+ for(c = 0; c < cpus ;c++)
+ irr->cpu[c].rd = NULL;
+ }
+
allocated = lines;
}
return irrs;
}
-int do_proc_interrupts(int update_every, unsigned long long dt) {
+int do_proc_interrupts(int update_every, usec_t dt) {
(void)dt;
-
static procfile *ff = NULL;
static int cpus = -1, do_per_core = -1;
struct interrupt *irrs = NULL;
uint32_t w;
cpus = 0;
for(w = 0; w < words ; w++) {
- if(unlikely(strncmp(procfile_lineword(ff, 0, w), "CPU", 3) == 0))
+ if(likely(strncmp(procfile_lineword(ff, 0, w), "CPU", 3) == 0))
cpus++;
}
}
int c;
for(c = 0; c < cpus ;c++) {
- if(unlikely((c + 1) < (int)words))
- irr->value[c] = strtoull(procfile_lineword(ff, l, (uint32_t)(c + 1)), NULL, 10);
+ if(likely((c + 1) < (int)words))
+ irr->cpu[c].value = strtoull(procfile_lineword(ff, l, (uint32_t)(c + 1)), NULL, 10);
else
- irr->value[c] = 0;
+ irr->cpu[c].value = 0;
- irr->total += irr->value[c];
+ irr->total += irr->cpu[c].value;
}
if(unlikely(isdigit(irr->id[0]) && (uint32_t)(cpus + 2) < words)) {
strncpyz(irr->name, procfile_lineword(ff, l, words - 1), MAX_INTERRUPT_NAME);
int nlen = strlen(irr->name);
- if(unlikely(nlen < (MAX_INTERRUPT_NAME-1))) {
+ int idlen = strlen(irr->id);
+ if(likely(nlen + 1 + idlen <= MAX_INTERRUPT_NAME)) {
irr->name[nlen] = '_';
- strncpyz(&irr->name[nlen + 1], irr->id, MAX_INTERRUPT_NAME - nlen);
+ strncpyz(&irr->name[nlen + 1], irr->id, MAX_INTERRUPT_NAME - nlen - 1);
+ }
+ else {
+ irr->name[MAX_INTERRUPT_NAME - idlen - 1] = '_';
+ strncpyz(&irr->name[MAX_INTERRUPT_NAME - idlen], irr->id, idlen);
}
}
else {
// --------------------------------------------------------------------
st = rrdset_find_bytype("system", "interrupts");
- if(unlikely(!st)) {
- st = rrdset_create("system", "interrupts", NULL, "interrupts", NULL, "System interrupts", "interrupts/s", 1000, update_every, RRDSET_TYPE_STACKED);
-
- for(l = 0; l < lines ;l++) {
- struct interrupt *irr = irrindex(irrs, l, cpus);
- if(unlikely(!irr->used)) continue;
- rrddim_add(st, irr->id, irr->name, 1, 1, RRDDIM_INCREMENTAL);
- }
- }
+ if(unlikely(!st)) st = rrdset_create("system", "interrupts", NULL, "interrupts", NULL, "System interrupts", "interrupts/s", 1000, update_every, RRDSET_TYPE_STACKED);
else rrdset_next(st);
for(l = 0; l < lines ;l++) {
struct interrupt *irr = irrindex(irrs, l, cpus);
if(unlikely(!irr->used)) continue;
- rrddim_set(st, irr->id, irr->total);
+ // some interrupt may have changed without changing the total number of lines
+ // if the same number of interrupts have been added and removed between two
+ // calls of this function.
+ if(unlikely(!irr->rd || strncmp(irr->rd->name, irr->name, MAX_INTERRUPT_NAME) != 0)) {
+ irr->rd = rrddim_find(st, irr->id);
+ if(unlikely(!irr->rd))
+ irr->rd = rrddim_add(st, irr->id, irr->name, 1, 1, RRDDIM_INCREMENTAL);
+ else
+ rrddim_set_name(st, irr->rd, irr->name);
+
+ // also reset per cpu RRDDIMs to avoid repeating strncmp() in the per core loop
+ if(likely(do_per_core)) {
+ int c;
+ for (c = 0; c < cpus ;c++)
+ irr->cpu[c].rd = NULL;
+ }
+ }
+ rrddim_set_by_pointer(st, irr->rd, irr->total);
}
rrdset_done(st);
if(likely(do_per_core)) {
int c;
- for(c = 0; c < cpus ; c++) {
+ for(c = 0; c < cpus ;c++) {
char id[50+1];
snprintfz(id, 50, "cpu%d_interrupts", c);
char title[100+1];
snprintfz(title, 100, "CPU%d Interrupts", c);
st = rrdset_create("cpu", id, NULL, "interrupts", "cpu.interrupts", title, "interrupts/s", 1100 + c, update_every, RRDSET_TYPE_STACKED);
-
- for(l = 0; l < lines ;l++) {
- struct interrupt *irr = irrindex(irrs, l, cpus);
- if(unlikely(!irr->used)) continue;
- rrddim_add(st, irr->id, irr->name, 1, 1, RRDDIM_INCREMENTAL);
- }
}
else rrdset_next(st);
for(l = 0; l < lines ;l++) {
struct interrupt *irr = irrindex(irrs, l, cpus);
if(unlikely(!irr->used)) continue;
- rrddim_set(st, irr->id, irr->value[c]);
+ if(unlikely(!irr->cpu[c].rd)) {
+ irr->cpu[c].rd = rrddim_find(st, irr->id);
+ if(unlikely(!irr->cpu[c].rd))
+ irr->cpu[c].rd = rrddim_add(st, irr->id, irr->name, 1, 1, RRDDIM_INCREMENTAL);
+ else
+ rrddim_set_name(st, irr->cpu[c].rd, irr->name);
+ }
+ rrddim_set_by_pointer(st, irr->cpu[c].rd, irr->cpu[c].value);
}
rrdset_done(st);
}
// linux calculates this once every 5 seconds
#define MIN_LOADAVG_UPDATE_EVERY 5
-int do_proc_loadavg(int update_every, unsigned long long dt) {
+int do_proc_loadavg(int update_every, usec_t dt) {
(void)dt;
static procfile *ff = NULL;
static int do_loadavg = -1, do_all_processes = -1;
- static unsigned long long last_loadavg_usec = 0;
+ static usec_t last_loadavg_usec = 0;
static RRDSET *load_chart = NULL, *processes_chart = NULL;
if(unlikely(!ff)) {
rrdset_done(load_chart);
}
- last_loadavg_usec = load_chart->update_every * 1000000ULL;
+ last_loadavg_usec = load_chart->update_every * USEC_PER_SEC;
}
else last_loadavg_usec -= dt;
#include "common.h"
-int do_proc_meminfo(int update_every, unsigned long long dt) {
+int do_proc_meminfo(int update_every, usec_t dt) {
(void)dt;
static procfile *ff = NULL;
#include "common.h"
-int do_proc_net_dev(int update_every, unsigned long long dt) {
+int do_proc_net_dev(int update_every, usec_t dt) {
static procfile *ff = NULL;
static int enable_new_interfaces = -1, enable_ifb_interfaces = -1;
static int do_bandwidth = -1, do_packets = -1, do_errors = -1, do_drops = -1, do_fifo = -1, do_compressed = -1, do_events = -1;
#define RRD_TYPE_NET_IPVS "ipvs"
#define RRD_TYPE_NET_IPVS_LEN strlen(RRD_TYPE_NET_IPVS)
-int do_proc_net_ip_vs_stats(int update_every, unsigned long long dt) {
+int do_proc_net_ip_vs_stats(int update_every, usec_t dt) {
static int do_bandwidth = -1, do_sockets = -1, do_packets = -1;
static procfile *ff = NULL;
}
-int do_proc_net_netstat(int update_every, unsigned long long dt) {
+int do_proc_net_netstat(int update_every, usec_t dt) {
(void)dt;
static int do_bandwidth = -1, do_inerrors = -1, do_mcast = -1, do_bcast = -1, do_mcast_p = -1, do_bcast_p = -1, do_ecn = -1, \
{ "", 0ULL, 0 }
};
-int do_proc_net_rpc_nfs(int update_every, unsigned long long dt) {
+int do_proc_net_rpc_nfs(int update_every, usec_t dt) {
(void)dt;
static procfile *ff = NULL;
};
-int do_proc_net_rpc_nfsd(int update_every, unsigned long long dt) {
+int do_proc_net_rpc_nfsd(int update_every, usec_t dt) {
static procfile *ff = NULL;
static int do_rc = -1, do_fh = -1, do_io = -1, do_th = -1, do_ra = -1, do_net = -1, do_rpc = -1, do_proc2 = -1, do_proc3 = -1, do_proc4 = -1, do_proc4ops = -1;
static int ra_warning = 0, th_warning = 0, proc2_warning = 0, proc3_warning = 0, proc4_warning = 0, proc4ops_warning = 0;
}
}
-int do_proc_net_snmp(int update_every, unsigned long long dt) {
+int do_proc_net_snmp(int update_every, usec_t dt) {
(void)dt;
static procfile *ff = NULL;
#define RRD_TYPE_NET_SNMP6 "ipv6"
#define RRD_TYPE_NET_SNMP6_LEN strlen(RRD_TYPE_NET_SNMP6)
-int do_proc_net_snmp6(int update_every, unsigned long long dt) {
+int do_proc_net_snmp6(int update_every, usec_t dt) {
(void)dt;
static procfile *ff = NULL;
}
}
-int do_proc_net_softnet_stat(int update_every, unsigned long long dt) {
+int do_proc_net_softnet_stat(int update_every, usec_t dt) {
(void)dt;
static procfile *ff = NULL;
#define RRD_TYPE_NET_STAT_NETFILTER "netfilter"
#define RRD_TYPE_NET_STAT_CONNTRACK "conntrack"
-int do_proc_net_stat_conntrack(int update_every, unsigned long long dt) {
+int do_proc_net_stat_conntrack(int update_every, usec_t dt) {
static procfile *ff = NULL;
static int do_sockets = -1, do_new = -1, do_changes = -1, do_expect = -1, do_search = -1, do_errors = -1;
- static unsigned long long get_max_every = 10 * 1000000ULL, usec_since_last_max = 0;
+ static usec_t get_max_every = 10 * USEC_PER_SEC, usec_since_last_max = 0;
static int read_full = 1;
static char *nf_conntrack_filename, *nf_conntrack_count_filename, *nf_conntrack_max_filename;
static RRDVAR *rrdvar_max = NULL;
snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/sys/net/netfilter/nf_conntrack_max");
nf_conntrack_max_filename = config_get("plugin:proc:/proc/sys/net/netfilter/nf_conntrack_max", "filename to monitor", filename);
- usec_since_last_max = get_max_every = config_get_number("plugin:proc:/proc/sys/net/netfilter/nf_conntrack_max", "read every seconds", 10) * 1000000ULL;
+ usec_since_last_max = get_max_every = config_get_number("plugin:proc:/proc/sys/net/netfilter/nf_conntrack_max", "read every seconds", 10) * USEC_PER_SEC;
read_full = 1;
ff = procfile_open(nf_conntrack_filename, " \t:", PROCFILE_FLAG_DEFAULT);
#define RRD_TYPE_NET_STAT_NETFILTER "netfilter"
#define RRD_TYPE_NET_STAT_SYNPROXY "synproxy"
-int do_proc_net_stat_synproxy(int update_every, unsigned long long dt) {
+int do_proc_net_stat_synproxy(int update_every, usec_t dt) {
(void)dt;
static int do_entries = -1, do_cookies = -1, do_syns = -1, do_reopened = -1;
return buffer;
}
+static inline int is_read_only(const char *s) {
+ if(!s) return 0;
+
+ size_t len = strlen(s);
+ if(len < 2) return 0;
+ if(len == 2) {
+ if(!strcmp(s, "ro")) return 1;
+ return 0;
+ }
+ if(!strncmp(s, "ro,", 3)) return 1;
+ if(!strncmp(&s[len - 3], ",ro", 3)) return 1;
+ if(strstr(s, ",ro,")) return 1;
+ return 0;
+}
+
// read the whole mountinfo into a linked list
struct mountinfo *mountinfo_read() {
char filename[FILENAME_MAX + 1];
mi->mount_options = strdupz(procfile_lineword(ff, l, w)); w++;
+ if(unlikely(is_read_only(mi->mount_options)))
+ mi->flags |= MOUNTINFO_READONLY;
+
// count the optional fields
/*
unsigned long wo = w;
mi->super_options = strdupz(procfile_lineword(ff, l, w)); w++;
+ if(unlikely(is_read_only(mi->super_options)))
+ mi->flags |= MOUNTINFO_READONLY;
+
if(unlikely(ME_DUMMY(mi->mount_source, mi->filesystem)))
mi->flags |= MOUNTINFO_IS_DUMMY;
#define MOUNTINFO_IS_SAME_DEV 0x00000008
#define MOUNTINFO_NO_STAT 0x00000010
#define MOUNTINFO_NO_SIZE 0x00000020
+#define MOUNTINFO_READONLY 0x00000040
struct mountinfo {
long id; // mount ID: unique identifier of the mount (may be reused after umount(2)).
#define MAX_INTERRUPT_NAME 50
+struct cpu_interrupt {
+ unsigned long long value;
+ RRDDIM *rd;
+};
+
struct interrupt {
int used;
char *id;
char name[MAX_INTERRUPT_NAME + 1];
+ RRDDIM *rd;
unsigned long long total;
- unsigned long long value[];
+ struct cpu_interrupt cpu[];
};
// since each interrupt is variable in size
// we use this to calculate its record size
-#define recordsize(cpus) (sizeof(struct interrupt) + (cpus * sizeof(unsigned long long)))
+#define recordsize(cpus) (sizeof(struct interrupt) + (cpus * sizeof(struct cpu_interrupt)))
// given a base, get a pointer to each record
#define irrindex(base, line, cpus) ((struct interrupt *)&((char *)(base))[line * recordsize(cpus)])
-static inline struct interrupt *get_interrupts_array(int lines, int cpus) {
+static inline struct interrupt *get_interrupts_array(uint32_t lines, int cpus) {
static struct interrupt *irrs = NULL;
- static int allocated = 0;
+ static uint32_t allocated = 0;
+
+ if(unlikely(lines != allocated)) {
+ uint32_t l;
+ int c;
- if(unlikely(lines > allocated)) {
irrs = (struct interrupt *)reallocz(irrs, lines * recordsize(cpus));
+
+ // reset all interrupt RRDDIM pointers as any line could have shifted
+ for(l = 0; l < lines ;l++) {
+ struct interrupt *irr = irrindex(irrs, l, cpus);
+ irr->rd = NULL;
+ irr->name[0] = '\0';
+ for(c = 0; c < cpus ;c++)
+ irr->cpu[c].rd = NULL;
+ }
+
allocated = lines;
}
return irrs;
}
-int do_proc_softirqs(int update_every, unsigned long long dt) {
+int do_proc_softirqs(int update_every, usec_t dt) {
(void)dt;
-
static procfile *ff = NULL;
static int cpus = -1, do_per_core = -1;
-
struct interrupt *irrs = NULL;
if(unlikely(do_per_core == -1)) do_per_core = config_get_boolean("plugin:proc:/proc/softirqs", "interrupts per core", 1);
uint32_t w;
cpus = 0;
for(w = 0; w < words ; w++) {
- if(unlikely(strncmp(procfile_lineword(ff, 0, w), "CPU", 3) == 0))
+ if(likely(strncmp(procfile_lineword(ff, 0, w), "CPU", 3) == 0))
cpus++;
}
}
int c;
for(c = 0; c < cpus ;c++) {
- if(unlikely((c + 1) < (int)words))
- irr->value[c] = strtoull(procfile_lineword(ff, l, (uint32_t)(c + 1)), NULL, 10);
+ if(likely((c + 1) < (int)words))
+ irr->cpu[c].value = strtoull(procfile_lineword(ff, l, (uint32_t)(c + 1)), NULL, 10);
else
- irr->value[c] = 0;
+ irr->cpu[c].value = 0;
- irr->total += irr->value[c];
+ irr->total += irr->cpu[c].value;
}
strncpyz(irr->name, irr->id, MAX_INTERRUPT_NAME);
// --------------------------------------------------------------------
st = rrdset_find_bytype("system", "softirqs");
- if(unlikely(!st)) {
- st = rrdset_create("system", "softirqs", NULL, "softirqs", NULL, "System softirqs", "softirqs/s", 950, update_every, RRDSET_TYPE_STACKED);
-
- for(l = 0; l < lines ;l++) {
- struct interrupt *irr = irrindex(irrs, l, cpus);
- if(unlikely(!irr->used)) continue;
- rrddim_add(st, irr->id, irr->name, 1, 1, RRDDIM_INCREMENTAL);
- }
- }
+ if(unlikely(!st)) st = rrdset_create("system", "softirqs", NULL, "softirqs", NULL, "System softirqs", "softirqs/s", 950, update_every, RRDSET_TYPE_STACKED);
else rrdset_next(st);
for(l = 0; l < lines ;l++) {
struct interrupt *irr = irrindex(irrs, l, cpus);
if(unlikely(!irr->used)) continue;
- rrddim_set(st, irr->id, irr->total);
+ // some interrupt may have changed without changing the total number of lines
+ // if the same number of interrupts have been added and removed between two
+ // calls of this function.
+ if(unlikely(!irr->rd || strncmp(irr->name, irr->rd->name, MAX_INTERRUPT_NAME) != 0)) {
+ irr->rd = rrddim_find(st, irr->id);
+ if(unlikely(!irr->rd))
+ irr->rd = rrddim_add(st, irr->id, irr->name, 1, 1, RRDDIM_INCREMENTAL);
+ else
+ rrddim_set_name(st, irr->rd, irr->name);
+
+ // also reset per cpu RRDDIMs to avoid repeating strncmp() in the per core loop
+ if(likely(do_per_core)) {
+ int c;
+ for (c = 0; c < cpus ;c++)
+ irr->cpu[c].rd = NULL;
+ }
+ }
+ rrddim_set_by_pointer(st, irr->rd, irr->total);
}
rrdset_done(st);
for(l = 0; l < lines ;l++) {
struct interrupt *irr = irrindex(irrs, l, cpus);
if(unlikely(!irr->used)) continue;
- core_sum += irr->value[c];
+ core_sum += irr->cpu[c].value;
}
if(unlikely(core_sum == 0)) continue; // try next core
char title[100+1];
snprintfz(title, 100, "CPU%d softirqs", c);
st = rrdset_create("cpu", id, NULL, "softirqs", "cpu.softirqs", title, "softirqs/s", 3000 + c, update_every, RRDSET_TYPE_STACKED);
-
- for(l = 0; l < lines ;l++) {
- struct interrupt *irr = irrindex(irrs, l, cpus);
- if(unlikely(!irr->used)) continue;
- rrddim_add(st, irr->id, irr->name, 1, 1, RRDDIM_INCREMENTAL);
- }
}
else rrdset_next(st);
for(l = 0; l < lines ;l++) {
struct interrupt *irr = irrindex(irrs, l, cpus);
if(unlikely(!irr->used)) continue;
- rrddim_set(st, irr->id, irr->value[c]);
+ if(unlikely(!irr->cpu[c].rd)) {
+ irr->cpu[c].rd = rrddim_find(st, irr->id);
+ if(unlikely(!irr->cpu[c].rd))
+ irr->cpu[c].rd = rrddim_add(st, irr->id, irr->name, 1, 1, RRDDIM_INCREMENTAL);
+ else
+ rrddim_set_name(st, irr->cpu[c].rd, irr->name);
+ }
+ rrddim_set_by_pointer(st, irr->cpu[c].rd, irr->cpu[c].value);
}
rrdset_done(st);
}
#include "common.h"
-int do_proc_stat(int update_every, unsigned long long dt) {
+int do_proc_stat(int update_every, usec_t dt) {
(void)dt;
static procfile *ff = NULL;
#include "common.h"
-int do_proc_sys_kernel_random_entropy_avail(int update_every, unsigned long long dt) {
+int do_proc_sys_kernel_random_entropy_avail(int update_every, usec_t dt) {
(void)dt;
static procfile *ff = NULL;
#include "common.h"
-int do_proc_vmstat(int update_every, unsigned long long dt) {
+int do_proc_vmstat(int update_every, usec_t dt) {
(void)dt;
static procfile *ff = NULL;
void registry_set_cookie(struct web_client *w, const char *guid) {
char edate[100];
- time_t et = time(NULL) + registry.persons_expiration;
+ time_t et = now_realtime_sec() + registry.persons_expiration;
struct tm etmbuf, *etm = gmtime_r(&et, &etmbuf);
strftime(edate, sizeof(edate), "%a, %d %b %Y %H:%M:%S %Z", etm);
void rrdhost_init(char *hostname) {
localhost.hostname = hostname;
localhost.health_log.next_log_id =
- localhost.health_log.next_alarm_id = time(NULL);
+ localhost.health_log.next_alarm_id = now_realtime_sec();
}
void rrdhost_rwlock(RRDHOST *host) {
error("File %s does not have the desired update frequency. Clearing it.", fullfilename);
memset(st, 0, size);
}
- else if((time(NULL) - st->last_updated.tv_sec) > update_every * entries) {
+ else if((now_realtime_sec() - st->last_updated.tv_sec) > update_every * entries) {
errno = 0;
error("File %s is too old. Clearing it.", fullfilename);
memset(st, 0, size);
if(rrd_memory_mode != RRD_MEMORY_MODE_RAM) rd = (RRDDIM *)mymmap(fullfilename, size, ((rrd_memory_mode == RRD_MEMORY_MODE_MAP)?MAP_SHARED:MAP_PRIVATE), 1);
if(rd) {
struct timeval now;
- gettimeofday(&now, NULL);
+ now_realtime_timeval(&now);
if(strcmp(rd->magic, RRDDIMENSION_MAGIC) != 0) {
errno = 0;
error("File %s does not have the same refresh frequency. Clearing it.", fullfilename);
memset(rd, 0, size);
}
- else if(usec_dt(&now, &rd->last_collected_time) > (rd->entries * rd->update_every * 1000000ULL)) {
+ else if(dt_usec(&now, &rd->last_collected_time) > (rd->entries * rd->update_every * USEC_PER_SEC)) {
errno = 0;
error("File %s is too old. Clearing it.", fullfilename);
memset(rd, 0, size);
{
debug(D_RRD_CALLS, "rrddim_set_by_pointer() for chart %s, dimension %s, value " COLLECTED_NUMBER_FORMAT, st->name, rd->name, value);
- gettimeofday(&rd->last_collected_time, NULL);
+ now_realtime_timeval(&rd->last_collected_time);
rd->collected_value = value;
rd->updated = 1;
rd->counter++;
return rrddim_set_by_pointer(st, rd, value);
}
-void rrdset_next_usec_unfiltered(RRDSET *st, unsigned long long microseconds)
+void rrdset_next_usec_unfiltered(RRDSET *st, usec_t microseconds)
{
if(unlikely(!st->last_collected_time.tv_sec || !microseconds)) {
// the first entry
- microseconds = st->update_every * 1000000ULL;
+ microseconds = st->update_every * USEC_PER_SEC;
}
st->usec_since_last_update = microseconds;
}
-void rrdset_next_usec(RRDSET *st, unsigned long long microseconds)
+void rrdset_next_usec(RRDSET *st, usec_t microseconds)
{
struct timeval now;
- gettimeofday(&now, NULL);
+ now_realtime_timeval(&now);
if(unlikely(!st->last_collected_time.tv_sec)) {
// the first entry
- microseconds = st->update_every * 1000000ULL;
+ microseconds = st->update_every * USEC_PER_SEC;
}
else if(unlikely(!microseconds)) {
// no dt given by the plugin
- microseconds = usec_dt(&now, &st->last_collected_time);
+ microseconds = dt_usec(&now, &st->last_collected_time);
}
else {
// microseconds has the time since the last collection
- unsigned long long now_usec = timeval_usec(&now);
- unsigned long long last_usec = timeval_usec(&st->last_collected_time);
- unsigned long long since_last_usec = usec_dt(&now, &st->last_collected_time);
+ usec_t now_usec = timeval_usec(&now);
+ usec_t last_usec = timeval_usec(&st->last_collected_time);
+ usec_t since_last_usec = dt_usec(&now, &st->last_collected_time);
// verify the microseconds given is good
if(unlikely(microseconds > since_last_usec)) {
st->usec_since_last_update = microseconds;
}
-unsigned long long rrdset_done(RRDSET *st)
+usec_t rrdset_done(RRDSET *st)
{
if(unlikely(netdata_exit)) return 0;
unsigned int
stored_entries = 0; // the number of entries we have stored in the db, during this call to rrdset_done()
- unsigned long long
+ usec_t
last_collect_ut, // the timestamp in microseconds, of the last collected value
now_collect_ut, // the timestamp in microseconds, of this collected value (this is NOW)
last_stored_ut, // the timestamp in microseconds, of the last stored entry in the db
next_store_ut, // the timestamp in microseconds, of the next entry to store in the db
- update_every_ut = st->update_every * 1000000ULL; // st->update_every in microseconds
+ update_every_ut = st->update_every * USEC_PER_SEC; // st->update_every in microseconds
if(unlikely(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &pthreadoldcancelstate) != 0))
error("Cannot set pthread cancel state to DISABLE.");
if(unlikely(!st->last_collected_time.tv_sec)) {
// it is the first entry
// set the last_collected_time to now
- gettimeofday(&st->last_collected_time, NULL);
+ now_realtime_timeval(&st->last_collected_time);
timeval_align(&st->last_collected_time, st->update_every);
- last_collect_ut = st->last_collected_time.tv_sec * 1000000ULL + st->last_collected_time.tv_usec - update_every_ut;
+ last_collect_ut = st->last_collected_time.tv_sec * USEC_PER_SEC + st->last_collected_time.tv_usec - update_every_ut;
// the first entry should not be stored
store_this_entry = 0;
else {
// it is not the first entry
// calculate the proper last_collected_time, using usec_since_last_update
- last_collect_ut = st->last_collected_time.tv_sec * 1000000ULL + st->last_collected_time.tv_usec;
- unsigned long long ut = last_collect_ut + st->usec_since_last_update;
- st->last_collected_time.tv_sec = (time_t) (ut / 1000000ULL);
- st->last_collected_time.tv_usec = (suseconds_t) (ut % 1000000ULL);
+ last_collect_ut = st->last_collected_time.tv_sec * USEC_PER_SEC + st->last_collected_time.tv_usec;
+ usec_t ut = last_collect_ut + st->usec_since_last_update;
+ st->last_collected_time.tv_sec = (time_t) (ut / USEC_PER_SEC);
+ st->last_collected_time.tv_usec = (suseconds_t) (ut % USEC_PER_SEC);
}
// if this set has not been updated in the past
if(unlikely(!st->last_updated.tv_sec)) {
// it has never been updated before
// set a fake last_updated, in the past using usec_since_last_update
- unsigned long long ut = st->last_collected_time.tv_sec * 1000000ULL + st->last_collected_time.tv_usec - st->usec_since_last_update;
- st->last_updated.tv_sec = (time_t) (ut / 1000000ULL);
- st->last_updated.tv_usec = (suseconds_t) (ut % 1000000ULL);
+ usec_t ut = st->last_collected_time.tv_sec * USEC_PER_SEC + st->last_collected_time.tv_usec - st->usec_since_last_update;
+ st->last_updated.tv_sec = (time_t) (ut / USEC_PER_SEC);
+ st->last_updated.tv_usec = (suseconds_t) (ut % USEC_PER_SEC);
// the first entry should not be stored
store_this_entry = 0;
}
// check if we will re-write the entire data set
- if(unlikely(usec_dt(&st->last_collected_time, &st->last_updated) > st->entries * update_every_ut)) {
+ if(unlikely(dt_usec(&st->last_collected_time, &st->last_updated) > st->entries * update_every_ut)) {
info("%s: too old data (last updated at %ld.%ld, last collected at %ld.%ld). Reseting it. Will not store the next entry.", st->name, st->last_updated.tv_sec, st->last_updated.tv_usec, st->last_collected_time.tv_sec, st->last_collected_time.tv_usec);
rrdset_reset(st);
st->usec_since_last_update = update_every_ut;
- gettimeofday(&st->last_collected_time, NULL);
+ now_realtime_timeval(&st->last_collected_time);
timeval_align(&st->last_collected_time, st->update_every);
- unsigned long long ut = st->last_collected_time.tv_sec * 1000000ULL + st->last_collected_time.tv_usec - st->usec_since_last_update;
- st->last_updated.tv_sec = (time_t) (ut / 1000000ULL);
- st->last_updated.tv_usec = (suseconds_t) (ut % 1000000ULL);
+ usec_t ut = st->last_collected_time.tv_sec * USEC_PER_SEC + st->last_collected_time.tv_usec - st->usec_since_last_update;
+ st->last_updated.tv_sec = (time_t) (ut / USEC_PER_SEC);
+ st->last_updated.tv_usec = (suseconds_t) (ut % USEC_PER_SEC);
// the first entry should not be stored
store_this_entry = 0;
// last_stored_ut = the last time we added a value to the storage
// now_collect_ut = the time the current value has been collected
// next_store_ut = the time of the next interpolation point
- last_stored_ut = st->last_updated.tv_sec * 1000000ULL + st->last_updated.tv_usec;
- now_collect_ut = st->last_collected_time.tv_sec * 1000000ULL + st->last_collected_time.tv_usec;
- next_store_ut = (st->last_updated.tv_sec + st->update_every) * 1000000ULL;
+ last_stored_ut = st->last_updated.tv_sec * USEC_PER_SEC + st->last_updated.tv_usec;
+ now_collect_ut = st->last_collected_time.tv_sec * USEC_PER_SEC + st->last_collected_time.tv_usec;
+ next_store_ut = (st->last_updated.tv_sec + st->update_every) * USEC_PER_SEC;
if(unlikely(st->debug)) {
debug(D_RRD_STATS, "%s: last_collect_ut = %0.3Lf (last collection time)", st->name, (long double)last_collect_ut/1000000.0);
#endif
}
- unsigned long long first_ut = last_stored_ut;
+ usec_t first_ut = last_stored_ut;
long long iterations = (now_collect_ut - last_stored_ut) / (update_every_ut);
if((now_collect_ut % (update_every_ut)) == 0) iterations++;
debug(D_RRD_STATS, "%s: next_store_ut = %0.3Lf (next interpolation point)", st->name, (long double)next_store_ut/1000000.0);
}
- st->last_updated.tv_sec = (time_t) (next_store_ut / 1000000ULL);
+ st->last_updated.tv_sec = (time_t) (next_store_ut / USEC_PER_SEC);
st->last_updated.tv_usec = 0;
for( rd = st->dimensions ; likely(rd) ; rd = rd->next ) {
uint32_t hash_name; // a simple hash on the name
- unsigned long long usec_since_last_update; // the time in microseconds since the last collection of data
+ usec_t usec_since_last_update; // the time in microseconds since the last collection of data
struct timeval last_updated; // when this data set was last updated (updated every time the rrd_stats_done() function)
struct timeval last_collected_time; // when did this data set last collected values
extern RRDSET *rrdset_find_bytype(const char *type, const char *id);
extern RRDSET *rrdset_find_byname(const char *name);
-extern void rrdset_next_usec_unfiltered(RRDSET *st, unsigned long long microseconds);
-extern void rrdset_next_usec(RRDSET *st, unsigned long long microseconds);
+extern void rrdset_next_usec_unfiltered(RRDSET *st, usec_t microseconds);
+extern void rrdset_next_usec(RRDSET *st, usec_t microseconds);
#define rrdset_next(st) rrdset_next_usec(st, 0ULL)
-extern unsigned long long rrdset_done(RRDSET *st);
+extern usec_t rrdset_done(RRDSET *st);
// get the total duration in seconds of the round robin database
#define rrdset_duration(st) ((time_t)( (((st)->counter >= ((unsigned long)(st)->entries))?(unsigned long)(st)->entries:(st)->counter) * (st)->update_every ))
unsigned long rrd_stats_one_json(RRDSET *st, char *options, BUFFER *wb)
{
- time_t now = time(NULL);
+ time_t now = now_realtime_sec();
pthread_rwlock_rdlock(&st->rwlock);
// ----------------------------------------------------------------------------
// cgroups main
-int do_sys_fs_cgroup(int update_every, unsigned long long dt) {
+int do_sys_fs_cgroup(int update_every, usec_t dt) {
(void)dt;
static int cgroup_global_config_read = 0;
static time_t last_run = 0;
- time_t now = time(NULL);
+ time_t now = now_realtime_sec();
if(unlikely(!cgroup_global_config_read)) {
read_cgroup_plugin_configuration();
int vdo_cpu_netdata = !config_get_boolean("plugin:cgroups", "cgroups plugin resources", 1);
// keep track of the time each module was called
- unsigned long long sutime_sys_fs_cgroup = 0ULL;
+ usec_t sutime_sys_fs_cgroup = 0ULL;
// the next time we will run - aligned properly
- unsigned long long sunext = (time(NULL) - (time(NULL) % rrd_update_every) + rrd_update_every) * 1000000ULL;
+ usec_t sunext = (now_realtime_sec() - (now_realtime_sec() % rrd_update_every) + rrd_update_every) * USEC_PER_SEC;
RRDSET *stcpu_thread = NULL;
for(;;) {
- unsigned long long sunow;
+ usec_t sunow;
if(unlikely(netdata_exit)) break;
// delay until it is our time to run
- while((sunow = time_usec()) < sunext)
+ while((sunow = now_realtime_usec()) < sunext)
sleep_usec(sunext - sunow);
// find the next time we need to run
- while(time_usec() > sunext)
- sunext += rrd_update_every * 1000000ULL;
+ while(now_realtime_usec() > sunext)
+ sunext += rrd_update_every * USEC_PER_SEC;
if(unlikely(netdata_exit)) break;
if(!vdo_sys_fs_cgroup) {
debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_sys_fs_cgroup().");
- sunow = time_usec();
+ sunow = now_realtime_usec();
vdo_sys_fs_cgroup = do_sys_fs_cgroup(rrd_update_every, (sutime_sys_fs_cgroup > 0)?sunow - sutime_sys_fs_cgroup:0ULL);
sutime_sys_fs_cgroup = sunow;
}
[PAGES_TO_SCAN] = { "/sys/kernel/mm/ksm/pages_to_scan", 0ULL },
};
-int do_sys_kernel_mm_ksm(int update_every, unsigned long long dt) {
+int do_sys_kernel_mm_ksm(int update_every, usec_t dt) {
static procfile *ff_pages_shared = NULL, *ff_pages_sharing = NULL, *ff_pages_unshared = NULL, *ff_pages_volatile = NULL, *ff_pages_to_scan = NULL;
static long page_size = -1;
st->debug = 1;
// feed it with the test data
- time_t time_now = 0, time_start = time(NULL);
+ time_t time_now = 0, time_start = now_realtime_sec();
unsigned long c;
collected_number last = 0;
for(c = 0; c < test->feed_entries; c++) {
if(do_absi) rrddim_set(st, "percentage-of-incremental-row", i);
if(!c) {
- gettimeofday(&st->last_collected_time, NULL);
+ now_realtime_timeval(&st->last_collected_time);
st->last_collected_time.tv_usec = shift;
}
}
}
+void buffer_strcat_htmlescape(BUFFER *wb, const char *txt)
+{
+ char b[2] = { [0] = '\0', [1] = '\0' };
+
+ while(*txt) {
+ switch(*txt) {
+ case '&': buffer_strcat(wb, "&"); break;
+ case '<': buffer_strcat(wb, "<"); break;
+ case '>': buffer_strcat(wb, ">"); break;
+ case '"': buffer_strcat(wb, """); break;
+ case '/': buffer_strcat(wb, "/"); break;
+ case '\'': buffer_strcat(wb, "'"); break;
+ default: {
+ b[0] = *txt;
+ buffer_strcat(wb, b);
+ }
+ }
+ txt++;
+ }
+}
void buffer_snprintf(BUFFER *wb, size_t len, const char *fmt, ...)
{
extern void buffer_snprintf(BUFFER *wb, size_t len, const char *fmt, ...) __attribute__ (( format (printf, 3, 4)));
extern void buffer_vsprintf(BUFFER *wb, const char *fmt, va_list args);
extern void buffer_sprintf(BUFFER *wb, const char *fmt, ...) __attribute__ (( format (printf, 2, 3)));
+extern void buffer_strcat_htmlescape(BUFFER *wb, const char *txt);
extern void buffer_char_replace(BUFFER *wb, char from, char to);
if(likely(w->last_url[0])) {
struct timeval tv;
- gettimeofday(&tv, NULL);
+ now_realtime_timeval(&tv);
size_t size = (w->mode == WEB_CLIENT_MODE_FILECOPY)?w->response.rlen:w->response.data->len;
size_t sent = size;
// --------------------------------------------------------------------
// global statistics
- finished_web_request_statistics(usec_dt(&tv, &w->tv_in),
+ finished_web_request_statistics(dt_usec(&tv, &w->tv_in),
w->stats_received_bytes,
w->stats_sent_bytes,
size,
log_access("%llu: (sent/all = %zu/%zu bytes %0.0f%%, prep/sent/total = %0.2f/%0.2f/%0.2f ms) %s: %d '%s'",
w->id,
sent, size, -((size > 0) ? ((size - sent) / (double) size * 100.0) : 0.0),
- usec_dt(&w->tv_ready, &w->tv_in) / 1000.0,
- usec_dt(&tv, &w->tv_ready) / 1000.0,
- usec_dt(&tv, &w->tv_in) / 1000.0,
+ dt_usec(&w->tv_ready, &w->tv_in) / 1000.0,
+ dt_usec(&tv, &w->tv_ready) / 1000.0,
+ dt_usec(&tv, &w->tv_in) / 1000.0,
(w->mode == WEB_CLIENT_MODE_FILECOPY) ? "filecopy" : ((w->mode == WEB_CLIENT_MODE_OPTIONS)
? "options" : "data"),
w->response.code,
for(s = filename; *s ;s++) {
if( !isalnum(*s) && *s != '/' && *s != '.' && *s != '-' && *s != '_') {
debug(D_WEB_CLIENT_ACCESS, "%llu: File '%s' is not acceptable.", w->id, filename);
- buffer_sprintf(w->response.data, "File '%s' cannot be served. Filename contains invalid character '%c'", filename, *s);
+ buffer_sprintf(w->response.data, "Filename contains invalid characters: ");
+ buffer_strcat_htmlescape(w->response.data, filename);
return 400;
}
}
// if the filename contains a .. refuse to serve it
if(strstr(filename, "..") != 0) {
debug(D_WEB_CLIENT_ACCESS, "%llu: File '%s' is not acceptable.", w->id, filename);
- buffer_sprintf(w->response.data, "File '%s' cannot be served. Relative filenames with '..' in them are not supported.", filename);
+ buffer_strcat(w->response.data, "Relative filenames are not supported: ");
+ buffer_strcat_htmlescape(w->response.data, filename);
return 400;
}
struct stat stat;
if(lstat(webfilename, &stat) != 0) {
debug(D_WEB_CLIENT_ACCESS, "%llu: File '%s' is not found.", w->id, webfilename);
- buffer_sprintf(w->response.data, "File '%s' does not exist, or is not accessible.", webfilename);
+ buffer_strcat(w->response.data, "File does not exist, or is not accessible: ");
+ buffer_strcat_htmlescape(w->response.data, webfilename);
return 404;
}
// check if the file is owned by expected user
if(stat.st_uid != web_files_uid()) {
error("%llu: File '%s' is owned by user %u (expected user %u). Access Denied.", w->id, webfilename, stat.st_uid, web_files_uid());
- buffer_sprintf(w->response.data, "Access to file '%s' is not permitted.", webfilename);
+ buffer_strcat(w->response.data, "Access to file is not permitted: ");
+ buffer_strcat_htmlescape(w->response.data, webfilename);
return 403;
}
// check if the file is owned by expected group
if(stat.st_gid != web_files_gid()) {
error("%llu: File '%s' is owned by group %u (expected group %u). Access Denied.", w->id, webfilename, stat.st_gid, web_files_gid());
- buffer_sprintf(w->response.data, "Access to file '%s' is not permitted.", webfilename);
+ buffer_strcat(w->response.data, "Access to file is not permitted: ");
+ buffer_strcat_htmlescape(w->response.data, webfilename);
return 403;
}
if((stat.st_mode & S_IFMT) != S_IFREG) {
error("%llu: File '%s' is not a regular file. Access Denied.", w->id, webfilename);
- buffer_sprintf(w->response.data, "Access to file '%s' is not permitted.", webfilename);
+ buffer_strcat(w->response.data, "Access to file is not permitted: ");
+ buffer_strcat_htmlescape(w->response.data, webfilename);
return 403;
}
if(errno == EBUSY || errno == EAGAIN) {
error("%llu: File '%s' is busy, sending 307 Moved Temporarily to force retry.", w->id, webfilename);
buffer_sprintf(w->response.header, "Location: /" WEB_PATH_FILE "/%s\r\n", filename);
- buffer_sprintf(w->response.data, "The file '%s' is currently busy. Please try again later.", webfilename);
+ buffer_strcat(w->response.data, "File is currently busy, please try again later: ");
+ buffer_strcat_htmlescape(w->response.data, webfilename);
return 307;
}
else {
error("%llu: Cannot open file '%s'.", w->id, webfilename);
- buffer_sprintf(w->response.data, "Cannot open file '%s'.", webfilename);
+ buffer_strcat(w->response.data, "Cannot open file: ");
+ buffer_strcat_htmlescape(w->response.data, webfilename);
return 404;
}
}
RRDSET *st = rrdset_find(chart);
if(!st) st = rrdset_find_byname(chart);
if(!st) {
- buffer_sprintf(w->response.data, "Chart '%s' is not found.", chart);
+ buffer_strcat(w->response.data, "Chart is not found: ");
+ buffer_strcat_htmlescape(w->response.data, chart);
ret = 404;
goto cleanup;
}
if (refresh > 0) {
buffer_sprintf(w->response.header, "Refresh: %d\r\n", refresh);
- w->response.data->expires = time(NULL) + refresh;
+ w->response.data->expires = now_realtime_sec() + refresh;
}
else buffer_no_cacheable(w->response.data);
ret = 500;
// if the collected value is too old, don't calculate its value
- if (rrdset_last_entry_t(st) >= (time(NULL) - (st->update_every * st->gap_when_lost_iterations_above)))
+ if (rrdset_last_entry_t(st) >= (now_realtime_sec() - (st->update_every * st->gap_when_lost_iterations_above)))
ret = rrd2value(st,
w->response.data,
&n,
}
else if (refresh > 0) {
buffer_sprintf(w->response.header, "Refresh: %d\r\n", refresh);
- w->response.data->expires = time(NULL) + refresh;
+ w->response.data->expires = now_realtime_sec() + refresh;
}
else buffer_no_cacheable(w->response.data);
RRDSET *st = rrdset_find(chart);
if(!st) st = rrdset_find_byname(chart);
if(!st) {
- buffer_sprintf(w->response.data, "Chart '%s' is not found.", chart);
+ buffer_strcat(w->response.data, "Chart is not found: ");
+ buffer_strcat_htmlescape(w->response.data, chart);
ret = 404;
goto cleanup;
}
}
if(action == 'A' && (!machine_guid || !machine_url || !url_name)) {
+ error("Invalid registry request - access requires these parameters: machine ('%s'), url ('%s'), name ('%s')",
+ machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", url_name?url_name:"UNSET");
buffer_flush(w->response.data);
- buffer_sprintf(w->response.data, "Invalid registry request - access requires these parameters: machine ('%s'), url ('%s'), name ('%s')",
- machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", url_name?url_name:"UNSET");
+ buffer_strcat(w->response.data, "Invalid registry Access request.");
return 400;
}
else if(action == 'D' && (!machine_guid || !machine_url || !delete_url)) {
+ error("Invalid registry request - delete requires these parameters: machine ('%s'), url ('%s'), delete_url ('%s')",
+ machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", delete_url?delete_url:"UNSET");
buffer_flush(w->response.data);
- buffer_sprintf(w->response.data, "Invalid registry request - delete requires these parameters: machine ('%s'), url ('%s'), delete_url ('%s')",
- machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", delete_url?delete_url:"UNSET");
+ buffer_strcat(w->response.data, "Invalid registry Delete request.");
return 400;
}
else if(action == 'S' && (!machine_guid || !machine_url || !search_machine_guid)) {
+ error("Invalid registry request - search requires these parameters: machine ('%s'), url ('%s'), for ('%s')",
+ machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", search_machine_guid?search_machine_guid:"UNSET");
buffer_flush(w->response.data);
- buffer_sprintf(w->response.data, "Invalid registry request - search requires these parameters: machine ('%s'), url ('%s'), for ('%s')",
- machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", search_machine_guid?search_machine_guid:"UNSET");
+ buffer_strcat(w->response.data, "Invalid registry Search request.");
return 400;
}
else if(action == 'W' && (!machine_guid || !machine_url || !to_person_guid)) {
+ error("Invalid registry request - switching identity requires these parameters: machine ('%s'), url ('%s'), to ('%s')",
+ machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", to_person_guid?to_person_guid:"UNSET");
buffer_flush(w->response.data);
- buffer_sprintf(w->response.data, "Invalid registry request - switching identity requires these parameters: machine ('%s'), url ('%s'), to ('%s')",
- machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", to_person_guid?to_person_guid:"UNSET");
+ buffer_strcat(w->response.data, "Invalid registry Switch request.");
return 400;
}
if(unlikely(cookie && person_guid[0] && !strcmp(person_guid, REGISTRY_VERIFY_COOKIES_GUID)))
person_guid[0] = '\0';
- return registry_request_access_json(w, person_guid, machine_guid, machine_url, url_name, time(NULL));
+ return registry_request_access_json(w, person_guid, machine_guid, machine_url, url_name, now_realtime_sec());
case 'D':
w->tracking_required = 1;
- return registry_request_delete_json(w, person_guid, machine_guid, machine_url, delete_url, time(NULL));
+ return registry_request_delete_json(w, person_guid, machine_guid, machine_url, delete_url, now_realtime_sec());
case 'S':
w->tracking_required = 1;
- return registry_request_search_json(w, person_guid, machine_guid, machine_url, search_machine_guid, time(NULL));
+ return registry_request_search_json(w, person_guid, machine_guid, machine_url, search_machine_guid, now_realtime_sec());
case 'W':
w->tracking_required = 1;
- return registry_request_switch_json(w, person_guid, machine_guid, machine_url, to_person_guid, time(NULL));
+ return registry_request_switch_json(w, person_guid, machine_guid, machine_url, to_person_guid, now_realtime_sec());
case 'H':
return registry_request_hello_json(w);
else {
buffer_flush(w->response.data);
- buffer_sprintf(w->response.data, "Unsupported v1 API command: %s", tok);
+ buffer_strcat(w->response.data, "Unsupported v1 API command: ");
+ buffer_strcat_htmlescape(w->response.data, tok);
return 404;
}
}
else {
buffer_flush(w->response.data);
- buffer_sprintf(w->response.data, "API v1 command?");
+ buffer_sprintf(w->response.data, "Which API v1 command?");
return 400;
}
}
return web_client_api_request_v1(w, url);
else {
buffer_flush(w->response.data);
- buffer_sprintf(w->response.data, "Unsupported API version: %s", tok);
+ buffer_strcat(w->response.data, "Unsupported API version: ");
+ buffer_strcat_htmlescape(w->response.data, tok);
return 404;
}
}
#endif
// start timing us
- gettimeofday(&w->tv_in, NULL);
+ now_realtime_timeval(&w->tv_in);
if(unlikely(!hash_api)) {
hash_api = simple_hash("api");
if(!st) st = rrdset_find(tok);
if(!st) {
code = 404;
- buffer_sprintf(w->response.data, "Chart %s is not found.\r\n", tok);
+ buffer_strcat(w->response.data, "Chart is not found: ");
+ buffer_strcat_htmlescape(w->response.data, tok);
debug(D_WEB_CLIENT_ACCESS, "%llu: %s is not found.", w->id, tok);
}
else {
code = 200;
debug_flags |= D_RRD_STATS;
st->debug = !st->debug;
- buffer_sprintf(w->response.data, "Chart %s has now debug %s.\r\n", tok, st->debug?"enabled":"disabled");
+ buffer_sprintf(w->response.data, "Chart has now debug %s: ", st->debug?"enabled":"disabled");
+ buffer_strcat_htmlescape(w->response.data, tok);
debug(D_WEB_CLIENT_ACCESS, "%llu: debug for %s is %s.", w->id, tok, st->debug?"enabled":"disabled");
}
}
}
}
- gettimeofday(&w->tv_ready, NULL);
+ now_realtime_timeval(&w->tv_ready);
w->response.sent = 0;
w->response.code = code;
<div class=grid-cell><h3><span class=star>★</span> In real-time</h3>
<p>netdata collects thousands of metrics per server <strong>per second</strong>,
with <a href="https://github.com/firehol/netdata/wiki/Performance#netdata-daemon" target="_blank" data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=Performance>just 1% CPU</a>
- utilization of a single core, <a href="https://github.com/firehol/netdata/wiki/Memory-Requirements" target="_blank" data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=MemoryRequirements>a few MB or RAM</a>
+ utilization of a single core, <a href="https://github.com/firehol/netdata/wiki/Memory-Requirements" target="_blank" data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=MemoryRequirements>a few MB of RAM</a>
and no disk I/O at all.
View everything on <strong>stunning</strong> real-time interactive web dashboards, even when netdata is
running on low-end hardware.
netdata has received significant contributions from:<br/> <br/>
<a href="https://github.com/philwhineray" target="_blank" data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=Phil>Phil Whineray</a> (release management),<br/>
<a href="https://github.com/alonbl" target="_blank" data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=Alon>Alon Bar-Lev</a> (autoconf and automake),<br/>
- <a href="https://github.com/titpetric" target="_blank" data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=titpetric>Tit Petric</a> (docker maintainer),<br/>
+ <a href="https://github.com/titpetric" target="_blank" data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=titpetric>Tit Petric</a> (docker image maintainer),<br/>
<a href="https://github.com/paulfantom" target="_blank" data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=Pawel>Paweł Krupa</a> (python.d.plugin and modules),<br/>
<a href="https://github.com/simonnagl" target="_blank" data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=simonnagl>simonnagl</a> (disk plugin and more),<br/>
<a href="https://github.com/fredericopissarra" target="_blank" data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=Frederico>Frederico Lamberti Pissarra</a> (performance improvements)<br/>
+ <a href="https://github.com/vlvkobal" target="_blank" data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=VladimirKobal>Vladimir Kobal</a> (FreeBSD port)<br/>
<br/>
and dozens more enthusiasts, engineers and professionals.<br/> <br/>
</p>
gotoServerInit();
};
- var this_is_demo = null;
+ var this_is_demo = null; // FIXME
function isdemo() {
if(this_is_demo !== null) return this_is_demo;
this_is_demo = false;
if(typeof charts['system.ram'] !== 'undefined')
head += '<div style="margin-right: 10px;" data-netdata="system.ram"'
- + ' data-dimensions="used|buffers"'
+ + ' data-dimensions="used|buffers|active|wired"' // active and wired are FreeBSD stats
+ ' data-append-options="percentage"'
+ ' data-chart-library="easypiechart"'
+ ' data-title="Used RAM"'
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
- <h4 class="modal-title" id="welcomeModalLabel">Welcome!</h4>
+ <h4 class="modal-title" id="welcomeModalLabel">Welcome to the world of netdata</h4>
</div>
<div class="modal-body">
- <div class="p">
- <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></b> is the fastest way to visualize metrics. It is a resource efficient, highly optimized system for collecting and visualizing any type of real-time time series data, from CPU usage, disk activity, SQL queries, API calls, web site visitors, etc.
- </div>
- <div class="p">
- <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></b> tries to visualize the truth of <b>now</b>, in its <b>greatest detail</b>, so that you can get insights of what is happening now and what just happened, on your systems and applications.
- </div>
- <div class="p">
- To make a chart in <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></b>, you just need a <b>number</b>. Just a number you can read somehow. <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></b> will turn this number to a real time, interactive, web chart. For collecting these numbers, it supports <a href="https://github.com/firehol/netdata/wiki/External-Plugins" target="_blank">external plugins</a>, even <a href="https://github.com/firehol/netdata/wiki/General-Info---charts.d" target="_blank">shell</a> or <a href="https://github.com/firehol/netdata/wiki/General-Info---charts.d" target="_blank">node.js</a> plugins. Any computer program, in any language, that can print a few lines of text on its standard output, can be a netdata data collector.
- </div>
- <div class="p">
- <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></b> can embed charts everywhere, like this one <div data-netdata="system.cpu" data-dimensions="system" data-after="-120" data-width="25%" data-height="15px" data-chart-library="dygraph" data-dygraph-theme="sparkline" data-show-value-of-system-at="system.cpu.system.modal.1"></div> (my CPU system usage which is <span id="system.cpu.system.modal.1" style="display: inline-block; width: 40px; text-align: right;"></span>%),
- or this one <div data-netdata="ipv4.tcppackets" data-dimensions="received" data-after="-120" data-width="25%" data-height="15px" data-chart-library="dygraph" data-dygraph-theme="sparkline" data-show-value-of-received-at="ipv4.tcppackets.received.modal.1"></div> (my IPv4 received TCP packets, which are <span id="ipv4.tcppackets.received.modal.1" style="display: inline-block; width: 60px; text-align: right;"></span>/second).
- </div>
- <div class="p">
- You can have <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></b> charts on your site too. Just give it a <code>div</code> and a real time chart, zoomable and draggable will appear (try it even on these tiny ones - <b>drag</b> them to pan horizontally, <b>shift + drag</b> to zoom in, on <b>chrome shift + mouse wheel</b> to zoom in/out, <b>double click</b> on them to reset them - don't be afraid of <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></b> performance - <a href="https://github.com/firehol/netdata/wiki/Performance" target="_blank">a raspberry pi 2 can sustain 300 charts updates per second</a>!).
- </div>
- <div class="p">
- For more information please refer to the <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata wiki</a></b>.
+ <div class="p">
+ <div style="width: 100%; text-align: center; padding-top: 10px; padding-bottom: 10px; font-size: 18px;">
+ if there is a metric for something, we want it visualised<br/>
+ and we want this visualisation to be <strong>real-time</strong>, <strong>efficient</strong> and <strong>awesome</strong>
</div>
+ </div>
+ <div class="p">
+ <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></b>
+ is a new way to monitor your systems and applications, to get <strong>real-time insights</strong>
+ of what is really happening and what affects performance.
+ It is carefully optimised to be a real-time system, without interfering in any way,
+ to the core function of your systems.
+ </div>
+ <div class="p">
+ <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></b>
+ has been designed to monitor <strong>massive amounts of metrics, per server, per second</strong>.
+ When installed, it might come up with 1k to 3k metrics, but we have been testing it with 100k
+ metrics, all collected per second, and still the cpu utilisation remained negligible.
+ <br/>
+ We have also tried to give each metric, a meaning, a context.
+ We have grouped and categorized all metrics into meaningful charts, providing a
+ better understanding of the underlying technologies and mechanisms.
+ </div>
+ <div class="p">
+ <b><a href="https://github.com/firehol/netdata/wiki" target="_blank">netdata</a></b> is free,
+ open-source software. If you decide to use it,
+ <strong><a href="https://github.com/firehol/netdata/wiki/a-github-star-is-important" target="_blank">it is important to give netdata a star at GitHub</a></strong>.
+ </div>
+ <div class="p">
+ Enjoy real-time performance monitoring!
+ </div>
+ <div class="p">
+ Costa Tsaousis
+ </div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>