trafficserver-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bc...@apache.org
Subject [trafficserver] branch master updated: Create system_stats plugin. This will insert system information in to the stats list on a five second interval. Currently it pulls load averages, number of processes, and most of the information from sysfs for each available network device.
Date Mon, 04 Dec 2017 17:35:32 GMT
This is an automated email from the ASF dual-hosted git repository.

bcall pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/master by this push:
     new 9145d25  Create system_stats plugin. This will insert system information in to the
stats list on a five second interval.  Currently it pulls load averages, number of processes,
and most of the information from sysfs for each available network device.
9145d25 is described below

commit 9145d255408c3dd395caa855341b7dfc42ba78ba
Author: Evan Zelkowitz <evan.zelkowitz@gmail.com>
AuthorDate: Tue Nov 14 09:30:34 2017 -0700

    Create system_stats plugin. This will insert system information in to
    the stats list on a five second interval.  Currently it pulls load
    averages, number of processes, and most of the information from sysfs
    for each available network device.
---
 doc/admin-guide/plugins/index.en.rst             |   4 +
 doc/admin-guide/plugins/system_stats.en.rst      |  89 ++++++++
 plugins/Makefile.am                              |   1 +
 plugins/experimental/system_stats/Makefile.inc   |  20 ++
 plugins/experimental/system_stats/system_stats.c | 256 +++++++++++++++++++++++
 5 files changed, 370 insertions(+)

diff --git a/doc/admin-guide/plugins/index.en.rst b/doc/admin-guide/plugins/index.en.rst
index b864aed..9081182 100644
--- a/doc/admin-guide/plugins/index.en.rst
+++ b/doc/admin-guide/plugins/index.en.rst
@@ -142,6 +142,7 @@ directory of the |TS| source tree. Experimental plugins can be compiled
by passi
    Signed URLs <url_sig.en>
    SSL Headers <sslheaders.en>
    Stale While Revalidate <stale_while_revalidate.en>
+   System Statistics <system_stats.en>
    TS Lua <ts_lua.en>
    WebP Transform <webp_transform.en>
 
@@ -206,6 +207,9 @@ directory of the |TS| source tree. Experimental plugins can be compiled
by passi
 
    Refresh content asynchronously while serving stale data.
 
+:doc:`System Stats <system_stats.en>`
+    Inserts system statistics in to the stats list
+
 :doc:`TS Lua <ts_lua.en>`
    Allows plugins to be written in Lua instead of C code.
 
diff --git a/doc/admin-guide/plugins/system_stats.en.rst b/doc/admin-guide/plugins/system_stats.en.rst
new file mode 100644
index 0000000..d71460f
--- /dev/null
+++ b/doc/admin-guide/plugins/system_stats.en.rst
@@ -0,0 +1,89 @@
+.. Licensed to the Apache Software Foundation (ASF) under one
+   or more contributor license agreements.  See the NOTICE file
+   distributed with this work for additional information
+   regarding copyright ownership.  The ASF licenses this file
+   to you under the Apache License, Version 2.0 (the
+   "License"); you may not use this file except in compliance
+   with the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing,
+   software distributed under the License is distributed on an
+   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+   KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+   under the License.
+
+.. include:: ../../common.defs
+
+.. _admin-plugins-system_stats:
+
+System Stats Plugin
+********************
+
+Purpose
+=======
+
+This plugin inserts system statistics in to the stats list that can then be
+retrieved either with stats_over_http or any other method using the management port.
+These can be used to diagnose issues like excessive load or networking performance.
+
+Installation
+============
+
+To enable this plugin, build with experimental plugin support add to the :file:`plugin.config`
file::
+
+    system_stats.so
+
+Caveats
+=======
+
+This plugin depends greatly on the sysfs interface so it is mostly useful only for Linux
hosts, however
+it will build for other hosts.
+
+Examples
+========
+
+Some example output is:
+
+.. code::
+
+	"proxy.process.ssl.cipher.user_agent.DES-CBC3-SHA": 0,
+	"proxy.process.ssl.cipher.user_agent.PSK-3DES-EDE-CBC-SHA": 0,
+	"plugin.system_stats.loadavg.one": 136128,
+	"plugin.system_stats.loadavg.five": 132032,
+	"plugin.system_stats.loadavg.ten": 88864,
+	"plugin.system_stats.current_processes": 503,
+	"plugin.system_stats.net.enp0s3.speed": 1000,
+	"plugin.system_stats.net.enp0s3.collisions": 0,
+	"plugin.system_stats.net.enp0s3.multicast": 0,
+	"plugin.system_stats.net.enp0s3.rx_bytes": 6783959,
+	"plugin.system_stats.net.enp0s3.rx_compressed": 0,
+	"plugin.system_stats.net.enp0s3.rx_crc_errors": 0,
+	"plugin.system_stats.net.enp0s3.rx_dropped": 0,
+	"plugin.system_stats.net.enp0s3.rx_errors": 0,
+	"plugin.system_stats.net.enp0s3.rx_fifo_errors": 0,
+	"plugin.system_stats.net.enp0s3.rx_frame_errors": 0,
+	"plugin.system_stats.net.enp0s3.rx_length_errors": 0,
+	"plugin.system_stats.net.enp0s3.rx_missed_errors": 0,
+	"plugin.system_stats.net.enp0s3.rx_nohandler": 0,
+	"plugin.system_stats.net.enp0s3.rx_over_errors": 0,
+	"plugin.system_stats.net.enp0s3.rx_packets": 9119,
+	"plugin.system_stats.net.enp0s3.tx_aborted_errors": 0,
+	"plugin.system_stats.net.enp0s3.tx_bytes": 922054,
+	"plugin.system_stats.net.enp0s3.tx_carrier_errors": 0,
+	"plugin.system_stats.net.enp0s3.tx_compressed": 0,
+	"plugin.system_stats.net.enp0s3.tx_dropped": 0,
+	"plugin.system_stats.net.enp0s3.tx_errors": 0,
+	"plugin.system_stats.net.enp0s3.tx_fifo_errors": 0,
+	"plugin.system_stats.net.enp0s3.tx_heartbeat_errors": 0,
+	"plugin.system_stats.net.enp0s3.tx_packets": 6013,
+	"plugin.system_stats.net.enp0s3.tx_window_errors": 0,
+	"proxy.process.cache.volume_0.bytes_used": 0,
+	"proxy.process.cache.volume_0.bytes_total": 268066816,
+
+This shows the system statistics inserted in with other stats. The above output
+displays the current load average, number of processes, and information on any network interfaces.
+
+This data is only updated every five seconds to not create large overhead.
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 2120cc1..9b9aefc 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -73,6 +73,7 @@ include experimental/ssl_cert_loader/Makefile.inc
 include experimental/sslheaders/Makefile.inc
 include experimental/stale_while_revalidate/Makefile.inc
 include experimental/stream_editor/Makefile.inc
+include experimental/system_stats/Makefile.inc
 include experimental/ts_lua/Makefile.inc
 include experimental/url_sig/Makefile.inc
 
diff --git a/plugins/experimental/system_stats/Makefile.inc b/plugins/experimental/system_stats/Makefile.inc
new file mode 100644
index 0000000..edba35d
--- /dev/null
+++ b/plugins/experimental/system_stats/Makefile.inc
@@ -0,0 +1,20 @@
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you under the Apache License, Version 2.0 (the
+#  "License"); you may not use this file except in compliance
+#  with the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+
+pkglib_LTLIBRARIES += experimental/system_stats/system_stats.la
+
+experimental_system_stats_system_stats_la_SOURCES = \
+experimental/system_stats/system_stats.c
diff --git a/plugins/experimental/system_stats/system_stats.c b/plugins/experimental/system_stats/system_stats.c
new file mode 100644
index 0000000..3d4dd62
--- /dev/null
+++ b/plugins/experimental/system_stats/system_stats.c
@@ -0,0 +1,256 @@
+/** @file
+
+  @section license License
+
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+ */
+
+#include "ts/ink_config.h"
+#include "ts/ink_defs.h"
+#include "ts/ts.h"
+
+#include <dirent.h>
+#include <getopt.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#ifdef HAVE_SYS_SYSINFO_H
+#include <sys/sysinfo.h>
+#endif
+
+#include <limits.h>
+
+#define PLUGIN_NAME "system_stats"
+#define DEBUG_TAG PLUGIN_NAME
+
+// Time in MS to grab the system stats
+#define SYSTEM_STATS_TIMEOUT 5000
+
+// Load Average Strings
+#define LOAD_AVG_ONE_MIN "plugin." PLUGIN_NAME ".loadavg.one"
+#define LOAD_AVG_FIVE_MIN "plugin." PLUGIN_NAME ".loadavg.five"
+#define LOAD_AVG_TEN_MIN "plugin." PLUGIN_NAME ".loadavg.ten"
+
+// Process Strings
+#define CURRENT_PROCESSES "plugin." PLUGIN_NAME ".current_processes"
+
+// Base net stats name, full name needs to populated
+// with NET_STATS.infname.RX/TX.standard_net_stats field
+#define NET_STATS "plugin." PLUGIN_NAME ".net."
+
+#define NET_STATS_DIR "/sys/class/net"
+#define STATISTICS_DIR "statistics"
+
+static int
+statAdd(const char *name, TSRecordDataType record_type, TSMutex create_mutex)
+{
+  int stat_id = -1;
+
+  TSMutexLock(create_mutex);
+
+  if (TS_ERROR == TSStatFindName((const char *)name, &stat_id)) {
+    stat_id = TSStatCreate((const char *)name, record_type, TS_STAT_NON_PERSISTENT, TS_STAT_SYNC_SUM);
+    if (stat_id == TS_ERROR) {
+      TSDebug(DEBUG_TAG, "Error creating stat_name: %s", name);
+    } else {
+      TSDebug(DEBUG_TAG, "Created stat_name: %s stat_id: %d", name, stat_id);
+    }
+  }
+
+  TSMutexUnlock(create_mutex);
+
+  return stat_id;
+}
+
+static int
+getFile(const char *filename, char *buffer, int bufferSize)
+{
+  TSFile f = 0;
+  size_t s = 0;
+
+  f = TSfopen(filename, "r");
+  if (!f) {
+    buffer[0] = 0;
+    // Return -1 to indicate read err
+    return -1;
+  }
+
+  s = TSfread(f, buffer, bufferSize);
+  if (s > 0) {
+    buffer[s] = 0;
+  } else {
+    buffer[0] = 0;
+  }
+
+  TSfclose(f);
+
+  return s;
+}
+
+static void
+statSet(const char *name, int value, TSMutex stat_creation_mutex)
+{
+  int stat_id = statAdd(name, TS_RECORDDATATYPE_INT, stat_creation_mutex);
+  if (stat_id != TS_ERROR) {
+    TSStatIntSet(stat_id, value);
+  }
+}
+
+static void
+setNetStat(TSMutex stat_creation_mutex, const char *interface, const char *entry, const char
*subdir)
+{
+  char sysfs_name[PATH_MAX];
+  char stat_name[255];
+  char data[255];
+
+  memset(&stat_name[0], 0, sizeof(stat_name));
+  memset(&sysfs_name[0], 0, sizeof(sysfs_name));
+  memset(&data[0], 0, sizeof(data));
+
+  if ((interface == NULL) || (entry == NULL)) {
+    TSError("%s: NULL subdir or entry", DEBUG_TAG);
+    return;
+  }
+
+  // Generate the ATS stats name
+  snprintf(&stat_name[0], sizeof(stat_name), "%s%s.%s", NET_STATS, interface, entry);
+
+  // Determine if this is a toplevel netdev stat, or one from stastistics.
+  if (subdir == NULL) {
+    snprintf(&sysfs_name[0], sizeof(sysfs_name), "%s/%s/%s", NET_STATS_DIR, interface,
entry);
+  } else {
+    snprintf(&sysfs_name[0], sizeof(sysfs_name), "%s/%s/%s/%s", NET_STATS_DIR, interface,
subdir, entry);
+  }
+
+  if (getFile(&sysfs_name[0], &data[0], sizeof(data)) < 0) {
+    TSDebug(DEBUG_TAG, "Error reading file %s", sysfs_name);
+  } else {
+    statSet(stat_name, atoi(data), stat_creation_mutex);
+  }
+}
+
+static int
+netStatsInfo(TSMutex stat_creation_mutex)
+{
+  struct dirent *dent;
+  DIR *srcdir = opendir(NET_STATS_DIR);
+
+  if (srcdir == NULL) {
+    return 0;
+  }
+
+  while ((dent = readdir(srcdir)) != NULL) {
+    if (strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0 || strcmp(dent->d_name,
"lo") == 0) {
+      continue;
+    }
+
+    setNetStat(stat_creation_mutex, dent->d_name, "speed", NULL);
+    setNetStat(stat_creation_mutex, dent->d_name, "collisions", STATISTICS_DIR);
+    setNetStat(stat_creation_mutex, dent->d_name, "multicast", STATISTICS_DIR);
+    setNetStat(stat_creation_mutex, dent->d_name, "rx_bytes", STATISTICS_DIR);
+    setNetStat(stat_creation_mutex, dent->d_name, "rx_compressed", STATISTICS_DIR);
+    setNetStat(stat_creation_mutex, dent->d_name, "rx_crc_errors", STATISTICS_DIR);
+    setNetStat(stat_creation_mutex, dent->d_name, "rx_dropped", STATISTICS_DIR);
+    setNetStat(stat_creation_mutex, dent->d_name, "rx_errors", STATISTICS_DIR);
+    setNetStat(stat_creation_mutex, dent->d_name, "rx_fifo_errors", STATISTICS_DIR);
+    setNetStat(stat_creation_mutex, dent->d_name, "rx_frame_errors", STATISTICS_DIR);
+    setNetStat(stat_creation_mutex, dent->d_name, "rx_length_errors", STATISTICS_DIR);
+    setNetStat(stat_creation_mutex, dent->d_name, "rx_missed_errors", STATISTICS_DIR);
+    setNetStat(stat_creation_mutex, dent->d_name, "rx_nohandler", STATISTICS_DIR);
+    setNetStat(stat_creation_mutex, dent->d_name, "rx_over_errors", STATISTICS_DIR);
+    setNetStat(stat_creation_mutex, dent->d_name, "rx_packets", STATISTICS_DIR);
+    setNetStat(stat_creation_mutex, dent->d_name, "tx_aborted_errors", STATISTICS_DIR);
+    setNetStat(stat_creation_mutex, dent->d_name, "tx_bytes", STATISTICS_DIR);
+    setNetStat(stat_creation_mutex, dent->d_name, "tx_carrier_errors", STATISTICS_DIR);
+    setNetStat(stat_creation_mutex, dent->d_name, "tx_compressed", STATISTICS_DIR);
+    setNetStat(stat_creation_mutex, dent->d_name, "tx_dropped", STATISTICS_DIR);
+    setNetStat(stat_creation_mutex, dent->d_name, "tx_errors", STATISTICS_DIR);
+    setNetStat(stat_creation_mutex, dent->d_name, "tx_fifo_errors", STATISTICS_DIR);
+    setNetStat(stat_creation_mutex, dent->d_name, "tx_heartbeat_errors", STATISTICS_DIR);
+    setNetStat(stat_creation_mutex, dent->d_name, "tx_packets", STATISTICS_DIR);
+    setNetStat(stat_creation_mutex, dent->d_name, "tx_window_errors", STATISTICS_DIR);
+  }
+  return 0;
+}
+
+static void
+getStats(TSMutex stat_creation_mutex)
+{
+#ifdef HAVE_SYS_SYSINFO_H
+  struct sysinfo info;
+
+  sysinfo(&info);
+
+  statSet(LOAD_AVG_ONE_MIN, info.loads[0], stat_creation_mutex);
+  statSet(LOAD_AVG_FIVE_MIN, info.loads[1], stat_creation_mutex);
+  statSet(LOAD_AVG_TEN_MIN, info.loads[2], stat_creation_mutex);
+  statSet(CURRENT_PROCESSES, info.procs, stat_creation_mutex);
+#endif // #ifdef HAVE_SYS_SYSINFO_H
+  netStatsInfo(stat_creation_mutex);
+
+  return;
+}
+
+static int
+systemStatsContCB(TSCont cont, TSEvent event ATS_UNUSED, void *edata)
+{
+  TSMutex stat_creation_mutex;
+
+  TSDebug(DEBUG_TAG, "entered %s", __FUNCTION__);
+
+  stat_creation_mutex = TSContMutexGet(cont);
+  getStats(stat_creation_mutex);
+
+  TSContSchedule(cont, SYSTEM_STATS_TIMEOUT, TS_THREAD_POOL_TASK);
+  TSDebug(DEBUG_TAG, "finished %s", __FUNCTION__);
+
+  return 0;
+}
+
+void
+TSPluginInit(int argc, const char *argv[])
+{
+  TSPluginRegistrationInfo info;
+  TSCont stats_cont;
+
+  info.plugin_name   = PLUGIN_NAME;
+  info.vendor_name   = "Apache Software Foundation";
+  info.support_email = "dev@trafficserver.apache.org";
+
+  if (TSPluginRegister(&info) != TS_SUCCESS) {
+    TSError("[%s] Plugin registration failed", DEBUG_TAG);
+    return;
+  } else {
+    TSDebug(DEBUG_TAG, "Plugin registration succeeded");
+  }
+
+  stats_cont = TSContCreate(systemStatsContCB, TSMutexCreate());
+  TSContDataSet(stats_cont, NULL);
+
+  // We want our first hit immediate to populate the stats,
+  // Subsequent schedules done within the function will be for
+  // 5 seconds.
+  TSContSchedule(stats_cont, 0, TS_THREAD_POOL_TASK);
+
+  TSDebug(DEBUG_TAG, "Init complete");
+}

-- 
To stop receiving notification emails like this one, please contact
['"commits@trafficserver.apache.org" <commits@trafficserver.apache.org>'].

Mime
View raw message