From 7ec5c5beb0a9b02e8b8761908ee75ac2cfd317ee Mon Sep 17 00:00:00 2001 From: Blake Matthes Date: Wed, 19 Mar 2025 17:15:33 -0500 Subject: [PATCH] feat(logger): logger service created with its endpoints --- server/services/logger/controller/clearLog.ts | 22 ++++++++ server/services/logger/controller/getLogs.ts | 28 ++++++++++ .../services/logger/controller/logCleanup.ts | 55 +++++++++++++++++++ server/services/logger/loggerService.ts | 30 ++++++++++ server/services/logger/routes/clearLog.ts | 44 +++++++++++++++ server/services/logger/routes/createLog.ts | 38 +++++++++++++ server/services/logger/routes/getLogs.ts | 39 +++++++++++++ 7 files changed, 256 insertions(+) create mode 100644 server/services/logger/controller/clearLog.ts create mode 100644 server/services/logger/controller/getLogs.ts create mode 100644 server/services/logger/controller/logCleanup.ts create mode 100644 server/services/logger/loggerService.ts create mode 100644 server/services/logger/routes/clearLog.ts create mode 100644 server/services/logger/routes/createLog.ts create mode 100644 server/services/logger/routes/getLogs.ts diff --git a/server/services/logger/controller/clearLog.ts b/server/services/logger/controller/clearLog.ts new file mode 100644 index 0000000..05ae5ef --- /dev/null +++ b/server/services/logger/controller/clearLog.ts @@ -0,0 +1,22 @@ +import {eq, sql} from "drizzle-orm"; +import {db} from "../../../../database/dbclient.js"; +import {logs} from "../../../../database/schema/logs.js"; +import {createLog} from "../logger.js"; + +export const clearLog = async (id: string) => { + /** + * mark the log as cleared + */ + + try { + const clear = await db + .update(logs) + .set({checked: true, checkedAt: sql`NOW()`}) + .where(eq(logs.log_id, id)); + createLog("info", "lst", "logger", "Log just cleared."); + return {success: true, message: "Log was just cleared."}; + } catch (error) { + createLog("error", "lst", "logger", "There was an error clearing the log."); + return {success: false, message: "There was an error clearing the log."}; + } +}; diff --git a/server/services/logger/controller/getLogs.ts b/server/services/logger/controller/getLogs.ts new file mode 100644 index 0000000..ee29071 --- /dev/null +++ b/server/services/logger/controller/getLogs.ts @@ -0,0 +1,28 @@ +import {and, eq, inArray, lte, sql} from "drizzle-orm"; +import {db} from "../../../../database/dbclient.js"; +import {logs} from "../../../../database/schema/logs.js"; +import {createLog} from "../logger.js"; + +export const getLogs = async (data: any) => { + try { + // clear all remaining logs ne to info. + const checked = data.checked && data.checked[0] === "true" ? true : false || false; + const logData = await db + .select() + .from(logs) + .where( + and( + lte(logs.created_at, sql.raw(`NOW() - INTERVAL '${data.hours} hours'`)), + inArray(logs.service, data.service), + inArray(logs.level, data.level), + eq(logs.checked, checked) + ) + ); + + return {success: true, message: "logs returned", data: logData}; + } catch (error) { + console.log(error); + createLog("error", "lst", "logger", `There was an error deleteing server logs. ${error}`); + return {success: false, message: "An error occured while trying to get the logs", error}; + } +}; diff --git a/server/services/logger/controller/logCleanup.ts b/server/services/logger/controller/logCleanup.ts new file mode 100644 index 0000000..9571d87 --- /dev/null +++ b/server/services/logger/controller/logCleanup.ts @@ -0,0 +1,55 @@ +import {and, eq, inArray, lte, ne, sql} from "drizzle-orm"; +import {db} from "../../../../database/dbclient.js"; +import {logs} from "../../../../database/schema/logs.js"; +import {createLog} from "../logger.js"; + +export const logCleanup = async () => { + /** + * We will run the clean logger where we have aged logs that do not need to be here flooding the db + */ + + // clear the server logs older than 3 days + try { + // clear info logs older than 3 days + const delLogs = await db + .delete(logs) + .where( + and( + lte(logs.created_at, sql`NOW() - INTERVAL '3 days'`), + inArray(logs.service, ["server", "tcp", "sqlProd", "globalutils"]), + eq(logs.level, "30") + ) + ) + .returning({name: logs.message}); + createLog( + "info", + "lst", + "logger", + `${delLogs.length} Server logs were just deleted that were older than 3 days` + ); + } catch (error) { + createLog("error", "lst", "logger", `There was an error deleteing server logs. ${error}`); + } + + try { + // clear all remaining logs ne to info. + const delLogs = await db + .delete(logs) + .where( + and( + lte(logs.created_at, sql`NOW() - INTERVAL '7 days'`), + inArray(logs.service, ["server", "tcp", "sqlProd", "globalutils"]), + ne(logs.level, "30") + ) + ) + .returning({name: logs.message}); + createLog( + "info", + "lst", + "logger", + `${delLogs.length} Server logs were just deleted that were older than 7 days` + ); + } catch (error) { + createLog("error", "lst", "logger", `There was an error deleteing server logs. ${error}`); + } +}; diff --git a/server/services/logger/loggerService.ts b/server/services/logger/loggerService.ts new file mode 100644 index 0000000..48d70f1 --- /dev/null +++ b/server/services/logger/loggerService.ts @@ -0,0 +1,30 @@ +import {OpenAPIHono} from "@hono/zod-openapi"; + +// routes +import clearLog from "./routes/clearLog.js"; +import {db} from "../../../database/dbclient.js"; +import {settings} from "../../../database/schema/settings.js"; +import {logCleanup} from "./controller/logCleanup.js"; +import createNewLog from "./routes/createLog.js"; +import getLogs from "./routes/getLogs.js"; + +const app = new OpenAPIHono(); + +const routes = [clearLog, createNewLog, getLogs] as const; +const setting = await db.select().from(settings); + +const appRoutes = routes.forEach((route) => { + app.route("/logger", route); +}); + +app.all("/logger/*", (c) => { + return c.json({success: false, message: "You have encounters a log route that dose not exist."}); +}); + +// run the clean up job ones on server restart/crash/update and then once a date +logCleanup(); +setInterval(async () => { + logCleanup(); +}, 60 * 1000 * 60 * 24); + +export default app; diff --git a/server/services/logger/routes/clearLog.ts b/server/services/logger/routes/clearLog.ts new file mode 100644 index 0000000..ed61e38 --- /dev/null +++ b/server/services/logger/routes/clearLog.ts @@ -0,0 +1,44 @@ +import {createRoute, OpenAPIHono, z} from "@hono/zod-openapi"; +import {apiHit} from "../../../globalUtils/apiHits.js"; +import {responses} from "../../../globalUtils/routeDefs/responses.js"; +import {clearLog} from "../controller/clearLog.js"; + +const app = new OpenAPIHono({strict: false}); +const ParamsSchema = z.object({ + id: z + .string() + .min(3) + .openapi({ + param: { + name: "id", + in: "path", + }, + example: "1212121", + }), +}); + +app.openapi( + createRoute({ + tags: ["server:logger"], + summary: "Marks the select log id as cleared out.", + method: "patch", + path: "/logs/{id}", + request: { + params: ParamsSchema, + }, + responses: responses(), + }), + async (c) => { + const {id} = c.req.valid("param"); + //const body = await c.req.json(); + // make sure we have a vaid user being accessed thats really logged in + apiHit(c, {endpoint: `api/logger/logs/id`}); + try { + const clear = await clearLog(id); + return c.json({success: clear.success, message: clear.message, data: []}, 200); + } catch (error) { + return c.json({success: false, message: "There was an error clearing the log.", data: error}, 400); + } + } +); +export default app; diff --git a/server/services/logger/routes/createLog.ts b/server/services/logger/routes/createLog.ts new file mode 100644 index 0000000..6d23e96 --- /dev/null +++ b/server/services/logger/routes/createLog.ts @@ -0,0 +1,38 @@ +// an external way to creating logs +import {createRoute, OpenAPIHono, z} from "@hono/zod-openapi"; +import {apiHit} from "../../../globalUtils/apiHits.js"; +import {responses} from "../../../globalUtils/routeDefs/responses.js"; +import {createLog} from "../logger.js"; + +const app = new OpenAPIHono({strict: false}); +const CreateLog = z.object({ + level: z.string().openapi({example: "info"}), + service: z.string().openapi({example: "server"}), + message: z.string().openapi({example: "This is a new log posted"}), +}); + +app.openapi( + createRoute({ + tags: ["server:logger"], + summary: "Post a log to the db.", + method: "post", + path: "/logs", + description: "This might be a temp soltuin during the transtion between versions", + request: { + body: {content: {"application/json": {schema: CreateLog}}}, + }, + responses: responses(), + }), + async (c) => { + const body = await c.req.json(); + + apiHit(c, {endpoint: `api/logger/logs/id`}); + try { + createLog(body.level, "logger", body.service, body.message); + return c.json({success: true, message: "A new log was created.", data: []}, 200); + } catch (error) { + return c.json({success: false, message: "There was an error clearing the log.", data: error}, 400); + } + } +); +export default app; diff --git a/server/services/logger/routes/getLogs.ts b/server/services/logger/routes/getLogs.ts new file mode 100644 index 0000000..a62658a --- /dev/null +++ b/server/services/logger/routes/getLogs.ts @@ -0,0 +1,39 @@ +// an external way to creating logs +import {createRoute, OpenAPIHono, z} from "@hono/zod-openapi"; +import {apiHit} from "../../../globalUtils/apiHits.js"; +import {responses} from "../../../globalUtils/routeDefs/responses.js"; +import {createLog} from "../logger.js"; +import {getLogs} from "../controller/getLogs.js"; + +const app = new OpenAPIHono({strict: false}); +const CreateLog = z.object({ + level: z.string().openapi({example: "info"}), + service: z.string().openapi({example: "server"}), + message: z.string().openapi({example: "This is a new log posted"}), +}); + +app.openapi( + createRoute({ + tags: ["server:logger"], + summary: "Gets logs.", + method: "get", + path: "/logs", + description: "This might be a temp soltuin during the transtion between versions", + request: { + body: {content: {"application/json": {schema: CreateLog}}}, + }, + responses: responses(), + }), + async (c) => { + const query = await c.req.queries(); + + apiHit(c, {endpoint: `api/logger/logs`}); + try { + const logData = await getLogs(query); + return c.json({success: logData?.success, message: logData?.message, data: logData?.data}, 200); + } catch (error) { + return c.json({success: false, message: "There was an error clearing the log.", data: error}, 400); + } + } +); +export default app;