1 // Copyright 2017 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/nqe/event_creator.h"
6
7 #include <stdlib.h>
8 #include <memory>
9 #include <utility>
10
11 #include "base/functional/bind.h"
12 #include "base/functional/callback.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/values.h"
15 #include "net/log/net_log_capture_mode.h"
16 #include "net/log/net_log_with_source.h"
17
18 namespace net::nqe::internal {
19
20 namespace {
21
NetworkQualityChangedNetLogParams(base::TimeDelta http_rtt,base::TimeDelta transport_rtt,int32_t downstream_throughput_kbps,EffectiveConnectionType effective_connection_type)22 base::Value::Dict NetworkQualityChangedNetLogParams(
23 base::TimeDelta http_rtt,
24 base::TimeDelta transport_rtt,
25 int32_t downstream_throughput_kbps,
26 EffectiveConnectionType effective_connection_type) {
27 base::Value::Dict value;
28 value.Set("http_rtt_ms", static_cast<int>(http_rtt.InMilliseconds()));
29 value.Set("transport_rtt_ms",
30 static_cast<int>(transport_rtt.InMilliseconds()));
31 value.Set("downstream_throughput_kbps", downstream_throughput_kbps);
32 value.Set("effective_connection_type",
33 GetNameForEffectiveConnectionType(effective_connection_type));
34 return value;
35 }
36
MetricChangedMeaningfully(int32_t past_value,int32_t current_value)37 bool MetricChangedMeaningfully(int32_t past_value, int32_t current_value) {
38 if ((past_value == INVALID_RTT_THROUGHPUT) !=
39 (current_value == INVALID_RTT_THROUGHPUT)) {
40 return true;
41 }
42
43 if (past_value == INVALID_RTT_THROUGHPUT &&
44 current_value == INVALID_RTT_THROUGHPUT) {
45 return false;
46 }
47
48 // Create a new entry only if (i) the difference between the two values exceed
49 // the threshold; and, (ii) the ratio of the values also exceeds the
50 // threshold.
51 static const int kMinDifferenceInMetrics = 100;
52 static const float kMinRatio = 1.2f;
53
54 if (std::abs(past_value - current_value) < kMinDifferenceInMetrics) {
55 // The absolute change in the value is not sufficient enough.
56 return false;
57 }
58
59 if (past_value < (kMinRatio * current_value) &&
60 current_value < (kMinRatio * past_value)) {
61 // The relative change in the value is not sufficient enough.
62 return false;
63 }
64
65 return true;
66 }
67
68 } // namespace
69
EventCreator(NetLogWithSource net_log)70 EventCreator::EventCreator(NetLogWithSource net_log) : net_log_(net_log) {}
71
~EventCreator()72 EventCreator::~EventCreator() {
73 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
74 }
75
MaybeAddNetworkQualityChangedEventToNetLog(EffectiveConnectionType effective_connection_type,const NetworkQuality & network_quality)76 void EventCreator::MaybeAddNetworkQualityChangedEventToNetLog(
77 EffectiveConnectionType effective_connection_type,
78 const NetworkQuality& network_quality) {
79 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
80
81 // Check if any of the network quality metrics changed meaningfully.
82 bool effective_connection_type_changed =
83 past_effective_connection_type_ != effective_connection_type;
84 bool http_rtt_changed = MetricChangedMeaningfully(
85 past_network_quality_.http_rtt().InMilliseconds(),
86 network_quality.http_rtt().InMilliseconds());
87
88 bool transport_rtt_changed = MetricChangedMeaningfully(
89 past_network_quality_.transport_rtt().InMilliseconds(),
90 network_quality.transport_rtt().InMilliseconds());
91 bool kbps_changed = MetricChangedMeaningfully(
92 past_network_quality_.downstream_throughput_kbps(),
93 network_quality.downstream_throughput_kbps());
94
95 if (!effective_connection_type_changed && !http_rtt_changed &&
96 !transport_rtt_changed && !kbps_changed) {
97 // Return since none of the metrics changed meaningfully.
98 return;
99 }
100
101 past_effective_connection_type_ = effective_connection_type;
102 past_network_quality_ = network_quality;
103
104 net_log_.AddEvent(NetLogEventType::NETWORK_QUALITY_CHANGED, [&] {
105 return NetworkQualityChangedNetLogParams(
106 network_quality.http_rtt(), network_quality.transport_rtt(),
107 network_quality.downstream_throughput_kbps(),
108 effective_connection_type);
109 });
110 }
111
112 } // namespace net::nqe::internal
113