invidious-companion-patches/patches/0013-metrics-track-unidentified-innertube-errors.patch

214 lines
7.1 KiB
Diff
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

From a18ba4ac49ae7bd3c8a82175875c9398d3c09056 Mon Sep 17 00:00:00 2001
From: Fijxu <fijxu@nadeko.net>
Date: Wed, 9 Apr 2025 13:37:16 -0400
Subject: [PATCH 13/14] metrics: track unidentified innertube errors
---
src/lib/helpers/config.ts | 4 ++
src/lib/helpers/metrics.ts | 117 +++++++++++++++++++++++++++++++------
src/main.ts | 4 +-
3 files changed, 106 insertions(+), 19 deletions(-)
diff --git a/src/lib/helpers/config.ts b/src/lib/helpers/config.ts
index acb04bb..20e5560 100644
--- a/src/lib/helpers/config.ts
+++ b/src/lib/helpers/config.ts
@@ -23,6 +23,10 @@ export const ConfigSchema = z.object({
disable_logs: z.boolean().default(
Deno.env.get("SERVER_DISABLE_LOGS") === "true" || false,
),
+ track_unknown_innertube_errors: z.boolean().default(
+ Deno.env.get("SERVER_TRACK_UNKNOWN_INNERTUBE_ERRORS") === "true" ||
+ false,
+ ),
}).strict().default({}),
cache: z.object({
enabled: z.boolean().default(true),
diff --git a/src/lib/helpers/metrics.ts b/src/lib/helpers/metrics.ts
index 5dee540..c22c792 100644
--- a/src/lib/helpers/metrics.ts
+++ b/src/lib/helpers/metrics.ts
@@ -2,14 +2,24 @@ import { IRawResponse } from "youtubei.js";
import { Counter, Registry } from "prom-client";
export class Metrics {
+ trackUnknownInnertubeErrors: boolean;
private METRICS_PREFIX = "invidious_companion_";
public register = new Registry();
- public createCounter(name: string, help?: string): Counter {
+ constructor(trackUnknownInnertubeErrors: boolean) {
+ this.trackUnknownInnertubeErrors = trackUnknownInnertubeErrors;
+ }
+
+ public createCounter(
+ name: string,
+ help?: string,
+ labels?: string[],
+ ): Counter {
return new Counter({
name: `${this.METRICS_PREFIX}${name}`,
help: help || "No help has been provided for this metric",
registers: [this.register],
+ labelNames: Array.isArray(labels) ? labels : [],
});
}
@@ -26,6 +36,7 @@ export class Metrics {
private innertubeErrorStatusUnknown = this.createCounter(
"innertube_error_status_unknown_total",
"Number of times that an unknown status has been returned by Innertube API",
+ ["error"],
);
private innertubeErrorReasonSignIn = this.createCounter(
@@ -66,26 +77,62 @@ export class Metrics {
private checkStatus(videoData: IRawResponse) {
const status = videoData.playabilityStatus?.status;
- return {
- unplayable: status ===
- "UNPLAYABLE",
- contentCheckRequired: status ===
- "CONTENT_CHECK_REQUIRED",
- loginRequired: status === "LOGIN_REQUIRED",
+ interface Error {
+ unplayable: boolean;
+ contentCheckRequired: boolean;
+ loginRequired: boolean;
+ unknown: string | undefined;
+ }
+
+ const error: Error = {
+ unplayable: false,
+ contentCheckRequired: false,
+ loginRequired: false,
+ unknown: undefined,
};
+
+ switch (status) {
+ case "UNPLAYABLE":
+ error.unplayable = true;
+ return error;
+ case "CONTENT_CHECK_REQUIRED":
+ error.contentCheckRequired = true;
+ return error;
+ case "LOGIN_REQUIRED":
+ error.loginRequired = true;
+ return error;
+ default:
+ error.unknown = status;
+ return error;
+ }
}
private checkReason(videoData: IRawResponse) {
const reason = videoData.playabilityStatus?.reason;
- return {
- signInToConfirmAge: reason?.includes(
- "Sign in to confirm your age",
- ),
- SignInToConfirmBot: reason?.includes(
- "Sign in to confirm youre not a bot",
- ),
+ interface Error {
+ signInToConfirmAge: boolean;
+ SignInToConfirmBot: boolean;
+ unknown: string | undefined;
+ }
+
+ const error: Error = {
+ signInToConfirmAge: false,
+ SignInToConfirmBot: false,
+ unknown: undefined,
};
+
+ switch (true) {
+ case reason?.includes("Sign in to confirm your age"):
+ error.signInToConfirmAge = true;
+ return error;
+ case reason?.includes("Sign in to confirm youre not a bot"):
+ error.SignInToConfirmBot = true;
+ return error;
+ default:
+ error.unknown = reason;
+ return error;
+ }
}
private checkSubreason(videoData: IRawResponse) {
@@ -93,17 +140,51 @@ export class Metrics {
?.playerErrorMessageRenderer
?.subreason?.runs?.[0]?.text;
- return {
- thisHelpsProtectCommunity: subReason?.includes(
- "This helps protect our community",
- ),
+ interface Error {
+ thisHelpsProtectCommunity: boolean;
+ unknown: string | undefined;
+ }
+
+ const error: Error = {
+ thisHelpsProtectCommunity: false,
+ unknown: undefined,
};
+
+ switch (true) {
+ case subReason?.includes("This helps protect our community"):
+ error.thisHelpsProtectCommunity = true;
+ return error;
+ default:
+ error.unknown = subReason;
+ return error;
+ }
}
public checkInnertubeResponse(videoData: IRawResponse) {
this.innertubeFailedRequest.inc();
const status = this.checkStatus(videoData);
+ if (this.trackUnknownInnertubeErrors) {
+ if (status?.unknown) {
+ this.innertubeErrorStatusUnknown.labels({
+ error: status.unknown,
+ }).inc();
+ const reason = this.checkReason(videoData);
+ if (reason) {
+ this.innertubeErrorReasonUnknown.labels({
+ error: status.unknown,
+ }).inc();
+ const subReason = this.checkSubreason(videoData);
+ if (subReason) {
+ this.innertubeErrorStatusUnknown.labels({
+ error: status.unknown,
+ }).inc();
+ }
+ }
+ return;
+ }
+ }
+
if (status.contentCheckRequired || status.unplayable) return;
if (status.loginRequired) {
diff --git a/src/main.ts b/src/main.ts
index f659d97..84ef286 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -27,7 +27,9 @@ declare module "hono" {
interface ContextVariableMap extends HonoVariables {}
}
const app = new Hono();
-const metrics = config.server.enable_metrics ? new Metrics() : undefined;
+const metrics = config.server.enable_metrics
+ ? new Metrics(config.server.track_unknown_innertube_errors)
+ : undefined;
let tokenMinter: TokenMinter;
let innertubeClient: Innertube;
--
2.49.0