From ca61d03cdffe89746cc7da5a09b3d1c45e0d66ac Mon Sep 17 00:00:00 2001 From: Wojciech Kudla Date: Mon, 19 Nov 2018 20:06:02 +0000 Subject: [PATCH 1/4] Switch CPU from field to tag in Interrupts input plugin (#4999) --- plugins/inputs/interrupts/README.md | 12 +- plugins/inputs/interrupts/interrupts.go | 45 ++-- plugins/inputs/interrupts/interrupts_test.go | 223 +++++++++---------- 3 files changed, 129 insertions(+), 151 deletions(-) diff --git a/plugins/inputs/interrupts/README.md b/plugins/inputs/interrupts/README.md index eb1e3979d89e2..98bb38fe878cd 100644 --- a/plugins/inputs/interrupts/README.md +++ b/plugins/inputs/interrupts/README.md @@ -16,20 +16,20 @@ There are two measurements reported by this plugin. - `soft_interrupts` gathers metrics from the `/proc/softirqs` file ### Fields -- CPUx: the amount of interrupts for the IRQ handled by that CPU -- total: total amount of interrupts for all CPUs +- Count: the amount of interrupts for the IRQ handled by CPU described in CPU tag ### Tags - irq: the IRQ - type: the type of interrupt - device: the name of the device that is located at that IRQ +- cpu: the CPU ### Example Output ``` ./telegraf --config ~/interrupts_config.conf --test * Plugin: inputs.interrupts, Collection 1 -> interrupts,irq=0,type=IO-APIC,device=2-edge\ timer,host=hostname CPU0=23i,total=23i 1489346531000000000 -> interrupts,irq=1,host=hostname,type=IO-APIC,device=1-edge\ i8042 CPU0=9i,total=9i 1489346531000000000 -> interrupts,irq=30,type=PCI-MSI,device=65537-edge\ virtio1-input.0,host=hostname CPU0=1i,total=1i 1489346531000000000 -> soft_interrupts,irq=NET_RX,host=hostname CPU0=280879i,total=280879i 1489346531000000000 +> interrupts,irq=0,type=IO-APIC,device=2-edge\ timer,host=hostname,cpu=cpu0 count=23i 1489346531000000000 +> interrupts,irq=1,host=hostname,type=IO-APIC,device=1-edge\ i8042,cpu=cpu0 count=9i 1489346531000000000 +> interrupts,irq=30,type=PCI-MSI,device=65537-edge\ virtio1-input.0,host=hostname,cpu=cpu1 count=1i 1489346531000000000 +> soft_interrupts,irq=NET_RX,host=hostname,cpu=cpu0 count=280879i 1489346531000000000 ``` diff --git a/plugins/inputs/interrupts/interrupts.go b/plugins/inputs/interrupts/interrupts.go index 9e8c8ea246ece..96d072e0259d8 100644 --- a/plugins/inputs/interrupts/interrupts.go +++ b/plugins/inputs/interrupts/interrupts.go @@ -18,12 +18,12 @@ type IRQ struct { ID string Type string Device string - Total int64 - Cpus []int64 + CPU int + Count int64 } -func NewIRQ(id string) *IRQ { - return &IRQ{ID: id, Cpus: []int64{}} +func NewIRQ(id string, cpu int, count int64) *IRQ { + return &IRQ{ID: id, CPU: cpu, Count: count} } const sampleConfig = ` @@ -59,28 +59,31 @@ scan: continue } irqid := strings.TrimRight(fields[0], ":") - irq := NewIRQ(irqid) irqvals := fields[1:] + + _, err := strconv.ParseInt(irqid, 10, 64) + irqType := "" + irqDevice := "" + if err == nil && len(fields) >= cpucount+2 { + irqType = fields[cpucount+1] + irqDevice = strings.Join(fields[cpucount+2:], " ") + } else if len(fields) > cpucount { + irqType = strings.Join(fields[cpucount+1:], " ") + } + for i := 0; i < cpucount; i++ { if i < len(irqvals) { irqval, err := strconv.ParseInt(irqvals[i], 10, 64) if err != nil { continue scan } - irq.Cpus = append(irq.Cpus, irqval) + irq := NewIRQ(irqid, i, irqval) + irq.Type = irqType + irq.Device = irqDevice + irqs = append(irqs, *irq) } } - for _, irqval := range irq.Cpus { - irq.Total += irqval - } - _, err := strconv.ParseInt(irqid, 10, 64) - if err == nil && len(fields) >= cpucount+2 { - irq.Type = fields[cpucount+1] - irq.Device = strings.Join(fields[cpucount+2:], " ") - } else if len(fields) > cpucount { - irq.Type = strings.Join(fields[cpucount+1:], " ") - } - irqs = append(irqs, *irq) + } if scanner.Err() != nil { return nil, fmt.Errorf("Error scanning file: %s", scanner.Err()) @@ -89,12 +92,8 @@ scan: } func gatherTagsFields(irq IRQ) (map[string]string, map[string]interface{}) { - tags := map[string]string{"irq": irq.ID, "type": irq.Type, "device": irq.Device} - fields := map[string]interface{}{"total": irq.Total} - for i := 0; i < len(irq.Cpus); i++ { - cpu := fmt.Sprintf("CPU%d", i) - fields[cpu] = irq.Cpus[i] - } + tags := map[string]string{"irq": irq.ID, "type": irq.Type, "device": irq.Device, "cpu": "cpu" + strconv.Itoa(irq.CPU)} + fields := map[string]interface{}{"count": irq.Count} return tags, fields } diff --git a/plugins/inputs/interrupts/interrupts_test.go b/plugins/inputs/interrupts/interrupts_test.go index 3990461b1e3c1..fa3b06df8d6f5 100644 --- a/plugins/inputs/interrupts/interrupts_test.go +++ b/plugins/inputs/interrupts/interrupts_test.go @@ -19,34 +19,19 @@ NET_RX: 867028 225 TASKLET: 205 0` f := bytes.NewBufferString(interruptStr) parsed := []IRQ{ - { - ID: "0", Type: "IO-APIC-edge", Device: "timer", - Cpus: []int64{int64(134), int64(0)}, Total: int64(134), - }, - { - ID: "1", Type: "IO-APIC-edge", Device: "i8042", - Cpus: []int64{int64(7), int64(3)}, Total: int64(10), - }, - { - ID: "NMI", Type: "Non-maskable interrupts", - Cpus: []int64{int64(0), int64(0)}, Total: int64(0), - }, - { - ID: "LOC", Type: "Local timer interrupts", - Cpus: []int64{int64(2338608687), int64(2334309625)}, - Total: int64(4672918312), - }, - { - ID: "MIS", Cpus: []int64{int64(0)}, Total: int64(0), - }, - { - ID: "NET_RX", Cpus: []int64{int64(867028), int64(225)}, - Total: int64(867253), - }, - { - ID: "TASKLET", Cpus: []int64{int64(205), int64(0)}, - Total: int64(205), - }, + {ID: "0", Type: "IO-APIC-edge", Device: "timer", CPU: 0, Count: int64(134)}, + {ID: "0", Type: "IO-APIC-edge", Device: "timer", CPU: 1, Count: int64(0)}, + {ID: "1", Type: "IO-APIC-edge", Device: "i8042", CPU: 0, Count: int64(7)}, + {ID: "1", Type: "IO-APIC-edge", Device: "i8042", CPU: 1, Count: int64(3)}, + {ID: "NMI", Type: "Non-maskable interrupts", CPU: 0, Count: int64(0)}, + {ID: "NMI", Type: "Non-maskable interrupts", CPU: 1, Count: int64(0)}, + {ID: "LOC", Type: "Local timer interrupts", CPU: 0, Count: int64(2338608687)}, + {ID: "LOC", Type: "Local timer interrupts", CPU: 1, Count: int64(2334309625)}, + {ID: "MIS", CPU: 0, Count: int64(0)}, + {ID: "NET_RX", CPU: 0, Count: int64(867028)}, + {ID: "NET_RX", CPU: 1, Count: int64(225)}, + {ID: "TASKLET", CPU: 0, Count: int64(205)}, + {ID: "TASKLET", CPU: 1, Count: int64(0)}, } got, err := parseInterrupts(f) require.Equal(t, nil, err) @@ -54,9 +39,6 @@ TASKLET: 205 0` require.Equal(t, len(got), len(parsed)) for i := 0; i < len(parsed); i++ { assert.Equal(t, parsed[i], got[i]) - for k := 0; k < len(parsed[i].Cpus); k++ { - assert.Equal(t, parsed[i].Cpus[k], got[i].Cpus[k]) - } } } @@ -88,94 +70,94 @@ func TestParseInterruptsBad(t *testing.T) { IPI6: 0 0 0 0 completion interrupts` f := bytes.NewBufferString(interruptStr) parsed := []IRQ{ - { - ID: "16", Type: "bcm2836-timer", Device: "0 Edge arch_timer", - Cpus: []int64{0, 0, 0, 0}, - }, - { - ID: "17", Type: "bcm2836-timer", Device: "1 Edge arch_timer", - Cpus: []int64{127224250, 118424219, 127224437, 117885416}, Total: 490758322, - }, - { - ID: "21", Type: "bcm2836-pmu", Device: "9 Edge arm-pmu", - Cpus: []int64{0, 0, 0, 0}, - }, - { - ID: "23", Type: "ARMCTRL-level", Device: "1 Edge 3f00b880.mailbox", - Cpus: []int64{1549514, 0, 0, 0}, Total: 1549514, - }, - { - ID: "24", Type: "ARMCTRL-level", Device: "2 Edge VCHIQ doorbell", - Cpus: []int64{2, 0, 0, 0}, Total: 2, - }, - { - ID: "46", Type: "ARMCTRL-level", Device: "48 Edge bcm2708_fb dma", - Cpus: []int64{0, 0, 0, 0}, - }, - { - ID: "48", Type: "ARMCTRL-level", Device: "50 Edge DMA IRQ", - Cpus: []int64{0, 0, 0, 0}, - }, - { - ID: "50", Type: "ARMCTRL-level", Device: "52 Edge DMA IRQ", - Cpus: []int64{0, 0, 0, 0}, - }, - { - ID: "51", Type: "ARMCTRL-level", Device: "53 Edge DMA IRQ", - Cpus: []int64{208, 0, 0, 0}, Total: 208, - }, - { - ID: "54", Type: "ARMCTRL-level", Device: "56 Edge DMA IRQ", - Cpus: []int64{883002, 0, 0, 0}, Total: 883002, - }, - { - ID: "59", Type: "ARMCTRL-level", Device: "61 Edge bcm2835-auxirq", - Cpus: []int64{0, 0, 0, 0}, - }, - { - ID: "62", Type: "ARMCTRL-level", Device: "64 Edge dwc_otg, dwc_otg_pcd, dwc_otg_hcd:usb1", - Cpus: []int64{521451447, 0, 0, 0}, Total: 521451447, - }, - { - ID: "86", Type: "ARMCTRL-level", Device: "88 Edge mmc0", - Cpus: []int64{857597, 0, 0, 0}, Total: 857597, - }, - { - ID: "87", Type: "ARMCTRL-level", Device: "89 Edge uart-pl011", - Cpus: []int64{4938, 0, 0, 0}, Total: 4938, - }, - { - ID: "92", Type: "ARMCTRL-level", Device: "94 Edge mmc1", - Cpus: []int64{5669, 0, 0, 0}, Total: 5669, - }, - { - ID: "IPI0", Type: "CPU wakeup interrupts", - Cpus: []int64{0, 0, 0, 0}, - }, - { - ID: "IPI1", Type: "Timer broadcast interrupts", - Cpus: []int64{0, 0, 0, 0}, - }, - { - ID: "IPI2", Type: "Rescheduling interrupts", - Cpus: []int64{23564958, 23464876, 23531165, 23040826}, Total: 93601825, - }, - { - ID: "IPI3", Type: "Function call interrupts", - Cpus: []int64{148438, 639704, 644266, 588150}, Total: 2020558, - }, - { - ID: "IPI4", Type: "CPU stop interrupts", - Cpus: []int64{0, 0, 0, 0}, - }, - { - ID: "IPI5", Type: "IRQ work interrupts", - Cpus: []int64{4348149, 1843985, 3819457, 1822877}, Total: 11834468, - }, - { - ID: "IPI6", Type: "completion interrupts", - Cpus: []int64{0, 0, 0, 0}, - }, + {ID: "16", Type: "bcm2836-timer", Device: "0 Edge arch_timer", CPU: 0, Count: int64(0)}, + {ID: "16", Type: "bcm2836-timer", Device: "0 Edge arch_timer", CPU: 1, Count: int64(0)}, + {ID: "16", Type: "bcm2836-timer", Device: "0 Edge arch_timer", CPU: 2, Count: int64(0)}, + {ID: "16", Type: "bcm2836-timer", Device: "0 Edge arch_timer", CPU: 3, Count: int64(0)}, + {ID: "17", Type: "bcm2836-timer", Device: "1 Edge arch_timer", CPU: 0, Count: int64(127224250)}, + {ID: "17", Type: "bcm2836-timer", Device: "1 Edge arch_timer", CPU: 1, Count: int64(118424219)}, + {ID: "17", Type: "bcm2836-timer", Device: "1 Edge arch_timer", CPU: 2, Count: int64(127224437)}, + {ID: "17", Type: "bcm2836-timer", Device: "1 Edge arch_timer", CPU: 3, Count: int64(117885416)}, + {ID: "21", Type: "bcm2836-pmu", Device: "9 Edge arm-pmu", CPU: 0, Count: int64(0)}, + {ID: "21", Type: "bcm2836-pmu", Device: "9 Edge arm-pmu", CPU: 1, Count: int64(0)}, + {ID: "21", Type: "bcm2836-pmu", Device: "9 Edge arm-pmu", CPU: 2, Count: int64(0)}, + {ID: "21", Type: "bcm2836-pmu", Device: "9 Edge arm-pmu", CPU: 3, Count: int64(0)}, + {ID: "23", Type: "ARMCTRL-level", Device: "1 Edge 3f00b880.mailbox", CPU: 0, Count: int64(1549514)}, + {ID: "23", Type: "ARMCTRL-level", Device: "1 Edge 3f00b880.mailbox", CPU: 1, Count: int64(0)}, + {ID: "23", Type: "ARMCTRL-level", Device: "1 Edge 3f00b880.mailbox", CPU: 2, Count: int64(0)}, + {ID: "23", Type: "ARMCTRL-level", Device: "1 Edge 3f00b880.mailbox", CPU: 3, Count: int64(0)}, + {ID: "24", Type: "ARMCTRL-level", Device: "2 Edge VCHIQ doorbell", CPU: 0, Count: int64(2)}, + {ID: "24", Type: "ARMCTRL-level", Device: "2 Edge VCHIQ doorbell", CPU: 1, Count: int64(0)}, + {ID: "24", Type: "ARMCTRL-level", Device: "2 Edge VCHIQ doorbell", CPU: 2, Count: int64(0)}, + {ID: "24", Type: "ARMCTRL-level", Device: "2 Edge VCHIQ doorbell", CPU: 3, Count: int64(0)}, + {ID: "46", Type: "ARMCTRL-level", Device: "48 Edge bcm2708_fb dma", CPU: 0, Count: int64(0)}, + {ID: "46", Type: "ARMCTRL-level", Device: "48 Edge bcm2708_fb dma", CPU: 1, Count: int64(0)}, + {ID: "46", Type: "ARMCTRL-level", Device: "48 Edge bcm2708_fb dma", CPU: 2, Count: int64(0)}, + {ID: "46", Type: "ARMCTRL-level", Device: "48 Edge bcm2708_fb dma", CPU: 3, Count: int64(0)}, + {ID: "48", Type: "ARMCTRL-level", Device: "50 Edge DMA IRQ", CPU: 0, Count: int64(0)}, + {ID: "48", Type: "ARMCTRL-level", Device: "50 Edge DMA IRQ", CPU: 1, Count: int64(0)}, + {ID: "48", Type: "ARMCTRL-level", Device: "50 Edge DMA IRQ", CPU: 2, Count: int64(0)}, + {ID: "48", Type: "ARMCTRL-level", Device: "50 Edge DMA IRQ", CPU: 3, Count: int64(0)}, + {ID: "50", Type: "ARMCTRL-level", Device: "52 Edge DMA IRQ", CPU: 0, Count: int64(0)}, + {ID: "50", Type: "ARMCTRL-level", Device: "52 Edge DMA IRQ", CPU: 1, Count: int64(0)}, + {ID: "50", Type: "ARMCTRL-level", Device: "52 Edge DMA IRQ", CPU: 2, Count: int64(0)}, + {ID: "50", Type: "ARMCTRL-level", Device: "52 Edge DMA IRQ", CPU: 3, Count: int64(0)}, + {ID: "51", Type: "ARMCTRL-level", Device: "53 Edge DMA IRQ", CPU: 0, Count: int64(208)}, + {ID: "51", Type: "ARMCTRL-level", Device: "53 Edge DMA IRQ", CPU: 1, Count: int64(0)}, + {ID: "51", Type: "ARMCTRL-level", Device: "53 Edge DMA IRQ", CPU: 2, Count: int64(0)}, + {ID: "51", Type: "ARMCTRL-level", Device: "53 Edge DMA IRQ", CPU: 3, Count: int64(0)}, + {ID: "54", Type: "ARMCTRL-level", Device: "56 Edge DMA IRQ", CPU: 0, Count: int64(883002)}, + {ID: "54", Type: "ARMCTRL-level", Device: "56 Edge DMA IRQ", CPU: 1, Count: int64(0)}, + {ID: "54", Type: "ARMCTRL-level", Device: "56 Edge DMA IRQ", CPU: 2, Count: int64(0)}, + {ID: "54", Type: "ARMCTRL-level", Device: "56 Edge DMA IRQ", CPU: 3, Count: int64(0)}, + {ID: "59", Type: "ARMCTRL-level", Device: "61 Edge bcm2835-auxirq", CPU: 0, Count: int64(0)}, + {ID: "59", Type: "ARMCTRL-level", Device: "61 Edge bcm2835-auxirq", CPU: 1, Count: int64(0)}, + {ID: "59", Type: "ARMCTRL-level", Device: "61 Edge bcm2835-auxirq", CPU: 2, Count: int64(0)}, + {ID: "59", Type: "ARMCTRL-level", Device: "61 Edge bcm2835-auxirq", CPU: 3, Count: int64(0)}, + {ID: "62", Type: "ARMCTRL-level", Device: "64 Edge dwc_otg, dwc_otg_pcd, dwc_otg_hcd:usb1", CPU: 0, Count: int64(521451447)}, + {ID: "62", Type: "ARMCTRL-level", Device: "64 Edge dwc_otg, dwc_otg_pcd, dwc_otg_hcd:usb1", CPU: 1, Count: int64(0)}, + {ID: "62", Type: "ARMCTRL-level", Device: "64 Edge dwc_otg, dwc_otg_pcd, dwc_otg_hcd:usb1", CPU: 2, Count: int64(0)}, + {ID: "62", Type: "ARMCTRL-level", Device: "64 Edge dwc_otg, dwc_otg_pcd, dwc_otg_hcd:usb1", CPU: 3, Count: int64(0)}, + {ID: "86", Type: "ARMCTRL-level", Device: "88 Edge mmc0", CPU: 0, Count: int64(857597)}, + {ID: "86", Type: "ARMCTRL-level", Device: "88 Edge mmc0", CPU: 1, Count: int64(0)}, + {ID: "86", Type: "ARMCTRL-level", Device: "88 Edge mmc0", CPU: 2, Count: int64(0)}, + {ID: "86", Type: "ARMCTRL-level", Device: "88 Edge mmc0", CPU: 3, Count: int64(0)}, + {ID: "87", Type: "ARMCTRL-level", Device: "89 Edge uart-pl011", CPU: 0, Count: int64(4938)}, + {ID: "87", Type: "ARMCTRL-level", Device: "89 Edge uart-pl011", CPU: 1, Count: int64(0)}, + {ID: "87", Type: "ARMCTRL-level", Device: "89 Edge uart-pl011", CPU: 2, Count: int64(0)}, + {ID: "87", Type: "ARMCTRL-level", Device: "89 Edge uart-pl011", CPU: 3, Count: int64(0)}, + {ID: "92", Type: "ARMCTRL-level", Device: "94 Edge mmc1", CPU: 0, Count: int64(5669)}, + {ID: "92", Type: "ARMCTRL-level", Device: "94 Edge mmc1", CPU: 1, Count: int64(0)}, + {ID: "92", Type: "ARMCTRL-level", Device: "94 Edge mmc1", CPU: 2, Count: int64(0)}, + {ID: "92", Type: "ARMCTRL-level", Device: "94 Edge mmc1", CPU: 3, Count: int64(0)}, + {ID: "IPI0", Type: "CPU wakeup interrupts", CPU: 0, Count: int64(0)}, + {ID: "IPI0", Type: "CPU wakeup interrupts", CPU: 1, Count: int64(0)}, + {ID: "IPI0", Type: "CPU wakeup interrupts", CPU: 2, Count: int64(0)}, + {ID: "IPI0", Type: "CPU wakeup interrupts", CPU: 3, Count: int64(0)}, + {ID: "IPI1", Type: "Timer broadcast interrupts", CPU: 0, Count: int64(0)}, + {ID: "IPI1", Type: "Timer broadcast interrupts", CPU: 1, Count: int64(0)}, + {ID: "IPI1", Type: "Timer broadcast interrupts", CPU: 2, Count: int64(0)}, + {ID: "IPI1", Type: "Timer broadcast interrupts", CPU: 3, Count: int64(0)}, + {ID: "IPI2", Type: "Rescheduling interrupts", CPU: 0, Count: int64(23564958)}, + {ID: "IPI2", Type: "Rescheduling interrupts", CPU: 1, Count: int64(23464876)}, + {ID: "IPI2", Type: "Rescheduling interrupts", CPU: 2, Count: int64(23531165)}, + {ID: "IPI2", Type: "Rescheduling interrupts", CPU: 3, Count: int64(23040826)}, + {ID: "IPI3", Type: "Function call interrupts", CPU: 0, Count: int64(148438)}, + {ID: "IPI3", Type: "Function call interrupts", CPU: 1, Count: int64(639704)}, + {ID: "IPI3", Type: "Function call interrupts", CPU: 2, Count: int64(644266)}, + {ID: "IPI3", Type: "Function call interrupts", CPU: 3, Count: int64(588150)}, + {ID: "IPI4", Type: "CPU stop interrupts", CPU: 0, Count: int64(0)}, + {ID: "IPI4", Type: "CPU stop interrupts", CPU: 1, Count: int64(0)}, + {ID: "IPI4", Type: "CPU stop interrupts", CPU: 2, Count: int64(0)}, + {ID: "IPI4", Type: "CPU stop interrupts", CPU: 3, Count: int64(0)}, + {ID: "IPI5", Type: "IRQ work interrupts", CPU: 0, Count: int64(4348149)}, + {ID: "IPI5", Type: "IRQ work interrupts", CPU: 1, Count: int64(1843985)}, + {ID: "IPI5", Type: "IRQ work interrupts", CPU: 2, Count: int64(3819457)}, + {ID: "IPI5", Type: "IRQ work interrupts", CPU: 3, Count: int64(1822877)}, + {ID: "IPI6", Type: "completion interrupts", CPU: 0, Count: int64(0)}, + {ID: "IPI6", Type: "completion interrupts", CPU: 1, Count: int64(0)}, + {ID: "IPI6", Type: "completion interrupts", CPU: 2, Count: int64(0)}, + {ID: "IPI6", Type: "completion interrupts", CPU: 3, Count: int64(0)}, } got, err := parseInterrupts(f) require.Equal(t, nil, err) @@ -183,8 +165,5 @@ func TestParseInterruptsBad(t *testing.T) { require.Equal(t, len(got), len(parsed)) for i := 0; i < len(parsed); i++ { assert.Equal(t, parsed[i], got[i]) - for k := 0; k < len(parsed[i].Cpus); k++ { - assert.Equal(t, parsed[i].Cpus[k], got[i].Cpus[k]) - } } } From e8afcdeee8da5e5fe391847e3f64237dce43e560 Mon Sep 17 00:00:00 2001 From: Wojciech Kudla Date: Fri, 30 Nov 2018 01:14:07 +0000 Subject: [PATCH 2/4] Added cpus_as_tags config param, restructured and extended tests (#4999) --- plugins/inputs/interrupts/README.md | 18 +- plugins/inputs/interrupts/interrupts.go | 78 +++-- plugins/inputs/interrupts/interrupts_test.go | 303 +++++++++---------- 3 files changed, 219 insertions(+), 180 deletions(-) diff --git a/plugins/inputs/interrupts/README.md b/plugins/inputs/interrupts/README.md index 98bb38fe878cd..afe2df2e13057 100644 --- a/plugins/inputs/interrupts/README.md +++ b/plugins/inputs/interrupts/README.md @@ -8,6 +8,10 @@ The interrupts plugin gathers metrics about IRQs from `/proc/interrupts` and `/p ## To filter which IRQs to collect, make use of tagpass / tagdrop, i.e. # [inputs.interrupts.tagdrop] # irq = [ "NET_RX", "TASKLET" ] + # + # To report cpus as tags instead of fields use cpus_as_tags + # cpus_as_tags = false + ``` ### Measurements @@ -16,20 +20,32 @@ There are two measurements reported by this plugin. - `soft_interrupts` gathers metrics from the `/proc/softirqs` file ### Fields +For cpus_as_tags=false (default): +- CPUx: the amount of interrupts for the IRQ handled by the CPU +- Total: sum of interrupts for the IRS for all CPUs +For cpus_as_tags=true (): - Count: the amount of interrupts for the IRQ handled by CPU described in CPU tag ### Tags - irq: the IRQ - type: the type of interrupt - device: the name of the device that is located at that IRQ -- cpu: the CPU +- cpu: the CPU (when cpus_as_tags=true) ### Example Output ``` ./telegraf --config ~/interrupts_config.conf --test +For cpus_as_tags=false (default): * Plugin: inputs.interrupts, Collection 1 > interrupts,irq=0,type=IO-APIC,device=2-edge\ timer,host=hostname,cpu=cpu0 count=23i 1489346531000000000 > interrupts,irq=1,host=hostname,type=IO-APIC,device=1-edge\ i8042,cpu=cpu0 count=9i 1489346531000000000 > interrupts,irq=30,type=PCI-MSI,device=65537-edge\ virtio1-input.0,host=hostname,cpu=cpu1 count=1i 1489346531000000000 > soft_interrupts,irq=NET_RX,host=hostname,cpu=cpu0 count=280879i 1489346531000000000 + +For cpus_as_tags=true: +> interrupts,cpu=cpu6,host=hostname,irq=PIW,type=Posted-interrupt\ wakeup\ event count=0i 1543539773000000000 +> interrupts,cpu=cpu7,host=hostname,irq=PIW,type=Posted-interrupt\ wakeup\ event count=0i 1543539773000000000 +> soft_interrupts,cpu=cpu0,host=hostname,irq=HI count=246441i 1543539773000000000 +> soft_interrupts,cpu=cpu1,host=hostname,irq=HI count=159154i 1543539773000000000 + ``` diff --git a/plugins/inputs/interrupts/interrupts.go b/plugins/inputs/interrupts/interrupts.go index 96d072e0259d8..5b3e0c89b6a8f 100644 --- a/plugins/inputs/interrupts/interrupts.go +++ b/plugins/inputs/interrupts/interrupts.go @@ -12,24 +12,33 @@ import ( "github.com/influxdata/telegraf/plugins/inputs" ) -type Interrupts struct{} +type Interrupts struct { + CpusAsTags bool +} + +func NewInterrupts() *Interrupts { + return &Interrupts{false} +} type IRQ struct { ID string Type string Device string - CPU int - Count int64 + Total int64 + Cpus []int64 } -func NewIRQ(id string, cpu int, count int64) *IRQ { - return &IRQ{ID: id, CPU: cpu, Count: count} +func NewIRQ(id string) *IRQ { + return &IRQ{ID: id, Cpus: []int64{}} } const sampleConfig = ` ## To filter which IRQs to collect, make use of tagpass / tagdrop, i.e. # [inputs.interrupts.tagdrop] - # irq = [ "NET_RX", "TASKLET" ] + # irq = [ "NET_RX", "TASKLET" ] + # + # To report cpus as tags instead of fields use cpus_as_tags + # cpus_as_tags = false ` func (s *Interrupts) Description() string { @@ -59,31 +68,28 @@ scan: continue } irqid := strings.TrimRight(fields[0], ":") + irq := NewIRQ(irqid) irqvals := fields[1:] - - _, err := strconv.ParseInt(irqid, 10, 64) - irqType := "" - irqDevice := "" - if err == nil && len(fields) >= cpucount+2 { - irqType = fields[cpucount+1] - irqDevice = strings.Join(fields[cpucount+2:], " ") - } else if len(fields) > cpucount { - irqType = strings.Join(fields[cpucount+1:], " ") - } - for i := 0; i < cpucount; i++ { if i < len(irqvals) { irqval, err := strconv.ParseInt(irqvals[i], 10, 64) if err != nil { continue scan } - irq := NewIRQ(irqid, i, irqval) - irq.Type = irqType - irq.Device = irqDevice - irqs = append(irqs, *irq) + irq.Cpus = append(irq.Cpus, irqval) } } - + for _, irqval := range irq.Cpus { + irq.Total += irqval + } + _, err := strconv.ParseInt(irqid, 10, 64) + if err == nil && len(fields) >= cpucount+2 { + irq.Type = fields[cpucount+1] + irq.Device = strings.Join(fields[cpucount+2:], " ") + } else if len(fields) > cpucount { + irq.Type = strings.Join(fields[cpucount+1:], " ") + } + irqs = append(irqs, *irq) } if scanner.Err() != nil { return nil, fmt.Errorf("Error scanning file: %s", scanner.Err()) @@ -92,8 +98,12 @@ scan: } func gatherTagsFields(irq IRQ) (map[string]string, map[string]interface{}) { - tags := map[string]string{"irq": irq.ID, "type": irq.Type, "device": irq.Device, "cpu": "cpu" + strconv.Itoa(irq.CPU)} - fields := map[string]interface{}{"count": irq.Count} + tags := map[string]string{"irq": irq.ID, "type": irq.Type, "device": irq.Device} + fields := map[string]interface{}{"total": irq.Total} + for i := 0; i < len(irq.Cpus); i++ { + cpu := fmt.Sprintf("cpu%d", i) + fields[cpu] = irq.Cpus[i] + } return tags, fields } @@ -110,12 +120,26 @@ func (s *Interrupts) Gather(acc telegraf.Accumulator) error { acc.AddError(fmt.Errorf("Parsing %s: %s", file, err)) continue } - for _, irq := range irqs { - tags, fields := gatherTagsFields(irq) + reportMetrics(measurement, irqs, acc, s.CpusAsTags) + } + return nil +} + +func reportMetrics(measurement string, irqs []IRQ, acc telegraf.Accumulator, cpusAsTags bool) { + for _, irq := range irqs { + tags, fields := gatherTagsFields(irq) + if cpusAsTags { + for cpu, count := range irq.Cpus { + cpuTags := map[string]string{"cpu": fmt.Sprintf("cpu%d", cpu)} + for k, v := range tags { + cpuTags[k] = v + } + acc.AddFields(measurement, map[string]interface{}{"count": count}, cpuTags) + } + } else { acc.AddFields(measurement, fields, tags) } } - return nil } func init() { diff --git a/plugins/inputs/interrupts/interrupts_test.go b/plugins/inputs/interrupts/interrupts_test.go index fa3b06df8d6f5..3df6ad390e8c8 100644 --- a/plugins/inputs/interrupts/interrupts_test.go +++ b/plugins/inputs/interrupts/interrupts_test.go @@ -2,168 +2,167 @@ package interrupts import ( "bytes" + "fmt" "testing" + "time" - "github.com/stretchr/testify/assert" + "github.com/influxdata/telegraf" + "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" ) -func TestParseInterrupts(t *testing.T) { - interruptStr := ` CPU0 CPU1 - 0: 134 0 IO-APIC-edge timer - 1: 7 3 IO-APIC-edge i8042 -NMI: 0 0 Non-maskable interrupts -LOC: 2338608687 2334309625 Local timer interrupts -MIS: 0 -NET_RX: 867028 225 -TASKLET: 205 0` - f := bytes.NewBufferString(interruptStr) - parsed := []IRQ{ - {ID: "0", Type: "IO-APIC-edge", Device: "timer", CPU: 0, Count: int64(134)}, - {ID: "0", Type: "IO-APIC-edge", Device: "timer", CPU: 1, Count: int64(0)}, - {ID: "1", Type: "IO-APIC-edge", Device: "i8042", CPU: 0, Count: int64(7)}, - {ID: "1", Type: "IO-APIC-edge", Device: "i8042", CPU: 1, Count: int64(3)}, - {ID: "NMI", Type: "Non-maskable interrupts", CPU: 0, Count: int64(0)}, - {ID: "NMI", Type: "Non-maskable interrupts", CPU: 1, Count: int64(0)}, - {ID: "LOC", Type: "Local timer interrupts", CPU: 0, Count: int64(2338608687)}, - {ID: "LOC", Type: "Local timer interrupts", CPU: 1, Count: int64(2334309625)}, - {ID: "MIS", CPU: 0, Count: int64(0)}, - {ID: "NET_RX", CPU: 0, Count: int64(867028)}, - {ID: "NET_RX", CPU: 1, Count: int64(225)}, - {ID: "TASKLET", CPU: 0, Count: int64(205)}, - {ID: "TASKLET", CPU: 1, Count: int64(0)}, +// ===================================================================================== +// Setup and helper functions +// ===================================================================================== + +type MockAccumulator struct { + telegraf.Accumulator + mock.Mock +} + +func (acc *MockAccumulator) AddFields(measurement string, fields map[string]interface{}, tags map[string]string, t ...time.Time) { + acc.Called(measurement, fields, tags) +} + +func expectIrqTags(m *MockAccumulator, t *testing.T, measurement string, irq IRQ) { + for idx, value := range irq.Cpus { + m.AssertCalled(t, "AddFields", measurement, map[string]interface{}{"count": value}, map[string]string{"irq": irq.ID, "type": irq.Type, "device": irq.Device, "cpu": fmt.Sprintf("cpu%d", idx)}) } - got, err := parseInterrupts(f) +} + +func expectIrqFields(m *MockAccumulator, t *testing.T, measurement string, irq IRQ) { + fields := map[string]interface{}{} + total := int64(0) + for idx, count := range irq.Cpus { + fields[fmt.Sprintf("cpu%d", idx)] = count + total += count + } + fields["total"] = total + + m.AssertCalled(t, "AddFields", measurement, fields, map[string]string{"irq": irq.ID, "type": irq.Type, "device": irq.Device}) +} + +func setup(t *testing.T, irqString string, cpusAsTags bool) (*MockAccumulator, []IRQ) { + f := bytes.NewBufferString(irqString) + irqs, err := parseInterrupts(f) require.Equal(t, nil, err) - require.NotEqual(t, 0, len(got)) - require.Equal(t, len(got), len(parsed)) - for i := 0; i < len(parsed); i++ { - assert.Equal(t, parsed[i], got[i]) + require.NotEqual(t, 0, len(irqs)) + + acc := new(MockAccumulator) + acc.On("AddFields", mock.Anything, mock.Anything, mock.Anything).Return(nil) + reportMetrics("soft_interrupts", irqs, acc, cpusAsTags) + + return acc, irqs +} + +// ===================================================================================== +// Soft interrupts +// ===================================================================================== + +const softIrqsString = ` CPU0 CPU1 + 0: 134 0 IO-APIC-edge timer + 1: 7 3 IO-APIC-edge i8042 + NMI: 0 0 Non-maskable interrupts + LOC: 2338608687 2334309625 Local timer interrupts + MIS: 0 + NET_RX: 867028 225 + TASKLET: 205 0` + +var softIrqsExpectedArgs = []IRQ{ + {ID: "0", Type: "IO-APIC-edge", Device: "timer", Cpus: []int64{134, 0}}, + {ID: "1", Type: "IO-APIC-edge", Device: "i8042", Cpus: []int64{7, 3}}, + {ID: "NMI", Type: "Non-maskable interrupts", Cpus: []int64{0, 0}}, + {ID: "MIS", Cpus: []int64{0}}, + {ID: "NET_RX", Cpus: []int64{867028, 225}}, + {ID: "TASKLET", Cpus: []int64{205, 0}}, +} + +func TestCpusAsTagsSoftIrqs(t *testing.T) { + acc, irqs := setup(t, softIrqsString, true) + reportMetrics("soft_interrupts", irqs, acc, true) + + for _, irq := range softIrqsExpectedArgs { + expectIrqTags(acc, t, "soft_interrupts", irq) } } -// Tests #4470 -func TestParseInterruptsBad(t *testing.T) { - interruptStr := ` CPU0 CPU1 CPU2 CPU3 - 16: 0 0 0 0 bcm2836-timer 0 Edge arch_timer - 17: 127224250 118424219 127224437 117885416 bcm2836-timer 1 Edge arch_timer - 21: 0 0 0 0 bcm2836-pmu 9 Edge arm-pmu - 23: 1549514 0 0 0 ARMCTRL-level 1 Edge 3f00b880.mailbox - 24: 2 0 0 0 ARMCTRL-level 2 Edge VCHIQ doorbell - 46: 0 0 0 0 ARMCTRL-level 48 Edge bcm2708_fb dma - 48: 0 0 0 0 ARMCTRL-level 50 Edge DMA IRQ - 50: 0 0 0 0 ARMCTRL-level 52 Edge DMA IRQ - 51: 208 0 0 0 ARMCTRL-level 53 Edge DMA IRQ - 54: 883002 0 0 0 ARMCTRL-level 56 Edge DMA IRQ - 59: 0 0 0 0 ARMCTRL-level 61 Edge bcm2835-auxirq - 62: 521451447 0 0 0 ARMCTRL-level 64 Edge dwc_otg, dwc_otg_pcd, dwc_otg_hcd:usb1 - 86: 857597 0 0 0 ARMCTRL-level 88 Edge mmc0 - 87: 4938 0 0 0 ARMCTRL-level 89 Edge uart-pl011 - 92: 5669 0 0 0 ARMCTRL-level 94 Edge mmc1 - FIQ: usb_fiq - IPI0: 0 0 0 0 CPU wakeup interrupts - IPI1: 0 0 0 0 Timer broadcast interrupts - IPI2: 23564958 23464876 23531165 23040826 Rescheduling interrupts - IPI3: 148438 639704 644266 588150 Function call interrupts - IPI4: 0 0 0 0 CPU stop interrupts - IPI5: 4348149 1843985 3819457 1822877 IRQ work interrupts - IPI6: 0 0 0 0 completion interrupts` - f := bytes.NewBufferString(interruptStr) - parsed := []IRQ{ - {ID: "16", Type: "bcm2836-timer", Device: "0 Edge arch_timer", CPU: 0, Count: int64(0)}, - {ID: "16", Type: "bcm2836-timer", Device: "0 Edge arch_timer", CPU: 1, Count: int64(0)}, - {ID: "16", Type: "bcm2836-timer", Device: "0 Edge arch_timer", CPU: 2, Count: int64(0)}, - {ID: "16", Type: "bcm2836-timer", Device: "0 Edge arch_timer", CPU: 3, Count: int64(0)}, - {ID: "17", Type: "bcm2836-timer", Device: "1 Edge arch_timer", CPU: 0, Count: int64(127224250)}, - {ID: "17", Type: "bcm2836-timer", Device: "1 Edge arch_timer", CPU: 1, Count: int64(118424219)}, - {ID: "17", Type: "bcm2836-timer", Device: "1 Edge arch_timer", CPU: 2, Count: int64(127224437)}, - {ID: "17", Type: "bcm2836-timer", Device: "1 Edge arch_timer", CPU: 3, Count: int64(117885416)}, - {ID: "21", Type: "bcm2836-pmu", Device: "9 Edge arm-pmu", CPU: 0, Count: int64(0)}, - {ID: "21", Type: "bcm2836-pmu", Device: "9 Edge arm-pmu", CPU: 1, Count: int64(0)}, - {ID: "21", Type: "bcm2836-pmu", Device: "9 Edge arm-pmu", CPU: 2, Count: int64(0)}, - {ID: "21", Type: "bcm2836-pmu", Device: "9 Edge arm-pmu", CPU: 3, Count: int64(0)}, - {ID: "23", Type: "ARMCTRL-level", Device: "1 Edge 3f00b880.mailbox", CPU: 0, Count: int64(1549514)}, - {ID: "23", Type: "ARMCTRL-level", Device: "1 Edge 3f00b880.mailbox", CPU: 1, Count: int64(0)}, - {ID: "23", Type: "ARMCTRL-level", Device: "1 Edge 3f00b880.mailbox", CPU: 2, Count: int64(0)}, - {ID: "23", Type: "ARMCTRL-level", Device: "1 Edge 3f00b880.mailbox", CPU: 3, Count: int64(0)}, - {ID: "24", Type: "ARMCTRL-level", Device: "2 Edge VCHIQ doorbell", CPU: 0, Count: int64(2)}, - {ID: "24", Type: "ARMCTRL-level", Device: "2 Edge VCHIQ doorbell", CPU: 1, Count: int64(0)}, - {ID: "24", Type: "ARMCTRL-level", Device: "2 Edge VCHIQ doorbell", CPU: 2, Count: int64(0)}, - {ID: "24", Type: "ARMCTRL-level", Device: "2 Edge VCHIQ doorbell", CPU: 3, Count: int64(0)}, - {ID: "46", Type: "ARMCTRL-level", Device: "48 Edge bcm2708_fb dma", CPU: 0, Count: int64(0)}, - {ID: "46", Type: "ARMCTRL-level", Device: "48 Edge bcm2708_fb dma", CPU: 1, Count: int64(0)}, - {ID: "46", Type: "ARMCTRL-level", Device: "48 Edge bcm2708_fb dma", CPU: 2, Count: int64(0)}, - {ID: "46", Type: "ARMCTRL-level", Device: "48 Edge bcm2708_fb dma", CPU: 3, Count: int64(0)}, - {ID: "48", Type: "ARMCTRL-level", Device: "50 Edge DMA IRQ", CPU: 0, Count: int64(0)}, - {ID: "48", Type: "ARMCTRL-level", Device: "50 Edge DMA IRQ", CPU: 1, Count: int64(0)}, - {ID: "48", Type: "ARMCTRL-level", Device: "50 Edge DMA IRQ", CPU: 2, Count: int64(0)}, - {ID: "48", Type: "ARMCTRL-level", Device: "50 Edge DMA IRQ", CPU: 3, Count: int64(0)}, - {ID: "50", Type: "ARMCTRL-level", Device: "52 Edge DMA IRQ", CPU: 0, Count: int64(0)}, - {ID: "50", Type: "ARMCTRL-level", Device: "52 Edge DMA IRQ", CPU: 1, Count: int64(0)}, - {ID: "50", Type: "ARMCTRL-level", Device: "52 Edge DMA IRQ", CPU: 2, Count: int64(0)}, - {ID: "50", Type: "ARMCTRL-level", Device: "52 Edge DMA IRQ", CPU: 3, Count: int64(0)}, - {ID: "51", Type: "ARMCTRL-level", Device: "53 Edge DMA IRQ", CPU: 0, Count: int64(208)}, - {ID: "51", Type: "ARMCTRL-level", Device: "53 Edge DMA IRQ", CPU: 1, Count: int64(0)}, - {ID: "51", Type: "ARMCTRL-level", Device: "53 Edge DMA IRQ", CPU: 2, Count: int64(0)}, - {ID: "51", Type: "ARMCTRL-level", Device: "53 Edge DMA IRQ", CPU: 3, Count: int64(0)}, - {ID: "54", Type: "ARMCTRL-level", Device: "56 Edge DMA IRQ", CPU: 0, Count: int64(883002)}, - {ID: "54", Type: "ARMCTRL-level", Device: "56 Edge DMA IRQ", CPU: 1, Count: int64(0)}, - {ID: "54", Type: "ARMCTRL-level", Device: "56 Edge DMA IRQ", CPU: 2, Count: int64(0)}, - {ID: "54", Type: "ARMCTRL-level", Device: "56 Edge DMA IRQ", CPU: 3, Count: int64(0)}, - {ID: "59", Type: "ARMCTRL-level", Device: "61 Edge bcm2835-auxirq", CPU: 0, Count: int64(0)}, - {ID: "59", Type: "ARMCTRL-level", Device: "61 Edge bcm2835-auxirq", CPU: 1, Count: int64(0)}, - {ID: "59", Type: "ARMCTRL-level", Device: "61 Edge bcm2835-auxirq", CPU: 2, Count: int64(0)}, - {ID: "59", Type: "ARMCTRL-level", Device: "61 Edge bcm2835-auxirq", CPU: 3, Count: int64(0)}, - {ID: "62", Type: "ARMCTRL-level", Device: "64 Edge dwc_otg, dwc_otg_pcd, dwc_otg_hcd:usb1", CPU: 0, Count: int64(521451447)}, - {ID: "62", Type: "ARMCTRL-level", Device: "64 Edge dwc_otg, dwc_otg_pcd, dwc_otg_hcd:usb1", CPU: 1, Count: int64(0)}, - {ID: "62", Type: "ARMCTRL-level", Device: "64 Edge dwc_otg, dwc_otg_pcd, dwc_otg_hcd:usb1", CPU: 2, Count: int64(0)}, - {ID: "62", Type: "ARMCTRL-level", Device: "64 Edge dwc_otg, dwc_otg_pcd, dwc_otg_hcd:usb1", CPU: 3, Count: int64(0)}, - {ID: "86", Type: "ARMCTRL-level", Device: "88 Edge mmc0", CPU: 0, Count: int64(857597)}, - {ID: "86", Type: "ARMCTRL-level", Device: "88 Edge mmc0", CPU: 1, Count: int64(0)}, - {ID: "86", Type: "ARMCTRL-level", Device: "88 Edge mmc0", CPU: 2, Count: int64(0)}, - {ID: "86", Type: "ARMCTRL-level", Device: "88 Edge mmc0", CPU: 3, Count: int64(0)}, - {ID: "87", Type: "ARMCTRL-level", Device: "89 Edge uart-pl011", CPU: 0, Count: int64(4938)}, - {ID: "87", Type: "ARMCTRL-level", Device: "89 Edge uart-pl011", CPU: 1, Count: int64(0)}, - {ID: "87", Type: "ARMCTRL-level", Device: "89 Edge uart-pl011", CPU: 2, Count: int64(0)}, - {ID: "87", Type: "ARMCTRL-level", Device: "89 Edge uart-pl011", CPU: 3, Count: int64(0)}, - {ID: "92", Type: "ARMCTRL-level", Device: "94 Edge mmc1", CPU: 0, Count: int64(5669)}, - {ID: "92", Type: "ARMCTRL-level", Device: "94 Edge mmc1", CPU: 1, Count: int64(0)}, - {ID: "92", Type: "ARMCTRL-level", Device: "94 Edge mmc1", CPU: 2, Count: int64(0)}, - {ID: "92", Type: "ARMCTRL-level", Device: "94 Edge mmc1", CPU: 3, Count: int64(0)}, - {ID: "IPI0", Type: "CPU wakeup interrupts", CPU: 0, Count: int64(0)}, - {ID: "IPI0", Type: "CPU wakeup interrupts", CPU: 1, Count: int64(0)}, - {ID: "IPI0", Type: "CPU wakeup interrupts", CPU: 2, Count: int64(0)}, - {ID: "IPI0", Type: "CPU wakeup interrupts", CPU: 3, Count: int64(0)}, - {ID: "IPI1", Type: "Timer broadcast interrupts", CPU: 0, Count: int64(0)}, - {ID: "IPI1", Type: "Timer broadcast interrupts", CPU: 1, Count: int64(0)}, - {ID: "IPI1", Type: "Timer broadcast interrupts", CPU: 2, Count: int64(0)}, - {ID: "IPI1", Type: "Timer broadcast interrupts", CPU: 3, Count: int64(0)}, - {ID: "IPI2", Type: "Rescheduling interrupts", CPU: 0, Count: int64(23564958)}, - {ID: "IPI2", Type: "Rescheduling interrupts", CPU: 1, Count: int64(23464876)}, - {ID: "IPI2", Type: "Rescheduling interrupts", CPU: 2, Count: int64(23531165)}, - {ID: "IPI2", Type: "Rescheduling interrupts", CPU: 3, Count: int64(23040826)}, - {ID: "IPI3", Type: "Function call interrupts", CPU: 0, Count: int64(148438)}, - {ID: "IPI3", Type: "Function call interrupts", CPU: 1, Count: int64(639704)}, - {ID: "IPI3", Type: "Function call interrupts", CPU: 2, Count: int64(644266)}, - {ID: "IPI3", Type: "Function call interrupts", CPU: 3, Count: int64(588150)}, - {ID: "IPI4", Type: "CPU stop interrupts", CPU: 0, Count: int64(0)}, - {ID: "IPI4", Type: "CPU stop interrupts", CPU: 1, Count: int64(0)}, - {ID: "IPI4", Type: "CPU stop interrupts", CPU: 2, Count: int64(0)}, - {ID: "IPI4", Type: "CPU stop interrupts", CPU: 3, Count: int64(0)}, - {ID: "IPI5", Type: "IRQ work interrupts", CPU: 0, Count: int64(4348149)}, - {ID: "IPI5", Type: "IRQ work interrupts", CPU: 1, Count: int64(1843985)}, - {ID: "IPI5", Type: "IRQ work interrupts", CPU: 2, Count: int64(3819457)}, - {ID: "IPI5", Type: "IRQ work interrupts", CPU: 3, Count: int64(1822877)}, - {ID: "IPI6", Type: "completion interrupts", CPU: 0, Count: int64(0)}, - {ID: "IPI6", Type: "completion interrupts", CPU: 1, Count: int64(0)}, - {ID: "IPI6", Type: "completion interrupts", CPU: 2, Count: int64(0)}, - {ID: "IPI6", Type: "completion interrupts", CPU: 3, Count: int64(0)}, +func TestCpusAsFieldsSoftIrqs(t *testing.T) { + acc, irqs := setup(t, softIrqsString, false) + reportMetrics("soft_interrupts", irqs, acc, false) + + for _, irq := range softIrqsExpectedArgs { + expectIrqFields(acc, t, "soft_interrupts", irq) } - got, err := parseInterrupts(f) - require.Equal(t, nil, err) - require.NotEqual(t, 0, len(got)) - require.Equal(t, len(got), len(parsed)) - for i := 0; i < len(parsed); i++ { - assert.Equal(t, parsed[i], got[i]) +} + +// ===================================================================================== +// HW interrupts, tests #4470 +// ===================================================================================== + +const hwIrqsString = ` CPU0 CPU1 CPU2 CPU3 + 16: 0 0 0 0 bcm2836-timer 0 Edge arch_timer + 17: 127224250 118424219 127224437 117885416 bcm2836-timer 1 Edge arch_timer + 21: 0 0 0 0 bcm2836-pmu 9 Edge arm-pmu + 23: 1549514 0 0 0 ARMCTRL-level 1 Edge 3f00b880.mailbox + 24: 2 0 0 0 ARMCTRL-level 2 Edge VCHIQ doorbell + 46: 0 0 0 0 ARMCTRL-level 48 Edge bcm2708_fb dma + 48: 0 0 0 0 ARMCTRL-level 50 Edge DMA IRQ + 50: 0 0 0 0 ARMCTRL-level 52 Edge DMA IRQ + 51: 208 0 0 0 ARMCTRL-level 53 Edge DMA IRQ + 54: 883002 0 0 0 ARMCTRL-level 56 Edge DMA IRQ + 59: 0 0 0 0 ARMCTRL-level 61 Edge bcm2835-auxirq + 62: 521451447 0 0 0 ARMCTRL-level 64 Edge dwc_otg, dwc_otg_pcd, dwc_otg_hcd:usb1 + 86: 857597 0 0 0 ARMCTRL-level 88 Edge mmc0 + 87: 4938 0 0 0 ARMCTRL-level 89 Edge uart-pl011 + 92: 5669 0 0 0 ARMCTRL-level 94 Edge mmc1 + FIQ: usb_fiq + IPI0: 0 0 0 0 CPU wakeup interrupts + IPI1: 0 0 0 0 Timer broadcast interrupts + IPI2: 23564958 23464876 23531165 23040826 Rescheduling interrupts + IPI3: 148438 639704 644266 588150 Function call interrupts + IPI4: 0 0 0 0 CPU stop interrupts + IPI5: 4348149 1843985 3819457 1822877 IRQ work interrupts + IPI6: 0 0 0 0 completion interrupts` + +var hwIrqsExpectedArgs = []IRQ{ + {ID: "16", Type: "bcm2836-timer", Device: "0 Edge arch_timer", Cpus: []int64{0, 0, 0, 0}}, + {ID: "17", Type: "bcm2836-timer", Device: "1 Edge arch_timer", Cpus: []int64{127224250, 118424219, 127224437, 117885416}}, + {ID: "21", Type: "bcm2836-pmu", Device: "9 Edge arm-pmu", Cpus: []int64{0, 0, 0, 0}}, + {ID: "23", Type: "ARMCTRL-level", Device: "1 Edge 3f00b880.mailbox", Cpus: []int64{1549514, 0, 0, 0}}, + {ID: "24", Type: "ARMCTRL-level", Device: "2 Edge VCHIQ doorbell", Cpus: []int64{2, 0, 0, 0}}, + {ID: "46", Type: "ARMCTRL-level", Device: "48 Edge bcm2708_fb dma", Cpus: []int64{0, 0, 0, 0}}, + {ID: "48", Type: "ARMCTRL-level", Device: "50 Edge DMA IRQ", Cpus: []int64{0, 0, 0, 0}}, + {ID: "50", Type: "ARMCTRL-level", Device: "52 Edge DMA IRQ", Cpus: []int64{0, 0, 0, 0}}, + {ID: "51", Type: "ARMCTRL-level", Device: "53 Edge DMA IRQ", Cpus: []int64{208, 0, 0, 0}}, + {ID: "54", Type: "ARMCTRL-level", Device: "56 Edge DMA IRQ", Cpus: []int64{883002, 0, 0, 0}}, + {ID: "59", Type: "ARMCTRL-level", Device: "61 Edge bcm2835-auxirq", Cpus: []int64{0, 0, 0, 0}}, + {ID: "62", Type: "ARMCTRL-level", Device: "64 Edge dwc_otg, dwc_otg_pcd, dwc_otg_hcd:usb1", Cpus: []int64{521451447, 0, 0, 0}}, + {ID: "86", Type: "ARMCTRL-level", Device: "88 Edge mmc0", Cpus: []int64{857597, 0, 0, 0}}, + {ID: "87", Type: "ARMCTRL-level", Device: "89 Edge uart-pl011", Cpus: []int64{4938, 0, 0, 0}}, + {ID: "92", Type: "ARMCTRL-level", Device: "94 Edge mmc1", Cpus: []int64{5669, 0, 0, 0}}, + {ID: "IPI0", Type: "CPU wakeup interrupts", Cpus: []int64{0, 0, 0, 0}}, + {ID: "IPI1", Type: "Timer broadcast interrupts", Cpus: []int64{0, 0, 0, 0}}, + {ID: "IPI2", Type: "Rescheduling interrupts", Cpus: []int64{23564958, 23464876, 23531165, 23040826}}, + {ID: "IPI3", Type: "Function call interrupts", Cpus: []int64{148438, 639704, 644266, 588150}}, + {ID: "IPI4", Type: "CPU stop interrupts", Cpus: []int64{0, 0, 0, 0}}, + {ID: "IPI5", Type: "IRQ work interrupts", Cpus: []int64{4348149, 1843985, 3819457, 1822877}}, + {ID: "IPI6", Type: "completion interrupts", Cpus: []int64{0, 0, 0, 0}}, +} + +func TestCpusAsTagsHwIrqs(t *testing.T) { + acc, irqs := setup(t, hwIrqsString, true) + reportMetrics("interrupts", irqs, acc, true) + + for _, irq := range hwIrqsExpectedArgs { + expectIrqTags(acc, t, "interrupts", irq) + } +} + +func TestCpusAsFieldsHwIrqs(t *testing.T) { + acc, irqs := setup(t, hwIrqsString, false) + reportMetrics("interrupts", irqs, acc, false) + + for _, irq := range hwIrqsExpectedArgs { + expectIrqFields(acc, t, "interrupts", irq) } } From 2d4c8de077960137d4f29f73c78dc29e59e82376 Mon Sep 17 00:00:00 2001 From: Wojciech Kudla Date: Fri, 30 Nov 2018 21:19:34 +0000 Subject: [PATCH 3/4] Clean-ups, documentation corrections and switched tests to testutil.Accumulator (#4999) --- plugins/inputs/interrupts/README.md | 7 ++-- plugins/inputs/interrupts/interrupts.go | 16 +++---- plugins/inputs/interrupts/interrupts_test.go | 44 +++++++------------- 3 files changed, 25 insertions(+), 42 deletions(-) diff --git a/plugins/inputs/interrupts/README.md b/plugins/inputs/interrupts/README.md index afe2df2e13057..ed687b1008f3b 100644 --- a/plugins/inputs/interrupts/README.md +++ b/plugins/inputs/interrupts/README.md @@ -5,13 +5,12 @@ The interrupts plugin gathers metrics about IRQs from `/proc/interrupts` and `/p ### Configuration ``` [[inputs.interrupts]] + # To report cpus as tags instead of fields use cpus_as_tags + # cpu_as_tags = false + # ## To filter which IRQs to collect, make use of tagpass / tagdrop, i.e. # [inputs.interrupts.tagdrop] # irq = [ "NET_RX", "TASKLET" ] - # - # To report cpus as tags instead of fields use cpus_as_tags - # cpus_as_tags = false - ``` ### Measurements diff --git a/plugins/inputs/interrupts/interrupts.go b/plugins/inputs/interrupts/interrupts.go index 5b3e0c89b6a8f..a366461688e55 100644 --- a/plugins/inputs/interrupts/interrupts.go +++ b/plugins/inputs/interrupts/interrupts.go @@ -13,11 +13,7 @@ import ( ) type Interrupts struct { - CpusAsTags bool -} - -func NewInterrupts() *Interrupts { - return &Interrupts{false} + CpuAsTags bool } type IRQ struct { @@ -33,12 +29,12 @@ func NewIRQ(id string) *IRQ { } const sampleConfig = ` + ## To report cpus as tags instead of fields use cpus_as_tags + # cpu_as_tags = false + # ## To filter which IRQs to collect, make use of tagpass / tagdrop, i.e. # [inputs.interrupts.tagdrop] - # irq = [ "NET_RX", "TASKLET" ] - # - # To report cpus as tags instead of fields use cpus_as_tags - # cpus_as_tags = false + # irq = [ "NET_RX", "TASKLET" ] ` func (s *Interrupts) Description() string { @@ -120,7 +116,7 @@ func (s *Interrupts) Gather(acc telegraf.Accumulator) error { acc.AddError(fmt.Errorf("Parsing %s: %s", file, err)) continue } - reportMetrics(measurement, irqs, acc, s.CpusAsTags) + reportMetrics(measurement, irqs, acc, s.CpuAsTags) } return nil } diff --git a/plugins/inputs/interrupts/interrupts_test.go b/plugins/inputs/interrupts/interrupts_test.go index 3df6ad390e8c8..2579d926d20c6 100644 --- a/plugins/inputs/interrupts/interrupts_test.go +++ b/plugins/inputs/interrupts/interrupts_test.go @@ -4,10 +4,8 @@ import ( "bytes" "fmt" "testing" - "time" - "github.com/influxdata/telegraf" - "github.com/stretchr/testify/mock" + "github.com/influxdata/telegraf/testutil" "github.com/stretchr/testify/require" ) @@ -15,22 +13,13 @@ import ( // Setup and helper functions // ===================================================================================== -type MockAccumulator struct { - telegraf.Accumulator - mock.Mock -} - -func (acc *MockAccumulator) AddFields(measurement string, fields map[string]interface{}, tags map[string]string, t ...time.Time) { - acc.Called(measurement, fields, tags) -} - -func expectIrqTags(m *MockAccumulator, t *testing.T, measurement string, irq IRQ) { +func expectCpuAsTags(m *testutil.Accumulator, t *testing.T, measurement string, irq IRQ) { for idx, value := range irq.Cpus { - m.AssertCalled(t, "AddFields", measurement, map[string]interface{}{"count": value}, map[string]string{"irq": irq.ID, "type": irq.Type, "device": irq.Device, "cpu": fmt.Sprintf("cpu%d", idx)}) + m.AssertContainsTaggedFields(t, measurement, map[string]interface{}{"count": value}, map[string]string{"irq": irq.ID, "type": irq.Type, "device": irq.Device, "cpu": fmt.Sprintf("cpu%d", idx)}) } } -func expectIrqFields(m *MockAccumulator, t *testing.T, measurement string, irq IRQ) { +func expectCpuAsFields(m *testutil.Accumulator, t *testing.T, measurement string, irq IRQ) { fields := map[string]interface{}{} total := int64(0) for idx, count := range irq.Cpus { @@ -39,18 +28,17 @@ func expectIrqFields(m *MockAccumulator, t *testing.T, measurement string, irq I } fields["total"] = total - m.AssertCalled(t, "AddFields", measurement, fields, map[string]string{"irq": irq.ID, "type": irq.Type, "device": irq.Device}) + m.AssertContainsTaggedFields(t, measurement, fields, map[string]string{"irq": irq.ID, "type": irq.Type, "device": irq.Device}) } -func setup(t *testing.T, irqString string, cpusAsTags bool) (*MockAccumulator, []IRQ) { +func setup(t *testing.T, irqString string, cpuAsTags bool) (*testutil.Accumulator, []IRQ) { f := bytes.NewBufferString(irqString) irqs, err := parseInterrupts(f) require.Equal(t, nil, err) require.NotEqual(t, 0, len(irqs)) - acc := new(MockAccumulator) - acc.On("AddFields", mock.Anything, mock.Anything, mock.Anything).Return(nil) - reportMetrics("soft_interrupts", irqs, acc, cpusAsTags) + acc := new(testutil.Accumulator) + reportMetrics("soft_interrupts", irqs, acc, cpuAsTags) return acc, irqs } @@ -77,21 +65,21 @@ var softIrqsExpectedArgs = []IRQ{ {ID: "TASKLET", Cpus: []int64{205, 0}}, } -func TestCpusAsTagsSoftIrqs(t *testing.T) { +func TestCpuAsTagsSoftIrqs(t *testing.T) { acc, irqs := setup(t, softIrqsString, true) reportMetrics("soft_interrupts", irqs, acc, true) for _, irq := range softIrqsExpectedArgs { - expectIrqTags(acc, t, "soft_interrupts", irq) + expectCpuAsTags(acc, t, "soft_interrupts", irq) } } -func TestCpusAsFieldsSoftIrqs(t *testing.T) { +func TestCpuAsFieldsSoftIrqs(t *testing.T) { acc, irqs := setup(t, softIrqsString, false) reportMetrics("soft_interrupts", irqs, acc, false) for _, irq := range softIrqsExpectedArgs { - expectIrqFields(acc, t, "soft_interrupts", irq) + expectCpuAsFields(acc, t, "soft_interrupts", irq) } } @@ -149,20 +137,20 @@ var hwIrqsExpectedArgs = []IRQ{ {ID: "IPI6", Type: "completion interrupts", Cpus: []int64{0, 0, 0, 0}}, } -func TestCpusAsTagsHwIrqs(t *testing.T) { +func TestCpuAsTagsHwIrqs(t *testing.T) { acc, irqs := setup(t, hwIrqsString, true) reportMetrics("interrupts", irqs, acc, true) for _, irq := range hwIrqsExpectedArgs { - expectIrqTags(acc, t, "interrupts", irq) + expectCpuAsTags(acc, t, "interrupts", irq) } } -func TestCpusAsFieldsHwIrqs(t *testing.T) { +func TestCpuAsFieldsHwIrqs(t *testing.T) { acc, irqs := setup(t, hwIrqsString, false) reportMetrics("interrupts", irqs, acc, false) for _, irq := range hwIrqsExpectedArgs { - expectIrqFields(acc, t, "interrupts", irq) + expectCpuAsFields(acc, t, "interrupts", irq) } } From 50b5133982ccc2937f2238fcb0db456d16daa21d Mon Sep 17 00:00:00 2001 From: Wojciech Kudla Date: Fri, 30 Nov 2018 21:36:33 +0000 Subject: [PATCH 4/4] Fixed typos (#4999) --- plugins/inputs/interrupts/README.md | 6 +++--- plugins/inputs/interrupts/interrupts.go | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/inputs/interrupts/README.md b/plugins/inputs/interrupts/README.md index ed687b1008f3b..188070f745c65 100644 --- a/plugins/inputs/interrupts/README.md +++ b/plugins/inputs/interrupts/README.md @@ -5,7 +5,7 @@ The interrupts plugin gathers metrics about IRQs from `/proc/interrupts` and `/p ### Configuration ``` [[inputs.interrupts]] - # To report cpus as tags instead of fields use cpus_as_tags + # To report cpus as tags instead of fields use cpu_as_tags # cpu_as_tags = false # ## To filter which IRQs to collect, make use of tagpass / tagdrop, i.e. @@ -19,10 +19,10 @@ There are two measurements reported by this plugin. - `soft_interrupts` gathers metrics from the `/proc/softirqs` file ### Fields -For cpus_as_tags=false (default): +For cpu_as_tags=false (default): - CPUx: the amount of interrupts for the IRQ handled by the CPU - Total: sum of interrupts for the IRS for all CPUs -For cpus_as_tags=true (): +For cpu_as_tags=true (): - Count: the amount of interrupts for the IRQ handled by CPU described in CPU tag ### Tags diff --git a/plugins/inputs/interrupts/interrupts.go b/plugins/inputs/interrupts/interrupts.go index a366461688e55..142dc34ec7d06 100644 --- a/plugins/inputs/interrupts/interrupts.go +++ b/plugins/inputs/interrupts/interrupts.go @@ -29,7 +29,7 @@ func NewIRQ(id string) *IRQ { } const sampleConfig = ` - ## To report cpus as tags instead of fields use cpus_as_tags + ## To report cpus as tags instead of fields use cpu_as_tags # cpu_as_tags = false # ## To filter which IRQs to collect, make use of tagpass / tagdrop, i.e.