运维服务中台
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.
 
 
 
 
 

491 lines
17 KiB

'use strict';
const moment = require('moment');
async function dataList (ctx) {
try {
const { models } = ctx.fs.dc;
const { userId, pepUserId, userInfo = {}, pepUserInfo } = ctx.fs.api
const { clickHouse } = ctx.app.fs
const { utils: { judgeSuper, anxinStrucIdRange, pomsProjectRange } } = ctx.app.fs
const { database: anxinyun } = clickHouse.anxinyun.opts.config
const { pepProjectId } = ctx.request.query
let anxinStruc = await anxinStrucIdRange({
ctx, pepProjectId
})
let pomsProject = await pomsProjectRange({
ctx, pepProjectId,
})
const pomsProjectIds = pomsProject.map(p => p.id)
if (anxinStruc.length) {
const anxinStrucIds = anxinStruc.map(a => a.strucId) || []
const dataAlarm = await clickHouse.dataAlarm.query(`
SELECT
formatDateTime(alarmData.StartTime,'%F %H') hours, count(AlarmId) count
FROM
( SELECT
AlarmId,State,StartTime
FROM
alarms
WHERE
alarms.StructureId IN (${anxinStrucIds.join(",")})
AND
AlarmGroup = 3) AS alarmData
GROUP BY hours
`).toPromise();
// const confirmedAlarm = dataAlarm
// // TODO: 开发临时注释
// .filter(ar => ar.State && ar.State > 2)
// .map(ar => "'" + ar.AlarmId + "'")
// // formatDateTime(Time,'%F %H') hours, count(AlarmId) count
// const dataConfirme = confirmedAlarm.length ?
// await clickHouse.dataAlarm.query(`
// SELECT
// max(Time) AS Time, AlarmId
// FROM
// alarm_details
// WHERE
// AlarmId IN (${confirmedAlarm.join(',')})
// GROUP BY AlarmId
// `).toPromise() :
// [];
// dataAlarm.forEach(ar => {
// ar.confirme =
// dataConfirme.find(as => as.AlarmId == ar.AlarmId) || {}
// })
ctx.status = 200
ctx.body = dataAlarm
} else {
ctx.status = 200
ctx.body = {
dataAlarm: 0,
}
}
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : undefined
}
}
}
async function personnelApp (ctx) {
try {
const models = ctx.fs.dc.models;
const { clickHouse } = ctx.app.fs
const sequelize = ctx.fs.dc.orm;
const { userId, pepUserId, userInfo, pepUserInfo } = ctx.fs.api
const { pepId } = ctx.query
const excludeField = ['lastInTime', 'inTimes', 'onlineDuration', 'lastInAddress', 'deleted', 'updateTime']
let findOption = {
attributes: {
exclude: excludeField,
// include: [[sequelize.fn('array_length', sequelize.col('role')), 'roleCount']]
},
where: {
deleted: false,
$or: [{
$not: {
role: { $contained: ['SuperAdmin', 'admin'] }
}
},
sequelize.where(sequelize.fn('cardinality', sequelize.col('role')), 0)],
// $not: {
// role: { $contained: ['SuperAdmin', 'admin'] }
// }
},
order: [['updateTime', 'DESC']]
}
const userRes = await models.User.findAndCountAll(findOption)
const adminRes = await models.User.findAll({
where: {
role: { $contains: ['admin'] }
},
attributes: {
exclude: excludeField,
},
order: [['updateTime', 'DESC']]
})
let userIds = new Set()
let pomsProjectIds = new Set()
for (let u of userRes.rows.concat(adminRes)) {
userIds.add(u.pepUserId)
for (let pid of u.correlationProject) {
pomsProjectIds.add(pid)
}
}
// 查用户所属的项企pep的部门、人员信息
let userPepRes = userIds.size ?
await clickHouse.pepEmis.query(`
SELECT DISTINCT
user.id AS id, "user"."name" AS name, department.name AS depName, department.id AS depId
FROM department_user
LEFT JOIN user
ON department_user.user=user.id
LEFT JOIN department
ON department.id=department_user.department
WHERE
user.id IN (${[...userIds].join(',')})
AND department.delete=false`
).toPromise() :
[]
// 查用户绑定的当前系统的项目 id
let pomsProjectRes = await models.ProjectCorrelation.findAll({
where: {
id: { $in: [...pomsProjectIds] },
// del: false
}
})
// 获取响应的绑定的 项企项目的 id
let pepPojectIds = new Set()
for (let p of pomsProjectRes) {
if (p.pepProjectId) {
pepPojectIds.add(p.pepProjectId)
}
}
// 查对应的项企项目信息
let pepProjectRes = pepPojectIds.size ?
await clickHouse.projectManage.query(`
SELECT id, project_name, isdelete FROM t_pim_project WHERE id IN (${[...pepPojectIds]})
`).toPromise() :
[]
// 遍历用户并将查到的信息拼合
for (let u of userRes.rows.concat(adminRes)) {
// 用户信息
const corUsers = userPepRes.filter(up => up.id == u.pepUserId)
u.dataValues.name = corUsers.length ? corUsers[0].name : ''
u.dataValues.departments = corUsers.length ? corUsers.map(cu => {
return {
name: cu.depName,
id: cu.depId
}
}) : []
// pep项目信息
u.dataValues.correlationProject = u.dataValues.correlationProject.map(cpid => {
let returnData = {
id: cpid,
}
const corPomsProject = pomsProjectRes.find(ppr => ppr.id == cpid)
if (corPomsProject) {
returnData.name = corPomsProject.name
returnData.del = corPomsProject.del
if (corPomsProject.pepProjectId) {
returnData.pepProjectId = corPomsProject.pepProjectId
const corPepProject = pepProjectRes.find(ppr => ppr.id == corPomsProject.pepProjectId)
if (corPepProject) {
returnData.pepProjectName = corPepProject.project_name
returnData.pepIsdelete = corPepProject.isdelete
}
}
}
return returnData
})
}
let findOptions = {
where: {
del: false
},
order: [['updateTime', 'desc']],
attributes: ['id', 'pepProjectId', 'name', 'anxinProjectId'],
distinct: true,
include: {
model: models.App,
}
}
if (!userInfo.role.includes('SuperAdmin') && !userInfo.role.includes('admin')) {
findOptions.where.id = { $in: userInfo.correlationProject }
}
if (pepId) {
findOption.where.id = pepId
}
const proRes = await models.ProjectCorrelation.findAndCountAll(findOptions)
let pepProjectIds = new Set()
let anxinProjectIds = new Set()
for (let p of proRes.rows) {
if (p.pepProjectId) {
pepProjectIds.add(p.pepProjectId)
}
for (let ap of p.anxinProjectId) {
if (ap) {
anxinProjectIds.add(ap)
}
}
}
const pepProjectRess = pepProjectIds.size ?
await clickHouse.projectManage.query(
`
SELECT
t_pim_project.id AS id,
t_pim_project.project_name AS project_name,
t_pim_project.isdelete AS isdelete,
t_pim_project_construction.construction_status_id AS construction_status_id,
t_pim_project_state.construction_status AS construction_status
FROM t_pim_project
LEFT JOIN t_pim_project_construction
ON t_pim_project.id = t_pim_project_construction.project_id
LEFT JOIN t_pim_project_state
ON t_pim_project_construction.construction_status_id = t_pim_project_state.id
WHERE id IN (${[...pepProjectIds].join(',')})
`
).toPromise() :
[]
for (let p of proRes.rows) {
const corPro = pepProjectRess.find(pp => pp.id == p.pepProjectId) || {}
p.dataValues.pepProjectName = corPro.project_name
p.dataValues.pepProjectIsDelete = corPro.isdelete
delete p.dataValues.anxinProjectId
}
let webApp = []
let appproRes = proRes.rows.filter(v => v.dataValues.pepProjectIsDelete != 1).map(r => {
if (r.dataValues.apps.length > 0) {
r.dataValues.apps.map(vv => {
if (webApp.map(n => n.name).indexOf(vv.dataValues.name)) {
webApp.push({ name: vv.dataValues.name, url: vv.dataValues.url })
}
})
}
})
let personnel = userRes.rows.filter(r => r.correlationProject.length > 0)
if (pepId) {
personnel = personnel.filter(r => r.dataValues.correlationProject.map(v => v.id).includes(Number(pepId)))
}
ctx.status = 200
ctx.body = {
personnel: personnel.map(v => v.dataValues.name),
webApp: webApp
}
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
}
}
}
async function problem (ctx) {
try {
const { models } = ctx.fs.dc;
const { clickHouse } = ctx.app.fs
const { utils: { pomsProjectRange, anxinStrucIdRange } } = ctx.app.fs
const { database: anxinyun } = clickHouse.anxinyun.opts.config
const { pepProjectId, limit = 50, page = 0 } = ctx.query
let anxinStruc = await anxinStrucIdRange({
ctx, pepProjectId
})
let pomsProject = await pomsProjectRange({
ctx, pepProjectId,
})
const pomsProjectIds = pomsProject.map(p => p.id)
let whereOption = []
if (anxinStruc.length) {
const anxinStrucIds = anxinStruc.map(a => a.strucId)
whereOption.push(`alarms.StructureId IN (${anxinStrucIds.join(",")})`)
const alarmRes = await clickHouse.dataAlarm.query(`
SELECT
AlarmId,State,AlarmGroup,AlarmGroupUnit,SourceName,StartTime,${anxinyun}.t_alarm_group_unit.name AS typeName
FROM alarms
LEFT JOIN ${anxinyun}.t_alarm_group_unit
ON ${anxinyun}.t_alarm_group_unit.id = alarms.AlarmGroupUnit
${whereOption.length ? 'WHERE ' + whereOption.join(' AND ') + ' AND ' + 'alarms.State < 3' : ''}
${limit ? 'LIMIT ' + limit : ''}
${limit && page ? 'OFFSET ' + parseInt(limit) * parseInt(page) : ''}
`).toPromise();
alarmRes.forEach(ar => {
switch (ar.AlarmGroup) {
case 1:
ar.groupName = '数据中断'
ar.url = '/problem/dataAlarm/dataLnterrupt'
break;
case 2:
ar.groupName = '数据异常'
ar.url = '/problem/dataAlarm/dataAbnormal'
break;
case 3:
ar.groupName = '策略命中'
ar.url = '/problem/dataAlarm/strategyHit'
break;
default:
ar.groupName = '设备异常'
ar.url = '/problem/deviceAlarm/deviceAbnormal'
break;
}
})
const video = anxinStrucIds.length ? await clickHouse.vcmp.query(
`
SELECT
cameraAlarm.cameraId AS cameraId,
cameraAlarm.cameraName AS cameraName,
cameraAlarm.alarmId AS alarmId,
cameraAlarm.createTime AS createTime,
cameraAlarm.confirmTime AS confirmTime
FROM
(
SELECT
camera.id AS cameraId,
camera.name AS cameraName,
camera_status_alarm.id AS alarmId,
camera_status_alarm.create_time AS createTime,
camera_status_alarm.platform AS platform,
camera_status_alarm.status_id AS statusId,
camera_status_alarm.serial_no AS cameraSerialNo,
camera_status_alarm.channel_no AS cameraChannelNo,
camera_status_alarm.confirm_time AS confirmTime
FROM camera_status_alarm
INNER JOIN camera
ON camera.serial_no = camera_status_alarm.serial_no
AND camera.channel_no = camera_status_alarm.channel_no
WHERE
camera.delete = false
AND camera.recycle_time is null
AND alarmId IN (
SELECT camera_status_alarm.id AS alarmId
FROM camera_status_alarm
RIGHT JOIN ${anxinyun}.t_video_ipc
ON toString(${anxinyun}.t_video_ipc.channel_no) = camera_status_alarm.channel_no
AND ${anxinyun}.t_video_ipc.serial_no = camera_status_alarm.serial_no
${`WHERE ${anxinyun}.t_video_ipc.structure IN (${anxinStrucIds.join(',')})`}
)
${limit ? 'LIMIT ' + limit : ''}
${limit && page ? 'OFFSET ' + parseInt(limit) * parseInt(page) : ''}
) AS cameraAlarm
LEFT JOIN camera_status
ON cameraAlarm.platform = camera_status.platform
AND cameraAlarm.statusId = camera_status.id
LEFT JOIN camera_status_resolve
ON camera_status_resolve.status_id = camera_status.id
LEFT JOIN ${anxinyun}.t_video_ipc AS anxinIpc
ON toString(anxinIpc.channel_no) = cameraAlarm.cameraChannelNo
AND anxinIpc.serial_no = cameraAlarm.cameraSerialNo
LEFT JOIN ${anxinyun}.t_video_ipc_station AS anxinIpcStation
ON anxinIpcStation.ipc = anxinIpc.id
WHERE
cameraAlarm.confirmTime is null
`
).toPromise() : []
let returnD = []
let positionD = {}
// 每个设备一个告警
for (let a of video) {
if (!positionD[a.cameraId]) {
let d = {
cameraId: a.cameraId,
SourceName: a.cameraName,
StartTime: a.createTime,
alarmId: a.alarmId,
}
returnD.push(d)
positionD[a.cameraId] = {
positionReturnD: returnD.length - 1
}
}
}
returnD.forEach(v => {
v.groupName = '视频异常'
v.url = '/problem/dataAlarm/videoAbnormal'
})
let findOption = {
where: {
'$app->projectCorrelations.id$': {
$in: pomsProjectIds
},
confirmTime: null
},
attributes: ['createTime', 'type'],
include: [{
model: models.App,
where: {
},
attributes: ['id', 'name'],
include: [{
model: models.ProjectCorrelation,
where: {
},
attributes: ['id'],
}]
}]
}
const listRes = await models.AppAlarm.findAndCountAll(findOption)
let app = listRes.rows.map(v => ({ StartTime: v.createTime, SourceName: v.app.name, type: v.type }))
let typeData = { element: '元素异常', apiError: "接口报错", timeout: '加载超时' }
app.forEach(v => {
v.groupName = '应用异常'
v.url = '/problem/useAlarm/useAbnormal',
v.typeName = typeData[v.type]
})
let sum = [...alarmRes, ...returnD, ...app]
sum.sort((a, b) => {
if (moment(a.StartTime).isBefore(b.StartTime)) {
return 1
} else {
return -1
}
})
ctx.status = 200;
ctx.body = sum
} else {
ctx.body =[]
}
ctx.status = 200;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`)
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : undefined
}
}
}
module.exports = {
dataList,
personnelApp,
problem
}