@@ -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,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