Skip to content

Commit

Permalink
Removed and renamed some content (#15285)
Browse files Browse the repository at this point in the history
Unexported policyFunc
Renamed Transport to Transporter
Removed TransportFunc, Pager, and Poller interfaces
Added responseError (removed from internal)
Fixed logging type aliases
Updated logging usage based on internal/log refactor
Removed StatusCodesForRetry, ProgressReceiver, ErrNoMorePolicies
Renamed LROPoller to Poller
  • Loading branch information
jhendrixMSFT authored Aug 13, 2021
1 parent 48b276d commit 695791e
Show file tree
Hide file tree
Showing 17 changed files with 157 additions and 223 deletions.
61 changes: 8 additions & 53 deletions sdk/azcore/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
package azcore

import (
"context"
"errors"
"io"
"net/http"
Expand All @@ -31,33 +30,24 @@ type Policy interface {
Do(req *Request) (*Response, error)
}

// PolicyFunc is a type that implements the Policy interface.
// policyFunc is a type that implements the Policy interface.
// Use this type when implementing a stateless policy as a first-class function.
type PolicyFunc func(*Request) (*Response, error)
type policyFunc func(*Request) (*Response, error)

// Do implements the Policy interface on PolicyFunc.
func (pf PolicyFunc) Do(req *Request) (*Response, error) {
func (pf policyFunc) Do(req *Request) (*Response, error) {
return pf(req)
}

// Transport represents an HTTP pipeline transport used to send HTTP requests and receive responses.
type Transport interface {
// Transporter represents an HTTP pipeline transport used to send HTTP requests and receive responses.
type Transporter interface {
// Do sends the HTTP request and returns the HTTP response or error.
Do(req *http.Request) (*http.Response, error)
}

// TransportFunc is a type that implements the Transport interface.
// Use this type when implementing a stateless transport as a first-class function.
type TransportFunc func(*http.Request) (*http.Response, error)

// Do implements the Transport interface on TransportFunc.
func (tf TransportFunc) Do(req *http.Request) (*http.Response, error) {
return tf(req)
}

// used to adapt a TransportPolicy to a Policy
type transportPolicy struct {
trans Transport
trans Transporter
}

func (tp transportPolicy) Do(req *Request) (*Response, error) {
Expand All @@ -80,12 +70,12 @@ type Pipeline struct {

// NewPipeline creates a new Pipeline object from the specified Transport and Policies.
// If no transport is provided then the default *http.Client transport will be used.
func NewPipeline(transport Transport, policies ...Policy) Pipeline {
func NewPipeline(transport Transporter, policies ...Policy) Pipeline {
if transport == nil {
transport = defaultHTTPClient
}
// transport policy must always be the last in the slice
policies = append(policies, PolicyFunc(httpHeaderPolicy), PolicyFunc(bodyDownloadPolicy), transportPolicy{trans: transport})
policies = append(policies, policyFunc(httpHeaderPolicy), policyFunc(bodyDownloadPolicy), transportPolicy{trans: transport})
return Pipeline{
policies: policies,
}
Expand Down Expand Up @@ -121,41 +111,6 @@ func NopCloser(rs io.ReadSeeker) ReadSeekCloser {
return nopCloser{rs}
}

// Poller provides operations for checking the state of a long-running operation.
// An LRO can be in either a non-terminal or terminal state. A non-terminal state
// indicates the LRO is still in progress. A terminal state indicates the LRO has
// completed successfully, failed, or was cancelled.
type Poller interface {
// Done returns true if the LRO has reached a terminal state.
Done() bool

// Poll fetches the latest state of the LRO. It returns an HTTP response or error.
// If the LRO has completed successfully, the poller's state is update and the HTTP
// response is returned.
// If the LRO has completed with failure or was cancelled, the poller's state is
// updated and the error is returned.
// If the LRO has not reached a terminal state, the poller's state is updated and
// the latest HTTP response is returned.
// If Poll fails, the poller's state is unmodified and the error is returned.
// Calling Poll on an LRO that has reached a terminal state will return the final
// HTTP response or error.
Poll(context.Context) (*http.Response, error)

// ResumeToken returns a value representing the poller that can be used to resume
// the LRO at a later time. ResumeTokens are unique per service operation.
ResumeToken() (string, error)
}

// Pager provides operations for iterating over paged responses.
type Pager interface {
// NextPage returns true if the pager advanced to the next page.
// Returns false if there are no more pages or an error occurred.
NextPage(context.Context) bool

// Err returns the last error encountered while paging.
Err() error
}

// holds sentinel values used to send nulls
var nullables map[reflect.Type]interface{} = map[reflect.Type]interface{}{}

Expand Down
41 changes: 28 additions & 13 deletions sdk/azcore/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,7 @@
package azcore

import (
"errors"
"net/http"

sdkruntime "github.com/Azure/azure-sdk-for-go/sdk/internal/runtime"
)

var (
// ErrNoMorePolicies is returned from Request.Next() if there are no more policies in the pipeline.
ErrNoMorePolicies = errors.New("no more policies")
)

var (
Expand All @@ -31,9 +23,6 @@ type HTTPResponse interface {
RawResponse() *http.Response
}

// ensure our internal ResponseError type implements HTTPResponse
var _ HTTPResponse = (*sdkruntime.ResponseError)(nil)

// NonRetriableError represents a non-transient error. This works in
// conjunction with the retry policy, indicating that the error condition
// is idempotent, so no retries will be attempted.
Expand All @@ -48,7 +37,33 @@ type NonRetriableError interface {
// in this error type so that callers can access the underlying *http.Response as required.
// DO NOT wrap failed HTTP requests that returned an error and no response with this type.
func NewResponseError(inner error, resp *http.Response) error {
return sdkruntime.NewResponseError(inner, resp)
return &responseError{inner: inner, resp: resp}
}

type responseError struct {
inner error
resp *http.Response
}

// Error implements the error interface for type ResponseError.
func (e *responseError) Error() string {
return e.inner.Error()
}

// Unwrap returns the inner error.
func (e *responseError) Unwrap() error {
return e.inner
}

// RawResponse returns the HTTP response associated with this error.
func (e *responseError) RawResponse() *http.Response {
return e.resp
}

// NonRetriable indicates this error is non-transient.
func (e *responseError) NonRetriable() {
// marker method
}

var _ NonRetriableError = (*sdkruntime.ResponseError)(nil)
var _ HTTPResponse = (*responseError)(nil)
var _ NonRetriableError = (*responseError)(nil)
8 changes: 4 additions & 4 deletions sdk/azcore/example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,15 @@ func ExampleRequest_SetBody() {
}

// false positive by linter
func ExampleLogger_SetClassifications() { //nolint:govet
func ExampleLogSetClassifications() { //nolint:govet
// only log HTTP requests and responses
azcore.SetClassifications(azcore.LogRequest, azcore.LogResponse)
azcore.LogSetClassifications(azcore.LogRequest, azcore.LogResponse)
}

// false positive by linter
func ExampleLogger_SetListener() { //nolint:govet
func ExampleLogSetListener() { //nolint:govet
// a simple logger that writes to stdout
azcore.SetListener(func(cls azcore.LogClassification, msg string) {
azcore.LogSetListener(func(cls azcore.LogClassification, msg string) {
fmt.Printf("%s: %s\n", cls, msg)
})
}
Expand Down
4 changes: 2 additions & 2 deletions sdk/azcore/go.mod
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
module github.com/Azure/azure-sdk-for-go/sdk/azcore

require (
github.com/Azure/azure-sdk-for-go/sdk/internal v0.5.2
github.com/stretchr/testify v1.7.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v0.6.0
github.com/stretchr/testify v1.7.0
golang.org/x/net v0.0.0-20210610132358-84b48f89b13b
)

Expand Down
5 changes: 3 additions & 2 deletions sdk/azcore/go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
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/Azure/azure-sdk-for-go/sdk/internal v0.6.0 h1:Lozt96x50m14Kb7U9FgYkI44AYXVa4lVhRF6exoLlqE=
github.com/Azure/azure-sdk-for-go/sdk/internal v0.6.0/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 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand All @@ -18,6 +18,7 @@ golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9sn
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 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
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=
Expand Down
47 changes: 13 additions & 34 deletions sdk/azcore/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,62 +6,41 @@
package azcore

import (
"github.com/Azure/azure-sdk-for-go/sdk/internal/logger"
"github.com/Azure/azure-sdk-for-go/sdk/internal/log"
)

// LogClassification is used to group entries. Each group can be toggled on or off
type LogClassification logger.LogClassification
// LogClassification is used to group entries. Each group can be toggled on or off.
type LogClassification = log.Classification

const (
// LogRequest entries contain information about HTTP requests.
// This includes information like the URL, query parameters, and headers.
LogRequest LogClassification = "Request"
LogRequest = log.Request

// LogResponse entries contain information about HTTP responses.
// This includes information like the HTTP status code, headers, and request URL.
LogResponse LogClassification = "Response"
LogResponse = log.Response

// LogRetryPolicy entries contain information specific to the retry policy in use.
LogRetryPolicy LogClassification = "RetryPolicy"
LogRetryPolicy = log.RetryPolicy

// LogLongRunningOperation entries contain information specific to long-running operations.
// This includes information like polling location, operation state and sleep intervals.
LogLongRunningOperation LogClassification = "LongRunningOperation"
LogLongRunningOperation = log.LongRunningOperation
)

// SetClassifications is used to control which classifications are written to
// LogSetClassifications 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 {
input = append(input, logger.LogClassification(l))
}
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)
lst(azcoreL, msg)
}
func LogSetClassifications(cls ...LogClassification) {
log.SetClassifications(cls...)
}

// SetListener will set the Logger to write to the specified Listener.
func SetListener(lst Listener) {
if lst == nil {
logger.Log().SetListener(nil)
} else {
logger.Log().SetListener(transform(lst))
}
func LogSetListener(lst func(log.Classification, string)) {
log.SetListener(lst)
}

// for testing purposes
func resetClassifications() {
logger.Log().SetClassifications([]logger.LogClassification{}...)
log.TestResetClassifications()
}
44 changes: 22 additions & 22 deletions sdk/azcore/log_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,47 +10,47 @@ import (
"net/http"
"testing"

"github.com/Azure/azure-sdk-for-go/sdk/internal/logger"
"github.com/Azure/azure-sdk-for-go/sdk/internal/log"
)

func TestLoggingDefault(t *testing.T) {
// ensure logging with nil listener doesn't fail
SetListener(nil)
logger.Log().Write(logger.LogRequest, "this should work just fine")
LogSetListener(nil)
log.Write(log.Request, "this should work just fine")

log := map[LogClassification]string{}
SetListener(func(cls LogClassification, msg string) {
log[cls] = msg
testlog := map[LogClassification]string{}
LogSetListener(func(cls LogClassification, msg string) {
testlog[cls] = msg
})
const req = "this is a request"
logger.Log().Write(logger.LogRequest, req)
log.Write(log.Request, req)
const resp = "this is a response: %d"
logger.Log().Writef(logger.LogResponse, resp, http.StatusOK)
if l := len(log); l != 2 {
log.Writef(log.Response, resp, http.StatusOK)
if l := len(testlog); l != 2 {
t.Fatalf("unexpected log entry count: %d", l)
}
if log[LogRequest] != req {
t.Fatalf("unexpected log request: %s", log[LogRequest])
if testlog[LogRequest] != req {
t.Fatalf("unexpected log request: %s", testlog[LogRequest])
}
if log[LogResponse] != fmt.Sprintf(resp, http.StatusOK) {
t.Fatalf("unexpected log response: %s", log[LogResponse])
if testlog[LogResponse] != fmt.Sprintf(resp, http.StatusOK) {
t.Fatalf("unexpected log response: %s", testlog[LogResponse])
}
}

func TestLoggingClassification(t *testing.T) {
log := map[LogClassification]string{}
SetListener(func(cls LogClassification, msg string) {
log[cls] = msg
testlog := map[LogClassification]string{}
LogSetListener(func(cls LogClassification, msg string) {
testlog[cls] = msg
})
SetClassifications(LogRequest)
LogSetClassifications(LogRequest)
defer resetClassifications()
logger.Log().Write(logger.LogResponse, "this shouldn't be in the log")
if s, ok := log[LogResponse]; ok {
log.Write(log.Response, "this shouldn't be in the log")
if s, ok := testlog[LogResponse]; ok {
t.Fatalf("unexpected log entry %s", s)
}
const req = "this is a request"
logger.Log().Write(logger.LogRequest, req)
if log[LogRequest] != req {
t.Fatalf("unexpected log entry: %s", log[LogRequest])
log.Write(log.Request, req)
if testlog[LogRequest] != req {
t.Fatalf("unexpected log entry: %s", testlog[LogRequest])
}
}
2 changes: 1 addition & 1 deletion sdk/azcore/policy_anonymous_credential.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
package azcore

func anonCredAuthPolicyFunc(AuthenticationOptions) Policy {
return PolicyFunc(anonCredPolicyFunc)
return policyFunc(anonCredPolicyFunc)
}

func anonCredPolicyFunc(req *Request) (*Response, error) {
Expand Down
Loading

0 comments on commit 695791e

Please sign in to comment.