feat(plugins): add Startup Timings (#189)
This commit is contained in:
parent
0cb24cad7e
commit
9663e229a6
2 changed files with 188 additions and 0 deletions
152
src/plugins/startupTimings/StartupTimingPage.tsx
Normal file
152
src/plugins/startupTimings/StartupTimingPage.tsx
Normal file
|
@ -0,0 +1,152 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a modification for Discord's desktop app
|
||||||
|
* Copyright (c) 2022 Vendicated and contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import ErrorBoundary from "../../components/ErrorBoundary";
|
||||||
|
import { Flex } from "../../components/Flex";
|
||||||
|
import { lazyWebpack } from "../../utils";
|
||||||
|
import { filters } from "../../webpack";
|
||||||
|
import { Forms, React } from "../../webpack/common";
|
||||||
|
|
||||||
|
interface AppStartPerformance {
|
||||||
|
prefix: string;
|
||||||
|
logs: Log[];
|
||||||
|
logGroups: LogGroup[];
|
||||||
|
endTime_: number;
|
||||||
|
isTracing_: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface LogGroup {
|
||||||
|
index: number;
|
||||||
|
timestamp: number;
|
||||||
|
logs: Log[];
|
||||||
|
nativeLogs: any[];
|
||||||
|
serverTrace: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Log {
|
||||||
|
emoji: string;
|
||||||
|
prefix: string;
|
||||||
|
log: string;
|
||||||
|
timestamp?: number;
|
||||||
|
delta?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const AppStartPerformance = lazyWebpack(filters.byProps("markWithDelta", "markAndLog", "markAt")) as AppStartPerformance;
|
||||||
|
|
||||||
|
interface TimerItemProps extends Log {
|
||||||
|
instance: {
|
||||||
|
sinceStart: number;
|
||||||
|
sinceLast: number;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function TimerItem({ emoji, prefix, log, delta, instance }: TimerItemProps) {
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<span>{instance.sinceStart.toFixed(3)}s</span>
|
||||||
|
<span>{instance.sinceLast.toFixed(3)}s</span>
|
||||||
|
<span>{delta?.toFixed(0) ?? ""}</span>
|
||||||
|
<span><pre>{emoji} {prefix ?? " "}{log}</pre></span>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TimingSectionProps {
|
||||||
|
title: string;
|
||||||
|
logs: Log[];
|
||||||
|
traceEnd?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
function TimingSection({ title, logs, traceEnd }: TimingSectionProps) {
|
||||||
|
const startTime = logs.find(l => l.timestamp)?.timestamp ?? 0;
|
||||||
|
|
||||||
|
let lastTimestamp = startTime;
|
||||||
|
const timings = logs.map(log => {
|
||||||
|
// Get last log entry with valid timestamp
|
||||||
|
const timestamp = log.timestamp ?? lastTimestamp;
|
||||||
|
|
||||||
|
const sinceStart = (timestamp - startTime) / 1000;
|
||||||
|
const sinceLast = (timestamp - lastTimestamp) / 1000;
|
||||||
|
|
||||||
|
lastTimestamp = timestamp;
|
||||||
|
|
||||||
|
return { sinceStart, sinceLast };
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Forms.FormSection title={title} tag={Forms.FormTitle.Tags.H1}>
|
||||||
|
<code>
|
||||||
|
{traceEnd && (
|
||||||
|
<div style={{ color: "var(--header-primary)", marginBottom: 5, userSelect: "text" }}>
|
||||||
|
Trace ended at: {(new Date(traceEnd)).toTimeString()}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div style={{ color: "var(--header-primary)", display: "grid", gridTemplateColumns: "repeat(3, auto) 1fr", gap: "2px 10px", userSelect: "text" }}>
|
||||||
|
<span>Start</span>
|
||||||
|
<span>Interval</span>
|
||||||
|
<span>Delta</span>
|
||||||
|
<span style={{ marginBottom: 5 }}>Event</span>
|
||||||
|
{AppStartPerformance.logs.map((log, i) => (
|
||||||
|
<TimerItem key={i} {...log} instance={timings[i]} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</code>
|
||||||
|
</Forms.FormSection>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ServerTraceProps {
|
||||||
|
trace: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function ServerTrace({ trace }: ServerTraceProps) {
|
||||||
|
const lines = trace.split("\n");
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Forms.FormSection title="Server Trace" tag={Forms.FormTitle.Tags.H2}>
|
||||||
|
<code>
|
||||||
|
<Flex flexDirection="column" style={{ color: "var(--header-primary)", gap: 5, userSelect: "text" }}>
|
||||||
|
{lines.map(line => (
|
||||||
|
<span>{line}</span>
|
||||||
|
))}
|
||||||
|
</Flex>
|
||||||
|
</code>
|
||||||
|
</Forms.FormSection>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function StartupTimingPage() {
|
||||||
|
if (!AppStartPerformance?.logs) return <div>Loading...</div>;
|
||||||
|
|
||||||
|
const serverTrace = AppStartPerformance.logGroups.find(g => g.serverTrace)?.serverTrace;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<TimingSection
|
||||||
|
title="Startup Timings"
|
||||||
|
logs={AppStartPerformance.logs}
|
||||||
|
traceEnd={AppStartPerformance.endTime_}
|
||||||
|
/>
|
||||||
|
{/* Lazy Divider */}
|
||||||
|
<div style={{ marginTop: 5 }}> </div>
|
||||||
|
{serverTrace && <ServerTrace trace={serverTrace} />}
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ErrorBoundary.wrap(StartupTimingPage);
|
36
src/plugins/startupTimings/index.tsx
Normal file
36
src/plugins/startupTimings/index.tsx
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a modification for Discord's desktop app
|
||||||
|
* Copyright (c) 2022 Vendicated and contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
import { LazyComponent } from "../../utils";
|
||||||
|
import { Devs } from "../../utils/constants";
|
||||||
|
import definePlugin from "../../utils/types";
|
||||||
|
|
||||||
|
export default definePlugin({
|
||||||
|
name: "StartupTimings",
|
||||||
|
description: "Adds Startup Timings to the Settings menu",
|
||||||
|
authors: [Devs.Megu],
|
||||||
|
patches: [{
|
||||||
|
find: "PAYMENT_FLOW_MODAL_TEST_PAGE,",
|
||||||
|
replacement: {
|
||||||
|
match: /({section:[\w.]+?\.PAYMENT_FLOW_MODAL_TEST_PAGE,)/,
|
||||||
|
replace: '{section:"StartupTimings",label:"Startup Timings",element:Vencord.Plugins.plugins.StartupTimings.StartupTimingPage},$1'
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
StartupTimingPage: LazyComponent(() => require("./StartupTimingPage").default)
|
||||||
|
});
|
Loading…
Reference in a new issue