Merge remote-tracking branch 'influxdata/master'

This commit is contained in:
Thomas Menard 2016-03-11 15:55:12 +01:00
commit 1bf03fb168
10 changed files with 394 additions and 40 deletions

View File

@ -1,4 +1,4 @@
## v0.10.5 [unreleased] ## v0.11.0 [unreleased]
### Release Notes ### Release Notes
@ -16,6 +16,7 @@
- [#776](https://github.com/influxdata/telegraf/pull/776): Add Zookeeper chroot option to kafka_consumer. Thanks @prune998! - [#776](https://github.com/influxdata/telegraf/pull/776): Add Zookeeper chroot option to kafka_consumer. Thanks @prune998!
- [#811](https://github.com/influxdata/telegraf/pull/811): Add processes plugin for classifying total procs on system. Thanks @titilambert! - [#811](https://github.com/influxdata/telegraf/pull/811): Add processes plugin for classifying total procs on system. Thanks @titilambert!
- [#235](https://github.com/influxdata/telegraf/issues/235): Add number of users to the `system` input plugin. - [#235](https://github.com/influxdata/telegraf/issues/235): Add number of users to the `system` input plugin.
- [#826](https://github.com/influxdata/telegraf/pull/826): "kernel" linux plugin for /proc/stat metrics (context switches, interrupts, etc.)
### Bugfixes ### Bugfixes
- [#748](https://github.com/influxdata/telegraf/issues/748): Fix sensor plugin split on ":" - [#748](https://github.com/influxdata/telegraf/issues/748): Fix sensor plugin split on ":"
@ -27,6 +28,7 @@
- [#708](https://github.com/influxdata/telegraf/issues/708): packaging: build ARM package - [#708](https://github.com/influxdata/telegraf/issues/708): packaging: build ARM package
- [#713](https://github.com/influxdata/telegraf/issues/713): packaging: insecure permissions error on log directory - [#713](https://github.com/influxdata/telegraf/issues/713): packaging: insecure permissions error on log directory
- [#816](https://github.com/influxdata/telegraf/issues/816): Fix phpfpm panic if fcgi endpoint unreachable. - [#816](https://github.com/influxdata/telegraf/issues/816): Fix phpfpm panic if fcgi endpoint unreachable.
- [#828](https://github.com/influxdata/telegraf/issues/828): fix net_response plugin overwriting host tag.
## v0.10.4.1 ## v0.10.4.1

View File

@ -215,6 +215,7 @@ Currently implemented sources:
* diskio * diskio
* swap * swap
* processes * processes
* kernel (/proc/stat)
Telegraf can also collect metrics via the following service plugins: Telegraf can also collect metrics via the following service plugins:

View File

@ -119,6 +119,10 @@
# Uncomment the following line if you do not need disk serial numbers. # Uncomment the following line if you do not need disk serial numbers.
# skip_serial_number = true # skip_serial_number = true
# Get kernel statistics from /proc/stat
[[inputs.kernel]]
# no configuration
# Read metrics about memory usage # Read metrics about memory usage
[[inputs.mem]] [[inputs.mem]]
# no configuration # no configuration

View File

@ -52,7 +52,7 @@ It can also check response text.
### Tags: ### Tags:
- All measurements have the following tags: - All measurements have the following tags:
- host - server
- port - port
- protocol - protocol
@ -60,7 +60,7 @@ It can also check response text.
``` ```
$ ./telegraf -config telegraf.conf -input-filter net_response -test $ ./telegraf -config telegraf.conf -input-filter net_response -test
net_response,host=127.0.0.1,port=22,protocol=tcp response_time=0.18070360500000002,string_found=true 1454785464182527094 net_response,server=192.168.2.2,port=22,protocol=tcp response_time=0.18070360500000002,string_found=true 1454785464182527094
net_response,host=127.0.0.1,port=2222,protocol=tcp response_time=1.090124776,string_found=false 1454784433658942325 net_response,server=192.168.2.2,port=2222,protocol=tcp response_time=1.090124776,string_found=false 1454784433658942325
``` ```

View File

@ -169,7 +169,7 @@ func (c *NetResponse) Gather(acc telegraf.Accumulator) error {
return errors.New("Bad port") return errors.New("Bad port")
} }
// Prepare data // Prepare data
tags := map[string]string{"host": host, "port": port} tags := map[string]string{"server": host, "port": port}
var fields map[string]interface{} var fields map[string]interface{}
// Gather data // Gather data
if c.Protocol == "tcp" { if c.Protocol == "tcp" {

View File

@ -69,7 +69,7 @@ func TestTCPOK1(t *testing.T) {
"string_found": true, "string_found": true,
"response_time": 1.0, "response_time": 1.0,
}, },
map[string]string{"host": "127.0.0.1", map[string]string{"server": "127.0.0.1",
"port": "2004", "port": "2004",
"protocol": "tcp", "protocol": "tcp",
}, },
@ -109,7 +109,7 @@ func TestTCPOK2(t *testing.T) {
"string_found": false, "string_found": false,
"response_time": 1.0, "response_time": 1.0,
}, },
map[string]string{"host": "127.0.0.1", map[string]string{"server": "127.0.0.1",
"port": "2004", "port": "2004",
"protocol": "tcp", "protocol": "tcp",
}, },
@ -164,7 +164,7 @@ func TestUDPOK1(t *testing.T) {
"string_found": true, "string_found": true,
"response_time": 1.0, "response_time": 1.0,
}, },
map[string]string{"host": "127.0.0.1", map[string]string{"server": "127.0.0.1",
"port": "2004", "port": "2004",
"protocol": "udp", "protocol": "udp",
}, },

View File

@ -23,6 +23,13 @@ type Snmp struct {
Table []Table Table []Table
Subtable []Subtable Subtable []Subtable
SnmptranslateFile string SnmptranslateFile string
nameToOid map[string]string
initNode Node
subTableMap map[string]Subtable
// TODO change as unexportable
//OidInstanceMapping map[string]map[string]string
} }
type Host struct { type Host struct {
@ -110,16 +117,7 @@ type Node struct {
subnodes map[string]Node subnodes map[string]Node
} }
var initNode = Node{ // TODO move this var to snmp struct
id: "1",
name: "",
subnodes: make(map[string]Node),
}
var SubTableMap = make(map[string]Subtable)
var NameToOid = make(map[string]string)
var OidInstanceMapping = make(map[string]map[string]string) var OidInstanceMapping = make(map[string]map[string]string)
var sampleConfig = ` var sampleConfig = `
@ -286,14 +284,24 @@ func findnodename(node Node, ids []string) (string, string) {
} }
func (s *Snmp) Gather(acc telegraf.Accumulator) error { func (s *Snmp) Gather(acc telegraf.Accumulator) error {
// TODO put this in cache on first run
// Create subtables mapping // Create subtables mapping
if len(SubTableMap) == 0 { if len(s.subTableMap) == 0 {
s.subTableMap = make(map[string]Subtable)
for _, sb := range s.Subtable { for _, sb := range s.Subtable {
SubTableMap[sb.Name] = sb s.subTableMap[sb.Name] = sb
} }
} }
// TODO put this in cache on first run
// Create oid tree // Create oid tree
if s.SnmptranslateFile != "" && len(initNode.subnodes) == 0 { if s.SnmptranslateFile != "" && len(s.initNode.subnodes) == 0 {
s.nameToOid = make(map[string]string)
s.initNode = Node{
id: "1",
name: "",
subnodes: make(map[string]Node),
}
data, err := ioutil.ReadFile(s.SnmptranslateFile) data, err := ioutil.ReadFile(s.SnmptranslateFile)
if err != nil { if err != nil {
log.Printf("Reading SNMPtranslate file error: %s", err) log.Printf("Reading SNMPtranslate file error: %s", err)
@ -305,8 +313,8 @@ func (s *Snmp) Gather(acc telegraf.Accumulator) error {
if oids[2] != "" { if oids[2] != "" {
oid_name := oids[1] oid_name := oids[1]
oid := oids[2] oid := oids[2]
fillnode(initNode, oid_name, strings.Split(string(oid), ".")) fillnode(s.initNode, oid_name, strings.Split(string(oid), "."))
NameToOid[oid_name] = oid s.nameToOid[oid_name] = oid
} }
} }
} }
@ -330,7 +338,7 @@ func (s *Snmp) Gather(acc telegraf.Accumulator) error {
// Get Easy GET oids // Get Easy GET oids
for _, oidstring := range host.GetOids { for _, oidstring := range host.GetOids {
oid := Data{} oid := Data{}
if val, ok := NameToOid[oidstring]; ok { if val, ok := s.nameToOid[oidstring]; ok {
// TODO should we add the 0 instance ? // TODO should we add the 0 instance ?
oid.Name = oidstring oid.Name = oidstring
oid.Oid = val oid.Oid = val
@ -351,7 +359,7 @@ func (s *Snmp) Gather(acc telegraf.Accumulator) error {
// Get GET oids // Get GET oids
for _, oid := range s.Get { for _, oid := range s.Get {
if oid.Name == oid_name { if oid.Name == oid_name {
if val, ok := NameToOid[oid.Oid]; ok { if val, ok := s.nameToOid[oid.Oid]; ok {
// TODO should we add the 0 instance ? // TODO should we add the 0 instance ?
if oid.Instance != "" { if oid.Instance != "" {
oid.rawOid = "." + val + "." + oid.Instance oid.rawOid = "." + val + "." + oid.Instance
@ -367,7 +375,7 @@ func (s *Snmp) Gather(acc telegraf.Accumulator) error {
// Get GETBULK oids // Get GETBULK oids
for _, oid := range s.Bulk { for _, oid := range s.Bulk {
if oid.Name == oid_name { if oid.Name == oid_name {
if val, ok := NameToOid[oid.Oid]; ok { if val, ok := s.nameToOid[oid.Oid]; ok {
oid.rawOid = "." + val oid.rawOid = "." + val
} else { } else {
oid.rawOid = oid.Oid oid.rawOid = oid.Oid
@ -389,26 +397,27 @@ func (s *Snmp) Gather(acc telegraf.Accumulator) error {
} }
} }
// Launch Mapping // Launch Mapping
// TODO put this in cache on first run
// TODO save mapping and computed oids // TODO save mapping and computed oids
// to do it only the first time // to do it only the first time
// only if len(OidInstanceMapping) == 0 // only if len(s.OidInstanceMapping) == 0
if len(OidInstanceMapping) >= 0 { if len(OidInstanceMapping) >= 0 {
if err := host.SNMPMap(acc); err != nil { if err := host.SNMPMap(acc, s.nameToOid, s.subTableMap); err != nil {
return err return err
} }
} }
// Launch Get requests // Launch Get requests
if err := host.SNMPGet(acc); err != nil { if err := host.SNMPGet(acc, s.initNode); err != nil {
return err return err
} }
if err := host.SNMPBulk(acc); err != nil { if err := host.SNMPBulk(acc, s.initNode); err != nil {
return err return err
} }
} }
return nil return nil
} }
func (h *Host) SNMPMap(acc telegraf.Accumulator) error { func (h *Host) SNMPMap(acc telegraf.Accumulator, nameToOid map[string]string, subTableMap map[string]Subtable) error {
// Get snmp client // Get snmp client
snmpClient, err := h.GetSNMPClient() snmpClient, err := h.GetSNMPClient()
if err != nil { if err != nil {
@ -426,7 +435,7 @@ func (h *Host) SNMPMap(acc telegraf.Accumulator) error {
// This is just a bulk request // This is just a bulk request
oid := Data{} oid := Data{}
oid.Oid = table.oid oid.Oid = table.oid
if val, ok := NameToOid[oid.Oid]; ok { if val, ok := nameToOid[oid.Oid]; ok {
oid.rawOid = "." + val oid.rawOid = "." + val
} else { } else {
oid.rawOid = oid.Oid oid.rawOid = oid.Oid
@ -441,7 +450,7 @@ func (h *Host) SNMPMap(acc telegraf.Accumulator) error {
// ... we create a new Data (oid) object // ... we create a new Data (oid) object
oid := Data{} oid := Data{}
// Looking for more information about this subtable // Looking for more information about this subtable
ssb, exists := SubTableMap[sb] ssb, exists := subTableMap[sb]
if exists { if exists {
// We found a subtable section in config files // We found a subtable section in config files
oid.Oid = ssb.Oid oid.Oid = ssb.Oid
@ -528,7 +537,7 @@ func (h *Host) SNMPMap(acc telegraf.Accumulator) error {
// Add table oid in bulk oid list // Add table oid in bulk oid list
oid := Data{} oid := Data{}
oid.Oid = table.oid oid.Oid = table.oid
if val, ok := NameToOid[oid.Oid]; ok { if val, ok := nameToOid[oid.Oid]; ok {
oid.rawOid = "." + val oid.rawOid = "." + val
} else { } else {
oid.rawOid = oid.Oid oid.rawOid = oid.Oid
@ -545,7 +554,7 @@ func (h *Host) SNMPMap(acc telegraf.Accumulator) error {
// ... we create a new Data (oid) object // ... we create a new Data (oid) object
oid := Data{} oid := Data{}
// Looking for more information about this subtable // Looking for more information about this subtable
ssb, exists := SubTableMap[sb] ssb, exists := subTableMap[sb]
if exists { if exists {
// We found a subtable section in config files // We found a subtable section in config files
oid.Oid = ssb.Oid + key oid.Oid = ssb.Oid + key
@ -587,7 +596,7 @@ func (h *Host) SNMPMap(acc telegraf.Accumulator) error {
return nil return nil
} }
func (h *Host) SNMPGet(acc telegraf.Accumulator) error { func (h *Host) SNMPGet(acc telegraf.Accumulator, initNode Node) error {
// Get snmp client // Get snmp client
snmpClient, err := h.GetSNMPClient() snmpClient, err := h.GetSNMPClient()
if err != nil { if err != nil {
@ -620,7 +629,7 @@ func (h *Host) SNMPGet(acc telegraf.Accumulator) error {
return err3 return err3
} }
// Handle response // Handle response
_, err = h.HandleResponse(oidsList, result, acc) _, err = h.HandleResponse(oidsList, result, acc, initNode)
if err != nil { if err != nil {
return err return err
} }
@ -628,7 +637,7 @@ func (h *Host) SNMPGet(acc telegraf.Accumulator) error {
return nil return nil
} }
func (h *Host) SNMPBulk(acc telegraf.Accumulator) error { func (h *Host) SNMPBulk(acc telegraf.Accumulator, initNode Node) error {
// Get snmp client // Get snmp client
snmpClient, err := h.GetSNMPClient() snmpClient, err := h.GetSNMPClient()
if err != nil { if err != nil {
@ -663,7 +672,7 @@ func (h *Host) SNMPBulk(acc telegraf.Accumulator) error {
return err3 return err3
} }
// Handle response // Handle response
last_oid, err := h.HandleResponse(oidsList, result, acc) last_oid, err := h.HandleResponse(oidsList, result, acc, initNode)
if err != nil { if err != nil {
return err return err
} }
@ -715,7 +724,7 @@ func (h *Host) GetSNMPClient() (*gosnmp.GoSNMP, error) {
return snmpClient, nil return snmpClient, nil
} }
func (h *Host) HandleResponse(oids map[string]Data, result *gosnmp.SnmpPacket, acc telegraf.Accumulator) (string, error) { func (h *Host) HandleResponse(oids map[string]Data, result *gosnmp.SnmpPacket, acc telegraf.Accumulator, initNode Node) (string, error) {
var lastOid string var lastOid string
for _, variable := range result.Variables { for _, variable := range result.Variables {
lastOid = variable.Name lastOid = variable.Name

View File

@ -0,0 +1,64 @@
# Kernel Input Plugin
This plugin is only available on Linux.
The kernel plugin gathers info about the kernel that doesn't fit into other
plugins. In general, it is the statistics available in `/proc/stat` that are
not covered by other plugins.
The metrics are documented in `man proc` under the `/proc/stat` section.
```
/proc/stat
kernel/system statistics. Varies with architecture. Common entries include:
page 5741 1808
The number of pages the system paged in and the number that were paged out (from disk).
swap 1 0
The number of swap pages that have been brought in and out.
intr 1462898
This line shows counts of interrupts serviced since boot time, for each of
the possible system interrupts. The first column is the total of all
interrupts serviced; each subsequent column is the total for a particular interrupt.
ctxt 115315
The number of context switches that the system underwent.
btime 769041601
boot time, in seconds since the Epoch, 1970-01-01 00:00:00 +0000 (UTC).
processes 86031
Number of forks since boot.
```
### Configuration:
```toml
# Get kernel statistics from /proc/stat
[[inputs.kernel]]
# no configuration
```
### Measurements & Fields:
- kernel
- boot_time (integer, seconds since epoch, `btime`)
- context_switches (integer, `ctxt`)
- disk_pages_in (integer, `page (0)`)
- disk_pages_out (integer, `page (1)`)
- interrupts (integer, `intr`)
- processes_forked (integer, `processes`)
### Tags:
None
### Example Output:
```
$ telegraf -config ~/ws/telegraf.conf -input-filter kernel -test
* Plugin: kernel, Collection 1
> kernel boot_time=1457505775i,context_switches=2626618i,disk_pages_in=5741i,disk_pages_out=1808i,interrupts=1472736i,processes_forked=10673i 1457613402960879816
```

View File

@ -0,0 +1,110 @@
// +build linux
package system
import (
"bytes"
"fmt"
"io/ioutil"
"os"
"strconv"
"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/plugins/inputs"
)
// /proc/stat file line prefixes to gather stats on:
var (
interrupts = []byte("intr")
context_switches = []byte("ctxt")
processes_forked = []byte("processes")
disk_pages = []byte("page")
boot_time = []byte("btime")
)
type Kernel struct {
statFile string
}
func (k *Kernel) Description() string {
return "Get kernel statistics from /proc/stat"
}
func (k *Kernel) SampleConfig() string { return "" }
func (k *Kernel) Gather(acc telegraf.Accumulator) error {
data, err := k.getProcStat()
if err != nil {
return err
}
fields := make(map[string]interface{})
dataFields := bytes.Fields(data)
for i, field := range dataFields {
switch {
case bytes.Equal(field, interrupts):
m, err := strconv.Atoi(string(dataFields[i+1]))
if err != nil {
return err
}
fields["interrupts"] = int64(m)
case bytes.Equal(field, context_switches):
m, err := strconv.Atoi(string(dataFields[i+1]))
if err != nil {
return err
}
fields["context_switches"] = int64(m)
case bytes.Equal(field, processes_forked):
m, err := strconv.Atoi(string(dataFields[i+1]))
if err != nil {
return err
}
fields["processes_forked"] = int64(m)
case bytes.Equal(field, boot_time):
m, err := strconv.Atoi(string(dataFields[i+1]))
if err != nil {
return err
}
fields["boot_time"] = int64(m)
case bytes.Equal(field, disk_pages):
in, err := strconv.Atoi(string(dataFields[i+1]))
if err != nil {
return err
}
out, err := strconv.Atoi(string(dataFields[i+2]))
if err != nil {
return err
}
fields["disk_pages_in"] = int64(in)
fields["disk_pages_out"] = int64(out)
}
}
acc.AddFields("kernel", fields, map[string]string{})
return nil
}
func (k *Kernel) getProcStat() ([]byte, error) {
if _, err := os.Stat(k.statFile); os.IsNotExist(err) {
return nil, fmt.Errorf("kernel: %s does not exist!", k.statFile)
} else if err != nil {
return nil, err
}
data, err := ioutil.ReadFile(k.statFile)
if err != nil {
return nil, err
}
return data, nil
}
func init() {
inputs.Add("kernel", func() telegraf.Input {
return &Kernel{
statFile: "/proc/stat",
}
})
}

View File

@ -0,0 +1,164 @@
// +build linux
package system
import (
"io/ioutil"
"os"
"testing"
"github.com/influxdata/telegraf/testutil"
"github.com/stretchr/testify/assert"
)
func TestFullProcFile(t *testing.T) {
tmpfile := makeFakeStatFile([]byte(statFile_Full))
defer os.Remove(tmpfile)
k := Kernel{
statFile: tmpfile,
}
acc := testutil.Accumulator{}
err := k.Gather(&acc)
assert.NoError(t, err)
fields := map[string]interface{}{
"boot_time": int64(1457505775),
"context_switches": int64(2626618),
"disk_pages_in": int64(5741),
"disk_pages_out": int64(1808),
"interrupts": int64(1472736),
"processes_forked": int64(10673),
}
acc.AssertContainsFields(t, "kernel", fields)
}
func TestPartialProcFile(t *testing.T) {
tmpfile := makeFakeStatFile([]byte(statFile_Partial))
defer os.Remove(tmpfile)
k := Kernel{
statFile: tmpfile,
}
acc := testutil.Accumulator{}
err := k.Gather(&acc)
assert.NoError(t, err)
fields := map[string]interface{}{
"boot_time": int64(1457505775),
"context_switches": int64(2626618),
"disk_pages_in": int64(5741),
"disk_pages_out": int64(1808),
"interrupts": int64(1472736),
}
acc.AssertContainsFields(t, "kernel", fields)
}
func TestInvalidProcFile1(t *testing.T) {
tmpfile := makeFakeStatFile([]byte(statFile_Invalid))
defer os.Remove(tmpfile)
k := Kernel{
statFile: tmpfile,
}
acc := testutil.Accumulator{}
err := k.Gather(&acc)
assert.Error(t, err)
}
func TestInvalidProcFile2(t *testing.T) {
tmpfile := makeFakeStatFile([]byte(statFile_Invalid2))
defer os.Remove(tmpfile)
k := Kernel{
statFile: tmpfile,
}
acc := testutil.Accumulator{}
err := k.Gather(&acc)
assert.Error(t, err)
}
func TestNoProcFile(t *testing.T) {
tmpfile := makeFakeStatFile([]byte(statFile_Invalid2))
os.Remove(tmpfile)
k := Kernel{
statFile: tmpfile,
}
acc := testutil.Accumulator{}
err := k.Gather(&acc)
assert.Error(t, err)
assert.Contains(t, err.Error(), "does not exist")
}
const statFile_Full = `cpu 6796 252 5655 10444977 175 0 101 0 0 0
cpu0 6796 252 5655 10444977 175 0 101 0 0 0
intr 1472736 57 10 0 0 0 0 0 0 0 0 0 0 156 0 0 0 0 0 0 111551 42541 12356 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
ctxt 2626618
btime 1457505775
processes 10673
procs_running 2
procs_blocked 0
softirq 1031662 0 649485 20946 111071 11620 0 1 0 994 237545
page 5741 1808
swap 1 0
`
const statFile_Partial = `cpu 6796 252 5655 10444977 175 0 101 0 0 0
cpu0 6796 252 5655 10444977 175 0 101 0 0 0
intr 1472736 57 10 0 0 0 0 0 0 0 0 0 0 156 0 0 0 0 0 0 111551 42541 12356 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
ctxt 2626618
btime 1457505775
procs_running 2
procs_blocked 0
softirq 1031662 0 649485 20946 111071 11620 0 1 0 994 237545
page 5741 1808
`
// missing btime measurement
const statFile_Invalid = `cpu 6796 252 5655 10444977 175 0 101 0 0 0
cpu0 6796 252 5655 10444977 175 0 101 0 0 0
intr 1472736 57 10 0 0 0 0 0 0 0 0 0 0 156 0 0 0 0 0 0 111551 42541 12356 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
ctxt 2626618
btime
processes 10673
procs_running 2
procs_blocked 0
softirq 1031662 0 649485 20946 111071 11620 0 1 0 994 237545
page 5741 1808
swap 1 0
`
// missing second page measurement
const statFile_Invalid2 = `cpu 6796 252 5655 10444977 175 0 101 0 0 0
cpu0 6796 252 5655 10444977 175 0 101 0 0 0
intr 1472736 57 10 0 0 0 0 0 0 0 0 0 0 156 0 0 0 0 0 0 111551 42541 12356 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
ctxt 2626618
processes 10673
procs_running 2
page 5741
procs_blocked 0
softirq 1031662 0 649485 20946 111071 11620 0 1 0 994 237545
`
func makeFakeStatFile(content []byte) string {
tmpfile, err := ioutil.TempFile("", "kerneltest")
if err != nil {
panic(err)
}
if _, err := tmpfile.Write(content); err != nil {
panic(err)
}
if err := tmpfile.Close(); err != nil {
panic(err)
}
return tmpfile.Name()
}