Do not take into account empty view sections
This commit is contained in:
parent
faabe996ba
commit
9b70c8e7e8
4 changed files with 26 additions and 14 deletions
|
@ -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 {
|
||||||
|
|
|
@ -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 () {
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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 })
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue