github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/apiserver/observer/request_notifier.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 package observer 4 5 import ( 6 "net/http" 7 "time" 8 9 "gopkg.in/juju/names.v2" 10 11 "github.com/juju/loggo" 12 "github.com/juju/utils/clock" 13 14 "github.com/juju/juju/rpc" 15 "github.com/juju/juju/rpc/jsoncodec" 16 ) 17 18 // RequestObserver serves as a sink for API server requests and 19 // responses. 20 type RequestObserver struct { 21 clock clock.Clock 22 logger loggo.Logger 23 apiConnectionCount func() int64 24 25 // state represents information that's built up as methods on this 26 // type are called. We segregate this to ensure it's clear what 27 // information is transient in case we want to extract it 28 // later. It's an anonymous struct so this doesn't leak outside 29 // this type. 30 state struct { 31 id uint64 32 websocketConnected time.Time 33 tag string 34 } 35 } 36 37 // RequestObservercontext provides information needed for a 38 // RequestObserverContext to operate correctly. 39 type RequestObserverContext struct { 40 41 // Clock is the clock to use for all time operations on this type. 42 Clock clock.Clock 43 44 // Logger is the log to use to write log statements. 45 Logger loggo.Logger 46 } 47 48 // NewRequestObserver returns a new RPCObserver. 49 func NewRequestObserver(ctx RequestObserverContext) *RequestObserver { 50 return &RequestObserver{ 51 clock: ctx.Clock, 52 logger: ctx.Logger, 53 } 54 } 55 56 // Login implements Observer. 57 func (n *RequestObserver) Login(entity names.Tag, _ names.ModelTag, _ bool, _ string) { 58 n.state.tag = entity.String() 59 } 60 61 // Join implements Observer. 62 func (n *RequestObserver) Join(req *http.Request, connectionID uint64) { 63 n.state.id = connectionID 64 n.state.websocketConnected = n.clock.Now() 65 66 n.logger.Debugf( 67 "[%X] API connection from %s", 68 n.state.id, 69 req.RemoteAddr, 70 ) 71 } 72 73 // Leave implements Observer. 74 func (n *RequestObserver) Leave() { 75 n.logger.Debugf( 76 "[%X] %s API connection terminated after %v", 77 n.state.id, 78 n.state.tag, 79 time.Since(n.state.websocketConnected), 80 ) 81 } 82 83 // RPCObserver implements Observer. 84 func (n *RequestObserver) RPCObserver() rpc.Observer { 85 return &rpcObserver{ 86 clock: n.clock, 87 logger: n.logger, 88 id: n.state.id, 89 tag: n.state.tag, 90 } 91 } 92 93 // rpcObserver serves as a sink for RPC requests and responses. 94 type rpcObserver struct { 95 clock clock.Clock 96 logger loggo.Logger 97 id uint64 98 tag string 99 requestStart time.Time 100 } 101 102 // ServerReques timplements rpc.Observer. 103 func (n *rpcObserver) ServerRequest(hdr *rpc.Header, body interface{}) { 104 n.requestStart = n.clock.Now() 105 106 if hdr.Request.Type == "Pinger" && hdr.Request.Action == "Ping" { 107 return 108 } 109 // TODO(rog) 2013-10-11 remove secrets from some requests. 110 // Until secrets are removed, we only log the body of the requests at trace level 111 // which is below the default level of debug. 112 if n.logger.IsTraceEnabled() { 113 n.logger.Tracef("<- [%X] %s %s", n.id, n.tag, jsoncodec.DumpRequest(hdr, body)) 114 } else { 115 n.logger.Debugf("<- [%X] %s %s", n.id, n.tag, jsoncodec.DumpRequest(hdr, "'params redacted'")) 116 } 117 } 118 119 // ServerReply implements rpc.Observer. 120 func (n *rpcObserver) ServerReply(req rpc.Request, hdr *rpc.Header, body interface{}) { 121 if req.Type == "Pinger" && req.Action == "Ping" { 122 return 123 } 124 125 // TODO(rog) 2013-10-11 remove secrets from some responses. 126 // Until secrets are removed, we only log the body of the requests at trace level 127 // which is below the default level of debug. 128 if n.logger.IsTraceEnabled() { 129 n.logger.Tracef("-> [%X] %s %s", n.id, n.tag, jsoncodec.DumpRequest(hdr, body)) 130 } else { 131 n.logger.Debugf( 132 "-> [%X] %s %s %s %s[%q].%s", 133 n.id, 134 n.tag, 135 time.Since(n.requestStart), 136 jsoncodec.DumpRequest(hdr, "'body redacted'"), 137 req.Type, 138 req.Id, 139 req.Action, 140 ) 141 } 142 }