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 dc88130e Add trace stress test suit (#422)
dc88130e is described below

commit dc88130e8d0516c7989734bdeb505e2d92c1ab71
Author: Gao Hongtao <hanahm...@gmail.com>
AuthorDate: Sat Mar 23 10:12:28 2024 +0800

    Add trace stress test suit (#422)
---
 banyand/measure/block.go                           |  10 +-
 banyand/measure/block_metadata.go                  |   2 +-
 banyand/measure/part_iter.go                       |   9 +-
 banyand/measure/part_iter_test.go                  |   4 +-
 banyand/measure/tstable_test.go                    |   4 +-
 banyand/stream/block.go                            |   9 +-
 banyand/stream/block_metadata.go                   |   2 +-
 banyand/stream/part.go                             |   3 +
 banyand/stream/part_iter.go                        |   9 +-
 banyand/stream/part_iter_test.go                   |   4 +-
 banyand/stream/tstable.go                          |   9 +-
 banyand/stream/tstable_test.go                     |   4 +-
 dist/LICENSE                                       |   6 +
 .../license-github.com-apache-skywalking-cli.txt   | 210 ++++++++++++++++++++
 .../license-github.com-cpuguy83-go-md2man-v2.txt   |  21 ++
 .../license-github.com-machinebox-graphql.txt      | 201 ++++++++++++++++++++
 .../license-github.com-russross-blackfriday-v2.txt |  29 +++
 dist/licenses/license-github.com-urfave-cli-v2.txt |  21 ++
 .../license-skywalking.apache.org-repo-goapi.txt   | 201 ++++++++++++++++++++
 go.mod                                             |  11 +-
 go.sum                                             |  38 ++++
 .../logical/stream/stream_plan_indexscan_local.go  |   5 +
 pkg/test/query/query.go                            | 211 +++++++++++++++++++++
 pkg/test/query/trace.go                            |  88 +++++++++
 test/integration/load/load_suite_test.go           |   2 +-
 test/stress/trace/Makefile                         |  25 +++
 test/stress/trace/docker-compose.yaml              |   8 +-
 test/stress/trace/log4j2.xml                       |   8 +-
 test/stress/trace/segment.tpl.json                 | 106 +++++++++++
 test/stress/trace/trace_suite_test.go              |  57 ++++++
 30 files changed, 1275 insertions(+), 42 deletions(-)

diff --git a/banyand/measure/block.go b/banyand/measure/block.go
index b23e8c34..cf3c2eab 100644
--- a/banyand/measure/block.go
+++ b/banyand/measure/block.go
@@ -214,10 +214,6 @@ func (b *block) unmarshalTagFamily(decoder 
*encoding.BytesBlockDecoder, tfIndex
        }
        bigValuePool.Release(bb)
        b.tagFamilies[tfIndex].name = name
-
-       if len(tagProjection) < 1 {
-               return
-       }
        cc := b.tagFamilies[tfIndex].resizeColumns(len(tagProjection))
        for j := range tagProjection {
                for i := range cfm.columnMetadata {
@@ -413,7 +409,7 @@ type blockCursor struct {
 func (bc *blockCursor) reset() {
        bc.idx = 0
        bc.p = nil
-       bc.bm = blockMetadata{}
+       bc.bm.reset()
        bc.minTimestamp = 0
        bc.maxTimestamp = 0
        bc.tagProjection = bc.tagProjection[:0]
@@ -429,10 +425,10 @@ func (bc *blockCursor) reset() {
        bc.fields.reset()
 }
 
-func (bc *blockCursor) init(p *part, bm blockMetadata, queryOpts queryOptions) 
{
+func (bc *blockCursor) init(p *part, bm *blockMetadata, queryOpts 
queryOptions) {
        bc.reset()
        bc.p = p
-       bc.bm = bm
+       bc.bm.copyFrom(bm)
        bc.minTimestamp = queryOpts.minTimestamp
        bc.maxTimestamp = queryOpts.maxTimestamp
        bc.tagProjection = queryOpts.TagProjection
diff --git a/banyand/measure/block_metadata.go 
b/banyand/measure/block_metadata.go
index 91584760..82e44ca1 100644
--- a/banyand/measure/block_metadata.go
+++ b/banyand/measure/block_metadata.go
@@ -186,7 +186,7 @@ func (bm *blockMetadata) unmarshal(src []byte) ([]byte, 
error) {
        return src, nil
 }
 
-func (bm blockMetadata) less(other blockMetadata) bool {
+func (bm *blockMetadata) less(other *blockMetadata) bool {
        if bm.seriesID == other.seriesID {
                return bm.timestamps.min < other.timestamps.min
        }
diff --git a/banyand/measure/part_iter.go b/banyand/measure/part_iter.go
index aa41f6d1..aef39977 100644
--- a/banyand/measure/part_iter.go
+++ b/banyand/measure/part_iter.go
@@ -35,19 +35,19 @@ import (
 type partIter struct {
        err                  error
        p                    *part
+       curBlock             *blockMetadata
        sids                 []common.SeriesID
        primaryBlockMetadata []primaryBlockMetadata
        bms                  []blockMetadata
        compressedPrimaryBuf []byte
        primaryBuf           []byte
-       curBlock             blockMetadata
        sidIdx               int
        minTimestamp         int64
        maxTimestamp         int64
 }
 
 func (pi *partIter) reset() {
-       pi.curBlock = blockMetadata{}
+       pi.curBlock = nil
        pi.p = nil
        pi.sids = nil
        pi.sidIdx = 0
@@ -60,6 +60,7 @@ func (pi *partIter) reset() {
 
 func (pi *partIter) init(bma *blockMetadataArray, p *part, sids 
[]common.SeriesID, minTimestamp, maxTimestamp int64) {
        pi.reset()
+       pi.curBlock = &blockMetadata{}
        pi.p = p
 
        pi.bms = bma.arr
@@ -227,7 +228,7 @@ func (pi *partIter) findBlock() bool {
                        continue
                }
 
-               pi.curBlock = *bm
+               pi.curBlock = bm
 
                pi.bms = bhs[1:]
                return true
@@ -346,7 +347,7 @@ func (pih *partMergeIterHeap) Len() int {
 
 func (pih *partMergeIterHeap) Less(i, j int) bool {
        x := *pih
-       return x[i].block.bm.less(x[j].block.bm)
+       return x[i].block.bm.less(&x[j].block.bm)
 }
 
 func (pih *partMergeIterHeap) Swap(i, j int) {
diff --git a/banyand/measure/part_iter_test.go 
b/banyand/measure/part_iter_test.go
index 2451c9b0..45c18d3c 100644
--- a/banyand/measure/part_iter_test.go
+++ b/banyand/measure/part_iter_test.go
@@ -124,7 +124,9 @@ func Test_partIter_nextBlock(t *testing.T) {
                                        if pi.curBlock.seriesID == 0 {
                                                t.Errorf("Expected currBlock to 
be initialized, but it was nil")
                                        }
-                                       got = append(got, pi.curBlock)
+                                       var bm blockMetadata
+                                       bm.copyFrom(pi.curBlock)
+                                       got = append(got, bm)
                                }
 
                                if !errors.Is(pi.error(), tt.wantErr) {
diff --git a/banyand/measure/tstable_test.go b/banyand/measure/tstable_test.go
index a37d1a9f..4ea3b81d 100644
--- a/banyand/measure/tstable_test.go
+++ b/banyand/measure/tstable_test.go
@@ -155,7 +155,9 @@ func Test_tstIter(t *testing.T) {
                        if ti.piHeap[0].curBlock.seriesID == 0 {
                                t.Errorf("Expected curBlock to be initialized, 
but it was nil")
                        }
-                       got = append(got, ti.piHeap[0].curBlock)
+                       var bm blockMetadata
+                       bm.copyFrom(ti.piHeap[0].curBlock)
+                       got = append(got, bm)
                }
 
                if !errors.Is(ti.Error(), tt.wantErr) {
diff --git a/banyand/stream/block.go b/banyand/stream/block.go
index ee254902..e8f63200 100644
--- a/banyand/stream/block.go
+++ b/banyand/stream/block.go
@@ -191,9 +191,6 @@ func (b *block) unmarshalTagFamily(decoder 
*encoding.BytesBlockDecoder, tfIndex
        }
        bigValuePool.Release(bb)
        b.tagFamilies[tfIndex].name = name
-       if len(tagProjection) < 1 {
-               return
-       }
        cc := b.tagFamilies[tfIndex].resizeTags(len(tagProjection))
        for j := range tagProjection {
                for i := range tfm.tagMetadata {
@@ -426,7 +423,7 @@ type blockCursor struct {
 func (bc *blockCursor) reset() {
        bc.idx = 0
        bc.p = nil
-       bc.bm = blockMetadata{}
+       bc.bm.reset()
        bc.minTimestamp = 0
        bc.maxTimestamp = 0
        bc.tagProjection = bc.tagProjection[:0]
@@ -441,10 +438,10 @@ func (bc *blockCursor) reset() {
        bc.tagFamilies = tff[:0]
 }
 
-func (bc *blockCursor) init(p *part, bm blockMetadata, queryOpts queryOptions) 
{
+func (bc *blockCursor) init(p *part, bm *blockMetadata, queryOpts 
queryOptions) {
        bc.reset()
        bc.p = p
-       bc.bm = bm
+       bc.bm.copyFrom(bm)
        bc.minTimestamp = queryOpts.minTimestamp
        bc.maxTimestamp = queryOpts.maxTimestamp
        bc.tagProjection = queryOpts.TagProjection
diff --git a/banyand/stream/block_metadata.go b/banyand/stream/block_metadata.go
index 08968b7f..8c8e2771 100644
--- a/banyand/stream/block_metadata.go
+++ b/banyand/stream/block_metadata.go
@@ -190,7 +190,7 @@ func (bm *blockMetadata) unmarshal(src []byte) ([]byte, 
error) {
        return src, nil
 }
 
-func (bm blockMetadata) less(other blockMetadata) bool {
+func (bm *blockMetadata) less(other *blockMetadata) bool {
        if bm.seriesID == other.seriesID {
                return bm.timestamps.min < other.timestamps.min
        }
diff --git a/banyand/stream/part.go b/banyand/stream/part.go
index 59af3462..426f4f5e 100644
--- a/banyand/stream/part.go
+++ b/banyand/stream/part.go
@@ -173,6 +173,9 @@ func (p *part) getElement(seriesID common.SeriesID, 
timestamp common.ItemID, tag
                                break
                        }
                }
+               if targetBlockMetadata.seriesID != seriesID {
+                       continue
+               }
 
                timestamps := make([]int64, 0)
                timestamps = mustReadTimestampsFrom(timestamps, 
&targetBlockMetadata.timestamps, int(targetBlockMetadata.count), p.timestamps)
diff --git a/banyand/stream/part_iter.go b/banyand/stream/part_iter.go
index 1b53439a..e9c24b98 100644
--- a/banyand/stream/part_iter.go
+++ b/banyand/stream/part_iter.go
@@ -35,19 +35,19 @@ import (
 type partIter struct {
        err                  error
        p                    *part
+       curBlock             *blockMetadata
        sids                 []common.SeriesID
        primaryBlockMetadata []primaryBlockMetadata
        bms                  []blockMetadata
        compressedPrimaryBuf []byte
        primaryBuf           []byte
-       curBlock             blockMetadata
        sidIdx               int
        minTimestamp         int64
        maxTimestamp         int64
 }
 
 func (pi *partIter) reset() {
-       pi.curBlock = blockMetadata{}
+       pi.curBlock = nil
        pi.p = nil
        pi.sids = nil
        pi.sidIdx = 0
@@ -60,6 +60,7 @@ func (pi *partIter) reset() {
 
 func (pi *partIter) init(bma *blockMetadataArray, p *part, sids 
[]common.SeriesID, minTimestamp, maxTimestamp int64) {
        pi.reset()
+       pi.curBlock = &blockMetadata{}
        pi.p = p
 
        pi.bms = bma.arr
@@ -227,7 +228,7 @@ func (pi *partIter) findBlock() bool {
                        continue
                }
 
-               pi.curBlock = *bm
+               pi.curBlock = bm
 
                pi.bms = bhs[1:]
                return true
@@ -341,7 +342,7 @@ func (pih *partMergeIterHeap) Len() int {
 
 func (pih *partMergeIterHeap) Less(i, j int) bool {
        x := *pih
-       return x[i].block.bm.less(x[j].block.bm)
+       return x[i].block.bm.less(&x[j].block.bm)
 }
 
 func (pih *partMergeIterHeap) Swap(i, j int) {
diff --git a/banyand/stream/part_iter_test.go b/banyand/stream/part_iter_test.go
index 8a600cc4..5a7d258a 100644
--- a/banyand/stream/part_iter_test.go
+++ b/banyand/stream/part_iter_test.go
@@ -123,7 +123,9 @@ func Test_partIter_nextBlock(t *testing.T) {
                                        if pi.curBlock.seriesID == 0 {
                                                t.Errorf("Expected currBlock to 
be initialized, but it was nil")
                                        }
-                                       got = append(got, pi.curBlock)
+                                       var bm blockMetadata
+                                       bm.copyFrom(pi.curBlock)
+                                       got = append(got, bm)
                                }
 
                                if !errors.Is(pi.error(), tt.wantErr) {
diff --git a/banyand/stream/tstable.go b/banyand/stream/tstable.go
index 272c956c..db28a032 100644
--- a/banyand/stream/tstable.go
+++ b/banyand/stream/tstable.go
@@ -285,9 +285,12 @@ func (tst *tsTable) mustAddElements(es *elements) {
 }
 
 func (tst *tsTable) getElement(seriesID common.SeriesID, timestamp 
common.ItemID, tagProjection []pbv1.TagProjection) (*element, int, error) {
-       tst.RLock()
-       defer tst.RUnlock()
-       for _, p := range tst.currentSnapshot().parts {
+       s := tst.currentSnapshot()
+       if s == nil {
+               return nil, 0, fmt.Errorf("snapshot is absent, cannot find 
element with seriesID %d and timestamp %d", seriesID, timestamp)
+       }
+       defer s.decRef()
+       for _, p := range s.parts {
                if !p.p.containTimestamp(timestamp) {
                        continue
                }
diff --git a/banyand/stream/tstable_test.go b/banyand/stream/tstable_test.go
index de3bef3b..f5bd52b9 100644
--- a/banyand/stream/tstable_test.go
+++ b/banyand/stream/tstable_test.go
@@ -154,7 +154,9 @@ func Test_tstIter(t *testing.T) {
                        if ti.piHeap[0].curBlock.seriesID == 0 {
                                t.Errorf("Expected curBlock to be initialized, 
but it was nil")
                        }
-                       got = append(got, ti.piHeap[0].curBlock)
+                       var bm blockMetadata
+                       bm.copyFrom(ti.piHeap[0].curBlock)
+                       got = append(got, bm)
                }
 
                if !errors.Is(ti.Error(), tt.wantErr) {
diff --git a/dist/LICENSE b/dist/LICENSE
index 06b1cfc3..978452f5 100644
--- a/dist/LICENSE
+++ b/dist/LICENSE
@@ -179,6 +179,7 @@ Apache-2.0 licenses
 ========================================================================
 
     github.com/SkyAPM/badger/v3 v3.0.0-20230511223516-583c6a825854 Apache-2.0
+    github.com/apache/skywalking-cli v0.0.0-20231201043336-d5f3597733aa 
Apache-2.0
     github.com/blevesearch/segment v0.9.1 Apache-2.0
     github.com/blevesearch/vellum v1.0.10 Apache-2.0
     github.com/coreos/go-semver v0.3.1 Apache-2.0
@@ -199,6 +200,7 @@ Apache-2.0 licenses
     github.com/inconshreveable/mousetrap v1.1.0 Apache-2.0
     github.com/jonboulle/clockwork v0.4.0 Apache-2.0
     github.com/kkdai/maglev v0.2.0 Apache-2.0
+    github.com/machinebox/graphql v0.2.2 Apache-2.0
     github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 Apache-2.0
     github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd 
Apache-2.0
     github.com/modern-go/reflect2 v1.0.2 Apache-2.0
@@ -238,6 +240,7 @@ Apache-2.0 licenses
     google.golang.org/grpc v1.60.1 Apache-2.0
     gopkg.in/ini.v1 v1.67.0 Apache-2.0
     gopkg.in/yaml.v2 v2.4.0 Apache-2.0
+    skywalking.apache.org/repo/goapi v0.0.0-20230712035303-201c1fb2d6ec 
Apache-2.0
 
 ========================================================================
 Apache-2.0 and BSD-3-Clause licenses
@@ -251,6 +254,7 @@ BSD-2-Clause licenses
 
     github.com/magiconair/properties v1.8.7 BSD-2-Clause
     github.com/pkg/errors v0.9.1 BSD-2-Clause
+    github.com/russross/blackfriday/v2 v2.1.0 BSD-2-Clause
 
 ========================================================================
 BSD-2-Clause and ISC licenses
@@ -321,6 +325,7 @@ MIT licenses
     github.com/cenkalti/backoff/v4 v4.2.1 MIT
     github.com/cespare/xxhash v1.1.0 MIT
     github.com/cespare/xxhash/v2 v2.2.0 MIT
+    github.com/cpuguy83/go-md2man/v2 v2.0.3 MIT
     github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 MIT
     github.com/dustin/go-humanize v1.0.1 MIT
     github.com/go-chi/chi/v5 v5.0.11 MIT
@@ -347,6 +352,7 @@ MIT licenses
     github.com/stretchr/testify v1.8.4 MIT
     github.com/subosito/gotenv v1.6.0 MIT
     github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75 MIT
+    github.com/urfave/cli/v2 v2.3.0 MIT
     github.com/xiang90/probing v0.0.0-20221125231312-a49e3df8f510 MIT
     github.com/yusufpapurcu/wmi v1.2.3 MIT
     github.com/zenizh/go-capturer v0.0.0-20211219060012-52ea6c8fed04 MIT
diff --git a/dist/licenses/license-github.com-apache-skywalking-cli.txt 
b/dist/licenses/license-github.com-apache-skywalking-cli.txt
new file mode 100644
index 00000000..5a80c2b5
--- /dev/null
+++ b/dist/licenses/license-github.com-apache-skywalking-cli.txt
@@ -0,0 +1,210 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright {yyyy} {name of copyright owner}
+
+   Licensed 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.
+
+========================================================================
+Apache 2.0 licenses
+========================================================================
+
+The following components are provided under the Apache License. See project 
link for details.
+The text of each license is the standard Apache 2.0 license.
+
+    pkg/display/graph/flamegraph files from 
jvm-profiling-tools/async-profiler: 
https://github.com/jvm-profiling-tools/async-profiler Apache-2.0
\ No newline at end of file
diff --git a/dist/licenses/license-github.com-cpuguy83-go-md2man-v2.txt 
b/dist/licenses/license-github.com-cpuguy83-go-md2man-v2.txt
new file mode 100644
index 00000000..1cade6ce
--- /dev/null
+++ b/dist/licenses/license-github.com-cpuguy83-go-md2man-v2.txt
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Brian Goff
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/dist/licenses/license-github.com-machinebox-graphql.txt 
b/dist/licenses/license-github.com-machinebox-graphql.txt
new file mode 100644
index 00000000..9b0dfaa8
--- /dev/null
+++ b/dist/licenses/license-github.com-machinebox-graphql.txt
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright 2017 Machine Box, Ltd.
+
+   Licensed 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.
diff --git a/dist/licenses/license-github.com-russross-blackfriday-v2.txt 
b/dist/licenses/license-github.com-russross-blackfriday-v2.txt
new file mode 100644
index 00000000..2885af36
--- /dev/null
+++ b/dist/licenses/license-github.com-russross-blackfriday-v2.txt
@@ -0,0 +1,29 @@
+Blackfriday is distributed under the Simplified BSD License:
+
+> Copyright © 2011 Russ Ross
+> All rights reserved.
+>
+> Redistribution and use in source and binary forms, with or without
+> modification, are permitted provided that the following conditions
+> are met:
+>
+> 1.  Redistributions of source code must retain the above copyright
+>     notice, this list of conditions and the following disclaimer.
+>
+> 2.  Redistributions in binary form must reproduce the above
+>     copyright notice, this list of conditions and the following
+>     disclaimer in the documentation and/or other materials provided with
+>     the distribution.
+>
+> THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+> "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+> LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+> FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+> COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+> INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+> BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+> LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+> CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+> LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+> ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+> POSSIBILITY OF SUCH DAMAGE.
diff --git a/dist/licenses/license-github.com-urfave-cli-v2.txt 
b/dist/licenses/license-github.com-urfave-cli-v2.txt
new file mode 100644
index 00000000..42a597e2
--- /dev/null
+++ b/dist/licenses/license-github.com-urfave-cli-v2.txt
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2016 Jeremy Saenz & Contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/dist/licenses/license-skywalking.apache.org-repo-goapi.txt 
b/dist/licenses/license-skywalking.apache.org-repo-goapi.txt
new file mode 100644
index 00000000..261eeb9e
--- /dev/null
+++ b/dist/licenses/license-skywalking.apache.org-repo-goapi.txt
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
diff --git a/go.mod b/go.mod
index bfaf6890..607bef95 100644
--- a/go.mod
+++ b/go.mod
@@ -4,6 +4,7 @@ go 1.21
 
 require (
        github.com/RoaringBitmap/roaring v1.7.0
+       github.com/apache/skywalking-cli v0.0.0-20231201043336-d5f3597733aa
        github.com/benbjohnson/clock v1.3.0
        github.com/blugelabs/bluge v0.2.2
        github.com/cespare/xxhash v1.1.0
@@ -20,6 +21,7 @@ require (
        github.com/hashicorp/golang-lru v1.0.2
        github.com/hashicorp/golang-lru/v2 v2.0.7
        github.com/kkdai/maglev v0.2.0
+       github.com/montanaflynn/stats v0.7.1
        github.com/oklog/run v1.1.0
        github.com/onsi/ginkgo/v2 v2.13.2
        github.com/onsi/gomega v1.30.0
@@ -30,6 +32,7 @@ require (
        github.com/spf13/pflag v1.0.5
        github.com/spf13/viper v1.18.2
        github.com/stretchr/testify v1.8.4
+       github.com/urfave/cli/v2 v2.3.0
        github.com/xhit/go-str2duration/v2 v2.1.0
        github.com/zenizh/go-capturer v0.0.0-20211219060012-52ea6c8fed04
        go.etcd.io/etcd/client/v3 v3.5.11
@@ -43,6 +46,13 @@ require (
        google.golang.org/grpc v1.60.1
        google.golang.org/protobuf v1.31.0
        sigs.k8s.io/yaml v1.4.0
+       skywalking.apache.org/repo/goapi v0.0.0-20230712035303-201c1fb2d6ec
+)
+
+require (
+       github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect
+       github.com/machinebox/graphql v0.2.2 // indirect
+       github.com/russross/blackfriday/v2 v2.1.0 // indirect
 )
 
 require (
@@ -97,7 +107,6 @@ require (
        github.com/mitchellh/mapstructure v1.5.0 // indirect
        github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // 
indirect
        github.com/modern-go/reflect2 v1.0.2 // indirect
-       github.com/montanaflynn/stats v0.7.1
        github.com/mschoch/smat v0.2.0 // indirect
        github.com/pelletier/go-toml/v2 v2.1.1 // indirect
        github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // 
indirect
diff --git a/go.sum b/go.sum
index 3cd60e04..7847d402 100644
--- a/go.sum
+++ b/go.sum
@@ -17,6 +17,8 @@ github.com/SkyAPM/clock v1.3.1-0.20220809233656-dc7607c94a97 
h1:FKuhJ+6n/DHspGeL
 github.com/SkyAPM/clock v1.3.1-0.20220809233656-dc7607c94a97/go.mod 
h1:2xGRl9H1pllhxTbEGO1W3gDkip8P9GQaHPni/wpdR44=
 github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod 
h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
 github.com/antihax/optional v1.0.0/go.mod 
h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
+github.com/apache/skywalking-cli v0.0.0-20231201043336-d5f3597733aa 
h1:BaY0aGFDrBZ2Pggbj3cG7WmvN5hOWoYmnKMD+FCZdoc=
+github.com/apache/skywalking-cli v0.0.0-20231201043336-d5f3597733aa/go.mod 
h1:p6h6J8MbHs9pAQXQaVF3CqEZzckoTrHmDrd6/ZEkYzc=
 github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod 
h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
 github.com/axiomhq/hyperloglog v0.0.0-20191112132149-a4c4c47bc57f/go.mod 
h1:2stgcRjl6QmW+gU2h5E7BQXg4HU0gzxKWDuT5HviN9s=
 github.com/axiomhq/hyperloglog v0.0.0-20230201085229-3ddf4bad03dc 
h1:Keo7wQ7UODUaHcEi7ltENhbAK2VgZjfat6mLy03tQzo=
@@ -53,6 +55,8 @@ github.com/cespare/xxhash/v2 v2.2.0 
h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj
 github.com/cespare/xxhash/v2 v2.2.0/go.mod 
h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
 github.com/client9/misspell v0.3.4/go.mod 
h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
 github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod 
h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
+github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod 
h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
+github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod 
h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
 github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 
h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k=
 github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod 
h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
 github.com/cockroachdb/datadriven v1.0.2 
h1:H9MtNqVoVhvd9nCBwOyDjUEdZCREqbIdCJD93PBm/jA=
@@ -65,6 +69,8 @@ github.com/coreos/go-semver v0.3.1/go.mod 
h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03V
 github.com/coreos/go-systemd/v22 v22.5.0 
h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
 github.com/coreos/go-systemd/v22 v22.5.0/go.mod 
h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
 github.com/cpuguy83/go-md2man v1.0.10/go.mod 
h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
+github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod 
h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
+github.com/cpuguy83/go-md2man/v2 v2.0.3 
h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM=
 github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod 
h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
 github.com/davecgh/go-spew v1.1.0/go.mod 
h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1/go.mod 
h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -88,6 +94,9 @@ github.com/emirpasic/gods v1.18.1/go.mod 
h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FM
 github.com/envoyproxy/go-control-plane v0.9.0/go.mod 
h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
 github.com/envoyproxy/go-control-plane 
v0.9.1-0.20191026205805-5f8ba28d4473/go.mod 
h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
 github.com/envoyproxy/go-control-plane v0.9.4/go.mod 
h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
+github.com/envoyproxy/go-control-plane 
v0.9.9-0.20201210154907-fd9021fe5dad/go.mod 
h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
+github.com/envoyproxy/go-control-plane 
v0.9.9-0.20210217033140-668b12f5399d/go.mod 
h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
+github.com/envoyproxy/go-control-plane 
v0.9.9-0.20210512163311-63b5d3c536b0/go.mod 
h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
 github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod 
h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
 github.com/envoyproxy/protoc-gen-validate v1.0.2 
h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA=
 github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod 
h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE=
@@ -139,8 +148,10 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod 
h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU
 github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod 
h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
 github.com/golang/protobuf v1.4.0/go.mod 
h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
 github.com/golang/protobuf v1.4.1/go.mod 
h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
+github.com/golang/protobuf v1.4.2/go.mod 
h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
 github.com/golang/protobuf v1.4.3/go.mod 
h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
 github.com/golang/protobuf v1.5.0/go.mod 
h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.2/go.mod 
h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
 github.com/golang/protobuf v1.5.3 
h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
 github.com/golang/protobuf v1.5.3/go.mod 
h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
 github.com/golang/snappy v0.0.3/go.mod 
h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
@@ -220,9 +231,13 @@ github.com/leesper/go_rng 
v0.0.0-20190531154944-a612b043e353/go.mod h1:N0SVk0uhy
 github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod 
h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
 github.com/lufia/plan9stats v0.0.0-20231016141302-07b5767bb0ed 
h1:036IscGBfJsFIgJQzlui7nK1Ncm0tp2ktmPj8xO4N/0=
 github.com/lufia/plan9stats v0.0.0-20231016141302-07b5767bb0ed/go.mod 
h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k=
+github.com/machinebox/graphql v0.2.2 
h1:dWKpJligYKhYKO5A2gvNhkJdQMNZeChZYyBbrZkBZfo=
+github.com/machinebox/graphql v0.2.2/go.mod 
h1:F+kbVMHuwrQ5tYgU9JXlnskM8nOaFxCAEolaQybkjWA=
 github.com/magiconair/properties v1.8.0/go.mod 
h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
 github.com/magiconair/properties v1.8.7 
h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
 github.com/magiconair/properties v1.8.7/go.mod 
h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
+github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE=
+github.com/matryer/is v1.4.0/go.mod 
h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
 github.com/mattn/go-colorable v0.1.13 
h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
 github.com/mattn/go-colorable v0.1.13/go.mod 
h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
 github.com/mattn/go-isatty v0.0.16/go.mod 
h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
@@ -281,6 +296,8 @@ github.com/rs/xid v1.5.0/go.mod 
h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
 github.com/rs/zerolog v1.31.0 h1:FcTR3NnLWW+NnTwwhFWiJSZr4ECLpqCm6QsEnyvbV4A=
 github.com/rs/zerolog v1.31.0/go.mod 
h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
 github.com/russross/blackfriday v1.5.2/go.mod 
h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
+github.com/russross/blackfriday/v2 v2.0.1/go.mod 
h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
+github.com/russross/blackfriday/v2 v2.1.0 
h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
 github.com/russross/blackfriday/v2 v2.1.0/go.mod 
h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 github.com/sagikazarmark/locafero v0.4.0 
h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=
 github.com/sagikazarmark/locafero v0.4.0/go.mod 
h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
@@ -292,6 +309,7 @@ github.com/shoenig/go-m1cpu v0.1.6 
h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFt
 github.com/shoenig/go-m1cpu v0.1.6/go.mod 
h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
 github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
 github.com/shoenig/test v0.6.4/go.mod 
h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
+github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod 
h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
 github.com/sirupsen/logrus v1.4.2/go.mod 
h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
 github.com/sirupsen/logrus v1.8.1/go.mod 
h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
 github.com/sirupsen/logrus v1.9.3 
h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
@@ -325,6 +343,7 @@ github.com/stretchr/objx v0.5.0/go.mod 
h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpE
 github.com/stretchr/testify v1.2.2/go.mod 
h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 github.com/stretchr/testify v1.3.0/go.mod 
h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
 github.com/stretchr/testify v1.4.0/go.mod 
h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/stretchr/testify v1.5.1/go.mod 
h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
 github.com/stretchr/testify v1.6.1/go.mod 
h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.7.0/go.mod 
h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.7.1/go.mod 
h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
@@ -343,6 +362,8 @@ github.com/tklauser/numcpus v0.7.0/go.mod 
h1:bb6dMVcj8A42tSE7i32fsIUCbQNllK5iDgu
 github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75 
h1:6fotK7otjonDflCTK0BCfls4SPy3NcCVb5dqqmbRknE=
 github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75/go.mod 
h1:KO6IkyS8Y3j8OdNO85qEYBsRPuteD+YciPomcXdrMnk=
 github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod 
h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
+github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M=
+github.com/urfave/cli/v2 v2.3.0/go.mod 
h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
 github.com/xhit/go-str2duration/v2 v2.1.0 
h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc=
 github.com/xhit/go-str2duration/v2 v2.1.0/go.mod 
h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU=
 github.com/xiang90/probing v0.0.0-20221125231312-a49e3df8f510 
h1:S2dVYn90KE98chqDkyE9Z4N61UnQd+KOfgp5Iu53llk=
@@ -350,6 +371,7 @@ github.com/xiang90/probing 
v0.0.0-20221125231312-a49e3df8f510/go.mod h1:UETIi67q
 github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod 
h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
 github.com/yuin/goldmark v1.1.27/go.mod 
h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.2.1/go.mod 
h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.3.5/go.mod 
h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
 github.com/yuin/goldmark v1.4.13/go.mod 
h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
 github.com/yusufpapurcu/wmi v1.2.3 
h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw=
 github.com/yusufpapurcu/wmi v1.2.3/go.mod 
h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
@@ -394,6 +416,7 @@ go.opentelemetry.io/otel/sdk v1.21.0 
h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZ
 go.opentelemetry.io/otel/sdk v1.21.0/go.mod 
h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E=
 go.opentelemetry.io/otel/trace v1.21.0 
h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc=
 go.opentelemetry.io/otel/trace v1.21.0/go.mod 
h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ=
+go.opentelemetry.io/proto/otlp v0.7.0/go.mod 
h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
 go.opentelemetry.io/proto/otlp v1.0.0 
h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I=
 go.opentelemetry.io/proto/otlp v1.0.0/go.mod 
h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM=
 go.uber.org/atomic v1.7.0/go.mod 
h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
@@ -427,8 +450,11 @@ golang.org/x/lint 
v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTk
 golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod 
h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
 golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod 
h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
 golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod 
h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod 
h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
+golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod 
h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
 golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod 
h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
 golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
 golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
@@ -446,6 +472,7 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod 
h1:sp8m0HH+o8qH0wwXwY
 golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod 
h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod 
h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod 
h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod 
h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
 golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9/go.mod 
h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod 
h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
 golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
@@ -464,6 +491,7 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod 
h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod 
h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod 
h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod 
h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod 
h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod 
h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod 
h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -479,6 +507,7 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod 
h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod 
h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod 
h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod 
h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod 
h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod 
h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod 
h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod 
h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -504,6 +533,7 @@ golang.org/x/term v0.8.0/go.mod 
h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
 golang.org/x/term v0.13.0/go.mod 
h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
 golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
@@ -523,8 +553,10 @@ golang.org/x/tools 
v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3
 golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod 
h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
 golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod 
h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod 
h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod 
h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
 golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod 
h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
 golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod 
h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.1.3/go.mod 
h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 golang.org/x/tools v0.1.12/go.mod 
h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
 golang.org/x/tools v0.6.0/go.mod 
h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
 golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA=
@@ -548,6 +580,7 @@ google.golang.org/genproto 
v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98
 google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod 
h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
 google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod 
h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
 google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod 
h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
+google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod 
h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24=
 google.golang.org/genproto v0.0.0-20231212172506-995d672761c0 
h1:YJ5pD9rF8o9Qtta0Cmy9rdBwkSjrTCT6XTiUQVOtIos=
 google.golang.org/genproto v0.0.0-20231212172506-995d672761c0/go.mod 
h1:l/k7rMz0vFTBPy+tFSGvXEd3z+BcoG1k7EHbqm+YBsY=
 google.golang.org/genproto/googleapis/api v0.0.0-20231212172506-995d672761c0 
h1:s1w3X6gQxwrLEpxnLd/qXTVLgQE2yXwaOaoa6IlY/+o=
@@ -562,6 +595,9 @@ google.golang.org/grpc v1.27.0/go.mod 
h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8
 google.golang.org/grpc v1.29.1/go.mod 
h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
 google.golang.org/grpc v1.33.1/go.mod 
h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
 google.golang.org/grpc v1.33.2/go.mod 
h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
+google.golang.org/grpc v1.36.0/go.mod 
h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
+google.golang.org/grpc v1.38.0/go.mod 
h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
+google.golang.org/grpc v1.40.0/go.mod 
h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
 google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU=
 google.golang.org/grpc v1.60.1/go.mod 
h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM=
 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod 
h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
@@ -600,3 +636,5 @@ honnef.co/go/tools 
v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
 rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
 sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
 sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
+skywalking.apache.org/repo/goapi v0.0.0-20230712035303-201c1fb2d6ec 
h1:s+C9qfKkom7OYFKo8sGtXlXk6jU8DjRiI6bh/CgrpD4=
+skywalking.apache.org/repo/goapi v0.0.0-20230712035303-201c1fb2d6ec/go.mod 
h1:onFubXaIoY/2FTRVrLMqCTlaNq4SilAEwF/2G0IcaBw=
diff --git a/pkg/query/logical/stream/stream_plan_indexscan_local.go 
b/pkg/query/logical/stream/stream_plan_indexscan_local.go
index a8a90110..194b3f97 100644
--- a/pkg/query/logical/stream/stream_plan_indexscan_local.go
+++ b/pkg/query/logical/stream/stream_plan_indexscan_local.go
@@ -172,6 +172,7 @@ func buildElementsFromColumnResult(r 
*pbv1.StreamColumnResult) (elements []*stre
 }
 
 func buildElementsFromQueryResults(results []pbv1.StreamQueryResult) (elements 
[]*streamv1.Element) {
+       deduplication := make(map[string]struct{})
        for _, result := range results {
                for {
                        r := result.Pull()
@@ -179,6 +180,10 @@ func buildElementsFromQueryResults(results 
[]pbv1.StreamQueryResult) (elements [
                                break
                        }
                        for i := range r.Timestamps {
+                               if _, ok := deduplication[r.ElementIDs[i]]; ok {
+                                       continue
+                               }
+                               deduplication[r.ElementIDs[i]] = struct{}{}
                                e := &streamv1.Element{
                                        Timestamp: timestamppb.New(time.Unix(0, 
r.Timestamps[i])),
                                        ElementId: r.ElementIDs[i],
diff --git a/pkg/test/query/query.go b/pkg/test/query/query.go
new file mode 100644
index 00000000..489cb034
--- /dev/null
+++ b/pkg/test/query/query.go
@@ -0,0 +1,211 @@
+// Licensed to 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. Apache Software Foundation (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.
+
+// Package query provides functions for analyzing and collecting metrics.
+package query
+
+import (
+       "encoding/csv"
+       "fmt"
+       "os"
+       "path/filepath"
+       "strconv"
+       "time"
+
+       "github.com/montanaflynn/stats"
+
+       "github.com/apache/skywalking-banyandb/pkg/logger"
+)
+
+const (
+       metricsFile = "data.csv"
+       resultFile  = "result.csv"
+)
+
+func init() {
+       _ = logger.Init(logger.Logging{
+               Env:   "dev",
+               Level: "debug",
+       })
+}
+
+func analyze(metricNames []string, rootPath string) {
+       file, err := os.Open(filepath.Join(rootPath, metricsFile))
+       if err != nil {
+               fmt.Println("Error opening metrics file:", err)
+               return
+       }
+       defer file.Close()
+
+       reader := csv.NewReader(file)
+       records, err := reader.ReadAll()
+       if err != nil {
+               fmt.Println("Error reading metrics file:", err)
+               return
+       }
+       if reader == nil {
+               fmt.Println("No records found in metrics file.")
+               return
+       }
+
+       // Transpose the records to handle column-based data.
+       transposed := transpose(records)
+
+       // Open the results file.
+       resultsFile, err := os.OpenFile(filepath.Join(rootPath, resultFile), 
os.O_CREATE|os.O_WRONLY, 0o644)
+       if err != nil {
+               fmt.Println("Error opening results file:", err)
+               return
+       }
+       defer resultsFile.Close()
+       if err = resultsFile.Truncate(0); err != nil {
+               fmt.Println("Error truncating results file:", err)
+               return
+       }
+       // Write the header to the results file.
+       writeHeader(resultsFile)
+
+       for i, record := range transposed {
+               // Convert the records to a slice of floats for analysis.
+               data := make([]float64, 0, len(record))
+               for _, r := range record {
+                       d := atof(r) // Convert the string to a float.
+                       if d < 0 {
+                               continue
+                       }
+                       data = append(data, d)
+               }
+
+               // Calculate the statistics.
+               min, _ := stats.Min(data)
+               max, _ := stats.Max(data)
+               mean, _ := stats.Mean(data)
+               median, _ := stats.Median(data)
+               p95, _ := stats.Percentile(data, 95)
+
+               // Write the results to another file and print them to the 
console.
+               writeResults(resultsFile, metricNames[i], min, max, mean, 
median, p95)
+       }
+}
+
+func writeHeader(file *os.File) {
+       header := "Metric Name, Min, Max, Mean, Median, P95\n"
+       _, err := file.WriteString(header)
+       if err != nil {
+               fmt.Println("Error writing to results file:", err)
+               return
+       }
+}
+
+func writeResults(file *os.File, metricName string, min, max, mean, median, 
p95 float64) {
+       results := fmt.Sprintf("%s, %f, %f, %f, %f, %f\n",
+               metricName, min, max, mean, median, p95)
+
+       _, err := file.WriteString(results)
+       if err != nil {
+               fmt.Println("Error writing to results file:", err)
+               return
+       }
+
+       fmt.Print(results)
+}
+
+func transpose(slice [][]string) [][]string {
+       xl := len(slice[0])
+       yl := len(slice)
+       result := make([][]string, xl)
+       for i := range result {
+               result[i] = make([]string, yl)
+       }
+       for i, row := range slice {
+               for j, col := range row {
+                       result[j][i] = col
+               }
+       }
+       return result
+}
+
+func atof(s string) float64 {
+       value, err := strconv.ParseFloat(s, 64)
+       if err != nil {
+               panic(err)
+       }
+       return value
+}
+
+type scrape func() ([]float64, error)
+
+func collect(rootPath string, scrape scrape, interval time.Duration, closeCh 
<-chan struct{}) {
+       file, err := os.OpenFile(filepath.Join(rootPath, metricsFile), 
os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644)
+       if err != nil {
+               panic(err)
+       }
+       defer file.Close()
+       if err = file.Truncate(0); err != nil {
+               panic(err)
+       }
+       lastCollectTime := time.Now()
+       for {
+               metrics, err := scrape()
+               if err != nil {
+                       logger.Errorf("Error scraping metrics: %v", err)
+                       select {
+                       case <-closeCh:
+                               return
+                       case <-time.After(5 * time.Second):
+                       }
+                       continue
+               }
+
+               select {
+               case <-closeCh:
+                       return
+               default:
+               }
+               if time.Since(lastCollectTime) < time.Minute {
+                       select {
+                       case <-closeCh:
+                               return
+                       case <-time.After(interval):
+                       }
+                       continue
+               }
+               lastCollectTime = time.Now()
+
+               err = writeMetrics(file, metrics)
+               if err != nil {
+                       fmt.Println("Error writing metrics:", err)
+               }
+               select {
+               case <-closeCh:
+                       return
+               case <-time.After(interval):
+               }
+       }
+}
+
+func writeMetrics(file *os.File, metrics []float64) error {
+       writer := csv.NewWriter(file)
+       defer writer.Flush()
+
+       record := make([]string, len(metrics))
+       for i := range metrics {
+               record[i] = fmt.Sprintf("%f", metrics[i])
+       }
+
+       return writer.Write(record)
+}
diff --git a/pkg/test/query/trace.go b/pkg/test/query/trace.go
new file mode 100644
index 00000000..3c4834f1
--- /dev/null
+++ b/pkg/test/query/trace.go
@@ -0,0 +1,88 @@
+// Licensed to 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. Apache Software Foundation (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.
+
+package query
+
+import (
+       "flag"
+       "fmt"
+       "os"
+       "path"
+       "time"
+
+       "github.com/apache/skywalking-cli/pkg/graphql/trace"
+       "github.com/apache/skywalking-cli/pkg/graphql/utils"
+       "github.com/urfave/cli/v2"
+       api "skywalking.apache.org/repo/goapi/query"
+)
+
+// TraceListOrderByDuration verifies the trace list order by duration.
+func TraceListOrderByDuration(basePath string, timeout time.Duration, fs 
*flag.FlagSet) {
+       basePath = path.Join(basePath, "trace-duration")
+       err := os.MkdirAll(basePath, 0o755)
+       if err != nil {
+               panic(err)
+       }
+       stopCh := make(chan struct{})
+       go func() {
+               time.Sleep(timeout)
+               close(stopCh)
+       }()
+       collect(basePath, func() ([]float64, error) {
+               d, err := traceList(api.QueryOrderByDuration, fs)
+               if err != nil {
+                       return nil, err
+               }
+               return []float64{d.Seconds()}, nil
+       }, 500*time.Millisecond, stopCh)
+       analyze([]string{"result"}, basePath)
+}
+
+const (
+       defaultPageSize = 15
+)
+
+func traceList(order api.QueryOrder, fs *flag.FlagSet) (time.Duration, error) {
+       ctx := cli.NewContext(cli.NewApp(), fs, nil)
+       duration := api.Duration{
+               Start: time.Now().Add(-30 * 
time.Minute).Format(utils.StepFormats[api.StepMinute]),
+               End:   time.Now().Format(utils.StepFormats[api.StepMinute]),
+               Step:  api.StepMinute,
+       }
+       pageNum := 1
+       serviceID := ctx.String("service-id")
+       condition := &api.TraceQueryCondition{
+               ServiceID:     &serviceID,
+               QueryDuration: &duration,
+               QueryOrder:    order,
+               TraceState:    api.TraceStateAll,
+               Paging: &api.Pagination{
+                       PageNum:  &pageNum,
+                       PageSize: defaultPageSize,
+               },
+       }
+       start := time.Now()
+       result, err := trace.Traces(ctx, condition)
+       elapsed := time.Since(start)
+       if err != nil {
+               return 0, err
+       }
+       if len(result.Traces) < 1 {
+               return 0, fmt.Errorf("no result")
+       }
+       return elapsed, nil
+}
diff --git a/test/integration/load/load_suite_test.go 
b/test/integration/load/load_suite_test.go
index 65011cd4..30f07696 100644
--- a/test/integration/load/load_suite_test.go
+++ b/test/integration/load/load_suite_test.go
@@ -44,7 +44,7 @@ func TestIntegrationLoad(t *testing.T) {
        RunSpecs(t, "Integration Load Suite", Label("integration", "slow"))
 }
 
-var _ = Describe("Test Suite", func() {
+var _ = Describe("Load Test Suit", func() {
        var (
                connection *grpc.ClientConn
                now        time.Time
diff --git a/test/stress/trace/Makefile b/test/stress/trace/Makefile
index ca57b2db..f331107e 100644
--- a/test/stress/trace/Makefile
+++ b/test/stress/trace/Makefile
@@ -26,6 +26,10 @@ endif
 
 cli_env := DOCKER_BUILDKIT=1 USER_ID=$(shell id -u) GROUP_ID=$(shell id -g)
 
+SIZE ?= 2
+
+QPS ?= 10
+
 .PHONY: clean
 clean:
        rm -rf /tmp/banyandb-stress-trace
@@ -37,3 +41,24 @@ up: clean
 .PHONY: down
 down:
        docker compose down
+
+.PHONY: test_traffic
+test_traffic:
+       curl -XPOST 
'http://localhost:12800/mock-data/segments/tasks?size=$(SIZE)' -H'Content-Type: 
application/json' -d "@segment.tpl.json"
+
+.PHONY: up_traffic
+up_traffic:
+       curl -XPOST 
'http://localhost:12800/mock-data/segments/tasks?qps=$(QPS)' -H'Content-Type: 
application/json' -d "@segment.tpl.json"
+
+.PHONY: ls_traffic
+ls_traffic:
+       curl -XGET 'http://localhost:12800/mock-data/segments/tasks'
+
+.PHONY: rm_traffic
+rm_traffic:
+       curl -XDELETE 'http://localhost:12800/mock-data/segments/tasks'
+
+.PHONY: test_query
+test_query:
+       go test -v -timeout 1h -run TestQuery ./...
+       
\ No newline at end of file
diff --git a/test/stress/trace/docker-compose.yaml 
b/test/stress/trace/docker-compose.yaml
index 9554ddf3..7ea06551 100644
--- a/test/stress/trace/docker-compose.yaml
+++ b/test/stress/trace/docker-compose.yaml
@@ -53,15 +53,11 @@ services:
     extends:
       file: ../../docker/base-compose.yml
       service: oap
+    image: hanahmily/data-generator:latest
     environment:
       SW_STORAGE: banyandb
     ports:
-      - 12800
-    deploy:
-      resources:
-        limits:
-          cpus: "4"
-          memory: 4G
+      - 12800:12800
     volumes:
       - ./log4j2.xml:/skywalking/config/log4j2.xml
     networks:
diff --git a/test/stress/trace/log4j2.xml b/test/stress/trace/log4j2.xml
index e3174f57..1a9ceccf 100644
--- a/test/stress/trace/log4j2.xml
+++ b/test/stress/trace/log4j2.xml
@@ -24,10 +24,10 @@
         </Console>
     </Appenders>
     <Loggers>
-        <logger 
name="org.apache.skywalking.oap.server.storage.plugin.banyandb" level="DEBUG"/>
-        <logger name="org.apache.skywalking.oap.server.core.storage.ttl" 
level="DEBUG"/>
-        <logger name="org.apache.skywalking.restapi" level="DEBUG"/>
-        <Root level="INFO">
+        <logger 
name="org.apache.skywalking.oap.server.storage.plugin.banyandb" level="WARN"/>
+        <logger name="org.apache.skywalking.oap.server.core.storage.ttl" 
level="INFO"/>
+        <logger name="org.apache.skywalking.restapi" level="INFO"/>
+        <Root level="WARN">
             <AppenderRef ref="Console"/>
         </Root>
     </Loggers>
diff --git a/test/stress/trace/segment.tpl.json 
b/test/stress/trace/segment.tpl.json
new file mode 100644
index 00000000..3597234a
--- /dev/null
+++ b/test/stress/trace/segment.tpl.json
@@ -0,0 +1,106 @@
+{
+  "traceId": {
+    "type": "uuid",
+    "changingFrequency": "1"
+  },
+  "serviceInstanceName": {
+    "type": "randomString",
+    "length": "10",
+    "letters": true,
+    "numbers": true,
+    "domainSize": 10
+  },
+  "serviceName": {
+    "type": "fixedString",
+    "value": "service_"
+  },
+  "segments": {
+    "type": "randomList",
+    "size": 5,
+    "item": {
+      "endpointName": {
+        "type": "randomString",
+        "length": "10",
+        "prefix": "test_",
+        "letters": true,
+        "numbers": true,
+        "domainSize": 10
+      },
+      "error": {
+        "type": "randomInt",
+        "min": 1,
+        "max": 1
+      },
+      "tags": {
+        "type": "randomList",
+        "size": 5,
+        "item": {
+          "key": {
+            "type": "randomString",
+            "length": "10",
+            "prefix": "test_tag_",
+            "letters": true,
+            "numbers": true,
+            "domainSize": 5
+          },
+          "value": {
+            "type": "randomString",
+            "length": "10",
+            "prefix": "test_value_",
+            "letters": true,
+            "numbers": true,
+            "domainSize": 10
+          }
+        }
+      },
+      "spans": {
+        "type": "randomList",
+        "size": 5,
+        "item": {
+          "latency": {
+            "type": "randomInt",
+            "min": 100,
+            "max": 1000
+          },
+          "operationName": {
+            "type": "randomString",
+            "length": "10",
+            "prefix": "test_endpoint_",
+            "letters": true,
+            "numbers": true
+          },
+          "componentId": {
+            "type": "randomInt",
+            "min": "0",
+            "max": "4"
+          },
+          "error": {
+            "type": "randomBool",
+            "possibility": "0.2"
+          },
+          "tags": {
+            "type": "randomList",
+            "size": 5,
+            "item": {
+              "key": {
+                "type": "randomString",
+                "length": "10",
+                "prefix": "test_tag_key_",
+                "letters": true,
+                "numbers": true,
+                "domainSize": 10
+              },
+              "value": {
+                "type": "randomString",
+                "length": "10",
+                "prefix": "test_tag_val_",
+                "letters": true,
+                "numbers": true
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/test/stress/trace/trace_suite_test.go 
b/test/stress/trace/trace_suite_test.go
new file mode 100644
index 00000000..c450a8db
--- /dev/null
+++ b/test/stress/trace/trace_suite_test.go
@@ -0,0 +1,57 @@
+// Licensed to 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. Apache Software Foundation (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.
+
+package trace_test
+
+import (
+       "flag"
+       "path"
+       "runtime"
+       "testing"
+       "time"
+
+       . "github.com/onsi/ginkgo/v2"
+       . "github.com/onsi/gomega"
+
+       "github.com/apache/skywalking-banyandb/pkg/test/query"
+)
+
+func TestIntegrationLoad(t *testing.T) {
+       t.Skip("Skip the stress trace test")
+       RegisterFailHandler(Fail)
+       RunSpecs(t, "Stress Trace Suite")
+}
+
+var _ = Describe("Query", func() {
+       const timeout = 30 * time.Minute
+       var (
+               fs       *flag.FlagSet
+               basePath string
+       )
+
+       BeforeEach(func() {
+               fs = flag.NewFlagSet("", flag.PanicOnError)
+               fs.String("base-url", "http://localhost:12800/graphql";, "")
+               fs.String("service-id", "c2VydmljZV8x.1", "")
+               _, basePath, _, _ = runtime.Caller(0)
+               basePath = path.Dir(basePath)
+       })
+
+       It("TraceListOrderByDuration", func() {
+               query.TraceListOrderByDuration(basePath, timeout, fs)
+       })
+})


Reply via email to