Added System.CPU.Interrupts and System.CPU.ContextSwitches agent parameters for Windo...
authorEriks Jenkevics <eriks@netxms.org>
Wed, 7 Dec 2016 14:35:05 +0000 (16:35 +0200)
committerEriks Jenkevics <eriks@netxms.org>
Tue, 13 Dec 2016 10:20:17 +0000 (12:20 +0200)
13 files changed:
include/nms_agent.h
src/agent/subagents/freebsd/Makefile.am
src/agent/subagents/freebsd/cpu.cpp [new file with mode: 0644]
src/agent/subagents/freebsd/freebsd.cpp
src/agent/subagents/freebsd/freebsd_subagent.h [new file with mode: 0644]
src/agent/subagents/freebsd/proc.cpp
src/agent/subagents/freebsd/system.cpp
src/agent/subagents/freebsd/system.h
src/agent/subagents/linux/cpu.cpp
src/agent/subagents/linux/linux.cpp
src/agent/subagents/linux/linux_subagent.h
src/agent/subagents/winnt/cpu.cpp
src/agent/subagents/winnt/main.cpp

index bbdb6c4..86f39f9 100644 (file)
 #define DCIDESC_SYSTEM_CPU_LOADAVG                _T("Average CPU load for last minute")
 #define DCIDESC_SYSTEM_CPU_LOADAVG5               _T("Average CPU load for last 5 minutes")
 #define DCIDESC_SYSTEM_CPU_LOADAVG15              _T("Average CPU load for last 15 minutes")
+#define DCIDESC_SYSTEM_CPU_INTERRUPTS             _T("Total CPU interrupts")
+#define DCIDESC_SYSTEM_CPU_CONTEXT_SWITCHES       _T("Total CPU context switches")
 
 #define DCIDESC_SYSTEM_CPU_USAGE_EX               _T("Average CPU {instance} utilization for last minute")
 #define DCIDESC_SYSTEM_CPU_USAGE5_EX              _T("Average CPU {instance} utilization for last 5 minutes")
index 35b5a3a..da17708 100644 (file)
@@ -1,12 +1,12 @@
 SUBAGENT = freebsd
 
 pkglib_LTLIBRARIES = freebsd.la
-freebsd_la_SOURCES = disk.cpp freebsd.cpp net.cpp proc.cpp system.cpp 
+freebsd_la_SOURCES = cpu.cpp disk.cpp freebsd.cpp net.cpp proc.cpp system.cpp 
 freebsd_la_CPPFLAGS=-I@top_srcdir@/include
 freebsd_la_LDFLAGS = -module -avoid-version -export-symbols ../platform-subagent.sym
 freebsd_la_LIBADD = ../../libnxagent/libnxagent.la ../../../libnetxms/libnetxms.la -lkvm
 
-EXTRA_DIST = disk.h net.h system.h
+EXTRA_DIST = disk.h net.h freebsd_subagent.h
 
 if !STATIC_BUILD
 install-exec-hook:
diff --git a/src/agent/subagents/freebsd/cpu.cpp b/src/agent/subagents/freebsd/cpu.cpp
new file mode 100644 (file)
index 0000000..69f1bac
--- /dev/null
@@ -0,0 +1,389 @@
+/*
+** NetXMS subagent for FreeBSD
+** Copyright (C) 2004 - 2016 Raden Solutions
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**/
+#include "freebsd_subagent.h"
+
+#define CPU_USAGE_SLOTS       900 // 60 sec * 15 min => 900 sec
+// 64 + 1 for overal
+#define MAX_CPU               (64 + 1)
+
+static THREAD m_cpuUsageCollector = INVALID_THREAD_HANDLE;
+static MUTEX m_cpuUsageMutex = INVALID_MUTEX_HANDLE;
+static bool volatile m_stopCollectorThread = false;
+static UINT64 m_user[MAX_CPU];
+static UINT64 m_nice[MAX_CPU];
+static UINT64 m_system[MAX_CPU];
+static UINT64 m_idle[MAX_CPU];
+static UINT64 m_cpuInterrupts;
+static float *m_cpuUsage;
+static float *m_cpuUsageUser;
+static float *m_cpuUsageNice;
+static float *m_cpuUsageSystem;
+static float *m_cpuUsageIdle;
+static int m_currentSlot = 0;
+static int m_cpuCount = 0;
+
+static int ExecSysctl(const char *param, void *buffer, size_t buffSize)
+{
+   int ret = SYSINFO_RC_ERROR;
+   int mib[2];
+   size_t nSize = sizeof(mib);
+
+   if (sysctlnametomib(param, mib, &nSize) == 0)
+   {
+      if (sysctl(mib, nSize, buffer, &buffSize, NULL, 0) == 0)
+      {
+         ret = SYSINFO_RC_SUCCESS;
+      }
+   }
+
+   return ret;
+}
+
+/**
+ * CPU usage collector
+ */
+static void CpuUsageCollector()
+{
+   UINT64 buffer[1024];
+   size_t buffSize = sizeof(buffer);
+
+   if (ExecSysctl("kern.cp_times", buffer, buffSize) != SYSINFO_RC_SUCCESS)
+      return;
+
+   MutexLock(m_cpuUsageMutex);
+   if (m_currentSlot == CPU_USAGE_SLOTS)
+   {
+      m_currentSlot = 0;
+   }
+
+   UINT64 user, nice, system, interrupts = 0, idle, n = 0;
+   // scan for all CPUs
+   for(int cpu = 0; cpu < m_cpuCount; cpu++)
+   {
+      user = buffer[n];
+      nice = buffer[n+1];
+      system = buffer[n+2];
+      interrupts += buffer[n+3];
+      idle = buffer[n+4];
+
+      UINT64 userDelta, niceDelta, systemDelta, idleDelta;
+
+#define DELTA(x, y) (((x) > (y)) ? ((x) - (y)) : 0)
+      userDelta = DELTA(user, m_user[cpu]);
+      niceDelta = DELTA(nice, m_nice[cpu]);
+      systemDelta = DELTA(system, m_system[cpu]);
+      idleDelta = DELTA(idle, m_idle[cpu]);
+#undef DELTA
+
+      UINT64 totalDelta = userDelta + niceDelta + systemDelta + idleDelta;
+      float onePercent = (float)totalDelta / 100.0; // 1% of total
+      if (onePercent == 0)
+      {
+         onePercent = 1; // TODO: why 1?
+      }
+
+      /* update detailed stats */
+#define UPDATE(delta, target) { \
+         if (delta > 0) { *(target + (cpu * CPU_USAGE_SLOTS) + m_currentSlot) = (float)delta / onePercent; \
+         } \
+         else { *(target + (cpu * CPU_USAGE_SLOTS) + m_currentSlot) = 0; } \
+      }
+
+      UPDATE(userDelta, m_cpuUsageUser);
+      UPDATE(niceDelta, m_cpuUsageNice);
+      UPDATE(systemDelta, m_cpuUsageSystem);
+      UPDATE(idleDelta, m_cpuUsageIdle);
+
+      /* update overal cpu usage */
+      if (totalDelta > 0)
+      {
+         *(m_cpuUsage + (cpu * CPU_USAGE_SLOTS) + m_currentSlot) = 100.0 - ((float)idleDelta / onePercent);
+      }
+      else
+      {
+         *(m_cpuUsage + (cpu * CPU_USAGE_SLOTS) + m_currentSlot) = 0;
+      }
+
+      m_user[cpu] = user;
+      m_nice[cpu] = nice;
+      m_system[cpu] = system;
+      m_idle[cpu] = idle;
+
+      n += 5;
+   }
+
+   m_cpuInterrupts = interrupts;
+
+   /* go to the next slot */
+   m_currentSlot++;
+   MutexUnlock(m_cpuUsageMutex);
+}
+
+/**
+ * CPU usage collector thread
+ *
+ */
+static THREAD_RESULT THREAD_CALL CpuUsageCollectorThread(void *pArg)
+{
+   while(m_stopCollectorThread == false)
+   {
+      CpuUsageCollector();
+      ThreadSleepMs(1000); // sleep 1 second
+   }
+   return THREAD_OK;
+}
+
+/**
+ * Start CPU usage collector
+ */
+void StartCpuUsageCollector()
+{
+   size_t size = sizeof(m_cpuCount);
+   if (ExecSysctl("hw.ncpu", &m_cpuCount, size) != SYSINFO_RC_SUCCESS)
+      return;
+
+   int i, j;
+
+   m_cpuUsageMutex = MutexCreate();
+
+#define SIZE sizeof(float) * CPU_USAGE_SLOTS * m_cpuCount
+#define ALLOCATE_AND_CLEAR(x) x = (float *)malloc(SIZE); memset(x, 0, SIZE);
+   ALLOCATE_AND_CLEAR(m_cpuUsage);
+   ALLOCATE_AND_CLEAR(m_cpuUsageUser);
+   ALLOCATE_AND_CLEAR(m_cpuUsageNice);
+   ALLOCATE_AND_CLEAR(m_cpuUsageSystem);
+   ALLOCATE_AND_CLEAR(m_cpuUsageIdle);
+#undef ALLOCATE_AND_CLEAR
+#undef SIZE
+   // get initial count of user/system/idle time
+   CpuUsageCollector();
+
+   sleep(1);
+
+   // fill first slot with u/s/i delta
+   CpuUsageCollector();
+
+   // fill all slots with current cpu usage
+#define FILL(x) memcpy(x + i, x, sizeof(float));
+   for (i = 0; i < (CPU_USAGE_SLOTS * m_cpuCount) - 1; i++)
+   {
+         FILL(m_cpuUsage);
+         FILL(m_cpuUsageUser);
+         FILL(m_cpuUsageNice);
+         FILL(m_cpuUsageSystem);
+         FILL(m_cpuUsageIdle);
+   }
+#undef FILL
+
+   // start collector
+   m_cpuUsageCollector = ThreadCreateEx(CpuUsageCollectorThread, 0, NULL);
+}
+
+/**
+ * Shutdown CPU usage collector
+ */
+void ShutdownCpuUsageCollector()
+{
+   m_stopCollectorThread = true;
+   ThreadJoin(m_cpuUsageCollector);
+   MutexDestroy(m_cpuUsageMutex);
+
+   free(m_cpuUsage);
+   free(m_cpuUsageUser);
+   free(m_cpuUsageNice);
+   free(m_cpuUsageSystem);
+   free(m_cpuUsageIdle);
+}
+
+static void GetUsage(int source, int cpu, int count, TCHAR *value)
+{
+   float *table;
+   switch (source)
+   {
+      case CPU_USAGE_OVERAL:
+         table = m_cpuUsage;
+         break;
+      case CPU_USAGE_USER:
+         table = m_cpuUsageUser;
+         break;
+      case CPU_USAGE_NICE:
+         table = m_cpuUsageNice;
+         break;
+      case CPU_USAGE_SYSTEM:
+         table = m_cpuUsageSystem;
+         break;
+      case CPU_USAGE_IDLE:
+         table = m_cpuUsageIdle;
+         break;
+      default:
+         table = (float *)m_cpuUsage;
+   }
+
+   table += cpu * CPU_USAGE_SLOTS;
+   double usage = 0;
+   MutexLock(m_cpuUsageMutex);
+
+   float *p = table + m_currentSlot - 1;
+   for (int i = 0; i < count; i++)
+   {
+      usage += *p;
+      if (p == table)
+      {
+         p += CPU_USAGE_SLOTS;
+      }
+      p--;
+   }
+
+   MutexUnlock(m_cpuUsageMutex);
+
+   usage /= count;
+
+   ret_double(value, usage);
+}
+
+LONG H_CpuUsage(const TCHAR *pszParam, const TCHAR *pArg, TCHAR *pValue, AbstractCommSession *session)
+{
+   int count;
+
+   switch(CPU_USAGE_PARAM_INTERVAL(pArg))
+   {
+      case INTERVAL_5MIN:
+         count = 5 * 60;
+         break;
+      case INTERVAL_15MIN:
+         count = 15 * 60;
+         break;
+      default:
+         count = 60;
+         break;
+   }
+
+   GetUsage(CPU_USAGE_PARAM_SOURCE(pArg), 0, count, pValue);
+   return SYSINFO_RC_SUCCESS;
+}
+
+LONG H_CpuUsageEx(const TCHAR *pszParam, const TCHAR *pArg, TCHAR *pValue, AbstractCommSession *session)
+{
+   int count, cpu;
+
+   switch(CPU_USAGE_PARAM_INTERVAL(pArg))
+   {
+      case INTERVAL_5MIN:
+         count = 5 * 60;
+         break;
+      case INTERVAL_15MIN:
+         count = 15 * 60;
+         break;
+      default:
+         count = 60;
+         break;
+   }
+
+   GetUsage(CPU_USAGE_PARAM_SOURCE(pArg), cpu + 1, count, pValue);
+
+   return SYSINFO_RC_SUCCESS;
+}
+
+/**
+ * Handler for CPU info parameters
+ */
+LONG H_CpuInfo(const TCHAR *param, const TCHAR *arg, TCHAR *value, AbstractCommSession *session)
+{
+   size_t size;
+   int ret;
+   switch(*arg)
+   {
+      case 'C':   // CPU count
+         UINT32 count;
+         size = sizeof(count);
+         ret = ExecSysctl("hw.ncpu", &count, size);
+         ret_uint(value, count);
+         break;
+      case 'F':   // Frequency
+         UINT32 freq;
+         size = sizeof(freq);
+         ret = ExecSysctl("hw.clockrate", &freq, size);
+         ret_uint(value, freq);
+         break;
+      case 'M':   // Model
+         char buffer[MAX_NAME];
+         size = sizeof(buffer);
+         ret = ExecSysctl("hw.model", buffer, size);
+         ret_mbstring(value, buffer);
+         break;
+      default:
+         return SYSINFO_RC_UNSUPPORTED;
+   }
+
+   return ret;
+}
+
+LONG H_CpuLoad(const TCHAR *pszParam, const TCHAR *pArg, TCHAR *pValue, AbstractCommSession *session)
+{
+   int nRet = SYSINFO_RC_ERROR;
+   char szArg[128] = {0};
+   FILE *hFile;
+   double dLoad[3];
+
+   struct loadavg sysload;
+   size_t size = sizeof(loadavg);
+   if (ExecSysctl("vm.loadavg", &sysload, size) != SYSINFO_RC_SUCCESS)
+      return nRet;
+
+   switch (pszParam[18])
+   {
+   case '1': // 15 min
+      ret_double(pValue, (float)sysload.ldavg[2] / sysload.fscale);
+      break;
+   case '5': // 5 min
+      ret_double(pValue, (float)sysload.ldavg[1] / sysload.fscale);
+      break;
+   default: // 1 min
+      ret_double(pValue, (float)sysload.ldavg[0] / sysload.fscale);
+      break;
+   }
+   nRet = SYSINFO_RC_SUCCESS;
+
+   return nRet;
+}
+
+/*
+ * Handler for CPU Context Switch parameter
+ */
+LONG H_CpuCswitch(const TCHAR *param, const TCHAR *arg, TCHAR *value, AbstractCommSession *session)
+{
+   UINT64 buffer;
+   size_t size = sizeof(buffer);
+
+   if (sysctlbyname("vm.stats.sys.v_swtch", &buffer, &size, NULL, 0) != 0)
+      return SYSINFO_RC_ERROR;
+
+   ret_uint(value, buffer);
+   return SYSINFO_RC_SUCCESS;
+}
+
+/*
+ * Handler for CPU Interrupts parameter
+ */
+LONG H_CpuInterrupts(const TCHAR *param, const TCHAR *arg, TCHAR *value, AbstractCommSession *session)
+{
+   ret_uint(value, m_cpuInterrupts);
+   return SYSINFO_RC_SUCCESS;
+}
index 8bcce87..b56d795 100644 (file)
 #include <nms_agent.h>
 
 #include "net.h"
-#include "system.h"
+#include "freebsd_subagent.h"
 #include "disk.h"
 
+/**
+ * Initalization callback
+ */
+static BOOL SubAgentInit(Config *config)
+{
+       StartCpuUsageCollector();
+       return TRUE;
+}
+
+/**
+ * Shutdown callback
+ */
+static void SubAgentShutdown()
+{
+       ShutdownCpuUsageCollector();
+}
+
 /**
  * Supported parameters
  */
@@ -81,11 +98,89 @@ static NETXMS_SUBAGENT_PARAM m_parameters[] =
        { _T("Process.WkSet(*)"),             H_ProcessInfo,     CAST_TO_POINTER(PROCINFO_WKSET, const TCHAR *),
                DCI_DT_INT64,   DCIDESC_PROCESS_WKSET },
 
-       { _T("System.CPU.Count"),             H_CpuCount,        NULL,                          DCI_DT_INT,     DCIDESC_SYSTEM_CPU_COUNT },
+       { _T("System.CPU.Count"),             H_CpuInfo,          _T("C"),                      DCI_DT_INT,     DCIDESC_SYSTEM_CPU_COUNT },
+       { _T("System.CPU.Freq"),              H_CpuInfo,          _T("F"),          DCI_DT_INT, DCIDESC_SYSTEM_CPU_COUNT },
+       { _T("System.CPU.Model"),             H_CpuInfo,          _T("M"),          DCI_DT_STRING, DCIDESC_SYSTEM_CPU_COUNT },
 
        { _T("System.CPU.LoadAvg"),           H_CpuLoad,         NULL,                          DCI_DT_FLOAT,   DCIDESC_SYSTEM_CPU_LOADAVG },
        { _T("System.CPU.LoadAvg5"),          H_CpuLoad,         NULL,                          DCI_DT_FLOAT,   DCIDESC_SYSTEM_CPU_LOADAVG5 },
        { _T("System.CPU.LoadAvg15"),         H_CpuLoad,         NULL,                          DCI_DT_FLOAT,   DCIDESC_SYSTEM_CPU_LOADAVG15 },
+
+       { _T("System.CPU.Interrupts"), H_CpuInterrupts,        MAKE_CPU_USAGE_PARAM(INTERVAL_1MIN, CPU_INTERRUPTS),
+            DCI_DT_UINT,  DCIDESC_SYSTEM_CPU_INTERRUPTS },
+    { _T("System.CPU.ContextSwitches"), H_CpuCswitch,        MAKE_CPU_USAGE_PARAM(INTERVAL_1MIN, CPU_CONTEXT_SWITCHES),
+            DCI_DT_UINT,  DCIDESC_SYSTEM_CPU_CONTEXT_SWITCHES },
+
+       /* usage */
+       { _T("System.CPU.Usage"),             H_CpuUsage,        MAKE_CPU_USAGE_PARAM(INTERVAL_1MIN, CPU_USAGE_OVERAL),
+               DCI_DT_FLOAT,   DCIDESC_SYSTEM_CPU_USAGE },
+       { _T("System.CPU.Usage5"),            H_CpuUsage,        MAKE_CPU_USAGE_PARAM(INTERVAL_5MIN, CPU_USAGE_OVERAL),
+               DCI_DT_FLOAT,   DCIDESC_SYSTEM_CPU_USAGE5 },
+       { _T("System.CPU.Usage15"),           H_CpuUsage,        MAKE_CPU_USAGE_PARAM(INTERVAL_15MIN, CPU_USAGE_OVERAL),
+               DCI_DT_FLOAT,   DCIDESC_SYSTEM_CPU_USAGE15 },
+       { _T("System.CPU.Usage(*)"),          H_CpuUsageEx,      MAKE_CPU_USAGE_PARAM(INTERVAL_1MIN, CPU_USAGE_OVERAL),
+               DCI_DT_FLOAT,   DCIDESC_SYSTEM_CPU_USAGE_EX },
+       { _T("System.CPU.Usage5(*)"),         H_CpuUsageEx,      MAKE_CPU_USAGE_PARAM(INTERVAL_5MIN, CPU_USAGE_OVERAL),
+               DCI_DT_FLOAT,   DCIDESC_SYSTEM_CPU_USAGE5_EX },
+       { _T("System.CPU.Usage15(*)"),        H_CpuUsageEx,      MAKE_CPU_USAGE_PARAM(INTERVAL_15MIN, CPU_USAGE_OVERAL),
+               DCI_DT_FLOAT,   DCIDESC_SYSTEM_CPU_USAGE15_EX },
+
+       /* user */
+       { _T("System.CPU.Usage.User"),             H_CpuUsage,        MAKE_CPU_USAGE_PARAM(INTERVAL_1MIN, CPU_USAGE_USER),
+               DCI_DT_FLOAT,   DCIDESC_SYSTEM_CPU_USAGE_USER },
+       { _T("System.CPU.Usage5.User"),            H_CpuUsage,        MAKE_CPU_USAGE_PARAM(INTERVAL_5MIN, CPU_USAGE_USER),
+               DCI_DT_FLOAT,   DCIDESC_SYSTEM_CPU_USAGE5_USER },
+       { _T("System.CPU.Usage15.User"),           H_CpuUsage,        MAKE_CPU_USAGE_PARAM(INTERVAL_15MIN, CPU_USAGE_USER),
+               DCI_DT_FLOAT,   DCIDESC_SYSTEM_CPU_USAGE15_USER },
+       { _T("System.CPU.Usage.User(*)"),          H_CpuUsageEx,      MAKE_CPU_USAGE_PARAM(INTERVAL_1MIN, CPU_USAGE_USER),
+               DCI_DT_FLOAT,   DCIDESC_SYSTEM_CPU_USAGE_USER_EX },
+       { _T("System.CPU.Usage5.User(*)"),         H_CpuUsageEx,      MAKE_CPU_USAGE_PARAM(INTERVAL_5MIN, CPU_USAGE_USER),
+               DCI_DT_FLOAT,   DCIDESC_SYSTEM_CPU_USAGE5_USER_EX },
+       { _T("System.CPU.Usage15.User(*)"),        H_CpuUsageEx,      MAKE_CPU_USAGE_PARAM(INTERVAL_15MIN, CPU_USAGE_USER),
+               DCI_DT_FLOAT,   DCIDESC_SYSTEM_CPU_USAGE15_USER_EX },
+
+       /* nice */
+       { _T("System.CPU.Usage.Nice"),             H_CpuUsage,        MAKE_CPU_USAGE_PARAM(INTERVAL_1MIN, CPU_USAGE_NICE),
+               DCI_DT_FLOAT,   DCIDESC_SYSTEM_CPU_USAGE_NICE },
+       { _T("System.CPU.Usage5.Nice"),            H_CpuUsage,        MAKE_CPU_USAGE_PARAM(INTERVAL_5MIN, CPU_USAGE_NICE),
+               DCI_DT_FLOAT,   DCIDESC_SYSTEM_CPU_USAGE5_NICE },
+       { _T("System.CPU.Usage15.Nice"),           H_CpuUsage,        MAKE_CPU_USAGE_PARAM(INTERVAL_15MIN, CPU_USAGE_NICE),
+               DCI_DT_FLOAT,   DCIDESC_SYSTEM_CPU_USAGE15_NICE },
+       { _T("System.CPU.Usage.Nice(*)"),          H_CpuUsageEx,      MAKE_CPU_USAGE_PARAM(INTERVAL_1MIN, CPU_USAGE_NICE),
+               DCI_DT_FLOAT,   DCIDESC_SYSTEM_CPU_USAGE_NICE_EX },
+       { _T("System.CPU.Usage5.Nice(*)"),         H_CpuUsageEx,      MAKE_CPU_USAGE_PARAM(INTERVAL_5MIN, CPU_USAGE_NICE),
+               DCI_DT_FLOAT,   DCIDESC_SYSTEM_CPU_USAGE5_NICE_EX },
+       { _T("System.CPU.Usage15.Nice(*)"),        H_CpuUsageEx,      MAKE_CPU_USAGE_PARAM(INTERVAL_15MIN, CPU_USAGE_NICE),
+               DCI_DT_FLOAT,   DCIDESC_SYSTEM_CPU_USAGE15_NICE_EX },
+
+       /* system */
+       { _T("System.CPU.Usage.System"),             H_CpuUsage,        MAKE_CPU_USAGE_PARAM(INTERVAL_1MIN, CPU_USAGE_SYSTEM),
+               DCI_DT_FLOAT,   DCIDESC_SYSTEM_CPU_USAGE_SYSTEM },
+       { _T("System.CPU.Usage5.System"),            H_CpuUsage,        MAKE_CPU_USAGE_PARAM(INTERVAL_5MIN, CPU_USAGE_SYSTEM),
+               DCI_DT_FLOAT,   DCIDESC_SYSTEM_CPU_USAGE5_SYSTEM },
+       { _T("System.CPU.Usage15.System"),           H_CpuUsage,        MAKE_CPU_USAGE_PARAM(INTERVAL_15MIN, CPU_USAGE_SYSTEM),
+               DCI_DT_FLOAT,   DCIDESC_SYSTEM_CPU_USAGE15_SYSTEM },
+       { _T("System.CPU.Usage.System(*)"),          H_CpuUsageEx,      MAKE_CPU_USAGE_PARAM(INTERVAL_1MIN, CPU_USAGE_SYSTEM),
+               DCI_DT_FLOAT,   DCIDESC_SYSTEM_CPU_USAGE_SYSTEM_EX },
+       { _T("System.CPU.Usage5.System(*)"),         H_CpuUsageEx,      MAKE_CPU_USAGE_PARAM(INTERVAL_5MIN, CPU_USAGE_SYSTEM),
+               DCI_DT_FLOAT,   DCIDESC_SYSTEM_CPU_USAGE5_SYSTEM_EX },
+       { _T("System.CPU.Usage15.System(*)"),        H_CpuUsageEx,      MAKE_CPU_USAGE_PARAM(INTERVAL_15MIN, CPU_USAGE_SYSTEM),
+               DCI_DT_FLOAT,   DCIDESC_SYSTEM_CPU_USAGE15_SYSTEM_EX },
+
+       /* idle */
+       { _T("System.CPU.Usage.Idle"),             H_CpuUsage,        MAKE_CPU_USAGE_PARAM(INTERVAL_1MIN, CPU_USAGE_IDLE),
+               DCI_DT_FLOAT,   DCIDESC_SYSTEM_CPU_USAGE_IDLE },
+       { _T("System.CPU.Usage5.Idle"),            H_CpuUsage,        MAKE_CPU_USAGE_PARAM(INTERVAL_5MIN, CPU_USAGE_IDLE),
+               DCI_DT_FLOAT,   DCIDESC_SYSTEM_CPU_USAGE5_IDLE },
+       { _T("System.CPU.Usage15.Idle"),           H_CpuUsage,        MAKE_CPU_USAGE_PARAM(INTERVAL_15MIN, CPU_USAGE_IDLE),
+               DCI_DT_FLOAT,   DCIDESC_SYSTEM_CPU_USAGE15_IDLE },
+       { _T("System.CPU.Usage.Idle(*)"),          H_CpuUsageEx,      MAKE_CPU_USAGE_PARAM(INTERVAL_1MIN, CPU_USAGE_IDLE),
+               DCI_DT_FLOAT,   DCIDESC_SYSTEM_CPU_USAGE_IDLE_EX },
+       { _T("System.CPU.Usage5.Idle5(*)"),         H_CpuUsageEx,      MAKE_CPU_USAGE_PARAM(INTERVAL_5MIN, CPU_USAGE_IDLE),
+               DCI_DT_FLOAT,   DCIDESC_SYSTEM_CPU_USAGE5_IDLE_EX },
+       { _T("System.CPU.Usage15.Idle(*)"),        H_CpuUsageEx,      MAKE_CPU_USAGE_PARAM(INTERVAL_15MIN, CPU_USAGE_IDLE),
+               DCI_DT_FLOAT,   DCIDESC_SYSTEM_CPU_USAGE15_IDLE_EX },
+
        { _T("System.Hostname"),              H_Hostname,        NULL,                          DCI_DT_FLOAT,   DCIDESC_SYSTEM_HOSTNAME },
        { _T("System.Memory.Physical.Free"),  H_MemoryInfo,      (const TCHAR *)PHYSICAL_FREE,          DCI_DT_UINT64,  DCIDESC_SYSTEM_MEMORY_PHYSICAL_FREE },
        { _T("System.Memory.Physical.FreePerc"), H_MemoryInfo,   (const TCHAR *)PHYSICAL_FREE_PCT,      DCI_DT_FLOAT,   DCIDESC_SYSTEM_MEMORY_PHYSICAL_FREE_PCT },
@@ -131,8 +226,8 @@ static NETXMS_SUBAGENT_INFO m_info =
        NETXMS_SUBAGENT_INFO_MAGIC,
        _T("FreeBSD"),
        NETXMS_VERSION_STRING,
-       NULL, // init handler
-       NULL, // shutdown handler
+       SubAgentInit, // init handler
+       SubAgentShutdown, // shutdown handler
        NULL, // command handler
        sizeof(m_parameters) / sizeof(NETXMS_SUBAGENT_PARAM),
        m_parameters,
diff --git a/src/agent/subagents/freebsd/freebsd_subagent.h b/src/agent/subagents/freebsd/freebsd_subagent.h
new file mode 100644 (file)
index 0000000..1d8e1d1
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+** NetXMS subagent for FreeBSD
+** Copyright (C) 2004 - 2016 Raden Solutions
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**/
+
+#ifndef __FREEBSD_SUBAGENT_H__
+#define __FREEBSD_SUBAGENT_H__
+
+#if __FreeBSD__ < 8
+#define _SYS_LOCK_PROFILE_H_  /* prevent include of sys/lock_profile.h which can be C++ incompatible) */
+#endif
+
+#include <nms_common.h>
+#include <nms_agent.h>
+
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <sys/utsname.h>
+#include <sys/param.h>
+
+#if __FreeBSD__ < 5
+#include <sys/proc.h>
+#endif
+
+#include <sys/user.h>
+#include <fcntl.h>
+#include <kvm.h>
+#include <paths.h>
+
+enum
+{
+   PHYSICAL_FREE,
+   PHYSICAL_FREE_PCT,
+   PHYSICAL_USED,
+   PHYSICAL_USED_PCT,
+   PHYSICAL_TOTAL,
+   SWAP_FREE,
+   SWAP_FREE_PCT,
+   SWAP_USED,
+   SWAP_USED_PCT,
+   SWAP_TOTAL,
+   VIRTUAL_FREE,
+   VIRTUAL_FREE_PCT,
+   VIRTUAL_USED,
+   VIRTUAL_USED_PCT,
+   VIRTUAL_TOTAL,
+};
+
+enum
+{
+   PROCINFO_CPUTIME,
+   PROCINFO_KTIME,
+   PROCINFO_PAGEFAULTS,
+   PROCINFO_THREADS,
+   PROCINFO_UTIME,
+   PROCINFO_VMSIZE,
+   PROCINFO_WKSET
+};
+
+/**
+ * CPU stats
+ */
+enum
+{
+   CPU_USAGE_OVERAL,
+   CPU_USAGE_USER,
+   CPU_USAGE_NICE,
+   CPU_USAGE_SYSTEM,
+   CPU_USAGE_IDLE,
+   CPU_INTERRUPTS,
+   CPU_CONTEXT_SWITCHES,
+};
+
+/**
+ * Load average intervals
+ */
+enum
+{
+       INTERVAL_1MIN,
+       INTERVAL_5MIN,
+       INTERVAL_15MIN,
+};
+
+#define MAX_NAME                64
+
+#define MAKE_CPU_USAGE_PARAM(interval, source) (const TCHAR *)((((DWORD)(interval)) << 16) | ((DWORD)(source)))
+#define CPU_USAGE_PARAM_INTERVAL(p)                                    ((CAST_FROM_POINTER((p), DWORD)) >> 16)
+#define CPU_USAGE_PARAM_SOURCE(p)                                      ((CAST_FROM_POINTER((p), DWORD)) & 0x0000FFFF)
+
+#define INFOTYPE_MIN             0
+#define INFOTYPE_MAX             1
+#define INFOTYPE_AVG             2
+#define INFOTYPE_SUM             3
+
+int ExecSysctl(TCHAR *param, void *buffer, size_t buffSize);
+void StartCpuUsageCollector();
+void ShutdownCpuUsageCollector();
+
+LONG H_ProcessList(const TCHAR *, const TCHAR *, StringList *, AbstractCommSession *);
+LONG H_Uptime(const TCHAR *, const TCHAR *, TCHAR *, AbstractCommSession *);
+LONG H_Uname(const TCHAR *, const TCHAR *, TCHAR *, AbstractCommSession *);
+LONG H_Hostname(const TCHAR *, const TCHAR *, TCHAR *, AbstractCommSession *);
+LONG H_Hostname(const TCHAR *, const TCHAR *, TCHAR *, AbstractCommSession *);
+LONG H_CpuInfo(const TCHAR *, const TCHAR *, TCHAR *, AbstractCommSession *);
+LONG H_CpuLoad(const TCHAR *, const TCHAR *, TCHAR *, AbstractCommSession *);
+LONG H_CpuUsage(const TCHAR *, const TCHAR *, TCHAR *, AbstractCommSession *);
+LONG H_CpuUsageEx(const TCHAR *, const TCHAR *, TCHAR *, AbstractCommSession *);
+LONG H_CpuCswitch(const TCHAR *param, const TCHAR *arg, TCHAR *value, AbstractCommSession *session);
+LONG H_CpuInterrupts(const TCHAR *param, const TCHAR *arg, TCHAR *value, AbstractCommSession *session);
+LONG H_ProcessCount(const TCHAR *, const TCHAR *, TCHAR *, AbstractCommSession *);
+LONG H_ProcessInfo(const TCHAR *, const TCHAR *, TCHAR *, AbstractCommSession *);
+LONG H_MemoryInfo(const TCHAR *, const TCHAR *, TCHAR *, AbstractCommSession *);
+LONG H_SourcePkgSupport(const TCHAR *, const TCHAR *, TCHAR *, AbstractCommSession *);
+
+#endif // __FREEBSD_SUBAGENT_H__
index 96dda6f..3523e79 100644 (file)
@@ -41,7 +41,7 @@
 #include <sys/user.h>
 #include <kvm.h>
 
-#include "system.h"
+#include "freebsd_subagent.h"
 
 #ifndef KERN_PROC_PROC
 #define KERN_PROC_PROC KERN_PROC_ALL
index 9b6a571..c636b09 100644 (file)
 
 #undef _XOPEN_SOURCE
 
-#if __FreeBSD__ < 8
-#define _SYS_LOCK_PROFILE_H_   /* prevent include of sys/lock_profile.h which can be C++ incompatible) */
-#endif
-
-#include <nms_common.h>
-#include <nms_agent.h>
-
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/sysctl.h>
-#include <sys/utsname.h>
-#include <sys/param.h>
-
-#if __FreeBSD__ < 5
-#include <sys/proc.h>
-#endif
-
-#include <sys/user.h>
-#include <fcntl.h>
-#include <kvm.h>
-#include <paths.h>
-
-
-#include "system.h"
+#include "freebsd_subagent.h"
 
 LONG H_Uptime(const TCHAR *pszParam, const TCHAR *pArg, TCHAR *pValue, AbstractCommSession *session)
 {
@@ -109,63 +86,6 @@ LONG H_Hostname(const TCHAR *pszParam, const TCHAR *pArg, TCHAR *pValue, Abstrac
    return nRet;
 }
 
-LONG H_CpuLoad(const TCHAR *pszParam, const TCHAR *pArg, TCHAR *pValue, AbstractCommSession *session)
-{
-       int nRet = SYSINFO_RC_ERROR;
-   char szArg[128] = {0};
-       FILE *hFile;
-       double dLoad[3];
-
-       // get processor
-       //AgentGetParameterArg(pszParam, 1, szArg, sizeof(szArg));
-
-       if (getloadavg(dLoad, 3) == 3)
-       {
-               switch (pszParam[18])
-               {
-               case '1': // 15 min
-                       ret_double(pValue, dLoad[2]);
-                       break;
-               case '5': // 5 min
-                       ret_double(pValue, dLoad[1]);
-                       break;
-               default: // 1 min
-                       ret_double(pValue, dLoad[0]);
-                       break;
-               }
-               nRet = SYSINFO_RC_SUCCESS;
-       }
-
-       return nRet;
-}
-
-LONG H_CpuUsage(const TCHAR *pszParam, const TCHAR *pArg, TCHAR *pValue, AbstractCommSession *session)
-{
-       return SYSINFO_RC_UNSUPPORTED;
-}
-
-LONG H_CpuCount(const TCHAR *pszParam, const TCHAR *pArg, TCHAR *pValue, AbstractCommSession *session)
-{
-       int nRet = SYSINFO_RC_ERROR;
-       int mib[2];
-       size_t nSize = sizeof(mib), nValSize;
-       int nVal;
-
-       if (sysctlnametomib("hw.ncpu", mib, &nSize) != 0)
-       {
-               return SYSINFO_RC_ERROR;
-       }
-
-       nValSize = sizeof(nVal);
-       if (sysctl(mib, nSize, &nVal, &nValSize, NULL, 0) == 0)
-       {
-       ret_int(pValue, nVal);
-               nRet = SYSINFO_RC_SUCCESS;
-       }
-
-       return nRet;
-}
-
 LONG H_MemoryInfo(const TCHAR *pszParam, const TCHAR *pArg, TCHAR *pValue, AbstractCommSession *session)
 {
        int nRet = SYSINFO_RC_ERROR;
@@ -305,7 +225,6 @@ LONG H_MemoryInfo(const TCHAR *pszParam, const TCHAR *pArg, TCHAR *pValue, Abstr
        return nRet;
 }
 
-
 //
 // stub
 //
index c95b63d..d821c00 100644 (file)
@@ -62,7 +62,7 @@ LONG H_Uptime(const TCHAR *, const TCHAR *, TCHAR *, AbstractCommSession *);
 LONG H_Uname(const TCHAR *, const TCHAR *, TCHAR *, AbstractCommSession *);
 LONG H_Hostname(const TCHAR *, const TCHAR *, TCHAR *, AbstractCommSession *);
 LONG H_Hostname(const TCHAR *, const TCHAR *, TCHAR *, AbstractCommSession *);
-LONG H_CpuCount(const TCHAR *, const TCHAR *, TCHAR *, AbstractCommSession *);
+LONG H_CpuInfo(const TCHAR *, const TCHAR *, TCHAR *, AbstractCommSession *);
 LONG H_CpuLoad(const TCHAR *, const TCHAR *, TCHAR *, AbstractCommSession *);
 LONG H_CpuUsage(const TCHAR *, const TCHAR *, TCHAR *, AbstractCommSession *);
 LONG H_ProcessCount(const TCHAR *, const TCHAR *, TCHAR *, AbstractCommSession *);
index bc9a589..55809ca 100644 (file)
@@ -36,6 +36,8 @@ static UINT64 m_irq[MAX_CPU];
 static UINT64 m_softirq[MAX_CPU];
 static UINT64 m_steal[MAX_CPU];
 static UINT64 m_guest[MAX_CPU];
+static UINT64 m_cpuInterrupts;
+static UINT64 m_cpuContextSwitches;
 static float *m_cpuUsage;
 static float *m_cpuUsageUser;
 static float *m_cpuUsageNice;
@@ -82,23 +84,33 @@ static void CpuUsageCollector()
                if (fgets(buffer, sizeof(buffer), hStat) == NULL)
                        break;
 
-               if (buffer[0] != 'c' || buffer[1] != 'p' || buffer[2] != 'u')
-                       continue;
-
                int ret;
-               if (buffer[3] == ' ')
+               if (buffer[0] == 'c' && buffer[1] == 'p' && buffer[2] == 'u')
                {
-                       // "cpu ..." - Overal
-                       cpu = 0;
-                       ret = sscanf(buffer, "cpu %llu %llu %llu %llu %llu %llu %llu %llu %llu",
-                                       &user, &nice, &system, &idle, &iowait, &irq, &softirq, &steal, &guest);
+         if (buffer[3] == ' ')
+         {
+            // "cpu ..." - Overal
+            cpu = 0;
+            ret = sscanf(buffer, "cpu %llu %llu %llu %llu %llu %llu %llu %llu %llu",
+                  &user, &nice, &system, &idle, &iowait, &irq, &softirq, &steal, &guest);
+         }
+         else
+         {
+            ret = sscanf(buffer, "cpu%u %llu %llu %llu %llu %llu %llu %llu %llu %llu",
+                  &cpu, &user, &nice, &system, &idle, &iowait, &irq, &softirq, &steal, &guest);
+            cpu++;
+         }
                }
-               else
+               else if (buffer[0] == 'i' && buffer[1] == 'n' && buffer[2] == 't' && buffer[3] == 'r')
                {
-                       ret = sscanf(buffer, "cpu%u %llu %llu %llu %llu %llu %llu %llu %llu %llu",
-                                       &cpu, &user, &nice, &system, &idle, &iowait, &irq, &softirq, &steal, &guest);
-                       cpu++;
+         sscanf(buffer, "intr %llu", &m_cpuInterrupts);
                }
+               else if (buffer[0] == 'c' && buffer[1] == 't' && buffer[2] == 'x' && buffer[3] == 't')
+      {
+         sscanf(buffer, "ctxt %llu", &m_cpuContextSwitches);
+      }
+               else
+                  continue;
 
                if (ret < 4)
                        continue;
@@ -313,26 +325,25 @@ static void GetUsage(int source, int cpu, int count, TCHAR *value)
                        table = (float *)m_cpuUsage;
        }
 
-       table += cpu * CPU_USAGE_SLOTS;
+   table += cpu * CPU_USAGE_SLOTS;
+   float usage = 0;
+   MutexLock(m_cpuUsageMutex);
 
-       float usage = 0;
-
-       MutexLock(m_cpuUsageMutex);
-
-       float *p = table + m_currentSlot - 1;
-       for (int i = 0; i < count; i++) 
+   float *p = table + m_currentSlot - 1;
+   for (int i = 0; i < count; i++)
    {
-               usage += *p;
-               if (p == table) 
+      usage += *p;
+      if (p == table)
       {
-                       p += CPU_USAGE_SLOTS;
-               }
-               p--;
-       }
+         p += CPU_USAGE_SLOTS;
+      }
+      p--;
+   }
 
-       MutexUnlock(m_cpuUsageMutex);
+   MutexUnlock(m_cpuUsageMutex);
+
+   usage /= count;
 
-       usage /= count;
        ret_double(value, usage);
 }
 
@@ -533,3 +544,21 @@ LONG H_CpuInfo(const TCHAR *param, const TCHAR *arg, TCHAR *value, AbstractCommS
 
    return SYSINFO_RC_SUCCESS;
 }
+
+/*
+ * Handler for CPU Context Switch parameter
+ */
+LONG H_CpuCswitch(const TCHAR *param, const TCHAR *arg, TCHAR *value, AbstractCommSession *session)
+{
+   ret_uint(value, m_cpuContextSwitches);
+   return SYSINFO_RC_SUCCESS;
+}
+
+/*
+ * Handler for CPU Interrupts parameter
+ */
+LONG H_CpuInterrupts(const TCHAR *param, const TCHAR *arg, TCHAR *value, AbstractCommSession *session)
+{
+   ret_uint(value, m_cpuInterrupts);
+   return SYSINFO_RC_SUCCESS;
+}
index 770707c..cd22096 100644 (file)
@@ -249,6 +249,12 @@ static NETXMS_SUBAGENT_PARAM m_parameters[] =
    { _T("System.CPU.PhysicalId(*)"), H_CpuInfo, _T("P"), DCI_DT_INT, DCIDESC_SYSTEM_CPU_PHYSICAL_ID },
 
        /**************************************************************/
+
+   { _T("System.CPU.Interrupts"), H_CpuInterrupts,        MAKE_CPU_USAGE_PARAM(INTERVAL_1MIN, CPU_INTERRUPTS),
+            DCI_DT_UINT,  DCIDESC_SYSTEM_CPU_INTERRUPTS },
+   { _T("System.CPU.ContextSwitches"), H_CpuCswitch,        MAKE_CPU_USAGE_PARAM(INTERVAL_1MIN, CPU_CONTEXT_SWITCHES),
+            DCI_DT_UINT,  DCIDESC_SYSTEM_CPU_CONTEXT_SWITCHES },
+
        /* usage */
        { _T("System.CPU.Usage"),             H_CpuUsage,        MAKE_CPU_USAGE_PARAM(INTERVAL_1MIN, CPU_USAGE_OVERAL),
                DCI_DT_FLOAT,   DCIDESC_SYSTEM_CPU_USAGE },
index 2787b45..df78648 100644 (file)
@@ -179,6 +179,8 @@ enum
        CPU_USAGE_SOFTIRQ,
        CPU_USAGE_STEAL,
        CPU_USAGE_GUEST,
+       CPU_INTERRUPTS,
+       CPU_CONTEXT_SWITCHES,
 };
 
 #define MAKE_CPU_USAGE_PARAM(interval, source) (const TCHAR *)((((DWORD)(interval)) << 16) | ((DWORD)(source)))
@@ -226,6 +228,8 @@ LONG H_Hostname(const TCHAR *, const TCHAR *, TCHAR *, AbstractCommSession *);
 LONG H_Hostname(const TCHAR *, const TCHAR *, TCHAR *, AbstractCommSession *);
 LONG H_CpuCount(const TCHAR *, const TCHAR *, TCHAR *, AbstractCommSession *);
 LONG H_CpuInfo(const TCHAR *, const TCHAR *, TCHAR *, AbstractCommSession *);
+LONG H_CpuCswitch(const TCHAR *param, const TCHAR *arg, TCHAR *value, AbstractCommSession *session);
+LONG H_CpuInterrupts(const TCHAR *param, const TCHAR *arg, TCHAR *value, AbstractCommSession *session);
 LONG H_CpuLoad(const TCHAR *, const TCHAR *, TCHAR *, AbstractCommSession *);
 LONG H_CpuUsage(const TCHAR *, const TCHAR *, TCHAR *, AbstractCommSession *);
 LONG H_CpuUsageEx(const TCHAR *, const TCHAR *, TCHAR *, AbstractCommSession *);
index 110c1ca..82894ed 100644 (file)
@@ -28,7 +28,8 @@ static SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *s_cpuTimes = NULL;
 static UINT32 *s_usage = NULL;
 static UINT32 *s_idle = NULL;
 static UINT32 *s_kernel = NULL;
-static UINT32 *s_user = NULL;
+static UINT64 *s_user = NULL;
+static UINT64 s_intr, s_ctxt;
 static int s_bpos = 0;
 static CRITICAL_SECTION s_lock;
 
@@ -43,6 +44,7 @@ static THREAD_RESULT THREAD_CALL CPUStatCollector(void *arg)
    SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *curr = &s_cpuTimes[s_cpuCount];
 
    ULONG cpuTimesLen = sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) * s_cpuCount;
+   ULONG cpuCtxtLen = sizeof(SYSTEM_INTERRUPT_INFORMATION) * s_cpuCount;
    ULONG size;
    NtQuerySystemInformation(SystemProcessorPerformanceInformation, s_cpuTimes, cpuTimesLen, &size);
 
@@ -52,10 +54,14 @@ static THREAD_RESULT THREAD_CALL CPUStatCollector(void *arg)
       {
          memcpy(curr, prev, cpuTimesLen);
       }
+      SYSTEM_INTERRUPT_INFORMATION ctxt
+      NtQuerySystemInformation(SystemInterruptInformation, &ctxt, cpuCtxtLen, &size);
 
       UINT64 sysIdle = 0;
       UINT64 sysKernel = 0;
       UINT64 sysUser = 0;
+      UINT64 intr = 0;
+      UINT64 ctxt = 0;
 
       EnterCriticalSection(&s_lock);
 
@@ -66,6 +72,8 @@ static THREAD_RESULT THREAD_CALL CPUStatCollector(void *arg)
          UINT64 kernel = curr[i].KernelTime.QuadPart - prev[i].KernelTime.QuadPart;
          UINT64 user = curr[i].UserTime.QuadPart - prev[i].UserTime.QuadPart;
          UINT64 total = kernel + user;  // kernel time includes idle time
+         intr += curr[i].InterruptCount;
+         ctxt += ctxt[i].ContextSwitches;
 
          sysIdle += idle;
          sysKernel += kernel;
@@ -87,6 +95,9 @@ static THREAD_RESULT THREAD_CALL CPUStatCollector(void *arg)
          }
       }
 
+      s_intr = intr;
+      s_ctxt = ctxt;
+
       UINT64 sysTotal = sysKernel + sysUser;
       if (sysTotal > 0)
       {
@@ -236,3 +247,21 @@ LONG H_CPUUsage(const TCHAR *param, const TCHAR *arg, TCHAR *value, AbstractComm
    _sntprintf(value, MAX_RESULT_LENGTH, _T("%d.%02d"), usage / 100, usage % 100);
    return SYSINFO_RC_SUCCESS;
 }
+
+/*
+ * Handler for CPU Context Switch parameter
+ */
+LONG H_CpuCswitch(const TCHAR *param, const TCHAR *arg, TCHAR *value, AbstractCommSession *session)
+{
+   ret_uint(value, s_ctxt);
+   return SYSINFO_RC_SUCCESS;
+}
+
+/*
+ * Handler for CPU Interrupts parameter
+ */
+LONG H_CpuInterrupts(const TCHAR *param, const TCHAR *arg, TCHAR *value, AbstractCommSession *session)
+{
+   ret_uint(value, s_intr);
+   return SYSINFO_RC_SUCCESS;
+}
index 1788264..a2aac3b 100644 (file)
@@ -53,6 +53,8 @@ LONG H_ServiceTable(const TCHAR *pszCmd, const TCHAR *pArg, Table *value, Abstra
 LONG H_SysUpdateTime(const TCHAR *cmd, const TCHAR *arg, TCHAR *value, AbstractCommSession *session);
 LONG H_ThreadCount(const TCHAR *cmd, const TCHAR *arg, TCHAR *value, AbstractCommSession *session);
 LONG H_WindowStations(const TCHAR *cmd, const TCHAR *arg, StringList *value, AbstractCommSession *session);
+LONG H_CpuCswitch(const TCHAR *param, const TCHAR *arg, TCHAR *value, AbstractCommSession *session);
+LONG H_CpuInterrupts(const TCHAR *param, const TCHAR *arg, TCHAR *value, AbstractCommSession *session);
 
 void StartCPUStatCollector();
 void StopCPUStatCollector();
@@ -219,6 +221,9 @@ static NETXMS_SUBAGENT_PARAM m_parameters[] =
        { _T("Process.WkSet(*)"), H_ProcInfo, (TCHAR *)PROCINFO_WKSET, DCI_DT_UINT64, DCIDESC_PROCESS_WKSET },
        { _T("System.AppAddressSpace"), H_AppAddressSpace, NULL, DCI_DT_UINT, DCIDESC_SYSTEM_APPADDRESSSPACE },
        { _T("System.ConnectedUsers"), H_ConnectedUsers, NULL, DCI_DT_INT, DCIDESC_SYSTEM_CONNECTEDUSERS },
+
+       { _T("System.CPU.Interrupts"), H_CpuInterrupts, _T("T0i"), DCI_DT_UINT, DCIDESC_SYSTEM_CPU_INTERRUPTS },
+       { _T("System.CPU.ContextSwitches"), H_CpuCswitch, _T("T0C"), DCI_DT_UINT, DCIDESC_SYSTEM_CPU_CONTEXT_SWITCHES },
    
    { _T("System.CPU.CurrentUsage"), H_CPUUsage, _T("T0U"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGECURR },
    { _T("System.CPU.CurrentUsage.Idle"), H_CPUUsage, _T("T0I"), DCI_DT_FLOAT, DCIDESC_SYSTEM_CPU_USAGECURR_IDLE },