e20ce7a0979e6ec4fc70c705aa73e13502c2847f
[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         goclient    = flag.Bool("goclient", true, "Use pure Go client for stats API")
40         dumpAll     = flag.Bool("all", false, "Dump all stats including ones with zero values")
41 )
42
43 func init() {
44         flag.Usage = func() {
45                 fmt.Fprintf(os.Stderr, "%s: usage [ls|dump|errors|interfaces|nodes|system|buffers] <patterns>...\n", os.Args[0])
46                 flag.PrintDefaults()
47                 os.Exit(1)
48         }
49 }
50
51 func main() {
52         flag.Parse()
53         skipZeros := !*dumpAll
54
55         cmd := flag.Arg(0)
56         switch cmd {
57         case "", "ls", "dump", "errors", "interfaces", "nodes", "system", "buffers":
58         default:
59                 flag.Usage()
60         }
61
62         var patterns []string
63         if flag.NArg() > 0 {
64                 patterns = flag.Args()[1:]
65         }
66
67         var client adapter.StatsAPI
68         if *goclient {
69                 client = statsclient.NewStatsClient(*statsSocket)
70         } else {
71                 client = vppapiclient.NewStatClient(*statsSocket)
72         }
73
74         fmt.Printf("Connecting to stats socket: %s\n", *statsSocket)
75
76         c, err := core.ConnectStats(client)
77         if err != nil {
78                 log.Fatalln("Connecting failed:", err)
79         }
80         defer c.Disconnect()
81
82         switch cmd {
83         case "system":
84                 stats, err := c.GetSystemStats()
85                 if err != nil {
86                         log.Fatalln("getting system stats failed:", err)
87                 }
88                 fmt.Printf("System stats: %+v\n", stats)
89
90         case "nodes":
91                 fmt.Println("Listing node stats..")
92                 stats, err := c.GetNodeStats()
93                 if err != nil {
94                         log.Fatalln("getting node stats failed:", err)
95                 }
96                 for _, node := range stats.Nodes {
97                         if node.Calls == 0 && node.Suspends == 0 && node.Clocks == 0 && node.Vectors == 0 && skipZeros {
98                                 continue
99                         }
100                         fmt.Printf(" - %+v\n", node)
101                 }
102                 fmt.Printf("Listed %d node counters\n", len(stats.Nodes))
103
104         case "interfaces":
105                 fmt.Println("Listing interface stats..")
106                 stats, err := c.GetInterfaceStats()
107                 if err != nil {
108                         log.Fatalln("getting interface stats failed:", err)
109                 }
110                 for _, iface := range stats.Interfaces {
111                         fmt.Printf(" - %+v\n", iface)
112                 }
113                 fmt.Printf("Listed %d interface counters\n", len(stats.Interfaces))
114
115         case "errors":
116                 fmt.Printf("Listing error stats.. %s\n", strings.Join(patterns, " "))
117                 stats, err := c.GetErrorStats(patterns...)
118                 if err != nil {
119                         log.Fatalln("getting error stats failed:", err)
120                 }
121                 n := 0
122                 for _, counter := range stats.Errors {
123                         if counter.Value == 0 && skipZeros {
124                                 continue
125                         }
126                         fmt.Printf(" - %v\n", counter)
127                         n++
128                 }
129                 fmt.Printf("Listed %d (%d) error counters\n", n, len(stats.Errors))
130
131         case "buffers":
132                 stats, err := c.GetBufferStats()
133                 if err != nil {
134                         log.Fatalln("getting buffer stats failed:", err)
135                 }
136                 fmt.Printf("Buffer stats: %+v\n", stats)
137
138         case "dump":
139                 dumpStats(client, patterns, skipZeros)
140         default:
141                 listStats(client, patterns)
142         }
143 }
144
145 func listStats(client adapter.StatsAPI, patterns []string) {
146         fmt.Printf("Listing stats.. %s\n", strings.Join(patterns, " "))
147
148         list, err := client.ListStats(patterns...)
149         if err != nil {
150                 log.Fatalln("listing stats failed:", err)
151         }
152
153         for _, stat := range list {
154                 fmt.Printf(" - %v\n", stat)
155         }
156
157         fmt.Printf("Listed %d stats\n", len(list))
158 }
159
160 func dumpStats(client adapter.StatsAPI, patterns []string, skipZeros bool) {
161         fmt.Printf("Dumping stats.. %s\n", strings.Join(patterns, " "))
162
163         stats, err := client.DumpStats(patterns...)
164         if err != nil {
165                 log.Fatalln("dumping stats failed:", err)
166         }
167
168         n := 0
169         for _, stat := range stats {
170                 if isZero(stat.Data) && skipZeros {
171                         continue
172                 }
173                 fmt.Printf(" - %-25s %25v %+v\n", stat.Name, stat.Type, stat.Data)
174                 n++
175         }
176
177         fmt.Printf("Dumped %d (%d) stats\n", n, len(stats))
178 }
179
180 func isZero(stat adapter.Stat) bool {
181         switch s := stat.(type) {
182         case adapter.ScalarStat:
183                 return s == 0
184         case adapter.ErrorStat:
185                 return s == 0
186         case adapter.SimpleCounterStat:
187                 for _, ss := range s {
188                         for _, sss := range ss {
189                                 if sss != 0 {
190                                         return false
191                                 }
192                         }
193                 }
194                 return true
195         case adapter.CombinedCounterStat:
196                 for _, ss := range s {
197                         for _, sss := range ss {
198                                 if sss.Bytes != 0 || sss.Packets != 0 {
199                                         return false
200                                 }
201                         }
202                 }
203                 return true
204         }
205         return false
206 }