Skip to content

Commit

Permalink
feat: 操作日志优化 (#1070)
Browse files Browse the repository at this point in the history
### 改动

对部分操作类型的操作日志的详细内容进行了一部分优化

- 提交作业,创建应用,结束作业新增  clusterId 
- 增加作业模板,删除作业模板,更新作业模板 新增clusterId
- 创建桌面新增clusterId, loginNode, 删除桌面新增clusterId
- 设置作业时限增加clusterId

对历史数据的处理,利用migration给上述操作类型的操作日志数据增加默认值,统一都是空字符串,展示历史数据时,显示unknown


![image](https://github.com/PKUHPC/SCOW/assets/130351655/72f5c63d-47fa-49d1-a2f6-261fad8fef6e)


![image](https://github.com/PKUHPC/SCOW/assets/130351655/a7c1459b-977d-42d5-8960-ff75cc54ba16)
  • Loading branch information
ZihanChen821 authored Feb 27, 2024
1 parent 16f4465 commit d3d891a
Show file tree
Hide file tree
Showing 19 changed files with 244 additions and 47 deletions.
5 changes: 5 additions & 0 deletions .changeset/lovely-kings-taste.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@scow/grpc-api": patch
---

门户系统部分操作类型增加 clusterId 及 loginNode 参数
7 changes: 7 additions & 0 deletions .changeset/wet-teachers-fetch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@scow/audit-server": patch
"@scow/portal-web": patch
"@scow/mis-web": patch
---

操作日志详细内容展示优化
97 changes: 97 additions & 0 deletions apps/audit-server/src/migrations/Migration20240218000000.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { Migration } from "@mikro-orm/migrations";

export class Migration20240129000000 extends Migration {

async up(): Promise<void> {
this.addSql(`
UPDATE operation_log
SET meta_data = JSON_SET(meta_data, '$.submitJob.clusterId', '')
WHERE JSON_UNQUOTE(JSON_EXTRACT(meta_data, '$.$case')) = 'submitJob';
`);
this.addSql(`
UPDATE operation_log
SET meta_data = JSON_SET(meta_data, '$.endJob.clusterId', '')
WHERE JSON_UNQUOTE(JSON_EXTRACT(meta_data, '$.$case')) = 'endJob';
`);
this.addSql(`
UPDATE operation_log
SET meta_data = JSON_SET(meta_data, '$.addJobTemplate.clusterId', '')
WHERE JSON_UNQUOTE(JSON_EXTRACT(meta_data, '$.$case')) = 'addJobTemplate';
`);
this.addSql(`
UPDATE operation_log
SET meta_data = JSON_SET(meta_data, '$.deleteJobTemplate.clusterId', '')
WHERE JSON_UNQUOTE(JSON_EXTRACT(meta_data, '$.$case')) = 'deleteJobTemplate';
`);
this.addSql(`
UPDATE operation_log
SET meta_data = JSON_SET(meta_data, '$.updateJobTemplate.clusterId', '')
WHERE JSON_UNQUOTE(JSON_EXTRACT(meta_data, '$.$case')) = 'updateJobTemplate';
`);
this.addSql(`
UPDATE operation_log
SET meta_data = JSON_SET(meta_data, '$.createDesktop.clusterId', '', '$.createDesktop.loginNode', '')
WHERE JSON_UNQUOTE(JSON_EXTRACT(meta_data, '$.$case')) = 'createDesktop';
`);
this.addSql(`
UPDATE operation_log
SET meta_data = JSON_SET(meta_data, '$.deleteDesktop.clusterId', '')
WHERE JSON_UNQUOTE(JSON_EXTRACT(meta_data, '$.$case')) = 'deleteDesktop';
`);
this.addSql(`
UPDATE operation_log
SET meta_data = JSON_SET(meta_data, '$.createApp.clusterId', '')
WHERE JSON_UNQUOTE(JSON_EXTRACT(meta_data, '$.$case')) = 'createApp';
`);
this.addSql(`
UPDATE operation_log
SET meta_data = JSON_SET(meta_data, '$.setJobTimeLimit.clusterId', '')
WHERE JSON_UNQUOTE(JSON_EXTRACT(meta_data, '$.$case')) = 'setJobTimeLimit';
`);
}

async down(): Promise<void> {
this.addSql(`
UPDATE operation_log
SET meta_data = JSON_REMOVE(meta_data, '$.submitJob.clusterId')
WHERE JSON_UNQUOTE(JSON_EXTRACT(meta_data, '$.$case')) = 'submitJob' AND JSON_CONTAINS_PATH(meta_data, 'one', '$.submitJob.clusterId');
`);
this.addSql(`
UPDATE operation_log
SET meta_data = JSON_REMOVE(meta_data, '$.endJob.clusterId')
WHERE JSON_UNQUOTE(JSON_EXTRACT(meta_data, '$.$case')) = 'endJob' AND JSON_CONTAINS_PATH(meta_data, 'one', '$.endJob.clusterId');
`);
this.addSql(`
UPDATE operation_log
SET meta_data = JSON_REMOVE(meta_data, '$.addJobTemplate.clusterId')
WHERE JSON_UNQUOTE(JSON_EXTRACT(meta_data, '$.$case')) = 'addJobTemplate' AND JSON_CONTAINS_PATH(meta_data, 'one', '$.addJobTemplate.clusterId');
`);
this.addSql(`
UPDATE operation_log
SET meta_data = JSON_REMOVE(meta_data, '$.deleteJobTemplate.clusterId')
WHERE JSON_UNQUOTE(JSON_EXTRACT(meta_data, '$.$case')) = 'deleteJobTemplate' AND JSON_CONTAINS_PATH(meta_data, 'one', '$.deleteJobTemplate.clusterId');
`);
this.addSql(`
UPDATE operation_log
SET meta_data = JSON_REMOVE(meta_data, '$.updateJobTemplate.clusterId')
WHERE JSON_UNQUOTE(JSON_EXTRACT(meta_data, '$.$case')) = 'updateJobTemplate' AND JSON_CONTAINS_PATH(meta_data, 'one', '$.updateJobTemplate.clusterId');
`);
this.addSql(`
UPDATE operation_log
SET meta_data = JSON_REMOVE(meta_data,'$.createDesktop.clusterId','$.createDesktop.loginNode')
WHERE JSON_UNQUOTE(JSON_EXTRACT(meta_data, '$.$case')) = 'createDesktop'
AND JSON_CONTAINS_PATH(meta_data, 'one', '$.createDesktop.clusterId')
AND JSON_CONTAINS_PATH(meta_data, 'one', '$.createDesktop.loginNode');
`);
this.addSql(`
UPDATE operation_log
SET meta_data = JSON_REMOVE(meta_data, '$.createApp.clusterId')
WHERE JSON_UNQUOTE(JSON_EXTRACT(meta_data, '$.$case')) = 'createApp' AND JSON_CONTAINS_PATH(meta_data, 'one', '$.createApp.clusterId');
`);
this.addSql(`
UPDATE operation_log
SET meta_data = JSON_REMOVE(meta_data, '$.setJobTimeLimit.clusterId')
WHERE JSON_UNQUOTE(JSON_EXTRACT(meta_data, '$.$case')) = 'setJobTimeLimit' AND JSON_CONTAINS_PATH(meta_data, 'one', '$.setJobTimeLimit.clusterId');
`);
}
}
7 changes: 6 additions & 1 deletion apps/audit-server/tests/log/operationLogs.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ const operationLog = {
operatorUserId: "testUserId",
operatorIp: "127.0.0.1",
operationResult: OperationResult.SUCCESS,
operationEvent: { "$case": "submitJob" as const, submitJob: { accountName: "testAccount", jobId: 123 } },
operationEvent: { "$case": "submitJob" as const, submitJob: {
accountName: "testAccount",
jobId: 123,
clusterId: "test" } },
};

const operationLog1 = new OperationLog({
Expand All @@ -51,6 +54,7 @@ const operationLog2 = new OperationLog({
metaData: {
$case: "endJob", endJob: {
jobId:123,
clusterId: "test",
},
},
});
Expand Down Expand Up @@ -249,6 +253,7 @@ it("get operation logs", async () => {
operationEvent: {
$case: "endJob", endJob: {
jobId:123,
clusterId: "test",
},
},
},
Expand Down
12 changes: 9 additions & 3 deletions apps/audit-server/tests/statistic/statistic.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ const operationLog = {
operatorUserId: "testUserId",
operatorIp: "127.0.0.1",
operationResult: OperationResult.SUCCESS,
operationEvent: { "$case": "submitJob" as const, submitJob: { accountName: "testAccount", jobId: 123 } },
operationEvent: { "$case": "submitJob" as const, submitJob: {
accountName: "testAccount", jobId: 123, clusterId: "test",
} },
};

beforeEach(async () => {
Expand Down Expand Up @@ -89,15 +91,19 @@ it("get portal usage count correctly", async () => {
operatorIp: operationLog.operatorIp,
operationResult: operationLog.operationResult,
operationTime: new Date(),
metaData: { "$case": "submitJob" as const, submitJob: { accountName: "testAccount", jobId: 123 } },
metaData: { "$case": "submitJob" as const, submitJob: {
accountName: "testAccount",
jobId: 123,
clusterId: "test",
} },
}));

const endJobLogs = Array.from({ length: 20 }, () => new OperationLog({
operatorUserId: operationLog.operatorUserId,
operatorIp: operationLog.operatorIp,
operationResult: operationLog.operationResult,
operationTime: new Date(),
metaData: { "$case": "endJob" as const, endJob: { jobId: 123 } },
metaData: { "$case": "endJob" as const, endJob: { jobId: 123, clusterId: "test" } },
}));

const shellLoginLogs = Array.from({ length: 30 }, () => new OperationLog({
Expand Down
19 changes: 17 additions & 2 deletions apps/mis-web/src/components/OperationLogTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ import {
import { ExportFileModaLButton } from "src/pageComponents/common/exportFileModal";
import { MAX_EXPORT_COUNT, urlToExport } from "src/pageComponents/file/apis";
import { User } from "src/stores/UserStore";
import { styled } from "styled-components";

const WordBreakText = styled.div`
word-wrap: break-word;
word-break: break-all;`;

interface FilterForm {
operatorUserId?: string;
Expand Down Expand Up @@ -203,7 +208,7 @@ export const OperationLogTable: React.FC<Props> = ({ user, queryType, accountNam
<Input style={{ width: 150 }} />
</Form.Item>
)}
<Form.Item label="操作内容" name="operationDetail">
<Form.Item label={t(p("operationDetail"))} name="operationDetail">
<Input style={{ width: 150 }} />
</Form.Item>
<Form.Item label={t(p("operationTime"))} name="operationTime">
Expand Down Expand Up @@ -247,6 +252,10 @@ export const OperationLogTable: React.FC<Props> = ({ user, queryType, accountNam
<Table.Column
dataIndex="operationDetail"
title={t(p("operationDetail"))}
width="30%"
render={(operationDetail) => (
<WordBreakText>{operationDetail}</WordBreakText>
)}
/>
<Table.Column<OperationLog>
dataIndex="operationResult"
Expand All @@ -263,7 +272,13 @@ export const OperationLogTable: React.FC<Props> = ({ user, queryType, accountNam
title={t(p("operatorUserId"))}
render={(_, r) => (`${r.operatorUserId} (${r.operatorUserName})`)}
/>
<Table.Column<OperationLog> dataIndex="operatorIp" title={t(p("operatorIp"))} />
<Table.Column<OperationLog>
dataIndex="operatorIp"
title={t(p("operatorIp"))}
render={(operatorIp) => (
<WordBreakText>{operatorIp}</WordBreakText>
)}
/>
</Table>
</div>
);
Expand Down
18 changes: 9 additions & 9 deletions apps/mis-web/src/i18n/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1079,23 +1079,23 @@ export default {
operationDetails: {
login: "User Login",
logout: "User Logout",
submitJob: "Job Submission under account {} (ID: {})",
endJob: "Terminate Job (ID: {})",
addJobTemplate: "Save Job Template (Template name: {})",
deleteJobTemplate: "Delete Job Template (Template name: {})",
updateJobTemplate: "Update Job Template (Old template name: {}, New template name: {})",
submitJob: "Job Submission(Cluster: {}, ID: {})",
endJob: "Terminate Job (Cluster: {}, ID: {})",
addJobTemplate: "Save Job Template (Cluster: {}, Template name: {})",
deleteJobTemplate: "Delete Job Template (Cluster: {}, Template name: {})",
updateJobTemplate: "Update Job Template (Cluster: {}, Old template name: {}, New template name: {})",
shellLogin: "Login to {} cluster's {} node",
createDesktop: "Create Desktop (Desktop name: {}, Desktop type: {})",
deleteDesktop: "Delete Desktop (Desktop ID: {}:{})",
createApp: "Create application under account {} (ID: {})",
createDesktop: "Create Desktop (Cluster: {}, Login Node: {}, Desktop name: {}, Desktop type: {})",
deleteDesktop: "Delete Desktop (Cluster: {}, Login Node: {}, Desktop ID: {})",
createApp: "Create application (Cluster: {}, ID: {})",
createFile: "Create File: {}",
deleteFile: "Delete File: {}",
uploadFile: "Upload File: {}",
createDirectory: "Create Directory: {}",
deleteDirectory: "Delete Directory: {}",
moveFileItem: "Move File/Folder: {} to {}",
copyFileItem: "Copy File/Folder: {} to {}",
setJobTimeLimit: "Set time limit for job (ID: {}) to {} minutes",
setJobTimeLimit: "Set time limit for job (Cluster: {}, ID: {}) to {} minutes",
createUser: "Create User {}",
addUserToAccount: "Add user {} to account {}",
removeUserFromAccount: "Remove user {} from account {}",
Expand Down
18 changes: 9 additions & 9 deletions apps/mis-web/src/i18n/zh_cn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1080,23 +1080,23 @@ export default {
operationDetails: {
login: "用户登录",
logout: "用户退出登录",
submitJob: "在账户{}下提交作业(ID: {})",
endJob: "结束作业(ID: {})",
addJobTemplate: "保存作业模板(模板名: {})",
deleteJobTemplate: "删除作业模板(模板名:{})",
updateJobTemplate: "更新作业模板(旧模板名:{},新模板名:{})",
submitJob: "提交作业(集群:{}, ID: {})",
endJob: "结束作业(集群:{}, ID: {})",
addJobTemplate: "保存作业模板(集群:{}, 模板名: {})",
deleteJobTemplate: "删除作业模板(集群:{}, 模板名:{})",
updateJobTemplate: "更新作业模板(集群:{}, 旧模板名:{},新模板名:{})",
shellLogin: "登录{}集群的{}节点",
createDesktop: "新建桌面(桌面名:{}, 桌面类型: {})",
deleteDesktop: "删除桌面(桌面ID: {}:{})",
createApp: "在账户{}下创建应用(ID: {})",
createDesktop: "新建桌面(集群:{}, 登陆节点: {}, 桌面名:{}, 桌面类型: {})",
deleteDesktop: "删除桌面(集群:{}, 登陆节点: {}, 桌面ID: {})",
createApp: "创建应用(集群:{}, ID: {})",
createFile: "新建文件:{}",
deleteFile: "删除文件:{}",
uploadFile: "上传文件:{}",
createDirectory: "新建文件夹:{}",
deleteDirectory: "删除文件夹:{}",
moveFileItem: "移动文件/文件夹:{}至{}",
copyFileItem: "复制文件/文件夹:{}至{}",
setJobTimeLimit: "设置作业(ID: {})时限 {} 分钟",
setJobTimeLimit: "设置作业(集群:{}, ID: {})时限 {} 分钟",
createUser: "创建用户{}",
addUserToAccount: "将用户{}添加到账户{}中",
removeUserFromAccount: "将用户{}从账户{}中移除",
Expand Down
46 changes: 32 additions & 14 deletions apps/mis-web/src/models/operationLog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -259,25 +259,42 @@ export const getOperationDetail = (
case "logout":
return t(pDetails("logout"));
case "submitJob":
return t(pDetails("submitJob"), [operationEvent[logEvent].accountName, operationEvent[logEvent].jobId]);
return t(pDetails("submitJob"), [operationEvent[logEvent].clusterId || "unknown",
operationEvent[logEvent].jobId || "-"]);
case "endJob":
return t(pDetails("endJob"), [operationEvent[logEvent].jobId]);
return t(pDetails("endJob"), [operationEvent[logEvent].clusterId || "unknown",
operationEvent[logEvent].jobId || "-"]);
case "addJobTemplate":
return t(pDetails("addJobTemplate"), [operationEvent[logEvent].jobTemplateId]);
return t(pDetails("addJobTemplate"), [operationEvent[logEvent].clusterId || "unknown",
operationEvent[logEvent].jobTemplateId]);
case "deleteJobTemplate":
return t(pDetails("deleteJobTemplate"), [operationEvent[logEvent].jobTemplateId]);
return t(pDetails("deleteJobTemplate"), [operationEvent[logEvent].clusterId || "unknown",
operationEvent[logEvent].jobTemplateId]);
case "updateJobTemplate":
return t(pDetails("updateJobTemplate"),
[operationEvent[logEvent].jobTemplateId, operationEvent[logEvent].newJobTemplateId]);
[
operationEvent[logEvent].clusterId || "unknown",
operationEvent[logEvent].jobTemplateId,
operationEvent[logEvent].newJobTemplateId,
]);
case "shellLogin":
return t(pDetails("shellLogin"), [operationEvent[logEvent].clusterId, operationEvent[logEvent].loginNode]);
case "createDesktop":
return t(pDetails("createDesktop"), [operationEvent[logEvent].desktopName, operationEvent[logEvent].wm]);
return t(pDetails("createDesktop"), [
operationEvent[logEvent].clusterId || "unknown",
operationEvent[logEvent].loginNode || "unknown",
operationEvent[logEvent].desktopName,
operationEvent[logEvent].wm,
]);
case "deleteDesktop":
return t(pDetails("deleteDesktop"),
[operationEvent[logEvent].loginNode, operationEvent[logEvent].desktopId]);
[
operationEvent[logEvent].clusterId || "unknown",
operationEvent[logEvent].loginNode,
operationEvent[logEvent].desktopId,
]);
case "createApp":
return t(pDetails("createApp"), [operationEvent[logEvent].accountName, operationEvent[logEvent].jobId]);
return t(pDetails("createApp"), [operationEvent[logEvent].clusterId, operationEvent[logEvent].jobId || "-"]);
case "createFile":
return t(pDetails("createFile"), [operationEvent[logEvent].path]);
case "deleteFile":
Expand All @@ -294,7 +311,8 @@ export const getOperationDetail = (
return t(pDetails("copyFileItem"), [operationEvent[logEvent].fromPath, operationEvent[logEvent].toPath]);
case "setJobTimeLimit":
return t(pDetails("setJobTimeLimit"),
[operationEvent[logEvent].jobId, Math.abs(operationEvent[logEvent].limitMinutes)]);
[operationEvent[logEvent].clusterId || "unknown",
operationEvent[logEvent].jobId, Math.abs(operationEvent[logEvent].limitMinutes)]);
case "createUser":
return t(pDetails("createUser"), [operationEvent[logEvent].userId]);
case "addUserToAccount":
Expand Down Expand Up @@ -358,11 +376,11 @@ export const getOperationDetail = (
return t(pDetails("unblockAccount"),
[operationEvent[logEvent].tenantName, operationEvent[logEvent].accountName]);
case "importUsers":
return `${t(pDetails("importUsers1"), [operationEvent[logEvent].tenantName])}${
operationEvent[logEvent].importAccounts.map(
(account: { accountName: string; userIds: string[];}) =>
(tArgs(pDetails("importUsers2"), [account.accountName, account.userIds.join("、")])),
).join(", ")}`;
return `${t(pDetails("importUsers1"),
[operationEvent[logEvent].tenantName])}${operationEvent[logEvent].importAccounts.map(
(account: { accountName: string; userIds: string[]; }) =>
(tArgs(pDetails("importUsers2"), [account.accountName, account.userIds.join("、")])),
).join(", ")}`;
case "setPlatformAdmin":
return t(pDetails("setPlatformAdmin"), [operationEvent[logEvent].userId]);
case "unsetPlatformAdmin":
Expand Down
2 changes: 1 addition & 1 deletion apps/mis-web/src/pages/api/job/cancelJob.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export default /* #__PURE__*/route(CancelJobSchema, async (req, res) => {
operatorIp: parseIp(req) ?? "",
operationTypeName: OperationType.endJob,
operationTypePayload: {
jobId: +jobId, accountName: job.account,
jobId: +jobId, accountName: job.account, clusterId: cluster,
},
};

Expand Down
2 changes: 1 addition & 1 deletion apps/mis-web/src/pages/api/job/changeJobTimeLimit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ export default typeboxRoute(ChangeJobTimeLimitSchema,
operatorIp: parseIp(req) ?? "",
operationTypeName: OperationType.setJobTimeLimit,
operationTypePayload:{
jobId: +jobId, accountName: job.account, limitMinutes,
jobId: +jobId, accountName: job.account, limitMinutes, clusterId: cluster,
},
};

Expand Down
4 changes: 2 additions & 2 deletions apps/portal-web/src/pages/api/app/createAppSession.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export default /* #__PURE__*/route(CreateAppSessionSchema, async (req, res) => {
operatorIp: parseIp(req) ?? "",
operationTypeName: OperationType.createApp,
operationTypePayload:{
accountName: account,
accountName: account, clusterId: cluster,
},
};

Expand Down Expand Up @@ -118,7 +118,7 @@ export default /* #__PURE__*/route(CreateAppSessionSchema, async (req, res) => {
}).catch(async (e) => {
await callLog({
...logInfo,
operationTypePayload: { ... logInfo.operationTypePayload, jobId: -1 },
operationTypePayload: { ... logInfo.operationTypePayload },
}, OperationResult.FAIL);
const ex = e as ServiceError;
const errors = parseErrorDetails(ex.metadata);
Expand Down
Loading

0 comments on commit d3d891a

Please sign in to comment.