@vpalmisano/webrtcperf 4.2.2 → 4.3.2
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.d.ts +13 -4
- package/build/src/app.js +145 -119
- package/build/src/app.js.map +1 -1
- package/build/src/config.d.ts +1 -1
- package/build/src/config.js +30 -24
- package/build/src/config.js.map +1 -1
- package/build/src/server.js +28 -10
- package/build/src/server.js.map +1 -1
- package/build/src/stats.d.ts +8 -21
- package/build/src/stats.js +48 -17
- package/build/src/stats.js.map +1 -1
- package/build/src/utils.d.ts +1 -1
- package/build/src/utils.js +9 -10
- package/build/src/utils.js.map +1 -1
- package/build/tsconfig.tsbuildinfo +1 -1
- package/package.json +23 -23
- package/src/app.ts +154 -130
- package/src/config.ts +28 -23
- package/src/server.ts +33 -13
- package/src/stats.ts +56 -25
- package/src/utils.ts +10 -12
package/src/stats.ts
CHANGED
|
@@ -32,23 +32,19 @@ function calculateFailAmountPercentile(stat: FastStats, percentile = 95): number
|
|
|
32
32
|
class StatsWriter {
|
|
33
33
|
fname: string
|
|
34
34
|
columns: string[]
|
|
35
|
-
private
|
|
35
|
+
private headerWritten = false
|
|
36
36
|
|
|
37
37
|
constructor(fname = 'stats.log', columns: string[]) {
|
|
38
38
|
this.fname = fname
|
|
39
39
|
this.columns = columns
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
* @param dataColumns
|
|
45
|
-
*/
|
|
46
|
-
async push(dataColumns: string[]): Promise<void> {
|
|
47
|
-
if (!this._header_written) {
|
|
42
|
+
async push(dataColumns: string[], append = true): Promise<void> {
|
|
43
|
+
if (!this.headerWritten || !append) {
|
|
48
44
|
const data = ['datetime', ...this.columns].join(',') + '\n'
|
|
49
45
|
await fs.promises.mkdir(path.dirname(this.fname), { recursive: true })
|
|
50
46
|
await fs.promises.writeFile(this.fname, data)
|
|
51
|
-
this.
|
|
47
|
+
this.headerWritten = true
|
|
52
48
|
}
|
|
53
49
|
//
|
|
54
50
|
const data = [Date.now(), ...dataColumns].join(',') + '\n'
|
|
@@ -330,6 +326,7 @@ export class Stats extends events.EventEmitter {
|
|
|
330
326
|
nextSessionId: number
|
|
331
327
|
statsWriter: StatsWriter | null
|
|
332
328
|
detailedStatsWriter: StatsWriter | null
|
|
329
|
+
detailedStatsSummaryWriter: StatsWriter | null
|
|
333
330
|
private scheduler?: Scheduler
|
|
334
331
|
|
|
335
332
|
private alertRules: Record<string, AlertRule> | null = null
|
|
@@ -386,18 +383,18 @@ export class Stats extends events.EventEmitter {
|
|
|
386
383
|
|
|
387
384
|
collectedStats: Record<string, CollectedStats>
|
|
388
385
|
|
|
389
|
-
collectedStatsConfig = {
|
|
386
|
+
private collectedStatsConfig = {
|
|
390
387
|
url: '',
|
|
391
388
|
pages: 0,
|
|
392
389
|
startTime: 0,
|
|
393
390
|
}
|
|
394
|
-
externalCollectedStats = new Map<
|
|
391
|
+
private externalCollectedStats = new Map<
|
|
395
392
|
string,
|
|
396
393
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
397
394
|
{ addedTime: number; externalStats: any; config: any }
|
|
398
395
|
>()
|
|
399
|
-
pushStatsInstance: axios.AxiosInstance | null = null
|
|
400
|
-
|
|
396
|
+
private pushStatsInstance: axios.AxiosInstance | null = null
|
|
397
|
+
private detailedStatsSummary: Record<string, Record<string, FastStats>> = {}
|
|
401
398
|
private running = false
|
|
402
399
|
|
|
403
400
|
/**
|
|
@@ -485,6 +482,7 @@ export class Stats extends events.EventEmitter {
|
|
|
485
482
|
|
|
486
483
|
this.statsWriter = null
|
|
487
484
|
this.detailedStatsWriter = null
|
|
485
|
+
this.detailedStatsSummaryWriter = null
|
|
488
486
|
if (alertRules.trim()) {
|
|
489
487
|
this.alertRules = json5.parse(alertRules)
|
|
490
488
|
log.debug(`using alertRules: ${JSON.stringify(this.alertRules, undefined, 2)}`)
|
|
@@ -615,6 +613,11 @@ export class Stats extends events.EventEmitter {
|
|
|
615
613
|
'trackId',
|
|
616
614
|
...this.statsNames,
|
|
617
615
|
])
|
|
616
|
+
this.detailedStatsSummaryWriter = new StatsWriter(this.detailedStatsPath.replace(/\.(.+)$/, '-summary.$1'), [
|
|
617
|
+
'participantName',
|
|
618
|
+
'trackId',
|
|
619
|
+
...this.statsNames,
|
|
620
|
+
])
|
|
618
621
|
}
|
|
619
622
|
|
|
620
623
|
if (this.prometheusPushgateway) {
|
|
@@ -821,8 +824,7 @@ export class Stats extends events.EventEmitter {
|
|
|
821
824
|
collectedStats.all.push(obj)
|
|
822
825
|
} else {
|
|
823
826
|
for (const [key, value] of Object.entries(obj)) {
|
|
824
|
-
|
|
825
|
-
if (typeof value === 'number' && isFinite(value as any)) {
|
|
827
|
+
if (typeof value === 'number' && isFinite(value)) {
|
|
826
828
|
collectedStats.all.push(value)
|
|
827
829
|
// Push host label.
|
|
828
830
|
const { trackId, hostName, participantName } = parseRtStatKey(key)
|
|
@@ -955,7 +957,7 @@ export class Stats extends events.EventEmitter {
|
|
|
955
957
|
|
|
956
958
|
async writeDetailedStats() {
|
|
957
959
|
if (!this.detailedStatsWriter) return
|
|
958
|
-
const participantTrackStats = new Map<string, Record<string,
|
|
960
|
+
const participantTrackStats = new Map<string, Record<string, number>>()
|
|
959
961
|
Object.entries(this.collectedStats).forEach(([name, stats]) => {
|
|
960
962
|
Object.entries(stats.byParticipantAndTrack).forEach(([label, value]) => {
|
|
961
963
|
let stats = participantTrackStats.get(label)
|
|
@@ -963,19 +965,47 @@ export class Stats extends events.EventEmitter {
|
|
|
963
965
|
stats = {}
|
|
964
966
|
participantTrackStats.set(label, stats)
|
|
965
967
|
}
|
|
966
|
-
stats[name] =
|
|
968
|
+
stats[name] = value
|
|
967
969
|
})
|
|
968
970
|
})
|
|
969
971
|
for (const [label, trackStats] of participantTrackStats.entries()) {
|
|
970
972
|
const [participantName, trackId] = label.split(':', 2)
|
|
973
|
+
if (!this.detailedStatsSummary[label]) {
|
|
974
|
+
this.detailedStatsSummary[label] = {}
|
|
975
|
+
}
|
|
976
|
+
const summary = this.detailedStatsSummary[label]
|
|
971
977
|
const values = [participantName, trackId]
|
|
972
978
|
for (const name of this.statsNames) {
|
|
973
|
-
values.push(trackStats[name]
|
|
979
|
+
values.push(trackStats[name] !== undefined ? toPrecision(trackStats[name], 6) : '')
|
|
980
|
+
// Update the summary stats.
|
|
981
|
+
if (!summary[name]) {
|
|
982
|
+
summary[name] = new FastStats({ store_data: false })
|
|
983
|
+
}
|
|
984
|
+
const stat = summary[name]
|
|
985
|
+
if (trackStats[name] !== undefined) {
|
|
986
|
+
stat.push(trackStats[name])
|
|
987
|
+
}
|
|
974
988
|
}
|
|
975
989
|
await this.detailedStatsWriter.push(values)
|
|
976
990
|
}
|
|
977
991
|
}
|
|
978
992
|
|
|
993
|
+
async writeDetailedStatsSummary() {
|
|
994
|
+
if (!this.detailedStatsSummaryWriter) return
|
|
995
|
+
let append = false
|
|
996
|
+
for (const label of Object.keys(this.detailedStatsSummary)) {
|
|
997
|
+
const summary = this.detailedStatsSummary[label]
|
|
998
|
+
const [participantName, trackId] = label.split(':', 2)
|
|
999
|
+
const values = [participantName, trackId]
|
|
1000
|
+
for (const name of this.statsNames) {
|
|
1001
|
+
const stat = summary[name]
|
|
1002
|
+
values.push(stat?.length > 0 ? toPrecision(stat.amean(), 6) : '')
|
|
1003
|
+
}
|
|
1004
|
+
await this.detailedStatsSummaryWriter.push(values, append)
|
|
1005
|
+
append = true
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
|
|
979
1009
|
/**
|
|
980
1010
|
* addCollectedStats
|
|
981
1011
|
* @param id
|
|
@@ -1652,17 +1682,13 @@ export class Stats extends events.EventEmitter {
|
|
|
1652
1682
|
}
|
|
1653
1683
|
}
|
|
1654
1684
|
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
*/
|
|
1658
|
-
async stop(): Promise<void> {
|
|
1659
|
-
if (!this.running) {
|
|
1660
|
-
return
|
|
1661
|
-
}
|
|
1685
|
+
async stop() {
|
|
1686
|
+
if (!this.running) return
|
|
1662
1687
|
this.running = false
|
|
1663
1688
|
log.debug('stop')
|
|
1689
|
+
|
|
1664
1690
|
if (this.scheduler) {
|
|
1665
|
-
this.scheduler.stop()
|
|
1691
|
+
await this.scheduler.stop()
|
|
1666
1692
|
this.scheduler = undefined
|
|
1667
1693
|
}
|
|
1668
1694
|
|
|
@@ -1676,7 +1702,12 @@ export class Stats extends events.EventEmitter {
|
|
|
1676
1702
|
}
|
|
1677
1703
|
this.sessions.clear()
|
|
1678
1704
|
|
|
1705
|
+
await this.writeDetailedStatsSummary()
|
|
1706
|
+
|
|
1679
1707
|
this.statsWriter = null
|
|
1708
|
+
this.detailedStatsWriter = null
|
|
1709
|
+
this.detailedStatsSummaryWriter = null
|
|
1710
|
+
this.detailedStatsSummary = {}
|
|
1680
1711
|
|
|
1681
1712
|
// delete metrics
|
|
1682
1713
|
if (this.gateway) {
|
package/src/utils.ts
CHANGED
|
@@ -291,7 +291,6 @@ export async function randomActivateAudio(
|
|
|
291
291
|
pages = pages.concat(sessionPages)
|
|
292
292
|
}
|
|
293
293
|
}
|
|
294
|
-
// Remove pages with no audio tracks.
|
|
295
294
|
for (const [i, page] of pages.entries()) {
|
|
296
295
|
if (!page) {
|
|
297
296
|
continue
|
|
@@ -307,15 +306,8 @@ export async function randomActivateAudio(
|
|
|
307
306
|
}
|
|
308
307
|
}
|
|
309
308
|
const pagesWithAudio: Page[] = pages.filter(p => !!p)
|
|
310
|
-
//
|
|
311
309
|
const index = Math.floor(Math.random() * pagesWithAudio.length)
|
|
312
310
|
const enable = Math.round(100 * Math.random()) <= randomAudioProbability
|
|
313
|
-
log.debug('randomActivateAudio %j', {
|
|
314
|
-
pages: pagesWithAudio.length,
|
|
315
|
-
randomAudioProbability,
|
|
316
|
-
index,
|
|
317
|
-
enable,
|
|
318
|
-
})
|
|
319
311
|
for (const [i, page] of pagesWithAudio.entries()) {
|
|
320
312
|
try {
|
|
321
313
|
if (i === index) {
|
|
@@ -613,7 +605,8 @@ SIGNALS.forEach(event =>
|
|
|
613
605
|
export async function checkChromeExecutable(): Promise<string> {
|
|
614
606
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
615
607
|
const { loadConfig } = require('./config')
|
|
616
|
-
const
|
|
608
|
+
const configs = await loadConfig()
|
|
609
|
+
const config = configs[0]
|
|
617
610
|
const cacheDir = path.join(os.homedir(), '.webrtcperf/chrome')
|
|
618
611
|
|
|
619
612
|
const fixSemVer = (v: string) => v.split('.').slice(0, 3).join('.')
|
|
@@ -806,21 +799,26 @@ export class Scheduler {
|
|
|
806
799
|
log.debug(`[${this.name}-scheduler] constructor interval=${this.interval}ms`)
|
|
807
800
|
}
|
|
808
801
|
|
|
809
|
-
start()
|
|
802
|
+
start() {
|
|
810
803
|
log.debug(`[${this.name}-scheduler] start`)
|
|
811
804
|
this.running = true
|
|
812
805
|
this.scheduleNext()
|
|
813
806
|
}
|
|
814
807
|
|
|
815
|
-
stop()
|
|
808
|
+
async stop() {
|
|
816
809
|
log.debug(`[${this.name}-scheduler] stop`)
|
|
817
810
|
this.running = false
|
|
818
811
|
if (this.statsTimeoutId) {
|
|
819
812
|
clearTimeout(this.statsTimeoutId)
|
|
820
813
|
}
|
|
814
|
+
try {
|
|
815
|
+
await this.callback(Date.now())
|
|
816
|
+
} catch (err) {
|
|
817
|
+
log.error(`[${this.name}-scheduler] stop callback error: ${(err as Error).stack}`, err)
|
|
818
|
+
}
|
|
821
819
|
}
|
|
822
820
|
|
|
823
|
-
private scheduleNext()
|
|
821
|
+
private scheduleNext() {
|
|
824
822
|
if (!this.running) {
|
|
825
823
|
return
|
|
826
824
|
}
|