Add wireless input plugin (#3847)
This commit is contained in:
parent
c304dd98bf
commit
b24e03b597
|
@ -135,6 +135,7 @@ import (
|
|||
_ "github.com/influxdata/telegraf/plugins/inputs/webhooks"
|
||||
_ "github.com/influxdata/telegraf/plugins/inputs/win_perf_counters"
|
||||
_ "github.com/influxdata/telegraf/plugins/inputs/win_services"
|
||||
_ "github.com/influxdata/telegraf/plugins/inputs/wireless"
|
||||
_ "github.com/influxdata/telegraf/plugins/inputs/x509_cert"
|
||||
_ "github.com/influxdata/telegraf/plugins/inputs/zfs"
|
||||
_ "github.com/influxdata/telegraf/plugins/inputs/zipkin"
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
# Wireless Input Plugin
|
||||
|
||||
The wireless plugin gathers metrics about wireless link quality by reading the `/proc/net/wireless` file. This plugin currently supports linux only.
|
||||
|
||||
### Configuration:
|
||||
|
||||
```toml
|
||||
# Monitor wifi signal strength and quality
|
||||
[[inputs.wireless]]
|
||||
## Sets 'proc' directory path
|
||||
## If not specified, then default is /proc
|
||||
# host_proc = "/proc"
|
||||
```
|
||||
|
||||
### Metrics:
|
||||
|
||||
- metric
|
||||
- tags:
|
||||
- interface (wireless interface)
|
||||
- fields:
|
||||
- status (int64, gauge) - Its current state. This is a device dependent information
|
||||
- link (int64, percentage, gauge) - general quality of the reception
|
||||
- level (int64, dBm, gauge) - signal strength at the receiver
|
||||
- noise (int64, dBm, gauge) - silence level (no packet) at the receiver
|
||||
- nwid (int64, packets, counter) - number of discarded packets due to invalid network id
|
||||
- crypt (int64, packets, counter) - number of packet unable to decrypt
|
||||
- frag (int64, packets, counter) - fragmented packets
|
||||
- retry (int64, packets, counter) - cumulative retry counts
|
||||
- misc (int64, packets, counter) - dropped for un-specified reason
|
||||
- missed_beacon (int64, packets, counter) - missed beacon packets
|
||||
|
||||
### Example Output:
|
||||
|
||||
This section shows example output in Line Protocol format.
|
||||
|
||||
```
|
||||
wireless,host=example.localdomain,interface=wlan0 misc=0i,frag=0i,link=60i,level=-50i,noise=-256i,nwid=0i,crypt=0i,retry=1525i,missed_beacon=0i,status=0i 1519843022000000000
|
||||
```
|
|
@ -0,0 +1,3 @@
|
|||
// +build !linux
|
||||
|
||||
package wireless
|
|
@ -0,0 +1,165 @@
|
|||
// +build linux
|
||||
|
||||
package wireless
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/plugins/inputs"
|
||||
)
|
||||
|
||||
// default host proc path
|
||||
const defaultHostProc = "/proc"
|
||||
|
||||
// env host proc variable name
|
||||
const envProc = "HOST_PROC"
|
||||
|
||||
// length of wireless interface fields
|
||||
const interfaceFieldLength = 10
|
||||
|
||||
var newLineByte = []byte("\n")
|
||||
|
||||
type wirelessInterface struct {
|
||||
Interface string
|
||||
Status int64
|
||||
Link int64
|
||||
Level int64
|
||||
Noise int64
|
||||
Nwid int64
|
||||
Crypt int64
|
||||
Frag int64
|
||||
Retry int64
|
||||
Misc int64
|
||||
Beacon int64
|
||||
}
|
||||
|
||||
// Wireless is used to store configuration values.
|
||||
type Wireless struct {
|
||||
HostProc string `toml:"host_proc"`
|
||||
}
|
||||
|
||||
var sampleConfig = `
|
||||
## Sets 'proc' directory path
|
||||
## If not specified, then default is /proc
|
||||
# host_proc = "/proc"
|
||||
`
|
||||
|
||||
// Description returns information about the plugin.
|
||||
func (w *Wireless) Description() string {
|
||||
return "Monitor wifi signal strength and quality"
|
||||
}
|
||||
|
||||
// SampleConfig displays configuration instructions.
|
||||
func (w *Wireless) SampleConfig() string {
|
||||
return sampleConfig
|
||||
}
|
||||
|
||||
// Gather collects the wireless information.
|
||||
func (w *Wireless) Gather(acc telegraf.Accumulator) error {
|
||||
// load proc path, get default value if config value and env variable are empty
|
||||
w.loadPath()
|
||||
|
||||
wirelessPath := path.Join(w.HostProc, "net", "wireless")
|
||||
table, err := ioutil.ReadFile(wirelessPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
interfaces, err := loadWirelessTable(table)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, w := range interfaces {
|
||||
tags := map[string]string{
|
||||
"interface": w.Interface,
|
||||
}
|
||||
fieldsG := map[string]interface{}{
|
||||
"status": w.Status,
|
||||
"link": w.Link,
|
||||
"level": w.Level,
|
||||
"noise": w.Noise,
|
||||
}
|
||||
fieldsC := map[string]interface{}{
|
||||
"nwid": w.Nwid,
|
||||
"crypt": w.Crypt,
|
||||
"frag": w.Frag,
|
||||
"retry": w.Retry,
|
||||
"misc": w.Misc,
|
||||
"beacon": w.Beacon,
|
||||
}
|
||||
acc.AddGauge("wireless", fieldsG, tags)
|
||||
acc.AddCounter("wireless", fieldsC, tags)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func loadWirelessTable(table []byte) ([]*wirelessInterface, error) {
|
||||
var w []*wirelessInterface
|
||||
lines := bytes.Split(table, newLineByte)
|
||||
|
||||
// iterate over interfaces
|
||||
for i := 2; i < len(lines); i = i + 1 {
|
||||
if len(lines[i]) == 0 {
|
||||
continue
|
||||
}
|
||||
values := make([]int64, 0, interfaceFieldLength)
|
||||
fields := strings.Fields(string(lines[i]))
|
||||
for j := 1; j < len(fields); j = j + 1 {
|
||||
v, err := strconv.ParseInt(strings.Trim(fields[j], "."), 10, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
values = append(values, v)
|
||||
}
|
||||
if len(values) != interfaceFieldLength {
|
||||
log.Printf("E! [input.wireless] invalid length of interface values")
|
||||
continue
|
||||
}
|
||||
w = append(w, &wirelessInterface{
|
||||
Interface: strings.Trim(fields[0], ":"),
|
||||
Status: values[0],
|
||||
Link: values[1],
|
||||
Level: values[2],
|
||||
Noise: values[3],
|
||||
Nwid: values[4],
|
||||
Crypt: values[5],
|
||||
Frag: values[6],
|
||||
Retry: values[7],
|
||||
Misc: values[8],
|
||||
Beacon: values[9],
|
||||
})
|
||||
}
|
||||
return w, nil
|
||||
}
|
||||
|
||||
// loadPath can be used to read path firstly from config
|
||||
// if it is empty then try read from env variable
|
||||
func (w *Wireless) loadPath() {
|
||||
if w.HostProc == "" {
|
||||
w.HostProc = proc(envProc, defaultHostProc)
|
||||
}
|
||||
}
|
||||
|
||||
// proc can be used to read file paths from env
|
||||
func proc(env, path string) string {
|
||||
// try to read full file path
|
||||
if p := os.Getenv(env); p != "" {
|
||||
return p
|
||||
}
|
||||
// return default path
|
||||
return path
|
||||
}
|
||||
|
||||
func init() {
|
||||
inputs.Add("wireless", func() telegraf.Input {
|
||||
return &Wireless{}
|
||||
})
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
// +build linux
|
||||
|
||||
package wireless
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var testInput = []byte(`Inter-| sta-| Quality | Discarded packets | Missed | WE
|
||||
face | tus | link level noise | nwid crypt frag retry misc | beacon | 22
|
||||
wlan0: 0000 60. -50. -256 0 0 0 1525 0 0
|
||||
wlan1: 0000 70. -39. -256 0 0 0 12096 191188 0`)
|
||||
|
||||
func TestLoadWirelessTable(t *testing.T) {
|
||||
expectedMetrics := []*wirelessInterface{
|
||||
&wirelessInterface{
|
||||
Interface: "wlan0",
|
||||
Status: int64(0000),
|
||||
Link: int64(60),
|
||||
Level: int64(-50),
|
||||
Noise: int64(-256),
|
||||
Nwid: int64(0),
|
||||
Crypt: int64(0),
|
||||
Frag: int64(0),
|
||||
Retry: int64(1525),
|
||||
Misc: int64(0),
|
||||
Beacon: int64(0),
|
||||
},
|
||||
&wirelessInterface{
|
||||
Interface: "wlan1",
|
||||
Status: int64(0000),
|
||||
Link: int64(70),
|
||||
Level: int64(-39),
|
||||
Noise: int64(-256),
|
||||
Nwid: int64(0),
|
||||
Crypt: int64(0),
|
||||
Frag: int64(0),
|
||||
Retry: int64(12096),
|
||||
Misc: int64(191188),
|
||||
Beacon: int64(0),
|
||||
},
|
||||
}
|
||||
metrics, err := loadWirelessTable(testInput)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
as := assert.New(t)
|
||||
as.Equal(metrics, expectedMetrics)
|
||||
}
|
Loading…
Reference in New Issue