github.com/therealbill/libredis@v0.0.0-20161227004305-7d50abda5ccf/info/methods.go (about) 1 package info 2 3 import ( 4 "reflect" 5 "strconv" 6 "strings" 7 "unicode" 8 "unicode/utf8" 9 10 "github.com/therealbill/libredis/structures" 11 ) 12 13 // BuildAllInfoMap will call `INFO ALL` and return a mapping of map[string]string for each section in the output 14 func BuildAllInfoMap(infostring string) map[string]map[string]string { 15 lines := strings.Split(infostring, "\r\n") 16 allmap := make(map[string]map[string]string) 17 var sectionname string 18 for _, line := range lines { 19 if len(line) > 0 { 20 if strings.Contains(line, "# ") { 21 sectionname = strings.Split(line, "# ")[1] 22 allmap[sectionname] = make(map[string]string) 23 } else { 24 splits := strings.Split(line, ":") 25 key := splits[0] 26 val := splits[1] 27 secmap := allmap[sectionname] 28 if secmap == nil { 29 allmap[sectionname] = make(map[string]string) 30 } 31 allmap[sectionname][key] = val 32 } 33 } 34 } 35 return allmap 36 } 37 38 // BuildMapFromInfoString will take the string from a Redis info call and 39 // return a map[string]string 40 func BuildMapFromInfoString(input string) map[string]string { 41 imap := make(map[string]string) 42 lines := strings.Split(input, "\r\n") 43 for _, line := range lines { 44 if len(line) > 0 { 45 if strings.Contains(line, "#") { 46 imap["section"] = strings.Split(line, "#")[1] 47 } else { 48 splits := strings.Split(line, ":") 49 key := splits[0] 50 val := splits[1] 51 imap[key] = val 52 } 53 } 54 } 55 return imap 56 } 57 58 // BuildInfoKeyspace builds out the InfoKeyspace struct 59 func BuildInfoKeyspace(raw string) structures.InfoKeyspace { 60 var keyspace structures.InfoKeyspace 61 lines := strings.Split(raw, "\r\n") 62 section := "" 63 for _, line := range lines { 64 if len(line) > 0 { 65 if strings.Contains(line, "#") { 66 section = strings.Split(line, "# ")[1] 67 } else { 68 if section == "Keyspace" { 69 record := strings.Split(line, ":") 70 db := record[0][2:] 71 data := record[1] 72 splits := strings.Split(data, ",") 73 imap := make(map[string]int64) 74 dbIndex, _ := strconv.ParseInt(db, 10, 32) 75 imap["db"] = dbIndex 76 for _, entry := range splits { 77 keyvals := strings.Split(entry, "=") 78 key := keyvals[0] 79 val, _ := strconv.ParseInt(keyvals[1], 10, 32) 80 imap[key] = val 81 } 82 keyspace.Databases = append(keyspace.Databases, imap) 83 } 84 } 85 } else { 86 section = "" 87 } 88 } 89 return keyspace 90 } 91 92 // CommandStats returns the InfoCommandStats struct 93 func CommandStats(commandstatstring string) (cmdstat structures.InfoCommandStats) { 94 lines := strings.Split(commandstatstring, "\r\n") 95 section := "" 96 for _, line := range lines { 97 if len(line) > 0 { 98 if strings.Contains(line, "# Commandstats") { 99 cmdstat.Stats = make(map[string]map[string]float64) 100 section = "Commandstats" 101 } else { 102 if section == "Commandstats" { 103 record := strings.Split(line, ":") 104 command := strings.Split(record[0], "_")[1] 105 data := record[1] 106 imap := make(map[string]float64) 107 splits := strings.Split(data, ",") 108 for _, entry := range splits { 109 keyvals := strings.Split(entry, "=") 110 key := keyvals[0] 111 val, _ := strconv.ParseFloat(keyvals[1], 64) 112 imap[key] = val 113 } 114 cmdstat.Stats[command] = imap 115 } 116 } 117 } else { 118 section = "" 119 } 120 } 121 return 122 } 123 124 // KeyspaceStats returns an InfoKeyspace struct for accessing keyspace stats 125 func KeyspaceStats(infostring string) (stats structures.InfoKeyspace) { 126 trimmed := strings.TrimSpace(infostring) 127 stats = BuildInfoKeyspace(trimmed) 128 return 129 } 130 131 // GetAllInfo retuns a RedisInfoAll struct. This scturb has as it's members a 132 // strict for each INFO section. Since the cost difference of running INFO all 133 // and INFO <section> is negligible it mkes sens to just return it all and let 134 // the user select what info they want out of it. 135 func GetAllInfo(infostring string) (info structures.RedisInfoAll) { 136 allmap := BuildAllInfoMap(infostring) 137 var alldata structures.RedisInfoAll 138 all := reflect.ValueOf(&alldata).Elem() 139 for i := 0; i < all.NumField(); i++ { 140 p := all.Type().Field(i) 141 section := all.FieldByName(p.Name) 142 typeOfT := section.Type() 143 info := allmap[p.Name] 144 s := section 145 switch p.Name { 146 case "Keyspace": 147 alldata.Keyspace = KeyspaceStats(infostring) 148 case "Commandstats": 149 alldata.Commandstats = CommandStats(infostring) 150 default: 151 for i := 0; i < s.NumField(); i++ { 152 p := typeOfT.Field(i) 153 f := s.Field(i) 154 tag := p.Tag.Get("redis") 155 if p.Name == "Slaves" && tag == "slave*" { 156 for k, v := range info { 157 if strings.Contains(k, "slave") && strings.Contains(v, "ip=") { 158 idstring := strings.TrimLeft(k, "slave") 159 _, err := strconv.Atoi(string(idstring)) 160 if err == nil { 161 var slave structures.InfoSlaves 162 pairs := strings.Split(v, ",") 163 for _, pstring := range pairs { 164 pdata := strings.Split(pstring, "=") 165 switch pdata[0] { 166 case "ip": 167 slave.IP = pdata[1] 168 case "port": 169 port, _ := strconv.Atoi(pdata[1]) 170 slave.Port = port 171 case "state": 172 slave.State = pdata[1] 173 case "offset": 174 num, _ := strconv.Atoi(pdata[1]) 175 slave.Offset = num 176 case "lag": 177 num, _ := strconv.Atoi(pdata[1]) 178 slave.Lag = num 179 } 180 } 181 alldata.Replication.Slaves = append(alldata.Replication.Slaves, slave) 182 } 183 } 184 } 185 } 186 if len(info[tag]) != 0 { 187 if f.Type().Name() == "int" { 188 val, err := strconv.ParseInt(info[tag], 10, 64) 189 if err == nil { 190 f.SetInt(val) 191 } 192 } 193 if f.Type().Name() == "float64" { 194 val, err := strconv.ParseFloat(info[tag], 64) 195 if err == nil { 196 f.SetFloat(val) 197 } 198 } 199 if f.Type().Name() == "string" { 200 f.SetString(info[tag]) 201 } 202 if f.Type().Name() == "bool" { 203 val, err := strconv.ParseInt(info[tag], 10, 64) 204 if err == nil && val != 0 { 205 f.SetBool(true) 206 } 207 } 208 } 209 } 210 } 211 } 212 return alldata 213 214 } 215 216 func upperFirst(s string) string { 217 if s == "" { 218 return "" 219 } 220 r, n := utf8.DecodeRuneInString(s) 221 return string(unicode.ToUpper(r)) + s[n:] 222 }