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.statsdatom.lib.AtomTestUtils; 21 import android.cts.statsdatom.lib.ConfigUtils; 22 import android.cts.statsdatom.lib.ReportUtils; 23 24 import com.android.internal.os.StatsdConfigProto.ActivationType; 25 import com.android.internal.os.StatsdConfigProto.AtomMatcher; 26 import com.android.internal.os.StatsdConfigProto.EventActivation; 27 import com.android.internal.os.StatsdConfigProto.FieldMatcher; 28 import com.android.internal.os.StatsdConfigProto.MetricActivation; 29 import com.android.internal.os.StatsdConfigProto.Predicate; 30 import com.android.internal.os.StatsdConfigProto.SimpleAtomMatcher; 31 import com.android.internal.os.StatsdConfigProto.SimplePredicate; 32 import com.android.internal.os.StatsdConfigProto.StatsdConfig; 33 import com.android.internal.os.StatsdConfigProto.TimeUnit; 34 import com.android.internal.os.StatsdConfigProto.ValueMetric; 35 36 import com.android.os.AtomsProto.AppBreadcrumbReported; 37 import com.android.os.AtomsProto.Atom; 38 import com.android.os.AtomsProto.SystemElapsedRealtime; 39 import com.android.os.StatsLog.StatsLogReport; 40 import com.android.os.StatsLog.ValueBucketInfo; 41 import com.android.os.StatsLog.ValueMetricData; 42 43 import com.android.tradefed.log.LogUtil; 44 import com.android.tradefed.testtype.DeviceTestCase; 45 import com.android.tradefed.util.RunUtil; 46 47 import com.google.protobuf.ExtensionRegistry; 48 49 public class ValueMetricsTests extends DeviceTestCase { 50 private static final int APP_BREADCRUMB_REPORTED_A_MATCH_START_ID = 0; 51 private static final int APP_BREADCRUMB_REPORTED_A_MATCH_STOP_ID = 1; 52 private static final int APP_BREADCRUMB_REPORTED_B_MATCH_START_ID = 2; 53 54 @Override setUp()55 protected void setUp() throws Exception { 56 super.setUp(); 57 ConfigUtils.removeConfig(getDevice()); 58 ReportUtils.clearReports(getDevice()); 59 RunUtil.getDefault().sleep(1000); 60 } 61 62 @Override tearDown()63 protected void tearDown() throws Exception { 64 ConfigUtils.removeConfig(getDevice()); 65 ReportUtils.clearReports(getDevice()); 66 super.tearDown(); 67 } 68 69 testValueMetric()70 public void testValueMetric() throws Exception { 71 // Add AtomMatcher's. 72 AtomMatcher startAtomMatcher = 73 MetricsUtils.startAtomMatcher(APP_BREADCRUMB_REPORTED_A_MATCH_START_ID); 74 AtomMatcher stopAtomMatcher = 75 MetricsUtils.stopAtomMatcher(APP_BREADCRUMB_REPORTED_A_MATCH_STOP_ID); 76 AtomMatcher atomMatcher = 77 MetricsUtils.simpleAtomMatcher(APP_BREADCRUMB_REPORTED_B_MATCH_START_ID); 78 79 StatsdConfig.Builder builder = ConfigUtils.createConfigBuilder( 80 MetricsUtils.DEVICE_SIDE_TEST_PACKAGE); 81 builder.addAtomMatcher(startAtomMatcher); 82 builder.addAtomMatcher(stopAtomMatcher); 83 builder.addAtomMatcher(atomMatcher); 84 85 // Add ValueMetric. 86 builder.addValueMetric(ValueMetric.newBuilder() 87 .setId(MetricsUtils.VALUE_METRIC_ID) 88 .setWhat(APP_BREADCRUMB_REPORTED_B_MATCH_START_ID) 89 .setBucket(TimeUnit.CTS) 90 .setValueField(FieldMatcher.newBuilder() 91 .setField(Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER) 92 .addChild(FieldMatcher.newBuilder().setField( 93 AppBreadcrumbReported.LABEL_FIELD_NUMBER))) 94 .setDimensionsInWhat(FieldMatcher.newBuilder() 95 .setField(APP_BREADCRUMB_REPORTED_B_MATCH_START_ID) 96 .build()) 97 .build()); 98 99 // Upload config. 100 ConfigUtils.uploadConfig(getDevice(), builder); 101 102 // Create AppBreadcrumbReported Start/Stop events. 103 AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(), 104 AppBreadcrumbReported.State.START.getNumber(), 1); 105 RunUtil.getDefault().sleep(1000); 106 AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(), 107 AppBreadcrumbReported.State.STOP.getNumber(), 1); 108 AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(), 109 AppBreadcrumbReported.State.START.getNumber(), 3); 110 AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(), 111 AppBreadcrumbReported.State.STOP.getNumber(), 3); 112 113 // Wait for the metrics to propagate to statsd. 114 RunUtil.getDefault().sleep(1000); 115 116 StatsLogReport metricReport = ReportUtils.getStatsLogReport(getDevice(), 117 ExtensionRegistry.getEmptyRegistry()); 118 LogUtil.CLog.d("Got the following value metric data: " + metricReport.toString()); 119 assertThat(metricReport.getMetricId()).isEqualTo(MetricsUtils.VALUE_METRIC_ID); 120 assertThat(metricReport.hasValueMetrics()).isTrue(); 121 StatsLogReport.ValueMetricDataWrapper valueData = metricReport.getValueMetrics(); 122 assertThat(valueData.getDataCount()).isEqualTo(1); 123 124 int bucketCount = valueData.getData(0).getBucketInfoCount(); 125 assertThat(bucketCount).isGreaterThan(1); 126 ValueMetricData data = valueData.getData(0); 127 int totalValue = 0; 128 for (ValueBucketInfo bucketInfo : data.getBucketInfoList()) { 129 MetricsUtils.assertBucketTimePresent(bucketInfo); 130 assertThat(bucketInfo.getValuesCount()).isEqualTo(1); 131 assertThat(bucketInfo.getValues(0).getIndex()).isEqualTo(0); 132 totalValue += (int) bucketInfo.getValues(0).getValueLong(); 133 } 134 assertThat(totalValue).isEqualTo(8); 135 } 136 137 // Test value metric with pulled atoms and across multiple buckets testPullerAcrossBuckets()138 public void testPullerAcrossBuckets() throws Exception { 139 // Add AtomMatcher's. 140 final String predicateTrueName = "APP_BREADCRUMB_REPORTED_START"; 141 final String predicateFalseName = "APP_BREADCRUMB_REPORTED_STOP"; 142 final String predicateName = "APP_BREADCRUMB_REPORTED_IS_STOP"; 143 144 AtomMatcher startAtomMatcher = 145 MetricsUtils.startAtomMatcher(predicateTrueName.hashCode()); 146 AtomMatcher stopAtomMatcher = 147 MetricsUtils.stopAtomMatcher(predicateFalseName.hashCode()); 148 149 StatsdConfig.Builder builder = ConfigUtils.createConfigBuilder( 150 MetricsUtils.DEVICE_SIDE_TEST_PACKAGE); 151 builder.addAtomMatcher(startAtomMatcher); 152 builder.addAtomMatcher(stopAtomMatcher); 153 builder.addPredicate(Predicate.newBuilder() 154 .setId(predicateName.hashCode()) 155 .setSimplePredicate(SimplePredicate.newBuilder() 156 .setStart(predicateTrueName.hashCode()) 157 .setStop(predicateFalseName.hashCode()) 158 .setCountNesting(false) 159 ) 160 ); 161 162 final String atomName = "SYSTEM_ELAPSED_REALTIME"; 163 SimpleAtomMatcher.Builder sam = SimpleAtomMatcher.newBuilder().setAtomId( 164 Atom.SYSTEM_ELAPSED_REALTIME_FIELD_NUMBER); 165 builder.addAtomMatcher(AtomMatcher.newBuilder() 166 .setId(atomName.hashCode()) 167 .setSimpleAtomMatcher(sam)); 168 169 // Add ValueMetric. 170 builder.addValueMetric(ValueMetric.newBuilder() 171 .setId(MetricsUtils.VALUE_METRIC_ID) 172 .setWhat(atomName.hashCode()) 173 .setBucket(TimeUnit.ONE_MINUTE) 174 .setValueField(FieldMatcher.newBuilder() 175 .setField(Atom.SYSTEM_ELAPSED_REALTIME_FIELD_NUMBER) 176 .addChild(FieldMatcher.newBuilder().setField( 177 SystemElapsedRealtime.TIME_MILLIS_FIELD_NUMBER))) 178 .setCondition(predicateName.hashCode()) 179 .build()); 180 181 // Upload config. 182 ConfigUtils.uploadConfig(getDevice(), builder); 183 184 // Create AppBreadcrumbReported Start/Stop events. 185 AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(), 186 AppBreadcrumbReported.State.START.getNumber(), 1); 187 // Wait for 2 min and 1 sec to capture at least 2 buckets 188 RunUtil.getDefault().sleep(2 * 60_000 + 10_000); 189 AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(), 190 AppBreadcrumbReported.State.STOP.getNumber(), 1); 191 192 // Wait for the metrics to propagate to statsd. 193 RunUtil.getDefault().sleep(1_000); 194 195 StatsLogReport metricReport = ReportUtils.getStatsLogReport(getDevice(), 196 ExtensionRegistry.getEmptyRegistry()); 197 LogUtil.CLog.d("Got the following value metric data: " + metricReport.toString()); 198 assertThat(metricReport.getMetricId()).isEqualTo(MetricsUtils.VALUE_METRIC_ID); 199 assertThat(metricReport.hasValueMetrics()).isTrue(); 200 StatsLogReport.ValueMetricDataWrapper valueData = metricReport.getValueMetrics(); 201 assertThat(valueData.getDataCount()).isEqualTo(1); 202 203 int bucketCount = valueData.getData(0).getBucketInfoCount(); 204 // should have at least 2 buckets 205 assertThat(bucketCount).isAtLeast(2); 206 ValueMetricData data = valueData.getData(0); 207 int totalValue = 0; 208 for (ValueBucketInfo bucketInfo : data.getBucketInfoList()) { 209 MetricsUtils.assertBucketTimePresent(bucketInfo); 210 assertThat(bucketInfo.getValuesCount()).isEqualTo(1); 211 assertThat(bucketInfo.getValues(0).getIndex()).isEqualTo(0); 212 totalValue += (int) bucketInfo.getValues(0).getValueLong(); 213 } 214 // At most we lose one full min bucket 215 assertThat(totalValue).isGreaterThan(130_000 - 60_000); 216 } 217 218 // Test value metric with pulled atoms and across multiple buckets testMultipleEventsPerBucket()219 public void testMultipleEventsPerBucket() throws Exception { 220 // Add AtomMatcher's. 221 final String predicateTrueName = "APP_BREADCRUMB_REPORTED_START"; 222 final String predicateFalseName = "APP_BREADCRUMB_REPORTED_STOP"; 223 final String predicateName = "APP_BREADCRUMB_REPORTED_IS_STOP"; 224 225 AtomMatcher startAtomMatcher = 226 MetricsUtils.startAtomMatcher(predicateTrueName.hashCode()); 227 AtomMatcher stopAtomMatcher = 228 MetricsUtils.stopAtomMatcher(predicateFalseName.hashCode()); 229 230 StatsdConfig.Builder builder = ConfigUtils.createConfigBuilder( 231 MetricsUtils.DEVICE_SIDE_TEST_PACKAGE); 232 builder.addAtomMatcher(startAtomMatcher); 233 builder.addAtomMatcher(stopAtomMatcher); 234 builder.addPredicate(Predicate.newBuilder() 235 .setId(predicateName.hashCode()) 236 .setSimplePredicate(SimplePredicate.newBuilder() 237 .setStart(predicateTrueName.hashCode()) 238 .setStop(predicateFalseName.hashCode()) 239 .setCountNesting(false) 240 ) 241 ); 242 243 final String atomName = "SYSTEM_ELAPSED_REALTIME"; 244 SimpleAtomMatcher.Builder sam = SimpleAtomMatcher.newBuilder().setAtomId( 245 Atom.SYSTEM_ELAPSED_REALTIME_FIELD_NUMBER); 246 builder.addAtomMatcher(AtomMatcher.newBuilder() 247 .setId(atomName.hashCode()) 248 .setSimpleAtomMatcher(sam)); 249 250 // Add ValueMetric. 251 builder.addValueMetric(ValueMetric.newBuilder() 252 .setId(MetricsUtils.VALUE_METRIC_ID) 253 .setWhat(atomName.hashCode()) 254 .setBucket(TimeUnit.ONE_MINUTE) 255 .setValueField(FieldMatcher.newBuilder() 256 .setField(Atom.SYSTEM_ELAPSED_REALTIME_FIELD_NUMBER) 257 .addChild(FieldMatcher.newBuilder().setField( 258 SystemElapsedRealtime.TIME_MILLIS_FIELD_NUMBER))) 259 .setCondition(predicateName.hashCode()) 260 .build()); 261 262 // Upload config. 263 ConfigUtils.uploadConfig(getDevice(), builder); 264 265 final int NUM_EVENTS = 10; 266 final long GAP_INTERVAL = 10_000; 267 // Create AppBreadcrumbReported Start/Stop events. 268 for (int i = 0; i < NUM_EVENTS; i++) { 269 AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(), 270 AppBreadcrumbReported.State.START.getNumber(), 1); 271 RunUtil.getDefault().sleep(GAP_INTERVAL); 272 AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(), 273 AppBreadcrumbReported.State.STOP.getNumber(), 1); 274 RunUtil.getDefault().sleep(GAP_INTERVAL); 275 } 276 277 // Wait for the metrics to propagate to statsd. 278 RunUtil.getDefault().sleep(1_000); 279 280 StatsLogReport metricReport = ReportUtils.getStatsLogReport(getDevice(), 281 ExtensionRegistry.getEmptyRegistry()); 282 LogUtil.CLog.d("Got the following value metric data: " + metricReport.toString()); 283 assertThat(metricReport.getMetricId()).isEqualTo(MetricsUtils.VALUE_METRIC_ID); 284 assertThat(metricReport.hasValueMetrics()).isTrue(); 285 StatsLogReport.ValueMetricDataWrapper valueData = metricReport.getValueMetrics(); 286 assertThat(valueData.getDataCount()).isEqualTo(1); 287 288 int bucketCount = valueData.getData(0).getBucketInfoCount(); 289 // should have at least 2 buckets 290 assertThat(bucketCount).isAtLeast(2); 291 ValueMetricData data = valueData.getData(0); 292 int totalValue = 0; 293 for (ValueBucketInfo bucketInfo : data.getBucketInfoList()) { 294 MetricsUtils.assertBucketTimePresent(bucketInfo); 295 assertThat(bucketInfo.getValuesCount()).isEqualTo(1); 296 assertThat(bucketInfo.getValues(0).getIndex()).isEqualTo(0); 297 totalValue += (int) bucketInfo.getValues(0).getValueLong(); 298 } 299 // At most we lose one full min bucket 300 assertThat((long) totalValue).isGreaterThan(GAP_INTERVAL * NUM_EVENTS - 60_000); 301 } 302 303 // Test value metric with pulled atoms and across multiple buckets testPullerAcrossBucketsWithActivation()304 public void testPullerAcrossBucketsWithActivation() throws Exception { 305 StatsdConfig.Builder builder = ConfigUtils.createConfigBuilder( 306 MetricsUtils.DEVICE_SIDE_TEST_PACKAGE); 307 308 // Add AtomMatcher's. 309 int activationAtomMatcherId = 1; 310 int activationAtomMatcherLabel = 1; 311 AtomMatcher activationAtomMatcher = 312 MetricsUtils.appBreadcrumbMatcherWithLabel( 313 activationAtomMatcherId, activationAtomMatcherLabel); 314 final String atomName = "SYSTEM_ELAPSED_REALTIME"; 315 SimpleAtomMatcher.Builder sam = SimpleAtomMatcher.newBuilder() 316 .setAtomId(Atom.SYSTEM_ELAPSED_REALTIME_FIELD_NUMBER); 317 builder.addAtomMatcher(activationAtomMatcher) 318 .addAtomMatcher(AtomMatcher.newBuilder() 319 .setId(atomName.hashCode()) 320 .setSimpleAtomMatcher(sam)); 321 322 // Add ValueMetric. 323 builder.addValueMetric(ValueMetric.newBuilder() 324 .setId(MetricsUtils.VALUE_METRIC_ID) 325 .setWhat(atomName.hashCode()) 326 .setBucket(TimeUnit.ONE_MINUTE) 327 .setValueField(FieldMatcher.newBuilder() 328 .setField(Atom.SYSTEM_ELAPSED_REALTIME_FIELD_NUMBER) 329 .addChild(FieldMatcher.newBuilder().setField( 330 SystemElapsedRealtime.TIME_MILLIS_FIELD_NUMBER))) 331 .build()); 332 // Add activation. 333 builder.addMetricActivation(MetricActivation.newBuilder() 334 .setMetricId(MetricsUtils.VALUE_METRIC_ID) 335 .setActivationType(ActivationType.ACTIVATE_IMMEDIATELY) 336 .addEventActivation(EventActivation.newBuilder() 337 .setAtomMatcherId(activationAtomMatcherId) 338 .setTtlSeconds(5))); 339 340 341 // Upload config. 342 ConfigUtils.uploadConfig(getDevice(), builder); 343 344 // Wait for 1 min and 10 sec to capture at least 1 bucket 345 RunUtil.getDefault().sleep(60_000 + 10_000); 346 347 // Wait for the metrics to propagate to statsd. 348 RunUtil.getDefault().sleep(1_000); 349 350 StatsLogReport metricReport = ReportUtils.getStatsLogReport(getDevice(), 351 ExtensionRegistry.getEmptyRegistry()); 352 LogUtil.CLog.d("Got the following value metric data: " + metricReport.toString()); 353 assertThat(metricReport.getMetricId()).isEqualTo(MetricsUtils.VALUE_METRIC_ID); 354 assertThat(metricReport.getValueMetrics().getDataList()).isEmpty(); 355 // Skipped buckets are not added when metric is empty. 356 assertThat(metricReport.getValueMetrics().getSkippedList()).isEmpty(); 357 } 358 testValueMetricWithConditionAndActivation()359 public void testValueMetricWithConditionAndActivation() throws Exception { 360 final int conditionLabel = 2; 361 final int activationMatcherId = 5; 362 final int activationMatcherLabel = 5; 363 final int whatMatcherId = 8; 364 final int ttlSec = 5; 365 366 // Add AtomMatchers. 367 AtomMatcher conditionStartAtomMatcher = MetricsUtils.startAtomMatcherWithLabel( 368 APP_BREADCRUMB_REPORTED_A_MATCH_START_ID, conditionLabel); 369 AtomMatcher conditionStopAtomMatcher = MetricsUtils.stopAtomMatcherWithLabel( 370 APP_BREADCRUMB_REPORTED_A_MATCH_STOP_ID, conditionLabel); 371 AtomMatcher activationMatcher = 372 MetricsUtils.startAtomMatcherWithLabel( 373 activationMatcherId, activationMatcherLabel); 374 AtomMatcher whatMatcher = 375 MetricsUtils.unspecifiedAtomMatcher(whatMatcherId); 376 377 StatsdConfig.Builder builder = ConfigUtils.createConfigBuilder( 378 MetricsUtils.DEVICE_SIDE_TEST_PACKAGE) 379 .addAtomMatcher(conditionStartAtomMatcher) 380 .addAtomMatcher(conditionStopAtomMatcher) 381 .addAtomMatcher(whatMatcher) 382 .addAtomMatcher(activationMatcher); 383 384 // Add Predicates. 385 SimplePredicate simplePredicate = SimplePredicate.newBuilder() 386 .setStart(APP_BREADCRUMB_REPORTED_A_MATCH_START_ID) 387 .setStop(APP_BREADCRUMB_REPORTED_A_MATCH_STOP_ID) 388 .build(); 389 Predicate predicate = Predicate.newBuilder() 390 .setId(MetricsUtils.StringToId("Predicate")) 391 .setSimplePredicate(simplePredicate) 392 .build(); 393 builder.addPredicate(predicate); 394 395 // Add ValueMetric. 396 builder.addValueMetric(ValueMetric.newBuilder() 397 .setId(MetricsUtils.VALUE_METRIC_ID) 398 .setWhat(whatMatcher.getId()) 399 .setBucket(TimeUnit.ONE_MINUTE) 400 .setCondition(predicate.getId()) 401 .setValueField(FieldMatcher.newBuilder() 402 .setField(Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER) 403 .addChild(FieldMatcher.newBuilder() 404 .setField(AppBreadcrumbReported.LABEL_FIELD_NUMBER)) 405 ) 406 .setDimensionsInWhat(FieldMatcher.newBuilder().setField(whatMatcherId)) 407 ) 408 .addMetricActivation(MetricActivation.newBuilder() 409 .setMetricId(MetricsUtils.VALUE_METRIC_ID) 410 .addEventActivation(EventActivation.newBuilder() 411 .setAtomMatcherId(activationMatcherId) 412 .setActivationType(ActivationType.ACTIVATE_IMMEDIATELY) 413 .setTtlSeconds(ttlSec) 414 ) 415 ); 416 417 ConfigUtils.uploadConfig(getDevice(), builder); 418 419 // Activate the metric. 420 AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(), 421 AppBreadcrumbReported.State.START.getNumber(), activationMatcherLabel); 422 RunUtil.getDefault().sleep(10); 423 424 // Set the condition to true. 425 AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(), 426 AppBreadcrumbReported.State.START.getNumber(), conditionLabel); 427 RunUtil.getDefault().sleep(10); 428 429 // Skipped due to unknown condition at start of bucket. 430 AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(), 431 AppBreadcrumbReported.State.UNSPECIFIED.getNumber(), 10); 432 RunUtil.getDefault().sleep(10); 433 434 // Skipped due to unknown condition at start of bucket. 435 AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(), 436 AppBreadcrumbReported.State.UNSPECIFIED.getNumber(), 200); 437 RunUtil.getDefault().sleep(10); 438 439 // Set the condition to false. 440 AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(), 441 AppBreadcrumbReported.State.STOP.getNumber(), conditionLabel); 442 RunUtil.getDefault().sleep(10); 443 444 // Log an event that should not be counted because condition is false. 445 AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(), 446 AppBreadcrumbReported.State.UNSPECIFIED.getNumber(), 3_000); 447 RunUtil.getDefault().sleep(10); 448 449 // Let the metric deactivate. 450 RunUtil.getDefault().sleep(ttlSec * 1000); 451 452 // Log an event that should not be counted. 453 AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(), 454 AppBreadcrumbReported.State.UNSPECIFIED.getNumber(), 40_000); 455 RunUtil.getDefault().sleep(10); 456 457 // Condition to true again. 458 AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(), 459 AppBreadcrumbReported.State.START.getNumber(), conditionLabel); 460 RunUtil.getDefault().sleep(10); 461 462 // Event should not be counted, metric is still not active. 463 AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(), 464 AppBreadcrumbReported.State.UNSPECIFIED.getNumber(), 500_000); 465 RunUtil.getDefault().sleep(10); 466 467 // Activate the metric. 468 AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(), 469 AppBreadcrumbReported.State.START.getNumber(), activationMatcherLabel); 470 RunUtil.getDefault().sleep(10); 471 472 // Log an event that should be counted. 473 AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(), 474 AppBreadcrumbReported.State.UNSPECIFIED.getNumber(), 6_000_000); 475 RunUtil.getDefault().sleep(10); 476 477 // Let the metric deactivate. 478 RunUtil.getDefault().sleep(ttlSec * 1000); 479 480 // Log an event that should not be counted. 481 AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(), 482 AppBreadcrumbReported.State.UNSPECIFIED.getNumber(), 70_000_000); 483 RunUtil.getDefault().sleep(10); 484 485 // Wait for the metrics to propagate to statsd. 486 RunUtil.getDefault().sleep(2000); 487 488 StatsLogReport metricReport = ReportUtils.getStatsLogReport(getDevice(), 489 ExtensionRegistry.getEmptyRegistry()); 490 LogUtil.CLog.d("Received the following data: " + metricReport.toString()); 491 assertThat(metricReport.getMetricId()).isEqualTo(MetricsUtils.VALUE_METRIC_ID); 492 assertThat(metricReport.hasValueMetrics()).isTrue(); 493 assertThat(metricReport.getIsActive()).isFalse(); 494 495 StatsLogReport.ValueMetricDataWrapper valueData = metricReport.getValueMetrics(); 496 assertThat(valueData.getDataCount()).isEqualTo(1); 497 assertThat(valueData.getData(0).getBucketInfoCount()).isEqualTo(1); 498 long totalValue = valueData.getData(0).getBucketInfoList().stream() 499 .peek(MetricsUtils::assertBucketTimePresent) 500 .peek(bucketInfo -> assertThat(bucketInfo.getValuesCount()).isEqualTo(1)) 501 .map(bucketInfo -> bucketInfo.getValues(0)) 502 .peek(value -> assertThat(value.getIndex()).isEqualTo(0)) 503 .mapToLong(value -> value.getValueLong()) 504 .sum(); 505 assertThat(totalValue).isEqualTo(6_000_000); 506 } 507 508 } 509