tambahannya
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import Elysia from "elysia";
|
import Elysia, { t } from "elysia";
|
||||||
import fs from "fs/promises";
|
import fs from "fs/promises";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
|
|
||||||
@@ -6,71 +6,92 @@ const LOGS_PATH = process.env.APP_LOGS_PATH || "./.logs";
|
|||||||
|
|
||||||
// Pastikan folder log ada saat startup
|
// Pastikan folder log ada saat startup
|
||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
await fs.access(LOGS_PATH);
|
await fs.access(LOGS_PATH);
|
||||||
} catch {
|
} catch {
|
||||||
await fs.mkdir(LOGS_PATH, { recursive: true });
|
await fs.mkdir(LOGS_PATH, { recursive: true });
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
// Helper baca log file + optional filter
|
// Helper baca log file + optional filter
|
||||||
async function readLogs(limit?: number, level?: string) {
|
async function readLogs(limit?: number, level?: string) {
|
||||||
const filePath = path.join(LOGS_PATH, "app.log");
|
const filePath = path.join(LOGS_PATH, "app.log");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const data = await fs.readFile(filePath, "utf-8");
|
const data = await fs.readFile(filePath, "utf-8");
|
||||||
let lines = data.trim().split("\n").filter(Boolean); // tiap baris = JSON log
|
let lines = data.trim().split("\n").filter(Boolean); // tiap baris = JSON log
|
||||||
|
|
||||||
if (limit) {
|
if (limit) {
|
||||||
lines = lines.slice(-limit);
|
lines = lines.slice(-limit);
|
||||||
|
}
|
||||||
|
|
||||||
|
let parsed = lines.map((line) => {
|
||||||
|
try {
|
||||||
|
return JSON.parse(line);
|
||||||
|
} catch {
|
||||||
|
return { raw: line };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Filter berdasarkan level (error, info, debug, warn)
|
||||||
|
if (level) {
|
||||||
|
parsed = parsed.filter((log) =>
|
||||||
|
log.level ? String(log.level) === level || log.level === level : false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return parsed;
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let parsed = lines.map((line) => {
|
|
||||||
try {
|
|
||||||
return JSON.parse(line);
|
|
||||||
} catch {
|
|
||||||
return { raw: line };
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Filter berdasarkan level (error, info, debug, warn)
|
|
||||||
if (level) {
|
|
||||||
parsed = parsed.filter((log) =>
|
|
||||||
log.level ? String(log.level) === level || log.level === level : false
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return parsed;
|
|
||||||
} catch {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const LogsRoute = new Elysia({
|
const LogsRoute = new Elysia({
|
||||||
prefix: "/logs",
|
prefix: "/logs",
|
||||||
tags: ["logs"],
|
tags: ["logs"],
|
||||||
})
|
})
|
||||||
/**
|
/**
|
||||||
* GET /logs/app?lines=100&level=error
|
* GET /logs/app?lines=100&level=error
|
||||||
*/
|
*/
|
||||||
.get("/app", async ({ query }) => {
|
.get("/show", async ({ query }) => {
|
||||||
const lines = query.lines ? Number(query.lines) : undefined;
|
const lines = query.lines ? Number(query.lines) : undefined;
|
||||||
const level = query.level || undefined;
|
const level = query.level || undefined;
|
||||||
|
|
||||||
const logs = await readLogs(lines, level);
|
const logs = await readLogs(lines, level);
|
||||||
|
|
||||||
if (!logs) {
|
if (!logs) {
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
message: "Log file not found or unreadable",
|
message: "Log file not found or unreadable",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
total: logs.length,
|
total: logs.length,
|
||||||
data: logs,
|
data: logs,
|
||||||
};
|
};
|
||||||
});
|
}, {
|
||||||
|
query: t.Object({
|
||||||
|
lines: t.Optional(t.Number()),
|
||||||
|
level: t.Optional(t.String()),
|
||||||
|
}),
|
||||||
|
detail: {
|
||||||
|
summary: "Get logs",
|
||||||
|
description: "Get logs from app.log",
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.post("/clear", async () => {
|
||||||
|
await fs.rm(path.join(LOGS_PATH, "app.log"));
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: "Log file cleared",
|
||||||
|
};
|
||||||
|
}, {
|
||||||
|
detail: {
|
||||||
|
summary: "Clear logs",
|
||||||
|
description: "Clear logs from app.log",
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
export default LogsRoute;
|
export default LogsRoute;
|
||||||
|
|||||||
Reference in New Issue
Block a user