Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch CPU from field to tag in Interrupts input plugin (#4999) #5024

Merged
merged 4 commits into from
Nov 30, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion plugins/inputs/interrupts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
bitcharmer marked this conversation as resolved.
Show resolved Hide resolved

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i am using telegraf version 1.9.2 and this is not working.
Error parsing file.conf, line 76: field corresponding to cpu_as_tag' is not defined in *interrupts.Interrupts'

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need at least version 1.10. We try to mark the milestone a feature will be released in on the pull request, you should be able to see it on the right sidebar.


```

### Measurements
Expand All @@ -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

```
78 changes: 51 additions & 27 deletions plugins/inputs/interrupts/interrupts.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,33 @@ import (
"github.com/influxdata/telegraf/plugins/inputs"
)

type Interrupts struct{}
type Interrupts struct {
CpusAsTags bool
}

func NewInterrupts() *Interrupts {
bitcharmer marked this conversation as resolved.
Show resolved Hide resolved
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
bitcharmer marked this conversation as resolved.
Show resolved Hide resolved
`

func (s *Interrupts) Description() string {
Expand Down Expand Up @@ -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())
Expand All @@ -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
}

Expand All @@ -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() {
Expand Down
Loading