Add API to report "interesting" usage patterns to PC client

Bug: chromium:866792
Change-Id: Ic8bec5494aaa617c833c90be2b912f7367b44929
Reviewed-on: https://webrtc-review.googlesource.com/90246
Commit-Queue: Harald Alvestrand <hta@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#24111}
This commit is contained in:
Harald Alvestrand
2018-07-26 10:39:55 +02:00
committed by Commit Bot
parent 6031e69d34
commit c0e9725916
3 changed files with 94 additions and 35 deletions

View File

@ -1098,6 +1098,14 @@ class PeerConnectionObserver {
// TODO(hbos,deadbeef): Make pure virtual when all subclasses implement it. // TODO(hbos,deadbeef): Make pure virtual when all subclasses implement it.
virtual void OnRemoveTrack( virtual void OnRemoveTrack(
rtc::scoped_refptr<RtpReceiverInterface> receiver) {} rtc::scoped_refptr<RtpReceiverInterface> receiver) {}
// Called when an interesting usage is detected by WebRTC.
// An appropriate action is to add information about the context of the
// PeerConnection and write the event to some kind of "interesting events"
// log function.
// The heuristics for defining what constitutes "interesting" are
// implementation-defined.
virtual void OnInterestingUsage(int usage_pattern) {}
}; };
// PeerConnectionDependencies holds all of PeerConnections dependencies. // PeerConnectionDependencies holds all of PeerConnections dependencies.

View File

@ -5948,6 +5948,17 @@ void PeerConnection::ReportUsagePattern() const {
RTC_HISTOGRAM_ENUMERATION_SPARSE("WebRTC.PeerConnection.UsagePattern", RTC_HISTOGRAM_ENUMERATION_SPARSE("WebRTC.PeerConnection.UsagePattern",
usage_event_accumulator_, usage_event_accumulator_,
static_cast<int>(UsageEvent::MAX_VALUE)); static_cast<int>(UsageEvent::MAX_VALUE));
const int bad_bits =
static_cast<int>(UsageEvent::SET_LOCAL_DESCRIPTION_CALLED) |
static_cast<int>(UsageEvent::CANDIDATE_COLLECTED);
const int good_bits =
static_cast<int>(UsageEvent::SET_REMOTE_DESCRIPTION_CALLED) |
static_cast<int>(UsageEvent::REMOTE_CANDIDATE_ADDED) |
static_cast<int>(UsageEvent::ICE_STATE_CONNECTED);
if ((usage_event_accumulator_ & bad_bits) == bad_bits &&
(usage_event_accumulator_ & good_bits) == 0) {
observer_->OnInterestingUsage(usage_event_accumulator_);
}
} }
void PeerConnection::ReportNegotiatedSdpSemantics( void PeerConnection::ReportNegotiatedSdpSemantics(

View File

@ -32,6 +32,7 @@ using RTCConfiguration = PeerConnectionInterface::RTCConfiguration;
using RTCOfferAnswerOptions = PeerConnectionInterface::RTCOfferAnswerOptions; using RTCOfferAnswerOptions = PeerConnectionInterface::RTCOfferAnswerOptions;
using ::testing::Values; using ::testing::Values;
static const char kUsagePatternMetric[] = "WebRTC.PeerConnection.UsagePattern";
static constexpr int kDefaultTimeout = 10000; static constexpr int kDefaultTimeout = 10000;
static const rtc::SocketAddress kDefaultLocalAddress("1.1.1.1", 0); static const rtc::SocketAddress kDefaultLocalAddress("1.1.1.1", 0);
static const rtc::SocketAddress kPrivateLocalAddress("10.1.1.1", 0); static const rtc::SocketAddress kPrivateLocalAddress("10.1.1.1", 0);
@ -75,12 +76,23 @@ typedef PeerConnectionWrapperForUsageHistogramTest* RawWrapperPtr;
class ObserverForUsageHistogramTest : public MockPeerConnectionObserver { class ObserverForUsageHistogramTest : public MockPeerConnectionObserver {
public: public:
void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) override; void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) override;
void OnInterestingUsage(int usage_pattern) override {
interesting_usage_detected_ = usage_pattern;
}
void PrepareToExchangeCandidates(RawWrapperPtr other) { void PrepareToExchangeCandidates(RawWrapperPtr other) {
candidate_target_ = other; candidate_target_ = other;
} }
bool HaveDataChannel() { return last_datachannel_; } bool HaveDataChannel() { return last_datachannel_; }
absl::optional<int> interesting_usage_detected() {
return interesting_usage_detected_;
}
private: private:
absl::optional<int> interesting_usage_detected_;
RawWrapperPtr candidate_target_; // Note: Not thread-safe against deletions. RawWrapperPtr candidate_target_; // Note: Not thread-safe against deletions.
}; };
@ -96,12 +108,16 @@ class PeerConnectionWrapperForUsageHistogramTest
return static_cast<PeerConnection*>(pci->internal()); return static_cast<PeerConnection*>(pci->internal());
} }
// Override with different return type
ObserverForUsageHistogramTest* observer() {
return static_cast<ObserverForUsageHistogramTest*>(
PeerConnectionWrapper::observer());
}
void PrepareToExchangeCandidates( void PrepareToExchangeCandidates(
PeerConnectionWrapperForUsageHistogramTest* other) { PeerConnectionWrapperForUsageHistogramTest* other) {
static_cast<ObserverForUsageHistogramTest*>(observer()) observer()->PrepareToExchangeCandidates(other);
->PrepareToExchangeCandidates(other); other->observer()->PrepareToExchangeCandidates(this);
static_cast<ObserverForUsageHistogramTest*>(other->observer())
->PrepareToExchangeCandidates(this);
} }
bool IsConnected() { bool IsConnected() {
@ -237,6 +253,13 @@ class PeerConnectionUsageHistogramTest : public ::testing::Test {
return wrapper; return wrapper;
} }
int ObservedFingerprint() {
// This works correctly only if there is only one sample value
// that has been counted.
// Returns -1 for "not found".
return webrtc::metrics::MinSample(kUsagePatternMetric);
}
std::unique_ptr<rtc::FakeNetworkManager> fake_network_manager_; std::unique_ptr<rtc::FakeNetworkManager> fake_network_manager_;
std::unique_ptr<rtc::VirtualSocketServer> vss_; std::unique_ptr<rtc::VirtualSocketServer> vss_;
rtc::AutoSocketServerThread main_; rtc::AutoSocketServerThread main_;
@ -246,11 +269,10 @@ TEST_F(PeerConnectionUsageHistogramTest, UsageFingerprintHistogramFromTimeout) {
auto pc = CreatePeerConnectionWithImmediateReport(); auto pc = CreatePeerConnectionWithImmediateReport();
int expected_fingerprint = MakeUsageFingerprint({}); int expected_fingerprint = MakeUsageFingerprint({});
ASSERT_TRUE_WAIT( ASSERT_EQ_WAIT(1, webrtc::metrics::NumSamples(kUsagePatternMetric),
1u == webrtc::metrics::NumSamples("WebRTC.PeerConnection.UsagePattern"),
kDefaultTimeout); kDefaultTimeout);
EXPECT_EQ(1, webrtc::metrics::NumEvents("WebRTC.PeerConnection.UsagePattern", EXPECT_EQ(
expected_fingerprint)); 1, webrtc::metrics::NumEvents(kUsagePatternMetric, expected_fingerprint));
} }
#ifndef WEBRTC_ANDROID #ifndef WEBRTC_ANDROID
@ -277,13 +299,12 @@ TEST_F(PeerConnectionUsageHistogramTest, FingerprintAudioVideo) {
PeerConnection::UsageEvent::CLOSE_CALLED}); PeerConnection::UsageEvent::CLOSE_CALLED});
// In this case, we may or may not have PRIVATE_CANDIDATE_COLLECTED, // In this case, we may or may not have PRIVATE_CANDIDATE_COLLECTED,
// depending on the machine configuration. // depending on the machine configuration.
EXPECT_EQ(2, EXPECT_EQ(2, webrtc::metrics::NumSamples(kUsagePatternMetric));
webrtc::metrics::NumSamples("WebRTC.PeerConnection.UsagePattern"));
EXPECT_TRUE( EXPECT_TRUE(
webrtc::metrics::NumEvents("WebRTC.PeerConnection.UsagePattern", webrtc::metrics::NumEvents(kUsagePatternMetric, expected_fingerprint) ==
expected_fingerprint) == 2 || 2 ||
webrtc::metrics::NumEvents( webrtc::metrics::NumEvents(
"WebRTC.PeerConnection.UsagePattern", kUsagePatternMetric,
expected_fingerprint | expected_fingerprint |
static_cast<int>( static_cast<int>(
PeerConnection::UsageEvent::PRIVATE_CANDIDATE_COLLECTED)) == PeerConnection::UsageEvent::PRIVATE_CANDIDATE_COLLECTED)) ==
@ -315,10 +336,9 @@ TEST_F(PeerConnectionUsageHistogramTest, FingerprintWithNoHostCandidates) {
PeerConnection::UsageEvent::REMOTE_CANDIDATE_ADDED, PeerConnection::UsageEvent::REMOTE_CANDIDATE_ADDED,
PeerConnection::UsageEvent::ICE_STATE_CONNECTED, PeerConnection::UsageEvent::ICE_STATE_CONNECTED,
PeerConnection::UsageEvent::CLOSE_CALLED}); PeerConnection::UsageEvent::CLOSE_CALLED});
EXPECT_EQ(2, EXPECT_EQ(2, webrtc::metrics::NumSamples(kUsagePatternMetric));
webrtc::metrics::NumSamples("WebRTC.PeerConnection.UsagePattern")); EXPECT_EQ(
EXPECT_EQ(2, webrtc::metrics::NumEvents("WebRTC.PeerConnection.UsagePattern", 2, webrtc::metrics::NumEvents(kUsagePatternMetric, expected_fingerprint));
expected_fingerprint));
} }
#ifdef HAVE_SCTP #ifdef HAVE_SCTP
@ -338,13 +358,12 @@ TEST_F(PeerConnectionUsageHistogramTest, FingerprintDataOnly) {
PeerConnection::UsageEvent::REMOTE_CANDIDATE_ADDED, PeerConnection::UsageEvent::REMOTE_CANDIDATE_ADDED,
PeerConnection::UsageEvent::ICE_STATE_CONNECTED, PeerConnection::UsageEvent::ICE_STATE_CONNECTED,
PeerConnection::UsageEvent::CLOSE_CALLED}); PeerConnection::UsageEvent::CLOSE_CALLED});
EXPECT_EQ(2, EXPECT_EQ(2, webrtc::metrics::NumSamples(kUsagePatternMetric));
webrtc::metrics::NumSamples("WebRTC.PeerConnection.UsagePattern"));
EXPECT_TRUE( EXPECT_TRUE(
webrtc::metrics::NumEvents("WebRTC.PeerConnection.UsagePattern", webrtc::metrics::NumEvents(kUsagePatternMetric, expected_fingerprint) ==
expected_fingerprint) == 2 || 2 ||
webrtc::metrics::NumEvents( webrtc::metrics::NumEvents(
"WebRTC.PeerConnection.UsagePattern", kUsagePatternMetric,
expected_fingerprint | expected_fingerprint |
static_cast<int>( static_cast<int>(
PeerConnection::UsageEvent::PRIVATE_CANDIDATE_COLLECTED)) == PeerConnection::UsageEvent::PRIVATE_CANDIDATE_COLLECTED)) ==
@ -369,10 +388,9 @@ TEST_F(PeerConnectionUsageHistogramTest, FingerprintStunTurn) {
MakeUsageFingerprint({PeerConnection::UsageEvent::STUN_SERVER_ADDED, MakeUsageFingerprint({PeerConnection::UsageEvent::STUN_SERVER_ADDED,
PeerConnection::UsageEvent::TURN_SERVER_ADDED, PeerConnection::UsageEvent::TURN_SERVER_ADDED,
PeerConnection::UsageEvent::CLOSE_CALLED}); PeerConnection::UsageEvent::CLOSE_CALLED});
EXPECT_EQ(1, EXPECT_EQ(1, webrtc::metrics::NumSamples(kUsagePatternMetric));
webrtc::metrics::NumSamples("WebRTC.PeerConnection.UsagePattern")); EXPECT_EQ(
EXPECT_EQ(1, webrtc::metrics::NumEvents("WebRTC.PeerConnection.UsagePattern", 1, webrtc::metrics::NumEvents(kUsagePatternMetric, expected_fingerprint));
expected_fingerprint));
} }
TEST_F(PeerConnectionUsageHistogramTest, FingerprintStunTurnInReconfiguration) { TEST_F(PeerConnectionUsageHistogramTest, FingerprintStunTurnInReconfiguration) {
@ -394,10 +412,9 @@ TEST_F(PeerConnectionUsageHistogramTest, FingerprintStunTurnInReconfiguration) {
MakeUsageFingerprint({PeerConnection::UsageEvent::STUN_SERVER_ADDED, MakeUsageFingerprint({PeerConnection::UsageEvent::STUN_SERVER_ADDED,
PeerConnection::UsageEvent::TURN_SERVER_ADDED, PeerConnection::UsageEvent::TURN_SERVER_ADDED,
PeerConnection::UsageEvent::CLOSE_CALLED}); PeerConnection::UsageEvent::CLOSE_CALLED});
EXPECT_EQ(1, EXPECT_EQ(1, webrtc::metrics::NumSamples(kUsagePatternMetric));
webrtc::metrics::NumSamples("WebRTC.PeerConnection.UsagePattern")); EXPECT_EQ(
EXPECT_EQ(1, webrtc::metrics::NumEvents("WebRTC.PeerConnection.UsagePattern", 1, webrtc::metrics::NumEvents(kUsagePatternMetric, expected_fingerprint));
expected_fingerprint));
} }
TEST_F(PeerConnectionUsageHistogramTest, FingerprintWithPrivateIP) { TEST_F(PeerConnectionUsageHistogramTest, FingerprintWithPrivateIP) {
@ -411,10 +428,33 @@ TEST_F(PeerConnectionUsageHistogramTest, FingerprintWithPrivateIP) {
PeerConnection::UsageEvent::CANDIDATE_COLLECTED, PeerConnection::UsageEvent::CANDIDATE_COLLECTED,
PeerConnection::UsageEvent::CLOSE_CALLED, PeerConnection::UsageEvent::CLOSE_CALLED,
PeerConnection::UsageEvent::PRIVATE_CANDIDATE_COLLECTED}); PeerConnection::UsageEvent::PRIVATE_CANDIDATE_COLLECTED});
EXPECT_EQ(1, EXPECT_EQ(1, webrtc::metrics::NumSamples(kUsagePatternMetric));
webrtc::metrics::NumSamples("WebRTC.PeerConnection.UsagePattern")); EXPECT_EQ(
EXPECT_EQ(1, webrtc::metrics::NumEvents("WebRTC.PeerConnection.UsagePattern", 1, webrtc::metrics::NumEvents(kUsagePatternMetric, expected_fingerprint));
expected_fingerprint));
} }
#ifndef WEBRTC_ANDROID
#ifdef HAVE_SCTP
TEST_F(PeerConnectionUsageHistogramTest, NotableUsageNoted) {
auto caller = CreatePeerConnection();
caller->CreateDataChannel("foo");
caller->GenerateOfferAndCollectCandidates();
caller->pc()->Close();
int expected_fingerprint = MakeUsageFingerprint(
{PeerConnection::UsageEvent::DATA_ADDED,
PeerConnection::UsageEvent::SET_LOCAL_DESCRIPTION_CALLED,
PeerConnection::UsageEvent::CANDIDATE_COLLECTED,
PeerConnection::UsageEvent::CLOSE_CALLED});
EXPECT_EQ(1, webrtc::metrics::NumSamples(kUsagePatternMetric));
EXPECT_TRUE(expected_fingerprint == ObservedFingerprint() ||
(expected_fingerprint |
static_cast<int>(
PeerConnection::UsageEvent::PRIVATE_CANDIDATE_COLLECTED)) ==
ObservedFingerprint());
EXPECT_EQ(absl::make_optional(ObservedFingerprint()),
caller->observer()->interesting_usage_detected());
}
#endif
#endif
} // namespace webrtc } // namespace webrtc