05608e2f2c4da5c81fbb60cac8a452147dbca182
[ric-plt/sdlgo.git] / internal / cli / statistics.go
1 /*
2    Copyright (c) 2021 AT&T Intellectual Property.
3    Copyright (c) 2018-2021 Nokia.
4
5    Licensed under the Apache License, Version 2.0 (the "License");
6    you may not use this file except in compliance with the License.
7    You may obtain a copy of the License at
8
9        http://www.apache.org/licenses/LICENSE-2.0
10
11    Unless required by applicable law or agreed to in writing, software
12    distributed under the License is distributed on an "AS IS" BASIS,
13    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14    See the License for the specific language governing permissions and
15    limitations under the License.
16 */
17
18 /*
19  * This source code is part of the near-RT RIC (RAN Intelligent Controller)
20  * platform project (RICP).
21  */
22
23 package cli
24
25 import (
26         "fmt"
27         "gerrit.o-ran-sc.org/r/ric-plt/sdlgo/internal/sdlgoredis"
28         "github.com/spf13/cobra"
29         "os"
30         "reflect"
31         "text/tabwriter"
32 )
33
34 func init() {
35         rootCmd.AddCommand(newStatisticsCmd(newDatabase))
36 }
37
38 var (
39         statsLong = `Display SDL resource usage statistics`
40
41         statsExample = `  # Show statistics per node
42   sdlcli statistics`
43 )
44
45 func newStatisticsCmd(dbCreateCb DbCreateCb) *cobra.Command {
46         return &cobra.Command{
47                 Use:     "statistics",
48                 Short:   "Display statistics.",
49                 Long:    statsLong,
50                 Example: statsExample,
51                 Args:    cobra.ExactArgs(0),
52                 RunE: func(cmd *cobra.Command, args []string) error {
53                         statistics, err := runStats(dbCreateCb)
54                         if err != nil {
55                                 fmt.Fprintf(os.Stderr, "%s", buf.String())
56                                 return err
57                         }
58                         printStatistics(cmd, statistics)
59                         return nil
60                 },
61         }
62 }
63
64 func runStats(dbCreateCb DbCreateCb) ([]*sdlgoredis.DbStatistics, error) {
65         var statistics []*sdlgoredis.DbStatistics
66         for _, dbInst := range dbCreateCb().Instances {
67                 dbStatistics, err := dbInst.Statistics()
68                 if err != nil {
69                         return nil, err
70                 }
71                 statistics = append(statistics, dbStatistics)
72         }
73         return statistics, nil
74 }
75
76 func writeClientsInfo(w *tabwriter.Writer, clients sdlgoredis.ClientsInfoFields) {
77         fmt.Fprintf(w, "\t\t\tConnectedClients:%d\n", clients.ConnectedClients)
78         fmt.Fprintf(w, "\t\t\tClientRecentMaxInputBuffer:%d\n", clients.ClientRecentMaxInputBuffer)
79         fmt.Fprintf(w, "\t\t\tClientRecentMaxOutputBuffer:%d\n", clients.ClientRecentMaxOutputBuffer)
80 }
81
82 func writeMemoryInfo(w *tabwriter.Writer, memory sdlgoredis.MeroryInfoFields) {
83         fmt.Fprintf(w, "\t\t\tUsedMemory:%d\n", memory.UsedMemory)
84         fmt.Fprintf(w, "\t\t\tUsedMemoryHuman:%s\n", memory.UsedMemoryHuman)
85         fmt.Fprintf(w, "\t\t\tUsedMemoryRss:%d\n", memory.UsedMemoryRss)
86         fmt.Fprintf(w, "\t\t\tUsedMemoryRssHuman:%s\n", memory.UsedMemoryRssHuman)
87         fmt.Fprintf(w, "\t\t\tUsedMemoryPeak:%d\n", memory.UsedMemoryPeak)
88         fmt.Fprintf(w, "\t\t\tUsedMemoryPeakHuman:%s\n", memory.UsedMemoryPeakHuman)
89         fmt.Fprintf(w, "\t\t\tUsedMemoryPeakPerc:%s\n", memory.UsedMemoryPeakPerc)
90         fmt.Fprintf(w, "\t\t\tMemFragmentationRatio:%.2f\n", memory.MemFragmentationRatio)
91         fmt.Fprintf(w, "\t\t\tMemFragmentationBytes:%d\n", memory.MemFragmentationBytes)
92 }
93
94 func writeStatsInfo(w *tabwriter.Writer, stats sdlgoredis.StatsInfoFields) {
95         fmt.Fprintf(w, "\t\t\tTotalConnectionsReceived:%d\n", stats.TotalConnectionsReceived)
96         fmt.Fprintf(w, "\t\t\tTotalCommandsProcessed:%d\n", stats.TotalCommandsProcessed)
97         fmt.Fprintf(w, "\t\t\tSyncFull:%d\n", stats.SyncFull)
98         fmt.Fprintf(w, "\t\t\tSyncPartialOk:%d\n", stats.SyncPartialOk)
99         fmt.Fprintf(w, "\t\t\tSyncPartialErr:%d\n", stats.SyncPartialErr)
100         fmt.Fprintf(w, "\t\t\tPubsubChannels:%d\n", stats.PubsubChannels)
101 }
102
103 func writeCpuInfo(w *tabwriter.Writer, cpu sdlgoredis.CpuInfoFields) {
104         fmt.Fprintf(w, "\t\t\tUsedCpuSys:%v\n", cpu.UsedCpuSys)
105         fmt.Fprintf(w, "\t\t\tUsedCpuUser:%v\n", cpu.UsedCpuUser)
106 }
107
108 func fillCommandstatsInfo(w *tabwriter.Writer, i interface{}, cmdstat string) {
109         stype := reflect.ValueOf(i).Elem()
110         callsField := stype.FieldByName("Calls").Interface()
111         usecField := stype.FieldByName("Usec").Interface()
112         usecPerCallField := stype.FieldByName("UsecPerCall").Interface()
113
114         if callsField.(uint32) > 0 {
115                 fmt.Fprintf(w, "\t\t\t%s:calls=%d usec:%d usecPerCall:%.2f\n",
116                         cmdstat, callsField, usecField, usecPerCallField)
117         }
118 }
119
120 func writeCommandstatsInfo(w *tabwriter.Writer, commandstats sdlgoredis.CommandstatsInfoFields) {
121         fillCommandstatsInfo(w, &commandstats.CmdstatReplconf, "CmdstatReplconf")
122         fillCommandstatsInfo(w, &commandstats.CmdstatKeys, "CmdstatKeys")
123         fillCommandstatsInfo(w, &commandstats.CmdstatRole, "CmdstatRole")
124         fillCommandstatsInfo(w, &commandstats.CmdstatPsync, "CmdstatPsync")
125         fillCommandstatsInfo(w, &commandstats.CmdstatMset, "CmdstatMset")
126         fillCommandstatsInfo(w, &commandstats.CmdstatPublish, "CmdstatPublish")
127         fillCommandstatsInfo(w, &commandstats.CmdstatInfo, "CmdstatInfo")
128         fillCommandstatsInfo(w, &commandstats.CmdstatPing, "CmdstatPing")
129         fillCommandstatsInfo(w, &commandstats.CmdstatClient, "CmdstatClient")
130         fillCommandstatsInfo(w, &commandstats.CmdstatCommand, "CmdstatCommand")
131         fillCommandstatsInfo(w, &commandstats.CmdstatSubscribe, "CmdstatSubscribe")
132         fillCommandstatsInfo(w, &commandstats.CmdstatMonitor, "CmdstatMonitor")
133         fillCommandstatsInfo(w, &commandstats.CmdstatConfig, "CmdstatConfig")
134         fillCommandstatsInfo(w, &commandstats.CmdstatSlaveof, "CmdstatSlaveof")
135 }
136
137 func writeKeyspaceInfo(w *tabwriter.Writer, keyspace sdlgoredis.KeyspaceInfoFields) {
138         fmt.Fprintf(w, "\t\t\tDb0:keys=%d\n", keyspace.Db.Keys)
139 }
140
141 func printStatistics(cmd *cobra.Command, statistics []*sdlgoredis.DbStatistics) {
142         w := tabwriter.NewWriter(cmd.OutOrStdout(), 6, 4, 2, ' ', 0)
143         fmt.Fprintln(w, "CLUSTER\tROLE\tADDRESS\tSTATISTICS")
144
145         for i, s := range statistics {
146                 for _, stats := range s.Stats {
147                         fmt.Fprintf(w, "%d", i)
148                         if stats.Info.Fields.PrimaryRole {
149                                 fmt.Fprintf(w, "\tPrimary")
150                         } else {
151                                 fmt.Fprintf(w, "\tReplica")
152                         }
153                         fmt.Fprintf(w, "\t%s:%s", stats.IPAddr, stats.Port)
154                         fmt.Fprintf(w, "\tUptimeInDays:%d\n", stats.Info.Fields.Server.UptimeInDays)
155                         writeClientsInfo(w, stats.Info.Fields.Clients)
156                         writeMemoryInfo(w, stats.Info.Fields.Memory)
157                         writeStatsInfo(w, stats.Info.Fields.Stats)
158                         writeCpuInfo(w, stats.Info.Fields.Cpu)
159                         writeCommandstatsInfo(w, stats.Info.Fields.Commandstats)
160                         writeKeyspaceInfo(w, stats.Info.Fields.Keyspace)
161                 }
162         }
163         w.Flush()
164 }