1 // Copyright 2014 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/trace_net_log_observer.h"
6
7 #include <stdio.h>
8
9 #include <memory>
10 #include <string>
11 #include <utility>
12
13 #include "base/check.h"
14 #include "base/json/json_writer.h"
15 #include "base/values.h"
16 #include "net/base/tracing.h"
17 #include "net/log/net_log_entry.h"
18 #include "net/log/net_log_event_type.h"
19
20 namespace net {
21
22 namespace {
23
24 // TraceLog category for NetLog events.
25 constexpr const char kNetLogTracingCategory[] = "netlog";
26
27 class TracedValue : public base::trace_event::ConvertableToTraceFormat {
28 public:
TracedValue(base::Value::Dict value)29 explicit TracedValue(base::Value::Dict value) : value_(std::move(value)) {}
30 ~TracedValue() override = default;
31
32 private:
AppendAsTraceFormat(std::string * out) const33 void AppendAsTraceFormat(std::string* out) const override {
34 if (!value_.empty()) {
35 std::string tmp;
36 base::JSONWriter::Write(value_, &tmp);
37 *out += tmp;
38 } else {
39 *out += "{}";
40 }
41 }
42
43 private:
44 base::Value::Dict value_;
45 };
46
47 } // namespace
48
49 TraceNetLogObserver::TraceNetLogObserver() = default;
50
~TraceNetLogObserver()51 TraceNetLogObserver::~TraceNetLogObserver() {
52 DCHECK(!net_log_to_watch_);
53 DCHECK(!net_log());
54 }
55
OnAddEntry(const NetLogEntry & entry)56 void TraceNetLogObserver::OnAddEntry(const NetLogEntry& entry) {
57 base::Value::Dict params = entry.params.Clone();
58 switch (entry.phase) {
59 case NetLogEventPhase::BEGIN:
60 TRACE_EVENT_NESTABLE_ASYNC_BEGIN2(
61 kNetLogTracingCategory, NetLogEventTypeToString(entry.type),
62 entry.source.id, "source_type",
63 NetLog::SourceTypeToString(entry.source.type), "params",
64 std::make_unique<TracedValue>(std::move(params)));
65 break;
66 case NetLogEventPhase::END:
67 TRACE_EVENT_NESTABLE_ASYNC_END1(
68 kNetLogTracingCategory, NetLogEventTypeToString(entry.type),
69 entry.source.id, "params",
70 std::make_unique<TracedValue>(std::move(params)));
71 break;
72 case NetLogEventPhase::NONE:
73 TRACE_EVENT_NESTABLE_ASYNC_INSTANT2(
74 kNetLogTracingCategory, NetLogEventTypeToString(entry.type),
75 entry.source.id, "source_type",
76 NetLog::SourceTypeToString(entry.source.type), "params",
77 std::make_unique<TracedValue>(std::move(params)));
78 break;
79 }
80 }
81
WatchForTraceStart(NetLog * netlog)82 void TraceNetLogObserver::WatchForTraceStart(NetLog* netlog) {
83 DCHECK(!net_log_to_watch_);
84 DCHECK(!net_log());
85 net_log_to_watch_ = netlog;
86 // Tracing can start before the observer is even created, for instance for
87 // startup tracing.
88 if (base::trace_event::TraceLog::GetInstance()->IsEnabled())
89 OnTraceLogEnabled();
90 base::trace_event::TraceLog::GetInstance()->AddAsyncEnabledStateObserver(
91 weak_factory_.GetWeakPtr());
92 }
93
StopWatchForTraceStart()94 void TraceNetLogObserver::StopWatchForTraceStart() {
95 // Should only stop if is currently watching.
96 DCHECK(net_log_to_watch_);
97 base::trace_event::TraceLog::GetInstance()->RemoveAsyncEnabledStateObserver(
98 this);
99 // net_log() != nullptr iff NetLog::AddObserver() has been called.
100 // This implies that if the netlog category wasn't enabled, then
101 // NetLog::RemoveObserver() will not get called, and there won't be
102 // a crash in NetLog::RemoveObserver().
103 if (net_log())
104 net_log()->RemoveObserver(this);
105 net_log_to_watch_ = nullptr;
106 }
107
OnTraceLogEnabled()108 void TraceNetLogObserver::OnTraceLogEnabled() {
109 bool enabled;
110 TRACE_EVENT_CATEGORY_GROUP_ENABLED(kNetLogTracingCategory, &enabled);
111 if (!enabled)
112 return;
113
114 net_log_to_watch_->AddObserver(this, NetLogCaptureMode::kDefault);
115 }
116
OnTraceLogDisabled()117 void TraceNetLogObserver::OnTraceLogDisabled() {
118 if (net_log())
119 net_log()->RemoveObserver(this);
120 }
121
122 } // namespace net
123