github.com/aavshr/aws-sdk-go@v1.41.3/aws/client/logger.go (about) 1 package client 2 3 import ( 4 "bytes" 5 "fmt" 6 "io" 7 "io/ioutil" 8 "net/http/httputil" 9 10 "github.com/aavshr/aws-sdk-go/aws" 11 "github.com/aavshr/aws-sdk-go/aws/request" 12 ) 13 14 const logReqMsg = `DEBUG: Request %s/%s Details: 15 ---[ REQUEST POST-SIGN ]----------------------------- 16 %s 17 -----------------------------------------------------` 18 19 const logReqErrMsg = `DEBUG ERROR: Request %s/%s: 20 ---[ REQUEST DUMP ERROR ]----------------------------- 21 %s 22 ------------------------------------------------------` 23 24 type logWriter struct { 25 // Logger is what we will use to log the payload of a response. 26 Logger aws.Logger 27 // buf stores the contents of what has been read 28 buf *bytes.Buffer 29 } 30 31 func (logger *logWriter) Write(b []byte) (int, error) { 32 return logger.buf.Write(b) 33 } 34 35 type teeReaderCloser struct { 36 // io.Reader will be a tee reader that is used during logging. 37 // This structure will read from a body and write the contents to a logger. 38 io.Reader 39 // Source is used just to close when we are done reading. 40 Source io.ReadCloser 41 } 42 43 func (reader *teeReaderCloser) Close() error { 44 return reader.Source.Close() 45 } 46 47 // LogHTTPRequestHandler is a SDK request handler to log the HTTP request sent 48 // to a service. Will include the HTTP request body if the LogLevel of the 49 // request matches LogDebugWithHTTPBody. 50 var LogHTTPRequestHandler = request.NamedHandler{ 51 Name: "awssdk.client.LogRequest", 52 Fn: logRequest, 53 } 54 55 func logRequest(r *request.Request) { 56 if !r.Config.LogLevel.AtLeast(aws.LogDebug) || r.Config.Logger == nil { 57 return 58 } 59 60 logBody := r.Config.LogLevel.Matches(aws.LogDebugWithHTTPBody) 61 bodySeekable := aws.IsReaderSeekable(r.Body) 62 63 b, err := httputil.DumpRequestOut(r.HTTPRequest, logBody) 64 if err != nil { 65 r.Config.Logger.Log(fmt.Sprintf(logReqErrMsg, 66 r.ClientInfo.ServiceName, r.Operation.Name, err)) 67 return 68 } 69 70 if logBody { 71 if !bodySeekable { 72 r.SetReaderBody(aws.ReadSeekCloser(r.HTTPRequest.Body)) 73 } 74 // Reset the request body because dumpRequest will re-wrap the 75 // r.HTTPRequest's Body as a NoOpCloser and will not be reset after 76 // read by the HTTP client reader. 77 if err := r.Error; err != nil { 78 r.Config.Logger.Log(fmt.Sprintf(logReqErrMsg, 79 r.ClientInfo.ServiceName, r.Operation.Name, err)) 80 return 81 } 82 } 83 84 r.Config.Logger.Log(fmt.Sprintf(logReqMsg, 85 r.ClientInfo.ServiceName, r.Operation.Name, string(b))) 86 } 87 88 // LogHTTPRequestHeaderHandler is a SDK request handler to log the HTTP request sent 89 // to a service. Will only log the HTTP request's headers. The request payload 90 // will not be read. 91 var LogHTTPRequestHeaderHandler = request.NamedHandler{ 92 Name: "awssdk.client.LogRequestHeader", 93 Fn: logRequestHeader, 94 } 95 96 func logRequestHeader(r *request.Request) { 97 if !r.Config.LogLevel.AtLeast(aws.LogDebug) || r.Config.Logger == nil { 98 return 99 } 100 101 b, err := httputil.DumpRequestOut(r.HTTPRequest, false) 102 if err != nil { 103 r.Config.Logger.Log(fmt.Sprintf(logReqErrMsg, 104 r.ClientInfo.ServiceName, r.Operation.Name, err)) 105 return 106 } 107 108 r.Config.Logger.Log(fmt.Sprintf(logReqMsg, 109 r.ClientInfo.ServiceName, r.Operation.Name, string(b))) 110 } 111 112 const logRespMsg = `DEBUG: Response %s/%s Details: 113 ---[ RESPONSE ]-------------------------------------- 114 %s 115 -----------------------------------------------------` 116 117 const logRespErrMsg = `DEBUG ERROR: Response %s/%s: 118 ---[ RESPONSE DUMP ERROR ]----------------------------- 119 %s 120 -----------------------------------------------------` 121 122 // LogHTTPResponseHandler is a SDK request handler to log the HTTP response 123 // received from a service. Will include the HTTP response body if the LogLevel 124 // of the request matches LogDebugWithHTTPBody. 125 var LogHTTPResponseHandler = request.NamedHandler{ 126 Name: "awssdk.client.LogResponse", 127 Fn: logResponse, 128 } 129 130 func logResponse(r *request.Request) { 131 if !r.Config.LogLevel.AtLeast(aws.LogDebug) || r.Config.Logger == nil { 132 return 133 } 134 135 lw := &logWriter{r.Config.Logger, bytes.NewBuffer(nil)} 136 137 if r.HTTPResponse == nil { 138 lw.Logger.Log(fmt.Sprintf(logRespErrMsg, 139 r.ClientInfo.ServiceName, r.Operation.Name, "request's HTTPResponse is nil")) 140 return 141 } 142 143 logBody := r.Config.LogLevel.Matches(aws.LogDebugWithHTTPBody) 144 if logBody { 145 r.HTTPResponse.Body = &teeReaderCloser{ 146 Reader: io.TeeReader(r.HTTPResponse.Body, lw), 147 Source: r.HTTPResponse.Body, 148 } 149 } 150 151 handlerFn := func(req *request.Request) { 152 b, err := httputil.DumpResponse(req.HTTPResponse, false) 153 if err != nil { 154 lw.Logger.Log(fmt.Sprintf(logRespErrMsg, 155 req.ClientInfo.ServiceName, req.Operation.Name, err)) 156 return 157 } 158 159 lw.Logger.Log(fmt.Sprintf(logRespMsg, 160 req.ClientInfo.ServiceName, req.Operation.Name, string(b))) 161 162 if logBody { 163 b, err := ioutil.ReadAll(lw.buf) 164 if err != nil { 165 lw.Logger.Log(fmt.Sprintf(logRespErrMsg, 166 req.ClientInfo.ServiceName, req.Operation.Name, err)) 167 return 168 } 169 170 lw.Logger.Log(string(b)) 171 } 172 } 173 174 const handlerName = "awsdk.client.LogResponse.ResponseBody" 175 176 r.Handlers.Unmarshal.SetBackNamed(request.NamedHandler{ 177 Name: handlerName, Fn: handlerFn, 178 }) 179 r.Handlers.UnmarshalError.SetBackNamed(request.NamedHandler{ 180 Name: handlerName, Fn: handlerFn, 181 }) 182 } 183 184 // LogHTTPResponseHeaderHandler is a SDK request handler to log the HTTP 185 // response received from a service. Will only log the HTTP response's headers. 186 // The response payload will not be read. 187 var LogHTTPResponseHeaderHandler = request.NamedHandler{ 188 Name: "awssdk.client.LogResponseHeader", 189 Fn: logResponseHeader, 190 } 191 192 func logResponseHeader(r *request.Request) { 193 if !r.Config.LogLevel.AtLeast(aws.LogDebug) || r.Config.Logger == nil { 194 return 195 } 196 197 b, err := httputil.DumpResponse(r.HTTPResponse, false) 198 if err != nil { 199 r.Config.Logger.Log(fmt.Sprintf(logRespErrMsg, 200 r.ClientInfo.ServiceName, r.Operation.Name, err)) 201 return 202 } 203 204 r.Config.Logger.Log(fmt.Sprintf(logRespMsg, 205 r.ClientInfo.ServiceName, r.Operation.Name, string(b))) 206 }