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