13025: Add request time metrics at /metrics and /metrics.json.
authorTom Clegg <tclegg@veritasgenetics.com>
Tue, 6 Feb 2018 22:52:18 +0000 (17:52 -0500)
committerTom Clegg <tclegg@veritasgenetics.com>
Tue, 6 Feb 2018 23:04:19 +0000 (18:04 -0500)
Arvados-DCO-1.1-Signed-off-by: Tom Clegg <tclegg@veritasgenetics.com>

17 files changed:
sdk/go/httpserver/logger.go
sdk/go/httpserver/responsewriter.go
services/keepstore/azure_blob_volume.go
services/keepstore/azure_blob_volume_test.go
services/keepstore/bufferpool.go
services/keepstore/bufferpool_test.go
services/keepstore/config.go
services/keepstore/config_test.go
services/keepstore/handlers.go
services/keepstore/keepstore.go
services/keepstore/mounts_test.go
services/keepstore/pull_worker.go
services/keepstore/s3_volume.go
services/keepstore/s3_volume_test.go
services/keepstore/trash_worker.go
services/keepstore/volume_unix.go
vendor/vendor.json

index decb2ff28b7a650546253aeea09675d70256dbea..fab850fd91173f17eb7c6b1b76bc2fb32749d6d9 100644 (file)
@@ -10,7 +10,7 @@ import (
        "time"
 
        "git.curoverse.com/arvados.git/sdk/go/stats"
-       log "github.com/Sirupsen/logrus"
+       "github.com/Sirupsen/logrus"
 )
 
 type contextKey struct {
@@ -19,13 +19,15 @@ type contextKey struct {
 
 var requestTimeContextKey = contextKey{"requestTime"}
 
+var Logger logrus.FieldLogger = logrus.StandardLogger()
+
 // LogRequests wraps an http.Handler, logging each request and
 // response via logrus.
 func LogRequests(h http.Handler) http.Handler {
        return http.HandlerFunc(func(wrapped http.ResponseWriter, req *http.Request) {
                w := &responseTimer{ResponseWriter: WrapResponseWriter(wrapped)}
                req = req.WithContext(context.WithValue(req.Context(), &requestTimeContextKey, time.Now()))
-               lgr := log.WithFields(log.Fields{
+               lgr := Logger.WithFields(logrus.Fields{
                        "RequestID":       req.Header.Get("X-Request-Id"),
                        "remoteAddr":      req.RemoteAddr,
                        "reqForwardedFor": req.Header.Get("X-Forwarded-For"),
@@ -39,20 +41,20 @@ func LogRequests(h http.Handler) http.Handler {
        })
 }
 
-func logRequest(w *responseTimer, req *http.Request, lgr *log.Entry) {
+func logRequest(w *responseTimer, req *http.Request, lgr *logrus.Entry) {
        lgr.Info("request")
 }
 
-func logResponse(w *responseTimer, req *http.Request, lgr *log.Entry) {
+func logResponse(w *responseTimer, req *http.Request, lgr *logrus.Entry) {
        if tStart, ok := req.Context().Value(&requestTimeContextKey).(time.Time); ok {
                tDone := time.Now()
-               lgr = lgr.WithFields(log.Fields{
+               lgr = lgr.WithFields(logrus.Fields{
                        "timeTotal":     stats.Duration(tDone.Sub(tStart)),
                        "timeToStatus":  stats.Duration(w.writeTime.Sub(tStart)),
                        "timeWriteBody": stats.Duration(tDone.Sub(w.writeTime)),
                })
        }
-       lgr.WithFields(log.Fields{
+       lgr.WithFields(logrus.Fields{
                "respStatusCode": w.WroteStatus(),
                "respStatus":     http.StatusText(w.WroteStatus()),
                "respBytes":      w.WroteBodyBytes(),
@@ -65,6 +67,13 @@ type responseTimer struct {
        writeTime time.Time
 }
 
+func (rt *responseTimer) CloseNotify() <-chan bool {
+       if cn, ok := rt.ResponseWriter.(http.CloseNotifier); ok {
+               return cn.CloseNotify()
+       }
+       return nil
+}
+
 func (rt *responseTimer) WriteHeader(code int) {
        if !rt.wrote {
                rt.wrote = true
index f17bc820a98f5c242ffc24122d1176cc5c21a57e..5fb810efa5a80bae22fed5449f6b86186c9aef63 100644 (file)
@@ -28,6 +28,13 @@ func WrapResponseWriter(orig http.ResponseWriter) ResponseWriter {
        return &responseWriter{ResponseWriter: orig}
 }
 
+func (w *responseWriter) CloseNotify() <-chan bool {
+       if cn, ok := w.ResponseWriter.(http.CloseNotifier); ok {
+               return cn.CloseNotify()
+       }
+       return nil
+}
+
 func (w *responseWriter) WriteHeader(s int) {
        w.wroteStatus = s
        w.ResponseWriter.WriteHeader(s)
@@ -41,6 +48,9 @@ func (w *responseWriter) Write(data []byte) (n int, err error) {
 }
 
 func (w *responseWriter) WroteStatus() int {
+       if w.wroteStatus == 0 {
+               return http.StatusOK
+       }
        return w.wroteStatus
 }
 
index 62c856da340183d0483503e0a2393816acaf0321..2638bf08cdab53e84d0ff206542286ad58ff3f94 100644 (file)
@@ -21,7 +21,6 @@ import (
        "time"
 
        "git.curoverse.com/arvados.git/sdk/go/arvados"
-       log "github.com/Sirupsen/logrus"
        "github.com/curoverse/azure-sdk-for-go/storage"
 )
 
index 06216edcb82aeddc3617c121cecc4e1a6387be4a..31b79da2982547c1b731eb9ae7336edce0c0de8a 100644 (file)
@@ -26,7 +26,6 @@ import (
        "testing"
        "time"
 
-       log "github.com/Sirupsen/logrus"
        "github.com/curoverse/azure-sdk-for-go/storage"
        check "gopkg.in/check.v1"
 )
index 91417fd52c37a23f940bb78a430cee56a9808c36..d2e7c9ebd3460b75855ca830ab05f6f9f5ab02b9 100644 (file)
@@ -8,8 +8,6 @@ import (
        "sync"
        "sync/atomic"
        "time"
-
-       log "github.com/Sirupsen/logrus"
 )
 
 type bufferPool struct {
index a6479e44378b75f1e9ad186871ac55834a3f4779..21b03edd49b967356c74958b1a1d762851babb60 100644 (file)
@@ -5,8 +5,9 @@
 package main
 
 import (
-       . "gopkg.in/check.v1"
        "time"
+
+       . "gopkg.in/check.v1"
 )
 
 var _ = Suite(&BufferPoolSuite{})
index 0a3ece41ad9d88589513c30a878f172276afd93c..bbce883504856cc49ac0d6317cd0c6d47fb4fd65 100644 (file)
@@ -9,11 +9,17 @@ import (
        "encoding/json"
        "fmt"
        "io/ioutil"
+       "net/http"
+       "strconv"
        "strings"
        "time"
 
        "git.curoverse.com/arvados.git/sdk/go/arvados"
-       log "github.com/Sirupsen/logrus"
+       "git.curoverse.com/arvados.git/sdk/go/stats"
+       "github.com/Sirupsen/logrus"
+       "github.com/golang/protobuf/jsonpb"
+       "github.com/prometheus/client_golang/prometheus"
+       "github.com/prometheus/client_golang/prometheus/promhttp"
 )
 
 type Config struct {
@@ -42,9 +48,23 @@ type Config struct {
        debugLogf       func(string, ...interface{})
 
        ManagementToken string
+
+       metrics
 }
 
-var theConfig = DefaultConfig()
+var (
+       theConfig = DefaultConfig()
+       formatter = map[string]logrus.Formatter{
+               "text": &logrus.TextFormatter{
+                       FullTimestamp:   true,
+                       TimestampFormat: rfc3339NanoFixed,
+               },
+               "json": &logrus.JSONFormatter{
+                       TimestampFormat: rfc3339NanoFixed,
+               },
+       }
+       log = logrus.StandardLogger()
+)
 
 const rfc3339NanoFixed = "2006-01-02T15:04:05.000000000Z07:00"
 
@@ -66,25 +86,18 @@ func DefaultConfig() *Config {
 // fields, and before using the config.
 func (cfg *Config) Start() error {
        if cfg.Debug {
-               log.SetLevel(log.DebugLevel)
+               log.Level = logrus.DebugLevel
                cfg.debugLogf = log.Printf
                cfg.debugLogf("debugging enabled")
        } else {
+               log.Level = logrus.InfoLevel
                cfg.debugLogf = func(string, ...interface{}) {}
        }
 
-       switch strings.ToLower(cfg.LogFormat) {
-       case "text":
-               log.SetFormatter(&log.TextFormatter{
-                       FullTimestamp:   true,
-                       TimestampFormat: rfc3339NanoFixed,
-               })
-       case "json":
-               log.SetFormatter(&log.JSONFormatter{
-                       TimestampFormat: rfc3339NanoFixed,
-               })
-       default:
+       if f := formatter[strings.ToLower(cfg.LogFormat)]; f == nil {
                return fmt.Errorf(`unsupported log format %q (try "text" or "json")`, cfg.LogFormat)
+       } else {
+               log.Formatter = f
        }
 
        if cfg.MaxBuffers < 0 {
@@ -142,6 +155,62 @@ func (cfg *Config) Start() error {
        return nil
 }
 
+type metrics struct {
+       registry     *prometheus.Registry
+       reqDuration  *prometheus.SummaryVec
+       timeToStatus *prometheus.SummaryVec
+       exportProm   http.Handler
+}
+
+func (*metrics) Levels() []logrus.Level {
+       return logrus.AllLevels
+}
+
+func (m *metrics) Fire(ent *logrus.Entry) error {
+       if tts, ok := ent.Data["timeToStatus"].(stats.Duration); !ok {
+       } else if method, ok := ent.Data["reqMethod"].(string); !ok {
+       } else if code, ok := ent.Data["respStatusCode"].(int); !ok {
+       } else {
+               m.timeToStatus.WithLabelValues(strconv.Itoa(code), strings.ToLower(method)).Observe(time.Duration(tts).Seconds())
+       }
+       return nil
+}
+
+func (m *metrics) setup() {
+       m.registry = prometheus.NewRegistry()
+       m.timeToStatus = prometheus.NewSummaryVec(prometheus.SummaryOpts{
+               Name: "time_to_status_seconds",
+               Help: "Summary of request TTFB.",
+       }, []string{"code", "method"})
+       m.reqDuration = prometheus.NewSummaryVec(prometheus.SummaryOpts{
+               Name: "request_duration_seconds",
+               Help: "Summary of request duration.",
+       }, []string{"code", "method"})
+       m.registry.MustRegister(m.timeToStatus)
+       m.registry.MustRegister(m.reqDuration)
+       m.exportProm = promhttp.HandlerFor(m.registry, promhttp.HandlerOpts{
+               ErrorLog: log,
+       })
+       log.AddHook(m)
+}
+
+func (m *metrics) exportJSON(w http.ResponseWriter, req *http.Request) {
+       jm := jsonpb.Marshaler{Indent: "  "}
+       mfs, _ := m.registry.Gather()
+       w.Write([]byte{'['})
+       for i, mf := range mfs {
+               if i > 0 {
+                       w.Write([]byte{','})
+               }
+               jm.Marshal(w, mf)
+       }
+       w.Write([]byte{']'})
+}
+
+func (m *metrics) Instrument(next http.Handler) http.Handler {
+       return promhttp.InstrumentHandlerDuration(m.reqDuration, next)
+}
+
 // VolumeTypes is built up by init() funcs in the source files that
 // define the volume types.
 var VolumeTypes = []func() VolumeWithExamples{}
index 5e55042c28747de26c0f9e1ad1806bcec00ad5c7..d6471e3d4547d45f577131c0a6ecb2f1ca59c52c 100644 (file)
@@ -5,9 +5,10 @@
 package main
 
 import (
-       log "github.com/Sirupsen/logrus"
+       "github.com/Sirupsen/logrus"
 )
 
 func init() {
+       log.Level = logrus.DebugLevel
        theConfig.debugLogf = log.Printf
 }
index daf4fc69ddff2702f0da43fd0af4d4927374bb2c..258604ce59c50176a4d4473fd7dbf87c8d66de9c 100644 (file)
@@ -31,7 +31,6 @@ import (
 
        "git.curoverse.com/arvados.git/sdk/go/health"
        "git.curoverse.com/arvados.git/sdk/go/httpserver"
-       log "github.com/Sirupsen/logrus"
 )
 
 type router struct {
@@ -41,54 +40,63 @@ type router struct {
 
 // MakeRESTRouter returns a new router that forwards all Keep requests
 // to the appropriate handlers.
-func MakeRESTRouter() *router {
-       rest := mux.NewRouter()
-       rtr := &router{Router: rest}
+func MakeRESTRouter() http.Handler {
+       rtr := &router{Router: mux.NewRouter()}
 
-       rest.HandleFunc(
+       rtr.HandleFunc(
                `/{hash:[0-9a-f]{32}}`, GetBlockHandler).Methods("GET", "HEAD")
-       rest.HandleFunc(
+       rtr.HandleFunc(
                `/{hash:[0-9a-f]{32}}+{hints}`,
                GetBlockHandler).Methods("GET", "HEAD")
 
-       rest.HandleFunc(`/{hash:[0-9a-f]{32}}`, PutBlockHandler).Methods("PUT")
-       rest.HandleFunc(`/{hash:[0-9a-f]{32}}`, DeleteHandler).Methods("DELETE")
+       rtr.HandleFunc(`/{hash:[0-9a-f]{32}}`, PutBlockHandler).Methods("PUT")
+       rtr.HandleFunc(`/{hash:[0-9a-f]{32}}`, DeleteHandler).Methods("DELETE")
        // List all blocks stored here. Privileged client only.
-       rest.HandleFunc(`/index`, rtr.IndexHandler).Methods("GET", "HEAD")
+       rtr.HandleFunc(`/index`, rtr.IndexHandler).Methods("GET", "HEAD")
        // List blocks stored here whose hash has the given prefix.
        // Privileged client only.
-       rest.HandleFunc(`/index/{prefix:[0-9a-f]{0,32}}`, rtr.IndexHandler).Methods("GET", "HEAD")
+       rtr.HandleFunc(`/index/{prefix:[0-9a-f]{0,32}}`, rtr.IndexHandler).Methods("GET", "HEAD")
 
        // Internals/debugging info (runtime.MemStats)
-       rest.HandleFunc(`/debug.json`, rtr.DebugHandler).Methods("GET", "HEAD")
+       rtr.HandleFunc(`/debug.json`, rtr.DebugHandler).Methods("GET", "HEAD")
 
        // List volumes: path, device number, bytes used/avail.
-       rest.HandleFunc(`/status.json`, rtr.StatusHandler).Methods("GET", "HEAD")
+       rtr.HandleFunc(`/status.json`, rtr.StatusHandler).Methods("GET", "HEAD")
 
        // List mounts: UUID, readonly, tier, device ID, ...
-       rest.HandleFunc(`/mounts`, rtr.MountsHandler).Methods("GET")
-       rest.HandleFunc(`/mounts/{uuid}/blocks`, rtr.IndexHandler).Methods("GET")
-       rest.HandleFunc(`/mounts/{uuid}/blocks/`, rtr.IndexHandler).Methods("GET")
+       rtr.HandleFunc(`/mounts`, rtr.MountsHandler).Methods("GET")
+       rtr.HandleFunc(`/mounts/{uuid}/blocks`, rtr.IndexHandler).Methods("GET")
+       rtr.HandleFunc(`/mounts/{uuid}/blocks/`, rtr.IndexHandler).Methods("GET")
 
        // Replace the current pull queue.
-       rest.HandleFunc(`/pull`, PullHandler).Methods("PUT")
+       rtr.HandleFunc(`/pull`, PullHandler).Methods("PUT")
 
        // Replace the current trash queue.
-       rest.HandleFunc(`/trash`, TrashHandler).Methods("PUT")
+       rtr.HandleFunc(`/trash`, TrashHandler).Methods("PUT")
 
        // Untrash moves blocks from trash back into store
-       rest.HandleFunc(`/untrash/{hash:[0-9a-f]{32}}`, UntrashHandler).Methods("PUT")
+       rtr.HandleFunc(`/untrash/{hash:[0-9a-f]{32}}`, UntrashHandler).Methods("PUT")
 
-       rest.Handle("/_health/{check}", &health.Handler{
+       rtr.Handle("/_health/{check}", &health.Handler{
                Token:  theConfig.ManagementToken,
                Prefix: "/_health/",
        }).Methods("GET")
 
        // Any request which does not match any of these routes gets
        // 400 Bad Request.
-       rest.NotFoundHandler = http.HandlerFunc(BadRequestHandler)
+       rtr.NotFoundHandler = http.HandlerFunc(BadRequestHandler)
 
-       return rtr
+       theConfig.metrics.setup()
+
+       rtr.limiter = httpserver.NewRequestLimiter(theConfig.MaxRequests, rtr)
+
+       mux := http.NewServeMux()
+       mux.Handle("/", theConfig.metrics.Instrument(
+               httpserver.AddRequestIDs(httpserver.LogRequests(rtr.limiter))))
+       mux.HandleFunc("/metrics.json", theConfig.metrics.exportJSON)
+       mux.Handle("/metrics", theConfig.metrics.exportProm)
+
+       return mux
 }
 
 // BadRequestHandler is a HandleFunc to address bad requests.
index b8a0ffb1cba46777ff1e2d1c745eb8102ea5fa61..03eef7e76b0b897ed2cb70b95f22989b76436123 100644 (file)
@@ -16,9 +16,7 @@ import (
 
        "git.curoverse.com/arvados.git/sdk/go/arvadosclient"
        "git.curoverse.com/arvados.git/sdk/go/config"
-       "git.curoverse.com/arvados.git/sdk/go/httpserver"
        "git.curoverse.com/arvados.git/sdk/go/keepclient"
-       log "github.com/Sirupsen/logrus"
        "github.com/coreos/go-systemd/daemon"
 )
 
@@ -160,9 +158,6 @@ func main() {
 
        // Middleware/handler stack
        router := MakeRESTRouter()
-       limiter := httpserver.NewRequestLimiter(theConfig.MaxRequests, router)
-       router.limiter = limiter
-       http.Handle("/", httpserver.AddRequestIDs(httpserver.LogRequests(limiter)))
 
        // Set up a TCP listener.
        listener, err := net.Listen("tcp", theConfig.Listen)
@@ -204,7 +199,7 @@ func main() {
                log.Printf("Error notifying init daemon: %v", err)
        }
        log.Println("listening at", listener.Addr())
-       srv := &http.Server{}
+       srv := &http.Server{Handler: router}
        srv.Serve(listener)
 }
 
index b4544d0f92225e3d17678dba8cd3b52865206b0f..883aa712e3db0bdcb8fee2eb0a583affd3150e53 100644 (file)
@@ -5,6 +5,7 @@
 package main
 
 import (
+       "bytes"
        "context"
        "encoding/json"
        "net/http"
@@ -24,8 +25,10 @@ type MountsSuite struct {
 func (s *MountsSuite) SetUpTest(c *check.C) {
        s.vm = MakeTestVolumeManager(2)
        KeepVM = s.vm
-       s.rtr = MakeRESTRouter()
+       theConfig = DefaultConfig()
        theConfig.systemAuthToken = arvadostest.DataManagerToken
+       theConfig.Start()
+       s.rtr = MakeRESTRouter()
 }
 
 func (s *MountsSuite) TearDownTest(c *check.C) {
@@ -40,7 +43,7 @@ func (s *MountsSuite) TestMounts(c *check.C) {
        vols[0].Put(context.Background(), TestHash, TestBlock)
        vols[1].Put(context.Background(), TestHash2, TestBlock2)
 
-       resp := s.call("GET", "/mounts", "")
+       resp := s.call("GET", "/mounts", "", nil)
        c.Check(resp.Code, check.Equals, http.StatusOK)
        var mntList []struct {
                UUID        string
@@ -64,7 +67,7 @@ func (s *MountsSuite) TestMounts(c *check.C) {
 
        // Bad auth
        for _, tok := range []string{"", "xyzzy"} {
-               resp = s.call("GET", "/mounts/"+mntList[1].UUID+"/blocks", tok)
+               resp = s.call("GET", "/mounts/"+mntList[1].UUID+"/blocks", tok, nil)
                c.Check(resp.Code, check.Equals, http.StatusUnauthorized)
                c.Check(resp.Body.String(), check.Equals, "Unauthorized\n")
        }
@@ -72,34 +75,74 @@ func (s *MountsSuite) TestMounts(c *check.C) {
        tok := arvadostest.DataManagerToken
 
        // Nonexistent mount UUID
-       resp = s.call("GET", "/mounts/X/blocks", tok)
+       resp = s.call("GET", "/mounts/X/blocks", tok, nil)
        c.Check(resp.Code, check.Equals, http.StatusNotFound)
        c.Check(resp.Body.String(), check.Equals, "mount not found\n")
 
        // Complete index of first mount
-       resp = s.call("GET", "/mounts/"+mntList[0].UUID+"/blocks", tok)
+       resp = s.call("GET", "/mounts/"+mntList[0].UUID+"/blocks", tok, nil)
        c.Check(resp.Code, check.Equals, http.StatusOK)
        c.Check(resp.Body.String(), check.Matches, TestHash+`\+[0-9]+ [0-9]+\n\n`)
 
        // Partial index of first mount (one block matches prefix)
-       resp = s.call("GET", "/mounts/"+mntList[0].UUID+"/blocks?prefix="+TestHash[:2], tok)
+       resp = s.call("GET", "/mounts/"+mntList[0].UUID+"/blocks?prefix="+TestHash[:2], tok, nil)
        c.Check(resp.Code, check.Equals, http.StatusOK)
        c.Check(resp.Body.String(), check.Matches, TestHash+`\+[0-9]+ [0-9]+\n\n`)
 
        // Complete index of second mount (note trailing slash)
-       resp = s.call("GET", "/mounts/"+mntList[1].UUID+"/blocks/", tok)
+       resp = s.call("GET", "/mounts/"+mntList[1].UUID+"/blocks/", tok, nil)
        c.Check(resp.Code, check.Equals, http.StatusOK)
        c.Check(resp.Body.String(), check.Matches, TestHash2+`\+[0-9]+ [0-9]+\n\n`)
 
        // Partial index of second mount (no blocks match prefix)
-       resp = s.call("GET", "/mounts/"+mntList[1].UUID+"/blocks/?prefix="+TestHash[:2], tok)
+       resp = s.call("GET", "/mounts/"+mntList[1].UUID+"/blocks/?prefix="+TestHash[:2], tok, nil)
        c.Check(resp.Code, check.Equals, http.StatusOK)
        c.Check(resp.Body.String(), check.Equals, "\n")
 }
 
-func (s *MountsSuite) call(method, path, tok string) *httptest.ResponseRecorder {
+func (s *MountsSuite) TestMetrics(c *check.C) {
+       s.call("PUT", "/"+TestHash, "", TestBlock)
+       s.call("PUT", "/"+TestHash2, "", TestBlock2)
+       resp := s.call("GET", "/metrics.json", "", nil)
+       c.Check(resp.Code, check.Equals, http.StatusOK)
+       var j []struct {
+               Name   string
+               Help   string
+               Type   string
+               Metric []struct {
+                       Label []struct {
+                               Name  string
+                               Value string
+                       }
+                       Summary struct {
+                               SampleCount string  `json:"sample_count"`
+                               SampleSum   float64 `json:"sample_sum"`
+                               Quantile    []struct {
+                                       Quantile float64
+                                       Value    float64
+                               }
+                       }
+               }
+       }
+       json.NewDecoder(resp.Body).Decode(&j)
+       found := make(map[string]bool)
+       for _, g := range j {
+               for _, m := range g.Metric {
+                       if len(m.Label) == 2 && m.Label[0].Name == "code" && m.Label[0].Value == "200" && m.Label[1].Name == "method" && m.Label[1].Value == "put" {
+                               c.Check(m.Summary.SampleCount, check.Equals, "2")
+                               c.Check(len(m.Summary.Quantile), check.Not(check.Equals), 0)
+                               c.Check(m.Summary.Quantile[0].Value, check.Not(check.Equals), float64(0))
+                               found[g.Name] = true
+                       }
+               }
+       }
+       c.Check(found["request_duration_seconds"], check.Equals, true)
+       c.Check(found["time_to_status_seconds"], check.Equals, true)
+}
+
+func (s *MountsSuite) call(method, path, tok string, body []byte) *httptest.ResponseRecorder {
        resp := httptest.NewRecorder()
-       req, _ := http.NewRequest(method, path, nil)
+       req, _ := http.NewRequest(method, path, bytes.NewReader(body))
        if tok != "" {
                req.Header.Set("Authorization", "OAuth2 "+tok)
        }
index f821fb548350587528c29bc9fab53528b424eaab..42b5d5889d30984685d43655f66fb3857f98de92 100644 (file)
@@ -13,8 +13,6 @@ import (
        "time"
 
        "git.curoverse.com/arvados.git/sdk/go/keepclient"
-
-       log "github.com/Sirupsen/logrus"
 )
 
 // RunPullWorker receives PullRequests from pullq, invokes
index 61e69f9096503eb88cf9328af5e85f129dba4226..90e8a1b4f6913da10b6789a4111a7ac8aa479721 100644 (file)
@@ -23,7 +23,6 @@ import (
        "git.curoverse.com/arvados.git/sdk/go/arvados"
        "github.com/AdRoll/goamz/aws"
        "github.com/AdRoll/goamz/s3"
-       log "github.com/Sirupsen/logrus"
 )
 
 const (
index 3d4a1956230473e264c3b22fc8d5db112b22160f..acc1b11df32526c132d763d970915f9f30735437 100644 (file)
@@ -19,7 +19,6 @@ import (
        "git.curoverse.com/arvados.git/sdk/go/arvados"
        "github.com/AdRoll/goamz/s3"
        "github.com/AdRoll/goamz/s3/s3test"
-       log "github.com/Sirupsen/logrus"
        check "gopkg.in/check.v1"
 )
 
index 51fbb947917328e30db244ca841441a983d8bec5..cbb831ebc000849c71fedd945a4574ea6f4f1171 100644 (file)
@@ -9,7 +9,6 @@ import (
        "time"
 
        "git.curoverse.com/arvados.git/sdk/go/arvados"
-       log "github.com/Sirupsen/logrus"
 )
 
 // RunTrashWorker is used by Keepstore to initiate trash worker channel goroutine.
index da9b110c56e80f1c4572aceb09b65c6dd29e8578..ea9aa489c5af8c357cd8c195851e94456537ce2a 100644 (file)
@@ -20,8 +20,6 @@ import (
        "sync"
        "syscall"
        "time"
-
-       log "github.com/Sirupsen/logrus"
 )
 
 type unixVolumeAdder struct {
index aeac93e475bb265d1ed7fb7fcfb75870604838e3..483ab70b6d0ba15f1f2fa675bd818bff5f1f853b 100644 (file)
                        "revision": "d682213848ed68c0a260ca37d6dd5ace8423f5ba",
                        "revisionTime": "2017-12-05T20:32:29Z"
                },
+               {
+                       "checksumSHA1": "spyv5/YFBjYyZLZa1U2LBfDR8PM=",
+                       "path": "github.com/beorn7/perks/quantile",
+                       "revision": "4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9",
+                       "revisionTime": "2016-08-04T10:47:26Z"
+               },
                {
                        "checksumSHA1": "+Zz+leZHHC9C0rx8DoRuffSRPso=",
                        "path": "github.com/coreos/go-systemd/daemon",
                        "revision": "160de10b2537169b5ae3e7e221d28269ef40d311",
                        "revisionTime": "2018-01-04T10:21:28Z"
                },
+               {
+                       "checksumSHA1": "iVfdaLxIDjfk2KLP8dCMIbsxZZM=",
+                       "path": "github.com/golang/protobuf/jsonpb",
+                       "revision": "1e59b77b52bf8e4b449a57e6f79f21226d571845",
+                       "revisionTime": "2017-11-13T18:07:20Z"
+               },
+               {
+                       "checksumSHA1": "yqF125xVSkmfLpIVGrLlfE05IUk=",
+                       "path": "github.com/golang/protobuf/proto",
+                       "revision": "1e59b77b52bf8e4b449a57e6f79f21226d571845",
+                       "revisionTime": "2017-11-13T18:07:20Z"
+               },
+               {
+                       "checksumSHA1": "Ylq6kq3KWBy6mu68oyEwenhNMdg=",
+                       "path": "github.com/golang/protobuf/ptypes/struct",
+                       "revision": "1e59b77b52bf8e4b449a57e6f79f21226d571845",
+                       "revisionTime": "2017-11-13T18:07:20Z"
+               },
                {
                        "checksumSHA1": "iIUYZyoanCQQTUaWsu8b+iOSPt4=",
                        "origin": "github.com/docker/docker/vendor/github.com/gorilla/context",
                        "revision": "83612a56d3dd153a94a629cd64925371c9adad78",
                        "revisionTime": "2017-11-26T05:04:59Z"
                },
+               {
+                       "checksumSHA1": "bKMZjd2wPw13VwoE7mBeSv5djFA=",
+                       "path": "github.com/matttproud/golang_protobuf_extensions/pbutil",
+                       "revision": "c12348ce28de40eed0136aa2b644d0ee0650e56c",
+                       "revisionTime": "2016-04-24T11:30:07Z"
+               },
                {
                        "checksumSHA1": "V/quM7+em2ByJbWBLOsEwnY3j/Q=",
                        "path": "github.com/mitchellh/go-homedir",
                        "revision": "e881fd58d78e04cf6d0de1217f8707c8cc2249bc",
                        "revisionTime": "2017-12-16T07:03:16Z"
                },
+               {
+                       "checksumSHA1": "Ajt29IHVbX99PUvzn8Gc/lMCXBY=",
+                       "path": "github.com/prometheus/client_golang/prometheus",
+                       "revision": "9bb6ab929dcbe1c8393cd9ef70387cb69811bd1c",
+                       "revisionTime": "2018-02-03T14:28:15Z"
+               },
+               {
+                       "checksumSHA1": "c3Ui7nnLiJ4CAGWZ8dGuEgqHd8s=",
+                       "path": "github.com/prometheus/client_golang/prometheus/promhttp",
+                       "revision": "9bb6ab929dcbe1c8393cd9ef70387cb69811bd1c",
+                       "revisionTime": "2018-02-03T14:28:15Z"
+               },
+               {
+                       "checksumSHA1": "DvwvOlPNAgRntBzt3b3OSRMS2N4=",
+                       "path": "github.com/prometheus/client_model/go",
+                       "revision": "99fa1f4be8e564e8a6b613da7fa6f46c9edafc6c",
+                       "revisionTime": "2017-11-17T10:05:41Z"
+               },
+               {
+                       "checksumSHA1": "xfnn0THnqNwjwimeTClsxahYrIo=",
+                       "path": "github.com/prometheus/common/expfmt",
+                       "revision": "89604d197083d4781071d3c65855d24ecfb0a563",
+                       "revisionTime": "2018-01-10T21:49:58Z"
+               },
+               {
+                       "checksumSHA1": "GWlM3d2vPYyNATtTFgftS10/A9w=",
+                       "path": "github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg",
+                       "revision": "89604d197083d4781071d3c65855d24ecfb0a563",
+                       "revisionTime": "2018-01-10T21:49:58Z"
+               },
+               {
+                       "checksumSHA1": "YU+/K48IMawQnToO4ETE6a+hhj4=",
+                       "path": "github.com/prometheus/common/model",
+                       "revision": "89604d197083d4781071d3c65855d24ecfb0a563",
+                       "revisionTime": "2018-01-10T21:49:58Z"
+               },
+               {
+                       "checksumSHA1": "lolK0h7LSVERIX8zLyVQ/+7wEyA=",
+                       "path": "github.com/prometheus/procfs",
+                       "revision": "cb4147076ac75738c9a7d279075a253c0cc5acbd",
+                       "revisionTime": "2018-01-25T13:30:57Z"
+               },
+               {
+                       "checksumSHA1": "lv9rIcjbVEGo8AT1UCUZXhXrfQc=",
+                       "path": "github.com/prometheus/procfs/internal/util",
+                       "revision": "cb4147076ac75738c9a7d279075a253c0cc5acbd",
+                       "revisionTime": "2018-01-25T13:30:57Z"
+               },
+               {
+                       "checksumSHA1": "BXJH5h2ri8SU5qC6kkDvTIGCky4=",
+                       "path": "github.com/prometheus/procfs/nfs",
+                       "revision": "cb4147076ac75738c9a7d279075a253c0cc5acbd",
+                       "revisionTime": "2018-01-25T13:30:57Z"
+               },
+               {
+                       "checksumSHA1": "yItvTQLUVqm/ArLEbvEhqG0T5a0=",
+                       "path": "github.com/prometheus/procfs/xfs",
+                       "revision": "cb4147076ac75738c9a7d279075a253c0cc5acbd",
+                       "revisionTime": "2018-01-25T13:30:57Z"
+               },
                {
                        "checksumSHA1": "UwtyqB7CaUWPlw0DVJQvw0IFQZs=",
                        "path": "github.com/sergi/go-diff/diffmatchpatch",