summaryrefslogtreecommitdiff
path: root/statsd/src
diff options
context:
space:
mode:
Diffstat (limited to 'statsd/src')
-rw-r--r--statsd/src/guardrail/StatsdStats.cpp63
-rw-r--r--statsd/src/guardrail/StatsdStats.h7
-rw-r--r--statsd/src/socket/StatsSocketListener.cpp64
-rw-r--r--statsd/src/stats_log.proto11
4 files changed, 114 insertions, 31 deletions
diff --git a/statsd/src/guardrail/StatsdStats.cpp b/statsd/src/guardrail/StatsdStats.cpp
index 2d9586f4..8cd68dc3 100644
--- a/statsd/src/guardrail/StatsdStats.cpp
+++ b/statsd/src/guardrail/StatsdStats.cpp
@@ -63,6 +63,7 @@ const int FIELD_ID_STATSD_STATS_ID = 22;
const int FIELD_ID_SUBSCRIPTION_STATS = 23;
const int FIELD_ID_SOCKET_LOSS_STATS = 24;
const int FIELD_ID_QUEUE_STATS = 25;
+const int FIELD_ID_SOCKET_READ_STATS = 26;
const int FIELD_ID_RESTRICTED_METRIC_QUERY_STATS_CALLING_UID = 1;
const int FIELD_ID_RESTRICTED_METRIC_QUERY_STATS_CONFIG_ID = 2;
@@ -200,13 +201,17 @@ const int FIELD_ID_PER_SUBSCRIPTION_STATS_START_TIME = 4;
const int FIELD_ID_PER_SUBSCRIPTION_STATS_END_TIME = 5;
const int FIELD_ID_PER_SUBSCRIPTION_STATS_FLUSH_COUNT = 6;
+// Socket read stats
+const int FIELD_ID_SOCKET_READ_STATS_BATCHED_READ_SIZE = 1;
+
const std::map<int, std::pair<size_t, size_t>> StatsdStats::kAtomDimensionKeySizeLimitMap = {
{util::BINDER_CALLS, {6000, 10000}},
{util::LOOPER_STATS, {1500, 2500}},
{util::CPU_TIME_PER_UID_FREQ, {6000, 10000}},
};
-StatsdStats::StatsdStats() : mStatsdStatsId(rand()) {
+StatsdStats::StatsdStats()
+ : mStatsdStatsId(rand()), mSocketBatchReadHistogram(kNumBinsInSocketBatchReadHistogram) {
mPushedAtomStats.resize(kMaxPushedAtomId + 1);
mStartTimeSec = getWallClockSec();
}
@@ -292,6 +297,28 @@ void StatsdStats::noteLogLost(int32_t wallClockTimeSec, int32_t count, int32_t l
mLogLossStats.emplace_back(wallClockTimeSec, count, lastError, lastTag, uid, pid);
}
+void StatsdStats::noteBatchSocketRead(int32_t size) {
+ // Calculate the bin.
+ int bin = 0;
+ if (size < 0) {
+ ALOGE("Unexpected negative size read from socket. This should never happen");
+ bin = 0;
+ } else if (size < 5) {
+ bin = size; // bin = [0,4].
+ } else if (size < 10) {
+ bin = 4 + (size / 5); // bin = 5.
+ } else if (size < 100) {
+ bin = 5 + (size / 10); // bin = [6,14].
+ } else if (size < 1000) {
+ bin = 14 + (size / 100); // bin = [15-23].
+ } else if (size < 2000) {
+ bin = 19 + (size / 200); // bin = [24-28].
+ } else { // 2000+
+ bin = 29;
+ }
+ lock_guard<std::mutex> lock(mLock);
+ mSocketBatchReadHistogram[bin] += 1;
+}
void StatsdStats::noteBroadcastSent(const ConfigKey& key) {
noteBroadcastSent(key, getWallClockSec());
}
@@ -1100,6 +1127,7 @@ void StatsdStats::resetInternalLocked() {
mPushedAtomDropsStats.clear();
mRestrictedMetricQueryStats.clear();
mSubscriptionPullThreadWakeupCount = 0;
+ std::fill(mSocketBatchReadHistogram.begin(), mSocketBatchReadHistogram.end(), 0);
for (auto it = mSubscriptionStats.begin(); it != mSubscriptionStats.end();) {
if (it->second.end_time_sec > 0) {
@@ -1413,6 +1441,28 @@ void StatsdStats::dumpStats(int out) const {
(long long)restart);
}
+ dprintf(out, "********Socket batch read size stats***********\n");
+ for (int i = 0; i < kNumBinsInSocketBatchReadHistogram; i++) {
+ if (mSocketBatchReadHistogram[i] == 0) {
+ continue;
+ }
+ string range;
+ if (i < 5) {
+ range = "[" + to_string(i) + "]";
+ } else if (i == 5) {
+ range = "[5-9]";
+ } else if (i < 15) {
+ range = "[" + to_string(i - 5) + "0-" + to_string(i - 5) + "9]";
+ } else if (i < 24) {
+ range = "[" + to_string(i - 14) + "00-" + to_string(i - 14) + "99]";
+ } else if (i < 29) {
+ range = "[" + to_string((i - 19) * 2) + "00-" + to_string((i - 19) * 2 + 1) + "99]";
+ } else {
+ range = "[2000+]";
+ }
+ dprintf(out, "%s: %lld\n", range.c_str(), (long long)mSocketBatchReadHistogram[i]);
+ }
+
for (const auto& loss : mLogLossStats) {
dprintf(out,
"Log loss: %lld (wall clock sec) - %d (count), %d (last error), %d (last tag), %d "
@@ -1492,6 +1542,7 @@ void StatsdStats::dumpStats(int out) const {
dprintf(out, "Statsd Stats Id %d\n", mStatsdStatsId);
dprintf(out, "********Shard Offset Provider stats***********\n");
dprintf(out, "Shard Offset: %u\n", ShardOffsetProvider::getInstance().getShardOffset());
+ dprintf(out, "\n");
}
void addConfigStatsToProto(const ConfigStats& configStats, ProtoOutputStream* proto) {
@@ -1931,6 +1982,16 @@ void StatsdStats::dumpStats(std::vector<uint8_t>* output, bool reset) {
proto.end(socketLossStatsToken);
+ // Socket batch read stats.
+ const uint64_t socketReadStatsToken =
+ proto.start(FIELD_TYPE_MESSAGE | FIELD_ID_SOCKET_READ_STATS);
+ for (const auto& it : mSocketBatchReadHistogram) {
+ proto.write(FIELD_TYPE_INT64 | FIELD_ID_SOCKET_READ_STATS_BATCHED_READ_SIZE |
+ FIELD_COUNT_REPEATED,
+ it);
+ }
+ proto.end(socketReadStatsToken);
+
output->clear();
proto.serializeToVector(output);
diff --git a/statsd/src/guardrail/StatsdStats.h b/statsd/src/guardrail/StatsdStats.h
index 3adb6683..6f202603 100644
--- a/statsd/src/guardrail/StatsdStats.h
+++ b/statsd/src/guardrail/StatsdStats.h
@@ -301,6 +301,8 @@ public:
static const int32_t kMaxLoggedBucketDropEvents = 10;
+ static const int32_t kNumBinsInSocketBatchReadHistogram = 30;
+
/**
* Report a new config has been received and report the static stats about the config.
*
@@ -706,6 +708,8 @@ public:
*/
void noteSubscriptionPullThreadWakeup();
+ void noteBatchSocketRead(int32_t readSize);
+
/**
* Reset the historical stats. Including all stats in icebox, and the tracked stats about
* metrics, matchers, and atoms. The active configs will be kept and StatsdStats will continue
@@ -936,6 +940,8 @@ private:
std::list<int32_t> mSystemServerRestartSec;
+ std::vector<int64_t> mSocketBatchReadHistogram;
+
struct RestrictedMetricQueryStats {
RestrictedMetricQueryStats(int32_t callingUid, int64_t configId,
const string& configPackage, std::optional<int32_t> configUid,
@@ -1054,6 +1060,7 @@ private:
FRIEND_TEST(StatsdStatsTest, TestSystemServerCrash);
FRIEND_TEST(StatsdStatsTest, TestTimestampThreshold);
FRIEND_TEST(StatsdStatsTest, TestValidConfigAdd);
+ FRIEND_TEST(StatsdStatsTest, TestSocketBatchReadStats);
};
InvalidConfigReason createInvalidConfigReasonWithMatcher(const InvalidConfigReasonEnum reason,
diff --git a/statsd/src/socket/StatsSocketListener.cpp b/statsd/src/socket/StatsSocketListener.cpp
index 7f0eb436..c9f8b895 100644
--- a/statsd/src/socket/StatsSocketListener.cpp
+++ b/statsd/src/socket/StatsSocketListener.cpp
@@ -64,41 +64,45 @@ bool StatsSocketListener::onDataAvailable(SocketClient* cli) {
};
const int socket = cli->getSocket();
-
- // To clear the entire buffer is secure/safe, but this contributes to 1.68%
- // overhead under logging load. We are safe because we check counts, but
- // still need to clear null terminator
- // memset(buffer, 0, sizeof(buffer));
- ssize_t n = recvmsg(socket, &hdr, 0);
- if (n <= (ssize_t)(sizeof(android_log_header_t))) {
- return false;
- }
-
- buffer[n] = 0;
-
- struct ucred* cred = NULL;
-
- struct cmsghdr* cmsg = CMSG_FIRSTHDR(&hdr);
- while (cmsg != NULL) {
- if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDENTIALS) {
- cred = (struct ucred*)CMSG_DATA(cmsg);
- break;
+ int i = 0;
+ ssize_t n = 0;
+ while (n = recvmsg(socket, &hdr, MSG_DONTWAIT), n > 0) {
+ // To clear the entire buffer is secure/safe, but this contributes to 1.68%
+ // overhead under logging load. We are safe because we check counts, but
+ // still need to clear null terminator.
+ // Note that the memset, if needed, should happen before each read in the while loop.
+ // memset(buffer, 0, sizeof(buffer));
+ if (n <= (ssize_t)(sizeof(android_log_header_t))) {
+ return false;
+ }
+ buffer[n] = 0;
+ i++;
+
+ struct ucred* cred = NULL;
+
+ struct cmsghdr* cmsg = CMSG_FIRSTHDR(&hdr);
+ while (cmsg != NULL) {
+ if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDENTIALS) {
+ cred = (struct ucred*)CMSG_DATA(cmsg);
+ break;
+ }
+ cmsg = CMSG_NXTHDR(&hdr, cmsg);
}
- cmsg = CMSG_NXTHDR(&hdr, cmsg);
- }
- struct ucred fake_cred;
- if (cred == NULL) {
- cred = &fake_cred;
- cred->pid = 0;
- cred->uid = DEFAULT_OVERFLOWUID;
- }
+ struct ucred fake_cred;
+ if (cred == NULL) {
+ cred = &fake_cred;
+ cred->pid = 0;
+ cred->uid = DEFAULT_OVERFLOWUID;
+ }
- const uint32_t uid = cred->uid;
- const uint32_t pid = cred->pid;
+ const uint32_t uid = cred->uid;
+ const uint32_t pid = cred->pid;
- processSocketMessage(buffer, n, uid, pid, *mQueue, *mLogEventFilter);
+ processSocketMessage(buffer, n, uid, pid, *mQueue, *mLogEventFilter);
+ }
+ StatsdStats::getInstance().noteBatchSocketRead(i);
return true;
}
diff --git a/statsd/src/stats_log.proto b/statsd/src/stats_log.proto
index ff219519..00763dea 100644
--- a/statsd/src/stats_log.proto
+++ b/statsd/src/stats_log.proto
@@ -697,6 +697,17 @@ message StatsdStatsReport {
}
optional EventQueueStats event_queue_stats = 25;
+
+ // Tracks info about reads from the socket.
+ message SocketReadStats {
+ // This is a histogram of sizes of the batched reads. The bins are as follows:
+ // [0, 1, 2, 3, 4, 5-9, 10-19, 20-29, 30-39, 40-49, 50-59, 60-69, 70-79, 80-89, 90-99,
+ // 100-199, 200-299, 300-399, 400-499, 500-599, 600-699, 700-799, 800-899, 900-999,
+ // 1000-1199, 1200-1399, 1400-1599, 1600-1799, 1800-1999, 2000+]
+ repeated int64 batched_read_size = 1;
+ }
+
+ optional SocketReadStats socket_read_stats = 26;
}
message AlertTriggerDetails {