Skip to content

Commit

Permalink
feat: Add conversion script to allow opening logs in Chrome devtools
Browse files Browse the repository at this point in the history
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
Ldoppea committed Dec 20, 2024
1 parent 95b2351 commit a1e7535
Show file tree
Hide file tree
Showing 2 changed files with 170 additions and 0 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"ios": "react-native run-ios",
"lint": "eslint 'src/**/*.{js,jsx,ts,tsx}'",
"log:android": "adb logcat *:S ReactNative:V ReactNativeJS:V",
"perf:convert": "yarn tsc --project scripts && node scripts/dist/convert-perf-logs.cmd.js",
"postinstall": "patch-package && yarn install:scripts && react-native setup-ios-permissions && pod-install",
"pre-commit": "yarn lint",
"start": "react-native start",
Expand Down
169 changes: 169 additions & 0 deletions scripts/convert-perf-logs.cmd.ts
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()

0 comments on commit a1e7535

Please sign in to comment.