From ae848e953910c932649ddd2ccc5d1251345cec20 Mon Sep 17 00:00:00 2001
From: gerardocorea92 <gerardocorea92@gmail.com>
Date: Fri, 5 Jan 2018 17:54:29 -0500
Subject: [PATCH] Add available_entropy field to kernel input plugin (#3524)

---
 plugins/inputs/system/KERNEL_README.md | 11 +++++++++--
 plugins/inputs/system/kernel.go        | 21 +++++++++++++++++++--
 plugins/inputs/system/kernel_test.go   | 26 +++++++++++++++++++++++---
 3 files changed, 51 insertions(+), 7 deletions(-)

diff --git a/plugins/inputs/system/KERNEL_README.md b/plugins/inputs/system/KERNEL_README.md
index 5ce2d21f..0f28bf77 100644
--- a/plugins/inputs/system/KERNEL_README.md
+++ b/plugins/inputs/system/KERNEL_README.md
@@ -4,11 +4,17 @@ This plugin is only available on Linux.
 
 The kernel plugin gathers info about the kernel that doesn't fit into other
 plugins. In general, it is the statistics available in `/proc/stat` that are
-not covered by other plugins.
+not covered by other plugins as well as the value of `/proc/sys/kernel/random/entropy_avail`
 
 The metrics are documented in `man proc` under the `/proc/stat` section.
+The metrics are documented in `man 4 random` under the `/proc/stat` section.
 
 ```
+
+
+/proc/sys/kernel/random/entropy_avail
+Contains the value of available entropy
+
 /proc/stat
 kernel/system statistics. Varies with architecture. Common entries include:
 
@@ -50,6 +56,7 @@ Number of forks since boot.
     - disk_pages_out (integer, `page (1)`)
     - interrupts (integer, `intr`)
     - processes_forked (integer, `processes`)
+    - entropy_avail (integer, `entropy_available`)
 
 ### Tags:
 
@@ -60,5 +67,5 @@ None
 ```
 $ telegraf --config ~/ws/telegraf.conf --input-filter kernel --test
 * Plugin: kernel, Collection 1
-> kernel boot_time=1457505775i,context_switches=2626618i,disk_pages_in=5741i,disk_pages_out=1808i,interrupts=1472736i,processes_forked=10673i 1457613402960879816
+> kernel entropy_available=2469i,boot_time=1457505775i,context_switches=2626618i,disk_pages_in=5741i,disk_pages_out=1808i,interrupts=1472736i,processes_forked=10673i 1457613402960879816
 ```
diff --git a/plugins/inputs/system/kernel.go b/plugins/inputs/system/kernel.go
index 66cb0f76..1b3bc1df 100644
--- a/plugins/inputs/system/kernel.go
+++ b/plugins/inputs/system/kernel.go
@@ -8,6 +8,7 @@ import (
 	"io/ioutil"
 	"os"
 	"strconv"
+	"strings"
 
 	"github.com/influxdata/telegraf"
 	"github.com/influxdata/telegraf/plugins/inputs"
@@ -23,7 +24,8 @@ var (
 )
 
 type Kernel struct {
-	statFile string
+	statFile        string
+	entropyStatFile string
 }
 
 func (k *Kernel) Description() string {
@@ -33,13 +35,27 @@ func (k *Kernel) Description() string {
 func (k *Kernel) SampleConfig() string { return "" }
 
 func (k *Kernel) Gather(acc telegraf.Accumulator) error {
+
 	data, err := k.getProcStat()
 	if err != nil {
 		return err
 	}
 
+	entropyData, err := ioutil.ReadFile(k.entropyStatFile)
+	if err != nil {
+		return err
+	}
+
+	entropyString := string(entropyData)
+	entropyValue, err := strconv.ParseInt(strings.TrimSpace(entropyString), 10, 64)
+	if err != nil {
+		return err
+	}
+
 	fields := make(map[string]interface{})
 
+	fields["entropy_avail"] = int64(entropyValue)
+
 	dataFields := bytes.Fields(data)
 	for i, field := range dataFields {
 		switch {
@@ -104,7 +120,8 @@ func (k *Kernel) getProcStat() ([]byte, error) {
 func init() {
 	inputs.Add("kernel", func() telegraf.Input {
 		return &Kernel{
-			statFile: "/proc/stat",
+			statFile:        "/proc/stat",
+			entropyStatFile: "/proc/sys/kernel/random/entropy_avail",
 		}
 	})
 }
diff --git a/plugins/inputs/system/kernel_test.go b/plugins/inputs/system/kernel_test.go
index 398cba4c..bf090eb8 100644
--- a/plugins/inputs/system/kernel_test.go
+++ b/plugins/inputs/system/kernel_test.go
@@ -14,10 +14,13 @@ import (
 
 func TestFullProcFile(t *testing.T) {
 	tmpfile := makeFakeStatFile([]byte(statFile_Full))
+	tmpfile2 := makeFakeStatFile([]byte(entropyStatFile_Full))
 	defer os.Remove(tmpfile)
+	defer os.Remove(tmpfile2)
 
 	k := Kernel{
-		statFile: tmpfile,
+		statFile:        tmpfile,
+		entropyStatFile: tmpfile2,
 	}
 
 	acc := testutil.Accumulator{}
@@ -31,16 +34,20 @@ func TestFullProcFile(t *testing.T) {
 		"disk_pages_out":   int64(1808),
 		"interrupts":       int64(1472736),
 		"processes_forked": int64(10673),
+		"entropy_avail":    int64(1024),
 	}
 	acc.AssertContainsFields(t, "kernel", fields)
 }
 
 func TestPartialProcFile(t *testing.T) {
 	tmpfile := makeFakeStatFile([]byte(statFile_Partial))
+	tmpfile2 := makeFakeStatFile([]byte(entropyStatFile_Partial))
 	defer os.Remove(tmpfile)
+	defer os.Remove(tmpfile2)
 
 	k := Kernel{
-		statFile: tmpfile,
+		statFile:        tmpfile,
+		entropyStatFile: tmpfile2,
 	}
 
 	acc := testutil.Accumulator{}
@@ -53,16 +60,20 @@ func TestPartialProcFile(t *testing.T) {
 		"disk_pages_in":    int64(5741),
 		"disk_pages_out":   int64(1808),
 		"interrupts":       int64(1472736),
+		"entropy_avail":    int64(1024),
 	}
 	acc.AssertContainsFields(t, "kernel", fields)
 }
 
 func TestInvalidProcFile1(t *testing.T) {
 	tmpfile := makeFakeStatFile([]byte(statFile_Invalid))
+	tmpfile2 := makeFakeStatFile([]byte(entropyStatFile_Invalid))
 	defer os.Remove(tmpfile)
+	defer os.Remove(tmpfile2)
 
 	k := Kernel{
-		statFile: tmpfile,
+		statFile:        tmpfile,
+		entropyStatFile: tmpfile2,
 	}
 
 	acc := testutil.Accumulator{}
@@ -108,6 +119,7 @@ procs_blocked 0
 softirq 1031662 0 649485 20946 111071 11620 0 1 0 994 237545
 page 5741 1808
 swap 1 0
+entropy_avail 1024
 `
 
 const statFile_Partial = `cpu  6796 252 5655 10444977 175 0 101 0 0 0
@@ -133,6 +145,7 @@ procs_blocked 0
 softirq 1031662 0 649485 20946 111071 11620 0 1 0 994 237545
 page 5741 1808
 swap 1 0
+entropy_avail 1024
 `
 
 // missing second page measurement
@@ -145,8 +158,15 @@ procs_running 2
 page 5741
 procs_blocked 0
 softirq 1031662 0 649485 20946 111071 11620 0 1 0 994 237545
+entropy_avail 1024 2048
 `
 
+const entropyStatFile_Full = `1024`
+
+const entropyStatFile_Partial = `1024`
+
+const entropyStatFile_Invalid = ``
+
 func makeFakeStatFile(content []byte) string {
 	tmpfile, err := ioutil.TempFile("", "kerneltest")
 	if err != nil {
-- 
GitLab