Do not take into account empty view sections

This commit is contained in:
Chocobozzz 2024-04-03 14:25:21 +02:00
parent faabe996ba
commit 9b70c8e7e8
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
4 changed files with 26 additions and 14 deletions

View File

@ -3,10 +3,10 @@ import { AvailableEncoders, EncoderOptionsBuilder, EncoderOptionsBuilderParams,
import ffmpeg, { FfmpegCommand } from 'fluent-ffmpeg' import ffmpeg, { FfmpegCommand } from 'fluent-ffmpeg'
type FFmpegLogger = { type FFmpegLogger = {
info: (msg: string, obj?: any) => void info: (msg: string, obj?: object) => void
debug: (msg: string, obj?: any) => void debug: (msg: string, obj?: object) => void
warn: (msg: string, obj?: any) => void warn: (msg: string, obj?: object) => void
error: (msg: string, obj?: any) => void error: (msg: string, obj?: object) => void
} }
export interface FFmpegCommandWrapperOptions { export interface FFmpegCommandWrapperOptions {

View File

@ -1,9 +1,9 @@
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
import { expect } from 'chai'
import { prepareViewsServers, prepareViewsVideos, processViewersStats } from '@tests/shared/views.js'
import { cleanupTests, PeerTubeServer } from '@peertube/peertube-server-commands'
import { wait } from '@peertube/peertube-core-utils' import { wait } from '@peertube/peertube-core-utils'
import { PeerTubeServer, cleanupTests } from '@peertube/peertube-server-commands'
import { prepareViewsServers, prepareViewsVideos, processViewersStats } from '@tests/shared/views.js'
import { expect } from 'chai'
describe('Test views retention stats', function () { describe('Test views retention stats', function () {
let servers: PeerTubeServer[] let servers: PeerTubeServer[]
@ -36,15 +36,20 @@ describe('Test views retention stats', function () {
it('Should display appropriate retention metrics', async function () { it('Should display appropriate retention metrics', async function () {
await servers[0].views.simulateViewer({ xForwardedFor: '127.0.0.2,127.0.0.1', id: vodVideoId, currentTimes: [ 0, 1 ] }) await servers[0].views.simulateViewer({ xForwardedFor: '127.0.0.2,127.0.0.1', id: vodVideoId, currentTimes: [ 0, 1 ] })
await servers[0].views.simulateViewer({ xForwardedFor: '127.0.0.3,127.0.0.1', id: vodVideoId, currentTimes: [ 1, 3 ] }) await servers[0].views.simulateViewer({ xForwardedFor: '127.0.0.3,127.0.0.1', id: vodVideoId, currentTimes: [ 1, 3 ] })
await servers[1].views.simulateViewer({ xForwardedFor: '127.0.0.2,127.0.0.1', id: vodVideoId, currentTimes: [ 4 ] }) await servers[1].views.simulateViewer({ xForwardedFor: '127.0.0.2,127.0.0.1', id: vodVideoId, currentTimes: [ 3, 4 ] })
await servers[1].views.simulateViewer({ xForwardedFor: '127.0.0.3,127.0.0.1', id: vodVideoId, currentTimes: [ 0, 1 ] }) await servers[1].views.simulateViewer({ xForwardedFor: '127.0.0.3,127.0.0.1', id: vodVideoId, currentTimes: [ 0, 1 ] })
// Do not take into account empty section
await servers[1].views.simulateViewer({ xForwardedFor: '127.0.0.3,127.0.0.1', id: vodVideoId, currentTimes: [ 5, 5 ] })
await servers[0].views.simulateViewer({ xForwardedFor: '127.0.0.4,127.0.0.1', id: vodVideoId, currentTimes: [ 1, 1 ] })
await servers[1].views.simulateViewer({ xForwardedFor: '127.0.0.4,127.0.0.1', id: vodVideoId, currentTimes: [ 1, 1 ] })
await processViewersStats(servers) await processViewersStats(servers)
const { data } = await servers[0].videoStats.getRetentionStats({ videoId: vodVideoId }) const { data } = await servers[0].videoStats.getRetentionStats({ videoId: vodVideoId })
expect(data).to.have.lengthOf(6) expect(data).to.have.lengthOf(6)
expect(data.map(d => d.retentionPercent)).to.deep.equal([ 50, 75, 25, 25, 25, 0 ]) expect(data.map(d => d.retentionPercent)).to.deep.equal([ 50, 75, 25, 50, 25, 0 ])
}) })
it('Should display appropriate retention metrics after a server restart', async function () { it('Should display appropriate retention metrics after a server restart', async function () {

View File

@ -160,7 +160,7 @@ export class VideoViewerStats {
const statsModel = await this.saveViewerStats(video, stats, t) const statsModel = await this.saveViewerStats(video, stats, t)
if (video.remote) { if (statsModel && video.remote) {
await sendCreateWatchAction(statsModel, t) await sendCreateWatchAction(statsModel, t)
} }
}) })
@ -178,6 +178,8 @@ export class VideoViewerStats {
} }
private async saveViewerStats (video: MVideo, stats: LocalViewerStats, transaction: Transaction) { private async saveViewerStats (video: MVideo, stats: LocalViewerStats, transaction: Transaction) {
if (stats.watchTime === 0) return
const statsModel = new LocalVideoViewerModel({ const statsModel = new LocalVideoViewerModel({
startDate: new Date(stats.firstUpdated), startDate: new Date(stats.firstUpdated),
endDate: new Date(stats.lastUpdated), endDate: new Date(stats.lastUpdated),

View File

@ -1,8 +1,8 @@
import { MLocalVideoViewerWatchSection } from '@server/types/models/index.js'
import { Transaction } from 'sequelize' import { Transaction } from 'sequelize'
import { AllowNull, BelongsTo, Column, CreatedAt, ForeignKey, Table } from 'sequelize-typescript' import { AllowNull, BelongsTo, Column, CreatedAt, ForeignKey, Table } from 'sequelize-typescript'
import { MLocalVideoViewerWatchSection } from '@server/types/models/index.js'
import { LocalVideoViewerModel } from './local-video-viewer.js'
import { SequelizeModel } from '../shared/index.js' import { SequelizeModel } from '../shared/index.js'
import { LocalVideoViewerModel } from './local-video-viewer.js'
@Table({ @Table({
tableName: 'localVideoViewerWatchSection', tableName: 'localVideoViewerWatchSection',
@ -49,9 +49,14 @@ export class LocalVideoViewerWatchSectionModel extends SequelizeModel<LocalVideo
const models: MLocalVideoViewerWatchSection[] = [] const models: MLocalVideoViewerWatchSection[] = []
for (const section of watchSections) { for (const section of watchSections) {
const watchStart = section.start || 0
const watchEnd = section.end || 0
if (watchStart === watchEnd) continue
const model = await this.create({ const model = await this.create({
watchStart: section.start || 0, watchStart,
watchEnd: section.end || 0, watchEnd,
localVideoViewerId localVideoViewerId
}, { transaction }) }, { transaction })