NEZ-3176 fix:explore 历史记录页面开发

This commit is contained in:
zhangyu
2023-09-13 18:01:22 +08:00
parent c669de4cca
commit 44b481af67
12 changed files with 347 additions and 2093 deletions

View File

@@ -120,6 +120,7 @@
@import './page/config/setup.scss';
@import './page/config/system.scss';
@import './page/dashboard/explore/explore.scss';
@import './page/dashboard/explore/exploreHistory.scss';
@import './page/dashboard/explore/logTab.scss';
@import './page/dashboard/explore/promqlInput.scss';
@import './page/dashboard/overview/chart.scss';

View File

@@ -0,0 +1,92 @@
.explore-history-box {
position: absolute;
max-height: 360px;
box-shadow: -1px 1px 10px -1px $--dropdown-menu-box-shadow-color;
border-radius: 2px;
min-height: 40px;
width: 100%;
background: $--background-color-empty;
bottom: -15px;
transform: translateY(100%);
z-index: 10;
display: flex;
flex-direction: column;
.explore-history-box-header {
display: flex;
justify-content: space-between;
box-sizing: border-box;
width: 100%;
padding: 0 10px 0 10px;
height: 42px;
line-height: 42px;
margin-bottom: 5px;
border-bottom: 1px solid $--border-color-light;
.header-text {
font-family: Roboto-Medium;
font-size: 14px;
color: $--color-text-primary;
letter-spacing: 0;
font-weight: 600;
}
.header-search {
width: 200px;
}
}
.explore-history-box-content {
flex: 1;
overflow-y: auto;
overflow-x: hidden;
}
.explore-history-item {
height: 32px;
line-height: 32px;
width: 100%;
font-size: 14px;
color: $--color-text-regular;
font-weight: 400;
display: flex;
box-sizing: border-box;
padding: 0 12px 0 20px;
.explore-history-item-icon {
display: none;
width: 46px;
}
}
.explore-history-item:hover{
background: $--table-row-hover-background-color;
.explore-history-item-content {
width: calc(100% - 46px);
box-sizing: border-box;
}
.explore-history-item-icon {
display: flex;
width: 46px;
justify-content: space-between;
.nz-icon{
cursor: pointer;
}
}
}
.no-more {
background: transparent !important;
text-align: center;
font-size: 12px;
color: $--color-text-secondary;
font-weight: 400;
display: block;
}
.explore-history-box-content.nodata {
background: transparent !important;
text-align: center;
font-size: 12px;
height: 300px;
color: $--color-text-secondary;
font-weight: 400;
flex-shrink: 0;
flex: unset;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
}

View File

@@ -188,6 +188,7 @@
}
#explore-promql-box{
.query-row {
position: relative;
.input-box {
flex: 1;
}

View File

@@ -1104,6 +1104,7 @@ export const loadMore = {
bind (el, binding) {
// 获取element定义scroll
const selectDom = binding.value.dom ? el.querySelector(binding.value.dom) : el
el.hasMore = binding.value.hasMore
heightLoad = bus.debounce(function () {
if (!el.hasMore) {
return

View File

@@ -307,11 +307,11 @@ export default {
params.params = {}
params.paramObj.forEach(item => {
if (item.type === 'CHECKBOX') {
params.params[item.name] = item.value
params.params[item.metaKey] = item.value
} else if (item.type === 'DATETIME' && JSON.parse(item.param).interval) {
params.params[item.name] = item.value
params.params[item.metaKey] = item.value
} else {
params.params[item.name] = item.value[0]
params.params[item.metaKey] = item.value[0]
}
})
params.icon = this.imageUrl

View File

@@ -315,7 +315,7 @@ export default {
params.icon = this.imageUrl
params.params = {}
params.paramObj.forEach(item => {
params.params[item.name] = item
params.params[item.metaKey] = item
})
if (this.editSoftwareType.id) {
this.$put(this.url, params).then(res => {

View File

@@ -82,7 +82,7 @@
:expression-list="expressions"
:state="promqlKeys[index-1].state"
:index="index-1"
:plugins="['metric-selector', 'metric-input', 'add', 'remove', 'copy','enable']"
:plugins="['metric-selector', 'metric-input', 'add', 'remove', 'copy','enable', 'history']"
:styleType="1"
type="metric"
@enableExpression="enableExpression"
@@ -102,7 +102,7 @@
:expression-list="expressions"
:state="promqlKeys[index-1].state"
:index="index-1"
:plugins="['metric-selector', 'metric-input', 'add', 'remove', 'copy','enable']"
:plugins="['metric-selector', 'metric-input', 'add', 'remove', 'copy','enable', 'history']"
:styleType="1"
type="log"
@enableExpression="enableExpression"
@@ -3618,12 +3618,16 @@ export default {
showTopBtn: false, // top按钮
scrollbarWrap: null,
allMatrix: false, // metric是否全部为matrix类型
rowData: []
rowData: [],
metricsHistory: [],
logsHistory: [],
lastHistory: []
}
},
async created () {
this.getPanelData()
this.resetExpression()
// this.getExploreHistory()
await this.loadWebAssembly()
this.initQueryFromPath()
},
@@ -3692,6 +3696,8 @@ export default {
changeType (value) {
this.showMetrics = value === 'Metrics'
this.showIntroduce = true
this.lastHistory = []
// this.getExploreHistory()
this.resetExpression()
},
split () {
@@ -4199,6 +4205,7 @@ export default {
} else {
this.queryLogData()
}
this.postHistory()
}
this.updatePath()
},
@@ -4399,6 +4406,37 @@ export default {
handleBox (show) {
this.rightBox.show = show
},
postHistory () {
// expressions
const postArr = []
const queryKey = this.showMetrics ? 'explore-metric' : 'explore-log'
const arr = this.promqlKeys.map((item, index) => {
item.queryValue = this.expressions[index]
return item
})
this.lastHistory.forEach((item) => {
const findItem = arr.find(history => history.id == item.id)
if (findItem && findItem.queryValue !== item.value) {
postArr.push({
queryKey,
queryValue: findItem.queryValue
})
}
})
arr.forEach(item => {
const findItem = this.lastHistory.find(history => history.id == item.id)
if (!findItem) {
postArr.push({
queryKey,
queryValue: item.queryValue
})
}
})
this.$post('/sys/user/queryHistory', postArr).then(res => {
console.log(res)
this.lastHistory = this.$lodash.cloneDeep(arr)
})
},
saveChart () {
const chart = {
id: '',

View File

@@ -0,0 +1,187 @@
<template>
<div class="explore-history-box" v-clickoutside="hideMe" >
<div class="explore-history-box-header">
<span class="header-text">{{$t('terminal.history')}}</span>
<el-input
class="header-search"
size="mini"
v-model="searchStr"
@input="changeSearchStr"
:placeholder="$t('overall.search')"
suffix-icon="nz-icon nz-icon-search"
/>
</div>
<div
class="explore-history-box-content"
v-if="historyArr.length"
infinite-scroll-disabled="disabled"
v-loadMore="{
load: loadNextData,
hasMore: hasMore,
}"
>
<div v-for="(item, index) in historyArr" :key="index" :title="item.value" class="explore-history-item" @click="selectHistory(item)">
<div class="explore-history-item-content text-ellipsis" :title="item.queryValue">
{{item.queryValue}}
</div>
<div class="explore-history-item-icon">
<i class="nz-icon nz-icon-override" @click.stop="copyHistoryItem(item)"></i>
<i class="nz-icon nz-icon-delete" @click.stop="deleteHistoryItem(item)"></i>
</div>
</div>
<div v-if="pageObj.total > historyArr.length" v-my-loading.scaleMin="loading" class="explore-history-item no-more">
{{$t('el.select.loading')}}...
</div>
<div v-else class="explore-history-item no-more">
{{$t('overall.noMoreData')}}
</div>
</div>
<div v-else class="explore-history-box-content nodata">
<svg class="icon" aria-hidden="true">
<use xlink:href="#nz-icon-no-data-list"></use>
</svg>
<div class="table-no-data__title">{{$t('overall.noDataAvailable')}}</div>
</div>
</div>
</template>
<script>
import bus from '@/libs/bus'
export default {
name: 'exploreHistory',
props: {
type: {
type: String,
default: 'metrics'
}
},
computed: {
},
data () {
return {
historyArr: [],
firstLoading: false,
loading: true,
searchStr: '',
pageObj: {
pageNo: 1,
pageSize: 10,
total: 0
},
hasMore: true
}
},
mounted () {
this.init()
},
methods: {
init (pageSize) {
this.firstLoading = true
this.historyArr = []
this.pageObj = {
pageNo: 1,
pageSize: pageSize || 10,
total: 0
}
this.total = 0
this.getExploreHistory()
},
loadNextData () {
this.pageObj.pageNo++
this.getExploreHistory()
},
changeSearchStr: bus.debounce(function (val) {
this.init()
}, 300),
getExploreHistory () {
const params = {
...this.pageObj,
queryValue: this.searchStr,
orderBy: 'uts'
}
if (this.type === 'metric') {
params.queryKey = 'explore-metric'
} else {
params.queryKey = 'explore-log'
}
delete params.total
this.$get('/sys/user/queryHistory', params).then(res => {
if (res.code === 200) {
this.historyArr = [...this.historyArr, ...res.data.list]
this.pageObj.total = res.data.total
if (this.pageObj.total > this.historyArr.length) {
this.hasMore = true
} else {
this.hasMore = false
}
this.pageObj.pageSize = 10
} else {
this.$message.error(res.msg || res.error)
}
})
},
hideMe () {
setTimeout(() => {
this.$emit('close')
}, 100)
},
copyHistoryItem (item) {
this.$copyText(item.queryValue).then(() => {
this.$message.success({ message: this.$t('overall.copySuccess') })
})
},
deleteHistoryItem (item) {
this.$delete('/sys/user/queryHistory?ids=' + item.id).then(res => {
if (res.code === 200) {
this.$message.success(this.$t('tip.deleteSuccess'))
this.firstLoading = true
setTimeout(() => {
this.deleteAfter(this.historyArr.length)
}, 100)
// this.pageObj.total--
// this.historyArr = this.historyArr.filter(historyItem => historyItem.id !== item.id)
} else {
this.$message.error(res.msg || res.error)
}
})
},
deleteAfter (pageSize) {
const params = {
pageNo: 1,
queryValue: this.searchStr,
orderBy: 'uts',
pageSize
}
if (this.type === 'metric') {
params.queryKey = 'explore-metric'
} else {
params.queryKey = 'explore-log'
}
delete params.total
this.$get('/sys/user/queryHistory', params).then(res => {
if (res.code === 200) {
this.firstLoading = false
this.historyArr = res.data.list
this.pageObj.total = res.data.total
if (this.pageObj.total > this.historyArr.length) {
this.hasMore = true
} else {
this.hasMore = false
}
this.pageObj.pageSize = 10
} else {
this.$message.error(res.msg || res.error)
}
})
},
selectHistory (item) {
this.$emit('selectHistory', item.queryValue)
}
}
}
</script>
<style scoped>
</style>

View File

@@ -1,128 +0,0 @@
module github.com/steinarvk/logqlparse
go 1.18
require (
github.com/grafana/loki v1.6.2-0.20220520203912-5206e3acd0e6
github.com/spf13/cobra v1.0.0
)
require (
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver/v3 v3.1.1 // indirect
github.com/Masterminds/sprig/v3 v3.2.2 // indirect
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect
github.com/armon/go-metrics v0.3.9 // indirect
github.com/aws/aws-sdk-go v1.43.10 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/coreos/etcd v3.3.25+incompatible // indirect
github.com/coreos/go-semver v0.3.0 // indirect
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf // indirect
github.com/coreos/go-systemd/v22 v22.3.2 // indirect
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dennwc/varint v1.0.0 // indirect
github.com/dustin/go-humanize v1.0.0 // indirect
github.com/edsrzf/mmap-go v1.1.0 // indirect
github.com/fatih/color v1.13.0 // indirect
github.com/felixge/httpsnoop v1.0.2 // indirect
github.com/go-kit/log v0.2.0 // indirect
github.com/go-logfmt/logfmt v0.5.1 // indirect
github.com/go-logr/logr v1.2.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/gogo/googleapis v1.4.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/gogo/status v1.1.0 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/btree v1.0.1 // indirect
github.com/google/uuid v1.2.0 // indirect
github.com/gorilla/mux v1.8.0 // indirect
github.com/grafana/dskit v0.0.0-20220331160727-49faf69f72ca // indirect
github.com/grafana/regexp v0.0.0-20220304100321-149c8afcd6cb // indirect
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect
github.com/hashicorp/consul/api v1.12.0 // indirect
github.com/hashicorp/errwrap v1.0.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-hclog v0.16.2 // indirect
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
github.com/hashicorp/go-msgpack v0.5.5 // indirect
github.com/hashicorp/go-multierror v1.1.0 // indirect
github.com/hashicorp/go-rootcerts v1.0.2 // indirect
github.com/hashicorp/go-sockaddr v1.0.2 // indirect
github.com/hashicorp/golang-lru v0.5.4 // indirect
github.com/hashicorp/memberlist v0.3.0 // indirect
github.com/hashicorp/serf v0.9.6 // indirect
github.com/huandu/xstrings v1.3.1 // indirect
github.com/imdario/mergo v0.3.12 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/jpillora/backoff v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/mattn/go-colorable v0.1.9 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
github.com/miekg/dns v1.1.46 // indirect
github.com/mitchellh/copystructure v1.0.0 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/mapstructure v1.4.3 // indirect
github.com/mitchellh/reflectwalk v1.0.1 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect
github.com/oklog/ulid v1.3.1 // indirect
github.com/opentracing-contrib/go-grpc v0.0.0-20210225150812-73cb765af46e // indirect
github.com/opentracing-contrib/go-stdlib v1.0.0 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.12.1 // indirect
github.com/prometheus/client_model v0.2.0 // indirect
github.com/prometheus/common v0.32.1 // indirect
github.com/prometheus/common/sigv4 v0.1.0 // indirect
github.com/prometheus/node_exporter v1.0.0-rc.0.0.20200428091818-01054558c289 // indirect
github.com/prometheus/procfs v0.7.3 // indirect
github.com/prometheus/prometheus v1.8.2-0.20220303173753-edfe657b5405 // indirect
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect
github.com/sercand/kuberesolver v2.4.0+incompatible // indirect
github.com/shopspring/decimal v1.2.0 // indirect
github.com/sirupsen/logrus v1.8.1 // indirect
github.com/spf13/cast v1.3.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stretchr/objx v0.2.0 // indirect
github.com/stretchr/testify v1.7.1 // indirect
github.com/uber/jaeger-client-go v2.30.0+incompatible // indirect
github.com/uber/jaeger-lib v2.4.1+incompatible // indirect
github.com/weaveworks/common v0.0.0-20211015155308-ebe5bdc2c89e // indirect
github.com/weaveworks/promrus v1.2.0 // indirect
go.etcd.io/etcd v3.3.25+incompatible // indirect
go.etcd.io/etcd/api/v3 v3.5.0 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.5.0 // indirect
go.etcd.io/etcd/client/v3 v3.5.0 // indirect
go.opentelemetry.io/otel v1.4.1 // indirect
go.opentelemetry.io/otel/trace v1.4.1 // indirect
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/goleak v1.1.12 // indirect
go.uber.org/multierr v1.7.0 // indirect
go.uber.org/zap v1.19.1 // indirect
go4.org/intern v0.0.0-20211027215823-ae77deb06f29 // indirect
go4.org/unsafe/assume-no-moving-gc v0.0.0-20211027215541-db492cf91b37 // indirect
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 // indirect
golang.org/x/mod v0.5.1 // indirect
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
golang.org/x/sys v0.0.0-20220222172238-00053529121e // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect
golang.org/x/tools v0.1.9 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20220222154240-daf995802d7b // indirect
google.golang.org/grpc v1.44.0 // indirect
google.golang.org/protobuf v1.27.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
inet.af/netaddr v0.0.0-20211027220019-c74959edd3b6 // indirect
)

View File

@@ -1,44 +0,0 @@
package main
import (
"fmt"
"io/ioutil"
"os"
"strings"
"github.com/grafana/loki/pkg/logql/syntax"
)
type parseFailed struct {
query string
err error
}
func (e parseFailed) Error() string {
return fmt.Sprintf("Parse failed as Loki LokQL expression:\n\t%s\n\nExpression was:\n\t%s", e.err.Error(), e.query)
}
func evaluate(query string) (string, error) {
query = strings.TrimSpace(query)
parsed, err := syntax.ParseExpr(query)
if err == nil {
canonical := parsed.String()
return canonical, nil
}
return "", parseFailed{query, err}
}
func main() {
data, err := ioutil.ReadAll(os.Stdin)
if err != nil {
fmt.Fprintf(os.Stderr, "read error: %v", err)
os.Exit(1)
}
if _, err := evaluate(string(data)); err != nil {
fmt.Println(err)
os.Exit(1)
}
}

View File

@@ -119,6 +119,14 @@
<i v-if="state" class="nz-icon nz-icon-mimakejian"></i>
<i v-else class="nz-icon nz-icon-mimabukejian" style="fontSize:16px"></i>
</button>
<button
v-if="plugins.indexOf('history') > -1"
class="top-tool-btn"
:title="$t('overall.history')"
@click.stop="showHistoryBox(!historyshow)"
>
<i class="nz-icon nz-icon-time" style="fontSize:16px"></i>
</button>
<button
v-if="plugins.indexOf('add') > -1"
class="top-tool-btn"
@@ -144,6 +152,7 @@
<i class="nz-icon nz-icon-minus"></i>
</button>
</div>
<explore-history v-if="historyshow" :type="type" @close="showHistoryBox(false)" @selectHistory="selectHistory"/>
</template>
<!--right-box里的样式-->
<template v-if="styleType === 2 || styleType === 3">
@@ -449,10 +458,12 @@ import {
closeBrackets,
closeBracketsKeymap
} from '@codemirror/autocomplete'
import exploreHistory from '@/components/page/dashboard/explore/histoyrComponent/exploreHistory'
export default {
name: 'promqlInput',
components: {
selectAlertSilence
selectAlertSilence,
exploreHistory
},
props: {
index: { type: Number },
@@ -519,7 +530,8 @@ export default {
filterSilence: '',
tempBoxId: {},
loading: false,
firstInit: true
firstInit: true,
historyshow: false
}
},
computed: {
@@ -1142,6 +1154,9 @@ export default {
tempBoxClose () {
this.cascaderValue = ''
},
selectHistory (str) {
this.insertText(str)
},
insertText (insertTxt) {
// 获取el-input中的input元素
// const elInput = this.$refs.elInput.$el.firstElementChild
@@ -1174,6 +1189,9 @@ export default {
})
)
})
},
showHistoryBox (flag) {
this.historyshow = flag
}
},
watch: {