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