forked from influxdata/telegraf
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add wireless input plugin (influxdata#3847)
- Loading branch information
1 parent
d0ae1e4
commit 54ce428
Showing
5 changed files
with
259 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
// +build !linux | ||
|
||
package wireless |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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{} | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) | ||
} |