运维服务中台
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

300 lines
8.4 KiB

'use strict';
const moment = require('moment')
async function groupList (ctx) {
try {
const { models } = ctx.fs.dc;
const { userId } = ctx.fs.api
const res = await models.ProjectGroup.findAll({
where: {
pomsUserId: userId
},
order: [['id', 'DESC']]
})
ctx.status = 200;
ctx.body = res
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : undefined
}
}
}
async function editGroup (ctx) {
try {
const { models } = ctx.fs.dc;
const { userId } = ctx.fs.api
const { id, name, pomsProjectIds = [] } = ctx.request.body
if (!name || !pomsProjectIds || !pomsProjectIds.length) {
throw '参数错误!'
}
let repeatNameRes = await models.ProjectGroup.findOne({
where: {
pomsUserId: userId,
name,
}
})
let repeatProjectRes = await models.ProjectGroup.findOne({
where: {
pomsUserId: userId,
pomsProjectIds
}
})
if (repeatNameRes && (!id || (id && repeatNameRes.id != id))) {
throw '已有相同名称的分组信息!'
}
if (repeatProjectRes && (!id || (id && repeatProjectRes.id != id))) {
throw '已有相同项目的分组信息!'
}
if (id) {
await models.ProjectGroup.update({
name,
pomsProjectIds,
}, {
where: {
id
}
})
} else {
await models.ProjectGroup.create({
name,
pomsProjectIds,
pomsUserId: userId,
}, {
where: {
id
}
})
}
ctx.status = 204;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : undefined
}
}
}
async function delGroup (ctx) {
try {
const { models } = ctx.fs.dc;
await models.ProjectGroup.destroy({
where: {
id: ctx.query.groupId
}
})
ctx.status = 204;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : undefined
}
}
}
async function groupStatistic (ctx) {
try {
const { models } = ctx.fs.dc;
const { userId } = ctx.fs.api
const { clickHouse } = ctx.app.fs
const sequelize = ctx.fs.dc.orm
1 year ago
const progectGroupList = await models.ProjectGroup.findAll({
where: {
pomsUserId: userId
}
})
// 获取全部的 poms 项目id 并构建关系
let pomsProjectIds = new Set()
for (let group of progectGroupList) {
for (let projectId of group.pomsProjectIds) {
pomsProjectIds.add(projectId)
}
}
let pomsProjectIdArr = Array.from(pomsProjectIds)
const groupProjectRes = await models.ProjectCorrelation.findAll({
where: {
id: { $in: pomsProjectIdArr }
}
})
// 获取所有的 安心云项目id
let anxinProjectIds = new Set()
for (let project of groupProjectRes) {
for (let projectId of project.anxinProjectId) {
anxinProjectIds.add(projectId)
}
}
let anxinProjectIdArr = Array.from(anxinProjectIds)
// 统计安心云项目下的结构物id
const strucIdRes = await clickHouse.anxinyun.query(
`
SELECT *
FROM t_project_structure
WHERE project IN (${[...anxinProjectIdArr].join(',')}, -1)
`
).toPromise()
let strucIds = new Set()
for (let struc of strucIdRes) {
strucIds.add(struc.structure)
}
let strucIdArr = Array.from(strucIds)
const deviceOffTimeRes = strucIdArr.length ? await models.StructureOff.findAll({
where: {
structure: { $in: strucIdArr }
}
}) : []
let rslt = []
for (let pg of progectGroupList) {
let strucCount = 0
let maxOffLineTime = 0
let anxinProjectCount = groupProjectRes.reduce((count, gp) => {
if (pg.pomsProjectIds.some(id => gp.id == id)) {
// 如果 pg 分组信息 存储的 pomsProjectIds 运维项目id 和 真正的 groupProjectRes 运维项目id 相等
// gp.anxinProjectId 就是对应的 安心云的项目 id 集
count += gp.anxinProjectId.length
//
let strucIdArr_ =
strucIdRes.filter(s => gp.anxinProjectId.includes(s.project))
strucCount += strucIdArr_.length
//
for (let { dataValues: off } of deviceOffTimeRes) {
if (strucIdArr_.some((s) => s.structure == off.structure)) {
if (off.offline > maxOffLineTime) {
maxOffLineTime = off.offline
}
}
}
}
return count
}, 0)
rslt.unshift({
...pg.dataValues,
strucCount,
maxOffLineTime,
anxinProjectCount,
})
}
ctx.status = 200;
ctx.body = rslt
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: error`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : undefined
}
}
}
async function groupStatisticOnline (ctx) {
try {
const { models } = ctx.fs.dc;
const { userId } = ctx.fs.api
const { groupId } = ctx.query
const sequelize = ctx.fs.dc.orm
const { clickHouse } = ctx.app.fs
const pomsProjectRes = await sequelize.query(`
SELECT project_correlation.anxin_project_id
FROM project_group
JOIN project_correlation
ON project_correlation.id = ANY(project_group.poms_project_ids)
WHERE project_group.id = ${groupId};
`)
const anxinProjectIds = new Set()
for (let pomsProject of (pomsProjectRes[0] || [])) {
for (let pid of pomsProject.anxin_project_id)
anxinProjectIds.add(pid)
}
const strucIdRes = await clickHouse.anxinyun.query(
`
SELECT *
FROM t_project_structure
WHERE project IN (${[...anxinProjectIds].join(',')}, -1)
`
).toPromise()
let strucIds = new Set()
for (let struc of strucIdRes) {
strucIds.add(struc.structure)
}
let strucIdArr = Array.from(strucIds)
const strucRes = strucIdArr.length ? await clickHouse.anxinyun.query(
`
SELECT * FROM t_structure WHERE id IN (${[...strucIdArr].join(',')});
`
).toPromise() : []
const strucOnlineClient = ctx.app.fs.esclient.strucOnline
const onlineRes = await strucOnlineClient.search({
index: strucOnlineClient.config.index,
type: strucOnlineClient.config.type,
body: {
"query": {
"bool": {
"filter": [
{
"range": {
"collect_time": {
"gte": `${moment().subtract(24, 'hours').format('YYYY-MM-DDTHH:mm:ss.SSS')}Z`,
"gte": "2023-08-24T08:00:00.000Z",
}
}
},
{
"terms": {
"structure": strucIdArr,
"structure": [1, 2, 3]
}
}
]
}
},
"sort": [
{
"collect_time": {
"order": "asc"
}
}
]
}
})
ctx.status = 200;
ctx.body = onlineRes.hits.hits;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: error`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : undefined
}
}
}
module.exports = {
groupList,
editGroup,
delGroup,
groupStatistic,
groupStatisticOnline,
};