Merge "[TeX] Introduced Telemetry Express Histogram Logging APIs"
This commit is contained in:
107
core/java/com/android/internal/expresslog/Histogram.java
Normal file
107
core/java/com/android/internal/expresslog/Histogram.java
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.internal.expresslog;
|
||||||
|
|
||||||
|
import android.annotation.NonNull;
|
||||||
|
|
||||||
|
import com.android.internal.util.FrameworkStatsLog;
|
||||||
|
|
||||||
|
/** CounterHistogram encapsulates StatsD write API calls */
|
||||||
|
public final class Histogram {
|
||||||
|
|
||||||
|
private final long mMetricIdHash;
|
||||||
|
private final BinOptions mBinOptions;
|
||||||
|
|
||||||
|
public Histogram(@NonNull String metricId, @NonNull BinOptions binOptions) {
|
||||||
|
mMetricIdHash = Utils.hashString(metricId);
|
||||||
|
mBinOptions = binOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs increment sample count for automatically calculated bin
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public void logSample(float sample) {
|
||||||
|
final int binIndex = mBinOptions.getBinForSample(sample);
|
||||||
|
FrameworkStatsLog.write(FrameworkStatsLog.EXPRESS_HISTOGRAM_SAMPLE_REPORTED, mMetricIdHash,
|
||||||
|
/*count*/ 1, binIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Used by CounterHistogram to map data sample to corresponding bin */
|
||||||
|
public interface BinOptions {
|
||||||
|
/**
|
||||||
|
* Returns bins count to be used by counter histogram
|
||||||
|
*
|
||||||
|
* @return bins count used to initialize Options, including overflow & underflow bins
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
int getBinsCount();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return zero based index
|
||||||
|
* Calculates bin index for the input sample value
|
||||||
|
* index == 0 stands for underflow
|
||||||
|
* index == getBinsCount() - 1 stands for overflow
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
int getBinForSample(float sample);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Used by CounterHistogram to map data sample to corresponding bin for on uniform bins */
|
||||||
|
public static final class UniformOptions implements BinOptions {
|
||||||
|
|
||||||
|
private final int mBinCount;
|
||||||
|
private final float mMinValue;
|
||||||
|
private final float mExclusiveMaxValue;
|
||||||
|
private final float mBinSize;
|
||||||
|
|
||||||
|
public UniformOptions(int binCount, float minValue, float exclusiveMaxValue) {
|
||||||
|
if (binCount < 1) {
|
||||||
|
throw new IllegalArgumentException("Bin count should be positive number");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exclusiveMaxValue <= minValue) {
|
||||||
|
throw new IllegalArgumentException("Bins range invalid (maxValue < minValue)");
|
||||||
|
}
|
||||||
|
|
||||||
|
mMinValue = minValue;
|
||||||
|
mExclusiveMaxValue = exclusiveMaxValue;
|
||||||
|
mBinSize = (mExclusiveMaxValue - minValue) / binCount;
|
||||||
|
|
||||||
|
// Implicitly add 2 for the extra undeflow & overflow bins
|
||||||
|
mBinCount = binCount + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getBinsCount() {
|
||||||
|
return mBinCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getBinForSample(float sample) {
|
||||||
|
if (sample < mMinValue) {
|
||||||
|
// goes to underflow
|
||||||
|
return 0;
|
||||||
|
} else if (sample >= mExclusiveMaxValue) {
|
||||||
|
// goes to overflow
|
||||||
|
return mBinCount - 1;
|
||||||
|
}
|
||||||
|
return (int) ((sample - mMinValue) / mBinSize + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
12
core/java/com/android/internal/expresslog/TEST_MAPPING
Normal file
12
core/java/com/android/internal/expresslog/TEST_MAPPING
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"presubmit": [
|
||||||
|
{
|
||||||
|
"name": "ExpressLogTests",
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"exclude-annotation": "org.junit.Ignore"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
47
core/tests/expresslog/Android.bp
Normal file
47
core/tests/expresslog/Android.bp
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
// Copyright (C) 2023 The Android Open Source Project
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package {
|
||||||
|
// See: http://go/android-license-faq
|
||||||
|
// A large-scale-change added 'default_applicable_licenses' to import
|
||||||
|
// all of the 'license_kinds' from "frameworks_base_license"
|
||||||
|
// to get the below license kinds:
|
||||||
|
// SPDX-license-identifier-Apache-2.0
|
||||||
|
default_applicable_licenses: ["frameworks_base_license"],
|
||||||
|
}
|
||||||
|
|
||||||
|
android_test {
|
||||||
|
name: "ExpressLogTests",
|
||||||
|
|
||||||
|
srcs: [
|
||||||
|
"src/**/*.java",
|
||||||
|
],
|
||||||
|
|
||||||
|
static_libs: [
|
||||||
|
"androidx.test.rules",
|
||||||
|
"modules-utils-build",
|
||||||
|
],
|
||||||
|
|
||||||
|
libs: [
|
||||||
|
"android.test.base",
|
||||||
|
"android.test.runner",
|
||||||
|
],
|
||||||
|
|
||||||
|
platform_apis: true,
|
||||||
|
test_suites: [
|
||||||
|
"general-tests",
|
||||||
|
],
|
||||||
|
|
||||||
|
certificate: "platform",
|
||||||
|
}
|
||||||
29
core/tests/expresslog/AndroidManifest.xml
Normal file
29
core/tests/expresslog/AndroidManifest.xml
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright (C) 2023 The Android Open Source Project
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:installLocation="internalOnly"
|
||||||
|
package="com.android.internal.expresslog" >
|
||||||
|
|
||||||
|
<application >
|
||||||
|
<uses-library android:name="android.test.runner" />
|
||||||
|
</application>
|
||||||
|
|
||||||
|
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
android:targetPackage="com.android.internal.expresslog"
|
||||||
|
android:label="Telemetry Express Logging Helper Tests" />
|
||||||
|
|
||||||
|
</manifest>
|
||||||
3
core/tests/expresslog/OWNERS
Normal file
3
core/tests/expresslog/OWNERS
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# Bug component: 719316
|
||||||
|
# Stats/expresslog
|
||||||
|
file:/services/core/java/com/android/server/stats/OWNERS
|
||||||
12
core/tests/expresslog/TEST_MAPPING
Normal file
12
core/tests/expresslog/TEST_MAPPING
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"presubmit": [
|
||||||
|
{
|
||||||
|
"name": "ExpressLogTests",
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"exclude-annotation": "org.junit.Ignore"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,133 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.android.internal.expresslog;
|
||||||
|
|
||||||
|
import androidx.test.filters.SmallTest;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.junit.runners.JUnit4;
|
||||||
|
|
||||||
|
@RunWith(JUnit4.class)
|
||||||
|
public class UniformOptionsTest {
|
||||||
|
private static final String TAG = UniformOptionsTest.class.getSimpleName();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@SmallTest
|
||||||
|
public void testGetBinsCount() {
|
||||||
|
Histogram.UniformOptions options1 = new Histogram.UniformOptions(1, 100, 1000);
|
||||||
|
assertEquals(3, options1.getBinsCount());
|
||||||
|
|
||||||
|
Histogram.UniformOptions options10 = new Histogram.UniformOptions(10, 100, 1000);
|
||||||
|
assertEquals(12, options10.getBinsCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
@SmallTest
|
||||||
|
public void testConstructZeroBinsCount() {
|
||||||
|
new Histogram.UniformOptions(0, 100, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
@SmallTest
|
||||||
|
public void testConstructNegativeBinsCount() {
|
||||||
|
new Histogram.UniformOptions(-1, 100, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
@SmallTest
|
||||||
|
public void testConstructMaxValueLessThanMinValue() {
|
||||||
|
new Histogram.UniformOptions(10, 1000, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@SmallTest
|
||||||
|
public void testBinIndexForRangeEqual1() {
|
||||||
|
Histogram.UniformOptions options = new Histogram.UniformOptions(10, 1, 11);
|
||||||
|
for (int i = 0, bins = options.getBinsCount(); i < bins; i++) {
|
||||||
|
assertEquals(i, options.getBinForSample(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@SmallTest
|
||||||
|
public void testBinIndexForRangeEqual2() {
|
||||||
|
Histogram.UniformOptions options = new Histogram.UniformOptions(10, 1, 21);
|
||||||
|
for (int i = 0, bins = options.getBinsCount(); i < bins; i++) {
|
||||||
|
assertEquals(i, options.getBinForSample(i * 2));
|
||||||
|
assertEquals(i, options.getBinForSample(i * 2 - 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@SmallTest
|
||||||
|
public void testBinIndexForRangeEqual5() {
|
||||||
|
Histogram.UniformOptions options = new Histogram.UniformOptions(2, 0, 10);
|
||||||
|
assertEquals(4, options.getBinsCount());
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
for (int sample = 0; sample < 5; sample++) {
|
||||||
|
assertEquals(i + 1, options.getBinForSample(i * 5 + sample));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@SmallTest
|
||||||
|
public void testBinIndexForRangeEqual10() {
|
||||||
|
Histogram.UniformOptions options = new Histogram.UniformOptions(10, 1, 101);
|
||||||
|
assertEquals(0, options.getBinForSample(0));
|
||||||
|
assertEquals(options.getBinsCount() - 2, options.getBinForSample(100));
|
||||||
|
assertEquals(options.getBinsCount() - 1, options.getBinForSample(101));
|
||||||
|
|
||||||
|
final float binSize = (101 - 1) / 10f;
|
||||||
|
for (int i = 1, bins = options.getBinsCount() - 1; i < bins; i++) {
|
||||||
|
assertEquals(i, options.getBinForSample(i * binSize));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@SmallTest
|
||||||
|
public void testBinIndexForRangeEqual90() {
|
||||||
|
final int binCount = 10;
|
||||||
|
final int minValue = 100;
|
||||||
|
final int maxValue = 100000;
|
||||||
|
|
||||||
|
Histogram.UniformOptions options = new Histogram.UniformOptions(binCount, minValue,
|
||||||
|
maxValue);
|
||||||
|
|
||||||
|
// logging underflow sample
|
||||||
|
assertEquals(0, options.getBinForSample(minValue - 1));
|
||||||
|
|
||||||
|
// logging overflow sample
|
||||||
|
assertEquals(binCount + 1, options.getBinForSample(maxValue));
|
||||||
|
assertEquals(binCount + 1, options.getBinForSample(maxValue + 1));
|
||||||
|
|
||||||
|
// logging min edge sample
|
||||||
|
assertEquals(1, options.getBinForSample(minValue));
|
||||||
|
|
||||||
|
// logging max edge sample
|
||||||
|
assertEquals(binCount, options.getBinForSample(maxValue - 1));
|
||||||
|
|
||||||
|
// logging single valid sample per bin
|
||||||
|
final int binSize = (maxValue - minValue) / binCount;
|
||||||
|
|
||||||
|
for (int i = 0; i < binCount; i++) {
|
||||||
|
assertEquals(i + 1, options.getBinForSample(minValue + binSize * i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user