feat: add metric endpoint, move logs to new telemetry dash
Code Analysis / SonarQube (push) Failing after 18s
Node.js CI / Lint and Test (push) Successful in 46s

This commit is contained in:
2025-10-07 16:01:01 -07:00
parent 568cbb92e1
commit 3c9f6fa41a
4 changed files with 63 additions and 19 deletions
+1
View File
@@ -8,3 +8,4 @@ STRIPE_WEBHOOK_SECRET="op://Environment Variables - Naomi/Alert Server/stripe_we
DISCORD_TOKEN="op://Environment Variables - Naomi/Alert Server/discord_token"
LOG_TOKEN="op://Environment Variables - Naomi/Alert Server/log_token"
ERROR_LOG_TOKEN="op://Environment Variables - Naomi/Alert Server/error_token"
TELEMETRY_TOKEN="op://Environment Variables - Naomi/Alert Server/telemetry_token"
+11
View File
@@ -0,0 +1,11 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
export interface Metric {
application: string;
name: string;
value: number;
metadata?: Record<string, string>;
}
+12 -15
View File
@@ -4,13 +4,6 @@
* @author Naomi Carrigan
*/
const priority: Record<string, number> = {
debug: 0,
error: 3,
info: 1,
warn: 2,
};
/**
* Pipes a log message to the Gotify server.
* @param appName - The name of the application.
@@ -26,13 +19,15 @@ const pipeLog = async(
if (logToken === undefined) {
return;
}
await fetch(`https://logs.nhcarrigan.com/message?token=${logToken}`, {
await fetch(`https://telemetry.nhcarrigan.com/api/33kzMoHcYaaEyqCFsauKPhTvEtx/default/_json`, {
body: JSON.stringify({
message: message,
priority: priority[level] ?? priority.debug,
title: appName,
job: appName,
level: level,
log: message,
}),
headers: {
// eslint-disable-next-line @typescript-eslint/naming-convention -- Standard header.
"Authorization": `Basic ${process.env.TELEMETRY_TOKEN ?? ""}`,
// eslint-disable-next-line @typescript-eslint/naming-convention -- Standard header.
"Content-Type": "application/json",
},
@@ -56,13 +51,15 @@ const pipeError = async(
if (logToken === undefined) {
return;
}
await fetch(`https://logs.nhcarrigan.com/message?token=${logToken}`, {
await fetch(`https://telemetry.nhcarrigan.com/api/33kzMoHcYaaEyqCFsauKPhTvEtx/default/_json`, {
body: JSON.stringify({
message: message,
priority: priority[level] ?? priority.debug,
title: appName,
job: appName,
level: level,
log: message,
}),
headers: {
// eslint-disable-next-line @typescript-eslint/naming-convention -- Standard header.
"Authorization": `Basic ${process.env.TELEMETRY_TOKEN ?? ""}`,
// eslint-disable-next-line @typescript-eslint/naming-convention -- Standard header.
"Content-Type": "application/json",
},
+36 -1
View File
@@ -3,6 +3,7 @@
* @license Naomi's Public License
* @author Naomi Carrigan
*/
/* eslint-disable max-lines -- this is kinda the main file. */
import fastify from "fastify";
import rawBody from "fastify-raw-body";
@@ -20,6 +21,7 @@ import { errorHandler } from "../utils/errorHandler.js";
import type { Entitlement } from "../interfaces/entitlement.js";
import type { Error } from "../interfaces/error.js";
import type { Log } from "../interfaces/log.js";
import type { Metric } from "../interfaces/metric.js";
import type { Uptime } from "../interfaces/uptime.js";
const stripe = new StripeApp(process.env.STRIPE_SECRET_KEY ?? "");
@@ -77,6 +79,40 @@ export const instantiateServer = async(): Promise<void> => {
response.send(html);
});
// eslint-disable-next-line @typescript-eslint/naming-convention -- Body must be capitalised for Fastify.
server.post<{ Body: Metric }>("/metric", async(request, response) => {
try {
if (!auth(request)) {
await response.status(401).send({ success: false });
return;
}
const { application, name, value, metadata } = request.body;
await fetch(`https://telemetry.nhcarrigan.com/api/33kzMoHcYaaEyqCFsauKPhTvEtx/ingest/metrics/_json`, {
body: JSON.stringify([ {
// eslint-disable-next-line @typescript-eslint/naming-convention -- Needs to match API's structure.
__name__: "metrics",
// eslint-disable-next-line @typescript-eslint/naming-convention -- Needs to match API's structure.
__type__: "count",
app: application,
metadata: metadata ?? {},
name: name,
timestamp: Date.now(),
value: value,
} ]),
headers: {
// eslint-disable-next-line @typescript-eslint/naming-convention -- Standard header.
"Authorization": `Basic ${process.env.TELEMETRY_TOKEN ?? ""}`,
// eslint-disable-next-line @typescript-eslint/naming-convention -- Standard header.
"Content-Type": "application/json",
},
method: "POST",
});
} catch (error) {
await errorHandler(error, "Metric Webhook");
await response.status(500).send({ success: false });
}
});
// eslint-disable-next-line @typescript-eslint/naming-convention -- Body must be capitalised for Fastify.
server.post<{ Body: Log }>("/log", logSchema, async(request, response) => {
try {
@@ -330,7 +366,6 @@ export const instantiateServer = async(): Promise<void> => {
});
server.listen({ port: 5003 }, (error) => {
// eslint-disable-next-line max-lines -- This block is long because of logging.
const application = "Rosalia Nightsong";
if (error) {
const { message, stack } = error;