@@ -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
175199func (cn * conn ) release () {
176200 cn .c .putFreeConn (cn .addr , cn )
@@ -667,3 +691,63 @@ 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+ // parseStatsResponse reads a GET response from r and calls cb for each
704+ // read and allocated Item
705+ func parseStatsResponse (r * bufio.Reader , stats * Statistics ) error {
706+ for {
707+ line , err := r .ReadSlice ('\n' )
708+ if err != nil {
709+ return err
710+ }
711+ if bytes .Equal (line , resultEnd ) {
712+ return nil
713+ }
714+ if hits , err := parseStatsLine (line , statsGetHits ); err == nil {
715+ stats .Hits = hits
716+ continue
717+ }
718+ if misses , err := parseStatsLine (line , statsGetMisses ); err == nil {
719+ stats .Misses = misses
720+ continue
721+ }
722+ if bytesWritten , err := parseStatsLine (line , statsBytesWritten ); err == nil {
723+ stats .ByteHits = bytesWritten
724+ continue
725+ }
726+ if items , err := parseStatsLine (line , statsItems ); err == nil {
727+ stats .Items = items
728+ continue
729+ }
730+ if bytes_total , err := parseStatsLine (line , statsBytes ); err == nil {
731+ stats .Bytes = bytes_total
732+ continue
733+ }
734+ }
735+ }
736+
737+
738+ func (c * Client ) Stats (addr net.Addr ) (* Statistics , error ) {
739+ stats := new (Statistics )
740+ err := c .withAddrRw (addr , func (rw * bufio.ReadWriter ) error {
741+ if _ , err := fmt .Fprintf (rw , "stats\r \n " ); err != nil {
742+ return err
743+ }
744+ if err := rw .Flush (); err != nil {
745+ return err
746+ }
747+ if err := parseStatsResponse (rw .Reader , stats ); err != nil {
748+ return err
749+ }
750+ return nil
751+ })
752+ return stats , err
753+ }
0 commit comments