Skip to content

Commit a560c2f

Browse files
tomklinoTom Klinovskydbyron-sf
authored
fix(stackdriver): read INT64 metrics correctly (#933)
* fix(stackdriver): read INT64 metrics correctly * WIP: added template for stackdriverMetricServiceTest * WIP: adding tests to StackdriverMetricsService * WIP: adding tests to StackdriverMetricsService * added tests for stackdriverMetricService * adding tests to StackdriverMetricsService --------- Co-authored-by: Tom Klinovsky <tomklino@google.com> Co-authored-by: David Byron <82477955+dbyron-sf@users.noreply.github.com>
1 parent 3c71ecc commit a560c2f

File tree

3 files changed

+177
-4
lines changed

3 files changed

+177
-4
lines changed

kayenta-stackdriver/kayenta-stackdriver.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,6 @@ dependencies {
22
implementation project(":kayenta-core")
33
implementation project(":kayenta-google")
44
api "com.google.apis:google-api-services-monitoring"
5+
6+
testImplementation 'org.mockito:mockito-inline'
57
}

kayenta-stackdriver/src/main/java/com/netflix/kayenta/stackdriver/metrics/StackdriverMetricsService.java

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -399,10 +399,27 @@ public List<MetricSet> queryMetrics(
399399
: stackdriverCanaryScope.getEnd();
400400

401401
// TODO(duftler): What if there are no data points?
402-
List<Double> pointValues =
403-
points.stream()
404-
.map(point -> point.getValue().getDoubleValue())
405-
.collect(Collectors.toList());
402+
List<Double> pointValues;
403+
404+
if (timeSeries.getValueType().equals("INT64")) {
405+
pointValues =
406+
points.stream()
407+
.map(point -> (double) point.getValue().getInt64Value())
408+
.collect(Collectors.toList());
409+
} else if (timeSeries.getValueType().equals("DOUBLE")) {
410+
pointValues =
411+
points.stream()
412+
.map(point -> point.getValue().getDoubleValue())
413+
.collect(Collectors.toList());
414+
} else {
415+
log.warn(
416+
"expected timeSeries value type to be either DOUBLE or INT64. Got {}.",
417+
timeSeries.getValueType());
418+
pointValues =
419+
points.stream()
420+
.map(point -> point.getValue().getDoubleValue())
421+
.collect(Collectors.toList());
422+
}
406423

407424
MetricSet.MetricSetBuilder metricSetBuilder =
408425
MetricSet.builder()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
package com.netflix.kayenta.stackdriver.metrics;
2+
3+
import static org.assertj.core.api.Assertions.assertThat;
4+
import static org.mockito.ArgumentMatchers.anyString;
5+
import static org.mockito.Mockito.mock;
6+
import static org.mockito.Mockito.when;
7+
8+
import com.google.api.services.monitoring.v3.Monitoring;
9+
import com.google.api.services.monitoring.v3.model.ListMetricDescriptorsResponse;
10+
import com.google.api.services.monitoring.v3.model.ListTimeSeriesResponse;
11+
import com.google.api.services.monitoring.v3.model.MetricDescriptor;
12+
import com.google.api.services.monitoring.v3.model.Point;
13+
import com.google.api.services.monitoring.v3.model.TimeInterval;
14+
import com.google.api.services.monitoring.v3.model.TimeSeries;
15+
import com.google.api.services.monitoring.v3.model.TypedValue;
16+
import com.netflix.kayenta.canary.CanaryConfig;
17+
import com.netflix.kayenta.canary.CanaryMetricConfig;
18+
import com.netflix.kayenta.canary.providers.metrics.StackdriverCanaryMetricSetQueryConfig;
19+
import com.netflix.kayenta.google.security.GoogleNamedAccountCredentials;
20+
import com.netflix.kayenta.metrics.MetricSet;
21+
import com.netflix.kayenta.security.AccountCredentials;
22+
import com.netflix.kayenta.security.AccountCredentialsRepository;
23+
import com.netflix.kayenta.stackdriver.canary.StackdriverCanaryScope;
24+
import com.netflix.spectator.api.DefaultRegistry;
25+
import java.io.IOException;
26+
import java.time.Instant;
27+
import java.util.ArrayList;
28+
import java.util.HashSet;
29+
import java.util.List;
30+
import java.util.Map;
31+
import java.util.Set;
32+
import org.junit.jupiter.api.BeforeEach;
33+
import org.junit.jupiter.api.Test;
34+
import org.mockito.Mockito;
35+
36+
public class StackdriverMetricsServiceTest {
37+
38+
private static final String ACCOUNT = "test-account";
39+
40+
private AccountCredentialsRepository accountCredentialsRepoMock;
41+
42+
private StackdriverMetricsService stackdriverMetricsService;
43+
44+
@BeforeEach
45+
void setup() {
46+
StackdriverMetricsService.StackdriverMetricsServiceBuilder stackdriverMetricsServiceBuilder =
47+
StackdriverMetricsService.builder();
48+
accountCredentialsRepoMock = mock(AccountCredentialsRepository.class);
49+
stackdriverMetricsServiceBuilder
50+
.accountCredentialsRepository(accountCredentialsRepoMock)
51+
.registry(new DefaultRegistry());
52+
stackdriverMetricsService = stackdriverMetricsServiceBuilder.build();
53+
}
54+
55+
@Test
56+
void readsInt64Metrics() throws IOException {
57+
GoogleNamedAccountCredentials stackdriverCredentialsMock =
58+
mock(GoogleNamedAccountCredentials.class);
59+
when(accountCredentialsRepoMock.getRequiredOne(ACCOUNT)).thenReturn(stackdriverCredentialsMock);
60+
61+
Monitoring monitoringMock = mock(Monitoring.class, Mockito.RETURNS_DEEP_STUBS);
62+
when(stackdriverCredentialsMock.getMonitoring()).thenReturn(monitoringMock);
63+
64+
Monitoring.Projects.TimeSeries.List timeSeriesListMock =
65+
mock(Monitoring.Projects.TimeSeries.List.class);
66+
67+
when(monitoringMock
68+
.projects()
69+
.timeSeries()
70+
.list(anyString())
71+
.setAggregationAlignmentPeriod(anyString())
72+
.setAggregationCrossSeriesReducer(anyString())
73+
.setAggregationPerSeriesAligner(anyString())
74+
.setFilter(anyString())
75+
.setIntervalStartTime(anyString())
76+
.setIntervalEndTime(anyString()))
77+
.thenReturn(timeSeriesListMock);
78+
79+
ListTimeSeriesResponse responseMock = mock(ListTimeSeriesResponse.class);
80+
when(timeSeriesListMock.execute()).thenReturn(responseMock);
81+
82+
List<TimeSeries> timeSeriesListWithInt64Points = new ArrayList<TimeSeries>();
83+
84+
// Create a time series with INT64 points
85+
List<Point> int64Points = new ArrayList<Point>();
86+
int64Points.add(
87+
new Point()
88+
.setValue(new TypedValue().setInt64Value((Long) 64l))
89+
.setInterval(
90+
new TimeInterval()
91+
.setStartTime("1970-01-01T00:00:00.00Z")
92+
.setEndTime("1970-01-01T00:00:01.00Z")));
93+
TimeSeries timeSeriesWithInt64Points =
94+
new TimeSeries().setValueType("INT64").setPoints(int64Points);
95+
timeSeriesListWithInt64Points.add(timeSeriesWithInt64Points);
96+
97+
when(responseMock.getTimeSeries()).thenReturn(timeSeriesListWithInt64Points);
98+
99+
CanaryConfig canaryConfig = new CanaryConfig();
100+
CanaryMetricConfig canaryMetricConfig =
101+
CanaryMetricConfig.builder()
102+
.name("metricConfig")
103+
.query(
104+
StackdriverCanaryMetricSetQueryConfig.builder()
105+
.resourceType("global")
106+
.metricType("instance")
107+
.build())
108+
.build();
109+
110+
StackdriverCanaryScope canaryScope = new StackdriverCanaryScope();
111+
canaryScope.setStart(Instant.EPOCH).setEnd(Instant.EPOCH.plusSeconds(1)).setStep(1l);
112+
canaryScope.setProject("my-project");
113+
List<MetricSet> queriedMetrics =
114+
stackdriverMetricsService.queryMetrics(
115+
ACCOUNT, canaryConfig, canaryMetricConfig, canaryScope);
116+
117+
assertThat(queriedMetrics.get(0).getValues()).contains(64d);
118+
}
119+
120+
@Test
121+
void returnsSingleMetricDescriptorInCache() throws IOException {
122+
GoogleNamedAccountCredentials googleAccountCredentialsMock =
123+
mock(GoogleNamedAccountCredentials.class, Mockito.RETURNS_DEEP_STUBS);
124+
125+
Set<AccountCredentials> accountCredentialsSetMock = new HashSet<>();
126+
accountCredentialsSetMock.add(googleAccountCredentialsMock);
127+
128+
when(accountCredentialsRepoMock.getAllOf(AccountCredentials.Type.METRICS_STORE))
129+
.thenReturn(accountCredentialsSetMock);
130+
131+
ListMetricDescriptorsResponse listMetricDescriptorsResponseMock =
132+
mock(ListMetricDescriptorsResponse.class);
133+
when(googleAccountCredentialsMock
134+
.getMonitoring()
135+
.projects()
136+
.metricDescriptors()
137+
.list(anyString())
138+
.execute())
139+
.thenReturn(listMetricDescriptorsResponseMock);
140+
141+
List<MetricDescriptor> metricDesciprtorMockList = new ArrayList<MetricDescriptor>();
142+
143+
MetricDescriptor exampleMetricDescriptor = new MetricDescriptor();
144+
metricDesciprtorMockList.add(exampleMetricDescriptor);
145+
when(listMetricDescriptorsResponseMock.getMetricDescriptors())
146+
.thenReturn(metricDesciprtorMockList);
147+
148+
stackdriverMetricsService.updateMetricDescriptorsCache();
149+
150+
List<Map> metadata = stackdriverMetricsService.getMetadata(ACCOUNT, "");
151+
152+
assertThat(metadata).containsOnly(exampleMetricDescriptor);
153+
}
154+
}

0 commit comments

Comments
 (0)