internal/telemetry/export/ocagent: correctly JSON marshal BucketOptionsExplicit

This change adds a custom MarshalJSON method to BucketOptionsExplicit for
marshalling parity with protobuf/jsonpb. This allows the OpenCensus service
to correctly decode a distribution's BucketOptions.

Updates golang/go#33819

Change-Id: Ia9dc868e1cbfc32a956f6a276dfd1591f7d4d31a
Reviewed-on: https://go-review.googlesource.com/c/tools/+/208398
Reviewed-by: Emmanuel Odeke <emm.odeke@gmail.com>
Run-TryBot: Emmanuel Odeke <emm.odeke@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
diff --git a/internal/telemetry/export/ocagent/wire/metrics.go b/internal/telemetry/export/ocagent/wire/metrics.go
index d9ff519..5e1b735 100644
--- a/internal/telemetry/export/ocagent/wire/metrics.go
+++ b/internal/telemetry/export/ocagent/wire/metrics.go
@@ -148,6 +148,24 @@
 
 func (BucketOptionsExplicit) tagBucketOptions() {}
 
+// Declared for the purpose of custom JSON marshalling without cycles.
+type bucketOptionsExplicitAlias BucketOptionsExplicit
+
+// MarshalJSON creates JSON formatted the same way as jsonpb so that the
+// OpenCensus service can correctly determine the underlying value type.
+// This custom MarshalJSON exists because,
+// by default BucketOptionsExplicit is JSON marshalled as:
+//     {"bounds":[1,2,3]}
+// but it should be marshalled as:
+//     {"explicit":{"bounds":[1,2,3]}}
+func (be *BucketOptionsExplicit) MarshalJSON() ([]byte, error) {
+	return json.Marshal(&struct {
+		Explicit *bucketOptionsExplicitAlias `json:"explicit,omitempty"`
+	}{
+		Explicit: (*bucketOptionsExplicitAlias)(be),
+	})
+}
+
 type Bucket struct {
 	Count    int64     `json:"count,omitempty"`
 	Exemplar *Exemplar `json:"exemplar,omitempty"`
diff --git a/internal/telemetry/export/ocagent/wire/metrics_test.go b/internal/telemetry/export/ocagent/wire/metrics_test.go
index b510ee2..fe2497d 100644
--- a/internal/telemetry/export/ocagent/wire/metrics_test.go
+++ b/internal/telemetry/export/ocagent/wire/metrics_test.go
@@ -44,7 +44,7 @@
 								Count: 2,
 							},
 						},
-						BucketOptions: BucketOptionsExplicit{
+						BucketOptions: &BucketOptionsExplicit{
 							Bounds: []float64{
 								0, 5,
 							},
@@ -52,7 +52,7 @@
 					},
 				},
 			},
-			`{"distributionValue":{"count":3,"sum":10,"bucket_options":{"bounds":[0,5]},"buckets":[{"count":1},{"count":2}]}}`,
+			`{"distributionValue":{"count":3,"sum":10,"bucket_options":{"explicit":{"bounds":[0,5]}},"buckets":[{"count":1},{"count":2}]}}`,
 		},
 		{
 			"nil point",