shill: mac80211_monitor: add metrics
Add metrics reporting, so that we know how often the mac80211
TX queues are getting stuck.
BUG=chromium:392209
TEST=unit tests
Change-Id: I56874da399ec47a19bc1ba3a3796b0a922da2ce6
Reviewed-on: https://chromium-review.googlesource.com/211707
Reviewed-by: Paul Stewart <pstew@chromium.org>
Tested-by: mukesh agrawal <quiche@chromium.org>
diff --git a/mac80211_monitor.cc b/mac80211_monitor.cc
index 8ef4609..b430018 100644
--- a/mac80211_monitor.cc
+++ b/mac80211_monitor.cc
@@ -10,6 +10,7 @@
#include <base/strings/string_split.h>
#include "shill/logging.h"
+#include "shill/metrics.h"
namespace shill {
@@ -22,9 +23,11 @@
const size_t Mac80211Monitor::kMaxQueueStateSizeBytes = 2048;
Mac80211Monitor::Mac80211Monitor(
- const string &link_name, size_t queue_length_limit)
+ const string &link_name, size_t queue_length_limit, Metrics *metrics)
: link_name_(link_name),
- queue_length_limit_(queue_length_limit) {
+ queue_length_limit_(queue_length_limit),
+ metrics_(metrics) {
+ CHECK(metrics_);
}
Mac80211Monitor::~Mac80211Monitor() {
@@ -60,9 +63,17 @@
for (unsigned int i=0; i < kStopReasonMax; ++i) {
auto stop_reason = static_cast<QueueStopReason>(i);
if (stuck_flags & GetFlagForReason(stop_reason)) {
- // TODO(quiche): report stop reason to UMA
+ metrics_->SendEnumToUMA(Metrics::kMetricWifiStoppedTxQueueReason,
+ stop_reason,
+ kStopReasonMax);
}
}
+
+ metrics_->SendToUMA(Metrics::kMetricWifiStoppedTxQueueLength,
+ max_stuck_queue_len,
+ Metrics::kMetricWifiStoppedTxQueueLengthMin,
+ Metrics::kMetricWifiStoppedTxQueueLengthMax,
+ Metrics::kMetricWifiStoppedTxQueueLengthNumBuckets);
}
return stuck_flags;
diff --git a/mac80211_monitor.h b/mac80211_monitor.h
index 5f5e053..0762f20 100644
--- a/mac80211_monitor.h
+++ b/mac80211_monitor.h
@@ -13,6 +13,8 @@
namespace shill {
+class Metrics;
+
class Mac80211Monitor {
public:
struct QueueState {
@@ -27,7 +29,8 @@
size_t queue_length;
};
- Mac80211Monitor(const std::string &link_name, size_t queue_length_limit);
+ Mac80211Monitor(const std::string &link_name, size_t queue_length_limit,
+ Metrics *metrics);
virtual ~Mac80211Monitor();
private:
@@ -36,6 +39,8 @@
FRIEND_TEST(Mac80211MonitorTest, CheckAreQueuesStuckMultipleQueues);
FRIEND_TEST(Mac80211MonitorTest, CheckAreQueuesStuckNotStuck);
FRIEND_TEST(Mac80211MonitorTest, CheckAreQueuesStuckQueueLength);
+ FRIEND_TEST(Mac80211MonitorTest,
+ CheckAreQueuesStuckQueueLengthIgnoresUnstopped);
FRIEND_TEST(Mac80211MonitorTest, CheckAreQueuesStuckSingleReason);
FRIEND_TEST(Mac80211MonitorTest, ParseQueueStateBadInput);
FRIEND_TEST(Mac80211MonitorTest, ParseQueueStateSimple);
@@ -76,6 +81,7 @@
const std::string link_name_;
size_t queue_length_limit_;
+ Metrics *metrics_;
DISALLOW_COPY_AND_ASSIGN(Mac80211Monitor);
};
diff --git a/mac80211_monitor_unittest.cc b/mac80211_monitor_unittest.cc
index 043692a..98dca4f 100644
--- a/mac80211_monitor_unittest.cc
+++ b/mac80211_monitor_unittest.cc
@@ -9,8 +9,11 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
+#include "shill/mock_metrics.h"
+
using std::vector;
using ::testing::ElementsAre;
+using ::testing::StrictMock;
namespace shill {
@@ -23,17 +26,20 @@
class Mac80211MonitorTest : public testing::Test {
public:
Mac80211MonitorTest()
- : mac80211_monitor_(kTestDeviceName, kQueueLengthLimit) {}
+ : metrics_(nullptr),
+ mac80211_monitor_(kTestDeviceName, kQueueLengthLimit, &metrics_) {}
virtual ~Mac80211MonitorTest() {}
protected:
static const size_t kQueueLengthLimit = 5;
+ MockMetrics &metrics() { return metrics_; }
uint32_t CheckAreQueuesStuck(const vector<QState> &queue_states) {
return mac80211_monitor_.CheckAreQueuesStuck(queue_states);
}
private:
+ StrictMock<MockMetrics> metrics_;
Mac80211Monitor mac80211_monitor_;
};
@@ -165,6 +171,20 @@
}
TEST_F(Mac80211MonitorTest, CheckAreQueuesStuckSingleReason) {
+ EXPECT_CALL(metrics(), SendEnumToUMA(
+ Metrics::kMetricWifiStoppedTxQueueReason,
+ Mac80211Monitor::kStopReasonDriver,
+ Mac80211Monitor::kStopReasonMax));
+ EXPECT_CALL(metrics(), SendEnumToUMA(
+ Metrics::kMetricWifiStoppedTxQueueReason,
+ Mac80211Monitor::kStopReasonPowerSave,
+ Mac80211Monitor::kStopReasonMax));
+ EXPECT_CALL(metrics(), SendToUMA(
+ Metrics::kMetricWifiStoppedTxQueueLength,
+ kQueueLengthLimit,
+ Metrics::kMetricWifiStoppedTxQueueLengthMin,
+ Metrics::kMetricWifiStoppedTxQueueLengthMax,
+ Metrics::kMetricWifiStoppedTxQueueLengthNumBuckets)).Times(2);
EXPECT_EQ(Mac80211Monitor::kStopFlagDriver,
CheckAreQueuesStuck({
QState(0, Mac80211Monitor::kStopFlagDriver, kQueueLengthLimit)}));
@@ -174,6 +194,24 @@
}
TEST_F(Mac80211MonitorTest, CheckAreQueuesStuckMultipleReasons) {
+ EXPECT_CALL(metrics(), SendEnumToUMA(
+ Metrics::kMetricWifiStoppedTxQueueReason,
+ Mac80211Monitor::kStopReasonPowerSave,
+ Mac80211Monitor::kStopReasonMax)).Times(2);
+ EXPECT_CALL(metrics(), SendEnumToUMA(
+ Metrics::kMetricWifiStoppedTxQueueReason,
+ Mac80211Monitor::kStopReasonDriver,
+ Mac80211Monitor::kStopReasonMax)).Times(2);
+ EXPECT_CALL(metrics(), SendEnumToUMA(
+ Metrics::kMetricWifiStoppedTxQueueReason,
+ Mac80211Monitor::kStopReasonChannelSwitch,
+ Mac80211Monitor::kStopReasonMax)).Times(2);
+ EXPECT_CALL(metrics(), SendToUMA(
+ Metrics::kMetricWifiStoppedTxQueueLength,
+ kQueueLengthLimit,
+ Metrics::kMetricWifiStoppedTxQueueLengthMin,
+ Metrics::kMetricWifiStoppedTxQueueLengthMax,
+ Metrics::kMetricWifiStoppedTxQueueLengthNumBuckets)).Times(3);
EXPECT_EQ(Mac80211Monitor::kStopFlagDriver |
Mac80211Monitor::kStopFlagPowerSave,
CheckAreQueuesStuck({
@@ -198,6 +236,20 @@
}
TEST_F(Mac80211MonitorTest, CheckAreQueuesStuckMultipleQueues) {
+ EXPECT_CALL(metrics(), SendEnumToUMA(
+ Metrics::kMetricWifiStoppedTxQueueReason,
+ Mac80211Monitor::kStopReasonPowerSave,
+ Mac80211Monitor::kStopReasonMax)).Times(5);
+ EXPECT_CALL(metrics(), SendEnumToUMA(
+ Metrics::kMetricWifiStoppedTxQueueReason,
+ Mac80211Monitor::kStopReasonDriver,
+ Mac80211Monitor::kStopReasonMax)).Times(2);
+ EXPECT_CALL(metrics(), SendToUMA(
+ Metrics::kMetricWifiStoppedTxQueueLength,
+ kQueueLengthLimit,
+ Metrics::kMetricWifiStoppedTxQueueLengthMin,
+ Metrics::kMetricWifiStoppedTxQueueLengthMax,
+ Metrics::kMetricWifiStoppedTxQueueLengthNumBuckets)).Times(5);
EXPECT_EQ(Mac80211Monitor::kStopFlagPowerSave,
CheckAreQueuesStuck({
QState(0, 0, 0),
@@ -237,6 +289,16 @@
}
TEST_F(Mac80211MonitorTest, CheckAreQueuesStuckQueueLength) {
+ EXPECT_CALL(metrics(), SendEnumToUMA(
+ Metrics::kMetricWifiStoppedTxQueueReason,
+ Mac80211Monitor::kStopReasonPowerSave,
+ Mac80211Monitor::kStopReasonMax)).Times(4);
+ EXPECT_CALL(metrics(), SendToUMA(
+ Metrics::kMetricWifiStoppedTxQueueLength,
+ kQueueLengthLimit,
+ Metrics::kMetricWifiStoppedTxQueueLengthMin,
+ Metrics::kMetricWifiStoppedTxQueueLengthMax,
+ Metrics::kMetricWifiStoppedTxQueueLengthNumBuckets)).Times(4);
EXPECT_TRUE(CheckAreQueuesStuck({
QState(0, Mac80211Monitor::kStopFlagPowerSave, kQueueLengthLimit)}));
EXPECT_TRUE(CheckAreQueuesStuck({
@@ -253,4 +315,20 @@
QState(0, Mac80211Monitor::kStopFlagPowerSave, kQueueLengthLimit-2)}));
}
+TEST_F(Mac80211MonitorTest, CheckAreQueuesStuckQueueLengthIgnoresUnstopped) {
+ EXPECT_CALL(metrics(), SendEnumToUMA(
+ Metrics::kMetricWifiStoppedTxQueueReason,
+ Mac80211Monitor::kStopReasonPowerSave,
+ Mac80211Monitor::kStopReasonMax));
+ EXPECT_CALL(metrics(), SendToUMA(
+ Metrics::kMetricWifiStoppedTxQueueLength,
+ kQueueLengthLimit,
+ Metrics::kMetricWifiStoppedTxQueueLengthMin,
+ Metrics::kMetricWifiStoppedTxQueueLengthMax,
+ Metrics::kMetricWifiStoppedTxQueueLengthNumBuckets));
+ EXPECT_TRUE(CheckAreQueuesStuck({
+ QState(0, 0, kQueueLengthLimit * 10),
+ QState(0, Mac80211Monitor::kStopFlagPowerSave, kQueueLengthLimit)}));
+}
+
} // namespace shill
diff --git a/metrics.cc b/metrics.cc
index a46665d..5d0f07b 100644
--- a/metrics.cc
+++ b/metrics.cc
@@ -280,6 +280,18 @@
const int Metrics::kMetricWifiAvailableBSSesMin = 1;
const int Metrics::kMetricWifiAvailableBSSesNumBuckets = 10;
+// static
+const char Metrics::kMetricWifiStoppedTxQueueReason[] =
+ "Network.Shill.WiFi.StoppedTxQueueReason";
+// Values are defined in mac80211_monitor.h.
+
+// static
+const char Metrics::kMetricWifiStoppedTxQueueLength[] =
+ "Network.Shill.WiFi.StoppedTxQueueLength";
+const int Metrics::kMetricWifiStoppedTxQueueLengthMax = 10000;
+const int Metrics::kMetricWifiStoppedTxQueueLengthMin = 1;
+const int Metrics::kMetricWifiStoppedTxQueueLengthNumBuckets = 50;
+
// Number of services associated with currently connected network.
const char Metrics::kMetricServicesOnSameNetwork[] =
"Network.Shill.ServicesOnSameNetwork";
diff --git a/metrics.h b/metrics.h
index 4eac003..2a84b98 100644
--- a/metrics.h
+++ b/metrics.h
@@ -514,6 +514,15 @@
static const int kMetricWifiAvailableBSSesMin;
static const int kMetricWifiAvailableBSSesNumBuckets;
+ // Reason that the mac80211 TX queue is stopped.
+ static const char kMetricWifiStoppedTxQueueReason[];
+
+ // Maximal queue length amongst all stopped mac80211 TX queues.
+ static const char kMetricWifiStoppedTxQueueLength[];
+ static const int kMetricWifiStoppedTxQueueLengthMax;
+ static const int kMetricWifiStoppedTxQueueLengthMin;
+ static const int kMetricWifiStoppedTxQueueLengthNumBuckets;
+
// Number of services associated with currently connected network.
static const char kMetricServicesOnSameNetwork[];
static const int kMetricServicesOnSameNetworkMax;