From b74e3b37479a7fa763bed1f2c76de612ee51dcbc Mon Sep 17 00:00:00 2001 From: Vladimir Lavor Date: Thu, 29 Oct 2020 12:56:24 +0100 Subject: [PATCH] Stats API: added GetMemory() Retrieved numbers relate to the statseg heap. Change-Id: I72750183db3524481918c71c993b39e65c28ddb6 Signed-off-by: Vladimir Lavor --- api/stats.go | 7 +++++++ core/stats.go | 27 +++++++++++++++++++++++++++ examples/multi-vpp/multi_vpp.go | 8 ++++---- examples/simple-client/simple_client.go | 8 ++++---- examples/stats-client/stats_api.go | 9 ++++++++- examples/stream-client/stream_client.go | 8 ++++---- proxy/client.go | 10 ++++++++++ proxy/server.go | 4 ++++ 8 files changed, 68 insertions(+), 13 deletions(-) diff --git a/api/stats.go b/api/stats.go index 2850b5f..9e1ba75 100644 --- a/api/stats.go +++ b/api/stats.go @@ -21,6 +21,7 @@ type StatsProvider interface { GetInterfaceStats(*InterfaceStats) error GetErrorStats(*ErrorStats) error GetBufferStats(*BufferStats) error + GetMemoryStats(*MemoryStats) error } // SystemStats represents global system statistics. @@ -113,3 +114,9 @@ type BufferPool struct { Used float64 Available float64 } + +// MemoryStats represents memory stats segment counters. +type MemoryStats struct { + Total float64 + Used float64 +} diff --git a/core/stats.go b/core/stats.go index cd93cc1..f2da494 100644 --- a/core/stats.go +++ b/core/stats.go @@ -39,6 +39,10 @@ const ( CounterStatsPrefix = "/err/" + MemoryStatPrefix = "/mem/statseg" + MemoryStats_Total = "total" + MemoryStats_Used = "used" + InterfaceStatsPrefix = "/if/" InterfaceStats_Names = InterfaceStatsPrefix + "names" InterfaceStats_Drops = InterfaceStatsPrefix + "drops" @@ -80,6 +84,7 @@ type StatsConnection struct { ifaceStatsData *adapter.StatDir sysStatsData *adapter.StatDir bufStatsData *adapter.StatDir + memStatsData *adapter.StatDir } func newStatsConnection(stats adapter.StatsAPI) *StatsConnection { @@ -471,3 +476,25 @@ func (c *StatsConnection) GetBufferStats(bufStats *api.BufferStats) (err error) return nil } + +func (c *StatsConnection) GetMemoryStats(memStats *api.MemoryStats) (err error) { + if err := c.updateStats(&c.memStatsData, MemoryStatPrefix); err != nil { + return err + } + + for _, stat := range c.memStatsData.Entries { + _, f := path.Split(string(stat.Name)) + var val float64 + m, ok := stat.Data.(adapter.ScalarStat) + if ok { + val = float64(m) + } + switch f { + case MemoryStats_Total: + memStats.Total = val + case MemoryStats_Used: + memStats.Used = val + } + } + return nil +} diff --git a/examples/multi-vpp/multi_vpp.go b/examples/multi-vpp/multi_vpp.go index c42f802..b207ae4 100644 --- a/examples/multi-vpp/multi_vpp.go +++ b/examples/multi-vpp/multi_vpp.go @@ -41,15 +41,15 @@ var ( statsSockAddrVpp2 = flag.String("stats-sock-2", statsclient.DefaultSocketName, "Path to stats socket file of the VPP2") ) -var Errors []error +var errors []error func main() { flag.Parse() fmt.Println("Starting multi-vpp example") defer func() { - if len(Errors) > 0 { - logInfo("Finished with %d errors\n", len(Errors)) + if len(errors) > 0 { + logInfo("Finished with %d errors\n", len(errors)) os.Exit(1) } else { logInfo("Finished successfully\n") @@ -347,5 +347,5 @@ func logInfo(format string, a ...interface{}) { // logError prints error message func logError(err error, msg string) { fmt.Printf("[ERROR]: %s: %v\n", msg, err) - Errors = append(Errors, err) + errors = append(errors, err) } diff --git a/examples/simple-client/simple_client.go b/examples/simple-client/simple_client.go index 10a0ea6..3be2447 100644 --- a/examples/simple-client/simple_client.go +++ b/examples/simple-client/simple_client.go @@ -74,8 +74,8 @@ func main() { // process errors encountered during the example defer func() { - if len(Errors) > 0 { - fmt.Printf("finished with %d errors\n", len(Errors)) + if len(errors) > 0 { + fmt.Printf("finished with %d errors\n", len(errors)) os.Exit(1) } else { fmt.Println("finished successfully") @@ -302,9 +302,9 @@ func marshal(v interface{}) { fmt.Printf("JSON: %s\n", b) } -var Errors []error +var errors []error func logError(err error, msg string) { fmt.Printf("ERROR: %s: %v\n", msg, err) - Errors = append(Errors, err) + errors = append(errors, err) } diff --git a/examples/stats-client/stats_api.go b/examples/stats-client/stats_api.go index 288caea..b1846a6 100644 --- a/examples/stats-client/stats_api.go +++ b/examples/stats-client/stats_api.go @@ -43,7 +43,7 @@ var ( func init() { flag.Usage = func() { - fmt.Fprintf(os.Stderr, "%s: usage [ls|dump|poll|errors|interfaces|nodes|system|buffers] ...\n", os.Args[0]) + fmt.Fprintf(os.Stderr, "%s: usage [ls|dump|poll|errors|interfaces|nodes|system|buffers|memory] ...\n", os.Args[0]) flag.PrintDefaults() os.Exit(1) } @@ -129,6 +129,13 @@ func main() { } fmt.Printf("Buffer stats: %+v\n", stats) + case "memory": + stats := new(api.MemoryStats) + if err := c.GetMemoryStats(stats); err != nil { + log.Fatalln("getting memory stats failed:", err) + } + fmt.Printf("Memory stats: %+v\n", stats) + case "dump": fmt.Printf("Dumping stats.. %s\n", strings.Join(patterns, " ")) diff --git a/examples/stream-client/stream_client.go b/examples/stream-client/stream_client.go index fadfe23..f4af859 100644 --- a/examples/stream-client/stream_client.go +++ b/examples/stream-client/stream_client.go @@ -76,8 +76,8 @@ func main() { // process errors encountered during the example defer func() { - if len(Errors) > 0 { - fmt.Printf("finished with %d errors\n", len(Errors)) + if len(errors) > 0 { + fmt.Printf("finished with %d errors\n", len(errors)) os.Exit(1) } else { fmt.Println("finished successfully") @@ -294,9 +294,9 @@ Loop: fmt.Println() } -var Errors []error +var errors []error func logError(err error, msg string) { fmt.Printf("ERROR: %s: %v\n", msg, err) - Errors = append(Errors, err) + errors = append(errors, err) } diff --git a/proxy/client.go b/proxy/client.go index 6f29c71..aea9a94 100644 --- a/proxy/client.go +++ b/proxy/client.go @@ -117,6 +117,16 @@ func (s *StatsClient) GetBufferStats(bufStats *api.BufferStats) error { return nil } +func (s *StatsClient) GetMemoryStats(memStats *api.MemoryStats) error { + req := StatsRequest{StatsType: "memory"} + resp := StatsResponse{MemStats: new(api.MemoryStats)} + if err := s.rpc.Call("StatsRPC.GetStats", req, &resp); err != nil { + return err + } + *memStats = *resp.MemStats + return nil +} + type BinapiClient struct { rpc *rpc.Client timeout time.Duration diff --git a/proxy/server.go b/proxy/server.go index 50a0077..21d8e1b 100644 --- a/proxy/server.go +++ b/proxy/server.go @@ -55,6 +55,7 @@ type StatsResponse struct { IfaceStats *api.InterfaceStats ErrStats *api.ErrorStats BufStats *api.BufferStats + MemStats *api.MemoryStats } // StatsRPC is a RPC server for proxying client request to api.StatsProvider. @@ -200,6 +201,9 @@ func (s *StatsRPC) GetStats(req StatsRequest, resp *StatsResponse) error { case "buffer": resp.BufStats = new(api.BufferStats) return s.statsConn.GetBufferStats(resp.BufStats) + case "memory": + resp.MemStats = new(api.MemoryStats) + return s.statsConn.GetMemoryStats(resp.MemStats) default: return fmt.Errorf("unknown stats type: %s", req.StatsType) } -- 2.16.6