Skip to content

Commit 62a8079

Browse files
authored
Add support for shallow cloning azcore.Client instances (#21065) (#21098)
* Add support for shallow cloning azcore.Client instances This allows for multiple clients to share the same underlying pipeline while having the correct client name string in traces. * improved field names
1 parent 47286b0 commit 62a8079

File tree

3 files changed

+106
-2
lines changed

3 files changed

+106
-2
lines changed

sdk/azcore/CHANGELOG.md

+44-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,54 @@
11
# Release History
22

3+
## 1.7.0 (Unreleased)
4+
5+
### Features Added
6+
* Added method `WithClientName()` to type `azcore.Client` to support shallow cloning of a client with a new name used for tracing.
7+
8+
### Breaking Changes
9+
> These changes affect only code written against beta versions v1.7.0-beta.1 or v1.7.0-beta.2
10+
* The beta features for CAE, tracing, and fakes have been omitted for this release.
11+
12+
### Bugs Fixed
13+
14+
### Other Changes
15+
16+
## 1.7.0-beta.2 (2023-06-06)
17+
18+
### Breaking Changes
19+
> These changes affect only code written against beta version v1.7.0-beta.1
20+
* Method `SpanFromContext()` on type `tracing.Tracer` had the `bool` return value removed.
21+
* This includes the field `SpanFromContext` in supporting type `tracing.TracerOptions`.
22+
* Method `AddError()` has been removed from type `tracing.Span`.
23+
* Method `Span.End()` now requires an argument of type `*tracing.SpanEndOptions`.
24+
325
## 1.6.1 (2023-06-06)
426

27+
### Bugs Fixed
28+
* Fixed an issue in `azcore.NewClient()` and `arm.NewClient()` that could cause an incorrect module name to be used in telemetry.
29+
30+
### Other Changes
31+
* This version contains all bug fixes from `v1.7.0-beta.1`
32+
33+
## 1.7.0-beta.1 (2023-05-24)
34+
35+
### Features Added
36+
* Restored CAE support for ARM clients.
37+
* Added supporting features to enable distributed tracing.
38+
* Added func `runtime.StartSpan()` for use by SDKs to start spans.
39+
* Added method `WithContext()` to `runtime.Request` to support shallow cloning with a new context.
40+
* Added field `TracingNamespace` to `runtime.PipelineOptions`.
41+
* Added field `Tracer` to `runtime.NewPollerOptions` and `runtime.NewPollerFromResumeTokenOptions` types.
42+
* Added field `SpanFromContext` to `tracing.TracerOptions`.
43+
* Added methods `Enabled()`, `SetAttributes()`, and `SpanFromContext()` to `tracing.Tracer`.
44+
* Added supporting pipeline policies to include HTTP spans when creating clients.
45+
* Added package `fake` to support generated fakes packages in SDKs.
46+
* The package contains public surface area exposed by fake servers and supporting APIs intended only for use by the fake server implementations.
47+
* Added an internal fake poller implementation.
48+
549
### Bugs Fixed
650
* Retry policy always clones the underlying `*http.Request` before invoking the next policy.
751
* Added some non-standard error codes to the list of error codes for unregistered resource providers.
8-
* Fixed an issue in `azcore.NewClient()` and `arm.NewClient()` that could cause an incorrect module name to be used in telemetry.
952

1053
## 1.6.0 (2023-05-04)
1154

sdk/azcore/core.go

+19-1
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ type ClientOptions = policy.ClientOptions
7373
type Client struct {
7474
pl runtime.Pipeline
7575
tr tracing.Tracer
76+
77+
// cached on the client to support shallow copying with new values
78+
tp tracing.Provider
79+
modVer string
7680
}
7781

7882
// NewClient creates a new Client instance with the provided values.
@@ -100,7 +104,13 @@ func NewClient(clientName, moduleVersion string, plOpts runtime.PipelineOptions,
100104
pl := runtime.NewPipeline(mod, moduleVersion, plOpts, options)
101105

102106
tr := options.TracingProvider.NewTracer(client, moduleVersion)
103-
return &Client{pl: pl, tr: tr}, nil
107+
108+
return &Client{
109+
pl: pl,
110+
tr: tr,
111+
tp: options.TracingProvider,
112+
modVer: moduleVersion,
113+
}, nil
104114
}
105115

106116
// Pipeline returns the pipeline for this client.
@@ -112,3 +122,11 @@ func (c *Client) Pipeline() runtime.Pipeline {
112122
func (c *Client) Tracer() tracing.Tracer {
113123
return c.tr
114124
}
125+
126+
// WithClientName returns a shallow copy of the Client with its tracing client name changed to clientName.
127+
// Note that the values for module name and version will be preserved from the source Client.
128+
// - clientName - the fully qualified name of the client ("package.Client"); this is used by the tracing provider when creating spans
129+
func (c *Client) WithClientName(clientName string) *Client {
130+
tr := c.tp.NewTracer(clientName, c.modVer)
131+
return &Client{pl: c.pl, tr: tr, tp: c.tp, modVer: c.modVer}
132+
}

sdk/azcore/core_test.go

+43
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,16 @@
77
package azcore
88

99
import (
10+
"context"
11+
"net/http"
1012
"reflect"
1113
"testing"
1214

15+
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported"
1316
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
1417
"github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
18+
"github.com/Azure/azure-sdk-for-go/sdk/azcore/tracing"
19+
"github.com/Azure/azure-sdk-for-go/sdk/internal/mock"
1520
"github.com/stretchr/testify/require"
1621
)
1722

@@ -131,3 +136,41 @@ func TestNewClientError(t *testing.T) {
131136
require.Error(t, err)
132137
require.Nil(t, client)
133138
}
139+
140+
func TestClientWithClientName(t *testing.T) {
141+
srv, close := mock.NewServer()
142+
defer close()
143+
144+
var clientName string
145+
var modVersion string
146+
client, err := NewClient("module/package.Client", "v1.0.0", runtime.PipelineOptions{}, &policy.ClientOptions{
147+
TracingProvider: tracing.NewProvider(func(name, version string) tracing.Tracer {
148+
clientName = name
149+
modVersion = version
150+
return tracing.NewTracer(func(ctx context.Context, spanName string, options *tracing.SpanOptions) (context.Context, tracing.Span) {
151+
return ctx, tracing.Span{}
152+
}, nil)
153+
}, nil),
154+
Transport: srv,
155+
})
156+
require.NoError(t, err)
157+
require.NotNil(t, client)
158+
require.NotZero(t, client.Pipeline())
159+
require.NotZero(t, client.Tracer())
160+
require.EqualValues(t, "package.Client", clientName)
161+
require.EqualValues(t, "v1.0.0", modVersion)
162+
163+
const requestEndpoint = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/fakeResourceGroupo/providers/Microsoft.Storage/storageAccounts/fakeAccountName"
164+
req, err := exported.NewRequest(context.Background(), http.MethodGet, srv.URL()+requestEndpoint)
165+
require.NoError(t, err)
166+
srv.SetResponse()
167+
_, err = client.Pipeline().Do(req)
168+
require.NoError(t, err)
169+
170+
newClient := client.WithClientName("other.Client")
171+
require.EqualValues(t, "other.Client", clientName)
172+
require.EqualValues(t, "v1.0.0", modVersion)
173+
require.EqualValues(t, client.Pipeline(), newClient.Pipeline())
174+
_, err = newClient.Pipeline().Do(req)
175+
require.NoError(t, err)
176+
}

0 commit comments

Comments
 (0)