Skip to content

Commit d2245ca

Browse files
author
Konstantin Nikitin
committed
Fetching Statistics from memcached server
1 parent 72a6864 commit d2245ca

1 file changed

Lines changed: 82 additions & 0 deletions

File tree

memcache/memcache.go

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,12 @@ var (
110110
resultTouched = []byte("TOUCHED\r\n")
111111

112112
resultClientErrorPrefix = []byte("CLIENT_ERROR ")
113+
114+
statsGetHits = []byte("STAT get_hits ")
115+
statsGetMisses = []byte("STAT get_misses ")
116+
statsBytesWritten = []byte("STAT bytes_written ")
117+
statsItems = []byte("STAT curr_items ")
118+
statsBytes = []byte("STAT bytes ")
113119
)
114120

115121
// New returns a memcache client using the provided server(s)
@@ -171,6 +177,24 @@ type conn struct {
171177
c *Client
172178
}
173179

180+
// Statistics is a record of memcached usage stats.
181+
type Statistics struct {
182+
// Counter of cache hits.
183+
Hits uint64
184+
185+
// Counter of cache misses.
186+
Misses uint64
187+
188+
// Counter of bytes transferred for gets.
189+
ByteHits uint64
190+
191+
// Items currently in the cache.
192+
Items uint64
193+
194+
// Size of all items currently in the cache.
195+
Bytes uint64
196+
}
197+
174198
// release returns this connection back to the client's free pool
175199
func (cn *conn) release() {
176200
cn.c.putFreeConn(cn.addr, cn)
@@ -667,3 +691,61 @@ func (c *Client) incrDecr(verb, key string, delta uint64) (uint64, error) {
667691
})
668692
return val, err
669693
}
694+
695+
func parseStatsLine(s []byte, expectedPrefix []byte) (uint64, error) {
696+
if !bytes.HasPrefix(s, expectedPrefix) {
697+
return 0, errors.New("line does not start with exceptedPrefix")
698+
}
699+
return strconv.ParseUint(
700+
string(s[len(expectedPrefix):len(s)-2]), 10, 64)
701+
}
702+
703+
func parseStatsResponse(r *bufio.Reader, stats *Statistics) error {
704+
for {
705+
line, err := r.ReadSlice('\n')
706+
if err != nil {
707+
return err
708+
}
709+
if bytes.Equal(line, resultEnd) {
710+
return nil
711+
}
712+
if hits, err := parseStatsLine(line, statsGetHits); err == nil {
713+
stats.Hits = hits
714+
continue
715+
}
716+
if misses, err := parseStatsLine(line, statsGetMisses); err == nil {
717+
stats.Misses = misses
718+
continue
719+
}
720+
if bytesWritten, err := parseStatsLine(line, statsBytesWritten); err == nil {
721+
stats.ByteHits = bytesWritten
722+
continue
723+
}
724+
if items, err := parseStatsLine(line, statsItems); err == nil {
725+
stats.Items = items
726+
continue
727+
}
728+
if bytes_total, err := parseStatsLine(line, statsBytes); err == nil {
729+
stats.Bytes = bytes_total
730+
continue
731+
}
732+
}
733+
}
734+
735+
736+
func (c *Client) Stats(addr net.Addr) (*Statistics, error) {
737+
stats := new(Statistics)
738+
err := c.withAddrRw(addr, func(rw *bufio.ReadWriter) error {
739+
if _, err := fmt.Fprintf(rw, "stats\r\n"); err != nil {
740+
return err
741+
}
742+
if err := rw.Flush(); err != nil {
743+
return err
744+
}
745+
if err := parseStatsResponse(rw.Reader, stats); err != nil {
746+
return err
747+
}
748+
return nil
749+
})
750+
return stats, err
751+
}

0 commit comments

Comments
 (0)