|
| 1 | +/* |
| 2 | + * Copyright (c) Meta Platforms, Inc. and affiliates. |
| 3 | + * |
| 4 | + * This source code is licensed under the MIT license found in the |
| 5 | + * LICENSE file in the root directory of this source tree. |
| 6 | + */ |
| 7 | + |
| 8 | +#pragma once |
| 9 | + |
| 10 | +#include <folly/dynamic.h> |
| 11 | + |
| 12 | +#include <utility> |
| 13 | + |
| 14 | +namespace facebook::react::jsinspector_modern::tracing { |
| 15 | + |
| 16 | +/// Arbitrary data structure, which represents payload of the "ProfileChunk" |
| 17 | +/// Trace Event. |
| 18 | +struct TraceEventProfileChunk { |
| 19 | + /// Deltas between timestamps of chronolocigally sorted samples. |
| 20 | + /// Will be sent as part of the "ProfileChunk" trace event. |
| 21 | + struct TimeDeltas { |
| 22 | + public: |
| 23 | + explicit TimeDeltas(std::vector<long long> deltas) |
| 24 | + : deltas_(std::move(deltas)) {} |
| 25 | + |
| 26 | + folly::dynamic asDynamic() const { |
| 27 | + folly::dynamic value = folly::dynamic::array(); |
| 28 | + for (auto delta : deltas_) { |
| 29 | + value.push_back(delta); |
| 30 | + } |
| 31 | + |
| 32 | + return value; |
| 33 | + } |
| 34 | + |
| 35 | + private: |
| 36 | + std::vector<long long> deltas_; |
| 37 | + }; |
| 38 | + |
| 39 | + /// Contains Profile information that will be emitted in this chunk: nodes and |
| 40 | + /// sample root node ids. |
| 41 | + struct CPUProfile { |
| 42 | + /// Unique node in the profile tree, has unique id, call frame and |
| 43 | + /// optionally |
| 44 | + /// id of its parent node. Only root node has no parent. |
| 45 | + struct Node { |
| 46 | + /// Unique call frame in the call stack. |
| 47 | + struct CallFrame { |
| 48 | + public: |
| 49 | + CallFrame( |
| 50 | + std::string codeType, |
| 51 | + uint32_t scriptId, |
| 52 | + std::string functionName, |
| 53 | + std::optional<std::string> url = std::nullopt, |
| 54 | + std::optional<uint32_t> lineNumber = std::nullopt, |
| 55 | + std::optional<uint32_t> columnNumber = std::nullopt) |
| 56 | + : codeType_(std::move(codeType)), |
| 57 | + scriptId_(scriptId), |
| 58 | + functionName_(std::move(functionName)), |
| 59 | + url_(std::move(url)), |
| 60 | + lineNumber_(lineNumber), |
| 61 | + columnNumber_(columnNumber) {} |
| 62 | + |
| 63 | + folly::dynamic asDynamic() const { |
| 64 | + folly::dynamic dynamicCallFrame = folly::dynamic::object(); |
| 65 | + dynamicCallFrame["codeType"] = codeType_; |
| 66 | + dynamicCallFrame["scriptId"] = scriptId_; |
| 67 | + dynamicCallFrame["functionName"] = functionName_; |
| 68 | + if (url_.has_value()) { |
| 69 | + dynamicCallFrame["url"] = url_.value(); |
| 70 | + } |
| 71 | + if (lineNumber_.has_value()) { |
| 72 | + dynamicCallFrame["lineNumber"] = lineNumber_.value(); |
| 73 | + } |
| 74 | + if (columnNumber_.has_value()) { |
| 75 | + dynamicCallFrame["columnNumber"] = columnNumber_.value(); |
| 76 | + } |
| 77 | + |
| 78 | + return dynamicCallFrame; |
| 79 | + } |
| 80 | + |
| 81 | + private: |
| 82 | + std::string codeType_; |
| 83 | + uint32_t scriptId_; |
| 84 | + std::string functionName_; |
| 85 | + std::optional<std::string> url_; |
| 86 | + std::optional<uint32_t> lineNumber_; |
| 87 | + std::optional<uint32_t> columnNumber_; |
| 88 | + }; |
| 89 | + |
| 90 | + public: |
| 91 | + Node( |
| 92 | + uint32_t id, |
| 93 | + CallFrame callFrame, |
| 94 | + std::optional<uint32_t> parentId = std::nullopt) |
| 95 | + : id_(id), callFrame_(std::move(callFrame)), parentId_(parentId) {} |
| 96 | + |
| 97 | + folly::dynamic asDynamic() const { |
| 98 | + folly::dynamic dynamicNode = folly::dynamic::object(); |
| 99 | + |
| 100 | + dynamicNode["callFrame"] = callFrame_.asDynamic(); |
| 101 | + dynamicNode["id"] = id_; |
| 102 | + if (parentId_.has_value()) { |
| 103 | + dynamicNode["parent"] = parentId_.value(); |
| 104 | + } |
| 105 | + |
| 106 | + return dynamicNode; |
| 107 | + } |
| 108 | + |
| 109 | + private: |
| 110 | + uint32_t id_; |
| 111 | + CallFrame callFrame_; |
| 112 | + std::optional<uint32_t> parentId_; |
| 113 | + }; |
| 114 | + |
| 115 | + public: |
| 116 | + CPUProfile(std::vector<Node> nodes, std::vector<uint32_t> samples) |
| 117 | + : nodes_(std::move(nodes)), samples_(std::move(samples)) {} |
| 118 | + |
| 119 | + folly::dynamic asDynamic() const { |
| 120 | + folly::dynamic dynamicNodes = folly::dynamic::array(); |
| 121 | + for (const auto& node : nodes_) { |
| 122 | + dynamicNodes.push_back(node.asDynamic()); |
| 123 | + } |
| 124 | + |
| 125 | + folly::dynamic dynamicSamples = folly::dynamic::array(); |
| 126 | + for (auto sample : samples_) { |
| 127 | + dynamicSamples.push_back(sample); |
| 128 | + } |
| 129 | + |
| 130 | + return folly::dynamic::object("nodes", dynamicNodes)( |
| 131 | + "samples", dynamicSamples); |
| 132 | + } |
| 133 | + |
| 134 | + private: |
| 135 | + std::vector<Node> nodes_; |
| 136 | + std::vector<uint32_t> samples_; |
| 137 | + }; |
| 138 | + |
| 139 | + public: |
| 140 | + TraceEventProfileChunk(CPUProfile cpuProfile, TimeDeltas timeDeltas) |
| 141 | + : cpuProfile_(std::move(cpuProfile)), |
| 142 | + timeDeltas_(std::move(timeDeltas)) {} |
| 143 | + |
| 144 | + folly::dynamic asDynamic() const { |
| 145 | + folly::dynamic value = folly::dynamic::object; |
| 146 | + value["cpuProfile"] = cpuProfile_.asDynamic(); |
| 147 | + value["timeDeltas"] = timeDeltas_.asDynamic(); |
| 148 | + |
| 149 | + return value; |
| 150 | + } |
| 151 | + |
| 152 | + private: |
| 153 | + CPUProfile cpuProfile_; |
| 154 | + TimeDeltas timeDeltas_; |
| 155 | +}; |
| 156 | + |
| 157 | +} // namespace facebook::react::jsinspector_modern::tracing |
0 commit comments