1
0
Fork 0

Add ability to customize views/playback interval

This commit is contained in:
Chocobozzz 2023-12-13 10:06:25 +01:00
parent 49a4b8cb7d
commit fe37e5232b
No known key found for this signature in database
GPG key ID: 583A612D890159BE
15 changed files with 143 additions and 14 deletions

View file

@ -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,

View file

@ -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
} }
} }

View file

@ -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 () {

View file

@ -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

View file

@ -135,6 +135,7 @@ type PeerTubePluginOptions = {
type MetricsPluginOptions = { type MetricsPluginOptions = {
mode: () => PlayerMode mode: () => PlayerMode
metricsUrl: () => string metricsUrl: () => string
metricsInterval: () => number
videoUUID: () => string videoUUID: () => string
} }

View file

@ -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,

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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'>

View file

@ -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()

View file

@ -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',

View file

@ -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: {

View file

@ -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
}
}
} }
} }
} }

View file

@ -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: