feat: 添加alertrule 新增条件 修改silence的mathers样式

This commit is contained in:
zhangyu
2021-05-07 21:27:47 +08:00
parent 99cd32b609
commit c89e5315e1
15 changed files with 181 additions and 76 deletions

View File

@@ -1,8 +1,8 @@
@font-face {
font-family: "nz-icon"; /* Project id 2030432 */
src: url('./font/iconfont.woff2?t=1620354698424') format('woff2'),
url('./font/iconfont.woff?t=1620354698424') format('woff'),
url('./font/iconfont.ttf?t=1620354698424') format('truetype');
src: url('./font/iconfont.woff2?t=1620386069576') format('woff2'),
url('./font/iconfont.woff?t=1620386069576') format('woff'),
url('./font/iconfont.ttf?t=1620386069576') format('truetype');
}
.nz-icon {
@@ -13,6 +13,10 @@
-moz-osx-font-smoothing: grayscale;
}
.nz-icon-circle:before {
content: "\e62f";
}
.nz-icon-guide:before {
content: "\e725";
}

View File

@@ -1112,7 +1112,7 @@ const cn = {
create: '创建告警静默',
edit: '修改告警静默',
time: '时间',
matcher: 'Matcher',
matchers: 'matchers',
reason: '描述',
selectTime: '请选择时间',
selectMather: '必填项',

View File

@@ -1074,7 +1074,7 @@ const en = {
rule: 'Rule', // '规则'
alertMessage: 'Alert message', // "告警信息"
alertRule: 'Alert rule', // "告警规则"
alertName: 'Alert name', // "告警名称"
alertName: 'Name', // "告警名称"
severity: 'Priority', // "等级"
description: 'Description', // "描述"
summary: 'Summary', // "概要"
@@ -1132,7 +1132,7 @@ const en = {
create: 'New alert silence',
edit: 'Edit alert silence',
time: 'Time',
matcher: 'Matcher',
matchers: 'matchers',
reason: 'Description',
selectTime: 'Please select time',
selectMather: 'Required',

View File

@@ -57,24 +57,16 @@
</el-input>
</el-form-item>
<!--severity-->
<el-form-item :label="$t('alert.severity')" prop="severity">
<el-select id="alert-box-input-severity" v-model="editAlertRule.severity" placeholder="" popper-class="config-dropdown" size="small">
<el-option v-for="item in $CONSTANTS.alertMessage.severityData" :id="'alert-severity-'+item.value" :key="item.value" :label="item.label" :value="item.value">
<template v-if="!item.isEdit">{{item.label}}</template>
<span v-if="item.isEdit" class="config-dropdown-label-input" @click.stop>
<el-input v-model="item.value" size="mini" type="text"></el-input>
<el-form-item :label="$t('alert.severity')" prop="severity" class="severity-box">
<el-select id="alert-box-input-severity" v-model="editAlertRule.severityId" placeholder="" popper-class="config-dropdown severity-box" size="small">
<el-option v-for="item in severityData" :id="'alert-severity-'+item.value" :key="item.id" :label="item.name" :value="item.id">
<span>
<i class="nz-icon nz-icon-circle" :style="{color:item.color,'font-size':'12px'}"></i> {{item.name}}
</span>
</el-option>
</el-select>
<i class="nz-icon nz-icon-circle severity-circle" v-if="editAlertRule.severityId" :style="{color:severityData.find(severity => severity.id === editAlertRule.severityId).color,'font-size':'12px'}"></i>
</el-form-item>
<div class="rule-severity-remark">
<i class="nz-icon nz-icon-info-normal"></i>
<div>
<p>{{$t('alert.P1Rule')}}</p>
<p>{{$t('alert.P2Rule')}}</p>
<p>{{$t('alert.P3Rule')}}</p>
</div>
</div>
<!--receiver-->
<el-form-item :label="$t('config.user.receiver')" prop="receiver">
<el-select
@@ -95,6 +87,13 @@
</el-option>
</el-select>
</el-form-item>
<!--notify-->
<el-form-item :label="$t('alert.notify')" prop="severity" class="notify-box">
<el-select id="alert-box-input-notify" v-model="editAlertRule.method" placeholder="" popper-class="config-dropdown notify-box" size="small" multiple>
<el-option v-for="item in notifyData" :id="'alert-severity-'+item.value" :key="item.id" :label="item.name" :value="item.id">
</el-option>
</el-select>
</el-form-item>
<!--summary-->
<el-form-item :label="$t('alert.summary')" prop="summary">
<el-input id="alert-box-input-summary" v-model="editAlertRule.summary" maxlength="512" placeholder="" rows="3" show-word-limit size="small" type="textarea"></el-input>
@@ -150,7 +149,7 @@ export default {
{ required: true, message: this.$t('validate.required'), trigger: 'blur' },
{ type: 'number', message: this.$t('validate.number') }
],
severity: [
severityId: [
{ required: true, message: this.$t('validate.required'), trigger: 'change' }
],
summary: [
@@ -195,7 +194,9 @@ export default {
],
unitOptions: chartDataFormat.unitOptions(),
userData: []
userData: [],
severityData: [],
notifyData: []
}
},
methods: {
@@ -210,11 +211,15 @@ export default {
if (this.prevent_opt.save) { return } ;
this.prevent_opt.save = true
this.editAlertRule.expr = this.expressions[0]
const params = {
...this.editAlertRule,
method: this.editAlertRule.method.join(',')
}
this.$refs.alertRuleForm.validate((valid) => {
if (valid) {
this.editAlertRule.receiver = this.editAlertRule.receiverShow.join(',')
if (this.editAlertRule.id) {
this.$put('alert/rule', this.editAlertRule).then(response => {
this.$put('alert/rule', params).then(response => {
this.prevent_opt.save = false
if (response.code === 200) {
this.$message({ duration: 1000, type: 'success', message: this.$t('tip.saveSuccess') })
@@ -224,7 +229,7 @@ export default {
}
})
} else {
this.$post('alert/rule', this.editAlertRule).then(response => {
this.$post('alert/rule', params).then(response => {
this.prevent_opt.save = false
if (response.code === 200) {
this.$message({ duration: 1000, type: 'success', message: this.$t('tip.saveSuccess') })
@@ -270,10 +275,26 @@ export default {
},
metricChange (val) {
this.editAlertRule.expr = val
},
getSeverityData () {
this.$get('alert/severity', { pageNo: 1, pageSize: -1 }).then(response => {
if (response.code == 200) {
this.severityData = response.data.list
}
})
},
getNotifyData () {
this.$get('alert/notify/method', { pageNo: 1, pageSize: -1 }).then(response => {
if (response.code == 200) {
this.notifyData = response.data.list
}
})
}
},
mounted () {
this.getUserList()
this.getSeverityData()
this.getNotifyData()
},
watch: {
alertRule: {
@@ -361,4 +382,15 @@ export default {
box-sizing: border-box;
margin: -13px 30px 18px 30px;
}
.severity-circle{
position: absolute;
left: 10px;
top: 0;
}
.severity-box{
position: relative;
}
.severity-box /deep/ .el-select .el-input__inner{
padding-left: 25px;
}
</style>

View File

@@ -61,20 +61,20 @@
</div>
</el-form-item>
<el-form-item :label='$t("alert.silence.matcher")' prop="matcher" class="matcher">
<div v-for="(item, index) in editAlertSilence.matcher" :key="index" class="param-box-row">
<el-form-item class="param-box-row-key" :rules="[{ required: true, message: $t('validate.required'), trigger: 'change' },]" :prop="'matcher.' + index + '.name'">
<el-form-item :label='$t("alert.silence.matchers")' prop="matchers" class="matchers">
<div v-for="(item, index) in editAlertSilence.matchers" :key="index" class="param-box-row">
<el-form-item class="param-box-row-key" :rules="[{ required: true, message: $t('validate.required'), trigger: 'change' },]" :prop="'matchers.' + index + '.name'">
<el-input placeholder="key" size="mini" v-model="item.name"></el-input>
</el-form-item>
<span class="param-box-row-eq">=</span>
<el-form-item class="param-box-row-value" :prop="'matcher.' + index + '.value'" :rules="[{ required: true, message: $t('validate.required'), trigger: 'change' },]" >
<el-input placeholder="value" size="mini" v-model="item.value" class="silence-matcher-value"></el-input>
<el-checkbox class="silence-matcher-regex" v-model="item.regex" :true-label="1" :false-label="0" >Regex</el-checkbox>
<el-form-item class="param-box-row-value" :prop="'matchers.' + index + '.value'" :rules="[{ required: true, message: $t('validate.required'), trigger: 'change' },]" >
<el-input placeholder="value" size="mini" v-model="item.value" class="silence-matchers-value"></el-input>
<el-checkbox class="silence-matchers-regex" v-model="item.regex" :true-label="1" :false-label="0" >Regex</el-checkbox>
</el-form-item>
<span class="param-box-row-symbol" :id="'moduel-remove-label-'+index" @click="removeMatcher(index)"><i class="nz-icon nz-icon-shanchu1" style="color:#666;"></i></span>
<span class="param-box-row-symbol" :id="'moduel-remove-label-'+index" @click="removematchers(index)"><i class="nz-icon nz-icon-shanchu1" style="color:#666;"></i></span>
</div>
<div style="text-align: center;" class="">
<span id="module-add-label" type="button" @click="addMatcher" class="right-box-form-add module-add-label right-box-form-minus-box module-add-label" style="">
<span id="module-add-label" type="button" @click="addmatchers" class="right-box-form-add module-add-label right-box-form-minus-box module-add-label" style="">
<span><i style="font-size: 16px;" class="nz-icon nz-icon-create-square"></i></span>
</span>
</div>
@@ -162,7 +162,7 @@ export default {
linkId: '',
reason: '',
time: [],
matcher: [
matchers: [
{ name: '', value: '', regex: 0 }
],
name: ''
@@ -223,7 +223,7 @@ export default {
})
return
}
const params = { ...this.editAlertSilence }
const params = { ...this.editAlertSilence, matchers: JSON.stringify(this.editAlertSilence.matchers) }
if (valid) {
if (this.editAlertSilence.id) {
this.$put('/alert/silence', params).then(response => {
@@ -308,15 +308,15 @@ export default {
this.editAlertSilence.linkId = ''
},
// 新增label
addMatcher () {
this.editAlertSilence.matcher.push({ name: '', value: '', regex: 0 })
addmatchers () {
this.editAlertSilence.matchers.push({ name: '', value: '', regex: 0 })
},
// 移除单个Label
removeMatcher (index) {
if (this.editAlertSilence.matcher.length === 1) {
this.editAlertSilence.matcher = [{ name: '', value: '', regex: 0 }]
removematchers (index) {
if (this.editAlertSilence.matchers.length === 1) {
this.editAlertSilence.matchers = [{ name: '', value: '', regex: 0 }]
}
this.editAlertSilence.matcher.splice(index, 1)
this.editAlertSilence.matchers.splice(index, 1)
}
}
}
@@ -358,7 +358,7 @@ export default {
}
}
}
.matcher{
.matchers{
/deep/ .el-input__prefix{
left: 0;
}
@@ -366,11 +366,11 @@ export default {
left: 126px;
padding-top: 10px;
}
.matcher-type{
.matchers-type{
display: flex;
justify-content: space-between;
margin-top: 20px;
.matcher-type-title{
.matchers-type-title{
width: 125px;
background:#E7EAED;
font-family: ArialMT;
@@ -380,7 +380,7 @@ export default {
font-weight: 400;
text-align: center;
}
/deep/ .matcher-type-title.el-select--small .el-input__inner{
/deep/ .matchers-type-title.el-select--small .el-input__inner{
background:#E7EAED;
font-family: ArialMT;
font-size: 14px;
@@ -390,15 +390,15 @@ export default {
text-align: center;
border: none;
}
.matcher-type-content{
.matchers-type-content{
flex: 1;
}
}
}
/deep/ .silence-matcher-value{
/deep/ .silence-matchers-value{
width: calc(100% - 100px);
}
.silence-matcher-regex{
.silence-matchers-regex{
margin-left: 10px;
}
/deep/ .param-box-row-key{

View File

@@ -57,10 +57,8 @@
<template v-if="scope.row[item.prop]">{{scope.row[item.prop]}}</template>
<span v-else>-</span>
</template>
<span v-else-if="item.prop === 'severity'" class="severity">
<span v-if="scope.row[item.prop] === 'P1'" class="P1">P1</span>
<span v-if="scope.row[item.prop] === 'P2'" class="P2">P2</span>
<span v-if="scope.row[item.prop] === 'P3'" class="P3">P3</span>
<span v-else-if="item.prop === 'severity'&&scope.row[item.prop]" class="severity">
<i class="nz-icon nz-icon-circle" :style="{color:scope.row[item.prop].color,'font-size':'12px','margin-right':'5px'}"></i> {{scope.row[item.prop].name}}
</span>
<span v-else-if="item.prop === 'startAt'">{{utcTimeToTimezoneStr(scope.row[item.prop])}}</span>
<template v-else-if="item.prop === 'duration'">

View File

@@ -34,17 +34,15 @@
<div class="col-resize-area"></div>
</template>
<template slot-scope="scope" :column="item">
<span v-if="item.prop === 'severity'" class="severity">
<span v-if="scope.row[item.prop] == 'P1'" class="P1">P1</span>
<span v-if="scope.row[item.prop] == 'P2'" class="P2">P2</span>
<span v-if="scope.row[item.prop] == 'P3'" class="P3">P3</span>
<span v-if="item.prop === 'severity'&&scope.row[item.prop]" class="severity">
<i class="nz-icon nz-icon-circle" :style="{color:scope.row[item.prop].color,'font-size':'12px','margin-right':'5px'}"></i> {{scope.row[item.prop].name}}
</span>
<template v-else-if="item.prop === 'alertNum'">
<span class="link" @click="queryMessage(scope.row)">{{scope.row.alertNum + ' ' + $t('overall.active')}}</span>
</template>
<template v-else-if="item.prop === 'threshold'">{{formatThreshold(scope.row[item.prop], scope.row.unit)}}</template>
<template v-else-if="item.prop === 'receivers'">
<el-tag v-for="(user, index) in scope.row[item.prop]" v-if="user.userName" :key="index" class="alert-rule-tag" effect="dark" size="mini">{{user.userName}}&nbsp;</el-tag>
<el-tag v-for="(user, index) in scope.row[item.prop]" v-if="user&&user.userName" :key="index" class="alert-rule-tag" effect="dark" size="mini">{{user.userName}}&nbsp;</el-tag>
</template>
<span v-else-if="scope.row[item.prop]">{{scope.row[item.prop]}}</span>
<template v-else>-</template>
@@ -85,12 +83,12 @@ export default {
prop: 'id',
show: true,
width: 80,
sortable:'custom'
sortable: 'custom'
}, {
label: this.$t('alert.alertName'),
prop: 'name',
show: true,
sortable:'custom'
sortable: 'custom'
}, {
label: this.$t('alert.config.expr'),
prop: 'expr',
@@ -111,7 +109,7 @@ export default {
label: this.$t('alert.severity'),
prop: 'severity',
show: true,
sortable:'custom'
sortable: 'custom'
}, {
label: this.$t('alert.summary'),
prop: 'summary',
@@ -124,8 +122,8 @@ export default {
label: this.$t('alert.message'),
prop: 'alertNum',
show: true,
width: 90,
sortable:'custom'
width: 150,
sortable: 'custom'
}, {
label: this.$t('alert.config.receiver'),
prop: 'receivers',

View File

@@ -54,7 +54,19 @@
<!-- <span :title="scope.row.ruleName" class="nz-silence-tag-content">{{scope.row.ruleName}}</span>-->
<!-- </span>-->
<!-- </div>-->
matchers
<span v-for="(item1, i) in labelsSort(scope.row.matchers)" :key="i">
<span >
<nz-alert-tag
v-if="item1.name !== 'alertname' && item1.name !== 'severity'" :key="i" :cursor-point="tagType(item1.name) !== 'info'"
:label="item1.name"
:type="tagType(item1.name)"
:regex="item1.regex"
style="margin: 5px 0 5px 5px;"
>
{{item1.value}}
</nz-alert-tag>
</span>
</span>
</template>
<template v-else-if="item.prop === 'state'">
<span v-if="scope.row.state===1" class="silence-pending">pending</span>
@@ -74,13 +86,13 @@
fixed="right">
<div slot="header" class="table-operation-title">{{$t('overall.option')}}</div>
<div slot-scope="scope" class="table-operation-items">
<button class="table-operation-item" @click="copyRow(scope.row,'alertSilence')"><i class="nz-icon nz-icon-override"></i></button>
<button class="table-operation-item" @click="$emit('edit', scope.row)"><i class="nz-icon nz-icon-edit"></i></button>
<el-dropdown size="medium" trigger="hover" @command="tableOperation">
<div class="table-operation-item table-operation-item--more">
<span></span><i class="nz-icon nz-icon-arrow-down"></i>
</div>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item :command="['edit', scope.row]"><i class="nz-icon nz-icon-edit"></i><span class="operation-dropdown-text">{{$t('overall.edit')}}</span></el-dropdown-item>
<!-- <el-dropdown-item :command="['edit', scope.row]"><i class="nz-icon nz-icon-edit"></i><span class="operation-dropdown-text">{{$t('overall.edit')}}</span></el-dropdown-item>-->
<el-dropdown-item :command="['delete', scope.row]"><i class="nz-icon nz-icon-delete"></i><span class="operation-dropdown-text">{{$t('buttons.expire')}}</span></el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
@@ -92,8 +104,12 @@
<script>
import table from '@/components/common/mixin/table'
import { calcDurationByStringTimeB } from '@/components/common/js/tools'
import nzAlertTag from '../../../page/alert/nzAlertTag'
export default {
name: 'alertSilenceTable',
components: {
nzAlertTag
},
mixins: [table],
data () {
return {
@@ -104,18 +120,18 @@ export default {
prop: 'id',
show: true,
width: 80,
sortable:'custom'
sortable: 'custom'
}, {
label: 'matchers',
prop: 'matchers',
show: true,
sortable:'custom'
sortable: 'custom'
}, {
label: 'Start time',
prop: 'startAt',
show: true,
width: 300,
sortable:'custom'
sortable: 'custom'
}, {
label: this.$t('config.terminallog.duration'),
prop: 'duration',
@@ -148,6 +164,39 @@ export default {
}
return calcDurationByStringTimeB(record.startAt, this.nowTime)
}
},
tagType () {
return (key) => {
if (key == 'asset' || key == 'module' || key == 'project' || key == 'datacenter' || key == 'endpoint') {
return 'normal'
} else {
return 'info'
}
}
}
},
methods: {
labelsSort (obj) {
obj = obj || []
const buildIn = ['asset', 'endpoint', 'module', 'project', 'datacenter']
if (typeof obj === 'string') obj = JSON.parse(obj)
const labels = JSON.parse(JSON.stringify(obj))
const result = []
const result2 = []
for (const key of buildIn) {
labels.forEach(item => {
if (item.name === key) {
result.push(item)
}
})
}
labels.forEach(item => {
if (buildIn.indexOf(item.name) === -1) {
result2.push(item)
}
})
console.log([...result, ...result2])
return [...result, ...result2]
}
}
}

View File

@@ -84,9 +84,10 @@ export default {
unit: 2,
operator: '>',
last: 60,
severity: 'P2',
severityId: '',
summary: '',
description: ''
description: '',
method: []
},
searchMsg: { // 给搜索框子组件传递的信息
zheze_none: true,
@@ -147,6 +148,17 @@ export default {
}
})
},
edit (u) {
this.$get(`${this.url}/${u.id}`).then(response => {
if (response.code === 200) {
this.object = {
...response.data,
method: response.data.method ? response.data.method.split(',').map(item => Number(item)) : []
}
this.rightBox.show = true
}
})
},
initEvent () {
bus.$on('alert-rule-list-change', () => {
this.getTableData()

View File

@@ -127,7 +127,7 @@ export default {
linkId: '',
reason: '',
time: [],
matcher: [
matchers: [
{ name: '', value: '', regex: 0 }
],
name: ''
@@ -172,7 +172,18 @@ export default {
this.blackObject.endAt = bus.timeFormate(bus.getOffsetTimezoneData(1), 'yyyy-MM-dd hh:mm:ss')
this.object = JSON.parse(JSON.stringify(this.blackObject))
this.rightBox.show = true
},
edit (u) {
this.$get(`${this.url}/${u.id}`).then(response => {
if (response.code === 200) {
this.object = {
...response.data,
matchers: JSON.parse(response.data.matchers)
}
this.rightBox.show = true
}
})
},
}
}
</script>

View File

@@ -1,7 +1,7 @@
<template>
<span class="nz-alert-tag" :class="['nz-alert-tag_' + type]" :style="{cursor: cursorPoint ? 'pointer' : 'default'}" @click="$emit('click')">
<span class="nz-alert-tag__label">{{label}}</span>
<span class="nz-alert-tag__content"><slot></slot></span>
<span class="nz-alert-tag__label"> {{label}}</span>
<span class="nz-alert-tag__content"><span v-if="!!regex"> ~ </span> <slot></slot></span>
</span>
</template>
@@ -11,7 +11,8 @@ export default {
props: {
label: String, // 标题
type: { type: String, default: 'normal' }, // normal:blue; success:green; info:gray; danger:red; warning:orange;
cursorPoint: { type: Boolean, default: true } // 是否鼠标悬停变手指
cursorPoint: { type: Boolean, default: true }, // 是否鼠标悬停变手指
regex: { type: Number, default: 0 }
},
methods: {
},

View File

@@ -776,7 +776,7 @@ export default {
$temp.quill.setSelection($temp.cursorIndex+text.length);
},200)//此值必须大于userChangeTimer的值 */
})
this.quill.clipboard.addMatcher(Node.ELEMENT_NODE, (node, delta) => {
this.quill.clipboard.addmatchers(Node.ELEMENT_NODE, (node, delta) => {
const ops = []
delta.ops.forEach(op => {
if (op.insert && typeof op.insert === 'string') {