diff options
Diffstat (limited to 'statsd/src')
-rw-r--r-- | statsd/src/guardrail/StatsdStats.cpp | 63 | ||||
-rw-r--r-- | statsd/src/guardrail/StatsdStats.h | 7 | ||||
-rw-r--r-- | statsd/src/socket/StatsSocketListener.cpp | 64 | ||||
-rw-r--r-- | statsd/src/stats_log.proto | 11 |
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 { |