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:

committed by
Commit Bot

parent
6031e69d34
commit
c0e9725916
@ -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.
|
||||||
|
@ -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(
|
||||||
|
@ -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
|
||||||
|
Reference in New Issue
Block a user