diff --git a/package.json b/package.json index 7832f03..cf9fd47 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "floatplane-plex-downloader", - "version": "5.11.3", + "version": "5.11.4", "private": true, "type": "module", "scripts": { diff --git a/src/Downloader.ts b/src/Downloader.ts index 807e4e7..87e548f 100644 --- a/src/Downloader.ts +++ b/src/Downloader.ts @@ -33,16 +33,16 @@ const summaryStats: { [key: string]: { totalMB: number; downloadedMB: number; do let AvalibleDeliverySlots = DownloadThreads; const DownloadQueue: (() => void)[] = []; -const promVideosQueued = new Gauge({ +const promQueued = new Gauge({ name: "queued", help: "Videos waiting to download", }); -const promVideoErrors = new Counter({ +const promErrors = new Counter({ name: "errors", help: "Video errors", labelNames: ["message"], }); -const promVideosDownloadedTotal = new Counter({ +const promDownloadedTotal = new Counter({ name: "downloaded_total", help: "Videos downloaded", }); @@ -53,7 +53,7 @@ const promDownloadedBytesTotal = new Counter({ const getDownloadSempahore = async () => { totalVideos++; - promVideosQueued.inc(); + promQueued.inc(); // If there is an available request slot, proceed immediately if (AvalibleDeliverySlots > 0) return AvalibleDeliverySlots--; @@ -63,7 +63,7 @@ const getDownloadSempahore = async () => { const releaseDownloadSemaphore = () => { AvalibleDeliverySlots++; - promVideosQueued.dec(); + promQueued.dec(); // If there are queued requests, resolve the first one in the queue DownloadQueue.shift()?.(); @@ -193,7 +193,7 @@ const processVideo = async (fTitle: string, video: Video, retries = 0) => { // eslint-disable-next-line no-fallthrough case Video.State.Muxed: { completedVideos++; - promVideosDownloadedTotal.inc(); + promDownloadedTotal.inc(); updateSummaryBar(); mpb?.done(fTitle); setTimeout(() => mpb?.removeTask(fTitle), 10000 + Math.floor(Math.random() * 6000)); @@ -203,7 +203,7 @@ const processVideo = async (fTitle: string, video: Video, retries = 0) => { let info; if (!(error instanceof Error)) info = new Error(`Something weird happened, whatever was thrown was not a error! ${error}`); else info = error; - promVideoErrors.labels({ message: info.message.includes("ffmpeg") ? "ffmpeg" : info.message }).inc(); + promErrors.labels({ message: info.message.includes("ffmpeg") ? "ffmpeg" : info.message }).inc(); // Handle errors when downloading nicely if (retries < MaxRetries) { log(fTitle, { message: `\u001b[31m\u001b[1mERR\u001b[0m: ${info.message} - Retrying in ${retries}s [${retries}/${MaxRetries}]` }); diff --git a/src/lib/helpers.ts b/src/lib/helpers.ts index b3a251e..36c8f7d 100644 --- a/src/lib/helpers.ts +++ b/src/lib/helpers.ts @@ -1,6 +1,7 @@ import { downloadBinaries, detectPlatform, getBinaryFilename } from "ffbinaries"; import { getEnv, rebuildTypes, recursiveUpdate } from "@inrixia/helpers/object"; import { defaultArgs, defaultSettings } from "./defaults.js"; +import { Histogram } from "prom-client"; import db from "@inrixia/db"; import fs from "fs"; @@ -14,7 +15,7 @@ import "dotenv/config"; import json5 from "json5"; const { parse } = json5; -export const DownloaderVersion = "5.11.3"; +export const DownloaderVersion = "5.11.4"; import type { PartialArgs, Settings } from "./types.js"; @@ -28,6 +29,34 @@ export const fApi = new Floatplane( `Floatplane-Downloader/${DownloaderVersion} (Inrix, +https://github.com/Inrixia/Floatplane-Downloader), CFNetwork`, ); +// Add floatplane api request metrics +const httpRequestDurationmMs = new Histogram({ + name: "request_duration_ms", + help: "Duration of HTTP requests in ms", + labelNames: ["method", "hostname", "pathname", "status"], + buckets: [1, 10, 50, 100, 250, 500], +}); +type WithStartTime = T & { _startTime: number }; +fApi.extend({ + hooks: { + beforeRequest: [ + (options) => { + (>options)._startTime = Date.now(); + }, + ], + afterResponse: [ + (res) => { + const url = res.requestUrl; + const options = >res.request.options; + const thumbsIndex = url.pathname.indexOf("thumbnails"); + const pathname = thumbsIndex !== -1 ? url.pathname.substring(0, thumbsIndex + 10) : url.pathname; + httpRequestDurationmMs.observe({ method: options.method, hostname: url.hostname, pathname, status: res.statusCode }, Date.now() - options._startTime); + return res; + }, + ], + }, +}); + export const settings = db("./db/settings.json", { template: defaultSettings, pretty: true, forceCreate: true, updateOnExternalChanges: true }); recursiveUpdate(settings, defaultSettings); diff --git a/src/lib/prometheus.ts b/src/lib/prometheus.ts index 974c1ce..f32ea82 100644 --- a/src/lib/prometheus.ts +++ b/src/lib/prometheus.ts @@ -1,48 +1,20 @@ -import { collectDefaultMetrics, Gauge, Histogram, register } from "prom-client"; +import { collectDefaultMetrics, Gauge, register } from "prom-client"; import { createServer } from "http"; import WebSocket from "ws"; -import { DownloaderVersion, fApi, settings } from "./helpers.js"; +import { DownloaderVersion, settings } from "./helpers.js"; -export const initProm = (instance: string) => { - collectDefaultMetrics(); - - new Gauge({ - name: "instance", - help: "Floatplane Downloader instances", - labelNames: ["version"], - }) - .labels({ version: DownloaderVersion }) - .set(1); +collectDefaultMetrics(); - // Add floatplane api request metrics - const httpRequestDurationmS = new Histogram({ - name: "request_duration_ms", - help: "Duration of HTTP requests in ms", - labelNames: ["method", "hostname", "pathname", "status"], - buckets: [1, 10, 50, 100, 250, 500], - }); - type WithStartTime = T & { _startTime: number }; - fApi.extend({ - hooks: { - beforeRequest: [ - (options) => { - (>options)._startTime = Date.now(); - }, - ], - afterResponse: [ - (res) => { - const url = res.requestUrl; - const options = >res.request.options; - const thumbsIndex = url.pathname.indexOf("thumbnails"); - const pathname = thumbsIndex !== -1 ? url.pathname.substring(0, thumbsIndex + 10) : url.pathname; - httpRequestDurationmS.observe({ method: options.method, hostname: url.hostname, pathname, status: res.statusCode }, Date.now() - options._startTime); - return res; - }, - ], - }, - }); +new Gauge({ + name: "instance", + help: "Floatplane Downloader instances", + labelNames: ["version"], +}) + .labels({ version: DownloaderVersion }) + .set(1); +export const initProm = (instance: string) => { if (settings.metrics.contributeMetrics) { const connect = () => { const socket = new WebSocket("ws://targets.monitor.spookelton.net");