1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package android.cts.statsd.metric;
17 
18 import static com.google.common.truth.Truth.assertThat;
19 
20 import android.cts.statsd.atom.DeviceAtomTestCase;
21 
22 import com.android.internal.os.StatsdConfigProto;
23 import com.android.internal.os.StatsdConfigProto.ActivationType;
24 import com.android.internal.os.StatsdConfigProto.AtomMatcher;
25 import com.android.internal.os.StatsdConfigProto.EventActivation;
26 import com.android.internal.os.StatsdConfigProto.FieldFilter;
27 import com.android.internal.os.StatsdConfigProto.FieldMatcher;
28 import com.android.internal.os.StatsdConfigProto.FieldValueMatcher;
29 import com.android.internal.os.StatsdConfigProto.GaugeMetric;
30 import com.android.internal.os.StatsdConfigProto.MetricActivation;
31 import com.android.internal.os.StatsdConfigProto.Predicate;
32 import com.android.internal.os.StatsdConfigProto.SimpleAtomMatcher;
33 import com.android.internal.os.StatsdConfigProto.SimplePredicate;
34 import com.android.internal.os.StatsdConfigProto.StatsdConfig;
35 import com.android.internal.os.StatsdConfigProto.TimeUnit;
36 import com.android.os.AtomsProto.AppBreadcrumbReported;
37 import com.android.os.AtomsProto.Atom;
38 import com.android.os.StatsLog.GaugeBucketInfo;
39 import com.android.os.StatsLog.GaugeMetricData;
40 import com.android.os.StatsLog.StatsLogReport;
41 import com.android.tradefed.log.LogUtil;
42 
43 public class GaugeMetricsTests extends DeviceAtomTestCase {
44 
45   private static final int APP_BREADCRUMB_REPORTED_A_MATCH_START_ID = 0;
46   private static final int APP_BREADCRUMB_REPORTED_A_MATCH_STOP_ID = 1;
47   private static final int APP_BREADCRUMB_REPORTED_B_MATCH_START_ID = 2;
48 
testGaugeMetric()49   public void testGaugeMetric() throws Exception {
50       // Add AtomMatcher's.
51       AtomMatcher startAtomMatcher =
52           MetricsUtils.startAtomMatcher(APP_BREADCRUMB_REPORTED_A_MATCH_START_ID);
53       AtomMatcher stopAtomMatcher =
54           MetricsUtils.stopAtomMatcher(APP_BREADCRUMB_REPORTED_A_MATCH_STOP_ID);
55       AtomMatcher atomMatcher =
56           MetricsUtils.simpleAtomMatcher(APP_BREADCRUMB_REPORTED_B_MATCH_START_ID);
57 
58       StatsdConfigProto.StatsdConfig.Builder builder = createConfigBuilder();
59       builder.addAtomMatcher(startAtomMatcher);
60       builder.addAtomMatcher(stopAtomMatcher);
61       builder.addAtomMatcher(atomMatcher);
62 
63       // Add Predicate's.
64       SimplePredicate simplePredicate = SimplePredicate.newBuilder()
65                                             .setStart(APP_BREADCRUMB_REPORTED_A_MATCH_START_ID)
66                                             .setStop(APP_BREADCRUMB_REPORTED_A_MATCH_STOP_ID)
67                                             .build();
68       Predicate predicate = Predicate.newBuilder()
69                                 .setId(MetricsUtils.StringToId("Predicate"))
70                                 .setSimplePredicate(simplePredicate)
71                                 .build();
72       builder.addPredicate(predicate);
73 
74       // Add GaugeMetric.
75       FieldMatcher fieldMatcher =
76           FieldMatcher.newBuilder().setField(APP_BREADCRUMB_REPORTED_B_MATCH_START_ID).build();
77       builder.addGaugeMetric(
78           StatsdConfigProto.GaugeMetric.newBuilder()
79               .setId(MetricsUtils.GAUGE_METRIC_ID)
80               .setWhat(APP_BREADCRUMB_REPORTED_B_MATCH_START_ID)
81               .setCondition(predicate.getId())
82               .setGaugeFieldsFilter(
83                   FieldFilter.newBuilder().setIncludeAll(false).setFields(fieldMatcher).build())
84               .setDimensionsInWhat(
85                   FieldMatcher.newBuilder()
86                       .setField(APP_BREADCRUMB_REPORTED_B_MATCH_START_ID)
87                       .addChild(FieldMatcher.newBuilder()
88                                     .setField(AppBreadcrumbReported.STATE_FIELD_NUMBER)
89                                     .build())
90                       .build())
91               .setBucket(StatsdConfigProto.TimeUnit.CTS)
92               .build());
93 
94       // Upload config.
95       uploadConfig(builder);
96 
97       // Create AppBreadcrumbReported Start/Stop events.
98       doAppBreadcrumbReportedStart(0);
99       Thread.sleep(10);
100       doAppBreadcrumbReportedStart(1);
101       Thread.sleep(10);
102       doAppBreadcrumbReportedStart(2);
103       Thread.sleep(2000);
104       doAppBreadcrumbReportedStop(2);
105       Thread.sleep(10);
106       doAppBreadcrumbReportedStop(0);
107       Thread.sleep(10);
108       doAppBreadcrumbReportedStop(1);
109       doAppBreadcrumbReportedStart(2);
110       Thread.sleep(10);
111       doAppBreadcrumbReportedStart(1);
112       Thread.sleep(2000);
113       doAppBreadcrumbReportedStop(2);
114       Thread.sleep(10);
115       doAppBreadcrumbReportedStop(1);
116 
117       // Wait for the metrics to propagate to statsd.
118       Thread.sleep(2000);
119 
120       StatsLogReport metricReport = getStatsLogReport();
121       LogUtil.CLog.d("Got the following gauge metric data: " + metricReport.toString());
122       assertThat(metricReport.getMetricId()).isEqualTo(MetricsUtils.GAUGE_METRIC_ID);
123       assertThat(metricReport.hasGaugeMetrics()).isTrue();
124       StatsLogReport.GaugeMetricDataWrapper gaugeData = metricReport.getGaugeMetrics();
125       gaugeData = backfillGaugeMetricData(gaugeData);
126       assertThat(gaugeData.getDataCount()).isEqualTo(1);
127 
128       int bucketCount = gaugeData.getData(0).getBucketInfoCount();
129       GaugeMetricData data = gaugeData.getData(0);
130       assertThat(bucketCount).isGreaterThan(2);
131       MetricsUtils.assertBucketTimePresent(data.getBucketInfo(0));
132       assertThat(data.getBucketInfo(0).getAtomCount()).isEqualTo(1);
133       assertThat(data.getBucketInfo(0).getAtom(0).getAppBreadcrumbReported().getLabel())
134               .isEqualTo(0);
135       assertThat(data.getBucketInfo(0).getAtom(0).getAppBreadcrumbReported().getState())
136               .isEqualTo(AppBreadcrumbReported.State.START);
137 
138       MetricsUtils.assertBucketTimePresent(data.getBucketInfo(1));
139       assertThat(data.getBucketInfo(1).getAtomCount()).isEqualTo(1);
140 
141       MetricsUtils.assertBucketTimePresent(data.getBucketInfo(bucketCount-1));
142       assertThat(data.getBucketInfo(bucketCount-1).getAtomCount()).isEqualTo(1);
143       assertThat(data.getBucketInfo(bucketCount-1).getAtom(0).getAppBreadcrumbReported().getLabel())
144               .isEqualTo(2);
145       assertThat(data.getBucketInfo(bucketCount-1).getAtom(0).getAppBreadcrumbReported().getState())
146               .isEqualTo(AppBreadcrumbReported.State.STOP);
147   }
148 
testPulledGaugeMetricWithActivation()149   public void testPulledGaugeMetricWithActivation() throws Exception {
150       // Add AtomMatcher's.
151       int activationAtomMatcherId = 1;
152       int activationAtomMatcherLabel = 1;
153 
154       int systemUptimeMatcherId = 2;
155       AtomMatcher activationAtomMatcher =
156               MetricsUtils.appBreadcrumbMatcherWithLabel(
157                       activationAtomMatcherId, activationAtomMatcherLabel);
158       AtomMatcher systemUptimeMatcher =
159               AtomMatcher.newBuilder()
160                       .setId(systemUptimeMatcherId)
161                       .setSimpleAtomMatcher(
162                               SimpleAtomMatcher.newBuilder().setAtomId(Atom.SYSTEM_UPTIME_FIELD_NUMBER))
163                       .build();
164 
165       StatsdConfigProto.StatsdConfig.Builder builder = createConfigBuilder();
166       builder.addAtomMatcher(activationAtomMatcher);
167       builder.addAtomMatcher(systemUptimeMatcher);
168 
169       // Add GaugeMetric.
170       builder.addGaugeMetric(
171               StatsdConfigProto.GaugeMetric.newBuilder()
172                       .setId(MetricsUtils.GAUGE_METRIC_ID)
173                       .setWhat(systemUptimeMatcherId)
174                       .setGaugeFieldsFilter(
175                               FieldFilter.newBuilder().setIncludeAll(true).build())
176                       .setBucket(StatsdConfigProto.TimeUnit.CTS)
177                       .build());
178 
179       // Add activation.
180       builder.addMetricActivation(MetricActivation.newBuilder()
181               .setMetricId(MetricsUtils.GAUGE_METRIC_ID)
182               .setActivationType(ActivationType.ACTIVATE_IMMEDIATELY)
183               .addEventActivation(EventActivation.newBuilder()
184                     .setAtomMatcherId(activationAtomMatcherId)
185                     .setTtlSeconds(5)));
186 
187       // Upload config.
188       uploadConfig(builder);
189 
190       // Plenty of time to pull, but we should not keep the data since we are not active.
191       Thread.sleep(20_000);
192 
193       StatsLogReport metricReport = getStatsLogReport();
194       LogUtil.CLog.d("Got the following gauge metric data: " + metricReport.toString());
195       assertThat(metricReport.getMetricId()).isEqualTo(MetricsUtils.GAUGE_METRIC_ID);
196       assertThat(metricReport.hasGaugeMetrics()).isFalse();
197   }
198 
testPulledGaugeMetricWithConditionAndActivation()199     public void testPulledGaugeMetricWithConditionAndActivation() throws Exception {
200         final int conditionLabel = 2;
201         final int activationMatcherId = 5;
202         final int activationMatcherLabel = 5;
203         final int whatMatcherId = 8;
204         final int ttlSec = 5;
205 
206         // Add AtomMatchers.
207         AtomMatcher conditionStartAtomMatcher = MetricsUtils.startAtomMatcherWithLabel(
208                 APP_BREADCRUMB_REPORTED_A_MATCH_START_ID, conditionLabel);
209         AtomMatcher conditionStopAtomMatcher = MetricsUtils.stopAtomMatcherWithLabel(
210                 APP_BREADCRUMB_REPORTED_A_MATCH_STOP_ID, conditionLabel);
211         AtomMatcher activationMatcher =
212                 MetricsUtils.startAtomMatcherWithLabel(
213                         activationMatcherId, activationMatcherLabel);
214         AtomMatcher whatMatcher =
215                 MetricsUtils.unspecifiedAtomMatcher(whatMatcherId);
216 
217         StatsdConfig.Builder builder = createConfigBuilder()
218                 .addAtomMatcher(conditionStartAtomMatcher)
219                 .addAtomMatcher(conditionStopAtomMatcher)
220                 .addAtomMatcher(whatMatcher)
221                 .addAtomMatcher(activationMatcher);
222 
223         // Add Predicates.
224         SimplePredicate simplePredicate = SimplePredicate.newBuilder()
225                 .setStart(APP_BREADCRUMB_REPORTED_A_MATCH_START_ID)
226                 .setStop(APP_BREADCRUMB_REPORTED_A_MATCH_STOP_ID)
227                 .build();
228         Predicate predicate = Predicate.newBuilder()
229                                   .setId(MetricsUtils.StringToId("Predicate"))
230                                   .setSimplePredicate(simplePredicate)
231                                   .build();
232         builder.addPredicate(predicate);
233 
234         // Add GaugeMetric.
235         builder
236                 .addGaugeMetric(GaugeMetric.newBuilder()
237                         .setId(MetricsUtils.GAUGE_METRIC_ID)
238                         .setWhat(whatMatcher.getId())
239                         .setBucket(TimeUnit.CTS)
240                         .setCondition(predicate.getId())
241                         .setGaugeFieldsFilter(
242                                 FieldFilter.newBuilder().setIncludeAll(false).setFields(
243                                         FieldMatcher.newBuilder()
244                                                 .setField(APP_BREADCRUMB_REPORTED_B_MATCH_START_ID)
245                                 )
246                         )
247                         .setDimensionsInWhat(FieldMatcher.newBuilder().setField(whatMatcherId))
248                 )
249                 .addMetricActivation(MetricActivation.newBuilder()
250                         .setMetricId(MetricsUtils.GAUGE_METRIC_ID)
251                         .addEventActivation(EventActivation.newBuilder()
252                                 .setAtomMatcherId(activationMatcherId)
253                                 .setActivationType(ActivationType.ACTIVATE_IMMEDIATELY)
254                                 .setTtlSeconds(ttlSec)
255                         )
256                 );
257 
258         uploadConfig(builder);
259 
260         // Activate the metric.
261         doAppBreadcrumbReportedStart(activationMatcherLabel);
262         Thread.sleep(10);
263 
264         // Set the condition to true.
265         doAppBreadcrumbReportedStart(conditionLabel);
266         Thread.sleep(10);
267 
268         // This value is collected.
269         doAppBreadcrumbReported(10);
270         Thread.sleep(10);
271 
272         // Ignored; value already collected.
273         doAppBreadcrumbReported(20);
274         Thread.sleep(10);
275 
276         // Set the condition to false.
277         doAppBreadcrumbReportedStop(conditionLabel);
278         Thread.sleep(10);
279 
280         // Value not updated because condition is false.
281         doAppBreadcrumbReported(30);
282         Thread.sleep(10);
283 
284         // Let the metric deactivate.
285         Thread.sleep(ttlSec * 1000);
286 
287         // Value not collected.
288         doAppBreadcrumbReported(40);
289         Thread.sleep(10);
290 
291         // Condition to true again.
292         doAppBreadcrumbReportedStart(conditionLabel);
293         Thread.sleep(10);
294 
295         // Value not collected.
296         doAppBreadcrumbReported(50);
297         Thread.sleep(10);
298 
299         // Activate the metric.
300         doAppBreadcrumbReportedStart(activationMatcherLabel);
301         Thread.sleep(10);
302 
303         // Value collected.
304         doAppBreadcrumbReported(60);
305         Thread.sleep(10);
306 
307         // Let the metric deactivate.
308         Thread.sleep(ttlSec * 1000);
309 
310         // Value not collected.
311         doAppBreadcrumbReported(70);
312         Thread.sleep(10);
313 
314         // Wait for the metrics to propagate to statsd.
315         Thread.sleep(2000);
316 
317         StatsLogReport metricReport = getStatsLogReport();
318         LogUtil.CLog.d("Received the following data: " + metricReport.toString());
319         assertThat(metricReport.getMetricId()).isEqualTo(MetricsUtils.GAUGE_METRIC_ID);
320         assertThat(metricReport.hasGaugeMetrics()).isTrue();
321         assertThat(metricReport.getIsActive()).isFalse();
322 
323         StatsLogReport.GaugeMetricDataWrapper gaugeData = metricReport.getGaugeMetrics();
324         gaugeData = backfillGaugeMetricData(gaugeData);
325         assertThat(gaugeData.getDataCount()).isEqualTo(1);
326         assertThat(gaugeData.getData(0).getBucketInfoCount()).isEqualTo(2);
327 
328         GaugeBucketInfo bucketInfo = gaugeData.getData(0).getBucketInfo(0);
329         MetricsUtils.assertBucketTimePresent(bucketInfo);
330         assertThat(bucketInfo.getAtomCount()).isEqualTo(1);
331         assertThat(bucketInfo.getAtom(0).getAppBreadcrumbReported().getLabel()).isEqualTo(10);
332 
333         bucketInfo = gaugeData.getData(0).getBucketInfo(1);
334         MetricsUtils.assertBucketTimePresent(bucketInfo);
335         assertThat(bucketInfo.getAtomCount()).isEqualTo(1);
336         assertThat(bucketInfo.getAtom(0).getAppBreadcrumbReported().getLabel()).isEqualTo(60);
337     }
338 }
339