Skip to content

Commit b039cd7

Browse files
committed
Remove the concept of static fields from the marker schema.
Use an optional description field instead. This causes less trouble with our Flow types. It's also a clearer API. And it will make it easier to switch marker.data from being an object to it being an array, in field order, because we'll be able to say that there should be one array element per field.
1 parent 9048722 commit b039cd7

26 files changed

+1032
-765
lines changed

docs-developer/CHANGELOG-formats.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,16 @@ Note that this is not an exhaustive list. Processed profile format upgraders can
66

77
## Processed profile format
88

9+
### Version 55
10+
11+
Changes to the `MarkerSchema` type which is used for the elements of the array at `profile.meta.markerSchema`:
12+
13+
- A new `description` field was added. This field is optional.
14+
- The `data` property was renamed to `fields`.
15+
- Every field must have a `key` and a `format` property now. There are no static fields any more.
16+
17+
Concretely, this means that if you have a `{ "label": "Description", value: "..." }` entry in your marker schema's `data` array, this entry needs to be removed and the description needs to be put into the `description` field instead, and the `data` property needs to be renamed to `fields`. If you have any other static fields, i.e. fields with `label` and `value` properties rather than `key` and `format` properties, then they need to be removed without replacement.
18+
919
### Version 54
1020

1121
The `implementation` column was removed from the frameTable. Modern profiles from Firefox use subcategories to represent the information about the JIT type of a JS frame.

src/app-logic/constants.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export const GECKO_PROFILE_VERSION = 31;
1414
// The current version of the "processed" profile format.
1515
// Please don't forget to update the processed profile format changelog in
1616
// `docs-developer/CHANGELOG-formats.md`.
17-
export const PROCESSED_PROFILE_VERSION = 54;
17+
export const PROCESSED_PROFILE_VERSION = 55;
1818

1919
// The following are the margin sizes for the left and right of the timeline. Independent
2020
// components need to share these values.

src/components/tooltip/Marker.js

Lines changed: 32 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -241,52 +241,43 @@ class MarkerTooltipContents extends React.PureComponent<Props> {
241241
// Add the details for the markers based on their Marker schema.
242242
const schema = getSchemaFromMarker(markerSchemaByName, marker.data);
243243
if (schema) {
244-
for (const schemaData of schema.data) {
245-
if (schemaData.hidden) {
246-
// Do not include the data field if it's marked as hidden.
244+
for (const field of schema.fields) {
245+
if (field.hidden) {
246+
// Do not include hidden fields.
247247
continue;
248248
}
249249

250-
// Check for a schema that is looking up and formatting a value from
251-
// the payload.
252-
if (schemaData.value === undefined) {
253-
const { key, label, format } = schemaData;
254-
if (key in data) {
255-
const value = data[key];
256-
257-
// Don't add undefined values, as values are optional.
258-
if (value !== undefined && value !== null) {
259-
details.push(
260-
<TooltipDetail
261-
key={schema.name + '-' + key}
262-
label={label || key}
263-
>
264-
{formatMarkupFromMarkerSchema(
265-
schema.name,
266-
format,
267-
value,
268-
thread.stringTable,
269-
threadIdToNameMap,
270-
processIdToNameMap
271-
)}
272-
</TooltipDetail>
273-
);
274-
}
275-
}
276-
}
250+
const { key, label, format } = field;
277251

278-
// Do a check to see if there is no key. This means this is a simple
279-
// label that is applied to every marker of this type, with no data
280-
// lookup. For some reason Flow as not able to refine this.
281-
if (schemaData.key === undefined) {
282-
const { label, value } = schemaData;
283-
const key = label + '-' + value;
284-
details.push(
285-
<TooltipDetail key={key} label={label}>
286-
<div className="tooltipDetailsDescription">{value}</div>
287-
</TooltipDetail>
288-
);
252+
const value = data[key];
253+
if (value === undefined || value === null) {
254+
// This marker doesn't have a value for this field. Values are optional.
255+
continue;
289256
}
257+
258+
details.push(
259+
<TooltipDetail key={schema.name + '-' + key} label={label || key}>
260+
{formatMarkupFromMarkerSchema(
261+
schema.name,
262+
format,
263+
value,
264+
thread.stringTable,
265+
threadIdToNameMap,
266+
processIdToNameMap
267+
)}
268+
</TooltipDetail>
269+
);
270+
}
271+
272+
if (schema.description) {
273+
const key = schema.name + '-description';
274+
details.push(
275+
<TooltipDetail key={key} label="Description">
276+
<div className="tooltipDetailsDescription">
277+
{schema.description}
278+
</div>
279+
</TooltipDetail>
280+
);
290281
}
291282
}
292283

src/profile-logic/import/chrome.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -939,7 +939,7 @@ function extractMarkers(
939939
tooltipLabel: '{marker.data.type2} - EventDispatch',
940940
tableLabel: '{marker.data.type2}',
941941
display: ['marker-chart', 'marker-table', 'timeline-overview'],
942-
data: [
942+
fields: [
943943
{
944944
// In the original chrome profile, the key is `type`, but we rename it
945945
// so that it doesn't clash with our internal `type` property.

src/profile-logic/marker-data.js

Lines changed: 22 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1434,36 +1434,29 @@ export function sanitizeFromMarkerSchema(
14341434
markerSchema: MarkerSchema,
14351435
markerPayload: MarkerPayload
14361436
): MarkerPayload {
1437-
for (const propertyDescription of markerSchema.data) {
1438-
if (
1439-
propertyDescription.key !== undefined &&
1440-
propertyDescription.format !== undefined
1441-
) {
1442-
const key = propertyDescription.key;
1443-
const format = propertyDescription.format;
1444-
if (!(key in markerPayload)) {
1445-
continue;
1446-
}
1437+
for (const { key, format } of markerSchema.fields) {
1438+
if (!(key in markerPayload)) {
1439+
continue;
1440+
}
14471441

1448-
// We're typing the result of the sanitization with `any` because Flow
1449-
// doesn't like much our enormous enum of non-exact objects that's used as
1450-
// MarkerPayload type, and this code is too generic for Flow in this context.
1451-
if (format === 'url') {
1452-
markerPayload = ({
1453-
...markerPayload,
1454-
[key]: removeURLs(markerPayload[key]),
1455-
}: any);
1456-
} else if (format === 'file-path') {
1457-
markerPayload = ({
1458-
...markerPayload,
1459-
[key]: removeFilePath(markerPayload[key]),
1460-
}: any);
1461-
} else if (format === 'sanitized-string') {
1462-
markerPayload = ({
1463-
...markerPayload,
1464-
[key]: '<sanitized>',
1465-
}: any);
1466-
}
1442+
// We're typing the result of the sanitization with `any` because Flow
1443+
// doesn't like much our enormous enum of non-exact objects that's used as
1444+
// MarkerPayload type, and this code is too generic for Flow in this context.
1445+
if (format === 'url') {
1446+
markerPayload = ({
1447+
...markerPayload,
1448+
[key]: removeURLs(markerPayload[key]),
1449+
}: any);
1450+
} else if (format === 'file-path') {
1451+
markerPayload = ({
1452+
...markerPayload,
1453+
[key]: removeFilePath(markerPayload[key]),
1454+
}: any);
1455+
} else if (format === 'sanitized-string') {
1456+
markerPayload = ({
1457+
...markerPayload,
1458+
[key]: '<sanitized>',
1459+
}: any);
14671460
}
14681461
}
14691462

src/profile-logic/marker-schema.js

Lines changed: 21 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,12 @@ export const markerSchemaFrontEndOnly: MarkerSchema[] = [
3939
display: ['marker-table', 'marker-chart'],
4040
tooltipLabel: 'Jank – event processing delay',
4141
tableLabel: 'Event processing delay',
42-
data: [
43-
{
44-
label: 'Description',
45-
value: oneLine`
46-
Jank markers show when the main event loop of a thread has been busy. It is
47-
a good indicator that there may be some kind of performance problem that
48-
is worth investigating.
49-
`,
50-
},
51-
],
42+
fields: [],
43+
description: oneLine`
44+
Jank markers show when the main event loop of a thread has been busy. It is
45+
a good indicator that there may be some kind of performance problem that
46+
is worth investigating.
47+
`,
5248
},
5349
// Note, these can also come from Gecko, but since we have lots of special handling
5450
// for IPC, the Gecko ones get overwritten by this definition.
@@ -58,17 +54,12 @@ export const markerSchemaFrontEndOnly: MarkerSchema[] = [
5854
tableLabel: '{marker.data.messageType} — {marker.data.niceDirection}',
5955
chartLabel: '{marker.data.messageType}',
6056
display: ['marker-chart', 'marker-table', 'timeline-ipc'],
61-
data: [
57+
fields: [
6258
{ key: 'messageType', label: 'Type', format: 'string', searchable: true },
6359
{ key: 'sync', label: 'Sync', format: 'string' },
6460
{ key: 'sendThreadName', label: 'From', format: 'string' },
6561
{ key: 'recvThreadName', label: 'To', format: 'string' },
66-
{
67-
key: 'otherPid',
68-
label: 'Other Pid',
69-
format: 'pid',
70-
searchable: true,
71-
},
62+
{ key: 'otherPid', label: 'Other Pid', format: 'pid', searchable: true },
7263
],
7364
},
7465
{
@@ -78,7 +69,7 @@ export const markerSchemaFrontEndOnly: MarkerSchema[] = [
7869
name: 'Network',
7970
display: ['marker-table', 'marker-chart'],
8071
chartLabel: '{marker.data.URI}',
81-
data: [
72+
fields: [
8273
{
8374
format: 'string',
8475
key: 'contentType',
@@ -212,11 +203,9 @@ export function parseLabel(
212203
// Handle: ^^^^^^^^^^^^^^^^
213204

214205
let format = null;
215-
for (const rule of markerSchema.data) {
216-
// The rule.value === undefined line is odd mainly because Flow was having trouble
217-
// refining the type.
218-
if (rule.value === undefined && rule.key === payloadKey) {
219-
format = rule.format;
206+
for (const field of markerSchema.fields) {
207+
if (field.key === payloadKey) {
208+
format = field.format;
220209
break;
221210
}
222211
}
@@ -634,19 +623,19 @@ export function markerPayloadMatchesSearch(
634623
}
635624

636625
// Check if searchable fields match the search regular expression.
637-
for (const payloadField of markerSchema.data) {
626+
for (const payloadField of markerSchema.fields) {
638627
if (payloadField.searchable) {
639628
let value = data[payloadField.key];
629+
if (value === undefined || value === null) {
630+
// The value is missing, but this is OK, values are optional.
631+
continue;
632+
}
633+
640634
if (
641635
payloadField.format === 'unique-string' ||
642636
payloadField.format === 'flow-id' ||
643637
payloadField.format === 'terminating-flow-id'
644638
) {
645-
if (value === undefined) {
646-
// The value is missing, but this is OK, values are optional.
647-
continue;
648-
}
649-
650639
if (typeof value !== 'number') {
651640
console.warn(
652641
`In marker ${marker.name}, the key ${payloadField.key} has an invalid value "${value}" as a unique string, it isn't a number.`
@@ -663,11 +652,7 @@ export function markerPayloadMatchesSearch(
663652
value = stringTable.getString(value);
664653
}
665654

666-
if (value === undefined || value === null || value === '') {
667-
continue;
668-
}
669-
670-
if (testFun(value, payloadField.key)) {
655+
if (value !== '' && testFun(value, payloadField.key)) {
671656
return true;
672657
}
673658
}
@@ -691,9 +676,9 @@ export function computeStringIndexMarkerFieldsByDataType(
691676
stringIndexMarkerFieldsByDataType.set('CompositorScreenshot', ['url']);
692677

693678
for (const schema of markerSchemas) {
694-
const { name, data } = schema;
679+
const { name, fields } = schema;
695680
const stringIndexFields = [];
696-
for (const field of data) {
681+
for (const field of fields) {
697682
if (field.format === 'unique-string' && field.key) {
698683
stringIndexFields.push(field.key);
699684
}

0 commit comments

Comments
 (0)