Logging improvements
This commit is contained in:
Родитель
bb9a4c3572
Коммит
ba7744adfa
|
@ -11,7 +11,7 @@ import (
|
|||
// The Factory interface represents an object that can create its Policy object. Each HTTP request sent
|
||||
// requires that this Factory create a new instance of its Policy object.
|
||||
type Factory interface {
|
||||
New(node Node) Policy
|
||||
New(next Policy, config *Configuration) Policy
|
||||
}
|
||||
|
||||
// The Policy interface represents a mutable Policy object created by a Factory. The object can mutate/process
|
||||
|
@ -113,8 +113,8 @@ func (p *pipeline) Do(ctx context.Context, methodFactory Factory, request Reques
|
|||
func (p *pipeline) newPolicies(methodFactory Factory) Policy {
|
||||
// The last Policy is the one that actually sends the request over the wire and gets the response.
|
||||
// It is overridable via the Options' HTTPSender field.
|
||||
node := Node{pipeline: p, next: nil}
|
||||
node.next = p.options.HTTPSender.New(node)
|
||||
config := &Configuration{pipeline: p} // One object shared by all policy objects
|
||||
next := p.options.HTTPSender.New(nil, config)
|
||||
|
||||
// Walk over the slice of Factory objects in reverse (from wire to API)
|
||||
markers := 0
|
||||
|
@ -127,11 +127,11 @@ func (p *pipeline) newPolicies(methodFactory Factory) Policy {
|
|||
}
|
||||
if methodFactory != nil {
|
||||
// Replace MethodFactoryMarker with passed-in methodFactory
|
||||
node.next = methodFactory.New(node)
|
||||
next = methodFactory.New(next, config)
|
||||
}
|
||||
} else {
|
||||
// Use the slice's Factory to construct its Policy
|
||||
node.next = factory.New(node)
|
||||
next = factory.New(next, config)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -139,39 +139,32 @@ func (p *pipeline) newPolicies(methodFactory Factory) Policy {
|
|||
if markers == 0 && methodFactory != nil {
|
||||
panic("Non-nil methodFactory requires MethodFactoryMarker in the pipeline")
|
||||
}
|
||||
return node.next // Return head of the Policy object linked-list
|
||||
return next // Return head of the Policy object linked-list
|
||||
}
|
||||
|
||||
// A Node represents a node in a linked-list of Policy objects. A Node is passed
|
||||
// to the Factory's New method which passes to the Policy object it creates. The Policy object
|
||||
// uses the Node to forward the Context and HTTP request to the next Policy object in the pipeline.
|
||||
type Node struct {
|
||||
// A Configuration represents additional configuration information that can optionally be used
|
||||
// by a node in the linked-list of Policy objects. A Configuration is passed to the Factory's
|
||||
// New method which passes it (if desired) to the Policy object it creates. Today, the Policy object
|
||||
// uses the Configuration to perform logging. But, in the future, this could be used for more.
|
||||
type Configuration struct {
|
||||
pipeline *pipeline
|
||||
next Policy
|
||||
}
|
||||
|
||||
// Do forwards the Context and HTTP request to the next Policy object in the pipeline. The last Policy object
|
||||
// sends the request over the network via HTTPSender's Do method. The response and error are returned
|
||||
// back up the pipeline through the Policy objects.
|
||||
func (n *Node) Do(ctx context.Context, request Request) (Response, error) {
|
||||
return n.next.Do(ctx, request)
|
||||
}
|
||||
|
||||
// ShouldLog returns true if the specified log level should be logged.
|
||||
func (n *Node) ShouldLog(level LogLevel) bool {
|
||||
func (c *Configuration) ShouldLog(level LogLevel) bool {
|
||||
if level == LogNone {
|
||||
return false
|
||||
}
|
||||
minimumLevel := LogNone
|
||||
if n.pipeline.options.Log.MinimumLevelToLog != nil {
|
||||
minimumLevel = n.pipeline.options.Log.MinimumLevelToLog()
|
||||
if c.pipeline.options.Log.MinimumLevelToLog != nil {
|
||||
minimumLevel = c.pipeline.options.Log.MinimumLevelToLog()
|
||||
}
|
||||
return level <= minimumLevel
|
||||
}
|
||||
|
||||
// Log logs a string to the Pipeline's Logger.
|
||||
func (n *Node) Log(level LogLevel, msg string) {
|
||||
if !n.ShouldLog(level) {
|
||||
func (c *Configuration) Log(level LogLevel, msg string) {
|
||||
if !c.ShouldLog(level) {
|
||||
return // Short circuit message formatting if we're not logging it
|
||||
}
|
||||
|
||||
|
@ -179,7 +172,7 @@ func (n *Node) Log(level LogLevel, msg string) {
|
|||
if len(msg) == 0 || msg[len(msg)-1] != '\n' {
|
||||
msg += "\n" // Ensure trailing newline
|
||||
}
|
||||
n.pipeline.options.Log.Log(level, msg)
|
||||
c.pipeline.options.Log.Log(level, msg)
|
||||
|
||||
// If logger doesn't handle fatal/panic, we'll do it here.
|
||||
if level == LogFatal {
|
||||
|
@ -224,12 +217,12 @@ type defaultHTTPClientPolicyFactory struct {
|
|||
}
|
||||
|
||||
// Create initializes a logging policy object.
|
||||
func (f *defaultHTTPClientPolicyFactory) New(node Node) Policy {
|
||||
return &defaultHTTPClientPolicy{node: node}
|
||||
func (f *defaultHTTPClientPolicyFactory) New(next Policy, config *Configuration) Policy {
|
||||
return &defaultHTTPClientPolicy{config: config}
|
||||
}
|
||||
|
||||
type defaultHTTPClientPolicy struct {
|
||||
node Node
|
||||
config *Configuration
|
||||
}
|
||||
|
||||
func (p *defaultHTTPClientPolicy) Do(ctx context.Context, request Request) (Response, error) {
|
||||
|
@ -252,6 +245,6 @@ func MethodFactoryMarker() Factory {
|
|||
type methodFactoryMarker struct {
|
||||
}
|
||||
|
||||
func (mpmf methodFactoryMarker) New(node Node) Policy {
|
||||
func (mpmf methodFactoryMarker) New(next Policy, config *Configuration) Policy {
|
||||
panic("methodFactoryMarker policy should have been replaced with a method policy")
|
||||
}
|
||||
|
|
|
@ -18,12 +18,13 @@ type myPolicyFactory struct {
|
|||
}
|
||||
|
||||
// New initializes a Xxx policy object.
|
||||
func (f *myPolicyFactory) New(node Node) Policy {
|
||||
return &myPolicy{node: node /* Set desired fields */}
|
||||
func (f *myPolicyFactory) New(next Policy, config *Configuration) Policy {
|
||||
return &myPolicy{next: next, config: config /* Set desired fields */}
|
||||
}
|
||||
|
||||
type myPolicy struct {
|
||||
node Node // Mandatory private field
|
||||
next Policy
|
||||
config *Configuration // Mandatory private field
|
||||
// Additional desired fields (mutable for use by this specific Policy object)
|
||||
}
|
||||
|
||||
|
@ -34,7 +35,7 @@ func (p *myPolicy) Do(ctx context.Context, request Request) (response Response,
|
|||
// You can also pass a different Context on.
|
||||
|
||||
// Forward the request to the next node in the pipeline:
|
||||
response, err = p.node.Do(ctx, request)
|
||||
response, err = p.next.Do(ctx, request)
|
||||
|
||||
// Process the response here. You can deserialize the body into an object.
|
||||
// If you do this, also define a struct that wraps an http.Response & your
|
||||
|
|
|
@ -34,18 +34,21 @@ func (r httpResponse) Response() *http.Response {
|
|||
return r.response
|
||||
}
|
||||
|
||||
// WriteRequest appends a formatted HTTP request into a Buffer.
|
||||
func WriteRequest(b *bytes.Buffer, request *http.Request) {
|
||||
// WriteRequestWithResponse appends a formatted HTTP request into a Buffer. If request and/or err are
|
||||
// not nil, then these are also written into the Buffer.
|
||||
func WriteRequestWithResponse(b *bytes.Buffer, request *http.Request, response *http.Response, err error) {
|
||||
// Write the request into the buffer.
|
||||
fmt.Fprint(b, " "+request.Method+" "+request.URL.String()+"\n")
|
||||
writeHeader(b, request.Header)
|
||||
}
|
||||
|
||||
// WriteRequestWithResponse appends a formatted HTTP response with its initiating request into a Buffer.
|
||||
func WriteRequestWithResponse(b *bytes.Buffer, request *http.Request, response *http.Response) {
|
||||
WriteRequest(b, request) // Write the request first followed by the response.
|
||||
fmt.Fprintln(b, " --------------------------------------------------------------------------------")
|
||||
fmt.Fprintf(b, " RESPONSE Status: %s\n", response.Status)
|
||||
writeHeader(b, response.Header)
|
||||
if response != nil {
|
||||
fmt.Fprintln(b, " --------------------------------------------------------------------------------")
|
||||
fmt.Fprintf(b, " RESPONSE Status: %s\n", response.Status)
|
||||
writeHeader(b, response.Header)
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Fprintln(b, " --------------------------------------------------------------------------------")
|
||||
fmt.Fprintf(b, " ERROR:\n%v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
// formatHeaders appends an HTTP request's or response's header into a Buffer.
|
||||
|
|
Загрузка…
Ссылка в новой задаче