Слияние кода завершено, страница обновится автоматически
const fs = require("fs");
const path = require("path");
const OSS = require("ali-oss");
const { ipcMain } = require("electron");
const getUsers = (users) => {
const us = {};
if (users) {
users.forEach((u) => {
us[u.uid] = u.name;
});
}
return us;
};
const toNumber = (str) => {
return isNaN(str) ? 0 : Number(str);
};
/**
* 日志字段参见: https://help.aliyun.com/document_detail/31868.html
* res: [Time, Request-UR, Referer, User-Agent, HostName, Request ID, LoggingFlag, Requester Aliyun ID, Operation, Bucket, Key, Error Code, UserID, Sync Reques, StorageClass,TargetStorageClass, null]
* other: [Remote IP, Reserved, Reserved, HTTP Status, SentBytes, RequestTime (ms), ObjectSize, Server Cost Time (ms), Request Length, Delta DataSize]
*/
const handleUser = (logOne, data, users) => {
const res = logOne
.trim()
.match(/".*?"|\[.*?\]/g)
.map((v) => v.replace(/"/g, ""));
const uid = res[7];
if (!(uid in data)) {
data[uid] = {
// 配置的用户备注
name: users[uid] || (uid == "-" ? "匿名" : uid),
// 返回错误的请求
errors: {},
errorCount: 0,
// 增加的大小
increasedSize: 0,
// 减少的大小
reducedSize: 0,
// 外网流量
outTraffic: 0,
// 操作
operations: {},
};
}
const others = logOne
.trim()
.replace(/".*?"|\[.*?\]/g, " ")
.split(/\s+/);
const status = toNumber(others[3]);
const operation = res[8];
if (status == 200) {
const dataSize = toNumber(others[9]);
if (dataSize > 0) {
data[uid].increasedSize += dataSize;
} else {
data[uid].reducedSize += dataSize;
}
const host = res[4];
if (host.indexOf("-internal.aliyuncs.com") < 0) {
const traffic = toNumber(others[8]);
data[uid].outTraffic += traffic;
}
if (!(operation in data[uid].operations)) {
data[uid].operations[operation] = 0;
}
data[uid].operations[operation] += 1;
} else {
data[uid].errorCount += 1;
const errCode = res[11];
if (!(operation in data[uid].errors)) {
data[uid].errors[operation] = {};
}
if (!(errCode in data[uid].errors[operation])) {
data[uid].errors[operation][errCode] = 0;
}
data[uid].errors[operation][errCode] += 1;
}
return data;
};
const handleLocalLogs = (
{ local, prefix, startTime, endTime, ...rest },
users
) => {
const data = {};
const files = fs.readdirSync(local.dir);
if (files.length === 0) {
return { status: 1, message: "所选日志位置无文件" };
}
const fileStartName = prefix + startTime;
const fileEndName = prefix + endTime;
let total = 0;
for (const file of files) {
if (file >= fileStartName && file <= fileEndName) {
const logText = fs.readFileSync(path.resolve(local.dir, file), "utf-8");
const logArr = logText.split("\n");
logArr.forEach((logOne) => {
if (logOne.trim()) {
if (rest.handleWay == "user") {
handleUser(logOne.trim(), data, users);
}
}
});
total += 1;
}
}
if (total === 0) {
return { status: 1, message: "没有对应前缀以及日期的日志文件" };
}
return {
status: 0,
message: "共处理 " + total + " 个文件",
data,
};
};
const handleClientLogs = async ({ connection, ...rest }, users) => {
const data = {};
const { endpoint, keyid, keysecret, cname, bucket, prefix } = connection;
const client = new OSS({
endpoint,
accessKeyId: keyid,
accessKeySecret: keysecret,
bucket,
cname,
});
let successTotal = 0,
filedTotal = 0;
let nextMarker = prefix + rest.prefix + rest.startTime + "-001";
while (nextMarker && nextMarker <= prefix + rest.prefix + rest.endTime) {
const result = await client.list({
prefix: prefix + rest.prefix,
marker: nextMarker,
});
if (result.res.statusCode === 200) {
for (const file of result.objects) {
if (file.name <= prefix + rest.prefix + rest.endTime) {
const res = await client.get(file.name);
if (res.res.statusCode === 200) {
successTotal += 1;
const buffer = Buffer.from(res.content);
const logText = buffer.toString();
const logArr = logText.split("\n");
logArr.forEach((logOne) => {
if (logOne.trim()) {
if (rest.handleWay == "user") {
handleUser(logOne.trim(), data, users);
}
}
});
} else {
filedTotal += 1;
}
}
}
nextMarker = result.nextMarker;
} else {
nextMarker = null;
}
}
if (successTotal === 0) {
return { status: 1, message: "没有对应前缀以及日期的日志文件" };
}
return {
status: 0,
message:
"共成功处理 " +
successTotal +
" 个文件" +
(filedTotal ? " 处理失败 " + filedTotal + " 个文件" : ""),
data,
};
};
const handleStatistics = async (params) => {
try {
const users = getUsers(params.users);
if (params.readWay === "local") {
return handleLocalLogs(params, users);
} else if (params.readWay === "client") {
// 在线查看日志文件
return await handleClientLogs(params, users);
}
return { status: 2, message: "无效的读取方式" };
} catch (error) {
return { status: 2, message: JSON.stringify(error) };
}
};
ipcMain.on("handleStatistics", async (event, params = {}) => {
params.users = global.config.users;
params.prefix = global.config.prefix;
if (params.readWay === "local") {
params.local = global.config.local;
} else if (params.readWay === "client") {
params.connection = global.config.connection;
}
event.reply("showResultData", await handleStatistics(params));
});
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Комментарий ( 0 )