mirror of
https://github.com/misskey-dev/misskey.git
synced 2026-07-25 16:45:00 +02:00
wip
This commit is contained in:
74
.github/scripts/chrome.mts
vendored
74
.github/scripts/chrome.mts
vendored
@@ -42,8 +42,23 @@ export type NetworkRequest = {
|
||||
errorText?: string;
|
||||
};
|
||||
|
||||
export type WebSocketConnection = {
|
||||
requestId: string;
|
||||
url: string;
|
||||
createdAt: number;
|
||||
handshakeRequestHeaders?: Record<string, string>;
|
||||
handshakeResponseStatus?: number;
|
||||
handshakeResponseStatusText?: string;
|
||||
handshakeResponseHeaders?: Record<string, string>;
|
||||
closedAt?: number;
|
||||
sentFrameCount: number;
|
||||
receivedFrameCount: number;
|
||||
errorCount: number;
|
||||
};
|
||||
|
||||
export type NetworkSummary = {
|
||||
requestCount: number;
|
||||
webSocketConnectionCount: number;
|
||||
finishedRequestCount: number;
|
||||
failedRequestCount: number;
|
||||
cachedRequestCount: number;
|
||||
@@ -332,6 +347,7 @@ export class Chrome {
|
||||
private handle: ChromeHandle;
|
||||
public cdp: CdpClient;
|
||||
public networkRequests: NetworkRequest[] = [];
|
||||
public webSocketConnections: WebSocketConnection[] = [];
|
||||
private scenarioTimeoutMs: number;
|
||||
private pendingNetworkDetailReads: Promise<void>[] = [];
|
||||
|
||||
@@ -369,6 +385,7 @@ export class Chrome {
|
||||
|
||||
public async enableNetworkTracking() {
|
||||
const requests = new Map<string, NetworkRequest>();
|
||||
const webSockets = new Map<string, WebSocketConnection>();
|
||||
|
||||
const readRequestBody = (row: NetworkRequest) => {
|
||||
if (!row.hasRequestBody || row.requestBody != null) return;
|
||||
@@ -405,6 +422,58 @@ export class Chrome {
|
||||
this.networkRequests.push(row);
|
||||
});
|
||||
|
||||
this.cdp.on('Network.webSocketCreated', params => {
|
||||
if (params.requestId == null || params.url == null) return;
|
||||
const row: WebSocketConnection = {
|
||||
requestId: params.requestId,
|
||||
url: params.url,
|
||||
createdAt: params.timestamp ?? 0,
|
||||
sentFrameCount: 0,
|
||||
receivedFrameCount: 0,
|
||||
errorCount: 0,
|
||||
};
|
||||
webSockets.set(params.requestId, row);
|
||||
this.webSocketConnections.push(row);
|
||||
});
|
||||
|
||||
this.cdp.on('Network.webSocketWillSendHandshakeRequest', params => {
|
||||
const row = webSockets.get(params.requestId);
|
||||
if (row == null) return;
|
||||
row.handshakeRequestHeaders = normalizeHeaders(params.request?.headers);
|
||||
});
|
||||
|
||||
this.cdp.on('Network.webSocketHandshakeResponseReceived', params => {
|
||||
const row = webSockets.get(params.requestId);
|
||||
if (row == null) return;
|
||||
row.handshakeResponseStatus = params.response?.status;
|
||||
row.handshakeResponseStatusText = params.response?.statusText;
|
||||
row.handshakeResponseHeaders = normalizeHeaders(params.response?.headers);
|
||||
});
|
||||
|
||||
this.cdp.on('Network.webSocketFrameSent', params => {
|
||||
const row = webSockets.get(params.requestId);
|
||||
if (row == null) return;
|
||||
row.sentFrameCount += 1;
|
||||
});
|
||||
|
||||
this.cdp.on('Network.webSocketFrameReceived', params => {
|
||||
const row = webSockets.get(params.requestId);
|
||||
if (row == null) return;
|
||||
row.receivedFrameCount += 1;
|
||||
});
|
||||
|
||||
this.cdp.on('Network.webSocketFrameError', params => {
|
||||
const row = webSockets.get(params.requestId);
|
||||
if (row == null) return;
|
||||
row.errorCount += 1;
|
||||
});
|
||||
|
||||
this.cdp.on('Network.webSocketClosed', params => {
|
||||
const row = webSockets.get(params.requestId);
|
||||
if (row == null) return;
|
||||
row.closedAt = params.timestamp ?? 0;
|
||||
});
|
||||
|
||||
this.cdp.on('Network.responseReceived', params => {
|
||||
const row = requests.get(params.requestId);
|
||||
if (row == null) return;
|
||||
@@ -609,7 +678,7 @@ function isMeasurableRequest(row: NetworkRequest) {
|
||||
return !row.url.startsWith('data:') && !row.url.startsWith('blob:') && !row.url.startsWith('devtools:');
|
||||
}
|
||||
|
||||
export function summarizeNetwork(requestRows: NetworkRequest[], baseUrl: string): NetworkSummary {
|
||||
export function summarizeNetwork(requestRows: NetworkRequest[], baseUrl: string, webSocketRows?: WebSocketConnection[]): NetworkSummary {
|
||||
const origin = new URL(baseUrl).origin;
|
||||
const rows = requestRows.filter(isMeasurableRequest);
|
||||
const byResourceType = {} as NetworkSummary['byResourceType'];
|
||||
@@ -636,6 +705,9 @@ export function summarizeNetwork(requestRows: NetworkRequest[], baseUrl: string)
|
||||
|
||||
return {
|
||||
requestCount: rows.length,
|
||||
webSocketConnectionCount: webSocketRows == null
|
||||
? rows.filter(row => row.resourceType === 'WebSocket').length
|
||||
: webSocketRows.length,
|
||||
finishedRequestCount: rows.filter(row => row.finished).length,
|
||||
failedRequestCount: rows.filter(row => row.failed).length,
|
||||
cachedRequestCount: rows.filter(row => row.fromDiskCache).length,
|
||||
|
||||
6
.github/scripts/frontend-browser-report.mts
vendored
6
.github/scripts/frontend-browser-report.mts
vendored
@@ -18,6 +18,7 @@ export type BrowserMeasurement = {
|
||||
durationMs: number;
|
||||
network: {
|
||||
requestCount: number;
|
||||
webSocketConnectionCount?: number;
|
||||
finishedRequestCount: number;
|
||||
failedRequestCount: number;
|
||||
cachedRequestCount: number;
|
||||
@@ -157,6 +158,10 @@ function resourceTypeSampleBytes(sample: BrowserMeasurementSample, resourceTypes
|
||||
return resourceTypeBytes(sample, resourceTypes);
|
||||
}
|
||||
|
||||
function webSocketConnectionCount(report: BrowserMeasurement) {
|
||||
return report.network.webSocketConnectionCount ?? report.network.byResourceType.WebSocket?.requests ?? 0;
|
||||
}
|
||||
|
||||
function getMetric(report: BrowserMeasurement, key: string) {
|
||||
return report.performance.cdpMetrics[key];
|
||||
}
|
||||
@@ -165,6 +170,7 @@ function renderSummaryTable(base: BrowserMetricsReport, head: BrowserMetricsRepo
|
||||
const rows = [
|
||||
//metricRow('Scenario duration', base, head, summary => summary.durationMs, sample => sample.durationMs, formatMs),
|
||||
metricRow('Requests', base, head, summary => summary.network.requestCount, sample => sample.network.requestCount, util.formatNumber),
|
||||
metricRow('WebSocket connections', base, head, webSocketConnectionCount, webSocketConnectionCount, util.formatNumber),
|
||||
//metricRow('Failed requests', base, head, summary => summary.network.failedRequestCount, sample => sample.network.failedRequestCount, util.formatNumber),
|
||||
metricRow('Encoded network', base, head, summary => summary.network.totalEncodedBytes, sample => sample.network.totalEncodedBytes, util.formatBytes, 10000),
|
||||
metricRow('Decoded body', base, head, summary => summary.network.totalDecodedBodyBytes, sample => sample.network.totalDecodedBodyBytes, util.formatBytes, 10000),
|
||||
|
||||
@@ -132,6 +132,7 @@ function summarizeNetworkSamples(samples: BrowserMeasurementSample[]): NetworkSu
|
||||
|
||||
return {
|
||||
requestCount: finiteMedian(samples.map(sample => sample.network.requestCount)),
|
||||
webSocketConnectionCount: finiteMedian(samples.map(sample => sample.network.webSocketConnectionCount)),
|
||||
finishedRequestCount: finiteMedian(samples.map(sample => sample.network.finishedRequestCount)),
|
||||
failedRequestCount: finiteMedian(samples.map(sample => sample.network.failedRequestCount)),
|
||||
cachedRequestCount: finiteMedian(samples.map(sample => sample.network.cachedRequestCount)),
|
||||
@@ -242,7 +243,7 @@ async function measureSample(label: 'base' | 'head', round: number, heapSnapshot
|
||||
url: baseUrl,
|
||||
scenario: 'fresh browser signup, first timeline note, after the note becomes visible',
|
||||
durationMs,
|
||||
network: summarizeNetwork(chrome.networkRequests, baseUrl),
|
||||
network: summarizeNetwork(chrome.networkRequests, baseUrl, chrome.webSocketConnections),
|
||||
networkRequests: chrome.networkRequests,
|
||||
performance,
|
||||
heapSnapshot,
|
||||
|
||||
2
.github/scripts/utility.mts
vendored
2
.github/scripts/utility.mts
vendored
@@ -5,7 +5,7 @@
|
||||
|
||||
// NOTE: このファイルはworkflow上でバックエンドからも参照されるため、side effectがあってはならない
|
||||
|
||||
import { ChildProcessWithoutNullStreams, spawn, spawnSync } from 'node:child_process';
|
||||
import { spawn, spawnSync, type ChildProcessWithoutNullStreams } from 'node:child_process';
|
||||
import { promises as fs } from 'node:fs';
|
||||
import path from 'node:path';
|
||||
|
||||
|
||||
Reference in New Issue
Block a user