Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/FoxxMD/multi-scrobbler. Scrobble plays from multiple sources to multiple clients docs.multi-scrobbler.app
deezer docker jellyfin koito lastfm listenbrainz maloja mopidy mpris music music-assistant plex scrobble self-hosted spotify subsonic tautulli youtube-music
Something went wrong. Try again.
7.3 kB · 145 lines
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145import type { DrizzlePlayHistoricalRepository } from "../common/database/drizzle/repositories/PlayHistoricalRepository.ts";import type { DrizzlePlayRepository } from "../common/database/drizzle/repositories/PlayRepository.ts";import prom from 'prom-client';import type ScrobbleSources from "../sources/ScrobbleSources.ts";import type ScrobbleClients from "../scrobblers/ScrobbleClients.ts";import { PLAY_CLIENT_STATE, PLAY_SOURCE_STATE } from "../../core/Atomic.ts";import AbstractHistoricalScrobbleClient from "../scrobblers/AbstractHistoricalScrobbleClient.ts";
let playRepo: DrizzlePlayRepository, playHistoricalRepo: DrizzlePlayHistoricalRepository;
export const setMetricRepositories = (play: DrizzlePlayRepository, playHistorical: DrizzlePlayHistoricalRepository) => { playRepo = play; playHistoricalRepo = playHistorical;}export const hasMetricRepositories = () => playRepo !== undefined;
export const registerMetrics = (scrobbleSources: ScrobbleSources, scrobbleClients: ScrobbleClients) => { if (prom.register.getSingleMetric('multiscrobbler_client_issues') === undefined) { new prom.Gauge({ name: 'multiscrobbler_client_issues', help: 'Number of errors/issues with Client', labelNames: ['name', 'type'], async collect() { for (const client of scrobbleClients.clients) { let issues = 0; if (!(await client.isReady())) { issues++; } this.labels({ name: client.getSafeExternalName(), type: client.type }).set(issues); } } }); } if (prom.register.getSingleMetric('multiscrobbler_source_issues') === undefined) { new prom.Gauge({ name: 'multiscrobbler_source_issues', help: 'Number of errors/issues with Source', labelNames: ['name', 'type'], async collect() { for (const source of scrobbleSources.sources) { let issues = 0; if (source.requiresAuth && !source.authed) { issues++; } if (source.canPoll && !source.polling) { issues++; } this.labels({ name: source.getSafeExternalName(), type: source.type }).set(issues); } } }); } if (prom.register.getSingleMetric('multiscrobbler_source_plays') === undefined) { new prom.Gauge({ name: 'multiscrobbler_source_plays', help: 'Count of stored plays by state for Sources', labelNames: ['name', 'type', 'state'], async collect() { const res = await playRepo.getPlayCountByState(); for (const source of scrobbleSources.sources) { const relevant = res.filter(x => x['componentId'] === source.componentId); for (const s of PLAY_SOURCE_STATE) { const rel = relevant.find(x => x['state'] === s); const count = rel === undefined ? 0 : rel['count(*)']; this.labels({ name: source.getSafeExternalName(), type: source.type, state: s }).set(count); } } } }); }
if (prom.register.getSingleMetric('multiscrobbler_source_plays_compacted') === undefined) { new prom.Gauge({ name: 'multiscrobbler_source_plays_compacted', help: 'Count of compacted, stored plays by compaction type for Sources', labelNames: ['name', 'type', 'compactionType'], async collect() { const res = await playRepo.getCompactedPlayCountByComponent(); for (const source of scrobbleSources.sources) { const relevant = res.filter(x => x['componentId'] === source.componentId); for (const s of ['input', 'transform', 'input-transform']) { const rel = relevant.find(x => x['compacted'] === s); const count = rel === undefined ? 0 : rel['count(*)']; this.labels({ name: source.getSafeExternalName(), type: source.type, compactionType: s }).set(count); } } } }); } if (prom.register.getSingleMetric('multiscrobbler_client_plays') === undefined) { new prom.Gauge({ name: 'multiscrobbler_client_plays', help: 'Count of stored plays by state for Clients', labelNames: ['name', 'type', 'state'], async collect() { const res = await playRepo.getPlayCountByState(); for (const client of scrobbleClients.clients) { const relevant = res.filter(x => x['componentId'] === client.componentId); for (const s of PLAY_CLIENT_STATE) { const rel = relevant.find(x => x['state'] === s); const count = rel === undefined ? 0 : rel['count(*)']; this.labels({ name: client.getSafeExternalName(), type: client.type, state: s }).set(count); } } } }); } if (prom.register.getSingleMetric('multiscrobbler_client_plays_compacted') === undefined) { new prom.Gauge({ name: 'multiscrobbler_client_plays_compacted', help: 'Count of compacted, stored plays by compaction type for Clients', labelNames: ['name', 'type', 'compactionType'], async collect() { const res = await playRepo.getCompactedPlayCountByComponent(); for (const client of scrobbleClients.clients) { const relevant = res.filter(x => x['componentId'] === client.componentId); for (const s of ['input', 'transform', 'input-transform']) { const rel = relevant.find(x => x['compacted'] === s); const count = rel === undefined ? 0 : rel['count(*)']; this.labels({ name: client.getSafeExternalName(), type: client.type, compactionType: s }).set(count); } } } }); } if (prom.register.getSingleMetric('multiscrobbler_client_historical_plays') === undefined) { new prom.Gauge({ name: 'multiscrobbler_client_historical_plays', help: 'Count of stored historical plays for Clients', labelNames: ['name', 'type'], async collect() { const res = await playHistoricalRepo.getPlayCountByComponent(); for (const client of scrobbleClients.clients) { if (client instanceof AbstractHistoricalScrobbleClient) { const relevant = res.filter(x => x['componentId'] === client.componentId); for (const rel of relevant) { this.labels({ name: client.getSafeExternalName(), type: client.type }).set(rel['count(*)']); } } } } }); }}