Skip to content
This repository was archived by the owner on Oct 3, 2023. It is now read-only.

Commit 2c06ade

Browse files
author
Ramon Nogueira
authored
Allow customizing the metric type and display name (#44)
Fixes: #42
1 parent d1e19f5 commit 2c06ade

3 files changed

Lines changed: 121 additions & 18 deletions

File tree

stackdriver.go

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,10 +143,25 @@ type Options struct {
143143
// Optional, but encouraged.
144144
MonitoredResource monitoredresource.Interface
145145

146-
// MetricPrefix overrides the prefix of a Stackdriver metric type names.
147-
// Optional. If unset defaults to "OpenCensus".
146+
// MetricPrefix overrides the prefix of a Stackdriver metric display names.
147+
// Optional. If unset defaults to "OpenCensus/".
148+
// Deprecated: Provide GetMetricDisplayName to change the display name of
149+
// the metric.
150+
// If GetMetricDisplayName is non-nil, this option is ignored.
148151
MetricPrefix string
149152

153+
// GetMetricDisplayName allows customizing the display name for the metric
154+
// associated with the given view. By default it will be:
155+
// MetricPrefix + view.Name
156+
GetMetricDisplayName func(view *view.View) string
157+
158+
// GetMetricType allows customizing the metric type for the given view.
159+
// By default, it will be:
160+
// "custom.googleapis.com/opencensus/" + view.Name
161+
//
162+
// See: https://cloud.google.com/monitoring/api/ref_v3/rest/v3/projects.metricDescriptors#MetricDescriptor
163+
GetMetricType func(view *view.View) string
164+
150165
// DefaultTraceAttributes will be appended to every span that is exported to
151166
// Stackdriver Trace.
152167
DefaultTraceAttributes map[string]interface{}

stats.go

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ func (e *statsExporter) makeReq(vds []*view.Data, limit int) []*monitoringpb.Cre
189189
for _, row := range vd.Rows {
190190
ts := &monitoringpb.TimeSeries{
191191
Metric: &metricpb.Metric{
192-
Type: namespacedViewName(vd.View.Name),
192+
Type: e.metricType(vd.View),
193193
Labels: newLabels(e.defaultLabels, row.Tags),
194194
},
195195
Resource: resource,
@@ -230,7 +230,7 @@ func (e *statsExporter) createMeasure(ctx context.Context, v *view.View) error {
230230
return e.equalMeasureAggTagKeys(md, m, agg, tagKeys)
231231
}
232232

233-
metricType := namespacedViewName(viewName)
233+
metricType := e.metricType(v)
234234
var valueType metricpb.MetricDescriptor_ValueType
235235
unit := m.Unit()
236236
// Default metric Kind
@@ -263,16 +263,22 @@ func (e *statsExporter) createMeasure(ctx context.Context, v *view.View) error {
263263
return fmt.Errorf("unsupported aggregation type: %s", agg.Type.String())
264264
}
265265

266-
displayNamePrefix := defaultDisplayNamePrefix
267-
if e.o.MetricPrefix != "" {
268-
displayNamePrefix = e.o.MetricPrefix
266+
var displayName string
267+
if e.o.GetMetricDisplayName == nil {
268+
displayNamePrefix := defaultDisplayNamePrefix
269+
if e.o.MetricPrefix != "" {
270+
displayNamePrefix = e.o.MetricPrefix
271+
}
272+
displayName = path.Join(displayNamePrefix, viewName)
273+
} else {
274+
displayName = e.o.GetMetricDisplayName(v)
269275
}
270276

271277
md, err := createMetricDescriptor(ctx, e.c, &monitoringpb.CreateMetricDescriptorRequest{
272278
Name: fmt.Sprintf("projects/%s", e.o.ProjectID),
273279
MetricDescriptor: &metricpb.MetricDescriptor{
274280
Name: fmt.Sprintf("projects/%s/metricDescriptors/%s", e.o.ProjectID, metricType),
275-
DisplayName: path.Join(displayNamePrefix, viewName),
281+
DisplayName: displayName,
276282
Description: v.Description,
277283
Unit: unit,
278284
Type: metricType,
@@ -380,8 +386,12 @@ func newTypedValue(vd *view.View, r *view.Row) *monitoringpb.TypedValue {
380386
return nil
381387
}
382388

383-
func namespacedViewName(v string) string {
384-
return path.Join("custom.googleapis.com", "opencensus", v)
389+
func (e *statsExporter) metricType(v *view.View) string {
390+
if formatter := e.o.GetMetricType; formatter != nil {
391+
return formatter(v)
392+
} else {
393+
return path.Join("custom.googleapis.com", "opencensus", v.Name)
394+
}
385395
}
386396

387397
func newLabels(defaults map[string]labelValue, tags []tag.Tag) map[string]string {

stats_test.go

Lines changed: 86 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323

2424
"cloud.google.com/go/monitoring/apiv3"
2525
"github.com/golang/protobuf/ptypes/timestamp"
26+
"github.com/google/go-cmp/cmp"
2627
"go.opencensus.io/stats"
2728
"go.opencensus.io/stats/view"
2829
"go.opencensus.io/tag"
@@ -58,7 +59,7 @@ func TestExporter_makeReq(t *testing.T) {
5859
}
5960

6061
v := &view.View{
61-
Name: "testview",
62+
Name: "example.com/views/testview",
6263
Description: "desc",
6364
TagKeys: []tag.Key{key},
6465
Measure: m,
@@ -95,6 +96,7 @@ func TestExporter_makeReq(t *testing.T) {
9596
projID string
9697
vd *view.Data
9798
want []*monitoringpb.CreateTimeSeriesRequest
99+
opts Options
98100
}{
99101
{
100102
name: "count agg + timeline",
@@ -105,7 +107,7 @@ func TestExporter_makeReq(t *testing.T) {
105107
TimeSeries: []*monitoringpb.TimeSeries{
106108
{
107109
Metric: &metricpb.Metric{
108-
Type: "custom.googleapis.com/opencensus/testview",
110+
Type: "custom.googleapis.com/opencensus/example.com/views/testview",
109111
Labels: map[string]string{
110112
"test_key": "test-value-1",
111113
opencensusTaskKey: taskValue,
@@ -134,7 +136,7 @@ func TestExporter_makeReq(t *testing.T) {
134136
},
135137
{
136138
Metric: &metricpb.Metric{
137-
Type: "custom.googleapis.com/opencensus/testview",
139+
Type: "custom.googleapis.com/opencensus/example.com/views/testview",
138140
Labels: map[string]string{
139141
"test_key": "test-value-2",
140142
opencensusTaskKey: taskValue,
@@ -164,6 +166,79 @@ func TestExporter_makeReq(t *testing.T) {
164166
},
165167
}},
166168
},
169+
{
170+
name: "metric type formatter",
171+
projID: "proj-id",
172+
vd: newTestViewData(v, start, end, sum1, sum2),
173+
opts: Options{
174+
GetMetricType: func(v *view.View) string {
175+
return fmt.Sprintf("external.googleapis.com/%s", v.Name)
176+
},
177+
},
178+
want: []*monitoringpb.CreateTimeSeriesRequest{{
179+
Name: monitoring.MetricProjectPath("proj-id"),
180+
TimeSeries: []*monitoringpb.TimeSeries{
181+
{
182+
Metric: &metricpb.Metric{
183+
Type: "external.googleapis.com/example.com/views/testview",
184+
Labels: map[string]string{
185+
"test_key": "test-value-1",
186+
opencensusTaskKey: taskValue,
187+
},
188+
},
189+
Resource: &monitoredrespb.MonitoredResource{
190+
Type: "global",
191+
},
192+
Points: []*monitoringpb.Point{
193+
{
194+
Interval: &monitoringpb.TimeInterval{
195+
StartTime: &timestamp.Timestamp{
196+
Seconds: start.Unix(),
197+
Nanos: int32(start.Nanosecond()),
198+
},
199+
EndTime: &timestamp.Timestamp{
200+
Seconds: end.Unix(),
201+
Nanos: int32(end.Nanosecond()),
202+
},
203+
},
204+
Value: &monitoringpb.TypedValue{Value: &monitoringpb.TypedValue_DoubleValue{
205+
DoubleValue: 5.5,
206+
}},
207+
},
208+
},
209+
},
210+
{
211+
Metric: &metricpb.Metric{
212+
Type: "external.googleapis.com/example.com/views/testview",
213+
Labels: map[string]string{
214+
"test_key": "test-value-2",
215+
opencensusTaskKey: taskValue,
216+
},
217+
},
218+
Resource: &monitoredrespb.MonitoredResource{
219+
Type: "global",
220+
},
221+
Points: []*monitoringpb.Point{
222+
{
223+
Interval: &monitoringpb.TimeInterval{
224+
StartTime: &timestamp.Timestamp{
225+
Seconds: start.Unix(),
226+
Nanos: int32(start.Nanosecond()),
227+
},
228+
EndTime: &timestamp.Timestamp{
229+
Seconds: end.Unix(),
230+
Nanos: int32(end.Nanosecond()),
231+
},
232+
},
233+
Value: &monitoringpb.TypedValue{Value: &monitoringpb.TypedValue_DoubleValue{
234+
DoubleValue: -11.1,
235+
}},
236+
},
237+
},
238+
},
239+
},
240+
}},
241+
},
167242
{
168243
name: "sum agg + timeline",
169244
projID: "proj-id",
@@ -173,7 +248,7 @@ func TestExporter_makeReq(t *testing.T) {
173248
TimeSeries: []*monitoringpb.TimeSeries{
174249
{
175250
Metric: &metricpb.Metric{
176-
Type: "custom.googleapis.com/opencensus/testview",
251+
Type: "custom.googleapis.com/opencensus/example.com/views/testview",
177252
Labels: map[string]string{
178253
"test_key": "test-value-1",
179254
opencensusTaskKey: taskValue,
@@ -202,7 +277,7 @@ func TestExporter_makeReq(t *testing.T) {
202277
},
203278
{
204279
Metric: &metricpb.Metric{
205-
Type: "custom.googleapis.com/opencensus/testview",
280+
Type: "custom.googleapis.com/opencensus/example.com/views/testview",
206281
Labels: map[string]string{
207282
"test_key": "test-value-2",
208283
opencensusTaskKey: taskValue,
@@ -341,7 +416,10 @@ func TestExporter_makeReq(t *testing.T) {
341416
}
342417
for _, tt := range tests {
343418
t.Run(tt.name, func(t *testing.T) {
344-
e, err := newStatsExporter(Options{ProjectID: tt.projID, MonitoringClientOptions: authOptions})
419+
opts := tt.opts
420+
opts.ProjectID = tt.projID
421+
opts.MonitoringClientOptions = authOptions
422+
e, err := newStatsExporter(opts)
345423
if err != nil {
346424
t.Fatal(err)
347425
}
@@ -352,8 +430,8 @@ func TestExporter_makeReq(t *testing.T) {
352430
if len(tt.want) == 0 {
353431
return
354432
}
355-
if !reflect.DeepEqual(resps, tt.want) {
356-
t.Errorf("%v: Exporter.makeReq() = %v, want %v", tt.name, resps, tt.want)
433+
if diff := cmp.Diff(resps, tt.want); diff != "" {
434+
t.Errorf("Values differ -got +want: %s", diff)
357435
}
358436
})
359437
}

0 commit comments

Comments
 (0)