xref: /aosp_15_r20/external/cronet/net/log/net_log.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2012 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/log/net_log.h"
6 
7 #include "base/check_op.h"
8 #include "base/containers/contains.h"
9 #include "base/no_destructor.h"
10 #include "base/notreached.h"
11 #include "base/ranges/algorithm.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "base/values.h"
14 #include "net/log/net_log_values.h"
15 
16 namespace net {
17 
18 NetLog::ThreadSafeObserver::ThreadSafeObserver() = default;
19 
~ThreadSafeObserver()20 NetLog::ThreadSafeObserver::~ThreadSafeObserver() {
21   // Make sure we aren't watching a NetLog on destruction.  Because the NetLog
22   // may pass events to each observer on multiple threads, we cannot safely
23   // stop watching a NetLog automatically from a parent class.
24   DCHECK(!net_log_);
25 }
26 
capture_mode() const27 NetLogCaptureMode NetLog::ThreadSafeObserver::capture_mode() const {
28   DCHECK(net_log_);
29   return capture_mode_;
30 }
31 
net_log() const32 NetLog* NetLog::ThreadSafeObserver::net_log() const {
33   return net_log_;
34 }
35 
36 NetLog::ThreadSafeCaptureModeObserver::ThreadSafeCaptureModeObserver() =
37     default;
38 NetLog::ThreadSafeCaptureModeObserver::~ThreadSafeCaptureModeObserver() =
39     default;
40 
41 NetLogCaptureModeSet
GetObserverCaptureModes() const42 NetLog::ThreadSafeCaptureModeObserver::GetObserverCaptureModes() const {
43   DCHECK(net_log_);
44   return net_log_->GetObserverCaptureModes();
45 }
46 
47 void NetLog::ThreadSafeCaptureModeObserver::
AddEntryAtTimeWithMaterializedParams(NetLogEventType type,const NetLogSource & source,NetLogEventPhase phase,base::TimeTicks time,base::Value::Dict params)48     AddEntryAtTimeWithMaterializedParams(NetLogEventType type,
49                                          const NetLogSource& source,
50                                          NetLogEventPhase phase,
51                                          base::TimeTicks time,
52                                          base::Value::Dict params) {
53   DCHECK(net_log_);
54   net_log_->AddEntryAtTimeWithMaterializedParams(type, source, phase, time,
55                                                  std::move(params));
56 }
57 
58 // static
Get()59 NetLog* NetLog::Get() {
60   static base::NoDestructor<NetLog> instance{base::PassKey<NetLog>()};
61   return instance.get();
62 }
63 
NetLog(base::PassKey<NetLog>)64 NetLog::NetLog(base::PassKey<NetLog>) {}
NetLog(base::PassKey<NetLogWithSource>)65 NetLog::NetLog(base::PassKey<NetLogWithSource>) {}
66 
AddEntry(NetLogEventType type,const NetLogSource & source,NetLogEventPhase phase)67 void NetLog::AddEntry(NetLogEventType type,
68                       const NetLogSource& source,
69                       NetLogEventPhase phase) {
70   AddEntry(type, source, phase, [] { return base::Value::Dict(); });
71 }
72 
AddGlobalEntry(NetLogEventType type)73 void NetLog::AddGlobalEntry(NetLogEventType type) {
74   AddEntry(type, NetLogSource(NetLogSourceType::NONE, NextID()),
75            NetLogEventPhase::NONE);
76 }
77 
AddGlobalEntryWithStringParams(NetLogEventType type,std::string_view name,std::string_view value)78 void NetLog::AddGlobalEntryWithStringParams(NetLogEventType type,
79                                             std::string_view name,
80                                             std::string_view value) {
81   AddGlobalEntry(type, [&] { return NetLogParamsWithString(name, value); });
82 }
83 
NextID()84 uint32_t NetLog::NextID() {
85   return base::subtle::NoBarrier_AtomicIncrement(&last_id_, 1);
86 }
87 
AddObserver(NetLog::ThreadSafeObserver * observer,NetLogCaptureMode capture_mode)88 void NetLog::AddObserver(NetLog::ThreadSafeObserver* observer,
89                          NetLogCaptureMode capture_mode) {
90   base::AutoLock lock(lock_);
91 
92   DCHECK(!observer->net_log_);
93   DCHECK(!HasObserver(observer));
94   DCHECK_LT(observers_.size(), 20u);  // Performance sanity check.
95 
96   observers_.push_back(observer);
97 
98   observer->net_log_ = this;
99   observer->capture_mode_ = capture_mode;
100   UpdateObserverCaptureModes();
101 }
102 
RemoveObserver(NetLog::ThreadSafeObserver * observer)103 void NetLog::RemoveObserver(NetLog::ThreadSafeObserver* observer) {
104   base::AutoLock lock(lock_);
105 
106   DCHECK_EQ(this, observer->net_log_);
107 
108   auto it = base::ranges::find(observers_, observer);
109   DCHECK(it != observers_.end());
110   observers_.erase(it);
111 
112   observer->net_log_ = nullptr;
113   observer->capture_mode_ = NetLogCaptureMode::kDefault;
114   UpdateObserverCaptureModes();
115 }
116 
AddCaptureModeObserver(NetLog::ThreadSafeCaptureModeObserver * observer)117 void NetLog::AddCaptureModeObserver(
118     NetLog::ThreadSafeCaptureModeObserver* observer) {
119   base::AutoLock lock(lock_);
120 
121   DCHECK(!observer->net_log_);
122   DCHECK(!HasCaptureModeObserver(observer));
123   DCHECK_LT(capture_mode_observers_.size(), 20u);  // Performance sanity check.
124 
125   observer->net_log_ = this;
126   capture_mode_observers_.push_back(observer);
127 }
128 
RemoveCaptureModeObserver(NetLog::ThreadSafeCaptureModeObserver * observer)129 void NetLog::RemoveCaptureModeObserver(
130     NetLog::ThreadSafeCaptureModeObserver* observer) {
131   base::AutoLock lock(lock_);
132 
133   DCHECK_EQ(this, observer->net_log_);
134   DCHECK(HasCaptureModeObserver(observer));
135 
136   auto it = base::ranges::find(capture_mode_observers_, observer);
137   DCHECK(it != capture_mode_observers_.end());
138   capture_mode_observers_.erase(it);
139 
140   observer->net_log_ = nullptr;
141 }
142 
UpdateObserverCaptureModes()143 void NetLog::UpdateObserverCaptureModes() {
144   lock_.AssertAcquired();
145 
146   NetLogCaptureModeSet capture_mode_set = 0;
147   for (const net::NetLog::ThreadSafeObserver* observer : observers_) {
148     NetLogCaptureModeSetAdd(observer->capture_mode_, &capture_mode_set);
149   }
150 
151   base::subtle::NoBarrier_Store(&observer_capture_modes_, capture_mode_set);
152 
153   // Notify any capture mode observers with the new |capture_mode_set|.
154   for (net::NetLog::ThreadSafeCaptureModeObserver* capture_mode_observer :
155        capture_mode_observers_) {
156     capture_mode_observer->OnCaptureModeUpdated(capture_mode_set);
157   }
158 }
159 
HasObserver(ThreadSafeObserver * observer)160 bool NetLog::HasObserver(ThreadSafeObserver* observer) {
161   lock_.AssertAcquired();
162   return base::Contains(observers_, observer);
163 }
164 
HasCaptureModeObserver(ThreadSafeCaptureModeObserver * observer)165 bool NetLog::HasCaptureModeObserver(ThreadSafeCaptureModeObserver* observer) {
166   lock_.AssertAcquired();
167   return base::Contains(capture_mode_observers_, observer);
168 }
169 
170 // static
TickCountToString(const base::TimeTicks & time)171 std::string NetLog::TickCountToString(const base::TimeTicks& time) {
172   int64_t delta_time = time.since_origin().InMilliseconds();
173   // TODO(https://crbug.com/915391): Use NetLogNumberValue().
174   return base::NumberToString(delta_time);
175 }
176 
177 // static
TimeToString(const base::Time & time)178 std::string NetLog::TimeToString(const base::Time& time) {
179   // Convert the base::Time to its (approximate) equivalent in base::TimeTicks.
180   base::TimeTicks time_ticks =
181       base::TimeTicks::UnixEpoch() + (time - base::Time::UnixEpoch());
182   return TickCountToString(time_ticks);
183 }
184 
185 // static
GetEventTypesAsValue()186 base::Value NetLog::GetEventTypesAsValue() {
187   base::Value::Dict dict;
188   for (int i = 0; i < static_cast<int>(NetLogEventType::COUNT); ++i) {
189     dict.Set(NetLogEventTypeToString(static_cast<NetLogEventType>(i)), i);
190   }
191   return base::Value(std::move(dict));
192 }
193 
194 // static
SourceTypeToString(NetLogSourceType source)195 const char* NetLog::SourceTypeToString(NetLogSourceType source) {
196   switch (source) {
197 #define SOURCE_TYPE(label)      \
198   case NetLogSourceType::label: \
199     return #label;
200 #include "net/log/net_log_source_type_list.h"
201 #undef SOURCE_TYPE
202     default:
203       NOTREACHED();
204       return nullptr;
205   }
206 }
207 
208 // static
GetSourceTypesAsValue()209 base::Value NetLog::GetSourceTypesAsValue() {
210   base::Value::Dict dict;
211   for (int i = 0; i < static_cast<int>(NetLogSourceType::COUNT); ++i) {
212     dict.Set(SourceTypeToString(static_cast<NetLogSourceType>(i)), i);
213   }
214   return base::Value(std::move(dict));
215 }
216 
217 // static
EventPhaseToString(NetLogEventPhase phase)218 const char* NetLog::EventPhaseToString(NetLogEventPhase phase) {
219   switch (phase) {
220     case NetLogEventPhase::BEGIN:
221       return "PHASE_BEGIN";
222     case NetLogEventPhase::END:
223       return "PHASE_END";
224     case NetLogEventPhase::NONE:
225       return "PHASE_NONE";
226   }
227   NOTREACHED();
228   return nullptr;
229 }
230 
InitializeSourceIdPartition()231 void NetLog::InitializeSourceIdPartition() {
232   int32_t old_value = base::subtle::NoBarrier_AtomicExchange(
233       &last_id_, std::numeric_limits<base::subtle::Atomic32>::min());
234   DCHECK_EQ(old_value, 0) << " NetLog::InitializeSourceIdPartition() called "
235                              "after NextID() or called multiple times";
236 }
237 
AddEntryInternal(NetLogEventType type,const NetLogSource & source,NetLogEventPhase phase,const GetParamsInterface * get_params)238 void NetLog::AddEntryInternal(NetLogEventType type,
239                               const NetLogSource& source,
240                               NetLogEventPhase phase,
241                               const GetParamsInterface* get_params) {
242   NetLogCaptureModeSet observer_capture_modes = GetObserverCaptureModes();
243 
244   for (int i = 0; i <= static_cast<int>(NetLogCaptureMode::kLast); ++i) {
245     NetLogCaptureMode capture_mode = static_cast<NetLogCaptureMode>(i);
246     if (!NetLogCaptureModeSetContains(capture_mode, observer_capture_modes))
247       continue;
248 
249     NetLogEntry entry(type, source, phase, base::TimeTicks::Now(),
250                       get_params->GetParams(capture_mode));
251 
252     // Notify all of the log observers with |capture_mode|.
253     base::AutoLock lock(lock_);
254     for (net::NetLog::ThreadSafeObserver* observer : observers_) {
255       if (observer->capture_mode() == capture_mode)
256         observer->OnAddEntry(entry);
257     }
258   }
259 }
260 
AddEntryWithMaterializedParams(NetLogEventType type,const NetLogSource & source,NetLogEventPhase phase,base::Value::Dict params)261 void NetLog::AddEntryWithMaterializedParams(NetLogEventType type,
262                                             const NetLogSource& source,
263                                             NetLogEventPhase phase,
264                                             base::Value::Dict params) {
265   AddEntryAtTimeWithMaterializedParams(
266       type, source, phase, base::TimeTicks::Now(), std::move(params));
267 }
268 
AddEntryAtTimeWithMaterializedParams(NetLogEventType type,const NetLogSource & source,NetLogEventPhase phase,base::TimeTicks time,base::Value::Dict params)269 void NetLog::AddEntryAtTimeWithMaterializedParams(NetLogEventType type,
270                                                   const NetLogSource& source,
271                                                   NetLogEventPhase phase,
272                                                   base::TimeTicks time,
273                                                   base::Value::Dict params) {
274   NetLogEntry entry(type, source, phase, time, std::move(params));
275 
276   // Notify all of the log observers, regardless of capture mode.
277   base::AutoLock lock(lock_);
278   for (net::NetLog::ThreadSafeObserver* observer : observers_) {
279     observer->OnAddEntry(entry);
280   }
281 }
282 
283 }  // namespace net
284