Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(696)

Side by Side Diff: appengine/tsmon/middleware.go

Issue 2043423004: Make HTTP middleware easier to use (Closed) Base URL: https://github.com/luci/luci-go@master
Patch Set: Rebase origin/master Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698