-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add conversion script to allow opening logs in Chrome devtools
In previous commit we allowed the users to send their performance logs by email to Cozy's support The sent file contains raw measurement data that cannot be easily read This script allows to convert the sent file to a format supported by Google Chrome's performance devtools In order to make it work, retrieve some user's logs and run the following command: ```shell yarn perf:convert <some_log_file_path> ``` A new file with the same name suffixed by `_converted` will be generated and can be imported to Google Chrome's performance devtools
- Loading branch information
Showing
2 changed files
with
170 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
// This script can be called using `yarn perf:convert <path_to_perf_logs>` | ||
|
||
import path from 'path' | ||
|
||
import fs from 'fs-extra' | ||
|
||
interface PerfEntry { | ||
name: string | ||
startTime: number | ||
duration: number | ||
initiatorType: string | ||
entryType: string | ||
detail?: { | ||
category?: string | ||
} | ||
} | ||
|
||
interface TrackInfo { | ||
color: string | ||
track: string | ||
} | ||
|
||
const convertFile = (): void => { | ||
const sourcePath = process.argv[2] | ||
|
||
if (!sourcePath) { | ||
console.error( | ||
'⚠️ Missing file path argument. Please provide a path to the source performance logs file' | ||
) | ||
return | ||
} | ||
|
||
const sourceFile = fs.readFileSync(sourcePath, 'utf-8') | ||
|
||
const performanceLogs = JSON.parse(sourceFile) as PerfEntry[] | ||
|
||
const minTimestamp = | ||
Math.min(...performanceLogs.map(entry => entry.startTime)) * 1000 | ||
const maxTimestamp = | ||
Math.max( | ||
...performanceLogs.map(entry => entry.startTime + entry.duration) | ||
) * 1000 | ||
|
||
const final = { | ||
metadata: { | ||
source: 'Cozy Flagship App', | ||
startTime: '2024-11-24T11:41:40.862Z', | ||
dataOrigin: 'TraceEvents' | ||
}, | ||
traceEvents: [ | ||
{ | ||
args: { | ||
data: { | ||
frameTreeNodeId: 1602, | ||
frames: [ | ||
{ | ||
frame: '58D933E9AC2121C7555CECAF5DABE9EA', | ||
isInPrimaryMainFrame: true, | ||
isOutermostMainFrame: true, | ||
name: '', | ||
processId: 1119, | ||
url: 'chrome://newtab/' | ||
} | ||
], | ||
persistentIds: true | ||
} | ||
}, | ||
cat: 'disabled-by-default-devtools.timeline', | ||
name: 'TracingStartedInBrowser', | ||
ph: 'I', | ||
pid: 1083, | ||
s: 't', | ||
tid: 259, | ||
ts: minTimestamp, | ||
tts: 1604839675 | ||
}, | ||
{ | ||
args: {}, | ||
cat: 'disabled-by-default-devtools.timeline', | ||
name: 'RunTask', | ||
ph: 'B', | ||
pid: 1094, | ||
tid: 20483, | ||
ts: maxTimestamp | ||
}, | ||
...performanceLogs.map((entry, index) => { | ||
return { | ||
args: { | ||
startTime: entry.startTime, | ||
detail: JSON.stringify({ | ||
devtools: { | ||
dataType: 'track-entry', | ||
...entryToTrack(entry), | ||
trackGroup: 'Cozy Flagship App' | ||
} | ||
}) | ||
}, | ||
cat: 'blink.user_timing', | ||
id2: { | ||
local: '0x' + index.toString(16) | ||
}, | ||
name: entry.name, | ||
ph: 'b', | ||
pid: index, | ||
tid: 259, | ||
ts: entry.startTime * 1000 | ||
} | ||
}), | ||
...performanceLogs.map((entry, index) => { | ||
return { | ||
args: {}, | ||
cat: 'blink.user_timing', | ||
id2: { | ||
local: '0x' + index.toString(16) | ||
}, | ||
name: entry.name, | ||
ph: 'e', | ||
pid: index, | ||
tid: 259, | ||
ts: (entry.startTime + entry.duration) * 1000 | ||
} | ||
}) | ||
] | ||
} | ||
|
||
const sourceFileName = path.basename(sourcePath, '.json') | ||
const sourceBasePath = path.dirname(sourcePath) | ||
const destinationPath = path.join( | ||
sourceBasePath, | ||
`${sourceFileName}_converted.json` | ||
) | ||
|
||
fs.writeFileSync(destinationPath, JSON.stringify(final), 'utf-8') | ||
} | ||
|
||
const entryToTrack = (entry: PerfEntry): TrackInfo => { | ||
const category = entry.detail?.category | ||
if (category) { | ||
return { | ||
color: 'primary', | ||
track: category | ||
} | ||
} | ||
if (entry.initiatorType === 'xmlhttprequest') { | ||
return { | ||
color: 'secondary', | ||
track: 'network' | ||
} | ||
} | ||
if (entry.entryType === 'mark') { | ||
if (entry.name.includes('SplashScreen')) { | ||
return { | ||
color: 'primary-light', | ||
track: 'splashscreen' | ||
} | ||
} | ||
|
||
return { | ||
color: 'primary-light', | ||
track: 'mark' | ||
} | ||
} | ||
return { | ||
color: 'tertiary', | ||
track: 'global' | ||
} | ||
} | ||
|
||
convertFile() |