@vpalmisano/webrtcperf 4.3.2 → 4.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app.min.js +1 -1
- package/build/src/app.js +16 -5
- package/build/src/app.js.map +1 -1
- package/build/src/docker.d.ts +1 -0
- package/build/src/docker.js +123 -0
- package/build/src/docker.js.map +1 -0
- package/build/src/session.js +12 -5
- package/build/src/session.js.map +1 -1
- package/build/src/utils.d.ts +5 -1
- package/build/src/utils.js +22 -14
- package/build/src/utils.js.map +1 -1
- package/build/tsconfig.tsbuildinfo +1 -1
- package/package.json +18 -16
- package/src/app.ts +17 -7
- package/src/docker.ts +131 -0
- package/src/session.ts +12 -5
- package/src/utils.ts +22 -13
package/src/docker.ts
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import path from 'path'
|
|
2
|
+
import Docker from 'dockerode'
|
|
3
|
+
import { logger, resolvePackagePath } from './utils'
|
|
4
|
+
import { loadConfig } from './config'
|
|
5
|
+
import fs from 'fs'
|
|
6
|
+
|
|
7
|
+
const log = logger('webrtcperf:docker')
|
|
8
|
+
|
|
9
|
+
export async function runWithDocker(argv: string[]) {
|
|
10
|
+
const docker = new Docker()
|
|
11
|
+
const configPath = argv.filter(s => s !== '--docker')[0]
|
|
12
|
+
if (!configPath) throw new Error('No configuration file specified')
|
|
13
|
+
const configName = path.basename(configPath)
|
|
14
|
+
const config = (await loadConfig(configPath))[0]
|
|
15
|
+
|
|
16
|
+
const startTimestamp = Date.now()
|
|
17
|
+
const dataDir = path.resolve(path.dirname(configPath), 'logs', `${startTimestamp}`)
|
|
18
|
+
await fs.promises.mkdir(dataDir, { recursive: true })
|
|
19
|
+
|
|
20
|
+
const binds: string[] = [
|
|
21
|
+
`${path.resolve(configPath)}:/config/${configName}:ro`,
|
|
22
|
+
'/dev/shm:/dev/shm',
|
|
23
|
+
`${dataDir}:/data`,
|
|
24
|
+
'/tmp/webrtcperf-cache:/root/.webrtcperf',
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
if (config.scriptPath) {
|
|
28
|
+
const scriptName = path.basename(config.scriptPath)
|
|
29
|
+
binds.push(`${path.resolve(config.scriptPath)}:/scripts/${scriptName}:ro`)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (process.env.DEBUG_SRC) {
|
|
33
|
+
binds.push(`${resolvePackagePath('app.min.js')}:/app/app.min.js:ro`)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const portBindings: Docker.PortMap = {}
|
|
37
|
+
const exposedPorts: { [portAndProtocol: string]: object } = {}
|
|
38
|
+
if (config.debuggingPort) {
|
|
39
|
+
for (let i = 0; i < config.sessions; i++) {
|
|
40
|
+
const port = `${config.debuggingPort + i}/tcp`
|
|
41
|
+
portBindings[port] = [{ HostPort: `${config.debuggingPort + i}` }]
|
|
42
|
+
exposedPorts[port] = {}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const env = [
|
|
47
|
+
`DEBUG_LEVEL=${process.env.DEBUG_LEVEL || 'info'}`,
|
|
48
|
+
'SHOW_PAGE_LOG=false',
|
|
49
|
+
'SHOW_STATS=false',
|
|
50
|
+
'SERVER_PORT=5000',
|
|
51
|
+
'SERVER_USE_HTTPS=true',
|
|
52
|
+
'SERVER_DATA=/data',
|
|
53
|
+
`START_TIMESTAMP=${startTimestamp}`,
|
|
54
|
+
`STATS_PATH=/data/stats.csv`,
|
|
55
|
+
`PAGE_LOG_PATH=/data/page.log`,
|
|
56
|
+
`DETAILED_STATS_PATH=/data/detailed-stats.csv`,
|
|
57
|
+
]
|
|
58
|
+
|
|
59
|
+
if (config.scriptPath) {
|
|
60
|
+
const scriptName = path.basename(config.scriptPath)
|
|
61
|
+
env.push(`SCRIPT_PATH=/scripts/${scriptName}`)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (config.debuggingPort) {
|
|
65
|
+
env.push(`DEBUGGING_PORT=${config.debuggingPort}`)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (config.prometheusPushgateway.startsWith('http://localhost')) {
|
|
69
|
+
env.push('PROMETHEUS_PUSHGATEWAY=http://pushgateway:9091')
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const containerConfig: Docker.ContainerCreateOptions = {
|
|
73
|
+
Image: 'ghcr.io/vpalmisano/webrtcperf:devel',
|
|
74
|
+
name: 'webrtcperf',
|
|
75
|
+
Cmd: [`/config/${configName}`],
|
|
76
|
+
HostConfig: {
|
|
77
|
+
Binds: binds,
|
|
78
|
+
PortBindings: portBindings,
|
|
79
|
+
CapAdd: ['NET_ADMIN'],
|
|
80
|
+
NetworkMode: config.prometheusPushgateway.startsWith('http://localhost') ? 'prometheus-stack_default' : 'bridge',
|
|
81
|
+
},
|
|
82
|
+
Env: env,
|
|
83
|
+
AttachStdin: true,
|
|
84
|
+
AttachStdout: true,
|
|
85
|
+
AttachStderr: true,
|
|
86
|
+
Tty: true,
|
|
87
|
+
OpenStdin: true,
|
|
88
|
+
StdinOnce: true,
|
|
89
|
+
ExposedPorts: exposedPorts,
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
try {
|
|
93
|
+
if (!process.env.DEBUG_SRC) {
|
|
94
|
+
log.info('Pulling latest development image...')
|
|
95
|
+
await docker.pull('ghcr.io/vpalmisano/webrtcperf:devel')
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
try {
|
|
99
|
+
const existingContainer = await docker.getContainer('webrtcperf')
|
|
100
|
+
await existingContainer.remove({ force: true })
|
|
101
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
102
|
+
} catch (err: unknown) {
|
|
103
|
+
// Container doesn't exist, continue
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const container = await docker.createContainer(containerConfig)
|
|
107
|
+
await container.start()
|
|
108
|
+
|
|
109
|
+
const stream = await container.attach({
|
|
110
|
+
stream: true,
|
|
111
|
+
stdin: true,
|
|
112
|
+
stdout: true,
|
|
113
|
+
stderr: true,
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
process.stdin.pipe(stream)
|
|
117
|
+
stream.pipe(process.stdout)
|
|
118
|
+
|
|
119
|
+
await new Promise(resolve => {
|
|
120
|
+
container.wait((err: Error, data: { StatusCode: number }) => {
|
|
121
|
+
if (err) log.error('Error waiting for container:', data, err.stack)
|
|
122
|
+
resolve(data)
|
|
123
|
+
})
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
await container.remove()
|
|
127
|
+
} catch (error) {
|
|
128
|
+
log.error('Docker operation failed:', error)
|
|
129
|
+
throw error
|
|
130
|
+
}
|
|
131
|
+
}
|
package/src/session.ts
CHANGED
|
@@ -676,7 +676,7 @@ export class Session extends EventEmitter {
|
|
|
676
676
|
deviceScaleFactor: this.deviceScaleFactor,
|
|
677
677
|
isMobile: false,
|
|
678
678
|
hasTouch: false,
|
|
679
|
-
isLandscape:
|
|
679
|
+
isLandscape: true,
|
|
680
680
|
},
|
|
681
681
|
})
|
|
682
682
|
} catch (err) {
|
|
@@ -803,7 +803,7 @@ try {
|
|
|
803
803
|
} catch (err) {
|
|
804
804
|
console.error('[webrtcperf] Error parsing scriptParams:', err);
|
|
805
805
|
webrtcperf.params = {};
|
|
806
|
-
}
|
|
806
|
+
};
|
|
807
807
|
`
|
|
808
808
|
|
|
809
809
|
if (this.serverPort) {
|
|
@@ -910,15 +910,22 @@ webrtcperf.config.AUDIO_URL = "http${this.serverUseHttps ? 's' : ''}://localhost
|
|
|
910
910
|
if (this.localStorage) {
|
|
911
911
|
log.debug('Using localStorage:', this.localStorage)
|
|
912
912
|
Object.entries(this.localStorage).map(([key, value]) => {
|
|
913
|
-
cmd += `localStorage.setItem('${key}',
|
|
913
|
+
cmd += `window.localStorage.setItem('${key}', ${JSON.stringify(value)});\n`
|
|
914
914
|
})
|
|
915
915
|
}
|
|
916
916
|
if (this.sessionStorage) {
|
|
917
917
|
log.debug('Using sessionStorage:', this.sessionStorage)
|
|
918
918
|
Object.entries(this.sessionStorage).map(([key, value]) => {
|
|
919
|
-
cmd += `sessionStorage.setItem('${key}',
|
|
919
|
+
cmd += `window.sessionStorage.setItem('${key}', ${JSON.stringify(value)});\n`
|
|
920
920
|
})
|
|
921
921
|
}
|
|
922
|
+
cmd += `
|
|
923
|
+
Object.defineProperty(window.screen, 'width', { value: ${this.windowWidth}, writable: false });
|
|
924
|
+
Object.defineProperty(window.screen, 'height', { value: ${this.windowHeight}, writable: false });
|
|
925
|
+
Object.defineProperty(window.screen, 'availWidth', { value: ${this.windowWidth}, writable: false });
|
|
926
|
+
Object.defineProperty(window.screen, 'availHeight', { value: ${this.windowHeight}, writable: false });
|
|
927
|
+
Object.defineProperty(window.screen.orientation, 'type', { value: 'landscape-primary', writable: false });
|
|
928
|
+
`
|
|
922
929
|
log.debug('init command:', cmd)
|
|
923
930
|
await page.evaluateOnNewDocument(cmd)
|
|
924
931
|
|
|
@@ -1305,7 +1312,7 @@ webrtcperf.config.AUDIO_URL = "http${this.serverUseHttps ? 's' : ''}://localhost
|
|
|
1305
1312
|
if (this.showPageLog || saveFile) {
|
|
1306
1313
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1307
1314
|
page.on('pageerror', async (error: any) => {
|
|
1308
|
-
const text = `pageerror: ${error
|
|
1315
|
+
const text = `pageerror: ${error?.message?.message || error?.message || error} - ${error?.message?.stack || error?.stack}`
|
|
1309
1316
|
await this.onPageMessage(index, 'error', text, saveFile)
|
|
1310
1317
|
})
|
|
1311
1318
|
|
package/src/utils.ts
CHANGED
|
@@ -651,28 +651,37 @@ export async function runShellCommand(
|
|
|
651
651
|
cmd: string,
|
|
652
652
|
verbose = false,
|
|
653
653
|
maxBuffer = 1024 * 1024,
|
|
654
|
+
{ provideStdin = false, returnStdout = true, returnStderr = true } = {},
|
|
654
655
|
): Promise<{ stdout: string; stderr: string }> {
|
|
655
656
|
if (verbose) log.debug(`runShellCommand cmd: ${cmd}`)
|
|
656
657
|
return new Promise((resolve, reject) => {
|
|
657
658
|
const p = spawn(cmd, {
|
|
658
659
|
shell: true,
|
|
659
|
-
stdio: [
|
|
660
|
+
stdio: [
|
|
661
|
+
provideStdin ? 'inherit' : 'ignore',
|
|
662
|
+
returnStdout ? 'pipe' : 'inherit',
|
|
663
|
+
returnStderr ? 'pipe' : 'inherit',
|
|
664
|
+
],
|
|
660
665
|
detached: true,
|
|
661
666
|
})
|
|
662
667
|
let stdout = ''
|
|
663
668
|
let stderr = ''
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
669
|
+
if (returnStdout) {
|
|
670
|
+
p.stdout?.on('data', data => {
|
|
671
|
+
if (maxBuffer && stdout.length > maxBuffer) {
|
|
672
|
+
stdout = stdout.slice(data.length)
|
|
673
|
+
}
|
|
674
|
+
stdout += data
|
|
675
|
+
})
|
|
676
|
+
}
|
|
677
|
+
if (returnStderr) {
|
|
678
|
+
p.stderr?.on('data', data => {
|
|
679
|
+
if (maxBuffer && stderr.length > maxBuffer) {
|
|
680
|
+
stderr = stderr.slice(data.length)
|
|
681
|
+
}
|
|
682
|
+
stderr += data
|
|
683
|
+
})
|
|
684
|
+
}
|
|
676
685
|
p.once('error', err => reject(err))
|
|
677
686
|
p.once('close', code => {
|
|
678
687
|
if (code !== 0) {
|