@cryptotaxi247 / netdata-1 / commits / 0860f0df3

added support for /proc/net/snmp

Costa Tsaousis (ktsaou) committed Mar 30, 2014 at 18:08 UTC 0860f0df39761f14e536a5f081ec8b38dc5886cc
3 files changed +213 -47
netdata.c
+167 -13
@@ -34,18 +34,21 @@
34 #define RRD_DIMENSION_ABSOLUTE 0
35 #define RRD_DIMENSION_INCREMENTAL 1
36
37 -#define RRD_TYPE_NET "net"
38 -#define RRD_TYPE_NET_LEN strlen(RRD_TYPE_NET)
37 +#define RRD_TYPE_NET "net"
38 +#define RRD_TYPE_NET_LEN strlen(RRD_TYPE_NET)
39
40 -#define RRD_TYPE_TC "tc"
41 -#define RRD_TYPE_TC_LEN strlen(RRD_TYPE_TC)
40 +#define RRD_TYPE_TC "tc"
41 +#define RRD_TYPE_TC_LEN strlen(RRD_TYPE_TC)
42
43 -#define RRD_TYPE_DISK "disk"
44 -#define RRD_TYPE_DISK_LEN strlen(RRD_TYPE_DISK)
43 +#define RRD_TYPE_DISK "disk"
44 +#define RRD_TYPE_DISK_LEN strlen(RRD_TYPE_DISK)
45
46 -#define WEB_PATH_FILE "file"
47 -#define WEB_PATH_DATA "data"
48 -#define WEB_PATH_GRAPH "graph"
46 +#define RRD_TYPE_NET_SNMP "ipv4"
47 +#define RRD_TYPE_NET_SNMP_LEN strlen(RRD_TYPE_NET_SNMP)
48 +
49 +#define WEB_PATH_FILE "file"
50 +#define WEB_PATH_DATA "data"
51 +#define WEB_PATH_GRAPH "graph"
52
53 // internal defaults
54 #define UPDATE_EVERY 1
@@ -102,6 +105,9 @@
105 #define MAX_PROC_DISKSTATS_LINE 4096
106 #define MAX_PROC_DISKSTATS_DISK_NAME 1024
107
108 +#define MAX_PROC_NET_SNMP_LINE 4096
109 +#define MAX_PROC_NET_SNMP_NAME 1024
110 +
111
112 int silent = 0;
113 int save_history = HISTORY;
@@ -1585,8 +1591,10 @@ void *new_client(void *ptr)
1591 debug(D_WEB_CLIENT, "%llu: Waiting...", w->id);
1592 retval = select(fdmax+1, &ifds, &ofds, &efds, &tv);
1593
1588 - if(retval == -1)
1589 - fatal("%llu: LISTENER: select() failed.", w->id);
1594 + if(retval == -1) {
1595 + error("%llu: LISTENER: select() failed.", w->id);
1596 + continue;
1597 + }
1598 else if(!retval) {
1599 // timeout
1600 w->obsolete = 1;
@@ -1664,8 +1672,10 @@ void *socket_listen_main(void *ptr)
1672 // debug(D_WEB_CLIENT, "LISTENER: Waiting...");
1673 retval = select(fdmax+1, &ifds, &ofds, &efds, &tv);
1674
1667 - if(retval == -1)
1668 - fatal("LISTENER: select() failed.");
1675 + if(retval == -1) {
1676 + error("LISTENER: select() failed.");
1677 + continue;
1678 + }
1679 else if(retval) {
1680 // check for new incoming connections
1681 if(FD_ISSET(listener, &ifds)) {
@@ -1939,6 +1949,148 @@ int do_proc_diskstats() {
1949 return 0;
1950 }
1951
1952 +// ----------------------------------------------------------------------------
1953 +// /proc/net/snmp processor
1954 +
1955 +int do_proc_net_snmp() {
1956 + char buffer[MAX_PROC_NET_SNMP_LINE+1] = "";
1957 +
1958 + FILE *fp = fopen("/proc/net/snmp", "r");
1959 + if(!fp) {
1960 + error("Cannot read /proc/net/snmp.");
1961 + return 1;
1962 + }
1963 +
1964 + for(;1;) {
1965 + char *p = fgets(buffer, MAX_PROC_NET_SNMP_LINE, fp);
1966 + if(!p) break;
1967 +
1968 + if(strncmp(p, "Ip: ", 4) == 0) {
1969 + // skip the header line, read the data
1970 + p = fgets(buffer, MAX_PROC_NET_SNMP_LINE, fp);
1971 + if(!p) break;
1972 +
1973 + if(strncmp(p, "Ip: ", 4) != 0) {
1974 + error("Cannot read IP line from /proc/net/snmp.");
1975 + break;
1976 + }
1977 +
1978 + // see also http://net-snmp.sourceforge.net/docs/mibs/ip.html
1979 + unsigned long long Forwarding, DefaultTTL, InReceives, InHdrErrors, InAddrErrors, ForwDatagrams, InUnknownProtos, InDiscards, InDelivers,
1980 + OutRequests, OutDiscards, OutNoRoutes, ReasmTimeout, ReasmReqds, ReasmOKs, ReasmFails, FragOKs, FragFails, FragCreates;
1981 +
1982 + int r = sscanf(&buffer[4], "%llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu\n",
1983 + &Forwarding, &DefaultTTL, &InReceives, &InHdrErrors, &InAddrErrors, &ForwDatagrams, &InUnknownProtos, &InDiscards, &InDelivers,
1984 + &OutRequests, &OutDiscards, &OutNoRoutes, &ReasmTimeout, &ReasmReqds, &ReasmOKs, &ReasmFails, &FragOKs, &FragFails, &FragCreates);
1985 +
1986 + if(r == EOF) break;
1987 + if(r != 19) error("Cannot read /proc/net/snmp IP line. Expected 19 params, read %d.", r);
1988 +
1989 + RRD_STATS *st = rrd_stats_find(RRD_TYPE_NET_SNMP ".ip");
1990 + if(!st) {
1991 + st = rrd_stats_create(RRD_TYPE_NET_SNMP ".ip", RRD_TYPE_NET_SNMP ".ip", save_history, "IPv4 Packets", "Packets/s", RRD_TYPE_NET_SNMP);
1992 + if(!st) {
1993 + error("Cannot create RRD_STATS for %s.", RRD_TYPE_NET_SNMP ".ip");
1994 + continue;
1995 + }
1996 +
1997 + if(!rrd_stats_dimension_add(st, "forwarded", "forwarded", sizeof(unsigned long long), 1, 1, RRD_DIMENSION_INCREMENTAL))
1998 + error("Cannot add RRD_STATS dimension %s.", "forwarded");
1999 +
2000 + if(!rrd_stats_dimension_add(st, "sent", "sent", sizeof(unsigned long long), -1, 1, RRD_DIMENSION_INCREMENTAL))
2001 + error("Cannot add RRD_STATS dimension %s.", "sent");
2002 +
2003 + if(!rrd_stats_dimension_add(st, "received", "received", sizeof(unsigned long long), 1, 1, RRD_DIMENSION_INCREMENTAL))
2004 + error("Cannot add RRD_STATS dimension %s.", "received");
2005 +
2006 + }
2007 + else rrd_stats_next(st);
2008 +
2009 + rrd_stats_dimension_set(st, "sent", &OutRequests);
2010 + rrd_stats_dimension_set(st, "received", &InReceives);
2011 + rrd_stats_dimension_set(st, "forwarded", &ForwDatagrams);
2012 + rrd_stats_done(st);
2013 + }
2014 + else if(strncmp(p, "Tcp: ", 5) == 0) {
2015 + // skip the header line, read the data
2016 + p = fgets(buffer, MAX_PROC_NET_SNMP_LINE, fp);
2017 + if(!p) break;
2018 +
2019 + if(strncmp(p, "Tcp: ", 5) != 0) {
2020 + error("Cannot read TCP line from /proc/net/snmp.");
2021 + break;
2022 + }
2023 +
2024 + unsigned long long RtoAlgorithm, RtoMin, RtoMax, MaxConn, ActiveOpens, PassiveOpens, AttemptFails, EstabResets, CurrEstab, InSegs, OutSegs, RetransSegs, InErrs, OutRsts;
2025 +
2026 + int r = sscanf(&buffer[5], "%llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu\n",
2027 + &RtoAlgorithm, &RtoMin, &RtoMax, &MaxConn, &ActiveOpens, &PassiveOpens, &AttemptFails, &EstabResets, &CurrEstab, &InSegs, &OutSegs, &RetransSegs, &InErrs, &OutRsts);
2028 +
2029 + if(r == EOF) break;
2030 + if(r != 14) error("Cannot read /proc/net/snmp TCP line. Expected 14 params, read %d.", r);
2031 +
2032 + // see http://net-snmp.sourceforge.net/docs/mibs/tcp.html
2033 + RRD_STATS *st = rrd_stats_find(RRD_TYPE_NET_SNMP ".tcp");
2034 + if(!st) {
2035 + st = rrd_stats_create(RRD_TYPE_NET_SNMP ".tcp", RRD_TYPE_NET_SNMP ".tcp", save_history, "IPv4 TCP Established Sockets", "Established Sockets", RRD_TYPE_NET_SNMP);
2036 + if(!st) {
2037 + error("Cannot create RRD_STATS for %s.", RRD_TYPE_NET_SNMP ".tcp");
2038 + continue;
2039 + }
2040 +
2041 + if(!rrd_stats_dimension_add(st, "established", "established", sizeof(unsigned long long), 1, 1, RRD_DIMENSION_ABSOLUTE))
2042 + error("Cannot add RRD_STATS dimension %s.", "established");
2043 + }
2044 + else rrd_stats_next(st);
2045 +
2046 + rrd_stats_dimension_set(st, "established", &CurrEstab);
2047 + rrd_stats_done(st);
2048 + }
2049 + else if(strncmp(p, "Udp: ", 5) == 0) {
2050 + // skip the header line, read the data
2051 + p = fgets(buffer, MAX_PROC_NET_SNMP_LINE, fp);
2052 + if(!p) break;
2053 +
2054 + if(strncmp(p, "Udp: ", 5) != 0) {
2055 + error("Cannot read UDP line from /proc/net/snmp.");
2056 + break;
2057 + }
2058 +
2059 + unsigned long long InDatagrams, NoPorts, InErrors, OutDatagrams, RcvbufErrors, SndbufErrors;
2060 +
2061 + int r = sscanf(&buffer[5], "%llu %llu %llu %llu %llu %llu\n",
2062 + &InDatagrams, &NoPorts, &InErrors, &OutDatagrams, &RcvbufErrors, &SndbufErrors);
2063 +
2064 + if(r == EOF) break;
2065 + if(r != 6) error("Cannot read /proc/net/snmp UDP line. Expected 6 params, read %d.", r);
2066 +
2067 + // see http://net-snmp.sourceforge.net/docs/mibs/udp.html
2068 + RRD_STATS *st = rrd_stats_find(RRD_TYPE_NET_SNMP ".udp");
2069 + if(!st) {
2070 + st = rrd_stats_create(RRD_TYPE_NET_SNMP ".udp", RRD_TYPE_NET_SNMP ".udp", save_history, "IPv4 UDP Packets", "Packets/s", RRD_TYPE_NET_SNMP);
2071 + if(!st) {
2072 + error("Cannot create RRD_STATS for %s.", RRD_TYPE_NET_SNMP ".udp");
2073 + continue;
2074 + }
2075 +
2076 + if(!rrd_stats_dimension_add(st, "sent", "sent", sizeof(unsigned long long), -1, 1, RRD_DIMENSION_INCREMENTAL))
2077 + error("Cannot add RRD_STATS dimension %s.", "sent");
2078 +
2079 + if(!rrd_stats_dimension_add(st, "received", "received", sizeof(unsigned long long), 1, 1, RRD_DIMENSION_INCREMENTAL))
2080 + error("Cannot add RRD_STATS dimension %s.", "received");
2081 + }
2082 + else rrd_stats_next(st);
2083 +
2084 + rrd_stats_dimension_set(st, "received", &InDatagrams);
2085 + rrd_stats_dimension_set(st, "sent", &OutDatagrams);
2086 + rrd_stats_done(st);
2087 + }
2088 + }
2089 +
2090 + fclose(fp);
2091 + return 0;
2092 +}
2093 +
2094 // ----------------------------------------------------------------------------
2095 // /proc processor
2096
@@ -1960,6 +2112,7 @@ void *proc_main(void *ptr)
2112 // BEGIN -- the job to be done
2113 do_proc_net_dev(usec);
2114 do_proc_diskstats(usec);
2115 + do_proc_net_snmp(usec);
2116 // END -- the job is done
2117
2118 // find the time to sleep in order to wait exactly update_every seconds
@@ -2288,6 +2441,7 @@ void become_daemon()
2441
2442 signal(SIGCHLD, SIG_IGN);
2443 signal(SIGHUP, SIG_IGN);
2444 + signal(SIGWINCH, SIG_IGN);
2445
2446 // fork() again
2447 i = fork();
web/index.html
+14 -2
@@ -38,6 +38,8 @@
38 mainchart.chart = null;
39 mainchart.width = Math.round(((window.innerWidth * 0.95) - 50) / 1);
40 mainchart.height = window.innerHeight - 200;
41 + if(mainchart.height < 300) mainchart.height = 300;
42 +
43 mainchart.thumbnail = false;
44 mainchart.group = 5;
45 mainchart.group_method = "max";
@@ -49,6 +51,10 @@
51 mainchart.group = 15;
52 mainchart.group_method = "average";
53 }
54 + else if(mainchart.type == "ipv4") {
55 + mainchart.group = 30;
56 + mainchart.group_method = "max";
57 + }
58
59 // calculate the time to refresh each chart
60 mainchart.chart_update_every = mainchart.group * 1000; // milliseconds
@@ -156,6 +162,11 @@
162 c.id == "net.lo")
163 c.enabled = false;
164 }
165 + else if(c.type == "ipv4") {
166 + c.category = "IPv4 connections"
167 + c.group = 60;
168 + c.group_method = "max";
169 + }
170 else if(c.type == "disk") {
171 c.category = "Disk I/O"
172 c.group = 20;
@@ -199,10 +210,11 @@
210 $.each(categories, function(i, a) {
211 if(a.name == "net") a.priority = 1;
212 else if(a.name == "tc") a.priority = 2;
202 - else if(a.name == "disk") a.priority = 3;
213 + else if(a.name == "ipv4") a.priority = 3;
214 + else if(a.name == "disk") a.priority = 4;
215 else a.priority = 4;
216
205 - a.html = "<tr><td><ol class=\"breadcrumb graphs\"><li class=\"active\"><a id=\"" + a.type + "\" href=\"#" + a.type + "\"><b>" + a.title + "</b> " + a.description + " </a></li></ol></td></tr><tr><td><div class=\"thumbgraphs\">" + a.html + "</td></tr>";
217 + a.html = "<tr><td><ol class=\"breadcrumb graphs\"><li class=\"active\"><a id=\"" + a.name + "\" href=\"#" + a.name + "\"><b>" + a.title + "</b> " + a.description + " </a></li></ol></td></tr><tr><td><div class=\"thumbgraphs\">" + a.html + "</td></tr>";
218 });
219
220 function categoriessort(a, b) {
web/netdata.js
+32 -32
@@ -29,45 +29,42 @@ function refreshChart(chart) {
29 // Create our data table out of JSON data loaded from server.
30 chart.datatable = new google.visualization.DataTable(chart.jsondata);
31
32 - var width = chart.width;
33 - var height = chart.height;
34 -
35 - var hAxisTitle = null;
36 - var vAxisTitle = null;
37 - if(height >= 200) hAxisTitle = "Time of Day";
38 - if(width >= 350) vAxisTitle = chart.vtitle;
39 -
40 - var title = chart.title;
41 -
42 - var isStacked = false;
43 - if(chart.name.substring(0, 3) == "tc.") {
44 - isStacked = true;
45 - title += " [stacked]";
46 - }
47 -
32 + // setup the default options
33 var options = {
49 - width: width,
50 - height: height,
51 - title: title,
52 - isStacked: isStacked,
53 - hAxis: {title: hAxisTitle},
54 - vAxis: {title: vAxisTitle, minValue: 10},
34 + width: chart.width,
35 + height: chart.height,
36 + title: chart.title,
37 + hAxis: {title: "Time of Day"},
38 + vAxis: {title: chart.vtitle, minValue: 10},
39 focusTarget: 'category',
56 - lineWidth: (isStacked)?1:2,
57 - areaOpacity: (isStacked)?1.0:0.3,
40 explorer: (chart.explorer)?true:false,
41 // animation: {duration: 1000, easing: 'inAndOut'},
42 };
43
62 - var thumb_options = {
63 - // legend: { position: 'none' },
64 - // tooltip: { trigger: 'none' },
65 - enableInteractivity: false,
66 - //chartArea: {left: 0, top: 0, width: chart.width, height: chart.height},
67 - };
68 - if(chart.thumbnail) $.extend(options, thumb_options);
44 + // disable interactivity on thumbnails
45 + if(chart.thumbnail) options.enableInteractivity = false;
46 +
47 + // hide axis titles if too small
48 + if(chart.height < 200) options.vAxis.title = null;
49 + if(chart.width < 350) options.hAxis.title = null;
50 +
51 + if(chart.name.substring(0, 5) == "ipv4.") {
52 + options.lineWidth = 3;
53 + options.curveType = 'function';
54 + }
55 + else if(chart.name.substring(0, 3) == "tc.") {
56 + options.isStacked = true;
57 + options.title += " [stacked]";
58 + options.areaOpacity = 1.0;
59 + options.lineWidth = 1;
60 + }
61 + else {
62 + options.areaOpacity = 0.3;
63 + options.lineWidth = 2;
64 + }
65
66 // cleanup once every 100 updates
67 + // we don't cleanup on every single, to avoid firefox flashing effect
68 if(chart.chart && chart.refreshCount > 100) {
69 chart.chart.clearChart();
70 chart.chart = null;
@@ -76,7 +73,10 @@ function refreshChart(chart) {
73 // Instantiate and draw our chart, passing in some options.
74 if(!chart.chart) {
75 console.log('Creating new chart for ' + chart.url);
79 - chart.chart = new google.visualization.AreaChart(document.getElementById(chart.div));
76 + if(chart.name.substring(0, 5) == "ipv4.")
77 + chart.chart = new google.visualization.LineChart(document.getElementById(chart.div));
78 + else
79 + chart.chart = new google.visualization.AreaChart(document.getElementById(chart.div));
80 }
81
82 if(chart.chart) chart.chart.draw(chart.datatable, options);