Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The LUCI Authors. All rights reserved. | 1 // Copyright 2016 The LUCI Authors. All rights reserved. |
| 2 // Use of this source code is governed under the Apache License, Version 2.0 | 2 // Use of this source code is governed under the Apache License, Version 2.0 |
| 3 // that can be found in the LICENSE file. | 3 // that can be found in the LICENSE file. |
| 4 | 4 |
| 5 package tsmon | 5 package tsmon |
| 6 | 6 |
| 7 import ( | 7 import ( |
| 8 "fmt" | 8 "fmt" |
| 9 "net/http" | 9 "net/http" |
| 10 "strings" | 10 "strings" |
| 11 "sync" | 11 "sync" |
| 12 "time" | 12 "time" |
| 13 | 13 |
| 14 "github.com/golang/protobuf/proto" | 14 "github.com/golang/protobuf/proto" |
| 15 "github.com/julienschmidt/httprouter" | |
| 16 "golang.org/x/net/context" | 15 "golang.org/x/net/context" |
| 17 | 16 |
| 18 "github.com/luci/gae/service/info" | 17 "github.com/luci/gae/service/info" |
| 19 gaeauth "github.com/luci/luci-go/appengine/gaeauth/client" | 18 gaeauth "github.com/luci/luci-go/appengine/gaeauth/client" |
| 20 "github.com/luci/luci-go/common/clock" | 19 "github.com/luci/luci-go/common/clock" |
| 21 gcps "github.com/luci/luci-go/common/gcloud/pubsub" | 20 gcps "github.com/luci/luci-go/common/gcloud/pubsub" |
| 22 "github.com/luci/luci-go/common/iotools" | 21 "github.com/luci/luci-go/common/iotools" |
| 23 "github.com/luci/luci-go/common/logging" | 22 "github.com/luci/luci-go/common/logging" |
| 24 "github.com/luci/luci-go/common/tsmon" | 23 "github.com/luci/luci-go/common/tsmon" |
| 25 "github.com/luci/luci-go/common/tsmon/metric" | 24 "github.com/luci/luci-go/common/tsmon/metric" |
| 26 "github.com/luci/luci-go/common/tsmon/monitor" | 25 "github.com/luci/luci-go/common/tsmon/monitor" |
| 27 "github.com/luci/luci-go/common/tsmon/store" | 26 "github.com/luci/luci-go/common/tsmon/store" |
| 28 "github.com/luci/luci-go/common/tsmon/target" | 27 "github.com/luci/luci-go/common/tsmon/target" |
| 29 » "github.com/luci/luci-go/server/middleware" | 28 » "github.com/luci/luci-go/server/router" |
| 30 ) | 29 ) |
| 31 | 30 |
| 32 // State holds the configuration of the tsmon library for GAE. | 31 // State holds the configuration of the tsmon library for GAE. |
| 33 // | 32 // |
| 34 // Define it as a global variable and inject it in the request contexts using | 33 // Define it as a global variable and inject it in the request contexts using |
| 35 // State.Middleware(). | 34 // State.Middleware(). |
| 36 // | 35 // |
| 37 // It will initialize itself from the tsmon state in the passed context on | 36 // It will initialize itself from the tsmon state in the passed context on |
| 38 // a first use, mutating it along the way. Assumes caller is consistently using | 37 // a first use, mutating it along the way. Assumes caller is consistently using |
| 39 // contexts configured with exact same tsmon state (in a vast majority of cases | 38 // contexts configured with exact same tsmon state (in a vast majority of cases |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 77 } | 76 } |
| 78 | 77 |
| 79 func newResponseWriter(rw http.ResponseWriter) responseWriter { | 78 func newResponseWriter(rw http.ResponseWriter) responseWriter { |
| 80 return responseWriter{ | 79 return responseWriter{ |
| 81 ResponseWriter: rw, | 80 ResponseWriter: rw, |
| 82 writer: iotools.CountingWriter{Writer: rw}, | 81 writer: iotools.CountingWriter{Writer: rw}, |
| 83 status: http.StatusOK, | 82 status: http.StatusOK, |
| 84 } | 83 } |
| 85 } | 84 } |
| 86 | 85 |
| 87 // Middleware returns a middleware that must be inserted into the chain to | 86 // Middleware returns a middleware that must be inserted into the middleware |
|
Vadim Sh.
2016/06/18 16:57:20
nit: "is a middleware"
nishanths
2016/06/19 02:47:02
Done.
| |
| 88 // enable tsmon metrics to be sent on App Engine. | 87 // chain to enable tsmon metrics to be send on AppEngine. |
| 89 func (s *State) Middleware(h middleware.Handler) middleware.Handler { | 88 func (s *State) Middleware(c *router.Context, next router.Handler) { |
| 90 » return func(c context.Context, rw http.ResponseWriter, r *http.Request, p httprouter.Params) { | 89 » state, settings := s.checkSettings(c.Context) |
| 91 » » state, settings := s.checkSettings(c) | 90 » if settings.Enabled { |
| 92 » » if settings.Enabled { | 91 » » started := clock.Now(c.Context) |
| 93 » » » started := clock.Now(c) | 92 » » userAgent, ok := c.Request.Header["User-Agent"] |
| 94 » » » userAgent, ok := r.Header["User-Agent"] | 93 » » if !ok || len(userAgent) == 0 { |
| 95 » » » if !ok || len(userAgent) == 0 { | 94 » » » userAgent = []string{"Unknown"} |
| 96 » » » » userAgent = []string{"Unknown"} | |
| 97 » » » } | |
| 98 » » » nrw := newResponseWriter(rw) | |
| 99 » » » defer func() { | |
| 100 » » » » dur := clock.Now(c).Sub(started) | |
| 101 » » » » metric.UpdatePresenceMetrics(c) | |
| 102 » » » » metric.UpdateServerMetrics(c, "/", nrw.Status(), dur, | |
| 103 » » » » » r.ContentLength, nrw.Size(), userAgent[0 ]) | |
| 104 » » » }() | |
| 105 » » » h(c, nrw, r, p) | |
| 106 » » » s.flushIfNeeded(c, state, settings) | |
| 107 » » } else { | |
| 108 » » » h(c, rw, r, p) | |
| 109 } | 95 } |
| 96 nrw := newResponseWriter(c.Writer) | |
| 97 c.Writer = nrw | |
| 98 defer func() { | |
| 99 dur := clock.Now(c.Context).Sub(started) | |
| 100 metric.UpdatePresenceMetrics(c.Context) | |
| 101 metric.UpdateServerMetrics(c.Context, "/", nrw.Status(), dur, | |
| 102 c.Request.ContentLength, nrw.Size(), userAgent[0 ]) | |
| 103 }() | |
| 104 next(c) | |
| 105 s.flushIfNeeded(c.Context, state, settings) | |
|
Vadim Sh.
2016/06/18 16:57:20
I think we need to preserve the original c.Context
nishanths
2016/06/19 02:47:02
Done. With Patch Set 39 applied, it matches behavi
nishanths
2016/06/20 15:14:29
typo: meant Patch Set 30 at both spots above
| |
| 106 } else { | |
| 107 next(c) | |
| 110 } | 108 } |
| 111 } | 109 } |
| 112 | 110 |
| 113 // checkSettings fetches tsmon settings and initializes, reinitializes or | 111 // checkSettings fetches tsmon settings and initializes, reinitializes or |
| 114 // deinitializes tsmon, as needed. | 112 // deinitializes tsmon, as needed. |
| 115 // | 113 // |
| 116 // Returns current tsmon state and settings. Panics if the context is using | 114 // Returns current tsmon state and settings. Panics if the context is using |
| 117 // unexpected tsmon state. | 115 // unexpected tsmon state. |
| 118 func (s *State) checkSettings(c context.Context) (*tsmon.State, *tsmonSettings) { | 116 func (s *State) checkSettings(c context.Context) (*tsmon.State, *tsmonSettings) { |
| 119 state := tsmon.GetState(c) | 117 state := tsmon.GetState(c) |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 327 } | 325 } |
| 328 } | 326 } |
| 329 | 327 |
| 330 if err := state.Flush(c, mon); err != nil { | 328 if err := state.Flush(c, mon); err != nil { |
| 331 return err | 329 return err |
| 332 } | 330 } |
| 333 | 331 |
| 334 state.ResetGlobalCallbackMetrics(c) | 332 state.ResetGlobalCallbackMetrics(c) |
| 335 return nil | 333 return nil |
| 336 } | 334 } |
| OLD | NEW |