diff --git a/apps/dokploy/components/dashboard/requests/show-requests.tsx b/apps/dokploy/components/dashboard/requests/show-requests.tsx index e510488a4..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, @@ -20,9 +21,13 @@ 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(); + const { mutateAsync: toggleRequests } = + api.settings.toggleRequests.useMutation(); return ( <> @@ -33,29 +38,45 @@ export const ShowRequests = () => { Showing web and API requests over time - {!isLogRotateActive && ( - { - mutateAsync() + + { + await toggleRequests({ enable: !isActive }) .then(() => { - toast.success("Log rotate activated"); - refetchLogRotate(); + refetch(); + toast.success( + `Requests ${isActive ? "deactivated" : "activated"}`, + ); }) .catch((err) => { toast.error(err.message); }); }} > - Activate Log Rotate - - )} + {isActive ? "Deactivate" : "Activate"} + - {isLogRotateActive && ( - { - deactivateLogRotate() + toggleLogRotate({ + enable: !isLogRotateActive, + }) .then(() => { - toast.success("Log rotate deactivated"); + toast.success( + `Log rotate ${isLogRotateActive ? "activated" : "deactivated"}`, + ); refetchLogRotate(); }) .catch((err) => { @@ -63,9 +84,13 @@ export const ShowRequests = () => { }); }} > - Deactivate Log Rotate - - )} + + {isLogRotateActive + ? "Activate Log Rotate" + : "Deactivate Log Rotate"} + + + diff --git a/apps/dokploy/components/shared/dialog-action.tsx b/apps/dokploy/components/shared/dialog-action.tsx new file mode 100644 index 000000000..8b6f28472 --- /dev/null +++ b/apps/dokploy/components/shared/dialog-action.tsx @@ -0,0 +1,45 @@ +import { + AlertDialog, + AlertDialogAction, + AlertDialogCancel, + AlertDialogContent, + AlertDialogDescription, + AlertDialogFooter, + AlertDialogHeader, + AlertDialogTitle, + AlertDialogTrigger, +} from "@/components/ui/alert-dialog"; + +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 f34778ee5..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"; @@ -372,14 +373,71 @@ 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(); + + 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 mainConfig = readMainConfig(); + if (!mainConfig) return false; + + const currentConfig = load(mainConfig) as { + accessLog?: { + filePath: string; + }; + }; + + if (input.enable) { + const config = { + accessLog: { + filePath: "/etc/dokploy/traefik/dynamic/access.log", + format: "json", + bufferingSize: 100, + filters: { + retryAttempts: true, + minDuration: "10ms", + }, + }, + }; + currentConfig.accessLog = config.accessLog; + } else { + currentConfig.accessLog = undefined; + } + + writeMainConfig(dump(currentConfig)); + + 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/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) { diff --git a/apps/dokploy/server/utils/access-log/utils.ts b/apps/dokploy/server/utils/access-log/utils.ts index 94e4be242..6813e758a 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,10 @@ export function parseRawConfig( parsedLogs = parsedLogs.slice(startIndex, startIndex + page.pageSize); } + parsedLogs = parsedLogs.filter( + (log) => log.ServiceName !== "dokploy-service-app@file", + ); + return { data: parsedLogs, totalCount }; } catch (error) { console.error("Error parsing rawConfig:", error); 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";