From 43c113527ba9d725db72c5c614ad4474a3988e8f Mon Sep 17 00:00:00 2001 From: Abhi Yerra Date: Thu, 10 Dec 2015 18:49:23 -0800 Subject: [PATCH 01/11] Initial meminfo proc info --- fixtures/meminfo | 42 ++++++++++++++++++ meminfo.go | 107 ++++++++++++++++++++++++++++++++++++++++++++++ meminfo_test.go | 109 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 258 insertions(+) create mode 100644 fixtures/meminfo create mode 100644 meminfo.go create mode 100644 meminfo_test.go diff --git a/fixtures/meminfo b/fixtures/meminfo new file mode 100644 index 000000000..00e140f50 --- /dev/null +++ b/fixtures/meminfo @@ -0,0 +1,42 @@ +MemTotal: 15666184 kB +MemFree: 440324 kB +Buffers: 1020128 kB +Cached: 12007640 kB +SwapCached: 0 kB +Active: 6761276 kB +Inactive: 6532708 kB +Active(anon): 267256 kB +Inactive(anon): 268 kB +Active(file): 6494020 kB +Inactive(file): 6532440 kB +Unevictable: 0 kB +Mlocked: 0 kB +SwapTotal: 0 kB +SwapFree: 0 kB +Dirty: 768 kB +Writeback: 0 kB +AnonPages: 266216 kB +Mapped: 44204 kB +Shmem: 1308 kB +Slab: 1807264 kB +SReclaimable: 1738124 kB +SUnreclaim: 69140 kB +KernelStack: 1616 kB +PageTables: 5288 kB +NFS_Unstable: 0 kB +Bounce: 0 kB +WritebackTmp: 0 kB +CommitLimit: 7833092 kB +Committed_AS: 530844 kB +VmallocTotal: 34359738367 kB +VmallocUsed: 36596 kB +VmallocChunk: 34359637840 kB +HardwareCorrupted: 0 kB +AnonHugePages: 12288 kB +HugePages_Total: 0 +HugePages_Free: 0 +HugePages_Rsvd: 0 +HugePages_Surp: 0 +Hugepagesize: 2048 kB +DirectMap4k: 91136 kB +DirectMap2M: 16039936 kB \ No newline at end of file diff --git a/meminfo.go b/meminfo.go new file mode 100644 index 000000000..0735c4023 --- /dev/null +++ b/meminfo.go @@ -0,0 +1,107 @@ +package procfs + +import ( + "bufio" + "os" + "reflect" + "regexp" + "strconv" +) + +// Meminfo represents memory statistics. +type Meminfo struct { + MemTotal int64 `meminfo:"MemTotal"` + MemFree int64 `meminfo:"MemFree"` + Buffers int64 `meminfo:"Buffers"` + Cached int64 `meminfo:"Cached"` + SwapCached int64 `meminfo:"SwapCached"` + Active int64 `meminfo:"Active"` + Inactive int64 `meminfo:"Inactive"` + ActiveAnon int64 `meminfo:"Active(anon)"` + InactiveAnon int64 `meminfo:"Inactive(anon)"` + ActiveFile int64 `meminfo:"Active(file)"` + InactiveFile int64 `meminfo:"Inactive(file)"` + Unevictable int64 `meminfo:"Unevictable"` + Mlocked int64 `meminfo:"Mlocked"` + SwapTotal int64 `meminfo:"SwapTotal"` + SwapFree int64 `meminfo:"SwapFree"` + Dirty int64 `meminfo:"Dirty"` + Writeback int64 `meminfo:"Writeback"` + AnonPages int64 `meminfo:"AnonPages"` + Mapped int64 `meminfo:"Mapped"` + Shmem int64 `meminfo:"Shmem"` + Slab int64 `meminfo:"Slab"` + SReclaimable int64 `meminfo:"SReclaimable"` + SUnreclaim int64 `meminfo:"SUnreclaim"` + KernelStack int64 `meminfo:"KernelStack"` + PageTables int64 `meminfo:"PageTables"` + NFSUnstable int64 `meminfo:"NFS_Unstable"` + Bounce int64 `meminfo:"Bounce"` + WritebackTmp int64 `meminfo:"WritebackTmp"` + CommitLimit int64 `meminfo:"CommitLimit"` + CommittedAS int64 `meminfo:"Committed_AS"` + VmallocTotal int64 `meminfo:"VmallocTotal"` + VmallocUsed int64 `meminfo:"VmallocUsed"` + VmallocChunk int64 `meminfo:"VmallocChunk"` + HardwareCorrupted int64 `meminfo:"HardwareCorrupted"` + AnonHugePages int64 `meminfo:"AnonHugePages"` + HugePagesTotal int64 `meminfo:"HugePages_Total"` + HugePagesFree int64 `meminfo:"HugePages_Free"` + HugePagesRsvd int64 `meminfo:"HugePages_Rsvd"` + HugePagesSurp int64 `meminfo:"HugePages_Surp"` + Hugepagesize int64 `meminfo:"Hugepagesize"` + DirectMap4k int64 `meminfo:"DirectMap4k"` + DirectMap2M int64 `meminfo:"DirectMap2M"` +} + +// NewMeminfo returns kernel/system statistics read from /proc/stat. +func NewMeminfo() (Meminfo, error) { + fs, err := NewFS(DefaultMountPoint) + if err != nil { + return Meminfo{}, err + } + + return fs.NewMeminfo() +} + +// NewMeminfo returns an information about current kernel/system statistics. +func (fs FS) NewMeminfo() (m Meminfo, err error) { + f, err := os.Open(fs.Path("meminfo")) + if err != nil { + return Meminfo{}, err + } + defer f.Close() + + st := reflect.TypeOf(m) + + s := bufio.NewScanner(f) + for s.Scan() { + line := s.Text() + + re := regexp.MustCompile(m.Regex()) + submatch := re.FindAllStringSubmatch(line, 1) + if submatch == nil { + continue + } + + key := submatch[0][1] + val := submatch[0][2] + + for i := 0; i < st.NumField(); i++ { + field := st.Field(i) + if field.Tag.Get("meminfo") == key { + v, err := strconv.ParseInt(val, 10, 64) + if err != nil { + // no op + } + reflect.ValueOf(&m).Elem().Field(i).SetInt(v) + } + } + } + + return m, nil +} + +func (m Meminfo) Regex() string { + return "([A-Za-z()]*): *([0-9]*).*$" +} diff --git a/meminfo_test.go b/meminfo_test.go new file mode 100644 index 000000000..3cd213204 --- /dev/null +++ b/meminfo_test.go @@ -0,0 +1,109 @@ +package procfs + +import ( + "reflect" + "regexp" + "testing" +) + +func TestMeminfo_regex(t *testing.T) { + + var expected = []struct { + Line string + Key string + Value string + }{ + { + Line: "Inactive(file): 6532440 kB", + Key: "Inactive(file)", + Value: "6532440", + }, + { + Line: "Writeback: 0 kB", + + Key: "Writeback", + Value: "0", + }, + { + Line: "Writeback: 0", + Key: "Writeback", + Value: "0", + }, + } + + m := Meminfo{} + re := regexp.MustCompile(m.Regex()) + + for _, i := range expected { + submatch := re.FindAllStringSubmatch(i.Line, 1) + if submatch == nil { + t.Errorf("regex fail") + } + + if submatch[0][1] != i.Key { + t.Errorf("Key failed for %s", i.Key) + } + if submatch[0][2] != i.Value { + t.Errorf("Value failed for %s", i.Value) + } + + } + +} + +func TestMeminfo(t *testing.T) { + + expected := Meminfo{ + MemTotal: 15666184, + MemFree: 440324, + Buffers: 1020128, + Cached: 12007640, + SwapCached: 0, + Active: 6761276, + Inactive: 6532708, + ActiveAnon: 267256, + InactiveAnon: 268, + ActiveFile: 6494020, + InactiveFile: 6532440, + Unevictable: 0, + Mlocked: 0, + SwapTotal: 0, + SwapFree: 0, + Dirty: 768, + Writeback: 0, + AnonPages: 266216, + Mapped: 44204, + Shmem: 1308, + Slab: 1807264, + SReclaimable: 1738124, + SUnreclaim: 69140, + KernelStack: 1616, + PageTables: 5288, + NFSUnstable: 0, + Bounce: 0, + WritebackTmp: 0, + CommitLimit: 7833092, + CommittedAS: 530844, + VmallocTotal: 34359738367, + VmallocUsed: 36596, + VmallocChunk: 34359637840, + HardwareCorrupted: 0, + AnonHugePages: 12288, + HugePagesTotal: 0, + HugePagesFree: 0, + HugePagesRsvd: 0, + HugePagesSurp: 0, + Hugepagesize: 2048, + DirectMap4k: 91136, + DirectMap2M: 16039936, + } + + have, err := FS("fixtures").NewMeminfo() + if err != nil { + t.Fatal(err) + } + + if reflect.DeepEqual(have, expected) { + t.Errorf("structs are not equal") + } +} From 52a3083475869117f85c2c8f16eafcf4c0ea3558 Mon Sep 17 00:00:00 2001 From: Abhi Yerra Date: Thu, 10 Dec 2015 18:58:56 -0800 Subject: [PATCH 02/11] Documentation for the meminfo keys https://www.kernel.org/doc/Documentation/filesystems/proc.txt --- meminfo.go | 131 ++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 99 insertions(+), 32 deletions(-) diff --git a/meminfo.go b/meminfo.go index 0735c4023..111d7a52e 100644 --- a/meminfo.go +++ b/meminfo.go @@ -10,38 +10,105 @@ import ( // Meminfo represents memory statistics. type Meminfo struct { - MemTotal int64 `meminfo:"MemTotal"` - MemFree int64 `meminfo:"MemFree"` - Buffers int64 `meminfo:"Buffers"` - Cached int64 `meminfo:"Cached"` - SwapCached int64 `meminfo:"SwapCached"` - Active int64 `meminfo:"Active"` - Inactive int64 `meminfo:"Inactive"` - ActiveAnon int64 `meminfo:"Active(anon)"` - InactiveAnon int64 `meminfo:"Inactive(anon)"` - ActiveFile int64 `meminfo:"Active(file)"` - InactiveFile int64 `meminfo:"Inactive(file)"` - Unevictable int64 `meminfo:"Unevictable"` - Mlocked int64 `meminfo:"Mlocked"` - SwapTotal int64 `meminfo:"SwapTotal"` - SwapFree int64 `meminfo:"SwapFree"` - Dirty int64 `meminfo:"Dirty"` - Writeback int64 `meminfo:"Writeback"` - AnonPages int64 `meminfo:"AnonPages"` - Mapped int64 `meminfo:"Mapped"` - Shmem int64 `meminfo:"Shmem"` - Slab int64 `meminfo:"Slab"` - SReclaimable int64 `meminfo:"SReclaimable"` - SUnreclaim int64 `meminfo:"SUnreclaim"` - KernelStack int64 `meminfo:"KernelStack"` - PageTables int64 `meminfo:"PageTables"` - NFSUnstable int64 `meminfo:"NFS_Unstable"` - Bounce int64 `meminfo:"Bounce"` - WritebackTmp int64 `meminfo:"WritebackTmp"` - CommitLimit int64 `meminfo:"CommitLimit"` - CommittedAS int64 `meminfo:"Committed_AS"` - VmallocTotal int64 `meminfo:"VmallocTotal"` - VmallocUsed int64 `meminfo:"VmallocUsed"` + // Total usable ram (i.e. physical ram minus a few reserved + // bits and the kernel binary code) + MemTotal int64 `meminfo:"MemTotal"` + // The sum of LowFree+HighFree + MemFree int64 `meminfo:"MemFree"` + // An estimate of how much memory is available for starting + // new applications, without swapping. Calculated from + // MemFree, SReclaimable, the size of the file LRU lists, and + // the low watermarks in each zone. The estimate takes into + // account that the system needs some page cache to function + // well, and that not all reclaimable slab will be + // reclaimable, due to items being in use. The impact of those + // factors will vary from system to system. + MemAvailable int64 `meminfo:"MemAvailable"` + // Relatively temporary storage for raw disk blocks shouldn't + // get tremendously large (20MB or so) + Buffers int64 `meminfo:"Buffers"` + Cached int64 `meminfo:"Cached"` + // Memory that once was swapped out, is swapped back in but + // still also is in the swapfile (if memory is needed it + // doesn't need to be swapped out AGAIN because it is already + // in the swapfile. This saves I/O) + SwapCached int64 `meminfo:"SwapCached"` + // Memory that has been used more recently and usually not + // reclaimed unless absolutely necessary. + Active int64 `meminfo:"Active"` + // Memory which has been less recently used. It is more + // eligible to be reclaimed for other purposes + Inactive int64 `meminfo:"Inactive"` + ActiveAnon int64 `meminfo:"Active(anon)"` + InactiveAnon int64 `meminfo:"Inactive(anon)"` + ActiveFile int64 `meminfo:"Active(file)"` + InactiveFile int64 `meminfo:"Inactive(file)"` + Unevictable int64 `meminfo:"Unevictable"` + Mlocked int64 `meminfo:"Mlocked"` + // total amount of swap space available + SwapTotal int64 `meminfo:"SwapTotal"` + // Memory which has been evicted from RAM, and is temporarily + // on the disk + SwapFree int64 `meminfo:"SwapFree"` + // Memory which is waiting to get written back to the disk + Dirty int64 `meminfo:"Dirty"` + // Memory which is actively being written back to the disk + Writeback int64 `meminfo:"Writeback"` + // Non-file backed pages mapped into userspace page tables + AnonPages int64 `meminfo:"AnonPages"` + // files which have been mmaped, such as libraries + Mapped int64 `meminfo:"Mapped"` + Shmem int64 `meminfo:"Shmem"` + // in-kernel data structures cache + Slab int64 `meminfo:"Slab"` + // Part of Slab, that might be reclaimed, such as caches + SReclaimable int64 `meminfo:"SReclaimable"` + // Part of Slab, that cannot be reclaimed on memory pressure + SUnreclaim int64 `meminfo:"SUnreclaim"` + KernelStack int64 `meminfo:"KernelStack"` + // amount of memory dedicated to the lowest level of page + // tables. + PageTables int64 `meminfo:"PageTables"` + // NFS pages sent to the server, but not yet committed to + // stable storage + NFSUnstable int64 `meminfo:"NFS_Unstable"` + // Memory used for block device "bounce buffers" + Bounce int64 `meminfo:"Bounce"` + // Memory used by FUSE for temporary writeback buffers + WritebackTmp int64 `meminfo:"WritebackTmp"` + // Based on the overcommit ratio ('vm.overcommit_ratio'), + // this is the total amount of memory currently available to + // be allocated on the system. This limit is only adhered to + // if strict overcommit accounting is enabled (mode 2 in + // 'vm.overcommit_memory'). + // The CommitLimit is calculated with the following formula: + // CommitLimit = ([total RAM pages] - [total huge TLB pages]) * + // overcommit_ratio / 100 + [total swap pages] + // For example, on a system with 1G of physical RAM and 7G + // of swap with a `vm.overcommit_ratio` of 30 it would + // yield a CommitLimit of 7.3G. + // For more details, see the memory overcommit documentation + // in vm/overcommit-accounting. + CommitLimit int64 `meminfo:"CommitLimit"` + // The amount of memory presently allocated on the system. + // The committed memory is a sum of all of the memory which + // has been allocated by processes, even if it has not been + // "used" by them as of yet. A process which malloc()'s 1G + // of memory, but only touches 300M of it will show up as + // using 1G. This 1G is memory which has been "committed" to + // by the VM and can be used at any time by the allocating + // application. With strict overcommit enabled on the system + // (mode 2 in 'vm.overcommit_memory'),allocations which would + // exceed the CommitLimit (detailed above) will not be permitted. + // This is useful if one needs to guarantee that processes will + // not fail due to lack of memory once that memory has been + // successfully allocated. + CommittedAS int64 `meminfo:"Committed_AS"` + // total size of vmalloc memory area + VmallocTotal int64 `meminfo:"VmallocTotal"` + // amount of vmalloc area which is used + VmallocUsed int64 `meminfo:"VmallocUsed"` + // largest contiguous block of vmalloc area which is free VmallocChunk int64 `meminfo:"VmallocChunk"` HardwareCorrupted int64 `meminfo:"HardwareCorrupted"` AnonHugePages int64 `meminfo:"AnonHugePages"` From 11735ec07cad3c7f5e0d450ecabce641f7a8d896 Mon Sep 17 00:00:00 2001 From: Abhi Yerra Date: Fri, 11 Dec 2015 10:01:12 -0800 Subject: [PATCH 03/11] Fix regex and make the Regex method private --- fixtures/meminfo | 2 +- meminfo.go | 8 ++++---- meminfo_test.go | 9 +++++++-- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/fixtures/meminfo b/fixtures/meminfo index 00e140f50..5dec80e81 100644 --- a/fixtures/meminfo +++ b/fixtures/meminfo @@ -39,4 +39,4 @@ HugePages_Rsvd: 0 HugePages_Surp: 0 Hugepagesize: 2048 kB DirectMap4k: 91136 kB -DirectMap2M: 16039936 kB \ No newline at end of file +DirectMap2M: 16039936 kB diff --git a/meminfo.go b/meminfo.go index 111d7a52e..615265da3 100644 --- a/meminfo.go +++ b/meminfo.go @@ -140,12 +140,12 @@ func (fs FS) NewMeminfo() (m Meminfo, err error) { defer f.Close() st := reflect.TypeOf(m) - + re := regexp.MustCompile(m.regex()) s := bufio.NewScanner(f) + for s.Scan() { line := s.Text() - re := regexp.MustCompile(m.Regex()) submatch := re.FindAllStringSubmatch(line, 1) if submatch == nil { continue @@ -169,6 +169,6 @@ func (fs FS) NewMeminfo() (m Meminfo, err error) { return m, nil } -func (m Meminfo) Regex() string { - return "([A-Za-z()]*): *([0-9]*).*$" +func (m Meminfo) regex() string { + return "([A-Za-z()_]*): *([0-9]*).*$" } diff --git a/meminfo_test.go b/meminfo_test.go index 3cd213204..fa2ffd3d4 100644 --- a/meminfo_test.go +++ b/meminfo_test.go @@ -25,14 +25,19 @@ func TestMeminfo_regex(t *testing.T) { Value: "0", }, { - Line: "Writeback: 0", + Line: "Writeback: 123", Key: "Writeback", + Value: "123", + }, + { + Line: "HugePages_Total: 0", + Key: "HugePages_Total", Value: "0", }, } m := Meminfo{} - re := regexp.MustCompile(m.Regex()) + re := regexp.MustCompile(m.regex()) for _, i := range expected { submatch := re.FindAllStringSubmatch(i.Line, 1) From ba37a0fb0e1ce56f0021b5d455b77992bd5a082e Mon Sep 17 00:00:00 2001 From: Abhi Yerra Date: Mon, 14 Dec 2015 11:24:46 -0800 Subject: [PATCH 04/11] Net sockstat --- fixtures/net/sockstat | 6 ++ net_sockstat.go | 139 ++++++++++++++++++++++++++++++++++++++++++ net_sockstat_test.go | 31 ++++++++++ 3 files changed, 176 insertions(+) create mode 100644 fixtures/net/sockstat create mode 100644 net_sockstat.go create mode 100644 net_sockstat_test.go diff --git a/fixtures/net/sockstat b/fixtures/net/sockstat new file mode 100644 index 000000000..47e51f731 --- /dev/null +++ b/fixtures/net/sockstat @@ -0,0 +1,6 @@ +sockets: used 3014 +TCP: inuse 3168 orphan 612 tw 13701 alloc 3169 mem 2734 +UDP: inuse 9 mem 2 +UDPLITE: inuse 0 +RAW: inuse 1 +FRAG: inuse 2 memory 2 \ No newline at end of file diff --git a/net_sockstat.go b/net_sockstat.go new file mode 100644 index 000000000..ba6a23991 --- /dev/null +++ b/net_sockstat.go @@ -0,0 +1,139 @@ +package procfs + +import ( + "bufio" + "os" + "strconv" + "strings" +) + +// NetSockstat stats on /proc/net/sockstat +type NetSockstat struct { + Sockets struct { + Used int64 + } + + TCP struct { + InUse int64 + Orphan int64 + Tw int64 + Alloc int64 + Mem int64 + } + + UDP struct { + InUse int64 + Mem int64 + } + + UDPLite struct { + InUse int64 + } + + RAW struct { + InUse int64 + } + + FRAG struct { + InUse int64 + Memory int64 + } +} + +// NewNetSockstat returns kernel/system statistics read from /proc/net/sockstat. +func NewNetSockstat() (NetSockstat, error) { + fs, err := NewFS(DefaultMountPoint) + if err != nil { + return NetSockstat{}, err + } + + return fs.NewNetSockstat() +} + +// NewNetSockstat returns an information about current kernel/system statistics. +func (fs FS) NewNetSockstat() (m NetSockstat, err error) { + f, err := os.Open(fs.Path("net/sockstat")) + if err != nil { + return NetSockstat{}, err + } + defer f.Close() + + s := bufio.NewScanner(f) + for s.Scan() { + line := s.Text() + + switch { + case strings.HasPrefix(line, "sockets:"): + parsedLines := strings.Fields(line) + for i := range parsedLines { + switch parsedLines[i] { + case "used": + m.Sockets.Used = parseInt64(parsedLines[i+1]) + } + } + case strings.HasPrefix(line, "TCP:"): + parsedLines := strings.Fields(line) + for i := range parsedLines { + switch parsedLines[i] { + case "inuse": + m.TCP.InUse = parseInt64(parsedLines[i+1]) + case "orphan": + m.TCP.Orphan = parseInt64(parsedLines[i+1]) + case "tw": + m.TCP.Tw = parseInt64(parsedLines[i+1]) + case "alloc": + m.TCP.Alloc = parseInt64(parsedLines[i+1]) + case "mem": + m.TCP.Mem = parseInt64(parsedLines[i+1]) + } + } + case strings.HasPrefix(line, "UDP:"): + parsedLines := strings.Fields(line) + for i := range parsedLines { + switch parsedLines[i] { + case "inuse": + m.UDP.InUse = parseInt64(parsedLines[i+1]) + case "mem": + m.UDP.Mem = parseInt64(parsedLines[i+1]) + } + } + case strings.HasPrefix(line, "UDPLITE:"): + parsedLines := strings.Fields(line) + for i := range parsedLines { + switch parsedLines[i] { + case "inuse": + m.UDPLite.InUse = parseInt64(parsedLines[i+1]) + } + } + case strings.HasPrefix(line, "RAW:"): + parsedLines := strings.Fields(line) + for i := range parsedLines { + switch parsedLines[i] { + case "inuse": + m.RAW.InUse = parseInt64(parsedLines[i+1]) + } + } + case strings.HasPrefix(line, "FRAG:"): + parsedLines := strings.Fields(line) + for i := range parsedLines { + switch parsedLines[i] { + case "inuse": + m.FRAG.InUse = parseInt64(parsedLines[i+1]) + case "memory": + m.FRAG.Memory = parseInt64(parsedLines[i+1]) + } + } + } + } + + return m, nil +} + +func parseInt64(val string) int64 { + v, err := strconv.ParseInt(val, 10, 64) + if err != nil { + return 0 + } + + return v +} diff --git a/net_sockstat_test.go b/net_sockstat_test.go new file mode 100644 index 000000000..197001584 --- /dev/null +++ b/net_sockstat_test.go @@ -0,0 +1,31 @@ +package procfs + +import ( + "reflect" + "testing" +) + +func TestNetSockstat(t *testing.T) { + expected := NetSockstat{} + expected.Sockets.Used = 3014 + expected.TCP.InUse = 3168 + expected.TCP.Orphan = 612 + expected.TCP.Tw = 13701 + expected.TCP.Alloc = 3169 + expected.TCP.Mem = 2734 + expected.UDP.InUse = 9 + expected.UDP.Mem = 2 + expected.UDPLite.InUse = 0 + expected.RAW.InUse = 1 + expected.FRAG.InUse = 2 + expected.FRAG.Memory = 2 + + have, err := FS("fixtures").NewNetSockstat() + if err != nil { + t.Fatal(err) + } + + if reflect.DeepEqual(expected, have) { + t.Errorf("structs are not equal") + } +} From 6d47c13590a3d23627c575bd1e1e269f2ec711bd Mon Sep 17 00:00:00 2001 From: Abhi Yerra Date: Mon, 14 Dec 2015 11:25:48 -0800 Subject: [PATCH 05/11] Updated Authors file --- AUTHORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS.md b/AUTHORS.md index 0c802dd87..34c92ef5e 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -18,3 +18,4 @@ The following individuals have contributed code to this repository * Nicky Gerritsen * Rémi Audebert * Tobias Schmidt +* Abhi Yerra From d45a74412858f49bb8dfb6843b7cdb5ac1e955c5 Mon Sep 17 00:00:00 2001 From: Abhi Yerra Date: Mon, 14 Dec 2015 11:39:00 -0800 Subject: [PATCH 06/11] Fixed test bug in net sockstat --- net_sockstat_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net_sockstat_test.go b/net_sockstat_test.go index 197001584..47fe7233a 100644 --- a/net_sockstat_test.go +++ b/net_sockstat_test.go @@ -25,7 +25,7 @@ func TestNetSockstat(t *testing.T) { t.Fatal(err) } - if reflect.DeepEqual(expected, have) { + if !reflect.DeepEqual(expected, have) { t.Errorf("structs are not equal") } } From eb972fad7dc41416680233cf594e968d40bb3355 Mon Sep 17 00:00:00 2001 From: Abhi Yerra Date: Mon, 14 Dec 2015 11:57:10 -0800 Subject: [PATCH 07/11] Error in validation code --- meminfo.go | 2 +- meminfo_test.go | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/meminfo.go b/meminfo.go index 615265da3..3d86de50f 100644 --- a/meminfo.go +++ b/meminfo.go @@ -170,5 +170,5 @@ func (fs FS) NewMeminfo() (m Meminfo, err error) { } func (m Meminfo) regex() string { - return "([A-Za-z()_]*): *([0-9]*).*$" + return "([A-Za-z0-9()_]*): *([0-9]*).*$" } diff --git a/meminfo_test.go b/meminfo_test.go index fa2ffd3d4..0e8f9dd3d 100644 --- a/meminfo_test.go +++ b/meminfo_test.go @@ -34,6 +34,11 @@ func TestMeminfo_regex(t *testing.T) { Key: "HugePages_Total", Value: "0", }, + { + Line: "DirectMap2M: 16039936 kB", + Key: "DirectMap2M", + Value: "16039936", + }, } m := Meminfo{} @@ -57,7 +62,6 @@ func TestMeminfo_regex(t *testing.T) { } func TestMeminfo(t *testing.T) { - expected := Meminfo{ MemTotal: 15666184, MemFree: 440324, @@ -108,7 +112,7 @@ func TestMeminfo(t *testing.T) { t.Fatal(err) } - if reflect.DeepEqual(have, expected) { + if !reflect.DeepEqual(have, expected) { t.Errorf("structs are not equal") } } From 637e2e098dc943bf782c0f3cf0a4ffb4b1b81463 Mon Sep 17 00:00:00 2001 From: Abhi Yerra Date: Tue, 15 Dec 2015 00:00:26 -0500 Subject: [PATCH 08/11] Initial net/tcp --- net_tcp.go | 141 ++++++++++++++++++++++++++++++++++++++++++++++++ net_tcp_test.go | 110 +++++++++++++++++++++++++++++++++++++ 2 files changed, 251 insertions(+) create mode 100644 net_tcp.go create mode 100644 net_tcp_test.go diff --git a/net_tcp.go b/net_tcp.go new file mode 100644 index 000000000..683a28a78 --- /dev/null +++ b/net_tcp.go @@ -0,0 +1,141 @@ +package procfs + +import ( + "bufio" + "os" + "regexp" +) + +type NetTcpLine struct { + Sl string `net_tcp:"sl"` + LocalAddress string `net_tcp:"local_address"` + RemoteAddress string `net_tcp:"rem_address"` + St string `net_tcp:"st"` + TxQueue string `net_tcp:"tx_queue"` + RxQueue string `net_tcp:"rx_queue"` + Tr string `net_tcp:"tr"` + TmWhen string `net_tcp:"tm->when"` + Retrnsmt string `net_tcp:"retrnsmt"` + Uid string `net_tcp:"uid"` + Timeout string `net_tcp:"timeout"` + Inode string `net_tcp:"inode"` + RefCount string `net_tcp:""` + MemoryAddress string `net_tcp:""` + + // There are optional attributes which I am not capturing + // including: Retransmit Timeout, Predicted Tick, Ack.quick, + // Sending Congestion Window, Slow Start Size Threshold. +} + +// NetTcp stats on /proc/net/sockstat +type NetTcp []NetTcpLine + +// NewNetTcp returns kernel/system statistics read from /proc/net/sockstat. +func NewNetTcp() (NetTcp, error) { + fs, err := NewFS(DefaultMountPoint) + if err != nil { + return NetTcp{}, err + } + + return fs.NewNetTcp() +} + +// NewNetTcp returns an information about current kernel/system statistics. +func (fs FS) NewNetTcp() (m NetTcp, err error) { + f, err := os.Open(fs.Path("net/sockstat")) + if err != nil { + return NetTcp{}, err + } + defer f.Close() + + re := regexp.MustCompile(m.regex()) + s := bufio.NewScanner(f) + + for s.Scan() { + line := s.Text() + + matches := re.FindAllStringSubmatch(line, 21) + if matches == nil { + continue + } + r := matches[0] + + l := NetTcpLine{ + Sl: r[1], + LocalAddress: r[2] + ":" + r[3], + RemoteAddress: r[4] + ":" + r[5], + St: r[6], + TxQueue: r[7], + RxQueue: r[8], + Tr: r[9], + TmWhen: r[10], + Retrnsmt: r[11], + Uid: r[12], + Timeout: r[13], + Inode: r[14], + RefCount: r[15], + MemoryAddress: r[16], + } + + m = append(m, l) + + } + + return m, nil +} + +/* +https://metacpan.org/source/SALVA/Linux-Proc-Net-TCP-0.07/README + +qr/^\s* + (\d+):\s # sl - 0 + ([\dA-F]{8}(?:[\dA-F]{24})?):([\dA-F]{4})\s # local address and port - 1 & 2 + ([\dA-F]{8}(?:[\dA-F]{24})?):([\dA-F]{4})\s # remote address and port - 3 & 4 + ([\dA-F]{2})\s # st - 5 + ([\dA-F]{8}):([\dA-F]{8})\s # tx_queue and rx_queue - 6 & 7 + (\d\d):([\dA-F]{8}|F{9,}|1AD7F[\dA-F]{6})\s # tr and tm->when - 8 & 9 + ([\dA-F]{8})\s+ # retrnsmt - 10 + (\d+)\s+ # uid - 11 + (\d+)\s+ # timeout - 12 + (\d+)\s+ # inode - 13 + (\d+)\s+ # ref count - 14 + ((?:[\dA-F]{8}){1,2}) # memory address - 15 + (?: + \s+ + (\d+)\s+ # retransmit timeout - 16 + (\d+)\s+ # predicted tick - 17 + (\d+)\s+ # ack.quick - 18 + (\d+)\s+ # sending congestion window - 19 + (-?\d+) # slow start size threshold - 20 + )? + \s* + (.*) # more - 21 + $ +/xi, +*/ +func (n NetTcp) regex() string { + return `^\s*(\d+):\s([\dA-F]{8}(?:[\dA-F]{24})?):([\dA-F]{4})\s([\dA-F]{8}(?:[\dA-F]{24})?):([\dA-F]{4})\s([\dA-F]{2})\s([\dA-F]{8}):([\dA-F]{8})\s(\d\d):([\dA-F]{8}|F{9,}|1AD7F[\dA-F]{6\})\s([\dA-F]{8})\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+((?:[\dA-F]{8}){1,2})(?:\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(-?\d+))?\s*(.*)$` +} + +/* + sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode + 0: 00000000:0016 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 16071 1 0000000000000000 100 0 0 10 0 + 1: 00000000:0056 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 16481 1 0000000000000000 100 0 0 10 0 + 2: 00000000:0057 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 16482 1 0000000000000000 100 0 0 10 0 + 3: 00000000:0BB8 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 516865617 1 0000000000000000 100 0 0 10 0 + 4: 00000000:0058 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 16476 1 0000000000000000 100 0 0 10 0 + 5: 00000000:0059 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 16480 1 0000000000000000 100 0 0 10 0 + 6: 00000000:005A 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 16479 1 0000000000000000 100 0 0 10 0 + 7: 00000000:01BB 00000000:0000 0A 00000000:00000000 02:00000002 00000000 0 0 3994549147 2 0000000000000000 100 0 1 10 0 + 8: 260FC90A:01BB AE6857C8:C747 03 00000000:00000000 01:000000DC 00000005 0 0 0 2 0000000000000000 + 9: 260FC90A:01BB 0E7F51DE:7A79 03 00000000:00000000 01:0000084A 00000005 0 0 0 2 0000000000000000 + 10: 260FC90A:01BB 89E2E3C9:749B 03 00000000:00000000 01:00000A16 00000005 0 0 0 2 0000000000000000 + 11: 260FC90A:01BB AE6857C8:C752 03 00000000:00000000 01:0000008E 00000002 0 0 0 2 0000000000000000 + 12: 260FC90A:01BB D81B38AC:64F9 03 00000000:00000000 01:00000063 00000000 0 0 0 2 0000000000000000 + 13: 260FC90A:01BB 14288875:155E 03 00000000:00000000 01:00000A16 00000005 0 0 0 2 0000000000000000 + 14: 260FC90A:01BB 53202464:C9D6 03 00000000:00000000 01:00000051 00000000 0 0 0 2 0000000000000000 + 15: 260FC90A:01BB 5C49E8DD:F022 03 00000000:00000000 01:0000021F 00000004 0 0 0 2 0000000000000000 + 16: 260FC90A:01BB 9A99935B:AFF3 03 00000000:00000000 01:00000246 00000004 0 0 0 2 0000000000000000 + 17: 260FC90A:01BB 231D4B4B:EF00 03 00000000:00000000 01:000001BA 00000004 0 0 0 2 0000000000000000 + 18: 260FC90A:01BB 162491A5:C524 03 00000000:00000000 01:00000272 00000004 0 0 0 2 0000000000000000 +*/ diff --git a/net_tcp_test.go b/net_tcp_test.go new file mode 100644 index 000000000..b7324dc44 --- /dev/null +++ b/net_tcp_test.go @@ -0,0 +1,110 @@ +package procfs + +import ( + "reflect" + "testing" +) + +func TestNetTcp_regex(t *testing.T) { + + var expected = []struct { + Line string + Expected NetTcpLine + }{ + { + Line: " 0: 00000000:0016 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 16071 1 0000000000000000 100 0 0 10 0", + Expected: NetTcpLine{ + Sl: "0" + LocalAddress: "00000000:0016" + RemoteAddress: "00000000:0000" + St: "0A" + TxQueue: "00000000:00000000" + RxQueue: "00:00000000" + Tr: "00000000" + TmWhen: "0" + Retrnsmt: "0" + Uid: "16071" + Timeout: "1" + Inode: "0000000000000000" + RefCount: + MemoryAddress: + + }, + }, + } + + m := NetTcp{} + re := regexp.MustCompile(m.regex()) + + for _, i := range expected { + submatch := re.FindAllStringSubmatch(i.Line, 1) + if submatch == nil { + t.Errorf("regex fail") + } + + if submatch[0][1] != i.Key { + t.Errorf("Key failed for %s", i.Key) + } + if submatch[0][2] != i.Value { + t.Errorf("Value failed for %s", i.Value) + } + + } + +} + +func TestNetTcp(t *testing.T) { + expected := NetTcp{ + MemTotal: 15666184, + MemFree: 440324, + Buffers: 1020128, + Cached: 12007640, + SwapCached: 0, + Active: 6761276, + Inactive: 6532708, + ActiveAnon: 267256, + InactiveAnon: 268, + ActiveFile: 6494020, + InactiveFile: 6532440, + Unevictable: 0, + Mlocked: 0, + SwapTotal: 0, + SwapFree: 0, + Dirty: 768, + Writeback: 0, + AnonPages: 266216, + Mapped: 44204, + Shmem: 1308, + Slab: 1807264, + SReclaimable: 1738124, + SUnreclaim: 69140, + KernelStack: 1616, + PageTables: 5288, + NFSUnstable: 0, + Bounce: 0, + WritebackTmp: 0, + CommitLimit: 7833092, + CommittedAS: 530844, + VmallocTotal: 34359738367, + VmallocUsed: 36596, + VmallocChunk: 34359637840, + HardwareCorrupted: 0, + AnonHugePages: 12288, + HugePagesTotal: 0, + HugePagesFree: 0, + HugePagesRsvd: 0, + HugePagesSurp: 0, + Hugepagesize: 2048, + DirectMap4k: 91136, + DirectMap2M: 16039936, + } + + have, err := FS("fixtures").NewNetTcp() + if err != nil { + t.Fatal(err) + } + + if !reflect.DeepEqual(have, expected) { + t.Errorf("structs are not equal") + } +} From dbf7491b91a81e87c5042e94073ab16c47ef65dd Mon Sep 17 00:00:00 2001 From: Abhi Yerra Date: Tue, 15 Dec 2015 00:12:39 -0500 Subject: [PATCH 09/11] First version of proc/net/tcp --- fixtures/net/tcp | 20 +++++++ net_tcp.go | 53 +++++++++-------- net_tcp_test.go | 151 +++++++++++++++++++++++------------------------ 3 files changed, 123 insertions(+), 101 deletions(-) create mode 100644 fixtures/net/tcp diff --git a/fixtures/net/tcp b/fixtures/net/tcp new file mode 100644 index 000000000..aecc80ccb --- /dev/null +++ b/fixtures/net/tcp @@ -0,0 +1,20 @@ + sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode + 0: 00000000:0016 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 16071 1 0000000000000000 100 0 0 10 0 + 1: 00000000:0056 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 16481 1 0000000000000000 100 0 0 10 0 + 2: 00000000:0057 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 16482 1 0000000000000000 100 0 0 10 0 + 3: 00000000:0BB8 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 516865617 1 0000000000000000 100 0 0 10 0 + 4: 00000000:0058 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 16476 1 0000000000000000 100 0 0 10 0 + 5: 00000000:0059 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 16480 1 0000000000000000 100 0 0 10 0 + 6: 00000000:005A 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 16479 1 0000000000000000 100 0 0 10 0 + 7: 00000000:01BB 00000000:0000 0A 00000000:00000000 02:00000002 00000000 0 0 3994549147 2 0000000000000000 100 0 1 10 0 + 8: 260FC90A:01BB AE6857C8:C747 03 00000000:00000000 01:000000DC 00000005 0 0 0 2 0000000000000000 + 9: 260FC90A:01BB 0E7F51DE:7A79 03 00000000:00000000 01:0000084A 00000005 0 0 0 2 0000000000000000 + 10: 260FC90A:01BB 89E2E3C9:749B 03 00000000:00000000 01:00000A16 00000005 0 0 0 2 0000000000000000 + 11: 260FC90A:01BB AE6857C8:C752 03 00000000:00000000 01:0000008E 00000002 0 0 0 2 0000000000000000 + 12: 260FC90A:01BB D81B38AC:64F9 03 00000000:00000000 01:00000063 00000000 0 0 0 2 0000000000000000 + 13: 260FC90A:01BB 14288875:155E 03 00000000:00000000 01:00000A16 00000005 0 0 0 2 0000000000000000 + 14: 260FC90A:01BB 53202464:C9D6 03 00000000:00000000 01:00000051 00000000 0 0 0 2 0000000000000000 + 15: 260FC90A:01BB 5C49E8DD:F022 03 00000000:00000000 01:0000021F 00000004 0 0 0 2 0000000000000000 + 16: 260FC90A:01BB 9A99935B:AFF3 03 00000000:00000000 01:00000246 00000004 0 0 0 2 0000000000000000 + 17: 260FC90A:01BB 231D4B4B:EF00 03 00000000:00000000 01:000001BA 00000004 0 0 0 2 0000000000000000 + 18: 260FC90A:01BB 162491A5:C524 03 00000000:00000000 01:00000272 00000004 0 0 0 2 0000000000000000 diff --git a/net_tcp.go b/net_tcp.go index 683a28a78..36832c14c 100644 --- a/net_tcp.go +++ b/net_tcp.go @@ -2,6 +2,7 @@ package procfs import ( "bufio" + "fmt" "os" "regexp" ) @@ -54,34 +55,40 @@ func (fs FS) NewNetTcp() (m NetTcp, err error) { for s.Scan() { line := s.Text() - matches := re.FindAllStringSubmatch(line, 21) - if matches == nil { - continue - } - r := matches[0] - - l := NetTcpLine{ - Sl: r[1], - LocalAddress: r[2] + ":" + r[3], - RemoteAddress: r[4] + ":" + r[5], - St: r[6], - TxQueue: r[7], - RxQueue: r[8], - Tr: r[9], - TmWhen: r[10], - Retrnsmt: r[11], - Uid: r[12], - Timeout: r[13], - Inode: r[14], - RefCount: r[15], - MemoryAddress: r[16], + l, err := m.netTcpLine(re, line) + if err == nil { + m = append(m, l) } + } - m = append(m, l) + return m, nil +} +func (m NetTcp) netTcpLine(re *regexp.Regexp, line string) (l NetTcpLine, err error) { + matches := re.FindAllStringSubmatch(line, 21) + if matches == nil { + return NetTcpLine{}, fmt.Errorf("Invalid NetTcp Line") + } + r := matches[0] + + l = NetTcpLine{ + Sl: r[1], + LocalAddress: r[2] + ":" + r[3], + RemoteAddress: r[4] + ":" + r[5], + St: r[6], + TxQueue: r[7], + RxQueue: r[8], + Tr: r[9], + TmWhen: r[10], + Retrnsmt: r[11], + Uid: r[12], + Timeout: r[13], + Inode: r[14], + RefCount: r[15], + MemoryAddress: r[16], } - return m, nil + return } /* diff --git a/net_tcp_test.go b/net_tcp_test.go index b7324dc44..14ff63a48 100644 --- a/net_tcp_test.go +++ b/net_tcp_test.go @@ -2,6 +2,7 @@ package procfs import ( "reflect" + "regexp" "testing" ) @@ -12,23 +13,22 @@ func TestNetTcp_regex(t *testing.T) { Expected NetTcpLine }{ { - Line: " 0: 00000000:0016 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 16071 1 0000000000000000 100 0 0 10 0", - Expected: NetTcpLine{ - Sl: "0" - LocalAddress: "00000000:0016" - RemoteAddress: "00000000:0000" - St: "0A" - TxQueue: "00000000:00000000" - RxQueue: "00:00000000" - Tr: "00000000" - TmWhen: "0" - Retrnsmt: "0" - Uid: "16071" - Timeout: "1" - Inode: "0000000000000000" - RefCount: - MemoryAddress: - + Line: " 0: 00000000:0016 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 16071 1 0000000000000000 100 0 0 10 0", + Expected: NetTcpLine{ + Sl: "0", + LocalAddress: "00000000:0016", + RemoteAddress: "00000000:0000", + St: "0A", + TxQueue: "00000000", + RxQueue: "00000000", + Tr: "00", + TmWhen: "00000000", + Retrnsmt: "00000000", + Uid: "0", + Timeout: "0", + Inode: "16071", + RefCount: "1", + MemoryAddress: "0000000000000000", }, }, } @@ -37,74 +37,69 @@ func TestNetTcp_regex(t *testing.T) { re := regexp.MustCompile(m.regex()) for _, i := range expected { - submatch := re.FindAllStringSubmatch(i.Line, 1) - if submatch == nil { - t.Errorf("regex fail") - } + have, _ := m.netTcpLine(re, i.Line) - if submatch[0][1] != i.Key { - t.Errorf("Key failed for %s", i.Key) - } - if submatch[0][2] != i.Value { - t.Errorf("Value failed for %s", i.Value) + if !reflect.DeepEqual(i.Expected, have) { + t.Errorf("NetTcp Regex is invalid") } - } } func TestNetTcp(t *testing.T) { - expected := NetTcp{ - MemTotal: 15666184, - MemFree: 440324, - Buffers: 1020128, - Cached: 12007640, - SwapCached: 0, - Active: 6761276, - Inactive: 6532708, - ActiveAnon: 267256, - InactiveAnon: 268, - ActiveFile: 6494020, - InactiveFile: 6532440, - Unevictable: 0, - Mlocked: 0, - SwapTotal: 0, - SwapFree: 0, - Dirty: 768, - Writeback: 0, - AnonPages: 266216, - Mapped: 44204, - Shmem: 1308, - Slab: 1807264, - SReclaimable: 1738124, - SUnreclaim: 69140, - KernelStack: 1616, - PageTables: 5288, - NFSUnstable: 0, - Bounce: 0, - WritebackTmp: 0, - CommitLimit: 7833092, - CommittedAS: 530844, - VmallocTotal: 34359738367, - VmallocUsed: 36596, - VmallocChunk: 34359637840, - HardwareCorrupted: 0, - AnonHugePages: 12288, - HugePagesTotal: 0, - HugePagesFree: 0, - HugePagesRsvd: 0, - HugePagesSurp: 0, - Hugepagesize: 2048, - DirectMap4k: 91136, - DirectMap2M: 16039936, - } + /* + expected := NetTcp{ + MemTotal: 15666184, + MemFree: 440324, + Buffers: 1020128, + Cached: 12007640, + SwapCached: 0, + Active: 6761276, + Inactive: 6532708, + ActiveAnon: 267256, + InactiveAnon: 268, + ActiveFile: 6494020, + InactiveFile: 6532440, + Unevictable: 0, + Mlocked: 0, + SwapTotal: 0, + SwapFree: 0, + Dirty: 768, + Writeback: 0, + AnonPages: 266216, + Mapped: 44204, + Shmem: 1308, + Slab: 1807264, + SReclaimable: 1738124, + SUnreclaim: 69140, + KernelStack: 1616, + PageTables: 5288, + NFSUnstable: 0, + Bounce: 0, + WritebackTmp: 0, + CommitLimit: 7833092, + CommittedAS: 530844, + VmallocTotal: 34359738367, + VmallocUsed: 36596, + VmallocChunk: 34359637840, + HardwareCorrupted: 0, + AnonHugePages: 12288, + HugePagesTotal: 0, + HugePagesFree: 0, + HugePagesRsvd: 0, + HugePagesSurp: 0, + Hugepagesize: 2048, + DirectMap4k: 91136, + DirectMap2M: 16039936, + } - have, err := FS("fixtures").NewNetTcp() - if err != nil { - t.Fatal(err) - } + have, err := FS("fixtures").NewNetTcp() + if err != nil { + t.Fatal(err) + } - if !reflect.DeepEqual(have, expected) { - t.Errorf("structs are not equal") - } + if !reflect.DeepEqual(have, expected) { + t.Errorf("structs are not equal") + } + */ } From 38bbaed3d95c15c7e93ba629a3a9c941232577e1 Mon Sep 17 00:00:00 2001 From: Abhi Yerra Date: Tue, 15 Dec 2015 00:19:10 -0500 Subject: [PATCH 10/11] Fixed Go Vet bug --- net_tcp.go | 60 ++++++++++++++++--------------------------------- net_tcp_test.go | 20 ++++++++--------- 2 files changed, 29 insertions(+), 51 deletions(-) diff --git a/net_tcp.go b/net_tcp.go index 36832c14c..ea1ecdf29 100644 --- a/net_tcp.go +++ b/net_tcp.go @@ -7,7 +7,8 @@ import ( "regexp" ) -type NetTcpLine struct { +// NetTCPLine is a parsed line of /proc/net/tcp +type NetTCPLine struct { Sl string `net_tcp:"sl"` LocalAddress string `net_tcp:"local_address"` RemoteAddress string `net_tcp:"rem_address"` @@ -17,7 +18,7 @@ type NetTcpLine struct { Tr string `net_tcp:"tr"` TmWhen string `net_tcp:"tm->when"` Retrnsmt string `net_tcp:"retrnsmt"` - Uid string `net_tcp:"uid"` + UID string `net_tcp:"uid"` Timeout string `net_tcp:"timeout"` Inode string `net_tcp:"inode"` RefCount string `net_tcp:""` @@ -28,24 +29,24 @@ type NetTcpLine struct { // Sending Congestion Window, Slow Start Size Threshold. } -// NetTcp stats on /proc/net/sockstat -type NetTcp []NetTcpLine +// NetTCP stats on /proc/net/tcp +type NetTCP []NetTCPLine -// NewNetTcp returns kernel/system statistics read from /proc/net/sockstat. -func NewNetTcp() (NetTcp, error) { +// NewNetTCP returns kernel/system statistics read from /proc/net/tcp. +func NewNetTCP() (NetTCP, error) { fs, err := NewFS(DefaultMountPoint) if err != nil { - return NetTcp{}, err + return NetTCP{}, err } - return fs.NewNetTcp() + return fs.NewNetTCP() } -// NewNetTcp returns an information about current kernel/system statistics. -func (fs FS) NewNetTcp() (m NetTcp, err error) { - f, err := os.Open(fs.Path("net/sockstat")) +// NewNetTCP returns an information about current kernel/system statistics. +func (fs FS) NewNetTCP() (m NetTCP, err error) { + f, err := os.Open(fs.Path("net/tcp")) if err != nil { - return NetTcp{}, err + return NetTCP{}, err } defer f.Close() @@ -55,7 +56,7 @@ func (fs FS) NewNetTcp() (m NetTcp, err error) { for s.Scan() { line := s.Text() - l, err := m.netTcpLine(re, line) + l, err := m.netTCPLine(re, line) if err == nil { m = append(m, l) } @@ -64,14 +65,14 @@ func (fs FS) NewNetTcp() (m NetTcp, err error) { return m, nil } -func (m NetTcp) netTcpLine(re *regexp.Regexp, line string) (l NetTcpLine, err error) { +func (n NetTCP) netTCPLine(re *regexp.Regexp, line string) (l NetTCPLine, err error) { matches := re.FindAllStringSubmatch(line, 21) if matches == nil { - return NetTcpLine{}, fmt.Errorf("Invalid NetTcp Line") + return NetTCPLine{}, fmt.Errorf("Invalid NetTCP Line") } r := matches[0] - l = NetTcpLine{ + l = NetTCPLine{ Sl: r[1], LocalAddress: r[2] + ":" + r[3], RemoteAddress: r[4] + ":" + r[5], @@ -81,7 +82,7 @@ func (m NetTcp) netTcpLine(re *regexp.Regexp, line string) (l NetTcpLine, err er Tr: r[9], TmWhen: r[10], Retrnsmt: r[11], - Uid: r[12], + UID: r[12], Timeout: r[13], Inode: r[14], RefCount: r[15], @@ -120,29 +121,6 @@ qr/^\s* $ /xi, */ -func (n NetTcp) regex() string { +func (n NetTCP) regex() string { return `^\s*(\d+):\s([\dA-F]{8}(?:[\dA-F]{24})?):([\dA-F]{4})\s([\dA-F]{8}(?:[\dA-F]{24})?):([\dA-F]{4})\s([\dA-F]{2})\s([\dA-F]{8}):([\dA-F]{8})\s(\d\d):([\dA-F]{8}|F{9,}|1AD7F[\dA-F]{6\})\s([\dA-F]{8})\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+((?:[\dA-F]{8}){1,2})(?:\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(-?\d+))?\s*(.*)$` } - -/* - sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode - 0: 00000000:0016 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 16071 1 0000000000000000 100 0 0 10 0 - 1: 00000000:0056 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 16481 1 0000000000000000 100 0 0 10 0 - 2: 00000000:0057 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 16482 1 0000000000000000 100 0 0 10 0 - 3: 00000000:0BB8 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 516865617 1 0000000000000000 100 0 0 10 0 - 4: 00000000:0058 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 16476 1 0000000000000000 100 0 0 10 0 - 5: 00000000:0059 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 16480 1 0000000000000000 100 0 0 10 0 - 6: 00000000:005A 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 16479 1 0000000000000000 100 0 0 10 0 - 7: 00000000:01BB 00000000:0000 0A 00000000:00000000 02:00000002 00000000 0 0 3994549147 2 0000000000000000 100 0 1 10 0 - 8: 260FC90A:01BB AE6857C8:C747 03 00000000:00000000 01:000000DC 00000005 0 0 0 2 0000000000000000 - 9: 260FC90A:01BB 0E7F51DE:7A79 03 00000000:00000000 01:0000084A 00000005 0 0 0 2 0000000000000000 - 10: 260FC90A:01BB 89E2E3C9:749B 03 00000000:00000000 01:00000A16 00000005 0 0 0 2 0000000000000000 - 11: 260FC90A:01BB AE6857C8:C752 03 00000000:00000000 01:0000008E 00000002 0 0 0 2 0000000000000000 - 12: 260FC90A:01BB D81B38AC:64F9 03 00000000:00000000 01:00000063 00000000 0 0 0 2 0000000000000000 - 13: 260FC90A:01BB 14288875:155E 03 00000000:00000000 01:00000A16 00000005 0 0 0 2 0000000000000000 - 14: 260FC90A:01BB 53202464:C9D6 03 00000000:00000000 01:00000051 00000000 0 0 0 2 0000000000000000 - 15: 260FC90A:01BB 5C49E8DD:F022 03 00000000:00000000 01:0000021F 00000004 0 0 0 2 0000000000000000 - 16: 260FC90A:01BB 9A99935B:AFF3 03 00000000:00000000 01:00000246 00000004 0 0 0 2 0000000000000000 - 17: 260FC90A:01BB 231D4B4B:EF00 03 00000000:00000000 01:000001BA 00000004 0 0 0 2 0000000000000000 - 18: 260FC90A:01BB 162491A5:C524 03 00000000:00000000 01:00000272 00000004 0 0 0 2 0000000000000000 -*/ diff --git a/net_tcp_test.go b/net_tcp_test.go index 14ff63a48..cf1ca0868 100644 --- a/net_tcp_test.go +++ b/net_tcp_test.go @@ -6,15 +6,15 @@ import ( "testing" ) -func TestNetTcp_regex(t *testing.T) { +func TestNetTCP_regex(t *testing.T) { var expected = []struct { Line string - Expected NetTcpLine + Expected NetTCPLine }{ { Line: " 0: 00000000:0016 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 16071 1 0000000000000000 100 0 0 10 0", - Expected: NetTcpLine{ + Expected: NetTCPLine{ Sl: "0", LocalAddress: "00000000:0016", RemoteAddress: "00000000:0000", @@ -24,7 +24,7 @@ func TestNetTcp_regex(t *testing.T) { Tr: "00", TmWhen: "00000000", Retrnsmt: "00000000", - Uid: "0", + UID: "0", Timeout: "0", Inode: "16071", RefCount: "1", @@ -33,22 +33,22 @@ func TestNetTcp_regex(t *testing.T) { }, } - m := NetTcp{} + m := NetTCP{} re := regexp.MustCompile(m.regex()) for _, i := range expected { - have, _ := m.netTcpLine(re, i.Line) + have, _ := m.netTCPLine(re, i.Line) if !reflect.DeepEqual(i.Expected, have) { - t.Errorf("NetTcp Regex is invalid") + t.Errorf("NetTCP Regex is invalid") } } } -func TestNetTcp(t *testing.T) { +func TestNetTCP(t *testing.T) { /* - expected := NetTcp{ + expected := NetTCP{ MemTotal: 15666184, MemFree: 440324, Buffers: 1020128, @@ -93,7 +93,7 @@ func TestNetTcp(t *testing.T) { DirectMap2M: 16039936, } - have, err := FS("fixtures").NewNetTcp() + have, err := FS("fixtures").NewNetTCP() if err != nil { t.Fatal(err) } From bd159863bd21ed749903948ff74cabdfe4cb5568 Mon Sep 17 00:00:00 2001 From: Abhi Yerra Date: Tue, 15 Dec 2015 00:28:48 -0500 Subject: [PATCH 11/11] Another test for net tcp --- net_tcp_test.go | 80 ++++++++++++++++--------------------------------- 1 file changed, 26 insertions(+), 54 deletions(-) diff --git a/net_tcp_test.go b/net_tcp_test.go index cf1ca0868..a71ff0cb8 100644 --- a/net_tcp_test.go +++ b/net_tcp_test.go @@ -31,6 +31,25 @@ func TestNetTCP_regex(t *testing.T) { MemoryAddress: "0000000000000000", }, }, + { + Line: " 8: 260FC90A:01BB AE6857C8:C747 03 00000000:00000000 01:000000DC 00000005 0 0 0 2 0000000000000000", + Expected: NetTCPLine{ + Sl: "8", + LocalAddress: "260FC90A:01BB", + RemoteAddress: "AE6857C8:C747", + St: "03", + TxQueue: "00000000", + RxQueue: "00000000", + Tr: "01", + TmWhen: "000000DC", + Retrnsmt: "00000005", + UID: "0", + Timeout: "0", + Inode: "0", + RefCount: "2", + MemoryAddress: "0000000000000000", + }, + }, } m := NetTCP{} @@ -47,59 +66,12 @@ func TestNetTCP_regex(t *testing.T) { } func TestNetTCP(t *testing.T) { - /* - expected := NetTCP{ - MemTotal: 15666184, - MemFree: 440324, - Buffers: 1020128, - Cached: 12007640, - SwapCached: 0, - Active: 6761276, - Inactive: 6532708, - ActiveAnon: 267256, - InactiveAnon: 268, - ActiveFile: 6494020, - InactiveFile: 6532440, - Unevictable: 0, - Mlocked: 0, - SwapTotal: 0, - SwapFree: 0, - Dirty: 768, - Writeback: 0, - AnonPages: 266216, - Mapped: 44204, - Shmem: 1308, - Slab: 1807264, - SReclaimable: 1738124, - SUnreclaim: 69140, - KernelStack: 1616, - PageTables: 5288, - NFSUnstable: 0, - Bounce: 0, - WritebackTmp: 0, - CommitLimit: 7833092, - CommittedAS: 530844, - VmallocTotal: 34359738367, - VmallocUsed: 36596, - VmallocChunk: 34359637840, - HardwareCorrupted: 0, - AnonHugePages: 12288, - HugePagesTotal: 0, - HugePagesFree: 0, - HugePagesRsvd: 0, - HugePagesSurp: 0, - Hugepagesize: 2048, - DirectMap4k: 91136, - DirectMap2M: 16039936, - } - - have, err := FS("fixtures").NewNetTCP() - if err != nil { - t.Fatal(err) - } + have, err := FS("fixtures").NewNetTCP() + if err != nil { + t.Fatal(err) + } - if !reflect.DeepEqual(have, expected) { - t.Errorf("structs are not equal") - } - */ + if len(have) != 19 { + t.Errorf("incorrect number of NetTCPLine items.") + } }