Log_service/app/Controllers/Http/ErpsController.ts

382 lines
11 KiB
TypeScript

import fs from "fs";
import type { HttpContextContract } from "@ioc:Adonis/Core/HttpContext";
import axios from "axios";
import Env from "@ioc:Adonis/Core/Env";
import LogDetectFile from "App/Models/LogDetectFile";
const path = require("path");
const BASE_URL = Env.get("BASE_URL_LOG");
const BASE_URL_AUTO = `${BASE_URL}/`;
const LOG_DIR = "home/logs";
export default class ErpsController {
/**
* Controller do tim cac serial number trong cac log trong khoang thoi gian xac dinh
* @param {Integer} from thoi gian bat dau YYYYMMDD (vd: 20230130)
* @param {Integer} to thoi gian ket thuc YYYYMMDD (vd: 20230230)
*/
public async getIndexSerialNumber({
request,
response,
}: HttpContextContract) {
const { from, to } = request.all();
const getListLogOld = async (from, to) => {
try {
const listLog: string[] = [];
const response = await axios.get(BASE_URL);
// const responseAUTO = await axios.get(BASE_URL_AUTO);
console.log("check!!!!!!!!!!!!!!!!!!!!!")
let data1 = response.data
.split("\n")
.filter((i) => i.search("<a href") !== -1 && i.search(".log") !== -1);
const arrayLine = data1;
arrayLine.map(async (u) => {
let fileName = u.slice(u.search("<a ") + 9, u.search("</a>")).split(">")[1];
if (
parseInt(fileName?.split("-")[0]) >= parseInt(from) &&
parseInt(fileName?.split("-")[0]) <= parseInt(to)
) {
listLog.push(
(BASE_URL + "/") +
fileName +
" "
);
const record = await LogDetectFile.firstOrCreate(
{ file_name: fileName },
{ file_name: fileName }
);
console.log(record.toJSON())
}
});
return listLog;
} catch (error) {
console.log(error);
}
};
const getListLog = async (from: string, to: string) => {
try {
const listLog: string[] = [];
// đọc danh sách file trong thư mục
const files = await fs.readdirSync(LOG_DIR);
// lọc file .log
const logFiles = files.filter((file) => file.endsWith(".log"));
// dùng Promise.all để xử lý async đúng cách
await Promise.all(
logFiles.map(async (fileName) => {
const prefixNumber = parseInt(fileName.split("-")[0]);
if (
prefixNumber >= parseInt(from) &&
prefixNumber <= parseInt(to)
) {
listLog.push(path.join(LOG_DIR, fileName));
const record = await LogDetectFile.firstOrCreate(
{ file_name: fileName },
{ file_name: fileName }
);
console.log(record.toJSON());
}
})
);
return listLog;
} catch (error) {
console.log(error);
return [];
}
};
const fetchWithRetry = async (url) => {
let retries = 0;
const MAX_RETRIES = 10;
while (retries < MAX_RETRIES) {
try {
const response = await axios.get(url);
return response.data;
} catch (error) {
if (error.code) {
retries++;
continue;
} else {
console.error("Error fetching file:", error);
return null;
}
}
}
return null;
};
const extractInfoFromLine = (cleanedLine, index, fName, lines, brand, PID) => {
const results: any = [];
const getWarehouse = (fileName) =>
/(US(?!A)|-US|\.US|US-)/.test(fileName) ? "US" : "AU";
const extractSN = (str) =>
str?.replace(/[!@#$%^&*()_+{}\[\]:;<>,.?~\\/]/g, "").trim();
// PID & SN
if (
cleanedLine.includes("PID:") &&
cleanedLine.includes("SN:") &&
!cleanedLine.includes("%")
) {
const parts = cleanedLine.split(",");
const SN = extractSN(
parts.find((p) => p.includes("SN:"))?.split(":")[1] ?? ""
);
PID = extractSN(
parts.find((p) => p.includes("PID:"))?.split(":")[1] ?? ""
);
const VID = extractSN(
parts.find((p) => p.includes("VID:"))?.split(":")[1] ?? ""
);
if (SN && SN !== "N/A" && SN.length > 4) {
results.push({
PID,
VID,
SN,
line: [index + 1],
brand,
fileName: fName,
warehouse: getWarehouse(fName),
});
}
}
// Serial Number
if (cleanedLine.includes("Serial Number")) {
const PCB_SN = extractSN(cleanedLine.split(":")[1]);
if (PCB_SN) {
results.push({
PID,
VID: "",
SN: PCB_SN,
line: [index + 1],
brand,
fileName: fName,
warehouse: getWarehouse(fName),
});
}
}
// Vendor Serial (SN)
if (cleanedLine.includes("Vendor Serial (SN)")) {
const PCB_SN = extractSN(cleanedLine.split(":")[1]);
if (PCB_SN) {
results.push({
PID,
VID: "",
SN: PCB_SN.trim(),
line: [index + 1],
brand,
fileName: fName,
warehouse: getWarehouse(fName),
});
}
}
if (cleanedLine.includes("System serial num")) {
const PCB_SN = extractSN(cleanedLine.split(":")[1]);
if (PCB_SN) {
results.push({
PID,
VID: "",
SN: PCB_SN,
line: [index + 1],
brand,
fileName: fName,
warehouse: getWarehouse(fName),
});
}
}
// Processor board ID
if (cleanedLine.includes("Processor board ID") || cleanedLine.includes("Processor Board ID")) {
const PBID = extractSN(cleanedLine.split(" ").pop());
if (PBID?.length >= 8) {
results.push({
PID,
VID: "",
SN: PBID,
line: [index + 1],
brand,
fileName: fName,
warehouse: getWarehouse(fName),
});
}
}
return results;
};
const mergeLines = (output, lineResult) => {
lineResult.forEach((entry) => {
const existing = output.find((o) => o.SN === entry.SN);
if (existing) {
existing.line = [...new Set([...existing.line, ...entry.line])];
if (entry.PID) existing.PID = entry.PID;
if (entry.VID) existing.VID = entry.VID;
} else {
output.push(entry);
}
});
};
const fetchFiles = async (from, to) => {
try {
const urls = await getListLog(from, to);
if (!urls || urls.length === 0) {
console.log("No logs found");
return [];
}
const fileContents = await Promise.all(
urls.map((u) => fetchWithRetry(u?.split(".log")[0] + ".log"))
);
let report: any = [];
fileContents.forEach((content, index) => {
const lines = content?.split("\n");
if (!lines) return;
const fName = path.basename(urls[index] ?? "").trim();
const output = [];
//Vendor Description: --> brand
let currentBrand = ""
let currentPID = ""
lines.forEach((line, i) => {
const cleanedLine = line.replace(/\r/g, "");
if (cleanedLine.includes("Vendor Description")) {
currentBrand = cleanedLine.split("Vendor Description:")[1]?.trim();
}
if (cleanedLine.includes("Vendor Part Number")) {
// console.log("Brand: ", cleanedLine)
// console.log("Brand1: ", cleanedLine.split("Vendor Part Number:")[1])
currentPID = cleanedLine.split("Vendor Part Number:")[1]?.trim();
}
const lineResult = extractInfoFromLine(cleanedLine, i, fName, lines, currentBrand, currentPID);
// Nếu dòng này tạo ra SN nào đó -> coi như brand đã được dùng xong
if (lineResult.length > 0 && currentBrand) {
currentBrand = "";
}
if (lineResult.length > 0 && currentPID) {
currentPID = "";
}
mergeLines(output, lineResult);
});
report = [...report, ...output];
});
const finalReport = report.filter(
(i) => i.SN && /^[A-Z0-9-]{5,}$/.test(i.SN)
);
fs.writeFileSync(
"./app/utils/indexSN.txt",
JSON.stringify(finalReport, null, 2).replace(/\\u0000/g, ""),
"utf-8"
);
console.log("Write loggg !");
return finalReport;
} catch (error) {
console.error("GET INFORMATION FAIL", error);
throw error;
}
};
const result = await fetchFiles(from, to);
response.status(200).json(result);
}
/**
* Controller lay noi dung file log theo so dong
* @param {String} fileName url file log tren server log
* @param {Integer} line dong chua serial number trong log
* @param {Integer} range khoang dong truoc/sau line
* @author {Token} req.headers.authorization //token xac thuc
*/
public async getParagraphOld({ request, response }: HttpContextContract) {
const { fileName, line, range } = request.all();
try {
let fName = fileName;
const res = await axios.get(BASE_URL + "/" + fName);
const arrayLine = res?.data?.split("\n");
if (Number(range) >= Number(line)) {
response.status(200).json({
content: arrayLine?.slice(0, line + range)?.join("\n"),
});
} else {
response.status(200).json({
content: arrayLine?.slice(line - range - 1, line + range)?.join("\n"),
});
}
} catch (error) {
console.log(error);
response.status(202).send({ mess: "FILE NOT FOUND", error: error });
}
}
public async getParagraph({ request, response }: HttpContextContract) {
const { fileName, line, range } = request.all();
try {
let fName = fileName;
// const res = await axios.get(BASE_URL + "/" + fName);
const LOG_DIR = "/home/logs";
const filePath = path.join(LOG_DIR, fileName);
const res = await fs.readFileSync(filePath, "utf-8");
const arrayLine = res?.split("\n");
if (Number(range) >= Number(line)) {
response.status(200).json({
content: arrayLine?.slice(0, line + range)?.join("\n"),
});
} else {
response.status(200).json({
content: arrayLine?.slice(line - range - 1, line + range)?.join("\n"),
});
}
} catch (error) {
console.log(error);
response.status(202).send({ mess: "FILE NOT FOUND", error: error });
}
}
public async store({ request, response }: HttpContextContract) { }
public async show({ }: HttpContextContract) { }
public async edit({ }: HttpContextContract) { }
public async update({ }: HttpContextContract) { }
public async destroy({ }: HttpContextContract) { }
}