mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Re-land Implement console.timeStamp
Summary: # Changelog: [Internal] Adds support for experimental non-standardized `console.timeStamp` API for capturing performance entries on a timeline. The main idea of the API is to be highly performant. More details in the corresponding RCP [1]. NOTE: Because of the `jsinspector-modern` stack gating logic, this won't be installed in production builds. `console.timeStamp` will be polyfilled with a stub - D76987507. Reviewed By: rubennorte Differential Revision: D77374707 fbshipit-source-id: cb66b9fda06168f4b13af764afe95a63a0a8d5a0
This commit is contained in:
committed by
Facebook GitHub Bot
parent
0386b9bd51
commit
ff97ca3134
@@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
#include <jsinspector-modern/RuntimeTarget.h>
|
||||
#include <jsinspector-modern/tracing/PerformanceTracer.h>
|
||||
|
||||
#include <concepts>
|
||||
#include <deque>
|
||||
@@ -324,6 +325,16 @@ void consoleAssert(
|
||||
#include "ForwardingConsoleMethods.def"
|
||||
#undef FORWARDING_CONSOLE_METHOD
|
||||
|
||||
/*
|
||||
* Attempt to call String() on the given value.
|
||||
*/
|
||||
std::optional<std::string> stringifyJsiValue(
|
||||
const jsi::Value& value,
|
||||
jsi::Runtime& runtime) {
|
||||
auto String = runtime.global().getPropertyAsFunction(runtime, "String");
|
||||
return String.call(runtime, value).asString(runtime).utf8(runtime);
|
||||
};
|
||||
|
||||
/**
|
||||
* Call innerFn and forward any arguments to the original console method
|
||||
* named methodName, if possible.
|
||||
@@ -354,6 +365,116 @@ auto forwardToOriginalConsole(
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Recording a marker on a timeline of the Performance instrumentation.
|
||||
* No actual logging is provided by definition.
|
||||
* https://developer.mozilla.org/en-US/docs/Web/API/console/timeStamp_static
|
||||
* https://developer.chrome.com/docs/devtools/performance/extension#inject_your_data_with_consoletimestamp
|
||||
*/
|
||||
void consoleTimeStamp(
|
||||
jsi::Runtime& runtime,
|
||||
const jsi::Value* arguments,
|
||||
size_t argumentsCount) {
|
||||
auto& performanceTracer = tracing::PerformanceTracer::getInstance();
|
||||
if (!performanceTracer.isTracing() || argumentsCount == 0) {
|
||||
// If not tracing, just early return to avoid the cost of parsing.
|
||||
return;
|
||||
}
|
||||
|
||||
const jsi::Value& labelArgument = arguments[0];
|
||||
std::string label;
|
||||
if (labelArgument.isString()) {
|
||||
label = labelArgument.asString(runtime).utf8(runtime);
|
||||
} else {
|
||||
auto maybeStringifiedLabel = stringifyJsiValue(labelArgument, runtime);
|
||||
if (maybeStringifiedLabel) {
|
||||
label = std::move(*maybeStringifiedLabel);
|
||||
} else {
|
||||
// Do not record this entry: unable to reliably stringify the label.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
auto now = HighResTimeStamp::now();
|
||||
std::optional<tracing::ConsoleTimeStampEntry> start;
|
||||
if (argumentsCount >= 2) {
|
||||
const jsi::Value& startArgument = arguments[1];
|
||||
if (startArgument.isNumber()) {
|
||||
start =
|
||||
HighResTimeStamp::fromDOMHighResTimeStamp(startArgument.asNumber());
|
||||
} else if (startArgument.isString()) {
|
||||
start = startArgument.asString(runtime).utf8(runtime);
|
||||
} else if (startArgument.isUndefined()) {
|
||||
start = now;
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<tracing::ConsoleTimeStampEntry> end;
|
||||
if (argumentsCount >= 3) {
|
||||
const jsi::Value& endArgument = arguments[2];
|
||||
if (endArgument.isNumber()) {
|
||||
end = HighResTimeStamp::fromDOMHighResTimeStamp(endArgument.asNumber());
|
||||
} else if (endArgument.isString()) {
|
||||
end = endArgument.asString(runtime).utf8(runtime);
|
||||
} else if (endArgument.isUndefined()) {
|
||||
end = now;
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<std::string> trackName;
|
||||
std::optional<std::string> trackGroup;
|
||||
std::optional<tracing::ConsoleTimeStampColor> color;
|
||||
if (argumentsCount >= 4) {
|
||||
const jsi::Value& trackNameArgument = arguments[3];
|
||||
if (trackNameArgument.isString()) {
|
||||
trackName = trackNameArgument.asString(runtime).utf8(runtime);
|
||||
}
|
||||
}
|
||||
if (argumentsCount >= 5) {
|
||||
const jsi::Value& trackGroupArgument = arguments[4];
|
||||
if (trackGroupArgument.isString()) {
|
||||
trackGroup = trackGroupArgument.asString(runtime).utf8(runtime);
|
||||
}
|
||||
}
|
||||
if (argumentsCount >= 6) {
|
||||
const jsi::Value& colorArgument = arguments[5];
|
||||
if (colorArgument.isString()) {
|
||||
color = tracing::getConsoleTimeStampColorFromString(
|
||||
colorArgument.asString(runtime).utf8(runtime));
|
||||
}
|
||||
}
|
||||
|
||||
performanceTracer.reportTimeStamp(
|
||||
label, start, end, trackName, trackGroup, color);
|
||||
}
|
||||
|
||||
/*
|
||||
* Installs console.timeStamp and manages the forwarding to the original console
|
||||
* object, if available.
|
||||
*/
|
||||
void installConsoleTimeStamp(
|
||||
jsi::Runtime& runtime,
|
||||
std::shared_ptr<jsi::Object> originalConsole,
|
||||
jsi::Object& consoleObject) {
|
||||
consoleObject.setProperty(
|
||||
runtime,
|
||||
"timeStamp",
|
||||
jsi::Function::createFromHostFunction(
|
||||
runtime,
|
||||
jsi::PropNameID::forAscii(runtime, "timeStamp"),
|
||||
0,
|
||||
forwardToOriginalConsole(
|
||||
originalConsole,
|
||||
"timeStamp",
|
||||
[](jsi::Runtime& runtime,
|
||||
const jsi::Value& /*thisVal*/,
|
||||
const jsi::Value* args,
|
||||
size_t count) {
|
||||
consoleTimeStamp(runtime, args, count);
|
||||
return jsi::Value::undefined();
|
||||
})));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void RuntimeTarget::installConsoleHandler() {
|
||||
@@ -470,6 +591,11 @@ void RuntimeTarget::installConsoleHandler() {
|
||||
*/
|
||||
installConsoleMethod("assert", consoleAssert);
|
||||
|
||||
/**
|
||||
* console.timeStamp
|
||||
*/
|
||||
installConsoleTimeStamp(runtime, originalConsole, console);
|
||||
|
||||
// Install forwarding console methods.
|
||||
#define FORWARDING_CONSOLE_METHOD(name, type) \
|
||||
installConsoleMethod(#name, console_##name);
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
# console.timeStamp API
|
||||
|
||||
[🏠 Home](../../../../../README.md)
|
||||
|
||||
The console.timeStamp API provides a way to record markers on the timeline of
|
||||
the Performance instrumentation.
|
||||
|
||||
The idea is to have a highly performant API for instrumenting React Native
|
||||
applications and surfacing the recorded timing data to performance tooling:
|
||||
Performance panel or Perfetto. This API should be explicitly designed to have
|
||||
minimal runtime overhead and expected to be used for instrumenting hot paths and
|
||||
profiling (production) builds.
|
||||
|
||||
See also:
|
||||
|
||||
- https://developer.mozilla.org/en-US/docs/Web/API/console/timeStamp_static
|
||||
- https://developer.chrome.com/docs/devtools/performance/extension#inject_your_data_with_consoletimestamp
|
||||
|
||||
## 🚀 Usage
|
||||
|
||||
The `console.timeStamp()` method can be called with various parameters to record
|
||||
markers on the performance timeline:
|
||||
|
||||
```javascript
|
||||
// Basic usage with just a label
|
||||
console.timeStamp('Click');
|
||||
|
||||
// Advanced usage with start and end markers
|
||||
console.timeStamp('Animation', performance.now(), performance.now() + 500);
|
||||
|
||||
// Full usage with all parameters
|
||||
console.timeStamp(
|
||||
'Animation', // label
|
||||
performance.now(), // start time
|
||||
performance.now() + 500, // end time
|
||||
'UI Animations', // track name
|
||||
'Main Thread', // track group
|
||||
'primary', // color
|
||||
);
|
||||
```
|
||||
|
||||
More examples are available on
|
||||
[Chrome DevTools website](https://developer.chrome.com/docs/devtools/performance/extension#consoletimestamp_api_examples).
|
||||
|
||||
### ⚙️ Parameters
|
||||
|
||||
1. `label` (required): A string label for the timestamp marker
|
||||
2. `start` (optional): A
|
||||
[DOMHighResTimeStamp](https://developer.mozilla.org/en-US/docs/Web/API/DOMHighResTimeStamp)
|
||||
or string marker for the start time
|
||||
3. `end` (optional): A
|
||||
[DOMHighResTimeStamp](https://developer.mozilla.org/en-US/docs/Web/API/DOMHighResTimeStamp)
|
||||
or string marker for the end time
|
||||
4. `trackName` (optional): A string specifying the track name
|
||||
5. `trackGroup` (optional): A string specifying the track group
|
||||
6. `color` (optional): A string specifying the color of the timestamp marker.
|
||||
Supported values depend on Performance instrumentation, for React Native
|
||||
DevTools, the supported values are listed in ConsoleTimeStamp.h.
|
||||
|
||||
## 📐 Design
|
||||
|
||||
The console.timeStamp API is a JSI Host Function that is installed as part of
|
||||
the Console interface when JavaScript Runtime target is registered with the
|
||||
jsinspector-modern stack.
|
||||
|
||||
To achieve minimal runtime costs:
|
||||
|
||||
- This API will not add or buffer Performance Entries that can be accessed or
|
||||
observed with PerformanceObserver.
|
||||
- This API won’t have any buffering implemented by design. The buffering may be
|
||||
implemented by the performance tooling, if needed.
|
||||
- This API will have limited validation and user feedback. All incorrect timing
|
||||
entries are expected to be ignored.
|
||||
|
||||
## 🩻 Visualization
|
||||
|
||||
With Chrome DevTools Performance panel integration:
|
||||
|
||||
- Marks (only `label` specified) are not reported to custom tracks. They are
|
||||
only reported as `"TimeStamp: <label>"` entries on the Timings track.
|
||||
- Measures (both start and end are defined) are reported to custom tracks, if
|
||||
specified.
|
||||
|
||||
## 🔗 Relationship with other systems
|
||||
|
||||
### Part of
|
||||
|
||||
- jsinspector-modern: The JavaScript debugger stack for React Native DevTools,
|
||||
which controls the lifetime of the Console interface for the targeted
|
||||
JavaScript Runtime.
|
||||
|
||||
### Used by this
|
||||
|
||||
- Performance Tracing System: The console.timeStamp API reports markers to the
|
||||
PerformanceTracer singleton, which is a Trace Event engine responsible for
|
||||
collection, storage and serialization of Performance timeline events.
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#include <folly/executors/QueuedImmediateExecutor.h>
|
||||
|
||||
#include "JsiIntegrationTest.h"
|
||||
#include "engines/JsiIntegrationTestHermesEngineAdapter.h"
|
||||
|
||||
#include <jsinspector-modern/tracing/PerformanceTracer.h>
|
||||
|
||||
using namespace ::testing;
|
||||
|
||||
namespace facebook::react::jsinspector_modern {
|
||||
|
||||
/**
|
||||
* A test fixture for the console.timeStamp API.
|
||||
*/
|
||||
class ConsoleTimeStampTest : public JsiIntegrationPortableTestBase<
|
||||
JsiIntegrationTestHermesEngineAdapter,
|
||||
folly::QueuedImmediateExecutor> {
|
||||
protected:
|
||||
size_t countNumberOfTimeStampEvents(
|
||||
tracing::PerformanceTracer& performanceTracer) {
|
||||
size_t count = 0;
|
||||
performanceTracer.collectEvents(
|
||||
[&count](const folly::dynamic& chunk) {
|
||||
auto event = chunk[0];
|
||||
if (event["name"] == "TimeStamp") {
|
||||
count++;
|
||||
}
|
||||
},
|
||||
1);
|
||||
return count;
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(ConsoleTimeStampTest, Installed) {
|
||||
auto result = eval("typeof console.timeStamp");
|
||||
auto& runtime = engineAdapter_->getRuntime();
|
||||
EXPECT_EQ(result.asString(runtime).utf8(runtime), "function");
|
||||
}
|
||||
|
||||
TEST_F(ConsoleTimeStampTest, RecordsEntriesWithJustLabel) {
|
||||
auto& tracer = tracing::PerformanceTracer::getInstance();
|
||||
EXPECT_TRUE(tracer.startTracing());
|
||||
|
||||
eval("console.timeStamp('test-label')");
|
||||
|
||||
EXPECT_TRUE(tracer.stopTracing());
|
||||
EXPECT_EQ(countNumberOfTimeStampEvents(tracer), 1);
|
||||
}
|
||||
|
||||
TEST_F(ConsoleTimeStampTest, RecordsEntriesWithSpecifiedTimestamps) {
|
||||
auto& tracer = tracing::PerformanceTracer::getInstance();
|
||||
EXPECT_TRUE(tracer.startTracing());
|
||||
|
||||
eval("console.timeStamp('test-range', 100, 200)");
|
||||
|
||||
EXPECT_TRUE(tracer.stopTracing());
|
||||
EXPECT_EQ(countNumberOfTimeStampEvents(tracer), 1);
|
||||
}
|
||||
|
||||
TEST_F(ConsoleTimeStampTest, RecordsEntriesWithMarkNames) {
|
||||
auto& tracer = tracing::PerformanceTracer::getInstance();
|
||||
EXPECT_TRUE(tracer.startTracing());
|
||||
|
||||
eval(
|
||||
"console.timeStamp('test-string-timestamps', 'start-marker', 'end-marker')");
|
||||
|
||||
EXPECT_TRUE(tracer.stopTracing());
|
||||
EXPECT_EQ(countNumberOfTimeStampEvents(tracer), 1);
|
||||
}
|
||||
|
||||
TEST_F(ConsoleTimeStampTest, KeepsEntriesWithUnknownMarkNames) {
|
||||
auto& tracer = tracing::PerformanceTracer::getInstance();
|
||||
EXPECT_TRUE(tracer.startTracing());
|
||||
|
||||
eval(
|
||||
"console.timeStamp('test-string-timestamps', 'start-marker', 'end-marker')");
|
||||
|
||||
EXPECT_TRUE(tracer.stopTracing());
|
||||
EXPECT_EQ(countNumberOfTimeStampEvents(tracer), 1);
|
||||
}
|
||||
|
||||
TEST_F(ConsoleTimeStampTest, DoesNotThrowIfNotTracing) {
|
||||
auto& tracer = tracing::PerformanceTracer::getInstance();
|
||||
EXPECT_FALSE(tracer.stopTracing());
|
||||
|
||||
// Call console.timeStamp - should be a no-op when not tracing
|
||||
eval("console.timeStamp('test-no-tracing')");
|
||||
}
|
||||
|
||||
TEST_F(ConsoleTimeStampTest, SurvivesInvalidArguments) {
|
||||
auto& tracer = tracing::PerformanceTracer::getInstance();
|
||||
EXPECT_TRUE(tracer.startTracing());
|
||||
|
||||
// Won't be logged, no label specified.
|
||||
eval("console.timeStamp()");
|
||||
// Will be logged - undefined will be stringified.
|
||||
eval("console.timeStamp(undefined)");
|
||||
// Will be logged - function will be stringified.
|
||||
eval("console.timeStamp(() => {})");
|
||||
// Will be logged - 123 will be stringified.
|
||||
eval("console.timeStamp(123)");
|
||||
// Will be logged - start will default to an empty string.
|
||||
eval("console.timeStamp('label', {})");
|
||||
|
||||
EXPECT_TRUE(tracer.stopTracing());
|
||||
EXPECT_EQ(countNumberOfTimeStampEvents(tracer), 4);
|
||||
}
|
||||
|
||||
TEST_F(ConsoleTimeStampTest, InvalidTrackNameIsIgnored) {
|
||||
auto& tracer = tracing::PerformanceTracer::getInstance();
|
||||
EXPECT_TRUE(tracer.startTracing());
|
||||
|
||||
eval("console.timeStamp('label', 0, 1, {})");
|
||||
|
||||
EXPECT_TRUE(tracer.stopTracing());
|
||||
EXPECT_EQ(countNumberOfTimeStampEvents(tracer), 1);
|
||||
}
|
||||
|
||||
TEST_F(ConsoleTimeStampTest, InvalidTrackGroupIsIgnored) {
|
||||
auto& tracer = tracing::PerformanceTracer::getInstance();
|
||||
EXPECT_TRUE(tracer.startTracing());
|
||||
|
||||
eval("console.timeStamp('label', 0, 1, 'trackName', {})");
|
||||
|
||||
EXPECT_TRUE(tracer.stopTracing());
|
||||
EXPECT_EQ(countNumberOfTimeStampEvents(tracer), 1);
|
||||
}
|
||||
|
||||
TEST_F(ConsoleTimeStampTest, InvalidColorIsIgnored) {
|
||||
auto& tracer = tracing::PerformanceTracer::getInstance();
|
||||
EXPECT_TRUE(tracer.startTracing());
|
||||
|
||||
eval("console.timeStamp('test', 100, 200, 'FooTrack', 'BarGroup', 'red')");
|
||||
|
||||
EXPECT_TRUE(tracer.stopTracing());
|
||||
EXPECT_EQ(countNumberOfTimeStampEvents(tracer), 1);
|
||||
}
|
||||
|
||||
} // namespace facebook::react::jsinspector_modern
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <react/timing/primitives.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <optional>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <variant>
|
||||
|
||||
namespace facebook::react::jsinspector_modern::tracing {
|
||||
|
||||
// https://developer.chrome.com/docs/devtools/performance/extension#inject_your_data_with_consoletimestamp
|
||||
using ConsoleTimeStampEntry = std::variant<HighResTimeStamp, std::string>;
|
||||
|
||||
// https://developer.chrome.com/docs/devtools/performance/extension#devtools_object
|
||||
enum class ConsoleTimeStampColor {
|
||||
Primary,
|
||||
PrimaryLight,
|
||||
PrimaryDark,
|
||||
Secondary,
|
||||
SecondaryLight,
|
||||
SecondaryDark,
|
||||
Tertiary,
|
||||
TertiaryLight,
|
||||
TertiaryDark,
|
||||
Error,
|
||||
};
|
||||
|
||||
inline std::string consoleTimeStampColorToString(ConsoleTimeStampColor color) {
|
||||
switch (color) {
|
||||
case ConsoleTimeStampColor::Primary:
|
||||
return "primary";
|
||||
case ConsoleTimeStampColor::PrimaryLight:
|
||||
return "primary-light";
|
||||
case ConsoleTimeStampColor::PrimaryDark:
|
||||
return "primary-dark";
|
||||
case ConsoleTimeStampColor::Secondary:
|
||||
return "secondary";
|
||||
case ConsoleTimeStampColor::SecondaryLight:
|
||||
return "secondary-light";
|
||||
case ConsoleTimeStampColor::SecondaryDark:
|
||||
return "secondary-dark";
|
||||
case ConsoleTimeStampColor::Tertiary:
|
||||
return "tertiary";
|
||||
case ConsoleTimeStampColor::TertiaryLight:
|
||||
return "tertiary-light";
|
||||
case ConsoleTimeStampColor::TertiaryDark:
|
||||
return "tertiary-dark";
|
||||
case ConsoleTimeStampColor::Error:
|
||||
return "error";
|
||||
default:
|
||||
throw std::runtime_error("Unknown ConsoleTimeStampColor");
|
||||
}
|
||||
};
|
||||
|
||||
inline std::optional<ConsoleTimeStampColor> getConsoleTimeStampColorFromString(
|
||||
const std::string& str) {
|
||||
if (str == "primary") {
|
||||
return ConsoleTimeStampColor::Primary;
|
||||
} else if (str == "primary-light") {
|
||||
return ConsoleTimeStampColor::PrimaryLight;
|
||||
} else if (str == "primary-dark") {
|
||||
return ConsoleTimeStampColor::PrimaryDark;
|
||||
} else if (str == "secondary") {
|
||||
return ConsoleTimeStampColor::Secondary;
|
||||
} else if (str == "secondary-light") {
|
||||
return ConsoleTimeStampColor::SecondaryLight;
|
||||
} else if (str == "secondary-dark") {
|
||||
return ConsoleTimeStampColor::SecondaryDark;
|
||||
} else if (str == "tertiary") {
|
||||
return ConsoleTimeStampColor::Tertiary;
|
||||
} else if (str == "tertiary-light") {
|
||||
return ConsoleTimeStampColor::TertiaryLight;
|
||||
} else if (str == "tertiary-dark") {
|
||||
return ConsoleTimeStampColor::TertiaryDark;
|
||||
} else if (str == "error") {
|
||||
return ConsoleTimeStampColor::Error;
|
||||
} else {
|
||||
return std::nullopt;
|
||||
}
|
||||
};
|
||||
|
||||
}; // namespace facebook::react::jsinspector_modern::tracing
|
||||
@@ -180,6 +180,61 @@ void PerformanceTracer::reportMeasure(
|
||||
});
|
||||
}
|
||||
|
||||
void PerformanceTracer::reportTimeStamp(
|
||||
std::string name,
|
||||
std::optional<ConsoleTimeStampEntry> start,
|
||||
std::optional<ConsoleTimeStampEntry> end,
|
||||
std::optional<std::string> trackName,
|
||||
std::optional<std::string> trackGroup,
|
||||
std::optional<ConsoleTimeStampColor> color) {
|
||||
if (!tracingAtomic_) {
|
||||
return;
|
||||
}
|
||||
|
||||
// `name` takes precedence over `message` in Chrome DevTools Frontend, no need
|
||||
// to record both.
|
||||
folly::dynamic data = folly::dynamic::object("name", std::move(name));
|
||||
if (start) {
|
||||
if (std::holds_alternative<HighResTimeStamp>(*start)) {
|
||||
data["start"] = highResTimeStampToTracingClockTimeStamp(
|
||||
std::get<HighResTimeStamp>(*start));
|
||||
} else {
|
||||
data["start"] = std::move(std::get<std::string>(*start));
|
||||
}
|
||||
}
|
||||
if (end) {
|
||||
if (std::holds_alternative<HighResTimeStamp>(*end)) {
|
||||
data["end"] = highResTimeStampToTracingClockTimeStamp(
|
||||
std::get<HighResTimeStamp>(*end));
|
||||
} else {
|
||||
data["end"] = std::move(std::get<std::string>(*end));
|
||||
}
|
||||
}
|
||||
if (trackName) {
|
||||
data["track"] = std::move(*trackName);
|
||||
}
|
||||
if (trackGroup) {
|
||||
data["trackGroup"] = std::move(*trackGroup);
|
||||
}
|
||||
if (color) {
|
||||
data["color"] = consoleTimeStampColorToString(*color);
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (!tracingAtomic_) {
|
||||
return;
|
||||
}
|
||||
buffer_.emplace_back(TraceEvent{
|
||||
.name = "TimeStamp",
|
||||
.cat = "devtools.timeline",
|
||||
.ph = 'I',
|
||||
.ts = HighResTimeStamp::now(),
|
||||
.pid = processId_,
|
||||
.tid = oscompat::getCurrentThreadId(),
|
||||
.args = folly::dynamic::object("data", std::move(data)),
|
||||
});
|
||||
}
|
||||
|
||||
void PerformanceTracer::reportProcess(uint64_t id, const std::string& name) {
|
||||
if (!tracingAtomic_) {
|
||||
return;
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "CdpTracing.h"
|
||||
#include "ConsoleTimeStamp.h"
|
||||
#include "TraceEvent.h"
|
||||
#include "TraceEventProfile.h"
|
||||
|
||||
@@ -79,6 +80,21 @@ class PerformanceTracer {
|
||||
HighResDuration duration,
|
||||
const std::optional<DevToolsTrackEntryPayload>& trackMetadata);
|
||||
|
||||
/**
|
||||
* Record a "TimeStamp" Trace Event - a labelled entry on Performance
|
||||
* timeline. The only required argument is `name`. Optional arguments, if not
|
||||
* provided, won't be recorded in the serialized Trace Event.
|
||||
* @see
|
||||
https://developer.chrome.com/docs/devtools/performance/extension#inject_your_data_with_consoletimestamp
|
||||
*/
|
||||
void reportTimeStamp(
|
||||
std::string name,
|
||||
std::optional<ConsoleTimeStampEntry> start = std::nullopt,
|
||||
std::optional<ConsoleTimeStampEntry> end = std::nullopt,
|
||||
std::optional<std::string> trackName = std::nullopt,
|
||||
std::optional<std::string> trackGroup = std::nullopt,
|
||||
std::optional<ConsoleTimeStampColor> color = std::nullopt);
|
||||
|
||||
/**
|
||||
* Record a corresponding Trace Event for OS-level process.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user