From 5f72f865f7449d11c1b9277172b2f4428743604f Mon Sep 17 00:00:00 2001 From: Nick Cabatoff Date: Mon, 3 Sep 2018 14:30:43 -0400 Subject: [PATCH] Make states metric report on thread counts instead of proc counts. Fix tests broken when adding wchan feature. --- proc/base_test.go | 4 +++- proc/grouper_test.go | 40 ++++++++++++++++++++-------------------- proc/read.go | 6 +++++- proc/tracker.go | 1 + proc/tracker_test.go | 36 ++++++++++++++++++------------------ 5 files changed, 47 insertions(+), 40 deletions(-) diff --git a/proc/base_test.go b/proc/base_test.go index 5711415..976f9a1 100644 --- a/proc/base_test.go +++ b/proc/base_test.go @@ -7,6 +7,8 @@ import ( common "github.com/ncabatoff/process-exporter" ) +type msi map[string]int + // procinfo reads the ProcIdInfo for a proc and returns it or a zero value plus // an error. func procinfo(p Proc) (IDInfo, error) { @@ -98,6 +100,6 @@ func piinfost(pid int, name string, c Counts, m Memory, f Filedesc, t int, s Sta return IDInfo{ ID: id, Static: static, - Metrics: Metrics{c, m, f, uint64(t), s}, + Metrics: Metrics{c, m, f, uint64(t), s, ""}, } } diff --git a/proc/grouper_test.go b/proc/grouper_test.go index 5084889..758dc27 100644 --- a/proc/grouper_test.go +++ b/proc/grouper_test.go @@ -51,9 +51,9 @@ func TestGrouperBasic(t *testing.T) { Filedesc{40, 400}, 3, States{Waiting: 1}), }, GroupByName{ - "g1": Group{Counts{}, States{Other: 1}, 1, Memory{7, 8, 0}, starttime, + "g1": Group{Counts{}, States{Other: 1}, msi{}, 1, Memory{7, 8, 0}, starttime, 4, 0.01, 2, nil}, - "g2": Group{Counts{}, States{Waiting: 1}, 1, Memory{8, 9, 0}, starttime, + "g2": Group{Counts{}, States{Waiting: 1}, msi{}, 1, Memory{8, 9, 0}, starttime, 40, 0.1, 3, nil}, }, }, @@ -65,9 +65,9 @@ func TestGrouperBasic(t *testing.T) { Memory{9, 8, 0}, Filedesc{400, 400}, 2, States{Running: 1}), }, GroupByName{ - "g1": Group{Counts{1, 1, 1, 1, 1, 1, 0, 0}, States{Zombie: 1}, 1, + "g1": Group{Counts{1, 1, 1, 1, 1, 1, 0, 0}, States{Zombie: 1}, msi{}, 1, Memory{6, 7, 0}, starttime, 100, 0.25, 4, nil}, - "g2": Group{Counts{2, 2, 2, 2, 2, 2, 0, 0}, States{Running: 1}, 1, + "g2": Group{Counts{2, 2, 2, 2, 2, 2, 0, 0}, States{Running: 1}, msi{}, 1, Memory{9, 8, 0}, starttime, 400, 1, 2, nil}, }, }, @@ -98,7 +98,7 @@ func TestGrouperProcJoin(t *testing.T) { piinfo(p1, n1, Counts{1, 2, 3, 4, 5, 6, 0, 0}, Memory{3, 4, 0}, Filedesc{4, 400}, 2), }, GroupByName{ - "g1": Group{Counts{}, States{}, 1, Memory{3, 4, 0}, starttime, 4, 0.01, 2, nil}, + "g1": Group{Counts{}, States{}, msi{}, 1, Memory{3, 4, 0}, starttime, 4, 0.01, 2, nil}, }, }, { // The counts for pid2 won't be factored into the total yet because we only add @@ -111,7 +111,7 @@ func TestGrouperProcJoin(t *testing.T) { Memory{1, 2, 0}, Filedesc{40, 400}, 3, States{Sleeping: 1}), }, GroupByName{ - "g1": Group{Counts{2, 2, 2, 2, 2, 2, 0, 0}, States{Running: 1, Sleeping: 1}, 2, + "g1": Group{Counts{2, 2, 2, 2, 2, 2, 0, 0}, States{Running: 1, Sleeping: 1}, msi{}, 2, Memory{4, 6, 0}, starttime, 44, 0.1, 5, nil}, }, }, { @@ -122,7 +122,7 @@ func TestGrouperProcJoin(t *testing.T) { Memory{2, 4, 0}, Filedesc{40, 400}, 3, States{Running: 1}), }, GroupByName{ - "g1": Group{Counts{4, 4, 4, 4, 4, 4, 0, 0}, States{Running: 2}, 2, + "g1": Group{Counts{4, 4, 4, 4, 4, 4, 0, 0}, States{Running: 2}, msi{}, 2, Memory{3, 9, 0}, starttime, 44, 0.1, 5, nil}, }, }, @@ -154,19 +154,19 @@ func TestGrouperNonDecreasing(t *testing.T) { piinfo(p2, n2, Counts{1, 1, 1, 1, 1, 1, 0, 0}, Memory{1, 2, 0}, Filedesc{40, 400}, 3), }, GroupByName{ - "g1": Group{Counts{}, States{}, 2, Memory{4, 6, 0}, starttime, 44, 0.1, 5, nil}, + "g1": Group{Counts{}, States{}, msi{}, 2, Memory{4, 6, 0}, starttime, 44, 0.1, 5, nil}, }, }, { []IDInfo{ piinfo(p1, n1, Counts{4, 5, 6, 7, 8, 9, 0, 0}, Memory{1, 5, 0}, Filedesc{4, 400}, 2), }, GroupByName{ - "g1": Group{Counts{1, 1, 1, 1, 1, 1, 0, 0}, States{}, 1, Memory{1, 5, 0}, starttime, 4, 0.01, 2, nil}, + "g1": Group{Counts{1, 1, 1, 1, 1, 1, 0, 0}, States{}, msi{}, 1, Memory{1, 5, 0}, starttime, 4, 0.01, 2, nil}, }, }, { []IDInfo{}, GroupByName{ - "g1": Group{Counts{1, 1, 1, 1, 1, 1, 0, 0}, States{}, 0, Memory{}, time.Time{}, 0, 0, 0, nil}, + "g1": Group{Counts{1, 1, 1, 1, 1, 1, 0, 0}, States{}, nil, 0, Memory{}, time.Time{}, 0, 0, 0, nil}, }, }, } @@ -189,34 +189,34 @@ func TestGrouperThreads(t *testing.T) { }{ { piinfot(p, n, Counts{}, Memory{}, Filedesc{1, 1}, []Thread{ - {ThreadID(ID{p, 0}), "t1", Counts{1, 2, 3, 4, 5, 6, 0, 0}}, - {ThreadID(ID{p + 1, 0}), "t2", Counts{1, 1, 1, 1, 1, 1, 0, 0}}, + {ThreadID(ID{p, 0}), "t1", Counts{1, 2, 3, 4, 5, 6, 0, 0}, "", States{}}, + {ThreadID(ID{p + 1, 0}), "t2", Counts{1, 1, 1, 1, 1, 1, 0, 0}, "", States{}}, }), GroupByName{ - "g1": Group{Counts{}, States{}, 1, Memory{}, tm, 1, 1, 2, []Threads{ + "g1": Group{Counts{}, States{}, msi{}, 1, Memory{}, tm, 1, 1, 2, []Threads{ Threads{"t1", 1, Counts{}}, Threads{"t2", 1, Counts{}}, }}, }, }, { piinfot(p, n, Counts{}, Memory{}, Filedesc{1, 1}, []Thread{ - {ThreadID(ID{p, 0}), "t1", Counts{2, 3, 4, 5, 6, 7, 0, 0}}, - {ThreadID(ID{p + 1, 0}), "t2", Counts{2, 2, 2, 2, 2, 2, 0, 0}}, - {ThreadID(ID{p + 2, 0}), "t2", Counts{1, 1, 1, 1, 1, 1, 0, 0}}, + {ThreadID(ID{p, 0}), "t1", Counts{2, 3, 4, 5, 6, 7, 0, 0}, "", States{}}, + {ThreadID(ID{p + 1, 0}), "t2", Counts{2, 2, 2, 2, 2, 2, 0, 0}, "", States{}}, + {ThreadID(ID{p + 2, 0}), "t2", Counts{1, 1, 1, 1, 1, 1, 0, 0}, "", States{}}, }), GroupByName{ - "g1": Group{Counts{}, States{}, 1, Memory{}, tm, 1, 1, 3, []Threads{ + "g1": Group{Counts{}, States{}, msi{}, 1, Memory{}, tm, 1, 1, 3, []Threads{ Threads{"t1", 1, Counts{1, 1, 1, 1, 1, 1, 0, 0}}, Threads{"t2", 2, Counts{1, 1, 1, 1, 1, 1, 0, 0}}, }}, }, }, { piinfot(p, n, Counts{}, Memory{}, Filedesc{1, 1}, []Thread{ - {ThreadID(ID{p + 1, 0}), "t2", Counts{4, 4, 4, 4, 4, 4, 0, 0}}, - {ThreadID(ID{p + 2, 0}), "t2", Counts{2, 3, 4, 5, 6, 7, 0, 0}}, + {ThreadID(ID{p + 1, 0}), "t2", Counts{4, 4, 4, 4, 4, 4, 0, 0}, "", States{}}, + {ThreadID(ID{p + 2, 0}), "t2", Counts{2, 3, 4, 5, 6, 7, 0, 0}, "", States{}}, }), GroupByName{ - "g1": Group{Counts{}, States{}, 1, Memory{}, tm, 1, 1, 2, []Threads{ + "g1": Group{Counts{}, States{}, msi{}, 1, Memory{}, tm, 1, 1, 2, []Threads{ Threads{"t2", 2, Counts{4, 5, 6, 7, 8, 9, 0, 0}}, }}, }, diff --git a/proc/read.go b/proc/read.go index 5db2bfd..d5e5b8a 100644 --- a/proc/read.go +++ b/proc/read.go @@ -62,6 +62,7 @@ type ( Limit uint64 } + // States counts how many threads are in each state. States struct { Running int Sleeping int @@ -80,12 +81,13 @@ type ( Wchan string } - // Thread contains the name and counts for a thread. + // Thread contains per-thread data. Thread struct { ThreadID ThreadName string Counts Wchan string + States } // IDInfo groups all info for a single process. @@ -514,12 +516,14 @@ func (p proc) GetThreads() ([]Thread, error) { } wchan, _ := iter.GetWchan() + states, _ := iter.GetStates() threads = append(threads, Thread{ ThreadID: ThreadID(id), ThreadName: static.Name, Counts: counts, Wchan: wchan, + States: states, }) } err = iter.Close() diff --git a/proc/tracker.go b/proc/tracker.go index c0d69d5..06d444f 100644 --- a/proc/tracker.go +++ b/proc/tracker.go @@ -244,6 +244,7 @@ func (t *Tracker) handleProc(proc Proc, updateTime time.Time) (*IDInfo, CollectE for _, thread := range threads { metrics.Counts.CtxSwitchNonvoluntary += thread.Counts.CtxSwitchNonvoluntary metrics.Counts.CtxSwitchVoluntary += thread.Counts.CtxSwitchVoluntary + metrics.States.Add(thread.States) } } diff --git a/proc/tracker_test.go b/proc/tracker_test.go index 4ee5d9f..e28a148 100644 --- a/proc/tracker_test.go +++ b/proc/tracker_test.go @@ -22,17 +22,17 @@ func TestTrackerBasic(t *testing.T) { }{ { []IDInfo{newProcStart(p1, n1, 1), newProcStart(p3, n3, 1)}, - []Update{{GroupName: n1, Start: t1}}, + []Update{{GroupName: n1, Start: t1, Wchans: msi{}}}, }, { // p3 (ignored) has exited and p2 has appeared []IDInfo{newProcStart(p1, n1, 1), newProcStart(p2, n2, 2)}, - []Update{{GroupName: n1, Start: t1}, {GroupName: n2, Start: t2}}, + []Update{{GroupName: n1, Start: t1, Wchans: msi{}}, {GroupName: n2, Start: t2, Wchans: msi{}}}, }, { // p1 has exited and a new proc with a new name has taken its pid []IDInfo{newProcStart(p1, n4, 3), newProcStart(p2, n2, 2)}, - []Update{{GroupName: n4, Start: t3}, {GroupName: n2, Start: t2}}, + []Update{{GroupName: n4, Start: t3, Wchans: msi{}}, {GroupName: n2, Start: t2, Wchans: msi{}}}, }, } // Note that n3 should not be tracked according to our namer. @@ -66,7 +66,7 @@ func TestTrackerChildren(t *testing.T) { newProcParent(p1, n1, 0), newProcParent(p2, n2, p1), }, - []Update{{GroupName: n2, Start: t1}}, + []Update{{GroupName: n2, Start: t1, Wchans: msi{}}}, }, { []IDInfo{ @@ -74,7 +74,7 @@ func TestTrackerChildren(t *testing.T) { newProcParent(p2, n2, p1), newProcParent(p3, n3, p2), }, - []Update{{GroupName: n2, Start: t1}, {GroupName: n2, Start: t1}}, + []Update{{GroupName: n2, Start: t1, Wchans: msi{}}, {GroupName: n2, Start: t1, Wchans: msi{}}}, }, } // Only n2 and children of n2s should be tracked @@ -102,13 +102,13 @@ func TestTrackerMetrics(t *testing.T) { piinfost(p, n, Counts{1, 2, 3, 4, 5, 6, 0, 0}, Memory{7, 8, 0}, Filedesc{1, 10}, 9, States{Sleeping: 1}), Update{n, Delta{}, Memory{7, 8, 0}, Filedesc{1, 10}, tm, - 9, States{Sleeping: 1}, nil}, + 9, States{Sleeping: 1}, msi{}, nil}, }, { piinfost(p, n, Counts{2, 3, 4, 5, 6, 7, 0, 0}, Memory{1, 2, 0}, Filedesc{2, 20}, 1, States{Running: 1}), Update{n, Delta{1, 1, 1, 1, 1, 1, 0, 0}, Memory{1, 2, 0}, - Filedesc{2, 20}, tm, 1, States{Running: 1}, nil}, + Filedesc{2, 20}, tm, 1, States{Running: 1}, msi{}, nil}, }, } tr := NewTracker(newNamer(n), false, false, false, false) @@ -131,13 +131,13 @@ func TestTrackerThreads(t *testing.T) { }{ { piinfo(p, n, Counts{}, Memory{}, Filedesc{1, 1}, 1), - Update{n, Delta{}, Memory{}, Filedesc{1, 1}, tm, 1, States{}, nil}, + Update{n, Delta{}, Memory{}, Filedesc{1, 1}, tm, 1, States{}, msi{}, nil}, }, { piinfot(p, n, Counts{}, Memory{}, Filedesc{1, 1}, []Thread{ - {ThreadID(ID{p, 0}), "t1", Counts{1, 2, 3, 4, 5, 6, 0, 0}}, - {ThreadID(ID{p + 1, 0}), "t2", Counts{1, 1, 1, 1, 1, 1, 0, 0}}, + {ThreadID(ID{p, 0}), "t1", Counts{1, 2, 3, 4, 5, 6, 0, 0}, "", States{}}, + {ThreadID(ID{p + 1, 0}), "t2", Counts{1, 1, 1, 1, 1, 1, 0, 0}, "", States{}}, }), - Update{n, Delta{}, Memory{}, Filedesc{1, 1}, tm, 2, States{}, + Update{n, Delta{}, Memory{}, Filedesc{1, 1}, tm, 2, States{}, msi{}, []ThreadUpdate{ {"t1", Delta{}}, {"t2", Delta{}}, @@ -145,11 +145,11 @@ func TestTrackerThreads(t *testing.T) { }, }, { piinfot(p, n, Counts{}, Memory{}, Filedesc{1, 1}, []Thread{ - {ThreadID(ID{p, 0}), "t1", Counts{2, 3, 4, 5, 6, 7, 0, 0}}, - {ThreadID(ID{p + 1, 0}), "t2", Counts{2, 2, 2, 2, 2, 2, 0, 0}}, - {ThreadID(ID{p + 2, 0}), "t2", Counts{1, 1, 1, 1, 1, 1, 0, 0}}, + {ThreadID(ID{p, 0}), "t1", Counts{2, 3, 4, 5, 6, 7, 0, 0}, "", States{}}, + {ThreadID(ID{p + 1, 0}), "t2", Counts{2, 2, 2, 2, 2, 2, 0, 0}, "", States{}}, + {ThreadID(ID{p + 2, 0}), "t2", Counts{1, 1, 1, 1, 1, 1, 0, 0}, "", States{}}, }), - Update{n, Delta{}, Memory{}, Filedesc{1, 1}, tm, 3, States{}, + Update{n, Delta{}, Memory{}, Filedesc{1, 1}, tm, 3, States{}, msi{}, []ThreadUpdate{ {"t1", Delta{1, 1, 1, 1, 1, 1, 0, 0}}, {"t2", Delta{1, 1, 1, 1, 1, 1, 0, 0}}, @@ -158,10 +158,10 @@ func TestTrackerThreads(t *testing.T) { }, }, { piinfot(p, n, Counts{}, Memory{}, Filedesc{1, 1}, []Thread{ - {ThreadID(ID{p, 0}), "t1", Counts{2, 3, 4, 5, 6, 7, 0, 0}}, - {ThreadID(ID{p + 2, 0}), "t2", Counts{1, 2, 3, 4, 5, 6, 0, 0}}, + {ThreadID(ID{p, 0}), "t1", Counts{2, 3, 4, 5, 6, 7, 0, 0}, "", States{}}, + {ThreadID(ID{p + 2, 0}), "t2", Counts{1, 2, 3, 4, 5, 6, 0, 0}, "", States{}}, }), - Update{n, Delta{}, Memory{}, Filedesc{1, 1}, tm, 2, States{}, + Update{n, Delta{}, Memory{}, Filedesc{1, 1}, tm, 2, States{}, msi{}, []ThreadUpdate{ {"t1", Delta{}}, {"t2", Delta{0, 1, 2, 3, 4, 5, 0, 0}},