NEZ-3321 fix:Log 图表时间轴精度异常
This commit is contained in:
@@ -2,7 +2,40 @@ export default {
|
|||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
metricOptions: [],
|
metricOptions: [],
|
||||||
showTemp: true
|
showTemp: true,
|
||||||
|
metricArr: [
|
||||||
|
{ expr: 'rate' },
|
||||||
|
{ expr: 'count_over_time' },
|
||||||
|
{ expr: 'bytes_rate' },
|
||||||
|
{ expr: 'bytes_over_time' },
|
||||||
|
{ expr: 'absent_over_time' },
|
||||||
|
{ expr: 'duration_seconds' },
|
||||||
|
{ expr: 'bytes' },
|
||||||
|
{ expr: 'rate_counter' },
|
||||||
|
{ expr: 'sum_over_time' },
|
||||||
|
{ expr: 'avg_over_time' },
|
||||||
|
{ expr: 'max_over_time' },
|
||||||
|
{ expr: 'min_over_time' },
|
||||||
|
{ expr: 'first_over_time' },
|
||||||
|
{ expr: 'last_over_time' },
|
||||||
|
{ expr: 'stdvar_over_time' },
|
||||||
|
{ expr: 'stddev_over_time' },
|
||||||
|
{ expr: 'quantile_over_time' },
|
||||||
|
{ expr: 'absent_over_time' },
|
||||||
|
{ expr: 'sum' },
|
||||||
|
{ expr: 'avg' },
|
||||||
|
{ expr: 'min' },
|
||||||
|
{ expr: 'max' },
|
||||||
|
{ expr: 'stddev' },
|
||||||
|
{ expr: 'stdvar' },
|
||||||
|
{ expr: 'count' },
|
||||||
|
{ expr: 'topk' },
|
||||||
|
{ expr: 'bottomk' },
|
||||||
|
{ expr: 'sort' },
|
||||||
|
{ expr: 'sort_desc' },
|
||||||
|
{ expr: 'vector' }
|
||||||
|
]
|
||||||
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -68,6 +101,13 @@ export default {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
validateMetric (text) {
|
||||||
|
const flag = this.metricArr.some(item => {
|
||||||
|
const regex = new RegExp(`${item.expr}\\(.*\\)`)
|
||||||
|
return regex.test(text)
|
||||||
|
})
|
||||||
|
return flag
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
|||||||
@@ -259,7 +259,18 @@
|
|||||||
</div>
|
</div>
|
||||||
</el-collapse-item>
|
</el-collapse-item>
|
||||||
<el-collapse-item v-if="showTab.indexOf('2') > -1" name="2" title="Logs">
|
<el-collapse-item v-if="showTab.indexOf('2') > -1" name="2" title="Logs">
|
||||||
<log-tab ref="logDetail" :timeRange="filterTime" :log-data="logData" :explore-log-table="logTabNoData" :explore-item="true" :tab-index="tabIndex" @exportLog="exportLog" @limitChange="queryLogData" v-my-loading="chartLoading"></log-tab>
|
<log-tab
|
||||||
|
ref="logDetail"
|
||||||
|
:unit="chartUnit"
|
||||||
|
:timeRange="filterTime"
|
||||||
|
:log-data="logData"
|
||||||
|
:explore-log-table="logTabNoData"
|
||||||
|
:explore-item="true"
|
||||||
|
:tab-index="tabIndex"
|
||||||
|
@exportLog="exportLog"
|
||||||
|
@limitChange="queryLogData"
|
||||||
|
v-my-loading="chartLoading">
|
||||||
|
</log-tab>
|
||||||
</el-collapse-item>
|
</el-collapse-item>
|
||||||
</template>
|
</template>
|
||||||
</el-collapse>
|
</el-collapse>
|
||||||
@@ -3757,7 +3768,92 @@ export default {
|
|||||||
reader.readAsText(error.response.data)
|
reader.readAsText(error.response.data)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
queryLogData (limit) { // log的chart和table是一个请求
|
queryLogChart () {
|
||||||
|
this.$refs.logDetail.$refs.logChart.startLoading()
|
||||||
|
const requestArr = []
|
||||||
|
const start = this.$stringTimeParseToUnix(bus.formateTimeToTime(this.filterTime[0]))
|
||||||
|
const end = this.$stringTimeParseToUnix(bus.formateTimeToTime(this.filterTime[1]))
|
||||||
|
// 当不是 指标查询表达式时,除直接查询 用户输入表达式外,另查询 sum by (level) (count_over_time($_expression[$_step]))
|
||||||
|
this.expressions.forEach((item, index) => {
|
||||||
|
if (item != '' && this.promqlKeys[index].state) {
|
||||||
|
const isMetric = this.validateMetric(item)
|
||||||
|
if (!isMetric) {
|
||||||
|
const step = bus.getStep(bus.formateTimeToTime(this.filterTime[0]), bus.formateTimeToTime(this.filterTime[1]))
|
||||||
|
const supplementaryExpr = `sum by (level) (count_over_time(${item}[${step}]))`
|
||||||
|
requestArr.push(this.$get('/logs/loki/api/v1/query_range?query=' + encodeURIComponent(supplementaryExpr) + '&start=' + start + '&end=' + end))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
axios.all(requestArr).then(res => {
|
||||||
|
res = res.filter((r, i) => r.code === 200)
|
||||||
|
if (res.length > 0) {
|
||||||
|
let series = []
|
||||||
|
let legend = []
|
||||||
|
const seriesItem = {
|
||||||
|
type: 'line',
|
||||||
|
name: '',
|
||||||
|
symbol: 'emptyCircle', // 去掉点
|
||||||
|
symbolSize: 8,
|
||||||
|
showSymbol: false,
|
||||||
|
smooth: 0.2, // 曲线变平滑
|
||||||
|
data: [],
|
||||||
|
lineStyle: {
|
||||||
|
width: 2,
|
||||||
|
opacity: 0.9
|
||||||
|
},
|
||||||
|
emphasis: {
|
||||||
|
focus: 'none'
|
||||||
|
},
|
||||||
|
blur: {
|
||||||
|
lineStyle: {
|
||||||
|
opacity: 0.3
|
||||||
|
},
|
||||||
|
itemStyle: {
|
||||||
|
opacity: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function mergeAndSort (arr) {
|
||||||
|
const mergedMap = new Map()
|
||||||
|
// 合并数组,根据时间戳累加值
|
||||||
|
arr.forEach(([timestamp, value]) => {
|
||||||
|
if (mergedMap.has(timestamp)) {
|
||||||
|
mergedMap.set(timestamp, mergedMap.get(timestamp) + Number(value))
|
||||||
|
} else {
|
||||||
|
mergedMap.set(timestamp, Number(value))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// 将Map转换为二维数组,并根据时间戳排序
|
||||||
|
const mergedArray = Array.from(mergedMap.entries()).sort((a, b) => a[0] - b[0])
|
||||||
|
return mergedArray
|
||||||
|
}
|
||||||
|
const logData = res.map(r => r.data)
|
||||||
|
logData.forEach((response) => {
|
||||||
|
const data = response.result
|
||||||
|
data.forEach((result, i) => {
|
||||||
|
seriesItem.name = 'logs'
|
||||||
|
const values = result.values.map((item) => {
|
||||||
|
return [item[0] * 1000, item[1]]
|
||||||
|
})
|
||||||
|
seriesItem.data.push(...values)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
seriesItem.data = mergeAndSort(seriesItem.data)
|
||||||
|
series = [seriesItem]
|
||||||
|
legend = [{ name: seriesItem.name, alias: seriesItem.name, isGray: false }]
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$refs.logDetail.$refs.logChart.setLegend(legend)
|
||||||
|
this.$refs.logDetail.$refs.logChart.setLogColor(series.length)
|
||||||
|
if (!series.length) {
|
||||||
|
series = ''
|
||||||
|
}
|
||||||
|
this.$refs.logDetail.$refs.logChart.setSeries(series)
|
||||||
|
this.$refs.logDetail.$refs.logChart.endLoading()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
queryLogData (limit) {
|
||||||
this.chartLoading = true
|
this.chartLoading = true
|
||||||
if (!limit) {
|
if (!limit) {
|
||||||
limit = this.$refs.logDetail ? this.$refs.logDetail.getLimit() : 100
|
limit = this.$refs.logDetail ? this.$refs.logDetail.getLimit() : 100
|
||||||
@@ -3836,7 +3932,7 @@ export default {
|
|||||||
let series = []
|
let series = []
|
||||||
const legend = []
|
const legend = []
|
||||||
this.expressions.forEach((item, index) => {
|
this.expressions.forEach((item, index) => {
|
||||||
if (item !== '') {
|
if (item !== '' && this.promqlKeys[index].state) {
|
||||||
promqlInputIndexs.push(index)
|
promqlInputIndexs.push(index)
|
||||||
queryExpression.push(item)
|
queryExpression.push(item)
|
||||||
}
|
}
|
||||||
@@ -4165,6 +4261,7 @@ export default {
|
|||||||
this.storeHistory()
|
this.storeHistory()
|
||||||
} else {
|
} else {
|
||||||
this.queryLogData()
|
this.queryLogData()
|
||||||
|
this.queryLogChart()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.updatePath()
|
this.updatePath()
|
||||||
|
|||||||
@@ -612,9 +612,16 @@ export default {
|
|||||||
const graphData = this.logData.filter(l => l.resultType === 'matrix')
|
const graphData = this.logData.filter(l => l.resultType === 'matrix')
|
||||||
if (graphData && graphData.length > 0) {
|
if (graphData && graphData.length > 0) {
|
||||||
this.$refs.logChart.startLoading()
|
this.$refs.logChart.startLoading()
|
||||||
|
const promqlInputIndexs = []
|
||||||
const queryExpression = []
|
const queryExpression = []
|
||||||
let series = []
|
let series = []
|
||||||
const legend = []
|
const legend = []
|
||||||
|
this.dataJson.data.forEach((item, index) => {
|
||||||
|
if (item.expression !== '' && item.state) {
|
||||||
|
promqlInputIndexs.push(index)
|
||||||
|
queryExpression.push(item.expression)
|
||||||
|
}
|
||||||
|
})
|
||||||
this.logData.forEach((response, index) => {
|
this.logData.forEach((response, index) => {
|
||||||
if (response.resultType === 'matrix') {
|
if (response.resultType === 'matrix') {
|
||||||
const data = response.result
|
const data = response.result
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="log-detail">
|
<div class="log-detail">
|
||||||
<div :id="`logChart${tabIndex}`" class="log-chart" v-if="showSwitch"></div>
|
<!-- <div :id="`logChart${tabIndex}`" class="log-chart" v-if="showSwitch"></div> -->
|
||||||
|
<chart ref="logChart" :unit="unit" :timeRange="timeRange"></chart>
|
||||||
<div class="log-chart chart-no-data" v-if="showSwitch&&noData" style="top: 150px">No data</div>
|
<div class="log-chart chart-no-data" v-if="showSwitch&&noData" style="top: 150px">No data</div>
|
||||||
<div class="log-operations" v-if="showSwitch">
|
<div class="log-operations" v-if="showSwitch">
|
||||||
<div class="log-operation">
|
<div class="log-operation">
|
||||||
@@ -108,6 +109,7 @@ import * as echarts from 'echarts'
|
|||||||
import chartConfig from '@/components/page/dashboard/overview/chartConfig'
|
import chartConfig from '@/components/page/dashboard/overview/chartConfig'
|
||||||
import { dealLegendAlias } from '@/components/common/js/tools'
|
import { dealLegendAlias } from '@/components/common/js/tools'
|
||||||
import bus from '@/libs/bus'
|
import bus from '@/libs/bus'
|
||||||
|
import chart from '../overview/chart'
|
||||||
export default {
|
export default {
|
||||||
name: 'logTab',
|
name: 'logTab',
|
||||||
props: {
|
props: {
|
||||||
@@ -120,7 +122,12 @@ export default {
|
|||||||
loadingBottom: Boolean,
|
loadingBottom: Boolean,
|
||||||
exploreLogTable: Boolean,
|
exploreLogTable: Boolean,
|
||||||
exploreItem: Boolean,
|
exploreItem: Boolean,
|
||||||
timeRange: {}
|
timeRange: {},
|
||||||
|
logChartData: Array,
|
||||||
|
unit: { type: Number, default: 5 }
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
chart
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
tableTimeFormat () {
|
tableTimeFormat () {
|
||||||
|
|||||||
@@ -621,6 +621,14 @@ export default {
|
|||||||
this.colors = Object.assign([], colors)
|
this.colors = Object.assign([], colors)
|
||||||
this.$set(this.option, 'color', colors)
|
this.$set(this.option, 'color', colors)
|
||||||
},
|
},
|
||||||
|
setLogColor: function (num) {
|
||||||
|
const colors = []
|
||||||
|
for (let i = 0; i < num; i++) {
|
||||||
|
colors.push('#bdc4cd')
|
||||||
|
}
|
||||||
|
this.colors = Object.assign([], colors)
|
||||||
|
this.$set(this.option, 'color', colors)
|
||||||
|
},
|
||||||
startLoading: function () {
|
startLoading: function () {
|
||||||
this.$refs.loading.startLoading()
|
this.$refs.loading.startLoading()
|
||||||
this.$emit('is-loading', true)
|
this.$emit('is-loading', true)
|
||||||
|
|||||||
Reference in New Issue
Block a user