Add p2p info to metrics
This commit is contained in:
parent
b63c607b92
commit
c6867725fb
15 changed files with 141 additions and 73 deletions
|
@ -203,7 +203,7 @@ export class PeerTubePlayer {
|
||||||
|
|
||||||
this.player.one('error', () => handleError())
|
this.player.one('error', () => handleError())
|
||||||
|
|
||||||
this.player.on('p2p-info', (_, data: PlayerNetworkInfo) => {
|
this.player.on('network-info', (_, data: PlayerNetworkInfo) => {
|
||||||
if (data.source !== 'p2p-media-loader' || isNaN(data.bandwidthEstimate)) return
|
if (data.source !== 'p2p-media-loader' || isNaN(data.bandwidthEstimate)) return
|
||||||
|
|
||||||
saveAverageBandwidth(data.bandwidthEstimate)
|
saveAverageBandwidth(data.bandwidthEstimate)
|
||||||
|
|
|
@ -39,15 +39,14 @@ class P2PInfoButton extends Button {
|
||||||
subDivP2P.appendChild(peersText)
|
subDivP2P.appendChild(peersText)
|
||||||
|
|
||||||
const subDivHttp = videojs.dom.createEl('div', { className: 'vjs-peertube-hidden' }) as HTMLElement
|
const subDivHttp = videojs.dom.createEl('div', { className: 'vjs-peertube-hidden' }) as HTMLElement
|
||||||
const subDivHttpText = videojs.dom.createEl('span', {
|
const subDivHttpText = videojs.dom.createEl('span', { className: 'http-fallback' })
|
||||||
className: 'http-fallback',
|
|
||||||
textContent: 'HTTP'
|
|
||||||
})
|
|
||||||
|
|
||||||
subDivHttp.appendChild(subDivHttpText)
|
subDivHttp.appendChild(subDivHttpText)
|
||||||
div.appendChild(subDivHttp)
|
div.appendChild(subDivHttp)
|
||||||
|
|
||||||
this.player_.on('p2p-info', (_event: any, data: PlayerNetworkInfo) => {
|
this.player_.on('network-info', (_event: any, data: PlayerNetworkInfo) => {
|
||||||
|
if (!data.p2p) return
|
||||||
|
|
||||||
subDivP2P.className = 'vjs-peertube-displayed'
|
subDivP2P.className = 'vjs-peertube-displayed'
|
||||||
subDivHttp.className = 'vjs-peertube-hidden'
|
subDivHttp.className = 'vjs-peertube-hidden'
|
||||||
|
|
||||||
|
@ -58,7 +57,7 @@ class P2PInfoButton extends Button {
|
||||||
const uploadSpeed = bytes(p2pStats.uploadSpeed)
|
const uploadSpeed = bytes(p2pStats.uploadSpeed)
|
||||||
const totalDownloaded = bytes(p2pStats.downloaded + httpStats.downloaded)
|
const totalDownloaded = bytes(p2pStats.downloaded + httpStats.downloaded)
|
||||||
const totalUploaded = bytes(p2pStats.uploaded)
|
const totalUploaded = bytes(p2pStats.uploaded)
|
||||||
const numPeers = p2pStats.numPeers
|
const numPeers = p2pStats.peersWithWebSeed
|
||||||
|
|
||||||
subDivP2P.title = this.player().localize('Total downloaded: ') + totalDownloaded.join(' ') + '\n'
|
subDivP2P.title = this.player().localize('Total downloaded: ') + totalDownloaded.join(' ') + '\n'
|
||||||
|
|
||||||
|
@ -85,8 +84,13 @@ class P2PInfoButton extends Button {
|
||||||
subDivP2P.className = 'vjs-peertube-displayed'
|
subDivP2P.className = 'vjs-peertube-displayed'
|
||||||
})
|
})
|
||||||
|
|
||||||
this.player_.on('http-info', (_event, data: PlayerNetworkInfo) => {
|
this.player_.on('network-info', (_event, data: PlayerNetworkInfo) => {
|
||||||
// We are in HTTP fallback
|
if (data.p2p) return
|
||||||
|
|
||||||
|
if (data.source === 'web-video') subDivHttpText.textContent = 'HTTP'
|
||||||
|
else if (data.source === 'p2p-media-loader') subDivHttpText.textContent = 'HLS'
|
||||||
|
|
||||||
|
// We are in HTTP mode
|
||||||
subDivHttp.className = 'vjs-peertube-displayed'
|
subDivHttp.className = 'vjs-peertube-displayed'
|
||||||
subDivP2P.className = 'vjs-peertube-hidden'
|
subDivP2P.className = 'vjs-peertube-hidden'
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ class MetricsPlugin extends Plugin {
|
||||||
private errors = 0
|
private errors = 0
|
||||||
|
|
||||||
private p2pEnabled: boolean
|
private p2pEnabled: boolean
|
||||||
private totalPeers = 0
|
private p2pPeers = 0
|
||||||
|
|
||||||
private lastPlayerNetworkInfo: PlayerNetworkInfo
|
private lastPlayerNetworkInfo: PlayerNetworkInfo
|
||||||
|
|
||||||
|
@ -111,12 +111,12 @@ class MetricsPlugin extends Plugin {
|
||||||
|
|
||||||
errors: this.errors,
|
errors: this.errors,
|
||||||
|
|
||||||
downloadedBytesP2P: this.downloadedBytesP2P,
|
|
||||||
downloadedBytesHTTP: this.downloadedBytesHTTP,
|
downloadedBytesHTTP: this.downloadedBytesHTTP,
|
||||||
|
|
||||||
|
downloadedBytesP2P: this.downloadedBytesP2P,
|
||||||
uploadedBytesP2P: this.uploadedBytesP2P,
|
uploadedBytesP2P: this.uploadedBytesP2P,
|
||||||
|
|
||||||
totalPeers: this.totalPeers,
|
p2pPeers: this.p2pPeers,
|
||||||
p2pEnabled: this.p2pEnabled,
|
p2pEnabled: this.p2pEnabled,
|
||||||
|
|
||||||
videoId: this.options_.videoUUID()
|
videoId: this.options_.videoUUID()
|
||||||
|
@ -139,23 +139,14 @@ class MetricsPlugin extends Plugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
private trackBytes () {
|
private trackBytes () {
|
||||||
this.player.on('p2p-info', (_event, data: PlayerNetworkInfo) => {
|
this.player.on('network-info', (_event, data: PlayerNetworkInfo) => {
|
||||||
this.downloadedBytesHTTP += Math.round(data.http.downloaded - (this.lastPlayerNetworkInfo?.http.downloaded || 0))
|
this.downloadedBytesHTTP += Math.round(data.http.downloaded - (this.lastPlayerNetworkInfo?.http.downloaded || 0))
|
||||||
this.downloadedBytesP2P += Math.round(data.p2p.downloaded - (this.lastPlayerNetworkInfo?.p2p.downloaded || 0))
|
this.downloadedBytesP2P += Math.round((data.p2p?.downloaded || 0) - (this.lastPlayerNetworkInfo?.p2p?.downloaded || 0))
|
||||||
|
|
||||||
this.uploadedBytesP2P += Math.round(data.p2p.uploaded - (this.lastPlayerNetworkInfo?.p2p.uploaded || 0))
|
this.uploadedBytesP2P += Math.round((data.p2p?.uploaded || 0) - (this.lastPlayerNetworkInfo?.p2p?.uploaded || 0))
|
||||||
|
|
||||||
this.totalPeers = data.p2p.numPeers
|
this.p2pPeers = data.p2p?.peersP2POnly
|
||||||
this.p2pEnabled = true
|
this.p2pEnabled = !!data.p2p
|
||||||
|
|
||||||
this.lastPlayerNetworkInfo = data
|
|
||||||
})
|
|
||||||
|
|
||||||
this.player.on('http-info', (_event, data: PlayerNetworkInfo) => {
|
|
||||||
this.downloadedBytesHTTP += Math.round(data.http.downloaded - (this.lastPlayerNetworkInfo?.http.downloaded || 0))
|
|
||||||
|
|
||||||
this.totalPeers = 0
|
|
||||||
this.p2pEnabled = false
|
|
||||||
|
|
||||||
this.lastPlayerNetworkInfo = data
|
this.lastPlayerNetworkInfo = data
|
||||||
})
|
})
|
||||||
|
|
|
@ -16,7 +16,8 @@ class P2pMediaLoaderPlugin extends Plugin {
|
||||||
private statsP2PBytes = {
|
private statsP2PBytes = {
|
||||||
pendingDownload: [] as number[],
|
pendingDownload: [] as number[],
|
||||||
pendingUpload: [] as number[],
|
pendingUpload: [] as number[],
|
||||||
numPeers: 0,
|
peersWithWebSeed: 0,
|
||||||
|
peersP2POnly: 0,
|
||||||
totalDownload: 0,
|
totalDownload: 0,
|
||||||
totalUpload: 0
|
totalUpload: 0
|
||||||
}
|
}
|
||||||
|
@ -113,7 +114,7 @@ class P2pMediaLoaderPlugin extends Plugin {
|
||||||
this.options.redundancyUrlManager.removeBySegmentUrl(segment.requestUrl)
|
this.options.redundancyUrlManager.removeBySegmentUrl(segment.requestUrl)
|
||||||
})
|
})
|
||||||
|
|
||||||
this.statsP2PBytes.numPeers = 1 + this.options.redundancyUrlManager.countBaseUrls()
|
this.statsP2PBytes.peersWithWebSeed = 1 + this.options.redundancyUrlManager.countBaseUrls()
|
||||||
|
|
||||||
this.runStats()
|
this.runStats()
|
||||||
|
|
||||||
|
@ -138,8 +139,14 @@ class P2pMediaLoaderPlugin extends Plugin {
|
||||||
this.statsP2PBytes.totalUpload += bytes
|
this.statsP2PBytes.totalUpload += bytes
|
||||||
})
|
})
|
||||||
|
|
||||||
this.p2pEngine.on(Events.PeerConnect, () => this.statsP2PBytes.numPeers++)
|
this.p2pEngine.on(Events.PeerConnect, () => {
|
||||||
this.p2pEngine.on(Events.PeerClose, () => this.statsP2PBytes.numPeers--)
|
this.statsP2PBytes.peersWithWebSeed++
|
||||||
|
this.statsP2PBytes.peersP2POnly++
|
||||||
|
})
|
||||||
|
this.p2pEngine.on(Events.PeerClose, () => {
|
||||||
|
this.statsP2PBytes.peersWithWebSeed--
|
||||||
|
this.statsP2PBytes.peersP2POnly--
|
||||||
|
})
|
||||||
|
|
||||||
this.networkInfoInterval = setInterval(() => {
|
this.networkInfoInterval = setInterval(() => {
|
||||||
const p2pDownloadSpeed = this.arraySum(this.statsP2PBytes.pendingDownload)
|
const p2pDownloadSpeed = this.arraySum(this.statsP2PBytes.pendingDownload)
|
||||||
|
@ -151,20 +158,23 @@ class P2pMediaLoaderPlugin extends Plugin {
|
||||||
this.statsP2PBytes.pendingUpload = []
|
this.statsP2PBytes.pendingUpload = []
|
||||||
this.statsHTTPBytes.pendingDownload = []
|
this.statsHTTPBytes.pendingDownload = []
|
||||||
|
|
||||||
return this.player.trigger('p2p-info', {
|
return this.player.trigger('network-info', {
|
||||||
source: 'p2p-media-loader',
|
source: 'p2p-media-loader',
|
||||||
|
bandwidthEstimate: (this.hlsjs as any).bandwidthEstimate / 8,
|
||||||
http: {
|
http: {
|
||||||
downloadSpeed: httpDownloadSpeed,
|
downloadSpeed: httpDownloadSpeed,
|
||||||
downloaded: this.statsHTTPBytes.totalDownload
|
downloaded: this.statsHTTPBytes.totalDownload
|
||||||
},
|
},
|
||||||
p2p: {
|
p2p: this.options.p2pEnabled
|
||||||
|
? {
|
||||||
downloadSpeed: p2pDownloadSpeed,
|
downloadSpeed: p2pDownloadSpeed,
|
||||||
uploadSpeed: p2pUploadSpeed,
|
uploadSpeed: p2pUploadSpeed,
|
||||||
numPeers: this.statsP2PBytes.numPeers,
|
peersWithWebSeed: this.statsP2PBytes.peersWithWebSeed,
|
||||||
|
peersP2POnly: this.statsP2PBytes.peersP2POnly,
|
||||||
downloaded: this.statsP2PBytes.totalDownload,
|
downloaded: this.statsP2PBytes.totalDownload,
|
||||||
uploaded: this.statsP2PBytes.totalUpload
|
uploaded: this.statsP2PBytes.totalUpload
|
||||||
},
|
}
|
||||||
bandwidthEstimate: (this.hlsjs as any).bandwidthEstimate / 8
|
: undefined
|
||||||
} as PlayerNetworkInfo)
|
} as PlayerNetworkInfo)
|
||||||
}, 1000)
|
}, 1000)
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,8 @@ export class HLSOptionsBuilder {
|
||||||
requiresUserAuth: this.options.requiresUserAuth,
|
requiresUserAuth: this.options.requiresUserAuth,
|
||||||
videoFileToken: this.options.videoFileToken,
|
videoFileToken: this.options.videoFileToken,
|
||||||
|
|
||||||
|
p2pEnabled: this.options.p2pEnabled,
|
||||||
|
|
||||||
redundancyUrlManager,
|
redundancyUrlManager,
|
||||||
type: 'application/x-mpegURL',
|
type: 'application/x-mpegURL',
|
||||||
src: this.options.hls.playlistUrl,
|
src: this.options.hls.playlistUrl,
|
||||||
|
|
|
@ -63,8 +63,7 @@ class StatsCard extends Component {
|
||||||
|
|
||||||
private liveLatency: InfoElement
|
private liveLatency: InfoElement
|
||||||
|
|
||||||
private onP2PInfoHandler: (_event: any, data: EventPlayerNetworkInfo) => void
|
private onNetworkInfoHandler: (_event: any, data: EventPlayerNetworkInfo) => void
|
||||||
private onHTTPInfoHandler: (_event: any, data: EventPlayerNetworkInfo) => void
|
|
||||||
|
|
||||||
createEl () {
|
createEl () {
|
||||||
this.containerEl = videojs.dom.createEl('div', {
|
this.containerEl = videojs.dom.createEl('div', {
|
||||||
|
@ -89,33 +88,26 @@ class StatsCard extends Component {
|
||||||
|
|
||||||
this.populateInfoBlocks()
|
this.populateInfoBlocks()
|
||||||
|
|
||||||
this.onP2PInfoHandler = (_event, data) => {
|
this.onNetworkInfoHandler = (_event, data) => {
|
||||||
this.mode = data.source
|
this.mode = data.source
|
||||||
|
|
||||||
const p2pStats = data.p2p
|
const p2pStats = data.p2p
|
||||||
const httpStats = data.http
|
const httpStats = data.http
|
||||||
|
|
||||||
this.playerNetworkInfo.downloadSpeed = bytes(p2pStats.downloadSpeed + httpStats.downloadSpeed).join(' ')
|
this.playerNetworkInfo.downloadSpeed = bytes((p2pStats?.downloadSpeed || 0) + (httpStats.downloadSpeed || 0)).join(' ')
|
||||||
this.playerNetworkInfo.uploadSpeed = bytes(p2pStats.uploadSpeed).join(' ')
|
this.playerNetworkInfo.uploadSpeed = bytes(p2pStats?.uploadSpeed || 0).join(' ')
|
||||||
this.playerNetworkInfo.totalDownloaded = bytes(p2pStats.downloaded + httpStats.downloaded).join(' ')
|
this.playerNetworkInfo.totalDownloaded = bytes((p2pStats?.downloaded || 0) + httpStats.downloaded).join(' ')
|
||||||
this.playerNetworkInfo.totalUploaded = bytes(p2pStats.uploaded).join(' ')
|
this.playerNetworkInfo.totalUploaded = bytes(p2pStats?.uploaded || 0).join(' ')
|
||||||
this.playerNetworkInfo.numPeers = p2pStats.numPeers
|
this.playerNetworkInfo.numPeers = p2pStats?.peersWithWebSeed
|
||||||
this.playerNetworkInfo.averageBandwidth = bytes(data.bandwidthEstimate).join(' ') + '/s'
|
|
||||||
|
|
||||||
if (data.source === 'p2p-media-loader') {
|
if (data.source === 'p2p-media-loader') {
|
||||||
|
this.playerNetworkInfo.averageBandwidth = bytes(data.bandwidthEstimate).join(' ') + '/s'
|
||||||
this.playerNetworkInfo.downloadedFromServer = bytes(httpStats.downloaded).join(' ')
|
this.playerNetworkInfo.downloadedFromServer = bytes(httpStats.downloaded).join(' ')
|
||||||
this.playerNetworkInfo.downloadedFromPeers = bytes(p2pStats.downloaded).join(' ')
|
this.playerNetworkInfo.downloadedFromPeers = bytes(p2pStats?.downloaded || 0).join(' ')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.onHTTPInfoHandler = (_event, data) => {
|
this.player().on('network-info', this.onNetworkInfoHandler)
|
||||||
this.mode = data.source
|
|
||||||
|
|
||||||
this.playerNetworkInfo.totalDownloaded = bytes(data.http.downloaded).join(' ')
|
|
||||||
}
|
|
||||||
|
|
||||||
this.player().on('p2p-info', this.onP2PInfoHandler)
|
|
||||||
this.player().on('http-info', this.onHTTPInfoHandler)
|
|
||||||
|
|
||||||
return this.containerEl
|
return this.containerEl
|
||||||
}
|
}
|
||||||
|
@ -123,8 +115,7 @@ class StatsCard extends Component {
|
||||||
dispose () {
|
dispose () {
|
||||||
if (this.updateInterval) clearInterval(this.updateInterval)
|
if (this.updateInterval) clearInterval(this.updateInterval)
|
||||||
|
|
||||||
this.player().off('p2p-info', this.onP2PInfoHandler)
|
this.player().off('network-info', this.onNetworkInfoHandler)
|
||||||
this.player().off('http-info', this.onHTTPInfoHandler)
|
|
||||||
|
|
||||||
super.dispose()
|
super.dispose()
|
||||||
}
|
}
|
||||||
|
|
|
@ -175,7 +175,7 @@ class WebVideoPlugin extends Plugin {
|
||||||
|
|
||||||
private setupNetworkInfoInterval () {
|
private setupNetworkInfoInterval () {
|
||||||
this.networkInfoInterval = setInterval(() => {
|
this.networkInfoInterval = setInterval(() => {
|
||||||
return this.player.trigger('http-info', {
|
return this.player.trigger('network-info', {
|
||||||
source: 'web-video',
|
source: 'web-video',
|
||||||
http: {
|
http: {
|
||||||
downloaded: this.player.bufferedPercent() * this.currentVideoFile.size
|
downloaded: this.player.bufferedPercent() * this.currentVideoFile.size
|
||||||
|
|
|
@ -184,6 +184,8 @@ type P2PMediaLoaderPluginOptions = {
|
||||||
type: string
|
type: string
|
||||||
src: string
|
src: string
|
||||||
|
|
||||||
|
p2pEnabled: boolean
|
||||||
|
|
||||||
loader: P2PMediaLoader
|
loader: P2PMediaLoader
|
||||||
segmentValidator: SegmentValidator
|
segmentValidator: SegmentValidator
|
||||||
|
|
||||||
|
@ -240,9 +242,12 @@ type PlayerNetworkInfo = {
|
||||||
p2p?: {
|
p2p?: {
|
||||||
downloadSpeed: number
|
downloadSpeed: number
|
||||||
uploadSpeed: number
|
uploadSpeed: number
|
||||||
|
|
||||||
downloaded: number
|
downloaded: number
|
||||||
uploaded: number
|
uploaded: number
|
||||||
numPeers: number
|
|
||||||
|
peersWithWebSeed: number
|
||||||
|
peersP2POnly: number
|
||||||
}
|
}
|
||||||
|
|
||||||
// In bytes
|
// In bytes
|
||||||
|
|
|
@ -35,6 +35,10 @@ smtp:
|
||||||
log:
|
log:
|
||||||
level: 'debug'
|
level: 'debug'
|
||||||
|
|
||||||
|
open_telemetry:
|
||||||
|
metrics:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
contact_form:
|
contact_form:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Counter, Histogram, Meter } from '@opentelemetry/api'
|
import { Counter, Meter } from '@opentelemetry/api'
|
||||||
import { MVideoImmutable } from '@server/types/models'
|
import { MVideoImmutable } from '@server/types/models'
|
||||||
import { PlaybackMetricCreate } from '@shared/models'
|
import { PlaybackMetricCreate } from '@shared/models'
|
||||||
|
|
||||||
|
@ -11,7 +11,10 @@ export class PlaybackMetrics {
|
||||||
|
|
||||||
private downloadedBytesHTTPCounter: Counter
|
private downloadedBytesHTTPCounter: Counter
|
||||||
|
|
||||||
private peersP2PPeers: Histogram
|
private peersP2PPeersGaugeBuffer: {
|
||||||
|
value: number
|
||||||
|
attributes: any
|
||||||
|
}[] = []
|
||||||
|
|
||||||
constructor (private readonly meter: Meter) {
|
constructor (private readonly meter: Meter) {
|
||||||
|
|
||||||
|
@ -37,8 +40,14 @@ export class PlaybackMetrics {
|
||||||
description: 'Uploaded bytes with P2P by PeerTube player.'
|
description: 'Uploaded bytes with P2P by PeerTube player.'
|
||||||
})
|
})
|
||||||
|
|
||||||
this.peersP2PPeers = this.meter.createHistogram('peertube_playback_p2p_peers', {
|
this.meter.createObservableGauge('peertube_playback_p2p_peers', {
|
||||||
description: 'Total P2P peers connected to the PeerTube player.'
|
description: 'Total P2P peers connected to the PeerTube player.'
|
||||||
|
}).addCallback(observableResult => {
|
||||||
|
for (const gauge of this.peersP2PPeersGaugeBuffer) {
|
||||||
|
observableResult.observe(gauge.value, gauge.attributes)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.peersP2PPeersGaugeBuffer = []
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,6 +75,11 @@ export class PlaybackMetrics {
|
||||||
|
|
||||||
this.uploadedBytesP2PCounter.add(metrics.uploadedBytesP2P, attributes)
|
this.uploadedBytesP2PCounter.add(metrics.uploadedBytesP2P, attributes)
|
||||||
|
|
||||||
if (metrics.totalPeers) this.peersP2PPeers.record(metrics.totalPeers, attributes)
|
if (metrics.p2pPeers) {
|
||||||
|
this.peersP2PPeersGaugeBuffer.push({
|
||||||
|
value: metrics.p2pPeers,
|
||||||
|
attributes
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,12 +13,11 @@ const addPlaybackMetricValidator = [
|
||||||
.optional()
|
.optional()
|
||||||
.isInt({ min: 0 }),
|
.isInt({ min: 0 }),
|
||||||
|
|
||||||
body('totalPeers')
|
body('p2pPeers')
|
||||||
.optional()
|
.optional()
|
||||||
.isInt({ min: 0 }),
|
.isInt({ min: 0 }),
|
||||||
|
|
||||||
body('p2pEnabled')
|
body('p2pEnabled')
|
||||||
.optional()
|
|
||||||
.isBoolean(),
|
.isBoolean(),
|
||||||
|
|
||||||
body('playerMode')
|
body('playerMode')
|
||||||
|
|
|
@ -38,6 +38,7 @@ describe('Test metrics API validators', function () {
|
||||||
fps: 30,
|
fps: 30,
|
||||||
resolutionChanges: 1,
|
resolutionChanges: 1,
|
||||||
errors: 2,
|
errors: 2,
|
||||||
|
p2pEnabled: true,
|
||||||
downloadedBytesP2P: 0,
|
downloadedBytesP2P: 0,
|
||||||
downloadedBytesHTTP: 0,
|
downloadedBytesHTTP: 0,
|
||||||
uploadedBytesP2P: 0,
|
uploadedBytesP2P: 0,
|
||||||
|
@ -145,7 +146,13 @@ describe('Test metrics API validators', function () {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should fail with an invalid p2pEnabled', async function () {
|
it('Should fail with a missing/invalid p2pEnabled', async function () {
|
||||||
|
await makePostBodyRequest({
|
||||||
|
url: server.url,
|
||||||
|
path,
|
||||||
|
fields: omit(baseParams, [ 'p2pEnabled' ])
|
||||||
|
})
|
||||||
|
|
||||||
await makePostBodyRequest({
|
await makePostBodyRequest({
|
||||||
url: server.url,
|
url: server.url,
|
||||||
path,
|
path,
|
||||||
|
@ -157,7 +164,7 @@ describe('Test metrics API validators', function () {
|
||||||
await makePostBodyRequest({
|
await makePostBodyRequest({
|
||||||
url: server.url,
|
url: server.url,
|
||||||
path,
|
path,
|
||||||
fields: { ...baseParams, totalPeers: 'toto' }
|
fields: { ...baseParams, p2pPeers: 'toto' }
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
import { expect } from 'chai'
|
import { expect } from 'chai'
|
||||||
import { expectLogContain, expectLogDoesNotContain, MockHTTP } from '@server/tests/shared'
|
import { expectLogContain, expectLogDoesNotContain, MockHTTP } from '@server/tests/shared'
|
||||||
import { HttpStatusCode, VideoPrivacy, VideoResolution } from '@shared/models'
|
import { HttpStatusCode, PlaybackMetricCreate, VideoPrivacy, VideoResolution } from '@shared/models'
|
||||||
import { cleanupTests, createSingleServer, makeRawRequest, PeerTubeServer, setAccessTokensToServers } from '@shared/server-commands'
|
import { cleanupTests, createSingleServer, makeRawRequest, PeerTubeServer, setAccessTokensToServers } from '@shared/server-commands'
|
||||||
|
|
||||||
describe('Open Telemetry', function () {
|
describe('Open Telemetry', function () {
|
||||||
|
@ -62,14 +62,49 @@ describe('Open Telemetry', function () {
|
||||||
downloadedBytesP2P: 0,
|
downloadedBytesP2P: 0,
|
||||||
downloadedBytesHTTP: 0,
|
downloadedBytesHTTP: 0,
|
||||||
uploadedBytesP2P: 5,
|
uploadedBytesP2P: 5,
|
||||||
totalPeers: 1,
|
p2pPeers: 1,
|
||||||
p2pEnabled: false,
|
p2pEnabled: false,
|
||||||
videoId: video.uuid
|
videoId: video.uuid
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const res = await makeRawRequest({ url: metricsUrl, expectedStatus: HttpStatusCode.OK_200 })
|
const res = await makeRawRequest({ url: metricsUrl, expectedStatus: HttpStatusCode.OK_200 })
|
||||||
|
|
||||||
expect(res.text).to.contain('peertube_playback_http_downloaded_bytes_total{')
|
expect(res.text).to.contain('peertube_playback_http_downloaded_bytes_total{')
|
||||||
|
expect(res.text).to.contain('peertube_playback_p2p_peers{')
|
||||||
|
expect(res.text).to.contain('p2pEnabled="false"')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should take the last playback metric', async function () {
|
||||||
|
await setAccessTokensToServers([ server ])
|
||||||
|
|
||||||
|
const video = await server.videos.quickUpload({ name: 'video' })
|
||||||
|
|
||||||
|
const metrics = {
|
||||||
|
playerMode: 'p2p-media-loader',
|
||||||
|
resolution: VideoResolution.H_1080P,
|
||||||
|
fps: 30,
|
||||||
|
resolutionChanges: 1,
|
||||||
|
errors: 2,
|
||||||
|
downloadedBytesP2P: 0,
|
||||||
|
downloadedBytesHTTP: 0,
|
||||||
|
uploadedBytesP2P: 5,
|
||||||
|
p2pPeers: 7,
|
||||||
|
p2pEnabled: false,
|
||||||
|
videoId: video.uuid
|
||||||
|
} as PlaybackMetricCreate
|
||||||
|
|
||||||
|
await server.metrics.addPlaybackMetric({ metrics })
|
||||||
|
|
||||||
|
metrics.p2pPeers = 42
|
||||||
|
await server.metrics.addPlaybackMetric({ metrics })
|
||||||
|
|
||||||
|
const res = await makeRawRequest({ url: metricsUrl, expectedStatus: HttpStatusCode.OK_200 })
|
||||||
|
|
||||||
|
// eslint-disable-next-line max-len
|
||||||
|
const label = `{videoOrigin="local",playerMode="p2p-media-loader",resolution="1080",fps="30",p2pEnabled="false",videoUUID="${video.uuid}"}`
|
||||||
|
expect(res.text).to.contain(`peertube_playback_p2p_peers${label} 42`)
|
||||||
|
expect(res.text).to.not.contain(`peertube_playback_p2p_peers${label} 7`)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should disable http request duration metrics', async function () {
|
it('Should disable http request duration metrics', async function () {
|
||||||
|
|
|
@ -6,8 +6,8 @@ export interface PlaybackMetricCreate {
|
||||||
resolution?: VideoResolution
|
resolution?: VideoResolution
|
||||||
fps?: number
|
fps?: number
|
||||||
|
|
||||||
p2pEnabled?: boolean
|
p2pEnabled: boolean
|
||||||
totalPeers?: number
|
p2pPeers?: number
|
||||||
|
|
||||||
resolutionChanges: number
|
resolutionChanges: number
|
||||||
|
|
||||||
|
|
|
@ -9528,6 +9528,11 @@ components:
|
||||||
fps:
|
fps:
|
||||||
type: number
|
type: number
|
||||||
description: Current player video fps
|
description: Current player video fps
|
||||||
|
p2pEnabled:
|
||||||
|
type: boolean
|
||||||
|
p2pPeers:
|
||||||
|
type: number
|
||||||
|
description: P2P peers connected (doesn't include WebSeed peers)
|
||||||
resolutionChanges:
|
resolutionChanges:
|
||||||
type: number
|
type: number
|
||||||
description: How many resolution changes occured since the last metric creation
|
description: How many resolution changes occured since the last metric creation
|
||||||
|
@ -9555,6 +9560,7 @@ components:
|
||||||
- downloadedBytesP2P
|
- downloadedBytesP2P
|
||||||
- downloadedBytesHTTP
|
- downloadedBytesHTTP
|
||||||
- uploadedBytesP2P
|
- uploadedBytesP2P
|
||||||
|
- p2pEnabled
|
||||||
- videoId
|
- videoId
|
||||||
|
|
||||||
RunnerRegistrationToken:
|
RunnerRegistrationToken:
|
||||||
|
|
Loading…
Reference in a new issue