From 092081578428d03d0db905fa2a9fcd338d19d135 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Tue, 27 Jul 2021 11:11:14 -0400 Subject: [PATCH 01/14] initial work, issues with using internal package --- sdk/azcore/ci.yml | 1 + sdk/azcore/example_test.go | 20 ++-- sdk/azcore/go.mod | 2 + sdk/azcore/log.go | 168 ++++++++++++++++-------------- sdk/azcore/log_test.go | 40 +++---- sdk/azcore/policy_logging.go | 11 +- sdk/azcore/policy_logging_test.go | 4 +- sdk/azcore/policy_retry.go | 18 ++-- sdk/azcore/poller.go | 12 ++- sdk/internal/ci.yml | 3 +- sdk/internal/logger/logger.go | 116 +++++++++++++++++++++ 11 files changed, 264 insertions(+), 131 deletions(-) create mode 100644 sdk/internal/logger/logger.go diff --git a/sdk/azcore/ci.yml b/sdk/azcore/ci.yml index 9ed5180726cb..7a92f020535c 100644 --- a/sdk/azcore/ci.yml +++ b/sdk/azcore/ci.yml @@ -3,6 +3,7 @@ trigger: paths: include: - sdk/azcore/ + - eng/ pr: paths: diff --git a/sdk/azcore/example_test.go b/sdk/azcore/example_test.go index e5e8c6b61d91..affe7f7f31da 100644 --- a/sdk/azcore/example_test.go +++ b/sdk/azcore/example_test.go @@ -48,23 +48,23 @@ func ExampleRequest_SetBody() { } } -func ExampleLogger_Should() { - // you can create your own logging classification as needed - const LogExpensiveThing azcore.LogClassification = "ExpensiveThing" - if azcore.Log().Should(LogExpensiveThing) { - // perform expensive calculation only when enabled - azcore.Log().Write(LogExpensiveThing, "expensive log message") - } -} +// func ExampleLogger_Should() { +// // you can create your own logging classification as needed +// const LogExpensiveThing azcore.LogClassification = "ExpensiveThing" +// if logger.Log().Should(LogExpensiveThing) { +// // perform expensive calculation only when enabled +// logger.Log().Write(LogExpensiveThing, "expensive log message") +// } +// } func ExampleLogger_SetClassifications() { // only log HTTP requests and responses - azcore.Log().SetClassifications(azcore.LogRequest, azcore.LogResponse) + azcore.SetClassifications(azcore.LogRequest, azcore.LogResponse) } func ExampleLogger_SetListener() { // a simple logger that writes to stdout - azcore.Log().SetListener(func(cls azcore.LogClassification, msg string) { + azcore.SetListener(func(cls azcore.LogClassification, msg string) { fmt.Printf("%s: %s\n", cls, msg) }) } diff --git a/sdk/azcore/go.mod b/sdk/azcore/go.mod index 560085f468f1..d00477111ccc 100644 --- a/sdk/azcore/go.mod +++ b/sdk/azcore/go.mod @@ -1,5 +1,7 @@ module github.com/Azure/azure-sdk-for-go/sdk/azcore +replace githu.com/Azure/azure-sdk-for-go/sdk/internal => ../internal + require ( github.com/Azure/azure-sdk-for-go/sdk/internal v0.5.1 golang.org/x/net v0.0.0-20201010224723-4f7140c49acb diff --git a/sdk/azcore/log.go b/sdk/azcore/log.go index be5db6726f4a..5a5029409a76 100644 --- a/sdk/azcore/log.go +++ b/sdk/azcore/log.go @@ -6,9 +6,7 @@ package azcore import ( - "fmt" - "os" - "time" + "github.com/Azure/azure-sdk-for-go/sdk/internal/logger" ) // LogClassification is used to group entries. Each group can be toggled on or off. @@ -31,86 +29,94 @@ const ( LogLongRunningOperation LogClassification = "LongRunningOperation" ) -// Listener is the function signature invoked when writing log entries. -// A Listener is required to perform its own synchronization if it's -// expected to be called from multiple Go routines. -type Listener func(LogClassification, string) - -// Logger controls which classifications to log and writing to the underlying log. -type Logger struct { - cls []LogClassification - lst Listener -} - -// SetClassifications is used to control which classifications are written to -// the log. By default all log classifications are written. -func (l *Logger) SetClassifications(cls ...LogClassification) { - l.cls = cls -} - -// SetListener will set the Logger to write to the specified Listener. -func (l *Logger) SetListener(lst Listener) { - l.lst = lst -} - -// Should returns true if the specified log classification should be written to the log. -// By default all log classifications will be logged. Call SetClassification() to limit -// the log classifications for logging. -// If no listener has been set this will return false. -// Calling this method is useful when the message to log is computationally expensive -// and you want to avoid the overhead if its log classification is not enabled. -func (l *Logger) Should(cls LogClassification) bool { - if l.lst == nil { - return false - } - if l.cls == nil || len(l.cls) == 0 { - return true - } - for _, c := range l.cls { - if c == cls { - return true - } - } - return false +// // Listener is the function signature invoked when writing log entries. +// // A Listener is required to perform its own synchronization if it's +// // expected to be called from multiple Go routines. +// type Listener func(LogClassification, string) + +// // Logger controls which classifications to log and writing to the underlying log. +// type Logger struct { +// cls []logger.LogClassification +// lst logger.Listener +// } + +// // SetClassifications is used to control which classifications are written to +// // the log. By default all log classifications are written. +// func (l *Logger) SetClassifications(cls ...LogClassification) { +// l.cls = cls +// } + +func SetClassifications(cls ...logger.LogClassification) { + logger.Log().SetClassifications(cls) } -// Write invokes the underlying Listener with the specified classification and message. -// If the classification shouldn't be logged or there is no listener then Write does nothing. -func (l *Logger) Write(cls LogClassification, message string) { - if !l.Should(cls) { - return - } - l.lst(cls, message) -} - -// Writef invokes the underlying Listener with the specified classification and formatted message. -// If the classification shouldn't be logged or there is no listener then Writef does nothing. -func (l *Logger) Writef(cls LogClassification, format string, a ...interface{}) { - if !l.Should(cls) { - return - } - l.lst(cls, fmt.Sprintf(format, a...)) -} +// // SetListener will set the Logger to write to the specified Listener. +// func (l *Logger) SetListener(lst Listener) { +// l.lst = lst +// } -// for testing purposes -func (l *Logger) resetClassifications() { - l.cls = nil +func SetListener(lst logger.Listener) { + logger.Log().SetListener(lst) } -var logger Logger - -// Log returns the process-wide logger. -func Log() *Logger { - return &logger -} - -func init() { - if cls := os.Getenv("AZURE_SDK_GO_LOGGING"); cls == "all" { - // cls could be enhanced to support a comma-delimited list of log classifications - logger.lst = func(cls LogClassification, msg string) { - // simple console logger, it writes to stderr in the following format: - // [time-stamp] Classification: message - fmt.Fprintf(os.Stderr, "[%s] %s: %s\n", time.Now().Format(time.StampMicro), cls, msg) - } - } -} +// // Should returns true if the specified log classification should be written to the log. +// // By default all log classifications will be logged. Call SetClassification() to limit +// // the log classifications for logging. +// // If no listener has been set this will return false. +// // Calling this method is useful when the message to log is computationally expensive +// // and you want to avoid the overhead if its log classification is not enabled. +// func (l *Logger) Should(cls LogClassification) bool { +// if l.lst == nil { +// return false +// } +// if l.cls == nil || len(l.cls) == 0 { +// return true +// } +// for _, c := range l.cls { +// if c == cls { +// return true +// } +// } +// return false +// } + +// // Write invokes the underlying Listener with the specified classification and message. +// // If the classification shouldn't be logged or there is no listener then Write does nothing. +// func (l *Logger) Write(cls LogClassification, message string) { +// if !l.Should(cls) { +// return +// } +// l.lst(cls, message) +// } + +// // Writef invokes the underlying Listener with the specified classification and formatted message. +// // If the classification shouldn't be logged or there is no listener then Writef does nothing. +// func (l *Logger) Writef(cls LogClassification, format string, a ...interface{}) { +// if !l.Should(cls) { +// return +// } +// l.lst(cls, fmt.Sprintf(format, a...)) +// } + +// // for testing purposes +// func (l *Logger) resetClassifications() { +// l.cls = nil +// } + +// var logger Logger + +// // Log returns the process-wide logger. +// func Log() *Logger { +// return &logger +// } + +// func init() { +// if cls := os.Getenv("AZURE_SDK_GO_LOGGING"); cls == "all" { +// // cls could be enhanced to support a comma-delimited list of log classifications +// logger.lst = func(cls LogClassification, msg string) { +// // simple console logger, it writes to stderr in the following format: +// // [time-stamp] Classification: message +// fmt.Fprintf(os.Stderr, "[%s] %s: %s\n", time.Now().Format(time.StampMicro), cls, msg) +// } +// } +// } diff --git a/sdk/azcore/log_test.go b/sdk/azcore/log_test.go index 8858a4448236..3dd35b35ccad 100644 --- a/sdk/azcore/log_test.go +++ b/sdk/azcore/log_test.go @@ -9,46 +9,48 @@ import ( "fmt" "net/http" "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/internal/logger" ) func TestLoggingDefault(t *testing.T) { // ensure logging with nil listener doesn't fail - Log().SetListener(nil) - Log().Write(LogRequest, "this should work just fine") + SetListener(nil) + logger.Log().Write(logger.LogRequest, "this should work just fine") - log := map[LogClassification]string{} - Log().SetListener(func(cls LogClassification, msg string) { + log := map[logger.LogClassification]string{} + logger.SetListener(func(cls logger.LogClassification, msg string) { log[cls] = msg }) const req = "this is a request" - Log().Write(LogRequest, req) + logger.Write(logger.LogRequest, req) const resp = "this is a response: %d" - Log().Writef(LogResponse, resp, http.StatusOK) + logger.Writef(logger.LogResponse, resp, http.StatusOK) if l := len(log); l != 2 { t.Fatalf("unexpected log entry count: %d", l) } - if log[LogRequest] != req { - t.Fatalf("unexpected log request: %s", log[LogRequest]) + if log[logger.LogRequest] != req { + t.Fatalf("unexpected log request: %s", log[logger.LogRequest]) } - if log[LogResponse] != fmt.Sprintf(resp, http.StatusOK) { - t.Fatalf("unexpected log response: %s", log[LogResponse]) + if log[logger.LogResponse] != fmt.Sprintf(resp, http.StatusOK) { + t.Fatalf("unexpected log response: %s", log[logger.LogResponse]) } } func TestLoggingClassification(t *testing.T) { - log := map[LogClassification]string{} - Log().SetListener(func(cls LogClassification, msg string) { + log := map[logger.LogClassification]string{} + logger.SetListener(func(cls logger.LogClassification, msg string) { log[cls] = msg }) - Log().SetClassifications(LogRequest) - defer Log().resetClassifications() - Log().Write(LogResponse, "this shouldn't be in the log") - if s, ok := log[LogResponse]; ok { + logger.SetClassifications(logger.LogRequest) + defer logger.resetClassifications() + logger.Write(logger.LogResponse, "this shouldn't be in the log") + if s, ok := log[logger.LogResponse]; ok { t.Fatalf("unexpected log entry %s", s) } const req = "this is a request" - Log().Write(LogRequest, req) - if log[LogRequest] != req { - t.Fatalf("unexpected log entry: %s", log[LogRequest]) + logger.Write(logger.LogRequest, req) + if log[logger.LogRequest] != req { + t.Fatalf("unexpected log entry: %s", log[logger.LogRequest]) } } diff --git a/sdk/azcore/policy_logging.go b/sdk/azcore/policy_logging.go index 86a0045a558d..7830080935a6 100644 --- a/sdk/azcore/policy_logging.go +++ b/sdk/azcore/policy_logging.go @@ -11,6 +11,7 @@ import ( "strings" "time" + "github.com/Azure/azure-sdk-for-go/sdk/internal/logger" "github.com/Azure/azure-sdk-for-go/sdk/internal/runtime" ) @@ -35,7 +36,7 @@ func NewLogPolicy(o *LogOptions) Policy { return &logPolicy{options: *o} } -// logPolicyOpValues is the struct containing the per-operation values +// logPolicyOpValues is the strucsst containing the per-operation values type logPolicyOpValues struct { try int32 start time.Time @@ -51,7 +52,7 @@ func (p *logPolicy) Do(req *Request) (*Response, error) { req.SetOperationValue(opValues) // Log the outgoing request as informational - if Log().Should(LogRequest) { + if logger.Log().Should(LogRequest) { b := &bytes.Buffer{} fmt.Fprintf(b, "==> OUTGOING REQUEST (Try=%d)\n", opValues.try) writeRequestWithResponse(b, req, nil, nil) @@ -59,7 +60,7 @@ func (p *logPolicy) Do(req *Request) (*Response, error) { if p.options.IncludeBody { err = req.writeBody(b) } - Log().Write(LogRequest, b.String()) + logger.Log().Write(LogRequest, b.String()) if err != nil { return nil, err } @@ -72,7 +73,7 @@ func (p *logPolicy) Do(req *Request) (*Response, error) { tryDuration := tryEnd.Sub(tryStart) opDuration := tryEnd.Sub(opValues.start) - if Log().Should(LogResponse) { + if logger.Log().Should(LogResponse) { // We're going to log this; build the string to log b := &bytes.Buffer{} fmt.Fprintf(b, "==> REQUEST/RESPONSE (Try=%d/%v, OpTime=%v) -- ", opValues.try, tryDuration, opDuration) @@ -89,7 +90,7 @@ func (p *logPolicy) Do(req *Request) (*Response, error) { } else if p.options.IncludeBody { err = response.writeBody(b) } - Log().Write(LogResponse, b.String()) + logger.Log().Write(LogResponse, b.String()) } return response, err } diff --git a/sdk/azcore/policy_logging_test.go b/sdk/azcore/policy_logging_test.go index 8f8cf378c468..4b364711ab56 100644 --- a/sdk/azcore/policy_logging_test.go +++ b/sdk/azcore/policy_logging_test.go @@ -18,7 +18,7 @@ import ( func TestPolicyLoggingSuccess(t *testing.T) { log := map[LogClassification]string{} - Log().SetListener(func(cls LogClassification, s string) { + SetListener(func(cls LogClassification, s string) { log[cls] = s }) srv, close := mock.NewServer() @@ -68,7 +68,7 @@ func TestPolicyLoggingSuccess(t *testing.T) { func TestPolicyLoggingError(t *testing.T) { log := map[LogClassification]string{} - Log().SetListener(func(cls LogClassification, s string) { + SetListener(func(cls LogClassification, s string) { log[cls] = s }) srv, close := mock.NewServer() diff --git a/sdk/azcore/policy_retry.go b/sdk/azcore/policy_retry.go index 6e7150c991ce..063196144c65 100644 --- a/sdk/azcore/policy_retry.go +++ b/sdk/azcore/policy_retry.go @@ -13,6 +13,8 @@ import ( "math/rand" "net/http" "time" + + "github.com/Azure/azure-sdk-for-go/sdk/internal/logger" ) const ( @@ -149,7 +151,7 @@ func (p *retryPolicy) Do(req *Request) (resp *Response, err error) { try := int32(1) for { resp = nil // reset - Log().Writef(LogRetryPolicy, "\n=====> Try=%d %s %s", try, req.Method, req.URL.String()) + logger.Log().Writef(LogRetryPolicy, "\n=====> Try=%d %s %s", try, req.Method, req.URL.String()) // For each try, seek to the beginning of the Body stream. We do this even for the 1st try because // the stream may not be at offset 0 when we first get it and we want the same behavior for the @@ -169,9 +171,9 @@ func (p *retryPolicy) Do(req *Request) (resp *Response, err error) { tryCancel() } if err == nil { - Log().Writef(LogRetryPolicy, "response %d", resp.StatusCode) + logger.Log().Writef(LogRetryPolicy, "response %d", resp.StatusCode) } else { - Log().Writef(LogRetryPolicy, "error %v", err) + logger.Log().Writef(LogRetryPolicy, "error %v", err) } if err == nil && !resp.HasStatusCode(options.StatusCodes...) { @@ -180,7 +182,7 @@ func (p *retryPolicy) Do(req *Request) (resp *Response, err error) { } else if ctxErr := req.Context().Err(); ctxErr != nil { // don't retry if the parent context has been cancelled or its deadline exceeded err = ctxErr - Log().Writef(LogRetryPolicy, "abort due to %v", err) + logger.Log().Writef(LogRetryPolicy, "abort due to %v", err) return } @@ -188,13 +190,13 @@ func (p *retryPolicy) Do(req *Request) (resp *Response, err error) { var nre NonRetriableError if errors.As(err, &nre) { // the error says it's not retriable so don't retry - Log().Writef(LogRetryPolicy, "non-retriable error %T", nre) + logger.Log().Writef(LogRetryPolicy, "non-retriable error %T", nre) return } if try == options.MaxRetries+1 { // max number of tries has been reached, don't sleep again - Log().Writef(LogRetryPolicy, "MaxRetries %d exceeded", options.MaxRetries) + logger.Log().Writef(LogRetryPolicy, "MaxRetries %d exceeded", options.MaxRetries) return } @@ -206,13 +208,13 @@ func (p *retryPolicy) Do(req *Request) (resp *Response, err error) { if delay <= 0 { delay = options.calcDelay(try) } - Log().Writef(LogRetryPolicy, "End Try #%d, Delay=%v", try, delay) + logger.Log().Writef(LogRetryPolicy, "End Try #%d, Delay=%v", try, delay) select { case <-time.After(delay): try++ case <-req.Context().Done(): err = req.Context().Err() - Log().Writef(LogRetryPolicy, "abort due to %v", err) + logger.Log().Writef(LogRetryPolicy, "abort due to %v", err) return } } diff --git a/sdk/azcore/poller.go b/sdk/azcore/poller.go index 0cea3c6a056d..14092b7656c2 100644 --- a/sdk/azcore/poller.go +++ b/sdk/azcore/poller.go @@ -16,6 +16,8 @@ import ( "strconv" "strings" "time" + + "github.com/Azure/azure-sdk-for-go/sdk/internal/logger" ) // ErrorUnmarshaller is the func to invoke when the endpoint returns an error response that requires unmarshalling. @@ -200,13 +202,13 @@ func (l *LROPoller) FinalResponse(ctx context.Context, respType interface{}) (*h // into the respType interface that is provided. func (l *LROPoller) PollUntilDone(ctx context.Context, freq time.Duration, respType interface{}) (*http.Response, error) { logPollUntilDoneExit := func(v interface{}) { - Log().Writef(LogLongRunningOperation, "END PollUntilDone() for %T: %v", l.lro, v) + logger.Log().Writef(LogLongRunningOperation, "END PollUntilDone() for %T: %v", l.lro, v) } - Log().Writef(LogLongRunningOperation, "BEGIN PollUntilDone() for %T", l.lro) + logger.Log().Writef(LogLongRunningOperation, "BEGIN PollUntilDone() for %T", l.lro) if l.resp != nil { // initial check for a retry-after header existing on the initial response if retryAfter := RetryAfter(l.resp.Response); retryAfter > 0 { - Log().Writef(LogLongRunningOperation, "initial Retry-After delay for %s", retryAfter.String()) + logger.Log().Writef(LogLongRunningOperation, "initial Retry-After delay for %s", retryAfter.String()) if err := delay(ctx, retryAfter); err != nil { logPollUntilDoneExit(err) return nil, err @@ -229,10 +231,10 @@ func (l *LROPoller) PollUntilDone(ctx context.Context, freq time.Duration, respT } d := freq if retryAfter := RetryAfter(resp); retryAfter > 0 { - Log().Writef(LogLongRunningOperation, "Retry-After delay for %s", retryAfter.String()) + logger.Log().Writef(LogLongRunningOperation, "Retry-After delay for %s", retryAfter.String()) d = retryAfter } else { - Log().Writef(LogLongRunningOperation, "delay for %s", d.String()) + logger.Log().Writef(LogLongRunningOperation, "delay for %s", d.String()) } if err = delay(ctx, d); err != nil { logPollUntilDoneExit(err) diff --git a/sdk/internal/ci.yml b/sdk/internal/ci.yml index 2e4d1a250ed3..570cddcf9d9b 100644 --- a/sdk/internal/ci.yml +++ b/sdk/internal/ci.yml @@ -3,12 +3,13 @@ trigger: paths: include: - sdk/internal/ + - eng/ pr: paths: include: - sdk/internal/ - + stages: - template: ../../eng/pipelines/templates/jobs/archetype-sdk-client.yml parameters: diff --git a/sdk/internal/logger/logger.go b/sdk/internal/logger/logger.go new file mode 100644 index 000000000000..6ba232e37f56 --- /dev/null +++ b/sdk/internal/logger/logger.go @@ -0,0 +1,116 @@ +// +build go1.13 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package logger + +import ( + "fmt" + "os" + "time" +) + +// LogClassification is used to group entries. Each group can be toggled on or off. +type LogClassification string + +// const ( +// // LogRequest entries contain information about HTTP requests. +// // This includes information like the URL, query parameters, and headers. +// LogRequest LogClassification = "Request" + +// // LogResponse entries contain information about HTTP responses. +// // This includes information like the HTTP status code, headers, and request URL. +// LogResponse LogClassification = "Response" + +// // LogRetryPolicy entries contain information specific to the retry policy in use. +// LogRetryPolicy LogClassification = "RetryPolicy" + +// // LogLongRunningOperation entries contain information specific to long-running operations. +// // This includes information like polling location, operation state and sleep intervals. +// LogLongRunningOperation LogClassification = "LongRunningOperation" +// ) + +// Listener is the function signature invoked when writing log entries. +// A Listener is required to perform its own synchronization if it's +// expected to be called from multiple Go routines. +type Listener func(LogClassification, string) + +// Logger controls which classifications to log and writing to the underlying log. +type Logger struct { + cls []logger.LogClassification + lst logger.Listener +} + +// SetClassifications is used to control which classifications are written to +// the log. By default all log classifications are written. +func (l *Logger) SetClassifications(cls ...LogClassification) { + l.cls = cls +} + +// SetListener will set the Logger to write to the specified Listener. +func (l *Logger) SetListener(lst Listener) { + l.lst = lst +} + +// Should returns true if the specified log classification should be written to the log. +// By default all log classifications will be logged. Call SetClassification() to limit +// the log classifications for logging. +// If no listener has been set this will return false. +// Calling this method is useful when the message to log is computationally expensive +// and you want to avoid the overhead if its log classification is not enabled. +func (l *Logger) Should(cls LogClassification) bool { + if l.lst == nil { + return false + } + if l.cls == nil || len(l.cls) == 0 { + return true + } + for _, c := range l.cls { + if c == cls { + return true + } + } + return false +} + +// Write invokes the underlying Listener with the specified classification and message. +// If the classification shouldn't be logged or there is no listener then Write does nothing. +func (l *Logger) Write(cls LogClassification, message string) { + if !l.Should(cls) { + return + } + l.lst(cls, message) +} + +// Writef invokes the underlying Listener with the specified classification and formatted message. +// If the classification shouldn't be logged or there is no listener then Writef does nothing. +func (l *Logger) Writef(cls LogClassification, format string, a ...interface{}) { + if !l.Should(cls) { + return + } + l.lst(cls, fmt.Sprintf(format, a...)) +} + +// for testing purposes +func (l *Logger) resetClassifications() { + l.cls = nil +} + +var logger Logger + +// Log returns the process-wide logger. +func Log() *Logger { + return &logger +} + +func init() { + if cls := os.Getenv("AZURE_SDK_GO_LOGGING"); cls == "all" { + // cls could be enhanced to support a comma-delimited list of log classifications + logger.lst = func(cls LogClassification, msg string) { + // simple console logger, it writes to stderr in the following format: + // [time-stamp] Classification: message + fmt.Fprintf(os.Stderr, "[%s] %s: %s\n", time.Now().Format(time.StampMicro), cls, msg) + } + } +} From 2f50adf2c054e1ba8f3df384b1770cc03c222efe Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Tue, 27 Jul 2021 11:22:19 -0400 Subject: [PATCH 02/14] fixing up errors in logger file --- sdk/azcore/log.go | 84 ----------------------------------- sdk/internal/go.mod | 1 + sdk/internal/go.sum | 12 +++++ sdk/internal/logger/logger.go | 38 +++++----------- 4 files changed, 23 insertions(+), 112 deletions(-) diff --git a/sdk/azcore/log.go b/sdk/azcore/log.go index 5a5029409a76..750b5c6da13b 100644 --- a/sdk/azcore/log.go +++ b/sdk/azcore/log.go @@ -29,94 +29,10 @@ const ( LogLongRunningOperation LogClassification = "LongRunningOperation" ) -// // Listener is the function signature invoked when writing log entries. -// // A Listener is required to perform its own synchronization if it's -// // expected to be called from multiple Go routines. -// type Listener func(LogClassification, string) - -// // Logger controls which classifications to log and writing to the underlying log. -// type Logger struct { -// cls []logger.LogClassification -// lst logger.Listener -// } - -// // SetClassifications is used to control which classifications are written to -// // the log. By default all log classifications are written. -// func (l *Logger) SetClassifications(cls ...LogClassification) { -// l.cls = cls -// } - func SetClassifications(cls ...logger.LogClassification) { logger.Log().SetClassifications(cls) } -// // SetListener will set the Logger to write to the specified Listener. -// func (l *Logger) SetListener(lst Listener) { -// l.lst = lst -// } - func SetListener(lst logger.Listener) { logger.Log().SetListener(lst) } - -// // Should returns true if the specified log classification should be written to the log. -// // By default all log classifications will be logged. Call SetClassification() to limit -// // the log classifications for logging. -// // If no listener has been set this will return false. -// // Calling this method is useful when the message to log is computationally expensive -// // and you want to avoid the overhead if its log classification is not enabled. -// func (l *Logger) Should(cls LogClassification) bool { -// if l.lst == nil { -// return false -// } -// if l.cls == nil || len(l.cls) == 0 { -// return true -// } -// for _, c := range l.cls { -// if c == cls { -// return true -// } -// } -// return false -// } - -// // Write invokes the underlying Listener with the specified classification and message. -// // If the classification shouldn't be logged or there is no listener then Write does nothing. -// func (l *Logger) Write(cls LogClassification, message string) { -// if !l.Should(cls) { -// return -// } -// l.lst(cls, message) -// } - -// // Writef invokes the underlying Listener with the specified classification and formatted message. -// // If the classification shouldn't be logged or there is no listener then Writef does nothing. -// func (l *Logger) Writef(cls LogClassification, format string, a ...interface{}) { -// if !l.Should(cls) { -// return -// } -// l.lst(cls, fmt.Sprintf(format, a...)) -// } - -// // for testing purposes -// func (l *Logger) resetClassifications() { -// l.cls = nil -// } - -// var logger Logger - -// // Log returns the process-wide logger. -// func Log() *Logger { -// return &logger -// } - -// func init() { -// if cls := os.Getenv("AZURE_SDK_GO_LOGGING"); cls == "all" { -// // cls could be enhanced to support a comma-delimited list of log classifications -// logger.lst = func(cls LogClassification, msg string) { -// // simple console logger, it writes to stderr in the following format: -// // [time-stamp] Classification: message -// fmt.Fprintf(os.Stderr, "[%s] %s: %s\n", time.Now().Format(time.StampMicro), cls, msg) -// } -// } -// } diff --git a/sdk/internal/go.mod b/sdk/internal/go.mod index 5a5a2fb7eb04..557bca5e5a64 100644 --- a/sdk/internal/go.mod +++ b/sdk/internal/go.mod @@ -3,6 +3,7 @@ module github.com/Azure/azure-sdk-for-go/sdk/internal go 1.14 require ( + github.com/Azure/azure-sdk-for-go/sdk/azcore v0.16.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dnaeon/go-vcr v1.2.0 github.com/stretchr/testify v1.7.0 diff --git a/sdk/internal/go.sum b/sdk/internal/go.sum index 7064208964e3..8587a49f1d8c 100644 --- a/sdk/internal/go.sum +++ b/sdk/internal/go.sum @@ -1,3 +1,6 @@ +github.com/Azure/azure-sdk-for-go/sdk/azcore v0.16.2 h1:UC4vfOhW2l0f2QOCQpOxJS4/K6oKFy2tQZE+uWU1MEo= +github.com/Azure/azure-sdk-for-go/sdk/azcore v0.16.2/go.mod h1:MVdrcUC4Hup35qHym3VdzoW+NBgBxrta9Vei97jRtM8= +github.com/Azure/azure-sdk-for-go/sdk/internal v0.5.1/go.mod h1:k4KbFSunV/+0hOHL1vyFaPsiYQ1Vmvy1TBpmtvCDLZM= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -9,11 +12,20 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210610132358-84b48f89b13b h1:k+E048sYJHyVnsr1GDrRZWQ32D2C7lWs9JRc0bel53A= golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/sdk/internal/logger/logger.go b/sdk/internal/logger/logger.go index 6ba232e37f56..fdbf2e6966be 100644 --- a/sdk/internal/logger/logger.go +++ b/sdk/internal/logger/logger.go @@ -9,42 +9,24 @@ import ( "fmt" "os" "time" -) - -// LogClassification is used to group entries. Each group can be toggled on or off. -type LogClassification string - -// const ( -// // LogRequest entries contain information about HTTP requests. -// // This includes information like the URL, query parameters, and headers. -// LogRequest LogClassification = "Request" -// // LogResponse entries contain information about HTTP responses. -// // This includes information like the HTTP status code, headers, and request URL. -// LogResponse LogClassification = "Response" - -// // LogRetryPolicy entries contain information specific to the retry policy in use. -// LogRetryPolicy LogClassification = "RetryPolicy" - -// // LogLongRunningOperation entries contain information specific to long-running operations. -// // This includes information like polling location, operation state and sleep intervals. -// LogLongRunningOperation LogClassification = "LongRunningOperation" -// ) + "github.com/Azure/azure-sdk-for-go/sdk/azcore" +) // Listener is the function signature invoked when writing log entries. // A Listener is required to perform its own synchronization if it's // expected to be called from multiple Go routines. -type Listener func(LogClassification, string) +type Listener func(azcore.LogClassification, string) // Logger controls which classifications to log and writing to the underlying log. type Logger struct { - cls []logger.LogClassification - lst logger.Listener + cls []azcore.LogClassification + lst Listener } // SetClassifications is used to control which classifications are written to // the log. By default all log classifications are written. -func (l *Logger) SetClassifications(cls ...LogClassification) { +func (l *Logger) SetClassifications(cls ...azcore.LogClassification) { l.cls = cls } @@ -59,7 +41,7 @@ func (l *Logger) SetListener(lst Listener) { // If no listener has been set this will return false. // Calling this method is useful when the message to log is computationally expensive // and you want to avoid the overhead if its log classification is not enabled. -func (l *Logger) Should(cls LogClassification) bool { +func (l *Logger) Should(cls azcore.LogClassification) bool { if l.lst == nil { return false } @@ -76,7 +58,7 @@ func (l *Logger) Should(cls LogClassification) bool { // Write invokes the underlying Listener with the specified classification and message. // If the classification shouldn't be logged or there is no listener then Write does nothing. -func (l *Logger) Write(cls LogClassification, message string) { +func (l *Logger) Write(cls azcore.LogClassification, message string) { if !l.Should(cls) { return } @@ -85,7 +67,7 @@ func (l *Logger) Write(cls LogClassification, message string) { // Writef invokes the underlying Listener with the specified classification and formatted message. // If the classification shouldn't be logged or there is no listener then Writef does nothing. -func (l *Logger) Writef(cls LogClassification, format string, a ...interface{}) { +func (l *Logger) Writef(cls azcore.LogClassification, format string, a ...interface{}) { if !l.Should(cls) { return } @@ -107,7 +89,7 @@ func Log() *Logger { func init() { if cls := os.Getenv("AZURE_SDK_GO_LOGGING"); cls == "all" { // cls could be enhanced to support a comma-delimited list of log classifications - logger.lst = func(cls LogClassification, msg string) { + logger.lst = func(cls azcore.LogClassification, msg string) { // simple console logger, it writes to stderr in the following format: // [time-stamp] Classification: message fmt.Fprintf(os.Stderr, "[%s] %s: %s\n", time.Now().Format(time.StampMicro), cls, msg) From e493952640be452ac2cc5dbca360823ad769c870 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Tue, 27 Jul 2021 12:12:44 -0400 Subject: [PATCH 03/14] adding logger test file --- sdk/internal/logger/logger.go | 2 -- sdk/internal/logger/logger_test.go | 54 ++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 sdk/internal/logger/logger_test.go diff --git a/sdk/internal/logger/logger.go b/sdk/internal/logger/logger.go index fdbf2e6966be..54c1482635df 100644 --- a/sdk/internal/logger/logger.go +++ b/sdk/internal/logger/logger.go @@ -1,5 +1,3 @@ -// +build go1.13 - // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. diff --git a/sdk/internal/logger/logger_test.go b/sdk/internal/logger/logger_test.go new file mode 100644 index 000000000000..2f112418625b --- /dev/null +++ b/sdk/internal/logger/logger_test.go @@ -0,0 +1,54 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package logger + +import ( + "fmt" + "net/http" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" +) + +func TestLoggingDefault(t *testing.T) { + // ensure logging with nil listener doesn't fail + azcore.SetListener(nil) + Log().Write(azcore.LogRequest, "this should work just fine") + + log := map[azcore.LogClassification]string{} + azcore.SetListener(func(cls azcore.LogClassification, msg string) { + log[cls] = msg + }) + const req = "this is a request" + Log().Write(azcore.LogRequest, req) + const resp = "this is a response: %d" + Log().Writef(azcore.LogResponse, resp, http.StatusOK) + if l := len(log); l != 2 { + t.Fatalf("unexpected log entry count: %d", l) + } + if log[azcore.LogRequest] != req { + t.Fatalf("unexpected log request: %s", log[azcore.LogRequest]) + } + if log[azcore.LogResponse] != fmt.Sprintf(resp, http.StatusOK) { + t.Fatalf("unexpected log response: %s", log[azcore.LogResponse]) + } +} + +func TestLoggingClassification(t *testing.T) { + log := map[azcore.LogClassification]string{} + azcore.SetListener(func(cls azcore.LogClassification, msg string) { + log[cls] = msg + }) + azcore.SetClassifications(azcore.LogRequest) + defer Log().resetClassifications() + Log().Write(azcore.LogResponse, "this shouldn't be in the log") + if s, ok := log[azcore.LogResponse]; ok { + t.Fatalf("unexpected log entry %s", s) + } + const req = "this is a request" + Log().Write(azcore.LogRequest, req) + if log[azcore.LogRequest] != req { + t.Fatalf("unexpected log entry: %s", log[azcore.LogRequest]) + } +} From cfd0b674f744957aa3c881b44487273bcfef8b7e Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Tue, 27 Jul 2021 12:18:53 -0400 Subject: [PATCH 04/14] removed an example --- sdk/azcore/example_test.go | 9 --------- 1 file changed, 9 deletions(-) diff --git a/sdk/azcore/example_test.go b/sdk/azcore/example_test.go index affe7f7f31da..0cbff4e87147 100644 --- a/sdk/azcore/example_test.go +++ b/sdk/azcore/example_test.go @@ -48,15 +48,6 @@ func ExampleRequest_SetBody() { } } -// func ExampleLogger_Should() { -// // you can create your own logging classification as needed -// const LogExpensiveThing azcore.LogClassification = "ExpensiveThing" -// if logger.Log().Should(LogExpensiveThing) { -// // perform expensive calculation only when enabled -// logger.Log().Write(LogExpensiveThing, "expensive log message") -// } -// } - func ExampleLogger_SetClassifications() { // only log HTTP requests and responses azcore.SetClassifications(azcore.LogRequest, azcore.LogResponse) From a0a0446992c467d0ab7d9b4651a225c8700555c3 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Wed, 28 Jul 2021 12:12:12 -0400 Subject: [PATCH 05/14] feedback and removing circular dependency --- sdk/azcore/go.mod | 2 -- sdk/azcore/policy_logging.go | 2 +- sdk/internal/go.mod | 1 - sdk/internal/go.sum | 12 ------------ 4 files changed, 1 insertion(+), 16 deletions(-) diff --git a/sdk/azcore/go.mod b/sdk/azcore/go.mod index d00477111ccc..560085f468f1 100644 --- a/sdk/azcore/go.mod +++ b/sdk/azcore/go.mod @@ -1,7 +1,5 @@ module github.com/Azure/azure-sdk-for-go/sdk/azcore -replace githu.com/Azure/azure-sdk-for-go/sdk/internal => ../internal - require ( github.com/Azure/azure-sdk-for-go/sdk/internal v0.5.1 golang.org/x/net v0.0.0-20201010224723-4f7140c49acb diff --git a/sdk/azcore/policy_logging.go b/sdk/azcore/policy_logging.go index 7830080935a6..bb3b93dd745f 100644 --- a/sdk/azcore/policy_logging.go +++ b/sdk/azcore/policy_logging.go @@ -36,7 +36,7 @@ func NewLogPolicy(o *LogOptions) Policy { return &logPolicy{options: *o} } -// logPolicyOpValues is the strucsst containing the per-operation values +// logPolicyOpValues is the struct containing the per-operation values type logPolicyOpValues struct { try int32 start time.Time diff --git a/sdk/internal/go.mod b/sdk/internal/go.mod index 557bca5e5a64..5a5a2fb7eb04 100644 --- a/sdk/internal/go.mod +++ b/sdk/internal/go.mod @@ -3,7 +3,6 @@ module github.com/Azure/azure-sdk-for-go/sdk/internal go 1.14 require ( - github.com/Azure/azure-sdk-for-go/sdk/azcore v0.16.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dnaeon/go-vcr v1.2.0 github.com/stretchr/testify v1.7.0 diff --git a/sdk/internal/go.sum b/sdk/internal/go.sum index 8587a49f1d8c..7064208964e3 100644 --- a/sdk/internal/go.sum +++ b/sdk/internal/go.sum @@ -1,6 +1,3 @@ -github.com/Azure/azure-sdk-for-go/sdk/azcore v0.16.2 h1:UC4vfOhW2l0f2QOCQpOxJS4/K6oKFy2tQZE+uWU1MEo= -github.com/Azure/azure-sdk-for-go/sdk/azcore v0.16.2/go.mod h1:MVdrcUC4Hup35qHym3VdzoW+NBgBxrta9Vei97jRtM8= -github.com/Azure/azure-sdk-for-go/sdk/internal v0.5.1/go.mod h1:k4KbFSunV/+0hOHL1vyFaPsiYQ1Vmvy1TBpmtvCDLZM= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -12,20 +9,11 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210610132358-84b48f89b13b h1:k+E048sYJHyVnsr1GDrRZWQ32D2C7lWs9JRc0bel53A= golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= From b168cad64b2853033534bc69c04cfd3c2b6bea09 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Wed, 28 Jul 2021 12:16:22 -0400 Subject: [PATCH 06/14] moving logclassification to be in logger, type alias in azcore --- sdk/azcore/log.go | 3 +-- sdk/internal/logger/logger.go | 34 ++++++++++++++++++++++++++-------- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/sdk/azcore/log.go b/sdk/azcore/log.go index 750b5c6da13b..9317ff45bd0d 100644 --- a/sdk/azcore/log.go +++ b/sdk/azcore/log.go @@ -9,8 +9,7 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/internal/logger" ) -// LogClassification is used to group entries. Each group can be toggled on or off. -type LogClassification string +type LogClassification logger.LogClassification const ( // LogRequest entries contain information about HTTP requests. diff --git a/sdk/internal/logger/logger.go b/sdk/internal/logger/logger.go index 54c1482635df..76d31f88730a 100644 --- a/sdk/internal/logger/logger.go +++ b/sdk/internal/logger/logger.go @@ -7,24 +7,42 @@ import ( "fmt" "os" "time" +) + +// LogClassification is used to group entries. Each group can be toggled on or off. +type LogClassification string + +const ( + // LogRequest entries contain information about HTTP requests. + // This includes information like the URL, query parameters, and headers. + LogRequest LogClassification = "Request" + + // LogResponse entries contain information about HTTP responses. + // This includes information like the HTTP status code, headers, and request URL. + LogResponse LogClassification = "Response" + + // LogRetryPolicy entries contain information specific to the retry policy in use. + LogRetryPolicy LogClassification = "RetryPolicy" - "github.com/Azure/azure-sdk-for-go/sdk/azcore" + // LogLongRunningOperation entries contain information specific to long-running operations. + // This includes information like polling location, operation state and sleep intervals. + LogLongRunningOperation LogClassification = "LongRunningOperation" ) // Listener is the function signature invoked when writing log entries. // A Listener is required to perform its own synchronization if it's // expected to be called from multiple Go routines. -type Listener func(azcore.LogClassification, string) +type Listener func(LogClassification, string) // Logger controls which classifications to log and writing to the underlying log. type Logger struct { - cls []azcore.LogClassification + cls []LogClassification lst Listener } // SetClassifications is used to control which classifications are written to // the log. By default all log classifications are written. -func (l *Logger) SetClassifications(cls ...azcore.LogClassification) { +func (l *Logger) SetClassifications(cls ...LogClassification) { l.cls = cls } @@ -39,7 +57,7 @@ func (l *Logger) SetListener(lst Listener) { // If no listener has been set this will return false. // Calling this method is useful when the message to log is computationally expensive // and you want to avoid the overhead if its log classification is not enabled. -func (l *Logger) Should(cls azcore.LogClassification) bool { +func (l *Logger) Should(cls LogClassification) bool { if l.lst == nil { return false } @@ -56,7 +74,7 @@ func (l *Logger) Should(cls azcore.LogClassification) bool { // Write invokes the underlying Listener with the specified classification and message. // If the classification shouldn't be logged or there is no listener then Write does nothing. -func (l *Logger) Write(cls azcore.LogClassification, message string) { +func (l *Logger) Write(cls LogClassification, message string) { if !l.Should(cls) { return } @@ -65,7 +83,7 @@ func (l *Logger) Write(cls azcore.LogClassification, message string) { // Writef invokes the underlying Listener with the specified classification and formatted message. // If the classification shouldn't be logged or there is no listener then Writef does nothing. -func (l *Logger) Writef(cls azcore.LogClassification, format string, a ...interface{}) { +func (l *Logger) Writef(cls LogClassification, format string, a ...interface{}) { if !l.Should(cls) { return } @@ -87,7 +105,7 @@ func Log() *Logger { func init() { if cls := os.Getenv("AZURE_SDK_GO_LOGGING"); cls == "all" { // cls could be enhanced to support a comma-delimited list of log classifications - logger.lst = func(cls azcore.LogClassification, msg string) { + logger.lst = func(cls LogClassification, msg string) { // simple console logger, it writes to stderr in the following format: // [time-stamp] Classification: message fmt.Fprintf(os.Stderr, "[%s] %s: %s\n", time.Now().Format(time.StampMicro), cls, msg) From 12f15a114ee576e75aae78fe095bf182858203a2 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Wed, 28 Jul 2021 13:54:45 -0400 Subject: [PATCH 07/14] update internal version --- sdk/azcore/go.mod | 5 +++-- sdk/azcore/go.sum | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/sdk/azcore/go.mod b/sdk/azcore/go.mod index 560085f468f1..a98d7212faf2 100644 --- a/sdk/azcore/go.mod +++ b/sdk/azcore/go.mod @@ -1,8 +1,9 @@ module github.com/Azure/azure-sdk-for-go/sdk/azcore require ( - github.com/Azure/azure-sdk-for-go/sdk/internal v0.5.1 - golang.org/x/net v0.0.0-20201010224723-4f7140c49acb + github.com/Azure/azure-sdk-for-go/sdk/internal v0.5.2 + golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect + golang.org/x/net v0.0.0-20210610132358-84b48f89b13b ) go 1.14 diff --git a/sdk/azcore/go.sum b/sdk/azcore/go.sum index 22aa85d38b50..b8b69a4adf39 100644 --- a/sdk/azcore/go.sum +++ b/sdk/azcore/go.sum @@ -1,15 +1,34 @@ github.com/Azure/azure-sdk-for-go/sdk/internal v0.5.1 h1:vx8McI56N5oLSQu8xa+xdiE0fjQq8W8Zt49vHP8Rygw= github.com/Azure/azure-sdk-for-go/sdk/internal v0.5.1/go.mod h1:k4KbFSunV/+0hOHL1vyFaPsiYQ1Vmvy1TBpmtvCDLZM= +github.com/Azure/azure-sdk-for-go/sdk/internal v0.5.2 h1:E2xwjsWU81O/XuSaxAGa8Jmqz4Vm4NmrpMSO9/XevDg= +github.com/Azure/azure-sdk-for-go/sdk/internal v0.5.2/go.mod h1:Hl9Vte0DDolj9zqzmfnmY9/zfZbiT5KnvXqVwAvnR8Q= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= +github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20201010224723-4f7140c49acb h1:mUVeFHoDKis5nxCAzoAi7E8Ghb86EXh/RK6wtvJIqRY= golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From 597c047f617d438916ee5fb14d3030a97e33e95d Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Wed, 28 Jul 2021 14:04:05 -0400 Subject: [PATCH 08/14] fixes in azcore --- sdk/azcore/log.go | 18 ++++++++++++++---- sdk/azcore/log_test.go | 15 +++++++-------- sdk/azcore/policy_logging.go | 8 ++++---- sdk/azcore/policy_retry.go | 16 ++++++++-------- sdk/azcore/poller.go | 10 +++++----- 5 files changed, 38 insertions(+), 29 deletions(-) diff --git a/sdk/azcore/log.go b/sdk/azcore/log.go index 9317ff45bd0d..4834953db59b 100644 --- a/sdk/azcore/log.go +++ b/sdk/azcore/log.go @@ -28,10 +28,20 @@ const ( LogLongRunningOperation LogClassification = "LongRunningOperation" ) -func SetClassifications(cls ...logger.LogClassification) { - logger.Log().SetClassifications(cls) +func SetClassifications(cls ...LogClassification) { + input := make([]logger.LogClassification, 0) + for _, l := range cls { + input = append(input, logger.LogClassification(l)) + } + logger.Log().SetClassifications(input...) } -func SetListener(lst logger.Listener) { - logger.Log().SetListener(lst) +// Listener is the function signature invoked when writing log entries. +// A Listener is required to perform its own synchronization if it's expected to be called +// from multiple Go routines +type Listener func(LogClassification, string) + +func SetListener(lst interface{}) { + l := lst.(logger.Listener) + logger.Log().SetListener(l) } diff --git a/sdk/azcore/log_test.go b/sdk/azcore/log_test.go index 3dd35b35ccad..3971e897debf 100644 --- a/sdk/azcore/log_test.go +++ b/sdk/azcore/log_test.go @@ -19,13 +19,13 @@ func TestLoggingDefault(t *testing.T) { logger.Log().Write(logger.LogRequest, "this should work just fine") log := map[logger.LogClassification]string{} - logger.SetListener(func(cls logger.LogClassification, msg string) { + SetListener(func(cls logger.LogClassification, msg string) { log[cls] = msg }) const req = "this is a request" - logger.Write(logger.LogRequest, req) + logger.Log().Write(logger.LogRequest, req) const resp = "this is a response: %d" - logger.Writef(logger.LogResponse, resp, http.StatusOK) + logger.Log().Writef(logger.LogResponse, resp, http.StatusOK) if l := len(log); l != 2 { t.Fatalf("unexpected log entry count: %d", l) } @@ -39,17 +39,16 @@ func TestLoggingDefault(t *testing.T) { func TestLoggingClassification(t *testing.T) { log := map[logger.LogClassification]string{} - logger.SetListener(func(cls logger.LogClassification, msg string) { + SetListener(func(cls logger.LogClassification, msg string) { log[cls] = msg }) - logger.SetClassifications(logger.LogRequest) - defer logger.resetClassifications() - logger.Write(logger.LogResponse, "this shouldn't be in the log") + SetClassifications(LogRequest) + logger.Log().Write(logger.LogResponse, "this shouldn't be in the log") if s, ok := log[logger.LogResponse]; ok { t.Fatalf("unexpected log entry %s", s) } const req = "this is a request" - logger.Write(logger.LogRequest, req) + logger.Log().Write(logger.LogRequest, req) if log[logger.LogRequest] != req { t.Fatalf("unexpected log entry: %s", log[logger.LogRequest]) } diff --git a/sdk/azcore/policy_logging.go b/sdk/azcore/policy_logging.go index bb3b93dd745f..41e4546f41d4 100644 --- a/sdk/azcore/policy_logging.go +++ b/sdk/azcore/policy_logging.go @@ -52,7 +52,7 @@ func (p *logPolicy) Do(req *Request) (*Response, error) { req.SetOperationValue(opValues) // Log the outgoing request as informational - if logger.Log().Should(LogRequest) { + if logger.Log().Should(logger.LogRequest) { b := &bytes.Buffer{} fmt.Fprintf(b, "==> OUTGOING REQUEST (Try=%d)\n", opValues.try) writeRequestWithResponse(b, req, nil, nil) @@ -60,7 +60,7 @@ func (p *logPolicy) Do(req *Request) (*Response, error) { if p.options.IncludeBody { err = req.writeBody(b) } - logger.Log().Write(LogRequest, b.String()) + logger.Log().Write(logger.LogRequest, b.String()) if err != nil { return nil, err } @@ -73,7 +73,7 @@ func (p *logPolicy) Do(req *Request) (*Response, error) { tryDuration := tryEnd.Sub(tryStart) opDuration := tryEnd.Sub(opValues.start) - if logger.Log().Should(LogResponse) { + if logger.Log().Should(logger.LogResponse) { // We're going to log this; build the string to log b := &bytes.Buffer{} fmt.Fprintf(b, "==> REQUEST/RESPONSE (Try=%d/%v, OpTime=%v) -- ", opValues.try, tryDuration, opDuration) @@ -90,7 +90,7 @@ func (p *logPolicy) Do(req *Request) (*Response, error) { } else if p.options.IncludeBody { err = response.writeBody(b) } - logger.Log().Write(LogResponse, b.String()) + logger.Log().Write(logger.LogResponse, b.String()) } return response, err } diff --git a/sdk/azcore/policy_retry.go b/sdk/azcore/policy_retry.go index 063196144c65..fcd888771ca0 100644 --- a/sdk/azcore/policy_retry.go +++ b/sdk/azcore/policy_retry.go @@ -151,7 +151,7 @@ func (p *retryPolicy) Do(req *Request) (resp *Response, err error) { try := int32(1) for { resp = nil // reset - logger.Log().Writef(LogRetryPolicy, "\n=====> Try=%d %s %s", try, req.Method, req.URL.String()) + logger.Log().Writef(logger.LogRetryPolicy, "\n=====> Try=%d %s %s", try, req.Method, req.URL.String()) // For each try, seek to the beginning of the Body stream. We do this even for the 1st try because // the stream may not be at offset 0 when we first get it and we want the same behavior for the @@ -171,9 +171,9 @@ func (p *retryPolicy) Do(req *Request) (resp *Response, err error) { tryCancel() } if err == nil { - logger.Log().Writef(LogRetryPolicy, "response %d", resp.StatusCode) + logger.Log().Writef(logger.LogRetryPolicy, "response %d", resp.StatusCode) } else { - logger.Log().Writef(LogRetryPolicy, "error %v", err) + logger.Log().Writef(logger.LogRetryPolicy, "error %v", err) } if err == nil && !resp.HasStatusCode(options.StatusCodes...) { @@ -182,7 +182,7 @@ func (p *retryPolicy) Do(req *Request) (resp *Response, err error) { } else if ctxErr := req.Context().Err(); ctxErr != nil { // don't retry if the parent context has been cancelled or its deadline exceeded err = ctxErr - logger.Log().Writef(LogRetryPolicy, "abort due to %v", err) + logger.Log().Writef(logger.LogRetryPolicy, "abort due to %v", err) return } @@ -190,13 +190,13 @@ func (p *retryPolicy) Do(req *Request) (resp *Response, err error) { var nre NonRetriableError if errors.As(err, &nre) { // the error says it's not retriable so don't retry - logger.Log().Writef(LogRetryPolicy, "non-retriable error %T", nre) + logger.Log().Writef(logger.LogRetryPolicy, "non-retriable error %T", nre) return } if try == options.MaxRetries+1 { // max number of tries has been reached, don't sleep again - logger.Log().Writef(LogRetryPolicy, "MaxRetries %d exceeded", options.MaxRetries) + logger.Log().Writef(logger.LogRetryPolicy, "MaxRetries %d exceeded", options.MaxRetries) return } @@ -208,13 +208,13 @@ func (p *retryPolicy) Do(req *Request) (resp *Response, err error) { if delay <= 0 { delay = options.calcDelay(try) } - logger.Log().Writef(LogRetryPolicy, "End Try #%d, Delay=%v", try, delay) + logger.Log().Writef(logger.LogRetryPolicy, "End Try #%d, Delay=%v", try, delay) select { case <-time.After(delay): try++ case <-req.Context().Done(): err = req.Context().Err() - logger.Log().Writef(LogRetryPolicy, "abort due to %v", err) + logger.Log().Writef(logger.LogRetryPolicy, "abort due to %v", err) return } } diff --git a/sdk/azcore/poller.go b/sdk/azcore/poller.go index 14092b7656c2..7947d65c11e9 100644 --- a/sdk/azcore/poller.go +++ b/sdk/azcore/poller.go @@ -202,13 +202,13 @@ func (l *LROPoller) FinalResponse(ctx context.Context, respType interface{}) (*h // into the respType interface that is provided. func (l *LROPoller) PollUntilDone(ctx context.Context, freq time.Duration, respType interface{}) (*http.Response, error) { logPollUntilDoneExit := func(v interface{}) { - logger.Log().Writef(LogLongRunningOperation, "END PollUntilDone() for %T: %v", l.lro, v) + logger.Log().Writef(logger.LogLongRunningOperation, "END PollUntilDone() for %T: %v", l.lro, v) } - logger.Log().Writef(LogLongRunningOperation, "BEGIN PollUntilDone() for %T", l.lro) + logger.Log().Writef(logger.LogLongRunningOperation, "BEGIN PollUntilDone() for %T", l.lro) if l.resp != nil { // initial check for a retry-after header existing on the initial response if retryAfter := RetryAfter(l.resp.Response); retryAfter > 0 { - logger.Log().Writef(LogLongRunningOperation, "initial Retry-After delay for %s", retryAfter.String()) + logger.Log().Writef(logger.LogLongRunningOperation, "initial Retry-After delay for %s", retryAfter.String()) if err := delay(ctx, retryAfter); err != nil { logPollUntilDoneExit(err) return nil, err @@ -231,10 +231,10 @@ func (l *LROPoller) PollUntilDone(ctx context.Context, freq time.Duration, respT } d := freq if retryAfter := RetryAfter(resp); retryAfter > 0 { - logger.Log().Writef(LogLongRunningOperation, "Retry-After delay for %s", retryAfter.String()) + logger.Log().Writef(logger.LogLongRunningOperation, "Retry-After delay for %s", retryAfter.String()) d = retryAfter } else { - logger.Log().Writef(LogLongRunningOperation, "delay for %s", d.String()) + logger.Log().Writef(logger.LogLongRunningOperation, "delay for %s", d.String()) } if err = delay(ctx, d); err != nil { logPollUntilDoneExit(err) From eb5517e6a2f9d68e1e12b166b61f9106b905ff3a Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Wed, 28 Jul 2021 15:29:53 -0400 Subject: [PATCH 09/14] fixes to azcore, works now --- sdk/azcore/go.mod | 1 - sdk/azcore/go.sum | 2 ++ sdk/azcore/log.go | 28 ++++++++++++++++++++++------ sdk/azcore/log_test.go | 23 ++++++++++++----------- 4 files changed, 36 insertions(+), 18 deletions(-) diff --git a/sdk/azcore/go.mod b/sdk/azcore/go.mod index a98d7212faf2..db8caa57b4fe 100644 --- a/sdk/azcore/go.mod +++ b/sdk/azcore/go.mod @@ -2,7 +2,6 @@ module github.com/Azure/azure-sdk-for-go/sdk/azcore require ( github.com/Azure/azure-sdk-for-go/sdk/internal v0.5.2 - golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect golang.org/x/net v0.0.0-20210610132358-84b48f89b13b ) diff --git a/sdk/azcore/go.sum b/sdk/azcore/go.sum index b8b69a4adf39..61e0ae67efb6 100644 --- a/sdk/azcore/go.sum +++ b/sdk/azcore/go.sum @@ -14,6 +14,7 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20201010224723-4f7140c49acb h1:mUVeFHoDKis5nxCAzoAi7E8Ghb86EXh/RK6wtvJIqRY= golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210610132358-84b48f89b13b h1:k+E048sYJHyVnsr1GDrRZWQ32D2C7lWs9JRc0bel53A= golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -25,6 +26,7 @@ golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/sdk/azcore/log.go b/sdk/azcore/log.go index 4834953db59b..8b0579cee3ee 100644 --- a/sdk/azcore/log.go +++ b/sdk/azcore/log.go @@ -6,6 +6,8 @@ package azcore import ( + "fmt" + "github.com/Azure/azure-sdk-for-go/sdk/internal/logger" ) @@ -36,12 +38,26 @@ func SetClassifications(cls ...LogClassification) { logger.Log().SetClassifications(input...) } -// Listener is the function signature invoked when writing log entries. -// A Listener is required to perform its own synchronization if it's expected to be called -// from multiple Go routines type Listener func(LogClassification, string) -func SetListener(lst interface{}) { - l := lst.(logger.Listener) - logger.Log().SetListener(l) +func transform(lst Listener) logger.Listener { + return func(l logger.LogClassification, msg string) { + azcoreL := LogClassification(l) + lst(azcoreL, msg) + } +} + +func SetListener(lst Listener) { + if lst == nil { + fmt.Println("nil listener") + logger.Log().SetListener(nil) + } else { + fmt.Println("Not nil listener") + logger.Log().SetListener(transform(lst)) + } +} + +// for testing purposes +func resetClassifications() { + logger.Log().SetClassifications([]logger.LogClassification{}...) } diff --git a/sdk/azcore/log_test.go b/sdk/azcore/log_test.go index 3971e897debf..c3fce30c2b6a 100644 --- a/sdk/azcore/log_test.go +++ b/sdk/azcore/log_test.go @@ -18,8 +18,8 @@ func TestLoggingDefault(t *testing.T) { SetListener(nil) logger.Log().Write(logger.LogRequest, "this should work just fine") - log := map[logger.LogClassification]string{} - SetListener(func(cls logger.LogClassification, msg string) { + log := map[LogClassification]string{} + SetListener(func(cls LogClassification, msg string) { log[cls] = msg }) const req = "this is a request" @@ -29,27 +29,28 @@ func TestLoggingDefault(t *testing.T) { if l := len(log); l != 2 { t.Fatalf("unexpected log entry count: %d", l) } - if log[logger.LogRequest] != req { - t.Fatalf("unexpected log request: %s", log[logger.LogRequest]) + if log[LogRequest] != req { + t.Fatalf("unexpected log request: %s", log[LogRequest]) } - if log[logger.LogResponse] != fmt.Sprintf(resp, http.StatusOK) { - t.Fatalf("unexpected log response: %s", log[logger.LogResponse]) + if log[LogResponse] != fmt.Sprintf(resp, http.StatusOK) { + t.Fatalf("unexpected log response: %s", log[LogResponse]) } } func TestLoggingClassification(t *testing.T) { - log := map[logger.LogClassification]string{} - SetListener(func(cls logger.LogClassification, msg string) { + log := map[LogClassification]string{} + SetListener(func(cls LogClassification, msg string) { log[cls] = msg }) SetClassifications(LogRequest) + defer resetClassifications() logger.Log().Write(logger.LogResponse, "this shouldn't be in the log") - if s, ok := log[logger.LogResponse]; ok { + if s, ok := log[LogResponse]; ok { t.Fatalf("unexpected log entry %s", s) } const req = "this is a request" logger.Log().Write(logger.LogRequest, req) - if log[logger.LogRequest] != req { - t.Fatalf("unexpected log entry: %s", log[logger.LogRequest]) + if log[LogRequest] != req { + t.Fatalf("unexpected log entry: %s", log[LogRequest]) } } From d776560d6dad2110e46d3511713117618bd63426 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Wed, 28 Jul 2021 15:39:58 -0400 Subject: [PATCH 10/14] linter false positive --- sdk/azcore/example_test.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sdk/azcore/example_test.go b/sdk/azcore/example_test.go index 0cbff4e87147..8e34c5cec984 100644 --- a/sdk/azcore/example_test.go +++ b/sdk/azcore/example_test.go @@ -48,12 +48,14 @@ func ExampleRequest_SetBody() { } } -func ExampleLogger_SetClassifications() { +// false positive by linter +func ExampleLogger_SetClassifications() { //nolint:govet // only log HTTP requests and responses azcore.SetClassifications(azcore.LogRequest, azcore.LogResponse) } -func ExampleLogger_SetListener() { +// false positive by linter +func ExampleLogger_SetListener() { //nolint:govet // a simple logger that writes to stdout azcore.SetListener(func(cls azcore.LogClassification, msg string) { fmt.Printf("%s: %s\n", cls, msg) From 7edca673e1182b45a57f00323000dfc63203e3e0 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Wed, 28 Jul 2021 16:36:11 -0400 Subject: [PATCH 11/14] catalina's comments --- sdk/azcore/go.sum | 14 -------------- sdk/azcore/log.go | 12 ++++++++---- 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/sdk/azcore/go.sum b/sdk/azcore/go.sum index 61e0ae67efb6..62d184faa625 100644 --- a/sdk/azcore/go.sum +++ b/sdk/azcore/go.sum @@ -1,5 +1,3 @@ -github.com/Azure/azure-sdk-for-go/sdk/internal v0.5.1 h1:vx8McI56N5oLSQu8xa+xdiE0fjQq8W8Zt49vHP8Rygw= -github.com/Azure/azure-sdk-for-go/sdk/internal v0.5.1/go.mod h1:k4KbFSunV/+0hOHL1vyFaPsiYQ1Vmvy1TBpmtvCDLZM= github.com/Azure/azure-sdk-for-go/sdk/internal v0.5.2 h1:E2xwjsWU81O/XuSaxAGa8Jmqz4Vm4NmrpMSO9/XevDg= github.com/Azure/azure-sdk-for-go/sdk/internal v0.5.2/go.mod h1:Hl9Vte0DDolj9zqzmfnmY9/zfZbiT5KnvXqVwAvnR8Q= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -9,23 +7,11 @@ github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3P github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20201010224723-4f7140c49acb h1:mUVeFHoDKis5nxCAzoAi7E8Ghb86EXh/RK6wtvJIqRY= -golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210610132358-84b48f89b13b h1:k+E048sYJHyVnsr1GDrRZWQ32D2C7lWs9JRc0bel53A= golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/sdk/azcore/log.go b/sdk/azcore/log.go index 8b0579cee3ee..6693de56ef19 100644 --- a/sdk/azcore/log.go +++ b/sdk/azcore/log.go @@ -6,11 +6,11 @@ package azcore import ( - "fmt" - "github.com/Azure/azure-sdk-for-go/sdk/internal/logger" ) +// SetClassifications is used to control which classifications are written to +// the log. By default all log classifications are writen. type LogClassification logger.LogClassification const ( @@ -30,6 +30,8 @@ const ( LogLongRunningOperation LogClassification = "LongRunningOperation" ) +// SetClassifications is used to control which classifications are written to +// the log. By default all log classifications are writen. func SetClassifications(cls ...LogClassification) { input := make([]logger.LogClassification, 0) for _, l := range cls { @@ -38,8 +40,12 @@ func SetClassifications(cls ...LogClassification) { logger.Log().SetClassifications(input...) } +// Listener is the function signature invoked when writing log entries. +// A Listener is required to perform its own synchronization if it's expected to be called +// from multiple Go routines type Listener func(LogClassification, string) +// transform to convert the azcore.Listener type into a usable one for internal.logger module func transform(lst Listener) logger.Listener { return func(l logger.LogClassification, msg string) { azcoreL := LogClassification(l) @@ -49,10 +55,8 @@ func transform(lst Listener) logger.Listener { func SetListener(lst Listener) { if lst == nil { - fmt.Println("nil listener") logger.Log().SetListener(nil) } else { - fmt.Println("Not nil listener") logger.Log().SetListener(transform(lst)) } } From edc132a23ce5bfe9a256fbd38e7656f26c676710 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Wed, 28 Jul 2021 17:20:08 -0400 Subject: [PATCH 12/14] more feedback --- sdk/azcore/log.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/azcore/log.go b/sdk/azcore/log.go index 6693de56ef19..b08a47df7797 100644 --- a/sdk/azcore/log.go +++ b/sdk/azcore/log.go @@ -9,8 +9,7 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/internal/logger" ) -// SetClassifications is used to control which classifications are written to -// the log. By default all log classifications are writen. +// LogClassification is used to group entries. Each group can be toggled on or off type LogClassification logger.LogClassification const ( @@ -53,6 +52,7 @@ func transform(lst Listener) logger.Listener { } } +// SetListener will set the Logger to write to the specified Listener. func SetListener(lst Listener) { if lst == nil { logger.Log().SetListener(nil) From 138f0fa09c5c9d9e78ef350e2805298b1a188ce5 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Thu, 29 Jul 2021 11:04:37 -0400 Subject: [PATCH 13/14] update version --- sdk/azcore/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/azcore/version.go b/sdk/azcore/version.go index 78fab47d84ee..8959fea247ec 100644 --- a/sdk/azcore/version.go +++ b/sdk/azcore/version.go @@ -10,5 +10,5 @@ const ( UserAgent = "azcore/" + Version // Version is the semantic version (see http://semver.org) of this module. - Version = "v0.16.3" + Version = "v0.17.0" ) From c4059cce15a9379a6d7010e63fc2775e8df1d3f5 Mon Sep 17 00:00:00 2001 From: Sean Kane <68240067+seankane-msft@users.noreply.github.com> Date: Thu, 29 Jul 2021 11:11:47 -0400 Subject: [PATCH 14/14] Update sdk/azcore/version.go Co-authored-by: catalinaperalta --- sdk/azcore/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/azcore/version.go b/sdk/azcore/version.go index 8959fea247ec..646e0b198176 100644 --- a/sdk/azcore/version.go +++ b/sdk/azcore/version.go @@ -10,5 +10,5 @@ const ( UserAgent = "azcore/" + Version // Version is the semantic version (see http://semver.org) of this module. - Version = "v0.17.0" + Version = "v0.18.0" )