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  }