Add ability to customize views/playback interval
This commit is contained in:
parent
49a4b8cb7d
commit
fe37e5232b
15 changed files with 143 additions and 14 deletions
|
@ -113,8 +113,6 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
private hotkeys: Hotkey[] = []
|
private hotkeys: Hotkey[] = []
|
||||||
|
|
||||||
private static VIEW_VIDEO_INTERVAL_MS = 5000
|
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
|
@ -625,9 +623,16 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
instanceName: this.serverConfig.instance.name,
|
instanceName: this.serverConfig.instance.name,
|
||||||
language: this.localeId,
|
language: this.localeId,
|
||||||
metricsUrl: environment.apiUrl + '/api/v1/metrics/playback',
|
|
||||||
|
|
||||||
videoViewIntervalMs: VideoWatchComponent.VIEW_VIDEO_INTERVAL_MS,
|
metricsUrl: this.serverConfig.openTelemetry.metrics.enabled
|
||||||
|
? environment.apiUrl + '/api/v1/metrics/playback'
|
||||||
|
: null,
|
||||||
|
metricsInterval: this.serverConfig.openTelemetry.metrics.playbackStatsInterval,
|
||||||
|
|
||||||
|
videoViewIntervalMs: this.isUserLoggedIn()
|
||||||
|
? this.serverConfig.views.videos.watchingInterval.users
|
||||||
|
: this.serverConfig.views.videos.watchingInterval.anonymous,
|
||||||
|
|
||||||
authorizationHeader: () => this.authService.getRequestHeaderValue(),
|
authorizationHeader: () => this.authService.getRequestHeaderValue(),
|
||||||
|
|
||||||
serverUrl: environment.originServerUrl || window.location.origin,
|
serverUrl: environment.originServerUrl || window.location.origin,
|
||||||
|
|
|
@ -382,6 +382,7 @@ export class PeerTubePlayer {
|
||||||
mode: () => this.currentLoadOptions.mode,
|
mode: () => this.currentLoadOptions.mode,
|
||||||
|
|
||||||
metricsUrl: () => this.options.metricsUrl,
|
metricsUrl: () => this.options.metricsUrl,
|
||||||
|
metricsInterval: () => this.options.metricsInterval,
|
||||||
videoUUID: () => this.currentLoadOptions.videoUUID
|
videoUUID: () => this.currentLoadOptions.videoUUID
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,10 +25,6 @@ class MetricsPlugin extends Plugin {
|
||||||
|
|
||||||
private metricsInterval: any
|
private metricsInterval: any
|
||||||
|
|
||||||
private readonly CONSTANTS = {
|
|
||||||
METRICS_INTERVAL: 15000
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor (player: videojs.Player, options: MetricsPluginOptions) {
|
constructor (player: videojs.Player, options: MetricsPluginOptions) {
|
||||||
super(player)
|
super(player)
|
||||||
|
|
||||||
|
@ -74,6 +70,7 @@ class MetricsPlugin extends Plugin {
|
||||||
|
|
||||||
private runMetricsInterval () {
|
private runMetricsInterval () {
|
||||||
if (this.metricsInterval) clearInterval(this.metricsInterval)
|
if (this.metricsInterval) clearInterval(this.metricsInterval)
|
||||||
|
if (!this.options_.metricsUrl()) return
|
||||||
|
|
||||||
this.metricsInterval = setInterval(() => {
|
this.metricsInterval = setInterval(() => {
|
||||||
let resolution: number
|
let resolution: number
|
||||||
|
@ -135,7 +132,7 @@ class MetricsPlugin extends Plugin {
|
||||||
|
|
||||||
return fetch(this.options_.metricsUrl(), { method: 'POST', body: JSON.stringify(body), headers })
|
return fetch(this.options_.metricsUrl(), { method: 'POST', body: JSON.stringify(body), headers })
|
||||||
.catch(err => logger.error('Cannot send metrics to the server.', err))
|
.catch(err => logger.error('Cannot send metrics to the server.', err))
|
||||||
}, this.CONSTANTS.METRICS_INTERVAL)
|
}, this.options_.metricsInterval())
|
||||||
}
|
}
|
||||||
|
|
||||||
private trackBytes () {
|
private trackBytes () {
|
||||||
|
|
|
@ -30,6 +30,8 @@ export type PeerTubePlayerContructorOptions = {
|
||||||
authorizationHeader: () => string
|
authorizationHeader: () => string
|
||||||
|
|
||||||
metricsUrl: string
|
metricsUrl: string
|
||||||
|
metricsInterval: number
|
||||||
|
|
||||||
serverUrl: string
|
serverUrl: string
|
||||||
|
|
||||||
errorNotifier: (message: string) => void
|
errorNotifier: (message: string) => void
|
||||||
|
|
|
@ -135,6 +135,7 @@ type PeerTubePluginOptions = {
|
||||||
type MetricsPluginOptions = {
|
type MetricsPluginOptions = {
|
||||||
mode: () => PlayerMode
|
mode: () => PlayerMode
|
||||||
metricsUrl: () => string
|
metricsUrl: () => string
|
||||||
|
metricsInterval: () => number
|
||||||
videoUUID: () => string
|
videoUUID: () => string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -186,8 +186,13 @@ export class PlayerOptionsBuilder {
|
||||||
playbackRate: this.playbackRate,
|
playbackRate: this.playbackRate,
|
||||||
|
|
||||||
inactivityTimeout: 2500,
|
inactivityTimeout: 2500,
|
||||||
videoViewIntervalMs: 5000,
|
|
||||||
metricsUrl: window.location.origin + '/api/v1/metrics/playback',
|
videoViewIntervalMs: serverConfig.views.videos.watchingInterval.anonymous,
|
||||||
|
|
||||||
|
metricsUrl: serverConfig.openTelemetry.metrics.enabled
|
||||||
|
? window.location.origin + '/api/v1/metrics/playback'
|
||||||
|
: null,
|
||||||
|
metricsInterval: serverConfig.openTelemetry.metrics.playbackStatsInterval,
|
||||||
|
|
||||||
authorizationHeader,
|
authorizationHeader,
|
||||||
|
|
||||||
|
|
|
@ -254,6 +254,9 @@ open_telemetry:
|
||||||
metrics:
|
metrics:
|
||||||
enabled: false
|
enabled: false
|
||||||
|
|
||||||
|
# How often viewers send playback stats to server
|
||||||
|
playback_stats_interval: '15 seconds'
|
||||||
|
|
||||||
http_request_duration:
|
http_request_duration:
|
||||||
# You can disable HTTP request duration metric that can have a high tag cardinality
|
# You can disable HTTP request duration metric that can have a high tag cardinality
|
||||||
enabled: true
|
enabled: true
|
||||||
|
@ -362,6 +365,17 @@ views:
|
||||||
|
|
||||||
ip_view_expiration: '1 hour'
|
ip_view_expiration: '1 hour'
|
||||||
|
|
||||||
|
# How often the web browser sends "is watching" information to the server
|
||||||
|
# Increase the value or set null to disable it if you plan to have many viewers
|
||||||
|
watching_interval:
|
||||||
|
# Non logged-in viewers
|
||||||
|
anonymous: '5 seconds'
|
||||||
|
|
||||||
|
# Logged-in users of your instance
|
||||||
|
# Unlike anonymous viewers, this endpoint is also used to store the "last watched video timecode" for your users
|
||||||
|
# Increasing this value reduces the accuracy of the video resume
|
||||||
|
users: '5 seconds'
|
||||||
|
|
||||||
# Used to get country location of views of local videos
|
# Used to get country location of views of local videos
|
||||||
geo_ip:
|
geo_ip:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
|
@ -38,6 +38,7 @@ log:
|
||||||
open_telemetry:
|
open_telemetry:
|
||||||
metrics:
|
metrics:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
playback_stats_interval: '13 seconds'
|
||||||
|
|
||||||
contact_form:
|
contact_form:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
@ -118,6 +119,10 @@ views:
|
||||||
remote:
|
remote:
|
||||||
max_age: -1
|
max_age: -1
|
||||||
|
|
||||||
|
watching_interval:
|
||||||
|
anonymous: '6 seconds'
|
||||||
|
users: '4 seconds'
|
||||||
|
|
||||||
geo_ip:
|
geo_ip:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
||||||
|
|
|
@ -252,6 +252,9 @@ open_telemetry:
|
||||||
metrics:
|
metrics:
|
||||||
enabled: false
|
enabled: false
|
||||||
|
|
||||||
|
# How often viewers send playback stats to server
|
||||||
|
playback_stats_interval: '15 seconds'
|
||||||
|
|
||||||
http_request_duration:
|
http_request_duration:
|
||||||
# You can disable HTTP request duration metric that can have a high tag cardinality
|
# You can disable HTTP request duration metric that can have a high tag cardinality
|
||||||
enabled: true
|
enabled: true
|
||||||
|
@ -360,6 +363,17 @@ views:
|
||||||
|
|
||||||
ip_view_expiration: '1 hour'
|
ip_view_expiration: '1 hour'
|
||||||
|
|
||||||
|
# How often the web browser sends "is watching" information to the server
|
||||||
|
# Increase the value or set null to disable it if you plan to have many viewers
|
||||||
|
watching_interval:
|
||||||
|
# Non logged-in viewers
|
||||||
|
anonymous: '5 seconds'
|
||||||
|
|
||||||
|
# Logged-in users of your instance
|
||||||
|
# Unlike anonymous viewers, this endpoint is also used to store the "last watched video timecode" for your users
|
||||||
|
# Increasing this value reduces the accuracy of the video resume
|
||||||
|
users: '5 seconds'
|
||||||
|
|
||||||
# Used to get country location of views of local videos
|
# Used to get country location of views of local videos
|
||||||
geo_ip:
|
geo_ip:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
|
@ -300,6 +300,27 @@ export interface ServerConfig {
|
||||||
homepage: {
|
homepage: {
|
||||||
enabled: boolean
|
enabled: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
openTelemetry: {
|
||||||
|
metrics: {
|
||||||
|
enabled: boolean
|
||||||
|
|
||||||
|
// milliseconds
|
||||||
|
playbackStatsInterval: number
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
views: {
|
||||||
|
videos: {
|
||||||
|
watchingInterval: {
|
||||||
|
// milliseconds
|
||||||
|
anonymous: number
|
||||||
|
|
||||||
|
// milliseconds
|
||||||
|
users: number
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type HTMLServerConfig = Omit<ServerConfig, 'signup'>
|
export type HTMLServerConfig = Omit<ServerConfig, 'signup'>
|
||||||
|
|
|
@ -498,6 +498,16 @@ describe('Test config', function () {
|
||||||
await setAccessTokensToServers([ server ])
|
await setAccessTokensToServers([ server ])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('Should have the correct default config', async function () {
|
||||||
|
const data = await server.config.getConfig()
|
||||||
|
|
||||||
|
expect(data.openTelemetry.metrics.enabled).to.be.false
|
||||||
|
expect(data.openTelemetry.metrics.playbackStatsInterval).to.equal(15000)
|
||||||
|
|
||||||
|
expect(data.views.videos.watchingInterval.anonymous).to.equal(5000)
|
||||||
|
expect(data.views.videos.watchingInterval.users).to.equal(5000)
|
||||||
|
})
|
||||||
|
|
||||||
it('Should have a correct config on a server with registration enabled', async function () {
|
it('Should have a correct config on a server with registration enabled', async function () {
|
||||||
const data = await server.config.getConfig()
|
const data = await server.config.getConfig()
|
||||||
|
|
||||||
|
|
|
@ -19,8 +19,9 @@ function checkMissedConfig () {
|
||||||
'storage.redundancy', 'storage.tmp', 'storage.streaming_playlists', 'storage.plugins', 'storage.well_known',
|
'storage.redundancy', 'storage.tmp', 'storage.streaming_playlists', 'storage.plugins', 'storage.well_known',
|
||||||
'log.level', 'log.rotation.enabled', 'log.rotation.max_file_size', 'log.rotation.max_files', 'log.anonymize_ip',
|
'log.level', 'log.rotation.enabled', 'log.rotation.max_file_size', 'log.rotation.max_files', 'log.anonymize_ip',
|
||||||
'log.log_ping_requests', 'log.log_tracker_unknown_infohash', 'log.prettify_sql', 'log.accept_client_log',
|
'log.log_ping_requests', 'log.log_tracker_unknown_infohash', 'log.prettify_sql', 'log.accept_client_log',
|
||||||
'open_telemetry.metrics.enabled', 'open_telemetry.metrics.prometheus_exporter.hostname',
|
'open_telemetry.metrics.enabled', 'open_telemetry.metrics.playback_stats_interval',
|
||||||
'open_telemetry.metrics.prometheus_exporter.port', 'open_telemetry.tracing.enabled', 'open_telemetry.tracing.jaeger_exporter.endpoint',
|
'open_telemetry.metrics.prometheus_exporter.hostname', 'open_telemetry.metrics.prometheus_exporter.port',
|
||||||
|
'open_telemetry.tracing.enabled', 'open_telemetry.tracing.jaeger_exporter.endpoint',
|
||||||
'open_telemetry.metrics.http_request_duration.enabled',
|
'open_telemetry.metrics.http_request_duration.enabled',
|
||||||
'user.history.videos.enabled', 'user.video_quota', 'user.video_quota_daily',
|
'user.history.videos.enabled', 'user.video_quota', 'user.video_quota_daily',
|
||||||
'video_channels.max_per_user',
|
'video_channels.max_per_user',
|
||||||
|
@ -54,6 +55,7 @@ function checkMissedConfig () {
|
||||||
'followers.instance.enabled', 'followers.instance.manual_approval',
|
'followers.instance.enabled', 'followers.instance.manual_approval',
|
||||||
'tracker.enabled', 'tracker.private', 'tracker.reject_too_many_announces',
|
'tracker.enabled', 'tracker.private', 'tracker.reject_too_many_announces',
|
||||||
'history.videos.max_age', 'views.videos.remote.max_age', 'views.videos.local_buffer_update_interval', 'views.videos.ip_view_expiration',
|
'history.videos.max_age', 'views.videos.remote.max_age', 'views.videos.local_buffer_update_interval', 'views.videos.ip_view_expiration',
|
||||||
|
'views.videos.watching_interval.anonymous', 'views.videos.watching_interval.users',
|
||||||
'rates_limit.api.window', 'rates_limit.api.max', 'rates_limit.login.window', 'rates_limit.login.max',
|
'rates_limit.api.window', 'rates_limit.api.max', 'rates_limit.login.window', 'rates_limit.login.max',
|
||||||
'rates_limit.signup.window', 'rates_limit.signup.max', 'rates_limit.ask_send_email.window', 'rates_limit.ask_send_email.max',
|
'rates_limit.signup.window', 'rates_limit.signup.max', 'rates_limit.ask_send_email.window', 'rates_limit.ask_send_email.max',
|
||||||
'rates_limit.receive_client_log.window', 'rates_limit.receive_client_log.max', 'rates_limit.plugins.window', 'rates_limit.plugins.max',
|
'rates_limit.receive_client_log.window', 'rates_limit.receive_client_log.max', 'rates_limit.plugins.window', 'rates_limit.plugins.max',
|
||||||
|
|
|
@ -228,6 +228,8 @@ const CONFIG = {
|
||||||
METRICS: {
|
METRICS: {
|
||||||
ENABLED: config.get<boolean>('open_telemetry.metrics.enabled'),
|
ENABLED: config.get<boolean>('open_telemetry.metrics.enabled'),
|
||||||
|
|
||||||
|
PLAYBACK_STATS_INTERVAL: parseDurationToMs(config.get<string>('open_telemetry.metrics.playback_stats_interval')),
|
||||||
|
|
||||||
HTTP_REQUEST_DURATION: {
|
HTTP_REQUEST_DURATION: {
|
||||||
ENABLED: config.get<boolean>('open_telemetry.metrics.http_request_duration.enabled')
|
ENABLED: config.get<boolean>('open_telemetry.metrics.http_request_duration.enabled')
|
||||||
},
|
},
|
||||||
|
@ -294,7 +296,11 @@ const CONFIG = {
|
||||||
MAX_AGE: parseDurationToMs(config.get('views.videos.remote.max_age'))
|
MAX_AGE: parseDurationToMs(config.get('views.videos.remote.max_age'))
|
||||||
},
|
},
|
||||||
LOCAL_BUFFER_UPDATE_INTERVAL: parseDurationToMs(config.get('views.videos.local_buffer_update_interval')),
|
LOCAL_BUFFER_UPDATE_INTERVAL: parseDurationToMs(config.get('views.videos.local_buffer_update_interval')),
|
||||||
IP_VIEW_EXPIRATION: parseDurationToMs(config.get('views.videos.ip_view_expiration'))
|
IP_VIEW_EXPIRATION: parseDurationToMs(config.get('views.videos.ip_view_expiration')),
|
||||||
|
WATCHING_INTERVAL: {
|
||||||
|
ANONYMOUS: parseDurationToMs(config.get<string>('views.videos.watching_interval.anonymous')),
|
||||||
|
USERS: parseDurationToMs(config.get<string>('views.videos.watching_interval.users'))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
GEO_IP: {
|
GEO_IP: {
|
||||||
|
|
|
@ -274,6 +274,22 @@ class ServerConfigManager {
|
||||||
|
|
||||||
homepage: {
|
homepage: {
|
||||||
enabled: this.homepageEnabled
|
enabled: this.homepageEnabled
|
||||||
|
},
|
||||||
|
|
||||||
|
openTelemetry: {
|
||||||
|
metrics: {
|
||||||
|
enabled: CONFIG.OPEN_TELEMETRY.METRICS.ENABLED,
|
||||||
|
playbackStatsInterval: CONFIG.OPEN_TELEMETRY.METRICS.PLAYBACK_STATS_INTERVAL
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
views: {
|
||||||
|
videos: {
|
||||||
|
watchingInterval: {
|
||||||
|
anonymous: CONFIG.VIEWS.VIDEOS.WATCHING_INTERVAL.ANONYMOUS,
|
||||||
|
users: CONFIG.VIEWS.VIDEOS.WATCHING_INTERVAL.USERS
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8126,6 +8126,36 @@ components:
|
||||||
enabled:
|
enabled:
|
||||||
type: boolean
|
type: boolean
|
||||||
|
|
||||||
|
openTelemetry:
|
||||||
|
type: object
|
||||||
|
description: 'PeerTube >= 6.1'
|
||||||
|
properties:
|
||||||
|
metrics:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
enabled:
|
||||||
|
type: boolean
|
||||||
|
playbackStatsInterval:
|
||||||
|
type: number
|
||||||
|
description: 'Milliseconds'
|
||||||
|
|
||||||
|
views:
|
||||||
|
type: object
|
||||||
|
description: 'PeerTube >= 6.1'
|
||||||
|
properties:
|
||||||
|
views:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
watchingInterval:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
anonymous:
|
||||||
|
type: number
|
||||||
|
description: 'Milliseconds'
|
||||||
|
users:
|
||||||
|
type: number
|
||||||
|
description: 'Milliseconds'
|
||||||
|
|
||||||
SendClientLog:
|
SendClientLog:
|
||||||
properties:
|
properties:
|
||||||
message:
|
message:
|
||||||
|
|
Loading…
Reference in a new issue