From c4dca5761421cb77faeaecc005df6ee4a8316234 Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Thu, 5 Sep 2024 21:52:48 -0600 Subject: [PATCH 1/5] refactor: filter count by dokploy service --- apps/dokploy/server/utils/access-log/utils.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/apps/dokploy/server/utils/access-log/utils.ts b/apps/dokploy/server/utils/access-log/utils.ts index 94e4be242..872ea510e 100644 --- a/apps/dokploy/server/utils/access-log/utils.ts +++ b/apps/dokploy/server/utils/access-log/utils.ts @@ -17,6 +17,9 @@ export function processLogs(logString: string): HourlyData[] { .map((entry) => { try { const log: LogEntry = JSON.parse(entry); + if (log.ServiceName === "dokploy-service-app@file") { + return null; + } const date = new Date(log.StartUTC); return `${date.toISOString().slice(0, 13)}:00:00Z`; } catch (error) { @@ -89,6 +92,8 @@ export function parseRawConfig( parsedLogs = parsedLogs.slice(startIndex, startIndex + page.pageSize); } + parsedLogs = parsedLogs.filter((log) => log.ServiceName !== "1"); + return { data: parsedLogs, totalCount }; } catch (error) { console.error("Error parsing rawConfig:", error); From d3a54163bfc0a10b831abdfc8b40e8150fe71cf7 Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Fri, 6 Sep 2024 01:32:14 -0600 Subject: [PATCH 2/5] refactor: add option to activate the request distribution --- .../dashboard/requests/show-requests.tsx | 74 +++++++++++++------ apps/dokploy/server/api/routers/settings.ts | 61 +++++++++++++++ .../server/api/services/application.ts | 6 -- .../server/utils/traefik/application.ts | 2 +- 4 files changed, 113 insertions(+), 30 deletions(-) diff --git a/apps/dokploy/components/dashboard/requests/show-requests.tsx b/apps/dokploy/components/dashboard/requests/show-requests.tsx index e510488a4..03e115079 100644 --- a/apps/dokploy/components/dashboard/requests/show-requests.tsx +++ b/apps/dokploy/components/dashboard/requests/show-requests.tsx @@ -24,6 +24,11 @@ export const ShowRequests = () => { const { mutateAsync: deactivateLogRotate } = api.settings.deactivateLogRotate.useMutation(); + const { data: isActive, refetch } = + api.settings.haveActivateRequests.useQuery(); + const { mutateAsync: toggleRequests } = + api.settings.toggleRequests.useMutation(); + return ( <> @@ -33,39 +38,62 @@ export const ShowRequests = () => { Showing web and API requests over time - {!isLogRotateActive && ( +
- )} - - {isLogRotateActive && ( - - )} + {!isLogRotateActive && ( + + )} + {isLogRotateActive && ( + + )} +
diff --git a/apps/dokploy/server/api/routers/settings.ts b/apps/dokploy/server/api/routers/settings.ts index f34778ee5..59fcdec1c 100644 --- a/apps/dokploy/server/api/routers/settings.ts +++ b/apps/dokploy/server/api/routers/settings.ts @@ -53,6 +53,7 @@ import { } from "../services/settings"; import { canAccessToTraefikFiles } from "../services/user"; import { adminProcedure, createTRPCRouter, protectedProcedure } from "../trpc"; +import { dump, load } from "js-yaml"; export const settingsRouter = createTRPCRouter({ reloadServer: adminProcedure.mutation(async () => { @@ -382,4 +383,64 @@ export const settingsRouter = createTRPCRouter({ getLogRotateStatus: adminProcedure.query(async () => { return await logRotationManager.getStatus(); }), + haveActivateRequests: adminProcedure.query(async () => { + const config = readMainConfig(); + + if (!config) return false; + const parsedConfig = load(config) as { + accessLog?: { + filePath: string; + }; + }; + + return !!parsedConfig?.accessLog?.filePath; + }), + toggleRequests: adminProcedure + .input( + z.object({ + enable: z.boolean(), + }), + ) + .mutation(async ({ input }) => { + const config = readMainConfig(); + if (!config) return false; + + if (input.enable) { + const parsedConfig = load(config) as { + accessLog?: { + filePath: string; + format: string; + bufferingSize: number; + filters?: { + retryAttempts?: boolean; + minDuration?: string; + }; + }; + }; + const config2 = { + accessLog: { + filePath: "/etc/dokploy/traefik/dynamic/access.log", + format: "json", + bufferingSize: 100, + filters: { + retryAttempts: true, + minDuration: "10ms", + }, + }, + }; + parsedConfig.accessLog = config2.accessLog; + writeMainConfig(dump(parsedConfig)); + } else { + const parsedConfig = load(config) as { + accessLog?: { + filePath: string; + }; + }; + + delete parsedConfig.accessLog; + writeMainConfig(dump(parsedConfig)); + } + + return true; + }), }); diff --git a/apps/dokploy/server/api/services/application.ts b/apps/dokploy/server/api/services/application.ts index e712eec4e..1e7570274 100644 --- a/apps/dokploy/server/api/services/application.ts +++ b/apps/dokploy/server/api/services/application.ts @@ -59,12 +59,6 @@ export const createApplication = async ( if (process.env.NODE_ENV === "development") { createTraefikConfig(newApplication.appName); - await tx.insert(domains).values({ - applicationId: newApplication.applicationId, - host: `${newApplication.appName}.docker.localhost`, - port: process.env.NODE_ENV === "development" ? 3000 : 80, - certificateType: "none", - }); } return newApplication; diff --git a/apps/dokploy/server/utils/traefik/application.ts b/apps/dokploy/server/utils/traefik/application.ts index 52531c6e1..87216fb3d 100644 --- a/apps/dokploy/server/utils/traefik/application.ts +++ b/apps/dokploy/server/utils/traefik/application.ts @@ -1,7 +1,7 @@ import fs, { writeFileSync } from "node:fs"; import path from "node:path"; import type { Domain } from "@/server/api/services/domain"; -import { DYNAMIC_TRAEFIK_PATH } from "@/server/constants"; +import { DYNAMIC_TRAEFIK_PATH, MAIN_TRAEFIK_PATH } from "@/server/constants"; import { dump, load } from "js-yaml"; import type { FileConfig, HttpLoadBalancerService } from "./file-types"; From e57f8a32ceda4f6754229a47be9d8f0443ae066a Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Fri, 6 Sep 2024 22:38:32 -0600 Subject: [PATCH 3/5] refactor(requests): simplify logic --- .../dashboard/requests/show-requests.tsx | 97 +++++++++---------- .../components/shared/dialog-action.tsx | 47 +++++++++ apps/dokploy/server/api/routers/settings.ts | 59 ++++++----- .../server/utils/access-log/handler.ts | 2 +- 4 files changed, 123 insertions(+), 82 deletions(-) create mode 100644 apps/dokploy/components/shared/dialog-action.tsx diff --git a/apps/dokploy/components/dashboard/requests/show-requests.tsx b/apps/dokploy/components/dashboard/requests/show-requests.tsx index 03e115079..a7dea1ad0 100644 --- a/apps/dokploy/components/dashboard/requests/show-requests.tsx +++ b/apps/dokploy/components/dashboard/requests/show-requests.tsx @@ -11,6 +11,7 @@ import * as React from "react"; import { toast } from "sonner"; import { RequestDistributionChart } from "./request-distribution-chart"; import { RequestsTable } from "./requests-table"; +import { DialogAction } from "@/components/shared/dialog-action"; export type LogEntry = NonNullable< RouterOutputs["settings"]["readStatsLogs"]["data"] @@ -20,9 +21,8 @@ export const ShowRequests = () => { const { data: isLogRotateActive, refetch: refetchLogRotate } = api.settings.getLogRotateStatus.useQuery(); - const { mutateAsync } = api.settings.activateLogRotate.useMutation(); - const { mutateAsync: deactivateLogRotate } = - api.settings.deactivateLogRotate.useMutation(); + const { mutateAsync: toggleLogRotate } = + api.settings.toggleLogRotate.useMutation(); const { data: isActive, refetch } = api.settings.haveActivateRequests.useQuery(); @@ -39,60 +39,57 @@ export const ShowRequests = () => { Showing web and API requests over time
- - {!isLogRotateActive && ( - + + + { + toggleLogRotate({ + enable: !isLogRotateActive, + }) + .then(() => { + toast.success( + `Log rotate ${isLogRotateActive ? "activated" : "deactivated"}`, + ); + refetchLogRotate(); + }) + .catch((err) => { + toast.error(err.message); + }); + }} + > + - )} - {isLogRotateActive && ( - - )} +
diff --git a/apps/dokploy/components/shared/dialog-action.tsx b/apps/dokploy/components/shared/dialog-action.tsx new file mode 100644 index 000000000..e2ebd88bc --- /dev/null +++ b/apps/dokploy/components/shared/dialog-action.tsx @@ -0,0 +1,47 @@ +import { + AlertDialog, + AlertDialogAction, + AlertDialogCancel, + AlertDialogContent, + AlertDialogDescription, + AlertDialogFooter, + AlertDialogHeader, + AlertDialogTitle, + AlertDialogTrigger, +} from "@/components/ui/alert-dialog"; +import { Button } from "../ui/button"; +import { AlertCircle, TrashIcon } from "lucide-react"; + +interface Props { + title?: string; + description?: string; + onClick: () => void; + children?: React.ReactNode; +} + +export const DialogAction = ({ + onClick, + children, + description, + title, +}: Props) => { + return ( + + {children} + + + + {title ?? "Are you absolutely sure?"} + + + {description ?? "This action cannot be undone."} + + + + Cancel + Confirm + + + + ); +}; diff --git a/apps/dokploy/server/api/routers/settings.ts b/apps/dokploy/server/api/routers/settings.ts index 59fcdec1c..30ec711cf 100644 --- a/apps/dokploy/server/api/routers/settings.ts +++ b/apps/dokploy/server/api/routers/settings.ts @@ -373,16 +373,24 @@ export const settingsRouter = createTRPCRouter({ const processedLogs = processLogs(rawConfig as string); return processedLogs || []; }), - activateLogRotate: adminProcedure.mutation(async () => { - await logRotationManager.activate(); - return true; - }), - deactivateLogRotate: adminProcedure.mutation(async () => { - return await logRotationManager.deactivate(); - }), getLogRotateStatus: adminProcedure.query(async () => { return await logRotationManager.getStatus(); }), + toggleLogRotate: adminProcedure + .input( + z.object({ + enable: z.boolean(), + }), + ) + .mutation(async ({ input }) => { + if (input.enable) { + await logRotationManager.activate(); + } else { + await logRotationManager.deactivate(); + } + + return true; + }), haveActivateRequests: adminProcedure.query(async () => { const config = readMainConfig(); @@ -402,22 +410,17 @@ export const settingsRouter = createTRPCRouter({ }), ) .mutation(async ({ input }) => { - const config = readMainConfig(); - if (!config) return false; + const mainConfig = readMainConfig(); + if (!mainConfig) return false; + + const currentConfig = load(mainConfig) as { + accessLog?: { + filePath: string; + }; + }; if (input.enable) { - const parsedConfig = load(config) as { - accessLog?: { - filePath: string; - format: string; - bufferingSize: number; - filters?: { - retryAttempts?: boolean; - minDuration?: string; - }; - }; - }; - const config2 = { + const config = { accessLog: { filePath: "/etc/dokploy/traefik/dynamic/access.log", format: "json", @@ -428,19 +431,13 @@ export const settingsRouter = createTRPCRouter({ }, }, }; - parsedConfig.accessLog = config2.accessLog; - writeMainConfig(dump(parsedConfig)); + currentConfig.accessLog = config.accessLog; } else { - const parsedConfig = load(config) as { - accessLog?: { - filePath: string; - }; - }; - - delete parsedConfig.accessLog; - writeMainConfig(dump(parsedConfig)); + currentConfig.accessLog = undefined; } + writeMainConfig(dump(currentConfig)); + return true; }), }); diff --git a/apps/dokploy/server/utils/access-log/handler.ts b/apps/dokploy/server/utils/access-log/handler.ts index c7c5d71e3..3fd7e5c99 100644 --- a/apps/dokploy/server/utils/access-log/handler.ts +++ b/apps/dokploy/server/utils/access-log/handler.ts @@ -99,7 +99,7 @@ class LogRotationManager { await this.deactivateStream(); } await execAsync( - "docker kill -s USR1 $(docker ps -q --filter name=traefik)", + "docker kill -s USR1 $(docker ps -q --filter name=dokploy-traefik)", ); console.log("USR1 Signal send to Traefik"); } catch (error) { From acdc0ce1b0d1c09063778debe7640af20466526d Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Fri, 6 Sep 2024 22:39:38 -0600 Subject: [PATCH 4/5] refactor: add correct service name filter --- apps/dokploy/server/utils/access-log/utils.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/dokploy/server/utils/access-log/utils.ts b/apps/dokploy/server/utils/access-log/utils.ts index 872ea510e..6813e758a 100644 --- a/apps/dokploy/server/utils/access-log/utils.ts +++ b/apps/dokploy/server/utils/access-log/utils.ts @@ -92,7 +92,9 @@ export function parseRawConfig( parsedLogs = parsedLogs.slice(startIndex, startIndex + page.pageSize); } - parsedLogs = parsedLogs.filter((log) => log.ServiceName !== "1"); + parsedLogs = parsedLogs.filter( + (log) => log.ServiceName !== "dokploy-service-app@file", + ); return { data: parsedLogs, totalCount }; } catch (error) { From 922dcc5de8569949a6434cd7da039d66fbf21cf2 Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Fri, 6 Sep 2024 22:41:58 -0600 Subject: [PATCH 5/5] chore: biome --- apps/dokploy/components/dashboard/requests/show-requests.tsx | 2 +- apps/dokploy/components/shared/dialog-action.tsx | 2 -- apps/dokploy/server/api/routers/settings.ts | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/apps/dokploy/components/dashboard/requests/show-requests.tsx b/apps/dokploy/components/dashboard/requests/show-requests.tsx index a7dea1ad0..1b066529b 100644 --- a/apps/dokploy/components/dashboard/requests/show-requests.tsx +++ b/apps/dokploy/components/dashboard/requests/show-requests.tsx @@ -1,3 +1,4 @@ +import { DialogAction } from "@/components/shared/dialog-action"; import { Button } from "@/components/ui/button"; import { Card, @@ -11,7 +12,6 @@ import * as React from "react"; import { toast } from "sonner"; import { RequestDistributionChart } from "./request-distribution-chart"; import { RequestsTable } from "./requests-table"; -import { DialogAction } from "@/components/shared/dialog-action"; export type LogEntry = NonNullable< RouterOutputs["settings"]["readStatsLogs"]["data"] diff --git a/apps/dokploy/components/shared/dialog-action.tsx b/apps/dokploy/components/shared/dialog-action.tsx index e2ebd88bc..8b6f28472 100644 --- a/apps/dokploy/components/shared/dialog-action.tsx +++ b/apps/dokploy/components/shared/dialog-action.tsx @@ -9,8 +9,6 @@ import { AlertDialogTitle, AlertDialogTrigger, } from "@/components/ui/alert-dialog"; -import { Button } from "../ui/button"; -import { AlertCircle, TrashIcon } from "lucide-react"; interface Props { title?: string; diff --git a/apps/dokploy/server/api/routers/settings.ts b/apps/dokploy/server/api/routers/settings.ts index 30ec711cf..f98b981bc 100644 --- a/apps/dokploy/server/api/routers/settings.ts +++ b/apps/dokploy/server/api/routers/settings.ts @@ -41,6 +41,7 @@ import { } from "@/server/utils/traefik/web-server"; import { generateOpenApiDocument } from "@dokploy/trpc-openapi"; import { TRPCError } from "@trpc/server"; +import { dump, load } from "js-yaml"; import { scheduleJob, scheduledJobs } from "node-schedule"; import { z } from "zod"; import { appRouter } from "../root"; @@ -53,7 +54,6 @@ import { } from "../services/settings"; import { canAccessToTraefikFiles } from "../services/user"; import { adminProcedure, createTRPCRouter, protectedProcedure } from "../trpc"; -import { dump, load } from "js-yaml"; export const settingsRouter = createTRPCRouter({ reloadServer: adminProcedure.mutation(async () => {