-
Notifications
You must be signed in to change notification settings - Fork 5.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
reviving code from #1447 to a new branch
- Loading branch information
Russ Savage
committed
Feb 8, 2018
1 parent
32dd1b3
commit af5017d
Showing
6 changed files
with
309 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
# Hugepages Input Plugin | ||
|
||
The hugepages plugin gathers hugepages metrics including per NUMA node | ||
|
||
### Configuration: | ||
|
||
```toml | ||
# Description | ||
[[inputs.hugepages]] | ||
## Path to a NUMA nodes | ||
# numa_node_path = "/sys/devices/system/node" | ||
## Path to a meminfo file | ||
# meminfo_path = "/proc/meminfo" | ||
``` | ||
|
||
### Measurements & Fields: | ||
|
||
- hugepages | ||
- free (int, kB) | ||
- nr (int, kB) | ||
- HugePages_Total (int, kB) | ||
- HugePages_Free (int, kB) | ||
|
||
### Tags: | ||
|
||
- hugepages has the following tags: | ||
- node | ||
|
||
### Example Output: | ||
|
||
``` | ||
$ ./telegraf -config telegraf.conf -input-filter hugepages -test | ||
> hugepages,host=maxpc,node=node0 free=0i,nr=0i 1467618621000000000 | ||
> hugepages,host=maxpc,name=meminfo HugePages_Free=0i,HugePages_Total=0i 1467618621000000000 | ||
``` |
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,184 @@ | ||
package system | ||
|
||
import ( | ||
"bytes" | ||
"fmt" | ||
"io/ioutil" | ||
"strconv" | ||
"strings" | ||
|
||
"github.com/influxdata/telegraf" | ||
"github.com/influxdata/telegraf/plugins/inputs" | ||
) | ||
|
||
var ( | ||
newlineByte = []byte("\n") | ||
colonByte = []byte(":") | ||
kbPrecisionByte = []byte("kB") | ||
) | ||
|
||
// default file paths | ||
const ( | ||
// the path where statistics are kept per NUMA nodes | ||
NUMA_NODE_PATH = "/sys/devices/system/node" | ||
// the path to the meminfo file which is produced by kernel | ||
MEMINFO_PATH = "/proc/meminfo" | ||
|
||
// hugepages stat field names on meminfo file | ||
HUGE_PAGES_TOTAL = "HugePages_Total" | ||
HUGE_PAGES_FREE = "HugePages_Free" | ||
) | ||
|
||
var hugepagesSampleConfig = ` | ||
## Path to a NUMA nodes | ||
# numa_node_path = "/sys/devices/system/node" | ||
## Path to a meminfo file | ||
# meminfo_path = "/proc/meminfo" | ||
` | ||
|
||
// Mem is the | ||
type Hugepages struct { | ||
NUMANodePath string `toml:"numa_node_path"` | ||
MeminfoPath string `toml:"meminfo_path"` | ||
} | ||
|
||
func (mem *Hugepages) Description() string { | ||
return "Collects hugepages metrics from kernel and per NUMA node" | ||
} | ||
|
||
func (mem *Hugepages) SampleConfig() string { | ||
return hugepagesSampleConfig | ||
} | ||
|
||
func (mem *Hugepages) Gather(acc telegraf.Accumulator) error { | ||
mem.loadPaths() | ||
err := mem.GatherStatsPerNode(acc) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
err = mem.GatherStatsFromMeminfo(acc) | ||
if err != nil { | ||
return err | ||
} | ||
return nil | ||
} | ||
|
||
// GatherHugepagesStatsPerNode collects hugepages stats per NUMA nodes | ||
func (mem *Hugepages) GatherStatsPerNode(acc telegraf.Accumulator) error { | ||
numaNodeMetrics, err := statsPerNUMA(mem.NUMANodePath) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
for k, v := range numaNodeMetrics { | ||
metrics := make(map[string]interface{}) | ||
tags := map[string]string{ | ||
"node": k, | ||
} | ||
metrics["free"] = v.Free | ||
metrics["nr"] = v.NR | ||
acc.AddFields("hugepages", metrics, tags) | ||
} | ||
return nil | ||
} | ||
|
||
// GatherHugepagesStatsFromMeminfo collects hugepages statistics from meminfo file | ||
func (mem *Hugepages) GatherStatsFromMeminfo(acc telegraf.Accumulator) error { | ||
tags := map[string]string{ | ||
"name": "meminfo", | ||
} | ||
metrics := make(map[string]interface{}) | ||
meminfoMetrics, err := statsFromMeminfo(mem.MeminfoPath) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
for k, v := range meminfoMetrics { | ||
metrics[k] = v | ||
} | ||
acc.AddFields("hugepages", metrics, tags) | ||
return nil | ||
} | ||
|
||
type HugepagesNUMAStats struct { | ||
Free int | ||
NR int | ||
} | ||
|
||
// statsPerNUMA gathers hugepages statistics from each NUMA node | ||
func statsPerNUMA(path string) (map[string]HugepagesNUMAStats, error) { | ||
var hugepagesStats = make(map[string]HugepagesNUMAStats) | ||
dirs, err := ioutil.ReadDir(path) | ||
if err != nil { | ||
return hugepagesStats, err | ||
} | ||
|
||
for _, d := range dirs { | ||
if !(d.IsDir() && strings.HasPrefix(d.Name(), "node")) { | ||
continue | ||
} | ||
|
||
hugepagesFree := fmt.Sprintf("%s/%s/hugepages/hugepages-2048kB/free_hugepages", path, d.Name()) | ||
hugepagesNR := fmt.Sprintf("%s/%s/hugepages/hugepages-2048kB/nr_hugepages", path, d.Name()) | ||
|
||
free, err := ioutil.ReadFile(hugepagesFree) | ||
if err != nil { | ||
return hugepagesStats, err | ||
} | ||
|
||
nr, err := ioutil.ReadFile(hugepagesNR) | ||
if err != nil { | ||
return hugepagesStats, err | ||
} | ||
|
||
f, _ := strconv.Atoi(string(bytes.TrimSuffix(free, newlineByte))) | ||
n, _ := strconv.Atoi(string(bytes.TrimSuffix(nr, newlineByte))) | ||
|
||
hugepagesStats[d.Name()] = HugepagesNUMAStats{Free: f, NR: n} | ||
|
||
} | ||
return hugepagesStats, nil | ||
} | ||
|
||
// statsFromMeminfo gathers hugepages statistics from kernel | ||
func statsFromMeminfo(path string) (map[string]interface{}, error) { | ||
stats := map[string]interface{}{} | ||
meminfo, err := ioutil.ReadFile(path) | ||
if err != nil { | ||
return stats, err | ||
} | ||
lines := bytes.Split(meminfo, newlineByte) | ||
for _, l := range lines { | ||
if bytes.Contains(l, kbPrecisionByte) { | ||
continue | ||
} | ||
fields := bytes.Fields(l) | ||
if len(fields) < 2 { | ||
continue | ||
} | ||
fieldName := string(bytes.TrimSuffix(fields[0], colonByte)) | ||
if fieldName == HUGE_PAGES_TOTAL || fieldName == HUGE_PAGES_FREE { | ||
val, _ := strconv.Atoi(string(fields[1])) | ||
stats[fieldName] = val | ||
} | ||
} | ||
return stats, nil | ||
} | ||
|
||
// loadPaths can be used to read paths firstly from config | ||
// if it is empty then try read from env variables | ||
func (mem *Hugepages) loadPaths() { | ||
if mem.NUMANodePath == "" { | ||
mem.NUMANodePath = NUMA_NODE_PATH | ||
} | ||
if mem.MeminfoPath == "" { | ||
mem.MeminfoPath = MEMINFO_PATH | ||
} | ||
} | ||
|
||
func init() { | ||
inputs.Add("hugepages", func() telegraf.Input { | ||
return &Hugepages{} | ||
}) | ||
} |
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,43 @@ | ||
package system | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/influxdata/telegraf/testutil" | ||
) | ||
|
||
var hugepages = Hugepages{ | ||
NUMANodePath: "./testdata/node", | ||
MeminfoPath: "./testdata/meminfo", | ||
} | ||
|
||
func init() { | ||
hugepages.loadPaths() | ||
} | ||
|
||
func TestHugepagesStatsFromMeminfo(t *testing.T) { | ||
acc := &testutil.Accumulator{} | ||
err := hugepages.GatherStatsFromMeminfo(acc) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
fields := map[string]interface{}{ | ||
"HugePages_Total": int(666), | ||
"HugePages_Free": int(999), | ||
} | ||
acc.AssertContainsFields(t, "hugepages", fields) | ||
} | ||
|
||
func TestHugepagesStatsPerNode(t *testing.T) { | ||
acc := &testutil.Accumulator{} | ||
err := hugepages.GatherStatsPerNode(acc) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
fields := map[string]interface{}{ | ||
"free": int(123), | ||
"nr": int(456), | ||
} | ||
acc.AssertContainsFields(t, "hugepages", fields) | ||
} |
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,45 @@ | ||
MemTotal: 5961204 kB | ||
MemFree: 5201764 kB | ||
MemAvailable: 5761624 kB | ||
Buffers: 120248 kB | ||
Cached: 419660 kB | ||
SwapCached: 0 kB | ||
Active: 370656 kB | ||
Inactive: 247364 kB | ||
Active(anon): 79032 kB | ||
Inactive(anon): 552 kB | ||
Active(file): 291624 kB | ||
Inactive(file): 246812 kB | ||
Unevictable: 0 kB | ||
Mlocked: 0 kB | ||
SwapTotal: 0 kB | ||
SwapFree: 0 kB | ||
Dirty: 4 kB | ||
Writeback: 0 kB | ||
AnonPages: 78164 kB | ||
Mapped: 114164 kB | ||
Shmem: 1452 kB | ||
Slab: 77180 kB | ||
SReclaimable: 57676 kB | ||
SUnreclaim: 19504 kB | ||
KernelStack: 2832 kB | ||
PageTables: 8692 kB | ||
NFS_Unstable: 0 kB | ||
Bounce: 0 kB | ||
WritebackTmp: 0 kB | ||
CommitLimit: 2980600 kB | ||
Committed_AS: 555492 kB | ||
VmallocTotal: 34359738367 kB | ||
VmallocUsed: 0 kB | ||
VmallocChunk: 0 kB | ||
HardwareCorrupted: 0 kB | ||
AnonHugePages: 0 kB | ||
CmaTotal: 0 kB | ||
CmaFree: 0 kB | ||
HugePages_Total: 666 | ||
HugePages_Free: 999 | ||
HugePages_Rsvd: 0 | ||
HugePages_Surp: 0 | ||
Hugepagesize: 2048 kB | ||
DirectMap4k: 84224 kB | ||
DirectMap2M: 6055936 kB |
1 change: 1 addition & 0 deletions
1
plugins/inputs/system/testdata/node/node0/hugepages/hugepages-2048kB/free_hugepages
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 @@ | ||
123 |
1 change: 1 addition & 0 deletions
1
plugins/inputs/system/testdata/node/node0/hugepages/hugepages-2048kB/nr_hugepages
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 @@ | ||
456 |