Improvements for binapi-generator and support VPP 19.04 in statsclient
[govpp.git] / examples / stats-api / stats_api.go
1 // Copyright (c) 2018 Cisco and/or its affiliates.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at:
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 package main
16
17 import (
18         "flag"
19         "fmt"
20         "log"
21         "os"
22         "strings"
23
24         "git.fd.io/govpp.git/adapter"
25         "git.fd.io/govpp.git/adapter/statsclient"
26         "git.fd.io/govpp.git/adapter/vppapiclient"
27         "git.fd.io/govpp.git/core"
28 )
29
30 // ------------------------------------------------------------------
31 // Example - Stats API
32 // ------------------------------------------------------------------
33 // The example stats_api demonstrates how to retrieve stats
34 // from the VPP using the new stats API.
35 // ------------------------------------------------------------------
36
37 var (
38         statsSocket = flag.String("socket", adapter.DefaultStatsSocket, "Path to VPP stats socket")
39         dumpAll     = flag.Bool("all", false, "Dump all stats including ones with zero values")
40
41         goclient = flag.Bool("goclient", false, "Use pure Go client for stats API")
42 )
43
44 func init() {
45         flag.Usage = func() {
46                 fmt.Fprintf(os.Stderr, "%s: usage [ls|dump|errors|interfaces|nodes|system|buffers] <patterns>...\n", os.Args[0])
47                 flag.PrintDefaults()
48                 os.Exit(1)
49         }
50 }
51
52 func main() {
53         flag.Parse()
54         skipZeros := !*dumpAll
55
56         cmd := flag.Arg(0)
57         switch cmd {
58         case "", "ls", "dump", "errors", "interfaces", "nodes", "system", "buffers":
59         default:
60                 flag.Usage()
61         }
62
63         var patterns []string
64         if flag.NArg() > 0 {
65                 patterns = flag.Args()[1:]
66         }
67
68         var client adapter.StatsAPI
69         if *goclient {
70                 client = statsclient.NewStatsClient(*statsSocket)
71         } else {
72                 client = vppapiclient.NewStatClient(*statsSocket)
73         }
74
75         fmt.Printf("Connecting to stats socket: %s\n", *statsSocket)
76
77         c, err := core.ConnectStats(client)
78         if err != nil {
79                 log.Fatalln("Connecting failed:", err)
80         }
81         defer c.Disconnect()
82
83         switch cmd {
84         case "system":
85                 stats, err := c.GetSystemStats()
86                 if err != nil {
87                         log.Fatalln("getting system stats failed:", err)
88                 }
89                 fmt.Printf("System stats: %+v\n", stats)
90
91         case "nodes":
92                 fmt.Println("Listing node stats..")
93                 stats, err := c.GetNodeStats()
94                 if err != nil {
95                         log.Fatalln("getting node stats failed:", err)
96                 }
97                 for _, node := range stats.Nodes {
98                         if node.Calls == 0 && node.Suspends == 0 && node.Clocks == 0 && node.Vectors == 0 && skipZeros {
99                                 continue
100                         }
101                         fmt.Printf(" - %+v\n", node)
102                 }
103                 fmt.Printf("Listed %d node counters\n", len(stats.Nodes))
104
105         case "interfaces":
106                 fmt.Println("Listing interface stats..")
107                 stats, err := c.GetInterfaceStats()
108                 if err != nil {
109                         log.Fatalln("getting interface stats failed:", err)
110                 }
111                 for _, iface := range stats.Interfaces {
112                         fmt.Printf(" - %+v\n", iface)
113                 }
114                 fmt.Printf("Listed %d interface counters\n", len(stats.Interfaces))
115
116         case "errors":
117                 fmt.Printf("Listing error stats.. %s\n", strings.Join(patterns, " "))
118                 stats, err := c.GetErrorStats(patterns...)
119                 if err != nil {
120                         log.Fatalln("getting error stats failed:", err)
121                 }
122                 n := 0
123                 for _, counter := range stats.Errors {
124                         if counter.Value == 0 && skipZeros {
125                                 continue
126                         }
127                         fmt.Printf(" - %v\n", counter)
128                         n++
129                 }
130                 fmt.Printf("Listed %d (%d) error counters\n", n, len(stats.Errors))
131
132         case "buffers":
133                 stats, err := c.GetBufferStats()
134                 if err != nil {
135                         log.Fatalln("getting buffer stats failed:", err)
136                 }
137                 fmt.Printf("Buffer stats: %+v\n", stats)
138
139         case "dump":
140                 dumpStats(client, patterns, skipZeros)
141         default:
142                 listStats(client, patterns)
143         }
144 }
145
146 func listStats(client adapter.StatsAPI, patterns []string) {
147         fmt.Printf("Listing stats.. %s\n", strings.Join(patterns, " "))
148
149         list, err := client.ListStats(patterns...)
150         if err != nil {
151                 log.Fatalln("listing stats failed:", err)
152         }
153
154         for _, stat := range list {
155                 fmt.Printf(" - %v\n", stat)
156         }
157
158         fmt.Printf("Listed %d stats\n", len(list))
159 }
160
161 func dumpStats(client adapter.StatsAPI, patterns []string, skipZeros bool) {
162         fmt.Printf("Dumping stats.. %s\n", strings.Join(patterns, " "))
163
164         stats, err := client.DumpStats(patterns...)
165         if err != nil {
166                 log.Fatalln("dumping stats failed:", err)
167         }
168
169         n := 0
170         for _, stat := range stats {
171                 if isZero(stat.Data) && skipZeros {
172                         continue
173                 }
174                 fmt.Printf(" - %-25s %25v %+v\n", stat.Name, stat.Type, stat.Data)
175                 n++
176         }
177
178         fmt.Printf("Dumped %d (%d) stats\n", n, len(stats))
179 }
180
181 func isZero(stat adapter.Stat) bool {
182         switch s := stat.(type) {
183         case adapter.ScalarStat:
184                 return s == 0
185         case adapter.ErrorStat:
186                 return s == 0
187         case adapter.SimpleCounterStat:
188                 for _, ss := range s {
189                         for _, sss := range ss {
190                                 if sss != 0 {
191                                         return false
192                                 }
193                         }
194                 }
195                 return true
196         case adapter.CombinedCounterStat:
197                 for _, ss := range s {
198                         for _, sss := range ss {
199                                 if sss.Bytes != 0 || sss.Packets != 0 {
200                                         return false
201                                 }
202                         }
203                 }
204                 return true
205         }
206         return false
207 }