Add buffer pool stats 89/18989/1
authorOndrej Fabry <ofabry@cisco.com>
Thu, 18 Apr 2019 00:25:34 +0000 (02:25 +0200)
committerOndrej Fabry <ofabry@cisco.com>
Thu, 18 Apr 2019 00:25:34 +0000 (02:25 +0200)
Change-Id: I15d1df825b4d4fc760da83d9c878a621936bb6fa
Signed-off-by: Ondrej Fabry <ofabry@cisco.com>
api/stats.go
core/stats.go
examples/stats-api/stats_api.go

index 9c3a16f..0bf9908 100644 (file)
@@ -68,10 +68,24 @@ type ErrorCounter struct {
        Value       uint64
 }
 
+// BufferStats represents statistics per buffer pool.
+type BufferStats struct {
+       Buffer map[string]BufferPool
+}
+
+// BufferPool represents buffer pool.
+type BufferPool struct {
+       PoolName  string
+       Cached    float64
+       Used      float64
+       Available float64
+}
+
 // StatsProvider provides the methods for getting statistics.
 type StatsProvider interface {
        GetSystemStats() (*SystemStats, error)
        GetNodeStats() (*NodeStats, error)
        GetInterfaceStats() (*InterfaceStats, error)
        GetErrorStats(names ...string) (*ErrorStats, error)
+       GetBufferStats() (*BufferStats, error)
 }
index 48b516c..e935888 100644 (file)
@@ -2,6 +2,7 @@ package core
 
 import (
        "fmt"
+       "path"
        "strings"
        "sync/atomic"
 
@@ -10,8 +11,6 @@ import (
 )
 
 const (
-       CounterStatsPrefix = "/err/"
-
        SystemStatsPrefix          = "/sys/"
        SystemStats_VectorRate     = SystemStatsPrefix + "vector_rate"
        SystemStats_InputRate      = SystemStatsPrefix + "input_rate"
@@ -26,6 +25,13 @@ const (
        NodeStats_Calls    = NodeStatsPrefix + "calls"
        NodeStats_Suspends = NodeStatsPrefix + "suspends"
 
+       BufferStatsPrefix     = "/buffer-pools/"
+       BufferStats_Cached    = "cached"
+       BufferStats_Used      = "used"
+       BufferStats_Available = "available"
+
+       CounterStatsPrefix = "/err/"
+
        InterfaceStatsPrefix         = "/if/"
        InterfaceStats_Names         = InterfaceStatsPrefix + "names"
        InterfaceStats_Drops         = InterfaceStatsPrefix + "drops"
@@ -45,12 +51,13 @@ const (
        InterfaceStats_TxMulticast   = InterfaceStatsPrefix + "tx-multicast"
        InterfaceStats_TxBroadcast   = InterfaceStatsPrefix + "tx-broadcast"
 
-       NetworkStatsPrefix = "/net/"
        // TODO: network stats
+       NetworkStatsPrefix     = "/net/"
        NetworkStats_RouteTo   = NetworkStatsPrefix + "route/to"
        NetworkStats_RouteVia  = NetworkStatsPrefix + "route/via"
        NetworkStats_MRoute    = NetworkStatsPrefix + "mroute"
        NetworkStats_Adjacency = NetworkStatsPrefix + "adjacency"
+       NetworkStats_Punt      = NetworkStatsPrefix + "punt"
 )
 
 type StatsConnection struct {
@@ -188,6 +195,7 @@ func (c *StatsConnection) GetNodeStats() (*api.NodeStats, error) {
        }
 
        nodeStats := &api.NodeStats{}
+
        var setPerNode = func(perNode []uint64, fn func(c *api.NodeCounters, v uint64)) {
                if nodeStats.Nodes == nil {
                        nodeStats.Nodes = make([]api.NodeCounters, len(perNode))
@@ -387,6 +395,42 @@ func (c *StatsConnection) GetInterfaceStats() (*api.InterfaceStats, error) {
        return ifStats, nil
 }
 
+// GetBufferStats retrieves VPP buffer pools stats.
+func (c *StatsConnection) GetBufferStats() (*api.BufferStats, error) {
+       stats, err := c.statsClient.DumpStats(BufferStatsPrefix)
+       if err != nil {
+               return nil, err
+       }
+
+       bufStats := &api.BufferStats{
+               Buffer: map[string]api.BufferPool{},
+       }
+
+       for _, stat := range stats {
+               d, f := path.Split(stat.Name)
+               d = strings.TrimSuffix(d, "/")
+
+               name := strings.TrimPrefix(d, BufferStatsPrefix)
+               b, ok := bufStats.Buffer[name]
+               if !ok {
+                       b.PoolName = name
+               }
+
+               switch f {
+               case BufferStats_Cached:
+                       b.Cached = scalarStatToFloat64(stat.Data)
+               case BufferStats_Used:
+                       b.Used = scalarStatToFloat64(stat.Data)
+               case BufferStats_Available:
+                       b.Available = scalarStatToFloat64(stat.Data)
+               }
+
+               bufStats.Buffer[name] = b
+       }
+
+       return bufStats, nil
+}
+
 func scalarStatToFloat64(stat adapter.Stat) float64 {
        if s, ok := stat.(adapter.ScalarStat); ok {
                return float64(s)
index 9808243..f74a055 100644 (file)
@@ -40,7 +40,7 @@ var (
 
 func init() {
        flag.Usage = func() {
-               fmt.Fprintf(os.Stderr, "%s: usage [ls|dump|errors|interfaces|nodes|system] <patterns>...\n", os.Args[0])
+               fmt.Fprintf(os.Stderr, "%s: usage [ls|dump|errors|interfaces|nodes|system|buffers] <patterns>...\n", os.Args[0])
                flag.PrintDefaults()
                os.Exit(1)
        }
@@ -52,7 +52,7 @@ func main() {
 
        cmd := flag.Arg(0)
        switch cmd {
-       case "", "ls", "dump", "errors", "interfaces", "nodes", "system":
+       case "", "ls", "dump", "errors", "interfaces", "nodes", "system", "buffers":
        default:
                flag.Usage()
        }
@@ -79,16 +79,21 @@ func main() {
                        log.Fatalln("getting system stats failed:", err)
                }
                fmt.Printf("System stats: %+v\n", stats)
+
        case "nodes":
                fmt.Println("Listing node stats..")
                stats, err := c.GetNodeStats()
                if err != nil {
                        log.Fatalln("getting node stats failed:", err)
                }
-               for _, iface := range stats.Nodes {
-                       fmt.Printf(" - %+v\n", iface)
+               for _, node := range stats.Nodes {
+                       if node.Calls == 0 && node.Suspends == 0 && node.Clocks == 0 && node.Vectors == 0 && skipZeros {
+                               continue
+                       }
+                       fmt.Printf(" - %+v\n", node)
                }
                fmt.Printf("Listed %d node counters\n", len(stats.Nodes))
+
        case "interfaces":
                fmt.Println("Listing interface stats..")
                stats, err := c.GetInterfaceStats()
@@ -99,6 +104,7 @@ func main() {
                        fmt.Printf(" - %+v\n", iface)
                }
                fmt.Printf("Listed %d interface counters\n", len(stats.Interfaces))
+
        case "errors":
                fmt.Printf("Listing error stats.. %s\n", strings.Join(patterns, " "))
                stats, err := c.GetErrorStats(patterns...)
@@ -114,6 +120,14 @@ func main() {
                        n++
                }
                fmt.Printf("Listed %d (%d) error counters\n", n, len(stats.Errors))
+
+       case "buffers":
+               stats, err := c.GetBufferStats()
+               if err != nil {
+                       log.Fatalln("getting buffer stats failed:", err)
+               }
+               fmt.Printf("Buffer stats: %+v\n", stats)
+
        case "dump":
                dumpStats(client, patterns, skipZeros)
        default: