[tracing] Add a way to test perfetto traces.

Add a new abstract class TraceEventListener which is just an interface
for consuming trace events. This separates the V8-specific stuff that
an actual perfetto consumer needs to do e.g. handling the has_more flag
and signalling back to the controller with a semaphore.

This is a change from the previous plan of making the PerfettoConsumer
class sub-classable to implement custom consumption of trace events.
This will be difficult when the consumer is created outside of the
PerfettoTracingController as we can't hook up the
consumer_finished_semaphore_ that belongs to the controller.

Now the PerfettoTracingController is responsible for the Consumer life-
cycle and hides it entirely from callers. We add the
AddTraceEventListener() method to allow callers to register a listener
either for testing or a JSON listener for real tracing.

This lets us write tests that can store all the trace events in memory
without first converting them to JSON, letting us write test more
easily. There's an example test add to test-tracing - more tests using
this style will follow.

Cq-Include-Trybots: luci.v8.try:v8_linux64_perfetto_dbg_ng
Bug: v8:8339
Change-Id: I2d2b0f408b1c7bed954144163e1968f40d772c1b
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1628789
Commit-Queue: Ulan Degenbaev <ulan@chromium.org>
Auto-Submit: Peter Marshall <petermarshall@chromium.org>
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#61854}
This commit is contained in:
Peter Marshall 2019-05-27 14:46:35 +02:00 committed by Commit Bot
parent 8f6391932c
commit d365f62ec1
14 changed files with 280 additions and 65 deletions

View File

@ -139,10 +139,6 @@ declare_args() {
# Use Siphash as added protection against hash flooding attacks.
v8_use_siphash = false
# Use Perfetto (https://perfetto.dev) as the default TracingController. Not
# currently implemented.
v8_use_perfetto = false
# Switches off inlining in V8.
v8_no_inline = false
@ -3661,10 +3657,10 @@ v8_component("v8_libplatform") {
]
if (v8_use_perfetto) {
sources += [
"src/libplatform/tracing/perfetto-consumer-base.cc",
"src/libplatform/tracing/perfetto-consumer-base.h",
"src/libplatform/tracing/perfetto-json-consumer.cc",
"src/libplatform/tracing/perfetto-json-consumer.h",
"src/libplatform/tracing/json-trace-event-listener.cc",
"src/libplatform/tracing/json-trace-event-listener.h",
"src/libplatform/tracing/perfetto-consumer.cc",
"src/libplatform/tracing/perfetto-consumer.h",
"src/libplatform/tracing/perfetto-producer.cc",
"src/libplatform/tracing/perfetto-producer.h",
"src/libplatform/tracing/perfetto-shared-memory.cc",
@ -3673,6 +3669,7 @@ v8_component("v8_libplatform") {
"src/libplatform/tracing/perfetto-tasks.h",
"src/libplatform/tracing/perfetto-tracing-controller.cc",
"src/libplatform/tracing/perfetto-tracing-controller.h",
"src/libplatform/tracing/trace-event-listener.h",
]
deps += [
"third_party/perfetto:libperfetto",

View File

@ -63,6 +63,10 @@ declare_args() {
# Expose symbols for dynamic linking.
v8_expose_symbols = false
# Use Perfetto (https://perfetto.dev) as the default TracingController. Not
# currently implemented.
v8_use_perfetto = false
}
if (v8_use_external_startup_data == "") {

View File

@ -24,6 +24,7 @@ namespace platform {
namespace tracing {
class PerfettoTracingController;
class TraceEventListener;
const int kTraceMaxNumArgs = 2;
@ -244,6 +245,9 @@ class V8_PLATFORM_EXPORT TracingController
// Must be called before StartTracing() if V8_USE_PERFETTO is true. Provides
// the output stream for the JSON trace data.
void InitializeForPerfetto(std::ostream* output_stream);
// Provide an optional listener for testing that will receive trace events.
// Must be called before StartTracing().
void SetTraceEventListenerForTesting(TraceEventListener* listener);
#endif
// v8::TracingController implementation.
@ -291,6 +295,8 @@ class V8_PLATFORM_EXPORT TracingController
std::atomic_bool perfetto_recording_{false};
std::unique_ptr<PerfettoTracingController> perfetto_tracing_controller_;
std::ostream* output_stream_ = nullptr;
std::unique_ptr<TraceEventListener> json_listener_;
TraceEventListener* listener_for_testing_ = nullptr;
#endif
// Disallow copy and assign

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/libplatform/tracing/perfetto-json-consumer.h"
#include "src/libplatform/tracing/json-trace-event-listener.h"
#include <cmath>
@ -15,19 +15,18 @@ namespace v8 {
namespace platform {
namespace tracing {
PerfettoJSONConsumer::PerfettoJSONConsumer(base::Semaphore* finished,
std::ostream* stream)
: PerfettoConsumerBase(finished), stream_(stream) {
JSONTraceEventListener::JSONTraceEventListener(std::ostream* stream)
: stream_(stream) {
*stream_ << "{\"traceEvents\":[";
}
PerfettoJSONConsumer::~PerfettoJSONConsumer() { *stream_ << "]}"; }
JSONTraceEventListener::~JSONTraceEventListener() { *stream_ << "]}"; }
// TODO(petermarshall): Clean up this code which was copied from trace-writer.cc
// once we've removed that file.
// Writes the given string, taking care to escape characters when necessary.
void PerfettoJSONConsumer::AppendJSONString(const char* str) {
void JSONTraceEventListener::AppendJSONString(const char* str) {
size_t len = strlen(str);
*stream_ << "\"";
for (size_t i = 0; i < len; ++i) {
@ -65,7 +64,7 @@ void PerfettoJSONConsumer::AppendJSONString(const char* str) {
*stream_ << "\"";
}
void PerfettoJSONConsumer::AppendArgValue(
void JSONTraceEventListener::AppendArgValue(
const ::perfetto::protos::ChromeTraceEvent_Arg& arg) {
if (arg.has_bool_value()) {
*stream_ << (arg.bool_value() ? "true" : "false");
@ -111,7 +110,7 @@ void PerfettoJSONConsumer::AppendArgValue(
CHECK(!arg.has_traced_value());
}
void PerfettoJSONConsumer::ProcessPacket(
void JSONTraceEventListener::ProcessPacket(
const ::perfetto::protos::ChromeTracePacket& packet) {
for (const ::perfetto::protos::ChromeTraceEvent& event :
packet.chrome_events().trace_events()) {

View File

@ -2,17 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_LIBPLATFORM_TRACING_PERFETTO_JSON_CONSUMER_H_
#define V8_LIBPLATFORM_TRACING_PERFETTO_JSON_CONSUMER_H_
#ifndef V8_LIBPLATFORM_TRACING_JSON_TRACE_EVENT_LISTENER_H_
#define V8_LIBPLATFORM_TRACING_JSON_TRACE_EVENT_LISTENER_H_
#include <ostream>
#include "src/libplatform/tracing/perfetto-consumer-base.h"
#include "src/libplatform/tracing/trace-event-listener.h"
namespace perfetto {
namespace protos {
class ChromeTraceEvent_Arg;
class ChromeTracePacket;
} // namespace protos
} // namespace perfetto
@ -20,12 +19,12 @@ namespace v8 {
namespace platform {
namespace tracing {
// A consumer that converts the proto trace data to JSON and writes it to a
// A listener that converts the proto trace data to JSON and writes it to a
// file.
class PerfettoJSONConsumer final : public PerfettoConsumerBase {
class JSONTraceEventListener final : public TraceEventListener {
public:
PerfettoJSONConsumer(base::Semaphore* finished, std::ostream* stream);
~PerfettoJSONConsumer() override;
explicit JSONTraceEventListener(std::ostream* stream);
~JSONTraceEventListener() override;
private:
void ProcessPacket(
@ -43,4 +42,4 @@ class PerfettoJSONConsumer final : public PerfettoConsumerBase {
} // namespace platform
} // namespace v8
#endif // V8_LIBPLATFORM_TRACING_PERFETTO_JSON_CONSUMER_H_
#endif // V8_LIBPLATFORM_TRACING_JSON_TRACE_EVENT_LISTENER_H_

View File

@ -2,29 +2,32 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/libplatform/tracing/perfetto-consumer-base.h"
#include "src/libplatform/tracing/perfetto-consumer.h"
#include "perfetto/trace/chrome/chrome_trace_packet.pb.h"
#include "perfetto/tracing/core/trace_packet.h"
#include "src/base/macros.h"
#include "src/base/platform/semaphore.h"
#include "src/libplatform/tracing/trace-event-listener.h"
namespace v8 {
namespace platform {
namespace tracing {
PerfettoConsumerBase::PerfettoConsumerBase(base::Semaphore* finished)
PerfettoConsumer::PerfettoConsumer(base::Semaphore* finished)
: finished_semaphore_(finished) {}
void PerfettoConsumerBase::OnTraceData(
std::vector<::perfetto::TracePacket> packets, bool has_more) {
void PerfettoConsumer::OnTraceData(std::vector<::perfetto::TracePacket> packets,
bool has_more) {
for (const ::perfetto::TracePacket& packet : packets) {
perfetto::protos::ChromeTracePacket proto_packet;
bool success = packet.Decode(&proto_packet);
USE(success);
DCHECK(success);
ProcessPacket(proto_packet);
for (TraceEventListener* listener : listeners_) {
listener->ProcessPacket(proto_packet);
}
}
// PerfettoTracingController::StopTracing() waits on this sempahore. This is
// so that we can ensure that this consumer has finished consuming all of the
@ -32,6 +35,10 @@ void PerfettoConsumerBase::OnTraceData(
if (!has_more) finished_semaphore_->Signal();
}
void PerfettoConsumer::AddTraceEventListener(TraceEventListener* listener) {
listeners_.push_back(listener);
}
} // namespace tracing
} // namespace platform
} // namespace v8

View File

@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_LIBPLATFORM_TRACING_PERFETTO_CONSUMER_BASE_H_
#define V8_LIBPLATFORM_TRACING_PERFETTO_CONSUMER_BASE_H_
#ifndef V8_LIBPLATFORM_TRACING_PERFETTO_CONSUMER_H_
#define V8_LIBPLATFORM_TRACING_PERFETTO_CONSUMER_H_
#include <memory>
@ -26,33 +26,39 @@ class Semaphore;
namespace platform {
namespace tracing {
// A base class for custom Consumers within V8. Implements V8-specific logic
// for interacting with the tracing controller and leaves the consumption of
// the trace events to the subclass.
class TraceEventListener;
// A Perfetto Consumer gets streamed trace events from the Service via
// OnTraceData(). A Consumer can be configured (via
// service_endpoint()->EnableTracing()) to listen to various different types of
// trace events. The Consumer is responsible for producing whatever tracing
// output the system should have.
class PerfettoConsumerBase : public ::perfetto::Consumer {
// Implements the V8-specific logic for interacting with the tracing controller
// and directs trace events to the added TraceEventListeners.
class PerfettoConsumer final : public ::perfetto::Consumer {
public:
explicit PerfettoConsumer(base::Semaphore* finished);
using ServiceEndpoint = ::perfetto::TracingService::ConsumerEndpoint;
// Register a trace event listener that will receive trace events from this
// consumer. This can be called multiple times to register multiple listeners,
// but must be called before starting tracing.
void AddTraceEventListener(TraceEventListener* listener);
ServiceEndpoint* service_endpoint() const { return service_endpoint_.get(); }
void set_service_endpoint(std::unique_ptr<ServiceEndpoint> endpoint) {
service_endpoint_ = std::move(endpoint);
}
protected:
explicit PerfettoConsumerBase(base::Semaphore* finished);
private:
// ::perfetto::Consumer implementation
void OnConnect() override {}
void OnDisconnect() override {}
void OnTracingDisabled() override {}
void OnTraceData(std::vector<::perfetto::TracePacket> packets,
bool has_more) final;
bool has_more) override;
void OnDetach(bool success) override {}
void OnAttach(bool success, const ::perfetto::TraceConfig&) override {}
void OnTraceStats(bool success, const ::perfetto::TraceStats&) override {
@ -62,16 +68,13 @@ class PerfettoConsumerBase : public ::perfetto::Consumer {
UNREACHABLE();
}
// Subclasses override this method to respond to trace packets.
virtual void ProcessPacket(
const ::perfetto::protos::ChromeTracePacket& packet) = 0;
std::unique_ptr<ServiceEndpoint> service_endpoint_;
base::Semaphore* finished_semaphore_;
std::vector<TraceEventListener*> listeners_;
};
} // namespace tracing
} // namespace platform
} // namespace v8
#endif // V8_LIBPLATFORM_TRACING_PERFETTO_CONSUMER_BASE_H_
#endif // V8_LIBPLATFORM_TRACING_PERFETTO_CONSUMER_H_

View File

@ -7,10 +7,11 @@
#include "perfetto/tracing/core/trace_config.h"
#include "perfetto/tracing/core/trace_writer.h"
#include "perfetto/tracing/core/tracing_service.h"
#include "src/libplatform/tracing/perfetto-json-consumer.h"
#include "src/libplatform/tracing/perfetto-consumer.h"
#include "src/libplatform/tracing/perfetto-producer.h"
#include "src/libplatform/tracing/perfetto-shared-memory.h"
#include "src/libplatform/tracing/perfetto-tasks.h"
#include "src/libplatform/tracing/trace-event-listener.h"
namespace v8 {
namespace platform {
@ -22,15 +23,12 @@ PerfettoTracingController::PerfettoTracingController()
consumer_finished_semaphore_(0) {}
void PerfettoTracingController::StartTracing(
const ::perfetto::TraceConfig& trace_config, std::ostream* output_stream) {
DCHECK_NOT_NULL(output_stream);
DCHECK(output_stream->good());
const ::perfetto::TraceConfig& trace_config) {
DCHECK(!task_runner_);
task_runner_ = base::make_unique<PerfettoTaskRunner>();
// The Perfetto service expects calls on the task runner thread which is why
// the setup below occurs in posted tasks.
task_runner_->PostTask([&trace_config, output_stream, this] {
task_runner_->PostTask([&trace_config, this] {
std::unique_ptr<::perfetto::SharedMemory::Factory> shmem_factory =
base::make_unique<PerfettoSharedMemoryFactory>();
@ -44,8 +42,12 @@ void PerfettoTracingController::StartTracing(
// for now we just leak all TraceWriters.
service_->SetSMBScrapingEnabled(true);
producer_ = base::make_unique<PerfettoProducer>(this);
consumer_ = base::make_unique<PerfettoJSONConsumer>(
&consumer_finished_semaphore_, output_stream);
consumer_ =
base::make_unique<PerfettoConsumer>(&consumer_finished_semaphore_);
for (TraceEventListener* listener : listeners_) {
consumer_->AddTraceEventListener(listener);
}
producer_->set_service_endpoint(service_->ConnectProducer(
producer_.get(), 0, "v8.perfetto-producer", 0, true));
@ -72,7 +74,7 @@ void PerfettoTracingController::StopTracing() {
// events that have been written by still-living TraceWriters.
consumer_->service_endpoint()->DisableTracing();
// Trigger the consumer to finish. This can trigger multiple calls to
// PerfettoConsumerBase::OnTraceData(), with the final call passing has_more
// PerfettoConsumer::OnTraceData(), with the final call passing has_more
// as false.
consumer_->service_endpoint()->ReadBuffers();
});
@ -91,6 +93,11 @@ void PerfettoTracingController::StopTracing() {
task_runner_.reset();
}
void PerfettoTracingController::AddTraceEventListener(
TraceEventListener* listener) {
listeners_.push_back(listener);
}
PerfettoTracingController::~PerfettoTracingController() {
base::Thread::DeleteThreadLocalKey(writer_key_);
}

View File

@ -23,9 +23,10 @@ namespace v8 {
namespace platform {
namespace tracing {
class PerfettoConsumerBase;
class PerfettoConsumer;
class PerfettoProducer;
class PerfettoTaskRunner;
class TraceEventListener;
// This is the top-level interface for performing tracing with perfetto. The
// user of this class should call StartTracing() to start tracing, and
@ -37,15 +38,19 @@ class PerfettoTracingController {
// Blocks and sets up all required data structures for tracing. It is safe to
// call GetOrCreateThreadLocalWriter() to obtain thread-local TraceWriters for
// writing trace events once this call returns. Tracing output will be sent in
// JSON format to |output_stream|.
void StartTracing(const ::perfetto::TraceConfig& trace_config,
std::ostream* output_stream);
// writing trace events once this call returns. Tracing output will be sent to
// the TraceEventListeners registered via AddTraceEventListener().
void StartTracing(const ::perfetto::TraceConfig& trace_config);
// Blocks and finishes all existing AddTraceEvent tasks. Stops the tracing
// thread.
void StopTracing();
// Register a trace event listener that will receive trace events. This can be
// called multiple times to register multiple listeners, but must be called
// before starting tracing.
void AddTraceEventListener(TraceEventListener* listener);
~PerfettoTracingController();
// Each thread that wants to trace should call this to get their TraceWriter.
@ -61,8 +66,9 @@ class PerfettoTracingController {
std::unique_ptr<::perfetto::TracingService> service_;
std::unique_ptr<PerfettoProducer> producer_;
std::unique_ptr<PerfettoConsumerBase> consumer_;
std::unique_ptr<PerfettoConsumer> consumer_;
std::unique_ptr<PerfettoTaskRunner> task_runner_;
std::vector<TraceEventListener*> listeners_;
base::Thread::LocalStorageKey writer_key_;
// A semaphore that is signalled when StartRecording is called. StartTracing
// waits on this semaphore to be notified when the tracing service is ready to

View File

@ -0,0 +1,34 @@
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_LIBPLATFORM_TRACING_TRACE_EVENT_LISTENER_H_
#define V8_LIBPLATFORM_TRACING_TRACE_EVENT_LISTENER_H_
namespace perfetto {
namespace protos {
class ChromeTracePacket;
} // namespace protos
} // namespace perfetto
namespace v8 {
namespace platform {
namespace tracing {
// A TraceEventListener is a simple interface that allows subclasses to listen
// to trace events. This interface is to hide the more complex interactions that
// the PerfettoConsumer class has to perform. Clients override ProcessPacket()
// to respond to trace events, e.g. to write them to a file as JSON or for
// testing purposes.
class TraceEventListener {
public:
virtual ~TraceEventListener() = default;
virtual void ProcessPacket(
const ::perfetto::protos::ChromeTracePacket& packet) = 0;
};
} // namespace tracing
} // namespace platform
} // namespace v8
#endif // V8_LIBPLATFORM_TRACING_TRACE_EVENT_LISTENER_H_

View File

@ -20,6 +20,7 @@
#include "perfetto/tracing/core/trace_config.h"
#include "perfetto/tracing/core/trace_packet.h"
#include "perfetto/tracing/core/trace_writer.h"
#include "src/libplatform/tracing/json-trace-event-listener.h"
#include "src/libplatform/tracing/perfetto-tracing-controller.h"
#endif // V8_USE_PERFETTO
@ -79,6 +80,11 @@ void TracingController::InitializeForPerfetto(std::ostream* output_stream) {
DCHECK_NOT_NULL(output_stream);
DCHECK(output_stream->good());
}
void TracingController::SetTraceEventListenerForTesting(
TraceEventListener* listener) {
listener_for_testing_ = listener;
}
#endif
int64_t TracingController::CurrentTimestampMicroseconds() {
@ -273,18 +279,21 @@ void TracingController::StartTracing(TraceConfig* trace_config) {
#ifdef V8_USE_PERFETTO
perfetto_tracing_controller_ = base::make_unique<PerfettoTracingController>();
if (listener_for_testing_) {
perfetto_tracing_controller_->AddTraceEventListener(listener_for_testing_);
}
DCHECK_NOT_NULL(output_stream_);
DCHECK(output_stream_->good());
json_listener_ = base::make_unique<JSONTraceEventListener>(output_stream_);
perfetto_tracing_controller_->AddTraceEventListener(json_listener_.get());
::perfetto::TraceConfig perfetto_trace_config;
perfetto_trace_config.add_buffers()->set_size_kb(4096);
auto* ds_config = perfetto_trace_config.add_data_sources()->mutable_config();
ds_config->set_name("v8.trace_events");
DCHECK_NOT_NULL(output_stream_);
DCHECK(output_stream_->good());
// TODO(petermarshall): Set all the params from |perfetto_trace_config|.
perfetto_tracing_controller_->StartTracing(perfetto_trace_config,
output_stream_);
perfetto_tracing_controller_->StartTracing(perfetto_trace_config);
perfetto_recording_.store(true);
#endif // V8_USE_PERFETTO
@ -321,6 +330,7 @@ void TracingController::StopTracing() {
perfetto_recording_.store(false);
perfetto_tracing_controller_->StopTracing();
perfetto_tracing_controller_.reset();
json_listener_.reset();
#endif // V8_USE_PERFETTO
{

View File

@ -412,6 +412,10 @@ v8_source_set("cctest_sources") {
# MSVS wants this for gay-{precision,shortest}.cc.
cflags += [ "/bigobj" ]
}
if (v8_use_perfetto) {
deps += [ "//third_party/perfetto/protos/perfetto/trace/chrome:minimal_complete_lite" ]
}
}
action("resources") {

View File

@ -0,0 +1,3 @@
include_rules = [
"+perfetto",
]

View File

@ -9,6 +9,12 @@
#include "src/tracing/trace-event.h"
#include "test/cctest/cctest.h"
#ifdef V8_USE_PERFETTO
#include "perfetto/trace/chrome/chrome_trace_event.pb.h"
#include "perfetto/trace/chrome/chrome_trace_packet.pb.h"
#include "src/libplatform/tracing/trace-event-listener.h"
#endif
namespace v8 {
namespace platform {
namespace tracing {
@ -525,6 +531,136 @@ TEST(AddTraceEventMultiThreaded) {
i::V8::SetPlatformForTesting(old_platform);
}
#ifdef V8_USE_PERFETTO
struct TraceEvent {
std::string name;
int64_t timestamp;
int32_t phase;
int32_t thread_id;
int64_t duration;
int64_t thread_duration;
std::string scope;
uint64_t id;
uint32_t flags;
std::string category_group_name;
int32_t process_id;
int64_t thread_timestamp;
uint64_t bind_id;
};
class TestListener : public TraceEventListener {
public:
void ProcessPacket(
const ::perfetto::protos::ChromeTracePacket& packet) override {
for (const ::perfetto::protos::ChromeTraceEvent& event :
packet.chrome_events().trace_events()) {
TraceEvent trace_event{event.name(), event.timestamp(),
event.phase(), event.thread_id(),
event.duration(), event.thread_duration(),
event.scope(), event.id(),
event.flags(), event.category_group_name(),
event.process_id(), event.thread_timestamp(),
event.bind_id()};
events_.push_back(trace_event);
}
}
TraceEvent* get_event(size_t index) { return &events_.at(index); }
size_t events_size() const { return events_.size(); }
private:
std::vector<TraceEvent> events_;
};
TEST(Perfetto) {
v8::Platform* old_platform = i::V8::GetCurrentPlatform();
std::unique_ptr<v8::Platform> default_platform(
v8::platform::NewDefaultPlatform());
i::V8::SetPlatformForTesting(default_platform.get());
auto tracing = base::make_unique<v8::platform::tracing::TracingController>();
v8::platform::tracing::TracingController* tracing_controller = tracing.get();
static_cast<v8::platform::DefaultPlatform*>(default_platform.get())
->SetTracingController(std::move(tracing));
MockTraceWriter* writer = new MockTraceWriter();
TraceBuffer* ring_buffer =
TraceBuffer::CreateTraceBufferRingBuffer(1, writer);
tracing_controller->Initialize(ring_buffer);
TestListener listener;
std::ostringstream sstream;
tracing_controller->InitializeForPerfetto(&sstream);
tracing_controller->SetTraceEventListenerForTesting(&listener);
TraceConfig* trace_config = new TraceConfig();
trace_config->AddIncludedCategory("v8");
tracing_controller->StartTracing(trace_config);
uint64_t uint64_arg = 1024;
const char* str_arg = "str_arg";
{
TRACE_EVENT0("v8", "test1");
TRACE_EVENT1("v8", "test2", "arg1", uint64_arg);
TRACE_EVENT2("v8", "test3", "arg1", uint64_arg, "arg2", str_arg);
}
TRACE_EVENT_INSTANT0("v8", "final event not captured",
TRACE_EVENT_SCOPE_THREAD);
tracing_controller->StopTracing();
TraceEvent* event = listener.get_event(0);
int32_t thread_id = event->thread_id;
int32_t process_id = event->process_id;
CHECK_EQ("test1", event->name);
CHECK_EQ(TRACE_EVENT_PHASE_BEGIN, event->phase);
int64_t timestamp = event->timestamp;
event = listener.get_event(1);
CHECK_EQ("test2", event->name);
CHECK_EQ(TRACE_EVENT_PHASE_BEGIN, event->phase);
CHECK_EQ(thread_id, event->thread_id);
CHECK_EQ(process_id, event->process_id);
CHECK_GE(event->timestamp, timestamp);
timestamp = event->timestamp;
event = listener.get_event(2);
CHECK_EQ("test3", event->name);
CHECK_EQ(TRACE_EVENT_PHASE_BEGIN, event->phase);
CHECK_EQ(thread_id, event->thread_id);
CHECK_EQ(process_id, event->process_id);
CHECK_GE(event->timestamp, timestamp);
timestamp = event->timestamp;
event = listener.get_event(3);
CHECK_EQ(TRACE_EVENT_PHASE_END, event->phase);
CHECK_EQ(thread_id, event->thread_id);
CHECK_EQ(process_id, event->process_id);
CHECK_GE(event->timestamp, timestamp);
timestamp = event->timestamp;
event = listener.get_event(4);
CHECK_EQ(TRACE_EVENT_PHASE_END, event->phase);
CHECK_EQ(thread_id, event->thread_id);
CHECK_EQ(process_id, event->process_id);
CHECK_GE(event->timestamp, timestamp);
timestamp = event->timestamp;
event = listener.get_event(5);
CHECK_EQ(TRACE_EVENT_PHASE_END, event->phase);
CHECK_EQ(thread_id, event->thread_id);
CHECK_EQ(process_id, event->process_id);
CHECK_GE(event->timestamp, timestamp);
timestamp = event->timestamp;
CHECK_EQ(6, listener.events_size());
i::V8::SetPlatformForTesting(old_platform);
}
#endif // V8_USE_PERFETTO
} // namespace tracing
} // namespace platform
} // namespace v8