From a12e082dbe875fec6bac5e027248694bbccb72b3 Mon Sep 17 00:00:00 2001
From: calerogers <cale.rogers.m@gmail.com>
Date: Fri, 14 Apr 2017 13:40:36 -0700
Subject: [PATCH] Refactor interrupts plugin code (#2670)

---
 plugins/inputs/interrupts/README.md          |  6 +-
 plugins/inputs/interrupts/interrupts.go      | 63 +++++++-------------
 plugins/inputs/interrupts/interrupts_test.go |  5 +-
 3 files changed, 29 insertions(+), 45 deletions(-)

diff --git a/plugins/inputs/interrupts/README.md b/plugins/inputs/interrupts/README.md
index aec30094..f823aae0 100644
--- a/plugins/inputs/interrupts/README.md
+++ b/plugins/inputs/interrupts/README.md
@@ -5,9 +5,9 @@ The interrupts plugin gathers metrics about IRQs from `/proc/interrupts` and `/p
 ### Configuration
 ```
 [[inputs.interrupts]]
-  ## A list of IRQs to include for metric ingestion, if not specified
-  ## will default to collecting all IRQs.
-  include = ["0", "1", "30", "NET_RX"]
+  ## To filter which IRQs to collect, make use of tagpass / tagdrop, i.e.
+  # [inputs.interrupts.tagdrop]
+    # irq = [ "NET_RX", "TASKLET" ]
 ```
 
 ### Measurements
diff --git a/plugins/inputs/interrupts/interrupts.go b/plugins/inputs/interrupts/interrupts.go
index 1feb6441..75cbf3be 100644
--- a/plugins/inputs/interrupts/interrupts.go
+++ b/plugins/inputs/interrupts/interrupts.go
@@ -5,7 +5,8 @@ import (
 	"fmt"
 	"github.com/influxdata/telegraf"
 	"github.com/influxdata/telegraf/plugins/inputs"
-	"io/ioutil"
+	"io"
+	"os"
 	"strconv"
 	"strings"
 )
@@ -38,18 +39,16 @@ func (s *Interrupts) SampleConfig() string {
 	return sampleConfig
 }
 
-func parseInterrupts(irqdata string) ([]IRQ, error) {
+func parseInterrupts(r io.Reader) ([]IRQ, error) {
 	var irqs []IRQ
 	var cpucount int
-	scanner := bufio.NewScanner(strings.NewReader(irqdata))
-	ok := scanner.Scan()
-	if ok {
+	scanner := bufio.NewScanner(r)
+	if scanner.Scan() {
 		cpus := strings.Fields(scanner.Text())
-		if cpus[0] == "CPU0" {
-			cpucount = len(cpus)
+		if cpus[0] != "CPU0" {
+			return nil, fmt.Errorf("Expected first line to start with CPU0, but was %s", scanner.Text())
 		}
-	} else if scanner.Err() != nil {
-		return irqs, fmt.Errorf("Reading %s: %s", scanner.Text(), scanner.Err())
+		cpucount = len(cpus)
 	}
 	for scanner.Scan() {
 		fields := strings.Fields(scanner.Text())
@@ -80,16 +79,10 @@ func parseInterrupts(irqdata string) ([]IRQ, error) {
 		}
 		irqs = append(irqs, *irq)
 	}
-	return irqs, nil
-}
-
-func fileToString(path string) (string, error) {
-	data, err := ioutil.ReadFile(path)
-	if err != nil {
-		return "", err
+	if scanner.Err() != nil {
+		return nil, fmt.Errorf("Error scanning file: %s", scanner.Err())
 	}
-	content := string(data)
-	return content, nil
+	return irqs, nil
 }
 
 func gatherTagsFields(irq IRQ) (map[string]string, map[string]interface{}) {
@@ -103,31 +96,21 @@ func gatherTagsFields(irq IRQ) (map[string]string, map[string]interface{}) {
 }
 
 func (s *Interrupts) Gather(acc telegraf.Accumulator) error {
-	irqdata, err := fileToString("/proc/interrupts")
-	if err != nil {
-		acc.AddError(fmt.Errorf("Reading %s: %s", "/proc/interrupts", err))
-	}
-	irqs, err := parseInterrupts(irqdata)
-	if err != nil {
-		acc.AddError(fmt.Errorf("Parsing %s: %s", "/proc/interrupts", err))
-	} else {
-		for _, irq := range irqs {
-			tags, fields := gatherTagsFields(irq)
-			acc.AddFields("interrupts", fields, tags)
+	for measurement, file := range map[string]string{"interrupts": "/proc/interrupts", "soft_interrupts": "/proc/softirqs"} {
+		f, err := os.Open(file)
+		if err != nil {
+			acc.AddError(fmt.Errorf("Could not open file: %s", file))
+			continue
+		}
+		defer f.Close()
+		irqs, err := parseInterrupts(f)
+		if err != nil {
+			acc.AddError(fmt.Errorf("Parsing %s: %s", file, err))
+			continue
 		}
-	}
-
-	irqdata, err = fileToString("/proc/softirqs")
-	if err != nil {
-		acc.AddError(fmt.Errorf("Reading %s: %s", "/proc/softirqs", err))
-	}
-	irqs, err = parseInterrupts(irqdata)
-	if err != nil {
-		acc.AddError(fmt.Errorf("Parsing %s: %s", "/proc/softirqs", err))
-	} else {
 		for _, irq := range irqs {
 			tags, fields := gatherTagsFields(irq)
-			acc.AddFields("softirqs", fields, tags)
+			acc.AddFields(measurement, fields, tags)
 		}
 	}
 	return nil
diff --git a/plugins/inputs/interrupts/interrupts_test.go b/plugins/inputs/interrupts/interrupts_test.go
index d968eb09..6c76c850 100644
--- a/plugins/inputs/interrupts/interrupts_test.go
+++ b/plugins/inputs/interrupts/interrupts_test.go
@@ -1,6 +1,7 @@
 package interrupts
 
 import (
+	"bytes"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 	"testing"
@@ -15,7 +16,7 @@ LOC: 2338608687 2334309625   Local timer interrupts
 MIS:          0
 NET_RX:     867028		225
 TASKLET:	205			0`
-
+	f := bytes.NewBufferString(interruptStr)
 	parsed := []IRQ{
 		IRQ{
 			ID: "0", Type: "IO-APIC-edge", Device: "timer",
@@ -46,7 +47,7 @@ TASKLET:	205			0`
 			Total: int64(205),
 		},
 	}
-	got, err := parseInterrupts(interruptStr)
+	got, err := parseInterrupts(f)
 	require.Equal(t, nil, err)
 	require.NotEqual(t, 0, len(got))
 	require.Equal(t, len(got), len(parsed))
-- 
GitLab