You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by wu...@apache.org on 2020/08/14 06:42:49 UTC
[skywalking-rocketbot-ui] branch master updated: Feat: Support tag
conditions for trace (#339)
This is an automated email from the ASF dual-hosted git repository.
wusheng pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/skywalking-rocketbot-ui.git
The following commit(s) were added to refs/heads/master by this push:
new 34f98b1 Feat: Support tag conditions for trace (#339)
34f98b1 is described below
commit 34f98b1c9aa667cc481abe6bbe46fa361124e1a2
Author: Qiuxia Fan <fi...@outlook.com>
AuthorDate: Fri Aug 14 14:42:39 2020 +0800
Feat: Support tag conditions for trace (#339)
---
src/assets/lang/en.ts | 4 +
src/assets/lang/zh.ts | 3 +
src/graph/fragments/trace.ts | 4 +-
src/store/modules/trace/index.ts | 4 +-
src/views/components/trace/trace-search.vue | 151 ++++++++--
src/views/containers/topology/trace/index.vue | 2 +-
.../containers/topology/trace/trace-search.vue | 329 ---------------------
7 files changed, 132 insertions(+), 365 deletions(-)
diff --git a/src/assets/lang/en.ts b/src/assets/lang/en.ts
index a77d413..3ba9903 100644
--- a/src/assets/lang/en.ts
+++ b/src/assets/lang/en.ts
@@ -149,6 +149,10 @@ const m = {
increaseOrder: 'Increase Order',
chartType: 'Chart Type',
currentDepth: 'Current Depth',
+ traceTagsTip:
+ 'Only tags defined in the core/default/searchableTagKeys are searchable. Check more details on the Configuration Vocabulary page',
+ traceLink: 'Configuration Vocabulary page',
+ traceAddTag: 'Please add a tag',
};
export default m;
diff --git a/src/assets/lang/zh.ts b/src/assets/lang/zh.ts
index abeb7fb..846cd74 100644
--- a/src/assets/lang/zh.ts
+++ b/src/assets/lang/zh.ts
@@ -149,6 +149,9 @@ const m = {
increaseOrder: '递增顺序',
chartType: '图表类型',
currentDepth: '当前深度',
+ traceTagsTip: '只有core/default/searchableTagKeys中定义的标记才可搜索。查看配置词汇表页面上的更多详细信息。',
+ traceLink: '配置词汇页',
+ traceAddTag: '请添加标签',
};
export default m;
diff --git a/src/graph/fragments/trace.ts b/src/graph/fragments/trace.ts
index 290b023..6e61794 100644
--- a/src/graph/fragments/trace.ts
+++ b/src/graph/fragments/trace.ts
@@ -18,8 +18,8 @@
export const Traces = {
variable: '$condition: TraceQueryCondition',
query: `
- traces: queryBasicTraces(condition: $condition) {
- data: traces {
+ data: queryBasicTraces(condition: $condition) {
+ traces {
key: segmentId
endpointNames
duration
diff --git a/src/store/modules/trace/index.ts b/src/store/modules/trace/index.ts
index 469a509..2ea5255 100644
--- a/src/store/modules/trace/index.ts
+++ b/src/store/modules/trace/index.ts
@@ -139,8 +139,8 @@ const actions: ActionTree<State, any> = {
.query('queryTraces')
.params({ condition: context.state.traceForm })
.then((res: AxiosResponse) => {
- context.commit(types.SET_TRACELIST, res.data.data.traces.data);
- context.commit(types.SET_TRACELIST_TOTAL, res.data.data.traces.total);
+ context.commit(types.SET_TRACELIST, res.data.data.data.traces);
+ context.commit(types.SET_TRACELIST_TOTAL, res.data.data.data.total);
});
},
GET_TRACE_SPANS(context: { commit: Commit }, params: any): Promise<void> {
diff --git a/src/views/components/trace/trace-search.vue b/src/views/components/trace/trace-search.vue
index e1b6a29..0463deb 100644
--- a/src/views/components/trace/trace-search.vue
+++ b/src/views/components/trace/trace-search.vue
@@ -59,22 +59,53 @@ limitations under the License. -->
</div>
</div>
</div>
- <div class="rk-trace-search-more flex-h" v-show="status">
- <div class="mr-15">
- <span class="sm b grey mr-10">{{ this.$t('traceID') }}:</span>
- <input type="text" v-model="traceId" class="rk-trace-search-input dib" />
- </div>
- <div class="mr-15">
- <span class="sm b grey mr-10">{{ this.$t('duration') }}:</span>
- <div class="rk-trace-search-range dib">
- <input class="vm tc" v-model="minTraceDuration" />
- <span class="grey vm">-</span>
- <input class="vm tc" v-model="maxTraceDuration" />
+ <div class="rk-trace-search-more" v-show="status">
+ <div class="flex-h">
+ <div class="mr-15">
+ <span class="sm b grey mr-10">{{ this.$t('traceID') }}:</span>
+ <input type="text" v-model="traceId" class="rk-trace-search-input dib" />
+ </div>
+ <div class="mr-15">
+ <span class="sm b grey mr-10">{{ this.$t('duration') }}:</span>
+ <div class="rk-trace-search-range dib">
+ <input class="vm tc" v-model="minTraceDuration" />
+ <span class="grey vm">-</span>
+ <input class="vm tc" v-model="maxTraceDuration" />
+ </div>
+ </div>
+ <div>
+ <span class="sm b grey mr-5">{{ this.$t('timeRange') }}:</span>
+ <RkDate class="sm" v-model="time" position="bottom" format="YYYY-MM-DD HH:mm:ss" />
</div>
</div>
- <div>
- <span class="sm b grey mr-5">{{ this.$t('timeRange') }}:</span>
- <RkDate class="sm" v-model="time" position="bottom" format="YYYY-MM-DD HH:mm:ss" />
+ <div class="flex-h">
+ <div class="mr-10" style="padding-top: 5px">
+ <span class="sm grey">{{ this.$t('tags') }}: </span>
+ <span class="rk-trace-tags">
+ <span class="selected" v-for="(item, index) in tagsList" :key="index">
+ <span>{{ item }}</span>
+ <span class="remove-icon" @click="removeTags(index)">×</span>
+ </span>
+ </span>
+ <input
+ type="text"
+ :placeholder="this.$t('traceAddTag')"
+ v-model="tags"
+ class="rk-trace-new-tag"
+ @keyup="addLabels"
+ />
+ <span class="trace-tips" v-tooltip:bottom="{ content: this.$t('traceTagsTip') }">
+ <a
+ target="blank"
+ href="https://github.com/apache/skywalking/blob/master/docs/en/setup/backend/configuration-vocabulary.md"
+ >
+ {{ this.$t('traceLink') }}
+ </a>
+ <svg class="icon mr-5 vm">
+ <use xlink:href="#help"></use>
+ </svg>
+ </span>
+ </div>
</div>
</div>
</div>
@@ -108,7 +139,26 @@ limitations under the License. -->
private endpointName: string = localStorage.getItem('endpointName') || '';
private traceId: string = localStorage.getItem('traceId') || '';
private traceState: Option = { label: 'All', key: 'ALL' };
+ private tags: string = '';
+ private tagsList: string[] = [];
+ private created() {
+ this.endpointName = this.$route.query.endpointname
+ ? this.$route.query.endpointname.toString()
+ : this.endpointName;
+ this.traceId = this.$route.query.traceid ? this.$route.query.traceid.toString() : this.traceId;
+ this.time = [this.rocketbotGlobal.durationRow.start, this.rocketbotGlobal.durationRow.end];
+ this.tagsList = localStorage.getItem('traceTags') ? JSON.parse(localStorage.getItem('traceTags') || '') : [];
+ }
+ private mounted() {
+ this.getTraceList();
+ if (this.service && this.service.key) {
+ this.GET_INSTANCES({
+ duration: this.durationTime,
+ serviceId: this.service.key,
+ });
+ }
+ }
private dateFormat(date: Date, step: string) {
const year = date.getFullYear();
const monthTemp = date.getMonth() + 1;
@@ -216,6 +266,17 @@ limitations under the License. -->
temp.traceId = this.traceId;
localStorage.setItem('traceId', this.traceId);
}
+ if (this.tagsList.length) {
+ const tagsMap = this.tagsList.map((item: string) => {
+ const t = item.split('=');
+ return {
+ key: t[0],
+ value: t[1],
+ };
+ });
+ temp.tags = tagsMap;
+ localStorage.setItem('traceTags', JSON.stringify(this.tagsList));
+ }
this.SET_TRACE_FORM(temp);
this.$eventBus.$emit('SET_LOADING_TRUE', () => {
@@ -236,6 +297,8 @@ limitations under the License. -->
this.instance = { label: 'All', key: '' };
this.endpointName = '';
localStorage.removeItem('endpointName');
+ this.tagsList = [];
+ localStorage.removeItem('traceTags');
this.traceId = '';
localStorage.removeItem('traceId');
this.traceState = { label: 'All', key: 'ALL' };
@@ -243,26 +306,21 @@ limitations under the License. -->
this.getTraceList();
}
- @Watch('rocketbotGlobal.durationRow')
- private durationRowWatch(value: Duration) {
- this.time = [value.start, value.end];
+ private addLabels(event: KeyboardEvent) {
+ if (event.keyCode !== 13 || !this.tags) {
+ return;
+ }
+ this.tagsList.push(this.tags);
+ this.tags = '';
}
- private created() {
- this.endpointName = this.$route.query.endpointname
- ? this.$route.query.endpointname.toString()
- : this.endpointName;
- this.traceId = this.$route.query.traceid ? this.$route.query.traceid.toString() : this.traceId;
- this.time = [this.rocketbotGlobal.durationRow.start, this.rocketbotGlobal.durationRow.end];
+ private removeTags(index: number) {
+ this.tagsList.splice(index, 1);
}
- private mounted() {
- this.getTraceList();
- if (this.service && this.service.key) {
- this.GET_INSTANCES({
- duration: this.durationTime,
- serviceId: this.service.key,
- });
- }
+
+ @Watch('rocketbotGlobal.durationRow')
+ private durationRowWatch(value: Duration) {
+ this.time = [value.start, value.end];
}
}
</script>
@@ -274,6 +332,22 @@ limitations under the License. -->
color: #eee;
width: 100%;
padding: 3px 15px 8px;
+ .selected {
+ display: inline-block;
+ padding: 0 3px;
+ border-radius: 3px;
+ overflow: hidden;
+ color: rgba(0, 0, 0, 0.65);
+ border: 1px dashed #aaa;
+ color: #eee;
+ font-size: 12px;
+ margin: 0 2px;
+ }
+ .remove-icon {
+ display: inline-block;
+ margin-left: 3px;
+ cursor: pointer;
+ }
}
.rk-trace-search-input {
@@ -282,6 +356,21 @@ limitations under the License. -->
padding: 2px 5px;
border-radius: 3px;
}
+ .rk-trace-new-tag {
+ border-style: unset;
+ outline: 0;
+ padding: 2px 5px;
+ border-radius: 3px;
+ width: 175px;
+ margin-right: 3px;
+ }
+ .rk-trace-tags {
+ padding: 1px 5px 0 0;
+ border-radius: 3px;
+ height: 24px;
+ display: inline-block;
+ vertical-align: top;
+ }
.rk-trace-search-range,
.rk-auto-select {
diff --git a/src/views/containers/topology/trace/index.vue b/src/views/containers/topology/trace/index.vue
index 55f9fb6..671f334 100644
--- a/src/views/containers/topology/trace/index.vue
+++ b/src/views/containers/topology/trace/index.vue
@@ -26,7 +26,7 @@ limitations under the License. -->
import { Option } from '@/types/global';
import { Component, Vue, Prop, PropSync, Watch } from 'vue-property-decorator';
import { State, Action, Mutation } from 'vuex-class';
- import TraceSearch from './trace-search.vue';
+ import TraceSearch from '@/views/components/trace/trace-search.vue';
import TraceTable from '@/views/components/trace/trace-table.vue';
import TraceDetail from '@/views/components/trace/trace-detail.vue';
@Component({
diff --git a/src/views/containers/topology/trace/trace-search.vue b/src/views/containers/topology/trace/trace-search.vue
deleted file mode 100644
index 7525d5e..0000000
--- a/src/views/containers/topology/trace/trace-search.vue
+++ /dev/null
@@ -1,329 +0,0 @@
-<!-- Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements. See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License. -->
-
-<template>
- <div class="rk-trace-search">
- <div>
- <a class="rk-trace-clear-btn r" @click="status = !status">
- <span class="mr-5 vm">{{ this.$t('more') }}</span>
- <svg class="icon trans vm" :style="`transform: rotate(${status ? 180 : 0}deg);`">
- <use xlink:href="#arrow-down"></use>
- </svg>
- </a>
- <a class="rk-trace-search-btn bg-blue r mr-10" @click="getTraceList">
- <svg class="icon mr-5 vm">
- <use xlink:href="#search"></use>
- </svg>
- <span class="vm">{{ this.$t('search') }}</span>
- </a>
- <a class="rk-trace-clear-btn r mr-10" @click="clearSearch">
- <svg class="icon mr-5 vm">
- <use xlink:href="#clear"></use>
- </svg>
- <span class="vm">{{ this.$t('clear') }}</span>
- </a>
- <div class="flex-h">
- <TraceSelect :hasSearch="true" :title="this.$t('instance')" v-model="instance" :data="rocketTrace.instances" />
- <TraceSelect
- :title="this.$t('status')"
- :value="traceState"
- @input="chooseStatus"
- :data="[
- { label: 'All', key: 'ALL' },
- { label: 'Success', key: 'SUCCESS' },
- { label: 'Error', key: 'ERROR' },
- ]"
- />
- <div class="mr-10" style="padding: 3px 15px 0">
- <div class="sm grey">{{ this.$t('endpointName') }}</div>
- <input type="text" v-model="endpointName" class="rk-trace-search-input" />
- </div>
- </div>
- </div>
- <div class="rk-trace-search-more flex-h" v-show="status">
- <div class="mr-15">
- <span class="sm b grey mr-10">{{ this.$t('traceID') }}:</span>
- <input type="text" v-model="traceId" class="rk-trace-search-input dib" />
- </div>
- <div class="mr-15">
- <span class="sm b grey mr-10">{{ this.$t('duration') }}:</span>
- <div class="rk-trace-search-range dib">
- <input class="vm tc" v-model="minTraceDuration" />
- <span class="grey vm">-</span>
- <input class="vm tc" v-model="maxTraceDuration" />
- </div>
- </div>
- <div>
- <span class="sm b grey mr-5">{{ this.$t('timeRange') }}:</span>
- <RkDate class="sm" v-model="time" position="bottom" format="YYYY-MM-DD HH:mm:ss" />
- </div>
- </div>
- </div>
-</template>
-
-<script lang="ts">
- import { Duration, Option } from '@/types/global';
- import { Component, Vue, Watch, Prop } from 'vue-property-decorator';
- import { Action, Getter, Mutation, State } from 'vuex-class';
- import TraceSelect from './trace-select.vue';
-
- @Component({ components: { TraceSelect } })
- export default class TraceSearch extends Vue {
- @State('rocketbot') private rocketbotGlobal: any;
- @State('rocketTrace') private rocketTrace: any;
- @Getter('durationTime') private durationTime: any;
- @Getter('duration') private duration: any;
- @Action('RESET_DURATION') private RESET_DURATION: any;
- @Action('rocketTrace/GET_SERVICES') private GET_SERVICES: any;
- @Action('rocketTrace/GET_INSTANCES') private GET_INSTANCES: any;
- @Action('rocketTrace/GET_TRACELIST') private GET_TRACELIST: any;
- @Action('rocketTrace/SET_TRACE_FORM') private SET_TRACE_FORM: any;
- @Mutation('rocketTrace/SET_TRACE_FORM_ITEM') private SET_TRACE_FORM_ITEM: any;
- @Prop() private service!: Option;
- private time!: Date[];
- private status: boolean = true;
- private maxTraceDuration: string = localStorage.getItem('maxTraceDuration') || '';
- private minTraceDuration: string = localStorage.getItem('minTraceDuration') || '';
- private instance: Option = { label: 'All', key: '' };
- private endpointName: string = localStorage.getItem('endpointName') || '';
- private traceId: string = localStorage.getItem('traceId') || '';
- private traceState: Option = { label: 'All', key: 'ALL' };
-
- private dateFormat(date: Date, step: string) {
- const year = date.getFullYear();
- const monthTemp = date.getMonth() + 1;
- let month: string = `${monthTemp}`;
- if (monthTemp < 10) {
- month = `0${monthTemp}`;
- }
- const dayTemp = date.getDate();
- let day: string = `${dayTemp}`;
- if (dayTemp < 10) {
- day = `0${dayTemp}`;
- }
- if (step === 'DAY' || step === 'MONTH') {
- return `${year}-${month}-${day}`;
- }
- const hourTemp = date.getHours();
- let hour: string = `${hourTemp}`;
- if (hourTemp < 10) {
- hour = `0${hourTemp}`;
- }
- if (step === 'HOUR') {
- return `${year}-${month}-${day} ${hour}`;
- }
- const minuteTemp = date.getMinutes();
- let minute: string = `${minuteTemp}`;
- if (minuteTemp < 10) {
- minute = `0${minuteTemp}`;
- }
- if (step === 'MINUTE') {
- return `${year}-${month}-${day} ${hour}${minute}`;
- }
- }
-
- private globalTimeFormat(time: Date[]) {
- let step = 'MINUTE';
- const unix = Math.round(time[1].getTime()) - Math.round(time[0].getTime());
- if (unix <= 60 * 60 * 1000) {
- step = 'MINUTE';
- } else if (unix <= 24 * 60 * 60 * 1000) {
- step = 'HOUR';
- } else {
- step = 'DAY';
- }
- return {
- start: this.dateFormat(time[0], step),
- end: this.dateFormat(time[1], step),
- step,
- };
- }
-
- private chooseService(i: any) {
- if (this.service.key === i.key) {
- return;
- }
- this.instance = { label: 'All', key: '' };
- this.service = i;
- if (i.key === '') {
- return;
- }
- this.GET_INSTANCES({ duration: this.durationTime, serviceId: i.key });
- }
-
- private chooseStatus(i: any) {
- this.traceState = i;
- }
-
- private getTraceList() {
- const temp: any = {
- queryDuration: this.globalTimeFormat([
- new Date(
- this.time[0].getTime() +
- (parseInt(this.rocketbotGlobal.utc, 10) + new Date().getTimezoneOffset() / 60) * 3600000,
- ),
- new Date(
- this.time[1].getTime() +
- (parseInt(this.rocketbotGlobal.utc, 10) + new Date().getTimezoneOffset() / 60) * 3600000,
- ),
- ]),
- traceState: this.traceState.key,
- paging: { pageNum: 1, pageSize: 15, needTotal: true },
- queryOrder: this.rocketTrace.traceForm.queryOrder,
- };
- temp.serviceId = this.service.key;
- if (this.instance.key) {
- temp.serviceInstanceId = this.instance.key;
- }
- if (this.maxTraceDuration) {
- temp.maxTraceDuration = this.maxTraceDuration;
- localStorage.setItem('maxTraceDuration', this.maxTraceDuration);
- }
- if (this.minTraceDuration) {
- temp.minTraceDuration = this.minTraceDuration;
- localStorage.setItem('minTraceDuration', this.minTraceDuration);
- }
- if (this.endpointName) {
- temp.endpointName = this.endpointName;
- localStorage.setItem('endpointName', this.endpointName);
- }
- if (this.traceId) {
- temp.traceId = this.traceId;
- localStorage.setItem('traceId', this.traceId);
- }
- this.SET_TRACE_FORM(temp);
-
- this.$eventBus.$emit('SET_LOADING_TRUE', () => {
- this.GET_TRACELIST().then(() => {
- this.$eventBus.$emit('SET_LOADING_FALSE');
- });
- });
- }
-
- private clearSearch() {
- this.RESET_DURATION();
- this.status = true;
- this.maxTraceDuration = '';
- localStorage.removeItem('maxTraceDuration');
- this.minTraceDuration = '';
- localStorage.removeItem('minTraceDuration');
- this.instance = { label: 'All', key: '' };
- this.endpointName = '';
- localStorage.removeItem('endpointName');
- this.traceId = '';
- localStorage.removeItem('traceId');
- this.traceState = { label: 'All', key: 'ALL' };
- this.SET_TRACE_FORM_ITEM({ type: 'queryOrder', data: '' });
- this.getTraceList();
- }
-
- @Watch('rocketbotGlobal.durationRow')
- private durationRowWatch(value: Duration) {
- this.time = [value.start, value.end];
- }
-
- private created() {
- this.endpointName = this.$route.query.endpointname
- ? this.$route.query.endpointname.toString()
- : this.endpointName;
- this.traceId = this.$route.query.traceid ? this.$route.query.traceid.toString() : this.traceId;
- this.time = [this.rocketbotGlobal.durationRow.start, this.rocketbotGlobal.durationRow.end];
- }
- private mounted() {
- this.getTraceList();
- this.GET_INSTANCES({
- duration: this.durationTime,
- serviceId: this.service.key,
- });
- }
- }
-</script>
-
-<style lang="scss">
- .rk-trace-search {
- flex-shrink: 0;
- background-color: #333840;
- color: #eee;
- width: 100%;
- padding: 3px 15px 8px;
- }
-
- .rk-trace-search-input {
- border-style: unset;
- outline: 0;
- padding: 2px 5px;
- border-radius: 3px;
- }
-
- .rk-trace-search-range,
- .rk-auto-select {
- border-radius: 3px;
- background-color: #fff;
- padding: 1px;
- border-radius: 3px;
-
- input {
- width: 38px;
- border-style: unset;
- outline: 0;
- }
- }
-
- .rk-trace-search-btn {
- padding: 3px 9px;
- background-color: #484b55;
- border-radius: 4px;
- margin-top: 12px;
-
- &.bg-blue {
- background-color: #448dfe;
- }
- }
-
- .rk-trace-clear-btn {
- padding: 3px 9px;
- background-color: #484b55;
- border-radius: 4px;
- margin-top: 12px;
-
- &.bg-warning {
- background-color: #fbb03b;
- }
- }
-
- .rk-trace-search-more {
- background-color: #484b55;
- padding: 4px 10px;
- border-radius: 3px;
- margin-top: 8px;
- position: relative;
- box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.1);
-
- &:after {
- bottom: 100%;
- right: 30px;
- border: solid transparent;
- content: ' ';
- height: 0;
- width: 0;
- position: absolute;
- pointer-events: none;
- border-color: rgba(0, 0, 0, 0);
- border-bottom-color: #484b55;
- border-width: 8px;
- margin-right: 0px;
- }
- }
-</style>