Skip to content

Commit 519ed9b

Browse files
authored
feat(bigtable): add handling of longupdown metrics aka gauge (#13871)
Same as googleapis/java-bigtable#2719 for subchannel/open_connections
1 parent 04d0eb6 commit 519ed9b

File tree

2 files changed

+43
-13
lines changed

2 files changed

+43
-13
lines changed

bigtable/metrics_monitoring_exporter.go

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -249,11 +249,15 @@ func (me *monitoringExporter) recordToTimeSeriesPb(m otelmetricdata.Metrics) ([]
249249
tss = append(tss, ts)
250250
}
251251
case otelmetricdata.Sum[int64]:
252+
kind := googlemetricpb.MetricDescriptor_CUMULATIVE
253+
if !a.IsMonotonic {
254+
kind = googlemetricpb.MetricDescriptor_GAUGE
255+
}
252256
for _, point := range a.DataPoints {
253257
metric, mr := me.recordToMetricAndMonitoredResourcePbs(m, point.Attributes)
254258
var ts *monitoringpb.TimeSeries
255259
var err error
256-
ts, err = sumToTimeSeries[int64](point, m, mr)
260+
ts, err = sumToTimeSeries[int64](point, m, mr, kind)
257261
if err != nil {
258262
errs = append(errs, err)
259263
continue
@@ -267,16 +271,16 @@ func (me *monitoringExporter) recordToTimeSeriesPb(m otelmetricdata.Metrics) ([]
267271
return tss, errors.Join(errs...)
268272
}
269273

270-
func sumToTimeSeries[N int64 | float64](point otelmetricdata.DataPoint[N], metrics otelmetricdata.Metrics, mr *monitoredrespb.MonitoredResource) (*monitoringpb.TimeSeries, error) {
271-
interval, err := toNonemptyTimeIntervalpb(point.StartTime, point.Time)
274+
func sumToTimeSeries[N int64 | float64](point otelmetricdata.DataPoint[N], metrics otelmetricdata.Metrics, mr *monitoredrespb.MonitoredResource, kind googlemetricpb.MetricDescriptor_MetricKind) (*monitoringpb.TimeSeries, error) {
275+
interval, err := toTimeIntervalPb(point.StartTime, point.Time, kind)
272276
if err != nil {
273277
return nil, err
274278
}
275279
value, valueType := numberDataPointToValue[N](point)
276280
return &monitoringpb.TimeSeries{
277281
Resource: mr,
278282
Unit: string(metrics.Unit),
279-
MetricKind: googlemetricpb.MetricDescriptor_CUMULATIVE,
283+
MetricKind: kind,
280284
ValueType: valueType,
281285
Points: []*monitoringpb.Point{{
282286
Interval: interval,
@@ -286,7 +290,7 @@ func sumToTimeSeries[N int64 | float64](point otelmetricdata.DataPoint[N], metri
286290
}
287291

288292
func histogramToTimeSeries[N int64 | float64](point otelmetricdata.HistogramDataPoint[N], metrics otelmetricdata.Metrics, mr *monitoredrespb.MonitoredResource) (*monitoringpb.TimeSeries, error) {
289-
interval, err := toNonemptyTimeIntervalpb(point.StartTime, point.Time)
293+
interval, err := toTimeIntervalPb(point.StartTime, point.Time, googlemetricpb.MetricDescriptor_CUMULATIVE)
290294
if err != nil {
291295
return nil, err
292296
}
@@ -307,13 +311,20 @@ func histogramToTimeSeries[N int64 | float64](point otelmetricdata.HistogramData
307311
}, nil
308312
}
309313

310-
func toNonemptyTimeIntervalpb(start, end time.Time) (*monitoringpb.TimeInterval, error) {
311-
// The end time of a new interval must be at least a millisecond after the end time of the
312-
// previous interval, for all non-gauge types.
313-
// https://cloud.google.com/monitoring/api/ref_v3/rpc/google.monitoring.v3#timeinterval
314-
if end.Sub(start).Milliseconds() <= 1 {
315-
end = start.Add(time.Millisecond)
314+
func toTimeIntervalPb(start, end time.Time, kind googlemetricpb.MetricDescriptor_MetricKind) (*monitoringpb.TimeInterval, error) {
315+
if kind == googlemetricpb.MetricDescriptor_GAUGE {
316+
// Same as https://github.com/googleapis/java-bigtable/pull/2719
317+
start = end
318+
} else { // CUMULATIVE or other types
319+
// The end time of a new interval must be at least a millisecond after the end time of the
320+
// previous interval for CUMULATIVE types.
321+
// https://cloud.google.com/monitoring/api/ref_v3/rpc/google.monitoring.v3#timeinterval
322+
323+
if end.Sub(start) < time.Millisecond {
324+
end = start.Add(time.Millisecond)
325+
}
316326
}
327+
317328
startpb := timestamppb.New(start)
318329
endpb := timestamppb.New(end)
319330
err := errors.Join(

bigtable/metrics_monitoring_exporter_test.go

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,7 @@ func TestRecordToMpb(t *testing.T) {
430430
func TestTimeIntervalStaggering(t *testing.T) {
431431
var tm time.Time
432432

433-
interval, err := toNonemptyTimeIntervalpb(tm, tm)
433+
interval, err := toTimeIntervalPb(tm, tm, googlemetricpb.MetricDescriptor_CUMULATIVE)
434434
if err != nil {
435435
t.Fatalf("conversion to PB failed: %v", err)
436436
}
@@ -450,10 +450,29 @@ func TestTimeIntervalStaggering(t *testing.T) {
450450
}
451451
}
452452

453+
func TestTimeIntervalGauge(t *testing.T) {
454+
startTime := time.Now()
455+
endTime := startTime.Add(time.Second)
456+
457+
interval, err := toTimeIntervalPb(startTime, endTime, googlemetricpb.MetricDescriptor_GAUGE)
458+
if err != nil {
459+
t.Fatalf("conversion to PB failed: %v", err)
460+
}
461+
462+
start := interval.StartTime.AsTime()
463+
end := interval.EndTime.AsTime()
464+
465+
if !start.Equal(end) {
466+
t.Errorf("Expected StartTime == EndTime for GAUGE, got StartTime=%v, EndTime=%v", start, end)
467+
}
468+
if !start.Equal(endTime) {
469+
t.Errorf("Expected StartTime to be reset to EndTime for GAUGE, got StartTime=%v, expected %v", start, endTime)
470+
}
471+
}
453472
func TestTimeIntervalPassthru(t *testing.T) {
454473
var tm time.Time
455474

456-
interval, err := toNonemptyTimeIntervalpb(tm, tm.Add(time.Second))
475+
interval, err := toTimeIntervalPb(tm, tm.Add(time.Second), googlemetricpb.MetricDescriptor_CUMULATIVE)
457476
if err != nil {
458477
t.Fatalf("conversion to PB failed: %v", err)
459478
}

0 commit comments

Comments
 (0)