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>