[TeX] Introduced Telemetry Express Histogram metric Native API
- added support C++ TeX Histogram logging API Bug: 268161449 Test: atest expresslog_test Change-Id: I284c6ceab42208dc9432fe3887c9ac000028d072
This commit is contained in:
parent
22387708fc
commit
75f860033c
4 changed files with 326 additions and 2 deletions
|
|
@ -18,11 +18,17 @@ package {
|
|||
default_applicable_licenses: ["Android-Apache-2.0"],
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libexpresslog",
|
||||
cc_defaults {
|
||||
name: "expresslog_defaults",
|
||||
srcs: [
|
||||
"Counter.cpp",
|
||||
"Histogram.cpp",
|
||||
],
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libexpresslog",
|
||||
defaults: ["expresslog_defaults"],
|
||||
cflags: [
|
||||
"-DNAMESPACE_FOR_HASH_FUNCTIONS=farmhash",
|
||||
"-Wall",
|
||||
|
|
@ -37,6 +43,7 @@ cc_library {
|
|||
],
|
||||
shared_libs: [
|
||||
"libbase",
|
||||
"liblog",
|
||||
"libstatssocket",
|
||||
],
|
||||
export_include_dirs: ["include"],
|
||||
|
|
@ -69,3 +76,38 @@ cc_library_static {
|
|||
"libstatssocket",
|
||||
],
|
||||
}
|
||||
|
||||
cc_test {
|
||||
name: "expresslog_test",
|
||||
defaults: ["expresslog_defaults"],
|
||||
test_suites: [
|
||||
"general-tests",
|
||||
],
|
||||
srcs: [
|
||||
"tests/Histogram_test.cpp",
|
||||
],
|
||||
local_include_dirs: [
|
||||
"include",
|
||||
],
|
||||
cflags: [
|
||||
"-DNAMESPACE_FOR_HASH_FUNCTIONS=farmhash",
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
"-Wunused",
|
||||
"-Wpedantic",
|
||||
"-Werror",
|
||||
],
|
||||
header_libs: [
|
||||
"libtextclassifier_hash_headers",
|
||||
],
|
||||
static_libs: [
|
||||
"libgmock",
|
||||
"libbase",
|
||||
"liblog",
|
||||
"libstatslog_express",
|
||||
"libtextclassifier_hash_static",
|
||||
],
|
||||
shared_libs: [
|
||||
"libstatssocket",
|
||||
]
|
||||
}
|
||||
|
|
|
|||
74
libstats/expresslog/Histogram.cpp
Normal file
74
libstats/expresslog/Histogram.cpp
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
#include "include/Histogram.h"
|
||||
|
||||
#define LOG_TAG "tex"
|
||||
|
||||
#include <log/log.h>
|
||||
#include <statslog_express.h>
|
||||
#include <string.h>
|
||||
#include <utils/hash/farmhash.h>
|
||||
|
||||
namespace android {
|
||||
namespace expresslog {
|
||||
|
||||
Histogram::UniformOptions* Histogram::UniformOptions::create(int binCount, float minValue,
|
||||
float exclusiveMaxValue) {
|
||||
if (binCount < 1) {
|
||||
ALOGE("Bin count should be positive number");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (exclusiveMaxValue <= minValue) {
|
||||
ALOGE("Bins range invalid (maxValue < minValue)");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return new UniformOptions(binCount, minValue, exclusiveMaxValue);
|
||||
}
|
||||
|
||||
Histogram::UniformOptions::UniformOptions(int binCount, float minValue, float exclusiveMaxValue)
|
||||
: // Implicitly add 2 for the extra undeflow & overflow bins
|
||||
mBinCount(binCount + 2),
|
||||
mMinValue(minValue),
|
||||
mExclusiveMaxValue(exclusiveMaxValue),
|
||||
mBinSize((exclusiveMaxValue - minValue) / binCount) {
|
||||
}
|
||||
|
||||
int Histogram::UniformOptions::getBinForSample(float sample) const {
|
||||
if (sample < mMinValue) {
|
||||
// goes to underflow
|
||||
return 0;
|
||||
} else if (sample >= mExclusiveMaxValue) {
|
||||
// goes to overflow
|
||||
return mBinCount - 1;
|
||||
}
|
||||
return (int)((sample - mMinValue) / mBinSize + 1);
|
||||
}
|
||||
|
||||
Histogram::Histogram(const char* metricName, std::shared_ptr<BinOptions> binOptions)
|
||||
: mMetricIdHash(farmhash::Fingerprint64(metricName, strlen(metricName))),
|
||||
mBinOptions(std::move(binOptions)) {
|
||||
}
|
||||
|
||||
void Histogram::logSample(float sample) const {
|
||||
const int binIndex = mBinOptions->getBinForSample(sample);
|
||||
stats_write(EXPRESS_HISTOGRAM_SAMPLE_REPORTED, mMetricIdHash, /*count*/ 1, binIndex);
|
||||
}
|
||||
|
||||
} // namespace expresslog
|
||||
} // namespace android
|
||||
80
libstats/expresslog/include/Histogram.h
Normal file
80
libstats/expresslog/include/Histogram.h
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace android {
|
||||
namespace expresslog {
|
||||
|
||||
/** Histogram encapsulates StatsD write API calls */
|
||||
class Histogram final {
|
||||
public:
|
||||
class BinOptions {
|
||||
public:
|
||||
virtual ~BinOptions() = default;
|
||||
/**
|
||||
* Returns bins count to be used by a Histogram
|
||||
*
|
||||
* @return bins count used to initialize Options, including overflow & underflow bins
|
||||
*/
|
||||
virtual int getBinsCount() const = 0;
|
||||
|
||||
/**
|
||||
* @return zero based index
|
||||
* Calculates bin index for the input sample value
|
||||
* index == 0 stands for underflow
|
||||
* index == getBinsCount() - 1 stands for overflow
|
||||
*/
|
||||
virtual int getBinForSample(float sample) const = 0;
|
||||
};
|
||||
|
||||
/** Used by Histogram to map data sample to corresponding bin for uniform bins */
|
||||
class UniformOptions : public BinOptions {
|
||||
UniformOptions(int binCount, float minValue, float exclusiveMaxValue);
|
||||
|
||||
public:
|
||||
static UniformOptions* create(int binCount, float minValue, float exclusiveMaxValue);
|
||||
|
||||
int getBinsCount() const override {
|
||||
return mBinCount;
|
||||
}
|
||||
|
||||
int getBinForSample(float sample) const override;
|
||||
|
||||
private:
|
||||
const int mBinCount;
|
||||
const float mMinValue;
|
||||
const float mExclusiveMaxValue;
|
||||
const float mBinSize;
|
||||
};
|
||||
|
||||
Histogram(const char* metricName, std::shared_ptr<BinOptions> binOptions);
|
||||
|
||||
/**
|
||||
* Logs increment sample count for automatically calculated bin
|
||||
*/
|
||||
void logSample(float sample) const;
|
||||
|
||||
private:
|
||||
const int64_t mMetricIdHash;
|
||||
const std::shared_ptr<BinOptions> mBinOptions;
|
||||
};
|
||||
|
||||
} // namespace expresslog
|
||||
} // namespace android
|
||||
128
libstats/expresslog/tests/Histogram_test.cpp
Normal file
128
libstats/expresslog/tests/Histogram_test.cpp
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
#include "Histogram.h"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace android {
|
||||
namespace expresslog {
|
||||
|
||||
#ifdef __ANDROID__
|
||||
TEST(UniformOptions, getBinsCount) {
|
||||
const std::shared_ptr<Histogram::UniformOptions> options1(
|
||||
Histogram::UniformOptions::create(1, 100, 1000));
|
||||
ASSERT_EQ(3, options1->getBinsCount());
|
||||
|
||||
const std::shared_ptr<Histogram::UniformOptions> options10(
|
||||
Histogram::UniformOptions::create(10, 100, 1000));
|
||||
ASSERT_EQ(12, options10->getBinsCount());
|
||||
}
|
||||
|
||||
TEST(UniformOptions, constructZeroBinsCount) {
|
||||
const std::shared_ptr<Histogram::UniformOptions> options(
|
||||
Histogram::UniformOptions::create(0, 100, 1000));
|
||||
ASSERT_EQ(nullptr, options);
|
||||
}
|
||||
|
||||
TEST(UniformOptions, constructNegativeBinsCount) {
|
||||
const std::shared_ptr<Histogram::UniformOptions> options(
|
||||
Histogram::UniformOptions::create(-1, 100, 1000));
|
||||
ASSERT_EQ(nullptr, options);
|
||||
}
|
||||
|
||||
TEST(UniformOptions, constructMaxValueLessThanMinValue) {
|
||||
const std::shared_ptr<Histogram::UniformOptions> options(
|
||||
Histogram::UniformOptions::create(10, 1000, 100));
|
||||
ASSERT_EQ(nullptr, options);
|
||||
}
|
||||
|
||||
TEST(UniformOptions, testBinIndexForRangeEqual1) {
|
||||
const std::shared_ptr<Histogram::UniformOptions> options(
|
||||
Histogram::UniformOptions::create(10, 1, 11));
|
||||
for (int i = 0, bins = options->getBinsCount(); i < bins; i++) {
|
||||
ASSERT_EQ(i, options->getBinForSample(i));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(UniformOptions, testBinIndexForRangeEqual2) {
|
||||
const std::shared_ptr<Histogram::UniformOptions> options(
|
||||
Histogram::UniformOptions::create(10, 1, 21));
|
||||
for (int i = 0, bins = options->getBinsCount(); i < bins; i++) {
|
||||
ASSERT_EQ(i, options->getBinForSample(i * 2));
|
||||
ASSERT_EQ(i, options->getBinForSample(i * 2 - 1));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(UniformOptions, testBinIndexForRangeEqual5) {
|
||||
const std::shared_ptr<Histogram::UniformOptions> options(
|
||||
Histogram::UniformOptions::create(2, 0, 10));
|
||||
ASSERT_EQ(4, options->getBinsCount());
|
||||
for (int i = 0; i < 2; i++) {
|
||||
for (int sample = 0; sample < 5; sample++) {
|
||||
ASSERT_EQ(i + 1, options->getBinForSample(i * 5 + sample));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(UniformOptions, testBinIndexForRangeEqual10) {
|
||||
const std::shared_ptr<Histogram::UniformOptions> options(
|
||||
Histogram::UniformOptions::create(10, 1, 101));
|
||||
ASSERT_EQ(0, options->getBinForSample(0));
|
||||
ASSERT_EQ(options->getBinsCount() - 2, options->getBinForSample(100));
|
||||
ASSERT_EQ(options->getBinsCount() - 1, options->getBinForSample(101));
|
||||
|
||||
const float binSize = (101 - 1) / 10.f;
|
||||
for (int i = 1, bins = options->getBinsCount() - 1; i < bins; i++) {
|
||||
ASSERT_EQ(i, options->getBinForSample(i * binSize));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(UniformOptions, testBinIndexForRangeEqual90) {
|
||||
const int binCount = 10;
|
||||
const int minValue = 100;
|
||||
const int maxValue = 100000;
|
||||
|
||||
const std::shared_ptr<Histogram::UniformOptions> options(
|
||||
Histogram::UniformOptions::create(binCount, minValue, maxValue));
|
||||
|
||||
// logging underflow sample
|
||||
ASSERT_EQ(0, options->getBinForSample(minValue - 1));
|
||||
|
||||
// logging overflow sample
|
||||
ASSERT_EQ(binCount + 1, options->getBinForSample(maxValue));
|
||||
ASSERT_EQ(binCount + 1, options->getBinForSample(maxValue + 1));
|
||||
|
||||
// logging min edge sample
|
||||
ASSERT_EQ(1, options->getBinForSample(minValue));
|
||||
|
||||
// logging max edge sample
|
||||
ASSERT_EQ(binCount, options->getBinForSample(maxValue - 1));
|
||||
|
||||
// logging single valid sample per bin
|
||||
const int binSize = (maxValue - minValue) / binCount;
|
||||
|
||||
for (int i = 0; i < binCount; i++) {
|
||||
ASSERT_EQ(i + 1, options->getBinForSample(minValue + binSize * i));
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
GTEST_LOG_(INFO) << "This test does nothing.\n";
|
||||
#endif
|
||||
|
||||
} // namespace expresslog
|
||||
} // namespace android
|
||||
Loading…
Add table
Reference in a new issue