Skip to content

Commit 6aa27dc

Browse files
authored
fix(bigtable): Correct the 'method' label value (#11350)
1 parent 1513106 commit 6aa27dc

File tree

3 files changed

+58
-7
lines changed

3 files changed

+58
-7
lines changed

bigtable/bigtable.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1605,7 +1605,7 @@ func gaxInvokeWithRecorder(ctx context.Context, mt *builtinMetricsTracer, method
16051605
f func(ctx context.Context, headerMD, trailerMD *metadata.MD, _ gax.CallSettings) error, opts ...gax.CallOption) error {
16061606
attemptHeaderMD := metadata.New(nil)
16071607
attempTrailerMD := metadata.New(nil)
1608-
mt.method = method
1608+
mt.setMethod(method)
16091609

16101610
var callWrapper func(context.Context, gax.CallSettings) error
16111611
if !mt.builtInEnabled {

bigtable/metrics.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,10 @@ type builtinMetricsTracer struct {
293293
currOp opTracer
294294
}
295295

296+
func (b *builtinMetricsTracer) setMethod(m string) {
297+
b.method = "Bigtable." + m
298+
}
299+
296300
// opTracer is used to record metrics for the entire operation, including retries.
297301
// Operation is a logical unit that represents a single method invocation on client.
298302
// The method might require multiple attempts/rpcs and backoff logic to complete

bigtable/metrics_test.go

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"encoding/base64"
2323
"fmt"
2424
"io"
25+
"slices"
2526
"sort"
2627
"strings"
2728
"sync"
@@ -166,17 +167,17 @@ func TestNewBuiltinMetricsTracerFactory(t *testing.T) {
166167
}{
167168
{
168169
desc: "should create a new tracer factory with default meter provider",
169-
config: ClientConfig{},
170+
config: ClientConfig{AppProfile: appProfile},
170171
wantBuiltinEnabled: true,
171172
wantCreateTSCallsCount: 2,
172173
},
173174
{
174175
desc: "should create a new tracer factory with noop meter provider",
175-
config: ClientConfig{MetricsProvider: NoopMetricsProvider{}},
176+
config: ClientConfig{MetricsProvider: NoopMetricsProvider{}, AppProfile: appProfile},
176177
},
177178
{
178179
desc: "should not create instruments when BIGTABLE_EMULATOR_HOST is set",
179-
config: ClientConfig{},
180+
config: ClientConfig{AppProfile: appProfile},
180181
setEmulator: true,
181182
},
182183
}
@@ -201,9 +202,8 @@ func TestNewBuiltinMetricsTracerFactory(t *testing.T) {
201202
t.Errorf("builtinEnabled: got: %v, want: %v", gotClient.metricsTracerFactory.enabled, test.wantBuiltinEnabled)
202203
}
203204

204-
if diff := testutil.Diff(gotClient.metricsTracerFactory.clientAttributes, wantClientAttributes,
205-
cmpopts.IgnoreUnexported(attribute.KeyValue{}, attribute.Value{})); diff != "" {
206-
t.Errorf("clientAttributes: got=-, want=+ \n%v", diff)
205+
if !equalsKeyValue(gotClient.metricsTracerFactory.clientAttributes, wantClientAttributes) {
206+
t.Errorf("clientAttributes: got: %+v, want: %+v", gotClient.metricsTracerFactory.clientAttributes, wantClientAttributes)
207207
}
208208

209209
// Check instruments
@@ -265,7 +265,26 @@ func TestNewBuiltinMetricsTracerFactory(t *testing.T) {
265265
for _, gotCreateTSCall := range gotCreateTSCalls {
266266
gotMetricTypes := []string{}
267267
for _, ts := range gotCreateTSCall.TimeSeries {
268+
// ts.Metric.Type is of the form "bigtable.googleapis.com/internal/client/server_latencies"
268269
gotMetricTypes = append(gotMetricTypes, ts.Metric.Type)
270+
271+
// Assert "streaming" metric label is correct
272+
gotStreaming, gotStreamingExists := ts.Metric.Labels[metricLabelKeyStreamingOperation]
273+
splitMetricType := strings.Split(ts.Metric.Type, "/")
274+
internalMetricName := splitMetricType[len(splitMetricType)-1] // server_latencies
275+
wantStreamingExists := slices.Contains(metricsDetails[internalMetricName].additionalAttrs, metricLabelKeyStreamingOperation)
276+
if wantStreamingExists && (!gotStreamingExists || gotStreaming != "true") {
277+
t.Errorf("Metric label key: %s, value: got: %v, want: %v", metricLabelKeyStreamingOperation, gotStreaming, "true")
278+
}
279+
if !wantStreamingExists && gotStreamingExists {
280+
t.Errorf("Metric label key: %s exists, value: got: %v, want: %v", metricLabelKeyStreamingOperation, gotStreamingExists, wantStreamingExists)
281+
}
282+
283+
// Assert "method" metric label is correct
284+
wantMethod := "Bigtable.ReadRows"
285+
if gotLabel, ok := ts.Metric.Labels[metricLabelKeyMethod]; !ok || gotLabel != wantMethod {
286+
t.Errorf("Metric label key: %s, value: got: %v, want: %v", metricLabelKeyMethod, gotLabel, wantMethod)
287+
}
269288
}
270289
sort.Strings(gotMetricTypes)
271290
if !testutil.Equal(gotMetricTypes, wantMetricTypesGCM) {
@@ -289,6 +308,34 @@ func setMockErrorHandler(t *testing.T, mockErrorHandler *MockErrorHandler) {
289308
})
290309
}
291310

311+
func equalsKeyValue(gotAttrs, wantAttrs []attribute.KeyValue) bool {
312+
if len(gotAttrs) != len(wantAttrs) {
313+
return false
314+
}
315+
316+
gotJSONVals, err := keyValueToKeyJSONValue(gotAttrs)
317+
if err != nil {
318+
return false
319+
}
320+
wantJSONVals, err := keyValueToKeyJSONValue(wantAttrs)
321+
if err != nil {
322+
return false
323+
}
324+
return testutil.Equal(gotJSONVals, wantJSONVals)
325+
}
326+
327+
func keyValueToKeyJSONValue(attrs []attribute.KeyValue) (map[string]string, error) {
328+
keyJSONVal := map[string]string{}
329+
for _, attr := range attrs {
330+
jsonVal, err := attr.Value.MarshalJSON()
331+
if err != nil {
332+
return nil, err
333+
}
334+
keyJSONVal[string(attr.Key)] = string(jsonVal)
335+
}
336+
return keyJSONVal, nil
337+
}
338+
292339
func TestExporterLogs(t *testing.T) {
293340
ctx := context.Background()
294341
project := "test-project"

0 commit comments

Comments
 (0)