Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Framasoft
PeerTube
PeerTube
Commits
adc94cf0
Verified
Commit
adc94cf0
authored
Jul 27, 2022
by
Chocobozzz
Browse files
Add live and viewers otel metrics
parent
50cc1ee4
Changes
8
Hide whitespace changes
Inline
Side-by-side
server/lib/opentelemetry/metric-helpers/index.ts
View file @
adc94cf0
export
*
from
'
./lives-observers-builder
'
export
*
from
'
./job-queue-observers-builder
'
export
*
from
'
./nodejs-observers-builder
'
export
*
from
'
./stats-observers-builder
'
export
*
from
'
./viewers-observers-builder
'
server/lib/opentelemetry/metric-helpers/lives-observers-builder.ts
0 → 100644
View file @
adc94cf0
import
{
Meter
}
from
'
@opentelemetry/api-metrics
'
import
{
VideoModel
}
from
'
@server/models/video/video
'
export
class
LivesObserversBuilder
{
constructor
(
private
readonly
meter
:
Meter
)
{
}
buildObservers
()
{
this
.
meter
.
createObservableGauge
(
'
peertube_running_lives_total
'
,
{
description
:
'
Total running lives on the instance
'
}).
addCallback
(
async
observableResult
=>
{
const
local
=
await
VideoModel
.
countLives
({
remote
:
false
,
mode
:
'
published
'
})
const
remote
=
await
VideoModel
.
countLives
({
remote
:
true
,
mode
:
'
published
'
})
observableResult
.
observe
(
local
,
{
liveOrigin
:
'
local
'
})
observableResult
.
observe
(
remote
,
{
liveOrigin
:
'
remote
'
})
})
}
}
server/lib/opentelemetry/metric-helpers/viewers-observers-builder.ts
0 → 100644
View file @
adc94cf0
import
{
Meter
}
from
'
@opentelemetry/api-metrics
'
import
{
VideoScope
,
ViewerScope
}
from
'
@server/lib/views/shared
'
import
{
VideoViewsManager
}
from
'
@server/lib/views/video-views-manager
'
export
class
ViewersObserversBuilder
{
constructor
(
private
readonly
meter
:
Meter
)
{
}
buildObservers
()
{
this
.
meter
.
createObservableGauge
(
'
peertube_viewers_total
'
,
{
description
:
'
Total viewers on the instance
'
}).
addCallback
(
observableResult
=>
{
for
(
const
viewerScope
of
[
'
local
'
,
'
remote
'
]
as
ViewerScope
[])
{
for
(
const
videoScope
of
[
'
local
'
,
'
remote
'
]
as
VideoScope
[])
{
const
result
=
VideoViewsManager
.
Instance
.
getTotalViewers
({
viewerScope
,
videoScope
})
observableResult
.
observe
(
result
,
{
viewerOrigin
:
viewerScope
,
videoOrigin
:
videoScope
})
}
}
})
}
}
server/lib/opentelemetry/metrics.ts
View file @
adc94cf0
...
...
@@ -4,7 +4,13 @@ import { PrometheusExporter } from '@opentelemetry/exporter-prometheus'
import
{
MeterProvider
}
from
'
@opentelemetry/sdk-metrics-base
'
import
{
logger
}
from
'
@server/helpers/logger
'
import
{
CONFIG
}
from
'
@server/initializers/config
'
import
{
JobQueueObserversBuilder
,
NodeJSObserversBuilder
,
StatsObserversBuilder
}
from
'
./metric-helpers
'
import
{
JobQueueObserversBuilder
,
LivesObserversBuilder
,
NodeJSObserversBuilder
,
StatsObserversBuilder
,
ViewersObserversBuilder
}
from
'
./metric-helpers
'
class
OpenTelemetryMetrics
{
...
...
@@ -53,6 +59,12 @@ class OpenTelemetryMetrics {
const
statsObserversBuilder
=
new
StatsObserversBuilder
(
this
.
meter
)
statsObserversBuilder
.
buildObservers
()
const
livesObserversBuilder
=
new
LivesObserversBuilder
(
this
.
meter
)
livesObserversBuilder
.
buildObservers
()
const
viewersObserversBuilder
=
new
ViewersObserversBuilder
(
this
.
meter
)
viewersObserversBuilder
.
buildObservers
()
}
private
buildRequestObserver
()
{
...
...
server/lib/views/shared/video-viewer-counters.ts
View file @
adc94cf0
...
...
@@ -10,9 +10,14 @@ import { buildUUID, sha256 } from '@shared/extra-utils'
const
lTags
=
loggerTagsFactory
(
'
views
'
)
export
type
ViewerScope
=
'
local
'
|
'
remote
'
export
type
VideoScope
=
'
local
'
|
'
remote
'
type
Viewer
=
{
expires
:
number
id
:
string
viewerScope
:
ViewerScope
videoScope
:
VideoScope
lastFederation
?:
number
}
...
...
@@ -50,7 +55,7 @@ export class VideoViewerCounters {
return
false
}
const
newViewer
=
await
this
.
addViewerToVideo
({
viewerId
,
video
})
const
newViewer
=
await
this
.
addViewerToVideo
({
viewerId
,
video
,
viewerScope
:
'
local
'
})
await
this
.
federateViewerIfNeeded
(
video
,
newViewer
)
return
true
...
...
@@ -65,13 +70,26 @@ export class VideoViewerCounters {
logger
.
debug
(
'
Adding remote viewer to video %s.
'
,
video
.
uuid
,
{
...
lTags
(
video
.
uuid
)
})
await
this
.
addViewerToVideo
({
video
,
viewerExpires
,
viewerId
})
await
this
.
addViewerToVideo
({
video
,
viewerExpires
,
viewerId
,
viewerScope
:
'
remote
'
})
return
true
}
// ---------------------------------------------------------------------------
getTotalViewers
(
options
:
{
viewerScope
:
ViewerScope
videoScope
:
VideoScope
})
{
let
total
=
0
for
(
const
viewers
of
this
.
viewersPerVideo
.
values
())
{
total
+=
viewers
.
filter
(
v
=>
v
.
viewerScope
===
options
.
viewerScope
&&
v
.
videoScope
===
options
.
videoScope
).
length
}
return
total
}
getViewers
(
video
:
MVideo
)
{
const
viewers
=
this
.
viewersPerVideo
.
get
(
video
.
id
)
if
(
!
viewers
)
return
0
...
...
@@ -88,9 +106,10 @@ export class VideoViewerCounters {
private
async
addViewerToVideo
(
options
:
{
video
:
MVideoImmutable
viewerId
:
string
viewerScope
:
ViewerScope
viewerExpires
?:
Date
})
{
const
{
video
,
viewerExpires
,
viewerId
}
=
options
const
{
video
,
viewerExpires
,
viewerId
,
viewerScope
}
=
options
let
watchers
=
this
.
viewersPerVideo
.
get
(
video
.
id
)
...
...
@@ -103,7 +122,11 @@ export class VideoViewerCounters {
?
viewerExpires
.
getTime
()
:
this
.
buildViewerExpireTime
()
const
viewer
=
{
id
:
viewerId
,
expires
}
const
videoScope
:
VideoScope
=
video
.
remote
?
'
remote
'
:
'
local
'
const
viewer
=
{
id
:
viewerId
,
expires
,
videoScope
,
viewerScope
}
watchers
.
push
(
viewer
)
this
.
idToViewer
.
set
(
viewerId
,
viewer
)
...
...
server/lib/views/video-views-manager.ts
View file @
adc94cf0
import
{
logger
,
loggerTagsFactory
}
from
'
@server/helpers/logger
'
import
{
MVideo
,
MVideoImmutable
}
from
'
@server/types/models
'
import
{
VideoViewEvent
}
from
'
@shared/models
'
import
{
VideoViewerCounters
,
VideoViewerStats
,
VideoViews
}
from
'
./shared
'
import
{
VideoScope
,
VideoViewerCounters
,
VideoViewerStats
,
VideoViews
,
ViewerScope
}
from
'
./shared
'
/**
* If processing a local view:
...
...
@@ -79,6 +79,13 @@ export class VideoViewsManager {
return
this
.
videoViewerCounters
.
getViewers
(
video
)
}
getTotalViewers
(
options
:
{
viewerScope
:
ViewerScope
videoScope
:
VideoScope
})
{
return
this
.
videoViewerCounters
.
getTotalViewers
(
options
)
}
buildViewerExpireTime
()
{
return
this
.
videoViewerCounters
.
buildViewerExpireTime
()
}
...
...
server/middlewares/validators/videos/video-live.ts
View file @
adc94cf0
...
...
@@ -119,7 +119,7 @@ const videoLiveAddValidator = getCommonVideoEditAttributes().concat([
if
(
!
await
doesVideoChannelOfAccountExist
(
body
.
channelId
,
user
,
res
))
return
cleanUpReqFiles
(
req
)
if
(
CONFIG
.
LIVE
.
MAX_INSTANCE_LIVES
!==
-
1
)
{
const
totalInstanceLives
=
await
VideoModel
.
countL
ocalL
ives
()
const
totalInstanceLives
=
await
VideoModel
.
countLives
(
{
remote
:
false
,
mode
:
'
not-ended
'
}
)
if
(
totalInstanceLives
>=
CONFIG
.
LIVE
.
MAX_INSTANCE_LIVES
)
{
cleanUpReqFiles
(
req
)
...
...
server/models/video/video.ts
View file @
adc94cf0
...
...
@@ -1209,18 +1209,21 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
return
VideoModel
.
getAvailableForApi
(
queryOptions
)
}
static
countLocalLives
()
{
const
options
=
{
static
countLives
(
options
:
{
remote
:
boolean
mode
:
'
published
'
|
'
not-ended
'
})
{
const
query
=
{
where
:
{
remote
:
fals
e
,
remote
:
options
.
remot
e
,
isLive
:
true
,
state
:
{
[
Op
.
ne
]:
VideoState
.
LIVE_ENDED
}
state
:
options
.
mode
===
'
not-ended
'
?
{
[
Op
.
ne
]:
VideoState
.
LIVE_ENDED
}
:
{
[
Op
.
eq
]:
VideoState
.
PUBLISHED
}
}
}
return
VideoModel
.
count
(
options
)
return
VideoModel
.
count
(
query
)
}
static
countVideosUploadedByUserSince
(
userId
:
number
,
since
:
Date
)
{
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment