This is an automated email from the ASF dual-hosted git repository.
wusheng pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-banyandb.git
The following commit(s) were added to refs/heads/main by this push:
new bcb4497b fix(UI): correct the tagProjection for trace query (#817)
bcb4497b is described below
commit bcb4497b64fca6a87b5e834e67c2101dbdd08ee2
Author: Fine0830 <[email protected]>
AuthorDate: Mon Oct 20 14:13:51 2025 +0800
fix(UI): correct the tagProjection for trace query (#817)
---
ui/src/components/IndexRule/index.vue | 1 +
ui/src/components/IndexRuleBinding/index.vue | 1 +
ui/src/components/TopNAggregation/index.vue | 1 +
ui/src/components/Trace/TraceRead.vue | 103 ++++++++++++++++++---------
4 files changed, 73 insertions(+), 33 deletions(-)
diff --git a/ui/src/components/IndexRule/index.vue
b/ui/src/components/IndexRule/index.vue
index 154a00bc..7ab02ce7 100644
--- a/ui/src/components/IndexRule/index.vue
+++ b/ui/src/components/IndexRule/index.vue
@@ -21,6 +21,7 @@
import { reactive } from 'vue';
import { watch, getCurrentInstance } from '@vue/runtime-core';
import { useRoute } from 'vue-router';
+ import { ElMessage } from 'element-plus';
import { getSecondaryDataModel } from '@/api/index';
import FormHeader from '../common/FormHeader.vue';
diff --git a/ui/src/components/IndexRuleBinding/index.vue
b/ui/src/components/IndexRuleBinding/index.vue
index 55bf07c0..1ee933aa 100644
--- a/ui/src/components/IndexRuleBinding/index.vue
+++ b/ui/src/components/IndexRuleBinding/index.vue
@@ -21,6 +21,7 @@
import { reactive } from 'vue';
import { watch, getCurrentInstance } from '@vue/runtime-core';
import { useRoute } from 'vue-router';
+ import { ElMessage } from 'element-plus';
import { getSecondaryDataModel } from '@/api/index';
import FormHeader from '../common/FormHeader.vue';
diff --git a/ui/src/components/TopNAggregation/index.vue
b/ui/src/components/TopNAggregation/index.vue
index b47da9d2..e4650c4f 100644
--- a/ui/src/components/TopNAggregation/index.vue
+++ b/ui/src/components/TopNAggregation/index.vue
@@ -21,6 +21,7 @@
import { reactive, ref } from 'vue';
import { watch } from '@vue/runtime-core';
import { useRoute } from 'vue-router';
+ import { ElMessage } from 'element-plus';
import { jsonToYaml, yamlToJson } from '@/utils/yaml';
import { Search, RefreshRight } from '@element-plus/icons-vue';
import { getTopNAggregationData } from '@/api/index';
diff --git a/ui/src/components/Trace/TraceRead.vue
b/ui/src/components/Trace/TraceRead.vue
index a3a55b62..cc523c64 100644
--- a/ui/src/components/Trace/TraceRead.vue
+++ b/ui/src/components/Trace/TraceRead.vue
@@ -18,7 +18,7 @@
-->
<script setup>
- import { queryTraces, getindexRuleList } from '@/api/index';
+ import { queryTraces, getindexRuleList, getTrace } from '@/api/index';
import { getCurrentInstance } from 'vue';
import { useRoute } from 'vue-router';
import { ElMessage } from 'element-plus';
@@ -40,13 +40,20 @@
group: route.params.group,
tableData: [],
name: route.params.name,
- indexRule: '',
- spanTags: ['traceId', 'spanId'],
+ indexRule: null,
+ spanTags: [],
});
const yamlCode = ref(``);
const selectedSpans = ref([]);
const getTraces = async (params) => {
+ if (!data.indexRule?.metadata?.name) {
+ ElMessage({
+ message: 'No index rule found',
+ type: 'error',
+ });
+ return;
+ }
$loadingCreate();
const response = await queryTraces({ groups: [data.group], name:
data.name, ...params });
$loadingClose();
@@ -55,11 +62,10 @@
ElMessage({
message: response.error.message,
type: 'error',
- duration: 3000,
});
return;
}
- data.spanTags = ['traceId', 'spanId'];
+ data.spanTags = [];
data.tableData = (response.traces || [])
.map((trace) => {
return trace.spans.map((span) => {
@@ -87,19 +93,34 @@
try {
const response = await getindexRuleList(data.group);
if (response.status === 200 && response.data.indexRule &&
response.data.indexRule.length > 0) {
- data.indexRule = response.data.indexRule[0].metadata;
+ data.indexRule = response.data.indexRule[0];
} else {
- data.indexRule = '';
+ data.indexRule = null;
}
} catch (err) {
- console.error('Failed to fetch indexRule:', err);
- data.indexRule = '';
+ data.indexRule = null;
+ ElMessage({
+ message: 'Failed to fetch index rule: ' + (err?.message ||
String(err)),
+ type: 'error',
+ duration: 3000,
+ });
+ }
+ };
+
+ const getTagProjection = async () => {
+ if (!(data.group && data.name)) {
+ return [];
+ }
+ const response = await getTrace(data.group, data.name);
+ if (response.error) {
ElMessage({
- message: 'Failed to fetch index rule: ' + err,
+ message: response.error.message,
type: 'error',
duration: 3000,
});
+ return [];
}
+ return response.trace.tags.map((tag) => tag.name);
};
function searchTraces() {
@@ -137,9 +158,7 @@
return;
}
await getIndexRule();
- if (!data.indexRule) {
- return;
- }
+ const tagProjection = await getTagProjection();
timeRange.value = [new Date(new Date().getTime() - Last15Minutes), new
Date()];
const range = jsonToYaml({
timeRange: {
@@ -152,11 +171,10 @@
name: ${data.name}
offset: 0
limit: 10
-tagProjection: ["start_time", "service_id"]
+tagProjection: ${Array.isArray(tagProjection) && tagProjection ?
JSON.stringify(tagProjection) : '[]'}
orderBy:
- indexRuleName: ${data.indexRule.name}
+ indexRuleName: ${data.indexRule?.metadata?.name || ''}
sort: SORT_DESC`;
-
getTraces(yamlToJson(yamlCode.value).data);
}
@@ -241,7 +259,8 @@ orderBy:
}
for (let i = 0; i < 2; i++) {
if (typeof value !== 'object') {
- return value;
+ const strValue = value.toString();
+ return strValue.length > 100 ? strValue.substring(0, 150) + '...' :
strValue;
}
for (const key in value) {
if (Object.hasOwn(value, key)) {
@@ -254,7 +273,8 @@ orderBy:
}
}
- return value;
+ const strValue = value.toString();
+ return strValue.length > 100 ? strValue.substring(0, 150) + '...' :
strValue;
};
const objectSpanMethod = ({ row, column, rowIndex, columnIndex }) => {
@@ -292,7 +312,7 @@ orderBy:
const { group, name } = route.params;
data.name = name;
data.group = group;
- data.indexRule = '';
+ data.indexRule = null;
initTraceData();
},
{
@@ -339,20 +359,32 @@ orderBy:
>
<el-button :icon="Download" @click="downloadMultipleSpans"> Download
Selected </el-button>
</div>
- <el-table
- :data="data.tableData"
- :border="true"
- style="width: 100%; background-color: #f5f7fa"
- @selection-change="handleSelectionChange"
- :span-method="objectSpanMethod"
- >
- <el-table-column type="selection" width="55" />
- <el-table-column v-for="tag in data.spanTags" :key="tag"
:label="tag" :prop="tag">
- <template #default="scope">
- {{ getTagValue({ value: scope.row[tag] }) }}
- </template>
- </el-table-column>
- </el-table>
+ <div class="table-container">
+ <el-table
+ :data="data.tableData"
+ :border="true"
+ style="width: 100%"
+ @selection-change="handleSelectionChange"
+ :span-method="objectSpanMethod"
+ >
+ <el-table-column type="selection" width="55" fixed />
+ <el-table-column label="traceId" prop="traceId" width="200" fixed>
+ <template #default="scope">
+ {{ getTagValue({ value: scope.row.traceId }) }}
+ </template>
+ </el-table-column>
+ <el-table-column label="spanId" prop="spanId" width="300" fixed>
+ <template #default="scope">
+ {{ getTagValue({ value: scope.row.spanId }) }}
+ </template>
+ </el-table-column>
+ <el-table-column v-for="tag in data.spanTags" :key="tag"
:label="tag" :prop="tag" min-width="200">
+ <template #default="scope">
+ {{ getTagValue({ value: scope.row[tag] }) }}
+ </template>
+ </el-table-column>
+ </el-table>
+ </div>
</div>
<el-empty v-else description="No trace data found" style="margin-top:
20px" />
</el-card>
@@ -375,4 +407,9 @@ orderBy:
word-break: break-all;
font-size: 12px;
}
+
+ .table-container {
+ overflow-x: auto;
+ width: 100%;
+ }
</style>