Skip to content

Commit

Permalink
Add ID to context to trace requests.
Browse files Browse the repository at this point in the history
Fix go.mod name.
  • Loading branch information
jefchien committed Oct 20, 2023
1 parent 1f23619 commit e5c60ba
Show file tree
Hide file tree
Showing 10 changed files with 247 additions and 109 deletions.
12 changes: 6 additions & 6 deletions extension/awsmiddleware/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,27 @@
An AWS middleware extension provides request and/or response handlers that can be configured on AWS SDK v1/v2 clients.
Other components can configure their AWS SDK clients using the `awsmiddleware.ConfigureSDKv1` and `awsmiddleware.ConfigureSDKv2` functions.

The `awsmiddleware.Extension` interface extends `component.Extension` by adding the following methods:
The `awsmiddleware.Extension` interface extends `component.Extension` by adding the following method:
```
RequestHandlers() []RequestHandler
ResponseHandlers() []ResponseHandler
Handlers() ([]RequestHandler, []ResponseHandler)
```

The `awsmiddleware.RequestHandler` interface contains the following methods:
```
ID() string
Position() HandlerPosition
HandleRequest(r *http.Request)
HandleRequest(id string, r *http.Request)
```

The `awsmiddleware.ResponseHandler` interface contains the following methods:
```
ID() string
Position() HandlerPosition
HandleResponse(r *http.Response)
HandleResponse(id string, r *http.Response)
```

- `ID` uniquely identifies a handler. Middleware will fail if there is clashing
- `Position` determines whether the handler is appended to the front or back of the existing list. Insertion is done
in the order of the handlers provided.
- `HandleRequest/Response` provides a hook to handle the request/response before and after they've been sent.
- `HandleRequest/Response` provides a hook to handle the request/response before and after they've been sent along
with an attached ID.
30 changes: 18 additions & 12 deletions extension/awsmiddleware/config.go
Original file line number Diff line number Diff line change
@@ -1,27 +1,33 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package awsmiddleware // import "github.com/open-telemetry/opentelemetry-collector-contrib/extension/awsmiddleware"
package awsmiddleware // import "github.com/amazon-contributing/opentelemetry-collector-contrib/extension/awsmiddleware"

import (
"fmt"

"go.opentelemetry.io/collector/component"
)

// Config defines the configuration for an AWS Middleware extension.
type Config struct {
// MiddlewareID is the ID of the Middleware extension.
MiddlewareID component.ID `mapstructure:"middleware"`
}
type ID = component.ID

// GetMiddleware retrieves the extension implementing Middleware based on the MiddlewareID.
func (c Config) GetMiddleware(extensions map[component.ID]component.Component) (Middleware, error) {
if ext, found := extensions[c.MiddlewareID]; found {
if mw, ok := ext.(Middleware); ok {
return mw, nil
// getMiddleware retrieves the extension implementing Middleware based on the middlewareID.
func getMiddleware(extensions map[component.ID]component.Component, middlewareID ID) (Middleware, error) {
if extension, found := extensions[middlewareID]; found {
if middleware, ok := extension.(Middleware); ok {
return middleware, nil
}
return nil, errNotMiddleware
}
return nil, fmt.Errorf("failed to resolve AWS client handler %q: %w", c.MiddlewareID, errNotFound)
return nil, fmt.Errorf("failed to resolve AWS middleware %q: %w", middlewareID, errNotFound)
}

// GetConfigurer retrieves the extension implementing Middleware based on the middlewareID and
// wraps it in a Configurer.
func GetConfigurer(extensions map[component.ID]component.Component, middlewareID ID) (*Configurer, error) {
middleware, err := getMiddleware(extensions, middlewareID)
if err != nil {
return nil, err
}
return NewConfigurer(middleware), nil
}
24 changes: 3 additions & 21 deletions extension/awsmiddleware/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,8 @@ import (
"go.opentelemetry.io/collector/extension/extensiontest"
)

type testMiddlewareExtension struct {
component.StartFunc
component.ShutdownFunc
requestHandlers []RequestHandler
responseHandlers []ResponseHandler
}

var _ Extension = (*testMiddlewareExtension)(nil)

func (t *testMiddlewareExtension) RequestHandlers() []RequestHandler {
return t.requestHandlers
}

func (t *testMiddlewareExtension) ResponseHandlers() []ResponseHandler {
return t.responseHandlers
}

func TestGetMiddleware(t *testing.T) {
func TestGetConfigurer(t *testing.T) {
id := component.NewID("test")
cfg := &Config{MiddlewareID: id}
nopExtension, err := extensiontest.NewNopBuilder().Create(context.Background(), extensiontest.NewNopCreateSettings())
require.Error(t, err)
testCases := map[string]struct {
Expand All @@ -48,12 +30,12 @@ func TestGetMiddleware(t *testing.T) {
wantErr: errNotMiddleware,
},
"WithMiddlewareExtension": {
extensions: map[component.ID]component.Component{id: &testMiddlewareExtension{}},
extensions: map[component.ID]component.Component{id: new(MockMiddlewareExtension)},
},
}
for name, testCase := range testCases {
t.Run(name, func(t *testing.T) {
got, err := cfg.GetMiddleware(testCase.extensions)
got, err := GetConfigurer(testCase.extensions, id)
if testCase.wantErr != nil {
assert.Error(t, err)
assert.ErrorIs(t, err, testCase.wantErr)
Expand Down
2 changes: 1 addition & 1 deletion extension/awsmiddleware/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@

// Package awsmiddleware defines an extension interface providing request and response handlers that can be
// configured on AWS SDK clients.
package awsmiddleware // import "github.com/open-telemetry/opentelemetry-collector-contrib/extension/awsmiddleware"
package awsmiddleware // import "github.com/amazon-contributing/opentelemetry-collector-contrib/extension/awsmiddleware"
12 changes: 7 additions & 5 deletions extension/awsmiddleware/go.mod
Original file line number Diff line number Diff line change
@@ -1,25 +1,26 @@
module github.com/open-telemetry/opentelemetry-collector-contrib/extension/awsmiddleware
module github.com/amazon-contributing/opentelemetry-collector-contrib/extension/awsmiddleware

go 1.20

require (
github.com/aws/aws-sdk-go v1.45.24
github.com/aws/aws-sdk-go-v2 v1.21.1
github.com/aws/aws-sdk-go-v2 v1.21.2
github.com/aws/aws-sdk-go-v2/service/s3 v1.40.0
github.com/aws/smithy-go v1.15.0
github.com/google/uuid v1.3.0
github.com/stretchr/testify v1.8.4
go.opentelemetry.io/collector/component v0.87.0
go.opentelemetry.io/collector/extension v0.87.0
)

require (
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.13 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.42 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.36 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.43 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.37 // indirect
github.com/aws/aws-sdk-go-v2/internal/v4a v1.1.4 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.14 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.36 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.36 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.37 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.15.4 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
Expand All @@ -32,6 +33,7 @@ require (
github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/stretchr/objx v0.5.0 // indirect
go.opentelemetry.io/collector/config/configtelemetry v0.87.0 // indirect
go.opentelemetry.io/collector/confmap v0.87.0 // indirect
go.opentelemetry.io/collector/featuregate v1.0.0-rcv0016 // indirect
Expand Down
24 changes: 16 additions & 8 deletions extension/awsmiddleware/go.sum

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

36 changes: 24 additions & 12 deletions extension/awsmiddleware/middleware.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package awsmiddleware // import "github.com/open-telemetry/opentelemetry-collector-contrib/extension/awsmiddleware"
package awsmiddleware // import "github.com/amazon-contributing/opentelemetry-collector-contrib/extension/awsmiddleware"

import (
"encoding"
Expand Down Expand Up @@ -85,20 +85,19 @@ type handlerConfig interface {
// RequestHandler allows for custom processing of requests.
type RequestHandler interface {
handlerConfig
HandleRequest(r *http.Request)
HandleRequest(id string, r *http.Request)
}

// ResponseHandler allows for custom processing of responses.
type ResponseHandler interface {
handlerConfig
HandleResponse(r *http.Response)
HandleResponse(id string, r *http.Response)
}

// Middleware defines the request and response handlers to be configured
// on AWS Clients.
type Middleware interface {
RequestHandlers() []RequestHandler
ResponseHandlers() []ResponseHandler
Handlers() ([]RequestHandler, []ResponseHandler)
}

// Extension is an extension that implements Middleware.
Expand All @@ -107,17 +106,29 @@ type Extension interface {
Middleware
}

// Configurer wraps a Middleware and provides convenience functions
// for applying it to the AWS SDKs.
type Configurer struct {
Middleware
}

// NewConfigurer wraps the Middleware.
func NewConfigurer(mw Middleware) *Configurer {
return &Configurer{Middleware: mw}
}

// ConfigureSDKv1 adds middleware to the AWS SDK v1. Request handlers are added to the
// Build handler list and response handlers are added to the Unmarshal handler list.
func ConfigureSDKv1(mw Middleware, handlers *request.Handlers) error {
func (c *Configurer) ConfigureSDKv1(handlers *request.Handlers) error {
var errs error
for _, handler := range mw.RequestHandlers() {
requestHandlers, responseHandlers := c.Middleware.Handlers()
for _, handler := range requestHandlers {
if err := appendHandler(&handlers.Build, namedRequestHandler(handler), handler.Position()); err != nil {
errs = errors.Join(errs, fmt.Errorf("%w (%q): %w", errInvalidHandler, handler.ID(), err))
}
}
for _, handler := range mw.ResponseHandlers() {
if err := appendHandler(&handlers.Unmarshal, namedResponseHandler(handler), handler.Position()); err != nil {
for _, handler := range responseHandlers {
if err := appendHandler(&handlers.ValidateResponse, namedResponseHandler(handler), handler.Position()); err != nil {
errs = errors.Join(errs, fmt.Errorf("%w (%q): %w", errInvalidHandler, handler.ID(), err))
}
}
Expand All @@ -126,17 +137,18 @@ func ConfigureSDKv1(mw Middleware, handlers *request.Handlers) error {

// ConfigureSDKv2 adds middleware to the AWS SDK v2. Request handlers are added to the
// Build step and response handlers are added to the Deserialize step.
func ConfigureSDKv2(mw Middleware, config *aws.Config) error {
func (c *Configurer) ConfigureSDKv2(config *aws.Config) error {
var errs error
for _, handler := range mw.RequestHandlers() {
requestHandlers, responseHandlers := c.Middleware.Handlers()
for _, handler := range requestHandlers {
relativePosition, err := toRelativePosition(handler.Position())
if err != nil {
errs = errors.Join(errs, fmt.Errorf("%w (%q): %w", errInvalidHandler, handler.ID(), err))
continue
}
config.APIOptions = append(config.APIOptions, withBuildOption(&requestMiddleware{RequestHandler: handler}, relativePosition))
}
for _, handler := range mw.ResponseHandlers() {
for _, handler := range responseHandlers {
relativePosition, err := toRelativePosition(handler.Position())
if err != nil {
errs = errors.Join(errs, fmt.Errorf("%w (%q): %w", errInvalidHandler, handler.ID(), err))
Expand Down
Loading

0 comments on commit e5c60ba

Please sign in to comment.