• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "agent/tracing_impl.h"
17 
18 #include "tooling/base/pt_events.h"
19 #include "protocol_channel.h"
20 
21 #include "ecmascript/napi/include/dfx_jsnapi.h"
22 
23 namespace panda::ecmascript::tooling {
Dispatch(const DispatchRequest & request)24 void TracingImpl::DispatcherImpl::Dispatch(const DispatchRequest &request)
25 {
26     static std::unordered_map<std::string, AgentHandler> dispatcherTable {
27         { "end", &TracingImpl::DispatcherImpl::End },
28         { "getCategories", &TracingImpl::DispatcherImpl::GetCategories },
29         { "recordClockSyncMarker", &TracingImpl::DispatcherImpl::RecordClockSyncMarker },
30         { "requestMemoryDump", &TracingImpl::DispatcherImpl::RequestMemoryDump },
31         { "start", &TracingImpl::DispatcherImpl::Start }
32     };
33 
34     const std::string &method = request.GetMethod();
35     LOG_DEBUGGER(DEBUG) << "dispatch [" << method << "] to TracingImpl";
36     auto entry = dispatcherTable.find(method);
37     if (entry != dispatcherTable.end() && entry->second != nullptr) {
38         (this->*(entry->second))(request);
39     } else {
40         SendResponse(request, DispatchResponse::Fail("Unknown method: " + method));
41     }
42 }
43 
End(const DispatchRequest & request)44 void TracingImpl::DispatcherImpl::End(const DispatchRequest &request)
45 {
46     auto traceEvents = tracing_->End();
47     if (traceEvents == nullptr) {
48         LOG_DEBUGGER(ERROR) << "Transfer DFXJSNApi::StopTracing is failure";
49         SendResponse(request, DispatchResponse::Fail("Stop is failure"));
50         return;
51     }
52     SendResponse(request, DispatchResponse::Ok());
53 
54     tracing_->frontend_.DataCollected(std::move(traceEvents));
55     tracing_->frontend_.TracingComplete();
56 }
57 
GetCategories(const DispatchRequest & request)58 void TracingImpl::DispatcherImpl::GetCategories(const DispatchRequest &request)
59 {
60     std::vector<std::string> categories;
61     DispatchResponse response = tracing_->GetCategories(categories);
62     SendResponse(request, response);
63 }
64 
RecordClockSyncMarker(const DispatchRequest & request)65 void TracingImpl::DispatcherImpl::RecordClockSyncMarker(const DispatchRequest &request)
66 {
67     std::string syncId;
68     DispatchResponse response = tracing_->RecordClockSyncMarker(syncId);
69     SendResponse(request, response);
70 }
71 
RequestMemoryDump(const DispatchRequest & request)72 void TracingImpl::DispatcherImpl::RequestMemoryDump(const DispatchRequest &request)
73 {
74     std::unique_ptr<RequestMemoryDumpParams> params =
75         RequestMemoryDumpParams::Create(request.GetParams());
76     std::string dumpGuid;
77     bool success = false;
78     DispatchResponse response = tracing_->RequestMemoryDump(std::move(params), dumpGuid, success);
79     SendResponse(request, response);
80 }
81 
Start(const DispatchRequest & request)82 void TracingImpl::DispatcherImpl::Start(const DispatchRequest &request)
83 {
84     std::unique_ptr<StartParams> params =
85         StartParams::Create(request.GetParams());
86     DispatchResponse response = tracing_->Start(std::move(params));
87     SendResponse(request, response);
88 }
89 
AllowNotify() const90 bool TracingImpl::Frontend::AllowNotify() const
91 {
92     return channel_ != nullptr;
93 }
94 
BufferUsage(double percentFull,int32_t eventCount,double value)95 void TracingImpl::Frontend::BufferUsage(double percentFull, int32_t eventCount, double value)
96 {
97     if (!AllowNotify()) {
98         return;
99     }
100 
101     tooling::BufferUsage bufferUsage;
102     bufferUsage.SetPercentFull(percentFull).SetEventCount(eventCount).SetValue(value);
103     channel_->SendNotification(bufferUsage);
104 }
105 
DataCollected(std::unique_ptr<std::vector<TraceEvent>> traceEvents)106 void TracingImpl::Frontend::DataCollected(std::unique_ptr<std::vector<TraceEvent>> traceEvents)
107 {
108     if (!AllowNotify()) {
109         return;
110     }
111 
112     tooling::DataCollected dataCollected;
113     dataCollected.SetTraceEvents(std::move(traceEvents));
114 
115     channel_->SendNotification(dataCollected);
116 }
117 
TracingComplete()118 void TracingImpl::Frontend::TracingComplete()
119 {
120     if (!AllowNotify()) {
121         return;
122     }
123 
124     tooling::TracingComplete tracingComplete;
125     channel_->SendNotification(tracingComplete);
126 }
127 
End()128 std::unique_ptr<std::vector<TraceEvent>> TracingImpl::End()
129 {
130 #if defined(ECMASCRIPT_SUPPORT_TRACING)
131     uv_timer_stop(&handle_);
132 #endif
133     auto traceEvents = panda::DFXJSNApi::StopTracing(vm_);
134     return traceEvents;
135 }
136 
GetCategories(std::vector<std::string> categories)137 DispatchResponse TracingImpl::GetCategories([[maybe_unused]] std::vector<std::string> categories)
138 {
139     return DispatchResponse::Fail("GetCategories not support now.");
140 }
141 
RecordClockSyncMarker(std::string syncId)142 DispatchResponse TracingImpl::RecordClockSyncMarker([[maybe_unused]] std::string syncId)
143 {
144     return DispatchResponse::Fail("RecordClockSyncMarker not support now.");
145 }
146 
RequestMemoryDump(std::unique_ptr<RequestMemoryDumpParams> params,std::string dumpGuid,bool success)147 DispatchResponse TracingImpl::RequestMemoryDump([[maybe_unused]] std::unique_ptr<RequestMemoryDumpParams> params,
148                                                 [[maybe_unused]] std::string dumpGuid, [[maybe_unused]] bool success)
149 {
150     return DispatchResponse::Fail("RequestMemoryDump not support now.");
151 }
152 
Start(std::unique_ptr<StartParams> params)153 DispatchResponse TracingImpl::Start(std::unique_ptr<StartParams> params)
154 {
155     std::string categories = params->GetCategories();
156     if (!panda::DFXJSNApi::StartTracing(vm_, categories)) {
157         return DispatchResponse::Fail("Start tracing failed");
158     }
159 
160 #if defined(ECMASCRIPT_SUPPORT_TRACING)
161     if (params->HasBufferUsageReportingInterval()) {
162         LOG_DEBUGGER(ERROR) << "HasBufferUsageReportingInterval " << params->GetBufferUsageReportingInterval();
163         if (uv_is_active(reinterpret_cast<uv_handle_t*>(&handle_))) {
164             LOG_DEBUGGER(ERROR) << "uv_is_active!!!";
165             return DispatchResponse::Ok();
166         }
167 
168         uv_loop_t *loop = reinterpret_cast<uv_loop_t *>(vm_->GetLoop());
169         if (loop == nullptr) {
170             return DispatchResponse::Fail("Loop is nullptr");
171         }
172         uv_timer_init(loop, &handle_);
173         handle_.data = this;
174         uv_timer_start(&handle_, TracingBufferUsageReport, 0, params->GetBufferUsageReportingInterval());
175 
176         uv_work_t *work = new uv_work_t;
177         uv_queue_work(loop, work, [](uv_work_t *) { }, [](uv_work_t *work, int32_t) { delete work; });
178     }
179 #endif
180     return DispatchResponse::Ok();
181 }
182 
183 #if defined(ECMASCRIPT_SUPPORT_TRACING)
TracingBufferUsageReport(uv_timer_t * handle)184 void TracingImpl::TracingBufferUsageReport(uv_timer_t* handle)
185 {
186     TracingImpl *tracing = static_cast<TracingImpl *>(handle->data);
187     if (tracing == nullptr) {
188         LOG_DEBUGGER(ERROR) << "tracing == nullptr";
189         return;
190     }
191 
192     double percentFull = 0.0;
193     uint32_t eventCount = 0;
194     double value = 0.0;
195     panda::DFXJSNApi::GetTracingBufferUseage(tracing->vm_, percentFull, eventCount, value);
196     tracing->frontend_.BufferUsage(percentFull, eventCount, value);
197 }
198 #endif
199 }  // namespace panda::ecmascript::tooling