Add CLI perf command to toggle request timing on proxied apps
This commit is contained in:
parent
1e4d66cbe4
commit
c3ad78f1be
|
|
@ -16,3 +16,4 @@ export {
|
|||
unshareApp,
|
||||
} from './manage'
|
||||
export { metricsApp } from './metrics'
|
||||
export { perfToggle } from './perf'
|
||||
|
|
|
|||
30
src/cli/commands/perf.ts
Normal file
30
src/cli/commands/perf.ts
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
import color from 'ansis'
|
||||
import { get, handleError, post } from '../http'
|
||||
|
||||
interface PerfState {
|
||||
perfTiming: boolean
|
||||
}
|
||||
|
||||
export async function perfToggle(onOff?: string) {
|
||||
try {
|
||||
if (onOff === undefined) {
|
||||
// Toggle
|
||||
const res = await post<PerfState>('/api/system/perf')
|
||||
if (res) console.log(`Perf timing ${res.perfTiming ? color.green('on') : color.red('off')}`)
|
||||
} else if (onOff === 'on') {
|
||||
const res = await post<PerfState>('/api/system/perf', { on: true })
|
||||
if (res) console.log(`Perf timing ${color.green('on')}`)
|
||||
} else if (onOff === 'off') {
|
||||
const res = await post<PerfState>('/api/system/perf', { on: false })
|
||||
if (res) console.log(`Perf timing ${color.red('off')}`)
|
||||
} else if (onOff === 'status') {
|
||||
const res = await get<PerfState>('/api/system/perf')
|
||||
if (res) console.log(`Perf timing is ${res.perfTiming ? color.green('on') : color.red('off')}`)
|
||||
} else {
|
||||
console.error('Usage: toes perf [on|off|status]')
|
||||
process.exit(1)
|
||||
}
|
||||
} catch (error) {
|
||||
handleError(error)
|
||||
}
|
||||
}
|
||||
|
|
@ -24,6 +24,7 @@ import {
|
|||
shareApp,
|
||||
startApp,
|
||||
metricsApp,
|
||||
perfToggle,
|
||||
stopApp,
|
||||
unshareApp,
|
||||
} from './commands'
|
||||
|
|
@ -232,6 +233,13 @@ env
|
|||
.option('-g, --global', 'remove a global variable')
|
||||
.action(envRm)
|
||||
|
||||
program
|
||||
.command('perf')
|
||||
.helpGroup('Config:')
|
||||
.description('Toggle request timing for proxied app requests')
|
||||
.argument('[on|off|status]', 'enable, disable, or check status (toggles if omitted)')
|
||||
.action(perfToggle)
|
||||
|
||||
// Shell
|
||||
|
||||
program
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { allApps, APPS_DIR, onChange } from '$apps'
|
||||
import { perfTiming, setPerfTiming } from '../proxy'
|
||||
import { onHostLog } from '../tui'
|
||||
import { Hype } from '@because/hype'
|
||||
import { cpus, freemem, platform, totalmem } from 'os'
|
||||
|
|
@ -283,6 +284,16 @@ onChange(collectLogs)
|
|||
// Subscribe to host-level log messages
|
||||
onHostLog(pushHostLog)
|
||||
|
||||
// Perf timing toggle
|
||||
router.get('/perf', c => c.json({ perfTiming }))
|
||||
router.post('/perf', async c => {
|
||||
const body = await c.req.json<{ on?: boolean }>()
|
||||
const on = body.on ?? !perfTiming
|
||||
setPerfTiming(on)
|
||||
console.log(`[perf] timing ${on ? 'enabled' : 'disabled'}`)
|
||||
return c.json({ perfTiming: on })
|
||||
})
|
||||
|
||||
// Restart server (systemd brings it back)
|
||||
router.post('/restart', c => {
|
||||
setTimeout(() => process.exit(0), 100)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,9 @@ import { getAppBySubdomain } from '$apps'
|
|||
|
||||
export type { WsData }
|
||||
|
||||
export let perfTiming = false
|
||||
export const setPerfTiming = (on: boolean) => { perfTiming = on }
|
||||
|
||||
const pendingMessages = new Map<ServerWebSocket<WsData>, (string | ArrayBuffer | Uint8Array)[]>()
|
||||
const upstreams = new Map<ServerWebSocket<WsData>, WebSocket>()
|
||||
|
||||
|
|
@ -53,12 +56,18 @@ export async function proxySubdomain(subdomain: string, req: Request): Promise<R
|
|||
headers.delete('transfer-encoding')
|
||||
|
||||
try {
|
||||
return await fetch(target, {
|
||||
const start = perfTiming ? performance.now() : 0
|
||||
const res = await fetch(target, {
|
||||
method: req.method,
|
||||
headers,
|
||||
body,
|
||||
redirect: 'manual',
|
||||
})
|
||||
if (perfTiming) {
|
||||
const ms = (performance.now() - start).toFixed(1)
|
||||
console.log(`[perf] ${req.method} ${subdomain}${url.pathname} → ${res.status} in ${ms}ms`)
|
||||
}
|
||||
return res
|
||||
} catch (e) {
|
||||
console.error(`Proxy error for ${subdomain}:`, e)
|
||||
return new Response(`App "${subdomain}" is not responding`, { status: 502 })
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user