Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for shallow cloning azcore.Client instances #21065

Merged
merged 2 commits into from
Jun 26, 2023
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions sdk/azcore/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@
### Features Added

- `messaging/CloudEvent` allows you to serialize/deserialize CloudEvents, as described in the CloudEvents 1.0 specification: [link](https://github.com/cloudevents/spec)
* Added method `WithClientName()` to type `azcore.Client` to support shallow cloning of a client with a new name used for tracing.

### Breaking Changes

25 changes: 24 additions & 1 deletion sdk/azcore/core.go
Original file line number Diff line number Diff line change
@@ -73,6 +73,11 @@ type ClientOptions = policy.ClientOptions
type Client struct {
pl runtime.Pipeline
tr tracing.Tracer

// cached on the client to support shallow copying with new values
tp tracing.Provider
mv string
jhendrixMSFT marked this conversation as resolved.
Show resolved Hide resolved
ns string
}

// NewClient creates a new Client instance with the provided values.
@@ -103,7 +108,14 @@ func NewClient(clientName, moduleVersion string, plOpts runtime.PipelineOptions,
if tr.Enabled() && plOpts.TracingNamespace != "" {
tr.SetAttributes(tracing.Attribute{Key: "az.namespace", Value: plOpts.TracingNamespace})
}
return &Client{pl: pl, tr: tr}, nil

return &Client{
pl: pl,
tr: tr,
tp: options.TracingProvider,
mv: moduleVersion,
ns: plOpts.TracingNamespace,
}, nil
}

// Pipeline returns the pipeline for this client.
@@ -115,3 +127,14 @@ func (c *Client) Pipeline() runtime.Pipeline {
func (c *Client) Tracer() tracing.Tracer {
return c.tr
}

// WithClientName returns a shallow copy of the Client with its tracing client name changed to clientName.
// Note that the values for module name and version will be preserved from the source Client.
// - clientName - the fully qualified name of the client ("package.Client"); this is used by the tracing provider when creating spans
func (c *Client) WithClientName(clientName string) *Client {
tr := c.tp.NewTracer(clientName, c.mv)
if tr.Enabled() && c.ns != "" {
tr.SetAttributes(tracing.Attribute{Key: "az.namespace", Value: c.ns})
}
return &Client{pl: c.pl, tr: tr, tp: c.tp, mv: c.mv, ns: c.ns}
}
48 changes: 48 additions & 0 deletions sdk/azcore/core_test.go
Original file line number Diff line number Diff line change
@@ -172,3 +172,51 @@ func TestNewClientTracingEnabled(t *testing.T) {
require.NoError(t, err)
require.EqualValues(t, "az.namespace:Widget.Factory", attrString)
}

func TestClientWithClientName(t *testing.T) {
srv, close := mock.NewServer()
defer close()

var clientName string
var modVersion string
var attrString string
client, err := NewClient("module/package.Client", "v1.0.0", runtime.PipelineOptions{TracingNamespace: "Widget.Factory"}, &policy.ClientOptions{
TracingProvider: tracing.NewProvider(func(name, version string) tracing.Tracer {
clientName = name
modVersion = version
return tracing.NewTracer(func(ctx context.Context, spanName string, options *tracing.SpanOptions) (context.Context, tracing.Span) {
require.NotNil(t, options)
for _, attr := range options.Attributes {
if attr.Key == "az.namespace" {
v, ok := attr.Value.(string)
require.True(t, ok)
attrString = attr.Key + ":" + v
}
}
return ctx, tracing.Span{}
}, nil)
}, nil),
Transport: srv,
})
require.NoError(t, err)
require.NotNil(t, client)
require.NotZero(t, client.Pipeline())
require.NotZero(t, client.Tracer())
require.EqualValues(t, "package.Client", clientName)
require.EqualValues(t, "v1.0.0", modVersion)

const requestEndpoint = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/fakeResourceGroupo/providers/Microsoft.Storage/storageAccounts/fakeAccountName"
req, err := exported.NewRequest(context.WithValue(context.Background(), shared.CtxWithTracingTracer{}, client.Tracer()), http.MethodGet, srv.URL()+requestEndpoint)
require.NoError(t, err)
srv.SetResponse()
_, err = client.Pipeline().Do(req)
require.NoError(t, err)
require.EqualValues(t, "az.namespace:Widget.Factory", attrString)

newClient := client.WithClientName("other.Client")
require.EqualValues(t, "other.Client", clientName)
require.EqualValues(t, "v1.0.0", modVersion)
_, err = newClient.Pipeline().Do(req)
require.NoError(t, err)
require.EqualValues(t, "az.namespace:Widget.Factory", attrString)
}