summaryrefslogtreecommitdiffstats
path: root/examples/cmd
diff options
context:
space:
mode:
authorOndrej Fabry <ofabry@cisco.com>2018-11-17 03:06:24 +0100
committerOndrej Fabry <ofabry@cisco.com>2018-11-17 03:06:24 +0100
commit6f8fd1541b33f280854e3d8341b8a342aca03fc9 (patch)
tree88dc9ee16c39f7d0b62bacfbfdc57f92569a31ed /examples/cmd
parente3a361295d952bb83dd81755677362c392718ccc (diff)
Improve Stats API example and add README
Change-Id: If25c7d05c42fbed6c43558f84fb86aca6c5af4d5 Signed-off-by: Ondrej Fabry <ofabry@cisco.com>
Diffstat (limited to 'examples/cmd')
-rw-r--r--examples/cmd/stats-api/README.md68
-rw-r--r--examples/cmd/stats-api/stats_api.go108
2 files changed, 159 insertions, 17 deletions
diff --git a/examples/cmd/stats-api/README.md b/examples/cmd/stats-api/README.md
new file mode 100644
index 0000000..44a1663
--- /dev/null
+++ b/examples/cmd/stats-api/README.md
@@ -0,0 +1,68 @@
+# Stats API Example
+
+This example demonstrates how to retrieve statistics from VPP using [the new Stats API](https://github.com/FDio/vpp/blob/master/src/vpp/stats/stats.md).
+
+## Requirements
+
+The following requirements are required to run this example:
+
+- install **VPP 18.10+**
+- enable stats in VPP:
+
+ ```sh
+ statseg {
+ default
+ }
+ ```
+ > The [default socket](https://wiki.fd.io/view/VPP/Command-line_Arguments#.22statseg.22_parameters) is located at `/run/vpp/stats.sock`.
+- run the VPP, ideally with some traffic
+
+## Running example
+
+First build the example: `go build git.fd.io/govpp.git/examples/cmd/stats-api`.
+
+Use commands `ls` and `dump` to list and dump statistics. Optionally, patterns can be used to filter the results.
+
+### List stats matching patterns `/sys/` and `/if/`
+```
+$ ./stats-api ls /sys/ /if/
+Listing stats.. /sys/ /if/
+ - /sys/vector_rate
+ - /sys/input_rate
+ - /sys/last_update
+ - /sys/last_stats_clear
+ - /sys/heartbeat
+ - /sys/node/clocks
+ - /sys/node/vectors
+ - /sys/node/calls
+ - /sys/node/suspends
+ - /if/drops
+ - /if/punt
+ - /if/ip4
+ - /if/ip6
+ - /if/rx-no-buf
+ - /if/rx-miss
+ - /if/rx-error
+ - /if/tx-error
+ - /if/rx
+ - /if/rx-unicast
+ - /if/rx-multicast
+ - /if/rx-broadcast
+ - /if/tx
+ - /if/tx-unicast-miss
+ - /if/tx-multicast
+ - /if/tx-broadcast
+Listed 25 stats
+```
+
+### Dump all stats with their types and values
+```
+$ ./stats-api dump
+Dumping stats..
+ - /sys/last_update ScalarIndex 10408
+ - /sys/heartbeat ScalarIndex 1041
+ - /err/ip4-icmp-error/unknown type ErrorIndex 5
+ - /net/route/to CombinedCounterVector [[{Packets:0 Bytes:0} {Packets:0 Bytes:0} {Packets:0 Bytes:0} {Packets:0 Bytes:0} {Packets:0 Bytes:0} {Packets:0 Bytes:0} {Packets:0 Bytes:0} {Packets:0 Bytes:0} {Packets:0 Bytes:0} {Packets:0 Bytes:0} {Packets:0 Bytes:0} {Packets:0 Bytes:0} {Packets:0 Bytes:0} {Packets:5 Bytes:420}]]
+ - /if/drops SimpleCounterVector [[0 5 5]]
+Dumped 5 (2798) stats
+```
diff --git a/examples/cmd/stats-api/stats_api.go b/examples/cmd/stats-api/stats_api.go
index 74454ab..bded8fd 100644
--- a/examples/cmd/stats-api/stats_api.go
+++ b/examples/cmd/stats-api/stats_api.go
@@ -15,29 +15,73 @@
package main
import (
+ "flag"
"fmt"
"log"
+ "os"
+ "strings"
"git.fd.io/govpp.git/adapter"
"git.fd.io/govpp.git/adapter/vppapiclient"
)
-// This example shows how to work with VPP's new stats API.
+// ------------------------------------------------------------------
+// Example - Stats API
+// ------------------------------------------------------------------
+// The example stats_api demonstrates how to retrieve stats
+// from the VPP using the new stats API.
+// ------------------------------------------------------------------
+
+var (
+ statsSocket = flag.String("socket", vppapiclient.DefaultStatSocket, "VPP stats segment socket")
+ skipZeros = flag.Bool("skipzero", true, "Skip stats with zero values")
+)
+
+func init() {
+ flag.Usage = func() {
+ fmt.Fprintf(os.Stderr, "%s: usage [ls|dump] <patterns>...\n", os.Args[0])
+ flag.PrintDefaults()
+ os.Exit(1)
+ }
+}
func main() {
- fmt.Println("Starting VPP stats API example..")
+ flag.Parse()
+
+ cmd := flag.Arg(0)
+
+ switch cmd {
+ case "", "ls", "dump":
+ default:
+ flag.Usage()
+ }
+
+ var patterns []string
+ if flag.NArg() > 0 {
+ patterns = flag.Args()[1:]
+ }
+
+ client := vppapiclient.NewStatClient(*statsSocket)
- client := vppapiclient.NewStatClient(vppapiclient.DefaultStatSocket)
+ fmt.Printf("Connecting to stats socket: %s\n", *statsSocket)
- // connect to stats API
if err := client.Connect(); err != nil {
- log.Fatalln("connecting client failed:", err)
+ log.Fatalln("Connecting failed:", err)
}
defer client.Disconnect()
- // list stats by patterns
- // you can omit parameters to list all stats
- list, err := client.ListStats("/if", "/sys")
+ switch cmd {
+ case "dump":
+ dumpStats(client, patterns)
+ default:
+ listStats(client, patterns)
+ }
+}
+
+func listStats(client adapter.StatsAPI, patterns []string) {
+ fmt.Printf("Listing stats.. %s\n", strings.Join(patterns, " "))
+
+ list, err := client.ListStats(patterns...)
if err != nil {
log.Fatalln("listing stats failed:", err)
}
@@ -45,22 +89,52 @@ func main() {
for _, stat := range list {
fmt.Printf(" - %v\n", stat)
}
- fmt.Printf("listed %d stats\n", len(list))
- // dump stats by patterns to retrieve stats with the stats data
- stats, err := client.DumpStats()
+ fmt.Printf("Listed %d stats\n", len(list))
+}
+
+func dumpStats(client adapter.StatsAPI, patterns []string) {
+ fmt.Printf("Dumping stats.. %s\n", strings.Join(patterns, " "))
+
+ stats, err := client.DumpStats(patterns...)
if err != nil {
log.Fatalln("dumping stats failed:", err)
}
+ n := 0
for _, stat := range stats {
- switch data := stat.Data.(type) {
- case adapter.ErrorStat:
- if data == 0 {
- // skip printing errors with 0 value
- continue
- }
+ if isZero(stat.Data) && *skipZeros {
+ continue
}
fmt.Printf(" - %-25s %25v %+v\n", stat.Name, stat.Type, stat.Data)
+ n++
+ }
+
+ fmt.Printf("Dumped %d (%d) stats\n", n, len(stats))
+}
+
+func isZero(stat adapter.Stat) bool {
+ switch s := stat.(type) {
+ case adapter.ScalarStat:
+ return s == 0
+ case adapter.ErrorStat:
+ return s == 0
+ case adapter.SimpleCounterStat:
+ for _, ss := range s {
+ for _, sss := range ss {
+ if sss != 0 {
+ return false
+ }
+ }
+ }
+ case adapter.CombinedCounterStat:
+ for _, ss := range s {
+ for _, sss := range ss {
+ if sss.Bytes != 0 || sss.Packets != 0 {
+ return false
+ }
+ }
+ }
}
+ return true
}