1 // Copyright (c) 2018 Cisco and/or its affiliates.
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:
7 // http://www.apache.org/licenses/LICENSE-2.0
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.
26 "git.fd.io/govpp.git/adapter"
27 "git.fd.io/govpp.git/adapter/statsclient"
28 "git.fd.io/govpp.git/api"
29 "git.fd.io/govpp.git/core"
32 // ------------------------------------------------------------------
33 // Example - Stats API
34 // ------------------------------------------------------------------
35 // The example stats_api demonstrates how to retrieve stats
36 // from the VPP using the new stats API.
37 // ------------------------------------------------------------------
40 statsSocket = flag.String("socket", statsclient.DefaultSocketName, "Path to VPP stats socket")
41 dumpAll = flag.Bool("all", false, "Dump all stats including ones with zero values")
42 pollPeriod = flag.Duration("period", time.Second*5, "Polling interval period")
43 async = flag.Bool("async", false, "Use asynchronous connection")
48 fmt.Fprintf(os.Stderr, "%s: usage [ls|dump|poll|errors|interfaces|nodes|system|buffers|memory|epoch] <patterns/index>...\n", os.Args[0])
56 skipZeros := !*dumpAll
58 patterns := make([]string, 0)
59 indexes := make([]uint32, 0)
61 for _, arg := range flag.Args()[1:] {
62 if index, err := strconv.Atoi(arg); err == nil {
63 indexes = append(indexes, uint32(index))
66 patterns = append(patterns, arg)
71 client *statsclient.StatsClient
72 c *core.StatsConnection
77 var statsChan chan core.ConnectionEvent
78 client = statsclient.NewStatsClient(*statsSocket, statsclient.SetSocketRetryPeriod(1*time.Second),
79 statsclient.SetSocketRetryTimeout(10*time.Second))
80 c, statsChan, err = core.AsyncConnectStats(client, core.DefaultMaxReconnectAttempts, core.DefaultReconnectInterval)
82 log.Fatalln("Asynchronous connecting failed:", err)
85 case e := <-statsChan:
86 if e.State == core.Connected {
89 log.Fatalf("VPP stats asynchronous connection failed: %s\n", e.State.String())
93 client = statsclient.NewStatsClient(*statsSocket)
94 c, err = core.ConnectStats(client)
96 log.Fatalln("Connecting failed:", err)
101 switch cmd := flag.Arg(0); cmd {
103 stats := new(api.SystemStats)
104 if err := c.GetSystemStats(stats); err != nil {
105 log.Fatalln("getting system stats failed:", err)
107 fmt.Printf("System stats: %+v\n", stats)
113 fmt.Println("Listing node stats..")
114 stats := new(api.NodeStats)
115 if err := c.GetNodeStats(stats); err != nil {
116 log.Fatalln("getting node stats failed:", err)
119 for _, node := range stats.Nodes {
120 if skipZeros && node.Calls == 0 && node.Suspends == 0 && node.Clocks == 0 && node.Vectors == 0 {
123 fmt.Printf(" - %+v\n", node)
125 fmt.Printf("Listed %d node counters\n", len(stats.Nodes))
128 fmt.Println("Listing interface stats..")
129 stats := new(api.InterfaceStats)
130 if err := c.GetInterfaceStats(stats); err != nil {
131 log.Fatalln("getting interface stats failed:", err)
133 for _, iface := range stats.Interfaces {
134 fmt.Printf(" - %+v\n", iface)
136 fmt.Printf("Listed %d interface counters\n", len(stats.Interfaces))
138 case "poll-interfaces":
142 fmt.Printf("Listing error stats.. %s\n", strings.Join(patterns, " "))
143 stats := new(api.ErrorStats)
144 if err := c.GetErrorStats(stats); err != nil {
145 log.Fatalln("getting error stats failed:", err)
148 for _, counter := range stats.Errors {
150 for _, valuePerWorker := range counter.Values {
151 sum += uint32(valuePerWorker)
154 if skipZeros && sum == 0 {
157 fmt.Printf(" - %v %d (per worker: %v)\n", counter.CounterName, sum, counter.Values)
160 fmt.Printf("Listed %d (%d) error counters\n", n, len(stats.Errors))
163 stats := new(api.BufferStats)
164 if err := c.GetBufferStats(stats); err != nil {
165 log.Fatalln("getting buffer stats failed:", err)
167 fmt.Printf("Buffer stats: %+v\n", stats)
170 stats := new(api.MemoryStats)
171 if err := c.GetMemoryStats(stats); err != nil {
172 log.Fatalln("getting memory stats failed:", err)
174 fmt.Printf("Memory stats: %+v\n", stats)
177 fmt.Printf("Dumping stats.. %s\n", strings.Join(patterns, " "))
179 dumpStats(client, patterns, indexes, skipZeros)
182 fmt.Printf("Polling stats.. %s\n", strings.Join(patterns, " "))
184 pollStats(client, patterns, skipZeros)
186 case "list", "ls", "":
187 fmt.Printf("Listing stats.. %s\n", strings.Join(patterns, " "))
189 listStats(client, patterns, indexes)
192 fmt.Printf("Getting epoch..\n")
197 fmt.Printf("invalid command: %q\n", cmd)
201 func listStats(client adapter.StatsAPI, patterns []string, indexes []uint32) {
203 list := make([]adapter.StatIdentifier, 0)
204 if (len(patterns) == 0 && len(indexes) == 0) || len(patterns) != 0 {
205 list, err = client.ListStats(patterns...)
207 log.Fatalln("listing stats failed:", err)
210 if len(indexes) != 0 {
211 dir, err := client.PrepareDirOnIndex(indexes...)
213 log.Fatalln("listing stats failed:", err)
215 for _, onIndexSi := range dir.Entries {
216 list = append(list, onIndexSi.StatIdentifier)
219 for _, stat := range list {
220 fmt.Printf(" - %d\t %v\n", stat.Index, string(stat.Name))
223 fmt.Printf("Listed %d stats\n", len(list))
226 func getEpoch(client adapter.StatsAPI) {
227 dir, err := client.PrepareDir()
229 log.Fatalln("failed to prepare dir in order to read epoch:", err)
232 fmt.Printf("Epoch %d\n", d.Epoch)
235 func dumpStats(client adapter.StatsAPI, patterns []string, indexes []uint32, skipZeros bool) {
237 stats := make([]adapter.StatEntry, 0)
238 if (len(patterns) == 0 && len(indexes) == 0) || len(patterns) != 0 {
239 stats, err = client.DumpStats(patterns...)
241 log.Fatalln("dumping stats failed:", err)
244 if len(indexes) != 0 {
245 dir, err := client.PrepareDirOnIndex(indexes...)
247 log.Fatalln("dumping stats failed:", err)
249 for _, onIndexSi := range dir.Entries {
250 stats = append(stats, onIndexSi)
255 for _, stat := range stats {
256 if skipZeros && (stat.Data == nil || stat.Data.IsZero()) {
259 fmt.Printf(" - %-50s %25v %+v\n", stat.Name, stat.Type, stat.Data)
263 fmt.Printf("Dumped %d (%d) stats\n", n, len(stats))
266 func pollStats(client adapter.StatsAPI, patterns []string, skipZeros bool) {
267 dir, err := client.PrepareDir(patterns...)
269 log.Fatalln("preparing dir failed:", err)
272 tick := time.Tick(*pollPeriod)
275 fmt.Println(time.Now().Format(time.Stamp))
276 for _, stat := range dir.Entries {
277 if skipZeros && (stat.Data == nil || stat.Data.IsZero()) {
280 fmt.Printf("%-50s %+v\n", stat.Name, stat.Data)
287 if err := client.UpdateDir(dir); err != nil {
288 if err == adapter.ErrStatsDirStale {
289 if dir, err = client.PrepareDir(patterns...); err != nil {
290 log.Fatalln("preparing dir failed:", err)
294 log.Fatalln("updating dir failed:", err)
300 func pollSystem(client api.StatsProvider) {
301 stats := new(api.SystemStats)
303 if err := client.GetSystemStats(stats); err != nil {
304 log.Fatalln("updating system stats failed:", err)
307 tick := time.Tick(*pollPeriod)
309 fmt.Printf("System stats: %+v\n", stats)
314 if err := client.GetSystemStats(stats); err != nil {
315 log.Println("updating system stats failed:", err)
321 func pollInterfaces(client api.StatsProvider) {
322 stats := new(api.InterfaceStats)
324 if err := client.GetInterfaceStats(stats); err != nil {
325 log.Fatalln("updating system stats failed:", err)
328 tick := time.Tick(*pollPeriod)
330 fmt.Printf("Interface stats (%d interfaces)\n", len(stats.Interfaces))
331 for i := range stats.Interfaces {
332 fmt.Printf(" - %+v\n", stats.Interfaces[i])
338 if err := client.GetInterfaceStats(stats); err != nil {
339 log.Println("updating system stats failed:", err)