Skip to content

Commit b6dc37c

Browse files
authored
improve error handling (#492)
1 parent b72b874 commit b6dc37c

2 files changed

Lines changed: 28 additions & 62 deletions

File tree

exporter/metric/metric.go

Lines changed: 28 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ package metric
1717
import (
1818
"context"
1919
"fmt"
20-
"log"
2120
"math"
2221
"reflect"
2322
"strings"
@@ -148,14 +147,10 @@ func newMetricExporter(o *options) (*metricExporter, error) {
148147

149148
// Export exports OpenTelemetry Metrics to Google Cloud Monitoring.
150149
func (me *metricExporter) Export(ctx context.Context, rm metricdata.ResourceMetrics) error {
151-
if err := me.exportMetricDescriptor(ctx, rm); err != nil {
152-
return err
153-
}
154-
155-
if err := me.exportTimeSeries(ctx, rm); err != nil {
156-
return err
157-
}
158-
return nil
150+
return multierr.Combine(
151+
me.exportMetricDescriptor(ctx, rm),
152+
me.exportTimeSeries(ctx, rm),
153+
)
159154
}
160155

161156
// exportMetricDescriptor create MetricDescriptor from the record
@@ -182,14 +177,15 @@ func (me *metricExporter) exportMetricDescriptor(ctx context.Context, rm metricd
182177
// goroutines to send CreateMetricDescriptorRequest asynchronously in the case
183178
// the descriptor does not exist in global cache (me.mdCache).
184179
// See details in #26.
180+
var err error
185181
for kmd, md := range mds {
186-
err := me.createMetricDescriptorIfNeeded(ctx, md)
187-
if err != nil {
188-
return err
182+
cmdErr := me.createMetricDescriptorIfNeeded(ctx, md)
183+
if cmdErr == nil {
184+
me.mdCache[kmd] = md
189185
}
190-
me.mdCache[kmd] = md
186+
err = multierr.Append(err, cmdErr)
191187
}
192-
return nil
188+
return err
193189
}
194190

195191
func (me *metricExporter) createMetricDescriptorIfNeeded(ctx context.Context, md *googlemetricpb.MetricDescriptor) error {
@@ -217,34 +213,18 @@ func (me *metricExporter) createMetricDescriptorIfNeeded(ctx context.Context, md
217213
func (me *metricExporter) exportTimeSeries(ctx context.Context, rm metricdata.ResourceMetrics) error {
218214
tss := []*monitoringpb.TimeSeries{}
219215
mr := me.resourceToMonitoredResourcepb(rm.Resource)
220-
var errs []error
216+
var aggError error
221217

222218
for _, scope := range rm.ScopeMetrics {
223219
for _, metrics := range scope.Metrics {
224220
ts, err := me.recordToTspb(metrics, mr, scope.Scope)
225-
if err != nil {
226-
errs = append(errs, err)
227-
} else {
228-
tss = append(tss, ts...)
229-
}
230-
}
231-
}
232-
233-
var aggError error
234-
if len(errs) > 0 {
235-
aggError = multierr.Combine(errs...)
236-
}
237-
238-
if aggError != nil {
239-
if me.o.onError != nil {
240-
me.o.onError(aggError)
241-
} else {
242-
log.Printf("Error during exporting TimeSeries: %v", aggError)
221+
aggError = multierr.Append(aggError, err)
222+
tss = append(tss, ts...)
243223
}
244224
}
245225

246226
if len(tss) == 0 {
247-
return nil
227+
return aggError
248228
}
249229

250230
// TODO: When this exporter is rewritten, support writing to multiple
@@ -254,7 +234,7 @@ func (me *metricExporter) exportTimeSeries(ctx context.Context, rm metricdata.Re
254234
TimeSeries: tss,
255235
}
256236

257-
return me.client.CreateTimeSeries(ctx, req)
237+
return multierr.Append(aggError, me.client.CreateTimeSeries(ctx, req))
258238
}
259239

260240
// descToMetricType converts descriptor to MetricType proto type.
@@ -433,13 +413,13 @@ func (me *metricExporter) recordToMpb(metrics metricdata.Metrics, attributes att
433413
// ref. https://cloud.google.com/monitoring/api/ref_v3/rest/v3/TimeSeries
434414
func (me *metricExporter) recordToTspb(m metricdata.Metrics, mr *monitoredrespb.MonitoredResource, library instrumentation.Scope) ([]*monitoringpb.TimeSeries, error) {
435415
var tss []*monitoringpb.TimeSeries
436-
errs := []error{}
416+
var aggErr error
437417
switch a := m.Data.(type) {
438418
case metricdata.Gauge[int64]:
439419
for _, point := range a.DataPoints {
440420
ts, err := gaugeToTimeSeries[int64](point, m, mr)
441421
if err != nil {
442-
errs = append(errs, err)
422+
aggErr = multierr.Append(aggErr, err)
443423
continue
444424
}
445425
ts.Metric = me.recordToMpb(m, point.Attributes, library)
@@ -449,7 +429,7 @@ func (me *metricExporter) recordToTspb(m metricdata.Metrics, mr *monitoredrespb.
449429
for _, point := range a.DataPoints {
450430
ts, err := gaugeToTimeSeries[float64](point, m, mr)
451431
if err != nil {
452-
errs = append(errs, err)
432+
aggErr = multierr.Append(aggErr, err)
453433
continue
454434
}
455435
ts.Metric = me.recordToMpb(m, point.Attributes, library)
@@ -466,7 +446,7 @@ func (me *metricExporter) recordToTspb(m metricdata.Metrics, mr *monitoredrespb.
466446
ts, err = gaugeToTimeSeries[int64](point, m, mr)
467447
}
468448
if err != nil {
469-
errs = append(errs, err)
449+
aggErr = multierr.Append(aggErr, err)
470450
continue
471451
}
472452
ts.Metric = me.recordToMpb(m, point.Attributes, library)
@@ -483,7 +463,7 @@ func (me *metricExporter) recordToTspb(m metricdata.Metrics, mr *monitoredrespb.
483463
ts, err = gaugeToTimeSeries[float64](point, m, mr)
484464
}
485465
if err != nil {
486-
errs = append(errs, err)
466+
aggErr = multierr.Append(aggErr, err)
487467
continue
488468
}
489469
ts.Metric = me.recordToMpb(m, point.Attributes, library)
@@ -493,16 +473,16 @@ func (me *metricExporter) recordToTspb(m metricdata.Metrics, mr *monitoredrespb.
493473
for _, point := range a.DataPoints {
494474
ts, err := histogramToTimeSeries(point, m, mr)
495475
if err != nil {
496-
errs = append(errs, err)
476+
aggErr = multierr.Append(aggErr, err)
497477
continue
498478
}
499479
ts.Metric = me.recordToMpb(m, point.Attributes, library)
500480
tss = append(tss, ts)
501481
}
502482
default:
503-
errs = append(errs, errUnexpectedAggregationKind{kind: reflect.TypeOf(m.Data).String()})
483+
aggErr = multierr.Append(aggErr, errUnexpectedAggregationKind{kind: reflect.TypeOf(m.Data).String()})
504484
}
505-
return tss, multierr.Combine(errs...)
485+
return tss, aggErr
506486
}
507487

508488
func sanitizeUTF8(s string) string {
@@ -572,14 +552,13 @@ func toNonemptyTimeIntervalpb(start, end time.Time) (*monitoringpb.TimeInterval,
572552
if end.Sub(start).Milliseconds() <= 1 {
573553
end = start.Add(time.Millisecond)
574554
}
575-
576555
startpb := timestamppb.New(start)
577-
if err := startpb.CheckValid(); err != nil {
578-
return nil, err
579-
}
580-
581556
endpb := timestamppb.New(end)
582-
if err := endpb.CheckValid(); err != nil {
557+
err := multierr.Combine(
558+
startpb.CheckValid(),
559+
endpb.CheckValid(),
560+
)
561+
if err != nil {
583562
return nil, err
584563
}
585564

exporter/metric/option.go

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,6 @@ type options struct {
4141
// metricDescriptorTypeFormatter is the custom formtter for the MetricDescriptor.Type.
4242
// By default, the format string is "custom.googleapis.com/opentelemetry/[metric name]".
4343
metricDescriptorTypeFormatter func(metricdata.Metrics) string
44-
// onError is the hook to be called when there is an error uploading the metric data.
45-
// If no custom hook is set, errors are logged. Optional.
46-
//
47-
// TODO: This option should be replaced with OTel defining error handler.
48-
// c.f. https://pkg.go.dev/go.opentelemetry.io/otel@v0.6.0/sdk/metric/controller/push?tab=doc#Config
49-
onError func(error)
5044
// projectID is the identifier of the Cloud Monitoring
5145
// project the user is uploading the stats data to.
5246
// If not set, this will default to your "Application Default Credentials".
@@ -90,10 +84,3 @@ func WithMetricDescriptorTypeFormatter(f func(metricdata.Metrics) string) func(o
9084
o.metricDescriptorTypeFormatter = f
9185
}
9286
}
93-
94-
// WithOnError sets the custom error handler to be called on errors.
95-
func WithOnError(f func(error)) func(o *options) {
96-
return func(o *options) {
97-
o.onError = f
98-
}
99-
}

0 commit comments

Comments
 (0)