11809: Add /status.json handler.
authorTom Clegg <tom@curoverse.com>
Wed, 7 Jun 2017 14:23:41 +0000 (10:23 -0400)
committerTom Clegg <tom@curoverse.com>
Wed, 7 Jun 2017 14:23:41 +0000 (10:23 -0400)
Arvados-DCO-1.1-Signed-off-by: Tom Clegg <tom@curoverse.com>

services/keep-web/cache.go
services/keep-web/handler.go

index e8bf3993c57f479af17fea2cc8881ec22b10b444..26f6627424ce605d38675f5e6f1b7fa4ac53f7a8 100644 (file)
@@ -26,11 +26,13 @@ type cache struct {
 }
 
 type cacheStats struct {
-       Requests       uint64
-       CollectionHits uint64
-       PDHHits        uint64
-       PermissionHits uint64
-       APICalls       uint64
+       Requests          uint64 `json:"Cache.Requests"`
+       CollectionBytes   uint64 `json:"Cache.CollectionBytes"`
+       CollectionEntries int    `json:"Cache.CollectionEntries"`
+       CollectionHits    uint64 `json:"Cache.CollectionHits"`
+       PDHHits           uint64 `json:"Cache.UUIDHits"`
+       PermissionHits    uint64 `json:"Cache.PermissionHits"`
+       APICalls          uint64 `json:"Cache.APICalls"`
 }
 
 type cachedPDH struct {
@@ -68,12 +70,15 @@ var selectPDH = map[string]interface{}{
 }
 
 func (c *cache) Stats() cacheStats {
+       c.setupOnce.Do(c.setup)
        return cacheStats{
-               Requests:       atomic.LoadUint64(&c.stats.Requests),
-               CollectionHits: atomic.LoadUint64(&c.stats.CollectionHits),
-               PDHHits:        atomic.LoadUint64(&c.stats.PDHHits),
-               PermissionHits: atomic.LoadUint64(&c.stats.PermissionHits),
-               APICalls:       atomic.LoadUint64(&c.stats.APICalls),
+               Requests:          atomic.LoadUint64(&c.stats.Requests),
+               CollectionBytes:   c.collectionBytes(),
+               CollectionEntries: c.collections.Len(),
+               CollectionHits:    atomic.LoadUint64(&c.stats.CollectionHits),
+               PDHHits:           atomic.LoadUint64(&c.stats.PDHHits),
+               PermissionHits:    atomic.LoadUint64(&c.stats.PermissionHits),
+               APICalls:          atomic.LoadUint64(&c.stats.APICalls),
        }
 }
 
@@ -219,6 +224,20 @@ func (c *cache) pruneCollections() {
        }
 }
 
+// collectionBytes returns the approximate memory size of the
+// collection cache.
+func (c *cache) collectionBytes() uint64 {
+       var size uint64
+       for _, k := range c.collections.Keys() {
+               v, ok := c.collections.Peek(k)
+               if !ok {
+                       continue
+               }
+               size += uint64(len(v.(*cachedCollection).collection["manifest_text"].(string)))
+       }
+       return size
+}
+
 func (c *cache) lookupCollection(pdh string) map[string]interface{} {
        if pdh == "" {
                return nil
index 45cd27fc639f05e7dffde604f3c1417435801542..42c37b8eebf947bea060ef2ace9a68b1fcca67ad 100644 (file)
@@ -1,6 +1,7 @@
 package main
 
 import (
+       "encoding/json"
        "fmt"
        "html"
        "io"
@@ -67,6 +68,15 @@ func (h *handler) setup() {
        keepclient.RefreshServiceDiscoveryOnSIGHUP()
 }
 
+func (h *handler) serveStatus(w http.ResponseWriter, r *http.Request) {
+       status := struct {
+               cacheStats
+       }{
+               cacheStats: h.Config.Cache.Stats(),
+       }
+       json.NewEncoder(w).Encode(status)
+}
+
 // ServeHTTP implements http.Handler.
 func (h *handler) ServeHTTP(wOrig http.ResponseWriter, r *http.Request) {
        h.setupOnce.Do(h.setup)
@@ -151,6 +161,9 @@ func (h *handler) ServeHTTP(wOrig http.ResponseWriter, r *http.Request) {
                // http://ID.collections.example/PATH...
                credentialsOK = true
                targetPath = pathParts
+       } else if r.URL.Path == "/status.json" {
+               h.serveStatus(w, r)
+               return
        } else if len(pathParts) >= 2 && strings.HasPrefix(pathParts[0], "c=") {
                // /c=ID/PATH...
                targetID = parseCollectionIDFromURL(pathParts[0][2:])