You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by ke...@apache.org on 2021/10/07 14:03:18 UTC

[skywalking-cli] branch flags created (now b88757a)

This is an automated email from the ASF dual-hosted git repository.

kezhenxu94 pushed a change to branch flags
in repository https://gitbox.apache.org/repos/asf/skywalking-cli.git.


      at b88757a  Migrate tests to infra-e2e, overhaul the flags names

This branch includes the following new commits:

     new b88757a  Migrate tests to infra-e2e, overhaul the flags names

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


[skywalking-cli] 01/01: Migrate tests to infra-e2e, overhaul the flags names

Posted by ke...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

kezhenxu94 pushed a commit to branch flags
in repository https://gitbox.apache.org/repos/asf/skywalking-cli.git

commit b88757af6af6d4f980bf89a92526976dd9cacc0b
Author: kezhenxu94 <ke...@apache.org>
AuthorDate: Wed Oct 6 21:15:32 2021 +0800

    Migrate tests to infra-e2e, overhaul the flags names
    
    Also remove the command documentations and move them into the command
    help manual.
---
 .asf.yaml                                          |    6 +-
 .github/workflows/go.yml                           |    4 +-
 CHANGES.md                                         |    6 +-
 CONTRIBUTING.md                                    |   79 +-
 Makefile                                           |   31 +-
 README.md                                          |  474 +-----
 assets/assets.gen.go                               | 1648 --------------------
 assets/assets.go                                   |    9 +-
 .../graphqls/dependency/EndpointDependency.graphql |    4 +-
 assets/graphqls/profile/CreateTask.graphql         |    4 +-
 assets/graphqls/profile/GetProfileAnalyze.graphql  |   20 +-
 assets/graphqls/profile/GetProfiledSegment.graphql |   30 +-
 assets/graphqls/profile/GetTaskList.graphql        |   10 +-
 cmd/swctl/main.go                                  |   83 +-
 docs/How-to-release.md                             |   52 +-
 examples/.skywalking.yaml                          |    2 +-
 {assets => examples}/assets.go                     |   23 +-
 go.mod                                             |    4 +-
 go.sum                                             |    6 +-
 internal/commands/completion/bash.go               |    4 +-
 internal/commands/completion/completion.go         |    6 +-
 internal/commands/completion/powershell.go         |    4 +-
 internal/commands/dashboard/dashboard.go           |   10 +-
 internal/commands/dashboard/global/global.go       |   22 +-
 internal/commands/dashboard/global/metrics.go      |   14 +-
 internal/commands/dependency/dependency.go         |   10 +-
 internal/commands/dependency/endpoint.go           |   30 +-
 internal/commands/dependency/instance.go           |   30 +-
 internal/commands/dependency/service.go            |   25 +-
 internal/commands/endpoint/endpoint.go             |   10 +-
 internal/commands/endpoint/list.go                 |   65 +-
 internal/commands/event/event.go                   |    6 +-
 internal/commands/event/list.go                    |   48 +-
 internal/commands/event/report.go                  |   80 +-
 internal/commands/healthcheck/healthcheck.go       |   38 +-
 internal/commands/install/install.go               |   12 +-
 internal/commands/install/manifest/manifest.go     |   18 +-
 internal/commands/install/manifest/oap.go          |    6 +-
 internal/commands/install/manifest/ui.go           |    6 +-
 internal/commands/instance/instance.go             |   32 +-
 internal/commands/instance/list.go                 |   35 +-
 internal/commands/instance/search.go               |   23 +-
 internal/commands/interceptor/duration.go          |    6 +-
 internal/commands/interceptor/endpoint.go          |  105 ++
 internal/commands/interceptor/entity.go            |   60 +-
 internal/commands/interceptor/event.go             |    6 +-
 internal/commands/interceptor/event_test.go        |    2 +-
 internal/commands/interceptor/instance.go          |  101 ++
 internal/commands/interceptor/interceptor.go       |    8 +-
 internal/commands/interceptor/service.go           |   98 ++
 internal/commands/interceptor/timezone.go          |   12 +-
 internal/commands/logs/list.go                     |   45 +-
 internal/commands/logs/log.go                      |   10 +-
 internal/commands/metrics/aggregation/topn.go      |   40 +-
 internal/commands/metrics/linear/linear-metrics.go |   22 +-
 .../metrics/linear/multiple-linear-metrics.go      |   26 +-
 internal/commands/metrics/list/list-metrics.go     |   24 +-
 internal/commands/metrics/metrics.go               |    4 +-
 internal/commands/metrics/single/single-metrics.go |   32 +-
 .../metrics/thermodynamic/thermodynamic.go         |   32 +-
 internal/commands/profile/create.go                |   87 +-
 internal/commands/profile/getProfileAnalyze.go     |   11 +-
 internal/commands/profile/getProfiledSegment.go    |    9 +-
 internal/commands/profile/getTaskList.go           |   13 +-
 internal/commands/profile/getTaskSegmentList.go    |    9 +-
 internal/commands/profile/profile.go               |    6 +-
 internal/commands/service/list.go                  |   36 +-
 internal/commands/service/service.go               |   10 +-
 internal/commands/trace/list.go                    |   79 +-
 internal/commands/trace/trace.go                   |   22 +-
 internal/flags/duration.go                         |   37 +-
 internal/flags/endpoint.go                         |   56 +
 internal/flags/flags.go                            |    2 +-
 internal/flags/instance.go                         |   39 +-
 internal/flags/metrics.go                          |   21 +-
 internal/flags/search.go                           |    4 +-
 internal/flags/{entity.go => service.go}           |   55 +-
 pkg/commands/event/report.go                       |   16 +-
 pkg/display/display.go                             |   16 +-
 pkg/display/graph/dashboard/global.go              |    4 +-
 pkg/display/graph/gauge/gauge.go                   |    2 +-
 pkg/display/graph/graph.go                         |    2 +-
 pkg/display/graph/linear/linear.go                 |    2 +-
 pkg/display/graph/tree/list.go                     |    2 +-
 pkg/graphql/client/client.go                       |   10 +-
 pkg/graphql/dashboard/global.go                    |    2 +-
 pkg/graphql/dependency/dependency.go               |    2 +-
 pkg/graphql/event/event.go                         |    2 +-
 pkg/graphql/healthcheck/healthcheck.go             |    2 +-
 pkg/graphql/log/log.go                             |    2 +-
 pkg/graphql/metadata/metadata.go                   |    2 +-
 pkg/graphql/metrics/metrics.go                     |    2 +-
 pkg/graphql/profile/profile.go                     |    2 +-
 pkg/graphql/trace/trace.go                         |    2 +-
 pkg/util/commandNotFound.go                        |    8 +-
 pkg/util/template.go                               |   28 +-
 scripts/test_commands.sh                           |   75 -
 test/docker-compose.yml                            |   74 +
 .../expected/dashboard-global-metrics.yml          |   37 +-
 .asf.yaml => test/expected/dashboard-global.yml    |   51 +-
 .asf.yaml => test/expected/dependency-endpoint.yml |   40 +-
 test/expected/dependency-instance.yml              |   43 +
 .asf.yaml => test/expected/dependency-service.yml  |   37 +-
 .asf.yaml => test/expected/empty-array.yml         |   16 +-
 .asf.yaml => test/expected/endpoint-list.yml       |   17 +-
 .asf.yaml => test/expected/instance-list.yml       |   26 +-
 .asf.yaml => test/expected/metrics-has-value.yml   |   19 +-
 .../expected/metrics-top-endpoint-sla-provider.yml |   19 +-
 .../expected/metrics-top-service-sla.yml           |   25 +-
 .asf.yaml => test/expected/service-endpoint.yml    |   19 +-
 .asf.yaml => test/expected/service-provider.yml    |   18 +-
 .asf.yaml => test/expected/service.yml             |   23 +-
 test/expected/trace-users-detail.yml               |   99 ++
 .asf.yaml => test/expected/traces-list.yml         |   27 +-
 .asf.yaml => test/expected/value.yml               |   16 +-
 test/services/consumer.py                          |   42 +
 .asf.yaml => test/services/provider.py             |   33 +-
 test/test.yaml                                     |   95 ++
 118 files changed, 1909 insertions(+), 3208 deletions(-)

diff --git a/.asf.yaml b/.asf.yaml
index 102dba2..1c4989d 100644
--- a/.asf.yaml
+++ b/.asf.yaml
@@ -25,6 +25,6 @@ github:
     - distributed-tracing
     - cli
   enabled_merge_buttons:
-    squash:  true
-    merge:   false
-    rebase:  false
+    squash: true
+    merge: false
+    rebase: false
diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml
index 7f948b4..6491c57 100644
--- a/.github/workflows/go.yml
+++ b/.github/workflows/go.yml
@@ -34,8 +34,8 @@ jobs:
         uses: getsentry/paths-filter@v2
         id: changes
         with:
-            token: ${{ github.token }}
-            filters: .github/file-filters.yml
+          token: ${{ github.token }}
+          filters: .github/file-filters.yml
 
       - name: Set up Go 1.14
         uses: actions/setup-go@v2
diff --git a/CHANGES.md b/CHANGES.md
index 809c5ca..20b5af5 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -31,7 +31,7 @@ Release Notes.
 
 ### Features
 
-- Add GitHub Action for integration of event reporter 
+- Add GitHub Action for integration of event reporter
 
 ### Bug Fixes
 
@@ -124,7 +124,7 @@ Release Notes.
 - Support visualization of heat map
 - Support top N entities, `swctl metrics top 5 --name service_sla`
 - Support thermodynamic metrics, `swctl metrics thermodynamic --name all_heatmap`
-- Support multiple linear metrics, `swctl --display=graph --debug metrics multiple-linear --name all_percentile` 
+- Support multiple linear metrics, `swctl --display=graph --debug metrics multiple-linear --name all_percentile`
 - Automatically make use of server timezone API when possible
 
 ### Chores
@@ -138,6 +138,7 @@ Release Notes.
 ------------------
 
 ### Features
+
 - Add command `swctl service` to list services
 - Add command `swctl instance` and `swctl search` to list and search instances of service.
 - Add command `swctl endpoint` to list endpoints of service.
@@ -145,4 +146,5 @@ Release Notes.
 - Add command `swctl single-metrics` to query single-value metrics.
 
 ### Chores
+
 - Set up GitHub actions to check code styles, licenses, and tests.
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 6a9d939..b9d9926 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,37 +1,38 @@
 # Contributing to Apache SkyWalking CLI
 
-Firstly, thanks for your interest in contributing! We hope that this will be a
-pleasant first experience for you, and that you will return to continue
-contributing.
+Firstly, thanks for your interest in contributing! We hope that this will be a pleasant first experience for you, and
+that you will return to continue contributing.
 
 ## Code of Conduct
 
-This project and everyone participating in it is governed by the Apache
-software Foundation's [Code of Conduct](http://www.apache.org/foundation/policies/conduct.html).
-By participating, you are expected to adhere to this code. If you are aware of unacceptable behavior, please visit the
+This project and everyone participating in it is governed by the Apache software
+Foundation's [Code of Conduct](http://www.apache.org/foundation/policies/conduct.html). By participating, you are
+expected to adhere to this code. If you are aware of unacceptable behavior, please visit the
 [Reporting Guidelines page](http://www.apache.org/foundation/policies/conduct.html#reporting-guidelines)
 and follow the instructions there.
 
 ## How to contribute?
 
-Most of the contributions that we receive are code contributions, but you can
-also contribute to the documentation or simply report solid bugs
-for us to fix.
+Most of the contributions that we receive are code contributions, but you can also contribute to the documentation or
+simply report solid bugs for us to fix.
 
 ## How to report a bug?
 
-* **Ensure the bug was not already reported** by searching on GitHub under [Issues](https://github.com/apache/skywalking/issues).
+* **Ensure the bug was not already reported** by searching on GitHub
+  under [Issues](https://github.com/apache/skywalking/issues).
 
-* If you're unable to find an open issue addressing the problem, [open a new one](https://github.com/apache/skywalking/issues/new).
-Be sure to include a **title and clear description**, as much relevant information as possible,
-and a **code sample** or an **executable test case** demonstrating the expected behavior that is not occurring.
+* If you're unable to find an open issue addressing the
+  problem, [open a new one](https://github.com/apache/skywalking/issues/new). Be sure to include a **title and clear
+  description**, as much relevant information as possible, and a **code sample** or an **executable test case**
+  demonstrating the expected behavior that is not occurring.
 
 ## How to add a new feature or change an existing one
 
 _Before making any significant changes, please [open an issue](https://github.com/apache/skywalking/issues)._
 Discussing your proposed changes ahead of time will make the contribution process smooth for everyone.
 
-Once we've discussed your changes and you've got your code ready, make sure that tests are passing and open your pull request. Your PR is most likely to be accepted if it:
+Once we've discussed your changes and you've got your code ready, make sure that tests are passing and open your pull
+request. Your PR is most likely to be accepted if it:
 
 * Update the README.md with details of changes to the interface.
 * Includes tests for new functionality.
@@ -39,63 +40,79 @@ Once we've discussed your changes and you've got your code ready, make sure that
 * Has a [good commit message](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
 
 ## Compiling and building
-Clone the source code and simply run `make` in the source directory,
-this will download all necessary dependencies and run tests, lint, and build three binary files in `./bin/`, for Windows, Linux, MacOS respectively.
+
+Clone the source code and simply run `make` in the source directory, this will download all necessary dependencies and
+run tests, lint, and build three binary files in `./bin/`, for Windows, Linux, MacOS respectively.
 
 ```shell
 make
 ```
 
 ## Writing a new command
-All commands files locate in directory [`commands`](internal/commands), and an individual directory for each second-level command,
-an individual `go` file for each third-level command, for example, there is a directory [`service`](internal/commands/service) for command `swctl service`, 
-and a [`list.go`](internal/commands/service/list.go) file for `swctl service list` command.
 
-Determine what entity your command will operate on, and put your command `go` file into that directory, or create one if it doesn't exist,
-for example, if you want to create a command to `list` all the `instance`s of a service, create a directory `commands/instance`,
-and a `go` file `commands/instance/list.go`.
+All commands files locate in directory [`commands`](internal/commands), and an individual directory for each
+second-level command, an individual `go` file for each third-level command, for example, there is a
+directory [`service`](internal/commands/service) for command `swctl service`, and
+a [`list.go`](internal/commands/service/list.go) file for `swctl service list` command.
+
+Determine what entity your command will operate on, and put your command `go` file into that directory, or create one if
+it doesn't exist, for example, if you want to create a command to `list` all the `instance`s of a service, create a
+directory `commands/instance`, and a `go` file `commands/instance/list.go`.
 
 ## Reusing common options
-There're some [common options](#common-options) that can be shared by multiple commands, check [`commands/flags`](internal/flags)
-to get all the shared options, and reuse them when possible, an example shares the options is [`commands/service/list.go`](internal/commands/service/list.go#L35)
+
+There're some [common options](#common-options) that can be shared by multiple commands,
+check [`commands/flags`](internal/flags)
+to get all the shared options, and reuse them when possible, an example shares the options
+is [`commands/service/list.go`](internal/commands/service/list.go#L35)
 
 ## Linting your codes
+
 We have some rules for the code style and please lint your codes locally before opening a pull request
 
 ```shell
 make lint
 ```
 
-if you found some errors in the output of the above command, try `make fix` to fix some obvious style issues, as for the complicated errors, please fix them manually.
+if you found some errors in the output of the above command, try `make fix` to fix some obvious style issues, as for the
+complicated errors, please fix them manually.
 
 ## Checking license
-The Apache Software Foundation requires every source file to contain a license header, run `make license` to check that there is license header in every source file.
+
+The Apache Software Foundation requires every source file to contain a license header, run `make license` to check that
+there is license header in every source file.
 
 ```shell
 make license
 ``` 
 
 ## Running tests
-Before submitting a pull request, add some test code to test the added/modified codes,
-and run the tests locally, make sure all tests passed.
+
+Before submitting a pull request, add some test code to test the added/modified codes, and run the tests locally, make
+sure all tests passed.
 
 ```shell
 make test
 ```
 
 ## How to release
+
 This section guides committers and PMC members to release SkyWalking CLI in Apache Way.
 
 ### Prerequisites
+
 - [x] [GNU Make](https://www.gnu.org/software/make/manual/make.html) is installed
 - [x] [GPG tool](https://gpgtools.org) is installed
 - [x] [Add your GPG key](docs/How-to-release.md#add-your-gpg-public-key)
 
 ### Release steps
+
 - Export the version that is to be released, `export VERSION=1.0.1 `
-- Tag the latest commit that is to be released with `git tag v${VERSION}` and push the tag with `git push https://github.com/apache/skywalking-cli v${VERSION}`
-- Verify licenses, build and sign distribution packages, simply run `make release`, distribution packages and checksums are generated
-- [Upload the packages to SVN repository](docs/How-to-release.md#upload-to-apache-svn) 
+- Tag the latest commit that is to be released with `git tag v${VERSION}` and push the tag
+  with `git push https://github.com/apache/skywalking-cli v${VERSION}`
+- Verify licenses, build and sign distribution packages, simply run `make release`, distribution packages and checksums
+  are generated
+- [Upload the packages to SVN repository](docs/How-to-release.md#upload-to-apache-svn)
 - [Send internal announcement](docs/How-to-release.md#make-the-internal-announcements)
 - [Wait at least 48 hours for test responses](docs/How-to-release.md#wait-at-least-48-hours-for-test-responses)
 - [Call for vote](docs/How-to-release.md#call-a-vote-in-dev)
diff --git a/Makefile b/Makefile
index a31fde4..a4dd4c7 100644
--- a/Makefile
+++ b/Makefile
@@ -37,8 +37,6 @@ GO_LINT = $(GO_PATH)/bin/golangci-lint
 GO_LICENSER = $(GO_PATH)/bin/go-licenser
 ARCH := $(shell uname)
 OSNAME := $(if $(findstring Darwin,$(ARCH)),darwin,linux)
-GOBINDATA_VERSION := v3.21.0
-GO_BINDATA = $(GO_PATH)/bin/go-bindata
 GO_BUILD_FLAGS = -v
 GO_BUILD_LDFLAGS = -X main.version=$(VERSION)
 
@@ -52,22 +50,12 @@ all: clean license deps lint test build
 
 tools:
 	mkdir -p $(GO_PATH)/bin
-	$(GO_BINDATA) -v || curl --location --output $(GO_BINDATA) https://github.com/kevinburke/go-bindata/releases/download/$(GOBINDATA_VERSION)/go-bindata-$(OSNAME)-amd64 \
-		&& chmod +x $(GO_BINDATA)
 	$(GO_LINT) version || curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(GO_PATH)/bin
 	$(GO_LICENSER) -version || GO111MODULE=off $(GO_GET) -u github.com/elastic/go-licenser
 
 deps: tools
 	$(GO_GET) -v -t -d ./...
 
-.PHONY: assets
-assets: tools
-	cd assets \
-		&& $(GO_BINDATA) --nocompress --nometadata --pkg assets --ignore '.*\.go' \
-			-o "assets.gen.go" ./... \
-		&& ../scripts/build-header.sh assets.gen.go \
-		&& cd ..
-
 .PHONY: $(PLATFORMS)
 $(PLATFORMS): clean
 	mkdir -p $(OUT_DIR)
@@ -158,11 +146,14 @@ docker.push: docker
 
 .PHONY: test-commands
 test-commands:
-	@if ! docker run --name oap -p 12800:12800 -p 11800:11800 -d -e SW_HEALTH_CHECKER=default -e SW_TELEMETRY=prometheus apache/skywalking-oap-server:8.4.0-es7 > /dev/null 2>&1;then \
-		docker container stop oap; \
-		docker container prune -f; \
-		docker run --name oap -p 12800:12800 -p 11800:11800 -d -e SW_HEALTH_CHECKER=default -e SW_TELEMETRY=prometheus apache/skywalking-oap-server:8.4.0-es7; \
-	fi
-	VERSION=$(VERSION) ./scripts/test_commands.sh
-	@docker container stop oap
-	@docker container prune -f
+	docker compose -f test/docker-compose.yml up -d
+	VERSION=$(VERSION) ./test/run.sh
+	docker compose -f test/docker-compose.yml down
+
+.PHONY: install
+install: $(OSNAME)
+	-cp $(OUT_DIR)/$(BINARY)-$(VERSION)-$(OSNAME)-$(ARCH) $(DESTDIR)/swctl
+
+.PHONY: uninstall
+uninstall: $(OSNAME)
+	-rm $(DESTDIR)/$(PROJECT)/swctl
diff --git a/README.md b/README.md
index 4ccc46a..305c279 100644
--- a/README.md
+++ b/README.md
@@ -8,8 +8,9 @@ Apache SkyWalking CLI
 
 The CLI (Command Line Interface) for [Apache SkyWalking](https://github.com/apache/skywalking).
 
-SkyWalking CLI is a command interaction tool for the SkyWalking user or OPS team, as an alternative besides using browser GUI.
-It is based on SkyWalking [GraphQL query protocol](https://github.com/apache/skywalking-query-protocol), same as GUI.
+SkyWalking CLI is a command interaction tool for the SkyWalking user or OPS team, as an alternative besides using
+browser GUI. It is based on SkyWalking [GraphQL query protocol](https://github.com/apache/skywalking-query-protocol),
+same as GUI.
 
 ## Install
 
@@ -33,11 +34,14 @@ curl -LO "https://raw.githubusercontent.com/apache/skywalking-cli/tree/master/sc
 
 ### Install by available binaries
 
-Go to the [download page](https://skywalking.apache.org/downloads/#SkyWalkingCLI) to download all available binaries, including macOS, Linux, Windows.
+Go to the [download page](https://skywalking.apache.org/downloads/#SkyWalkingCLI) to download all available binaries,
+including macOS, Linux, Windows.
 
 ### Build from source
 
-If you want to try the latest features, you can compile the latest source code and build `swctl` by yourself. Since SkyWalking CLI is using `Makefile`, compiling the project is as easy as executing a command in the root directory of the project.
+If you want to try the latest features, you can compile the latest source code and build `swctl` by yourself. Since
+SkyWalking CLI is using `Makefile`, compiling the project is as easy as executing a command in the root directory of the
+project.
 
 ```shell
 git clone https://github.com/apache/skywalking-cli
@@ -45,15 +49,17 @@ cd skywalking-cli
 make
 ```
 
-Then copy the `./bin/swctl-latest-(darwin|linux|windows)-amd64` to your `PATH` directory according to your OS, usually `/usr/bin/` or `/usr/local/bin`. 
+Then copy the `./bin/swctl-latest-(darwin|linux|windows)-amd64` to your `PATH` directory according to your OS,
+usually `/usr/bin/` or `/usr/local/bin`.
 
-You can also copy it to any directory you like, then add that directory to `PATH`. **We recommend you to rename the `swctl-latest-(darwin|linux|windows)-amd64` to `swctl`.**
+You can also copy it to any directory you like, then add that directory to `PATH`. **We recommend you to rename
+the `swctl-latest-(darwin|linux|windows)-amd64` to `swctl`.**
 
 ### Run from Docker image
 
-If you prefer to use Docker, skywalking-cli also provides Docker images for convenient usages since 0.9.0.
-We also push the snapshot Docker images to GitHub registry for developers who want to test the latest features,
-note that this is not Apache releases, and it's for test only, **DO NOT** use it in your production environment.
+If you prefer to use Docker, skywalking-cli also provides Docker images for convenient usages since 0.9.0. We also push
+the snapshot Docker images to GitHub registry for developers who want to test the latest features, note that this is not
+Apache releases, and it's for test only, **DO NOT** use it in your production environment.
 
 ```shell
 docker run -it --rm apache/skywalking-cli service ls
@@ -69,7 +75,8 @@ docker run -it --rm ghcr.io/apache/skywalking-cli/skywalking-cli  service ls
 
 ### Bash
 
-The swctl completion script for bash can be generated with the command `swctl completion bash`. Sourcing the completion script in your shell enables swctl auto-completion:
+The swctl completion script for bash can be generated with the command `swctl completion bash`. Sourcing the completion
+script in your shell enables swctl auto-completion:
 
 ```shell
 swctl completion bash > bash_autocomplete &&
@@ -89,7 +96,8 @@ set-executionpolicy remotesigned -Scope CurrentUser
 swctl completion powershell >> $profile
 ```
 
-If you get an error like `OpenError: (:) [Out-File], DirectoryNotFoundException`, then you need to run the following command to create `$profile` file:
+If you get an error like `OpenError: (:) [Out-File], DirectoryNotFoundException`, then you need to run the following
+command to create `$profile` file:
 
 ```shell
 New-Item -Type file -Force $profile
@@ -97,142 +105,13 @@ New-Item -Type file -Force $profile
 
 After reloading your shell, swctl auto-completion should be working.
 
-
-# Commands
-Commands in SkyWalking CLI are organized into two levels, in the form of `swctl --option <level1> --option <level2> --option`,
-there're options in each level, which should follow right after the corresponding command, take the following command as example:
-
-```shell
-$ swctl --debug service list --start="2019-11-11" --end="2019-11-12"
-```
-
-where `--debug` is is an option of `swctl`, and since the `swctl` is a top-level command, `--debug` is also called global option,
-and `--start` is an option of the third level command `list`, there is no option for the second level command `service`.
-
-Generally, the second level commands are entity related, there're entities like `service`, `service instance`, `metrics` in SkyWalking,
-and we have corresponding sub-command like `service`; the third level commands are operations on the entities, such as `list` command
-will list all the `service`s, `service instance`s, etc.
-
-## Common options
-There're some common options that are shared by multiple commands, and they follow the same rules in different commands,
-
-<details>
-
-<summary>--start, --end, --timezone</summary>
-
-`--start` and `--end` specify a time range during which the query is preformed,
-they are both optional and their default values follow the rules below:
-
-- when `start` and `end` are both absent, `start = now - 30 minutes` and `end = now`, namely past 30 minutes;
-- when `start` and `end` are both present, they are aligned to the same precision by **truncating the more precise one**,
-e.g. if `start = 2019-01-01 1234, end = 2019-01-01 18`, then `start` is truncated (because it's more precise) to `2019-01-01 12`,
-and `end = 2019-01-01 18`;
-- when `start` is absent and `end` is present, will determine the precision of `end` and then use the precision to calculate `start` (minus 30 units),
-e.g. `end = 2019-11-09 1234`, the precision is `MINUTE`, so `start = end - 30 minutes = 2019-11-09 1204`,
-and if `end = 2019-11-09 12`, the precision is `HOUR`, so `start = end - 30HOUR = 2019-11-08 06`;
-- when `start` is present and `end` is absent, will determine the precision of `start` and then use the precision to calculate `end` (plus 30 units),
-e.g. `start = 2019-11-09 1204`, the precision is `MINUTE`, so `end = start + 30 minutes = 2019-11-09 1234`,
-and if `start = 2019-11-08 06`, the precision is `HOUR`, so `end = start + 30HOUR = 2019-11-09 12`;
-
-`--timezone` specifies the timezone where `--start` `--end` are based, in the form of `+0800`:
-
-- if `--timezone` is given in the command line option, then it's used directly;
-- else if the backend support the timezone API (since 6.5.0), CLI will try to get the timezone from backend, and use it;
-- otherwise, the CLI will use the current timezone in the current machine; 
-
-</details>
-
-## All available commands
-This section covers all the available commands in SkyWalking CLI and their usages.
-
-### `swctl`
-`swctl` is the top-level command, which has some options that will take effects globally.
-
-| option | description | default |
-| :--- | :--- | :--- |
-| `--config` | from where the default options values will be loaded | `~/.skywalking.yml`, example can be found [here](examples/.skywalking.yaml) |
-| `--debug` | enable debug mode, will print more detailed information at runtime | `false` |
-| `--base-url` | base url of GraphQL backend | `http://127.0.0.1:12800/graphql` |
-| `--grpcAddr` | The address of gRPC endpoint | `127.0.0.1:11800` |
-| `--username` | username of `Basic` authorization | `` |
-| `--password` | password of `Basic` authorization | `` |
-| `--authorization` | authorization header, can be something like `Basic base64<username:password>` or `Bearer jwt-token`, if `authorization` is set, `username` and `password` are ignored | `` |
-| `--display` | display style when printing the query result, supported styles are: `json`, `yaml`, `table`, `graph` | `json` |
-
-Note that not all display styles (except for `json` and `yaml`) are supported in all commands due to data formats incompatibilities and the limits of
-Ascii Graph, like coloring in terminal, so please use `json`  or `yaml` instead.
-
-### `service`
-
-<details>
-
-<summary>service list [--start=start-time] [--end=end-time]</summary>
-
-`service list` lists all the services in the time range of `[start, end]`.
-
-| option | description | default |
-| :--- | :--- | :--- |
-| `--start` | See [Common options](#common-options) | See [Common options](#common-options) |
-| `--end` | See [Common options](#common-options) | See [Common options](#common-options) |
-
-</details>
-
-### `instance`
-
-<details>
-
-<summary>instance list [--start=start-time] [--end=end-time] [--service-id=service-id] [--service-name=service-name]</summary>
-
-`instance list` lists all the instances in the time range of `[start, end]` and given `--service-id` or `--service-name`.
-
-| option | description | default |
-| :--- | :--- | :--- |
-| `--service-id` | Query by service id (priority over `--service-name`)|  |
-| `--service-name` | Query by service name if `--service-id` is absent |  |
-| `--start` | See [Common options](#common-options) | See [Common options](#common-options) |
-| `--end` | See [Common options](#common-options) | See [Common options](#common-options) |
-
-</details>
-
-<details>
-
-<summary>instance search [--start=start-time] [--end=end-time] [--regex=instance-name-regex] [--service-id=service-id] [--service-name=service-name]</summary>
-
-`instance search` filter the instance in the time range of `[start, end]` and given --regex --service-id or --service-name.
-
-| option | description | default |
-| :--- | :--- | :--- |
-| `--regex` | Query regex of instance name|  |
-| `--service-id` | Query by service id (priority over `--service-name`)|  |
-| `--service-name` | Query by service name if `service-id` is absent |  |
-| `--start` | See [Common options](#common-options) | See [Common options](#common-options) |
-| `--end` | See [Common options](#common-options) | See [Common options](#common-options) |
-
-</details>
-
-### `endpoint`
-
-<details>
-
-<summary>endpoint list [--start=start-time] [--end=end-time] --service-id=service-id [--limit=count] [--keyword=search-keyword]</summary>
-
-`endpoint list` lists all the endpoints of the given service id in the time range of `[start, end]`.
-
-| option | description | default |
-| :--- | :--- | :--- |
-| `--service-id` | <service id> whose endpoints are to be searched | |
-| `--limit` | returns at most <limit> endpoints (default: 100) | 100 |
-| `--keyword` | <keyword> of the endpoint name to search for, empty to search all | "" |
-
-</details>
-
 ### `metrics`
 
 #### `metrics linear`
 
 <details>
 
-<summary>metrics linear [--start=start-time] [--end=end-time] --name=metrics-name [--service=service-name] [--instance=instance-name] [--endpoint=endpoint-name] [--isNormal=true/false] [--destService=dest-service-name] [--destInstance=dest-instance-name] [--destEndpoint=dest-endpoint-name] [--isDestNormal=true/false]</summary>
+<summary>metrics linear [--start=start-time] [--end=end-time] --name=metrics-name [--service=service-name] [--instance=instance-name] [--endpoint=endpoint-name] [--destService=dest-service-name] [--destInstance=dest-instance-name] [--destEndpoint=dest-endpoint-name] [--isDestNormal=true/false]</summary>
 
 | option | description | default |
 | :--- | :--- | :--- |
@@ -240,7 +119,6 @@ Ascii Graph, like coloring in terminal, so please use `json`  or `yaml` instead.
 | `--service` | The name of the service. | "" |
 | `--instance` | The name of the service instance. | "" |
 | `--endpoint` | The name of the endpoint. | "" |
-| `--isNormal` | Set the service to normal or unnormal. | `true` |
 | `--destService` | The name of the destination service. | "" |
 | `--destInstance` | The name of the destination instance. | "" |
 | `--destEndpoint` | The name of the destination endpoint. | "" |
@@ -295,86 +173,6 @@ Ascii Graph, like coloring in terminal, so please use `json`  or `yaml` instead.
 
 </details>
 
-#### `metrics top <n>`
-
-<details>
-
-<summary>metrics top 5 [--start=start-time] [--end=end-time] --name=metrics-name [--service=parent-service] [--order=DES] [--scope=Service/ServiceInstance/Endpoint] [--isNormal=true/false]</summary>
-
-| option | description | default |
-| :--- | :--- | :--- |
-| arguments | The first argument is the number of top entities | `5` |
-| `--name` | Metrics name, defined in [OAL](https://github.com/apache/skywalking/blob/master/oap-server/server-bootstrap/src/main/resources/oal/core.oal), such as `service_sla`, etc. |
-| `--service` | The name of the parent service, could be null if query the global top N. | "" |
-| `--order` | The order of metrics, `DES` or `ASC`. |`DES`|
-| `--scope` | The scope of the metrics entity, only accept `Service`/`ServiceInstance`/`Endpoint`, ignore others due to those are pointless. |`Service`|
-| `--isNormal` | Set the service to normal or unnormal. | `true` |
-| `--start` | See [Common options](#common-options) | See [Common options](#common-options) |
-| `--end` | See [Common options](#common-options) | See [Common options](#common-options) |
-
-</details>
-
-#### `metrics thermodynamic`
-
-<details>
-
-<summary>metrics thermodynamic [--name=metrics-name] [--destService=dest-service-name] [--destInstance=dest-instance-name] [--destEndpoint=dest-endpoint-name] [--isDestNormal=true/false]</summary>
-
-| option | description | default |
-| :--- | :--- | :--- |
-| `--name` | Metrics name that ends with `_heatmap`, defined in [OAL](https://github.com/apache/skywalking/blob/master/oap-server/server-bootstrap/src/main/resources/oal/core.oal), such as `all_heatmap`, etc. | `all_heatmap` |
-| `--destService` | The name of the destination service. | "" |
-| `--destInstance` | The name of the destination instance. | "" |
-| `--destEndpoint` | The name of the destination endpoint. | "" |
-| `--isDestNormal` | Set the destination service to normal or unnormal. | `true` |
-| `--start` | See [Common options](#common-options) | See [Common options](#common-options) |
-| `--end` | See [Common options](#common-options) | See [Common options](#common-options) |
-
-</details>
-
-#### `metrics list`
-
-<details>
-
-<summary>metrics list [--regex=regular-expression]</summary>
-
-| option | description | default |
-| :--- | :--- | :--- |
-| `--regex` | Filter metrics with a regular expression | "" |
-
-</details>
-
-### `trace`
-
-<details>
-
-<summary>trace [trace id]</summary>
-
-`trace` displays the spans of a given trace.
-
-| argument | description | default |
-| :--- | :--- | :--- |
-| `trace id` | The trace id whose spans are to displayed |  |
-
-</details>
-
-#### `trace ls`
-
-<details>
-
-<summary>trace ls</summary>
-
-| argument | description | default |
-| :--- | :--- | :--- |
-| `--trace-id` | The trace id whose spans are to displayed |  |
-| `--service-id` | The service id whose trace are to displayed |  |
-| `--service-instance-id` | The service instance id whose trace are to displayed |  |
-| `--tags` | Only tags defined in the core/default/searchableTagKeys are searchable. Check more details on the Configuration Vocabulary page | See [Configuration Vocabulary page](https://github.com/apache/skywalking/blob/master/docs/en/setup/backend/configuration-vocabulary.md) |
-| `--start` | See [Common options](#common-options) | See [Common options](#common-options) |
-| `--end` | See [Common options](#common-options) | See [Common options](#common-options) |
-
-</details>
-
 ### `dashboard`
 
 #### `dashboard global-metrics`
@@ -414,22 +212,6 @@ You can imitate the content of [the default template file](examples/global.yml)
 
 </details>
 
-### `checkHealth`
-
-<details>
-
-<summary>checkHealth [--grpc=true/false] [--grpcAddr=host:port] [--grpcTLS=true/false]</summary>
-
-| argument | description | default |
-| :--- | :--- | :--- |
-| `--grpc` | Enable/Disable check gRPC endpoint | `true` |
-| `--grpcAddr` | The address of gRPC endpoint | `127.0.0.1:11800` |
-| `--grpcTLS` | Enable/Disable TLS to access gRPC endpoint | `false` |
-
-*Notice: Once enable gRPC TLS, checkHealth command would ignore server's cert.
-
-</details>
-
 ### `install`
 
 #### `manifest`
@@ -492,12 +274,12 @@ You can imitate the content of [the default template file](examples/global.yml)
 
 <details>
 
-<summary>logs list [--service-id=service-id] [--service-instance-id=service-instance-id] [--endpoint-id=endpoint-id] [--trace-id=trace-id] [--tags=tags] [--start=start-time] [--end=end-time] </summary>
+<summary>logs list [--service-id=service-id] [--instance-id=instance-id] [--endpoint-id=endpoint-id] [--trace-id=trace-id] [--tags=tags] [--start=start-time] [--end=end-time] </summary>
 
 | argument | description | default |
 | :--- | :--- | :--- |
 | `service-id` | The service id whose logs are to displayed. |  |
-| `service-instance-id` | The service instance id whose logs are to displayed. |  |
+| `instance-id` | The service instance id whose logs are to displayed. |  |
 | `endpoint-id` | The service endpoint id whose logs are to displayed. |  |
 | `trace-id` | The trace id whose logs are to displayed. |  |
 | `tags` | Only tags defined in the core/default/searchableLogsTags are searchable. Check more details on the Configuration Vocabulary page | See [Configuration Vocabulary page](https://github.com/apache/skywalking/blob/master/docs/en/setup/backend/configuration-vocabulary.md) |
@@ -616,7 +398,8 @@ You can imitate the content of [the default template file](examples/global.yml)
 
 <summary>dependency instance [clientService-id] [serverService-id] [--start=start-time] [--end=end-time]</summary>
 
-`dependency instance` shows the instance topology of given `[clientService-id]` and `[serverService-id]` in the time range of `[start, end]`.
+`dependency instance` shows the instance topology of given `[clientService-id]` and `[serverService-id]` in the time
+range of `[start, end]`.
 
 | argument | description | default |
 | :--- | :--- | :--- |
@@ -631,57 +414,6 @@ You can imitate the content of [the default template file](examples/global.yml)
 
 <details>
 
-<summary>Query a specific service by name</summary>
-
-```shell
-# query the service named projectC
-$ ./bin/swctl service ls projectC
-[{"id":"4","name":"projectC"}]
-```
-
-</details>
-
-<details>
-
-<summary>Query instances of a specific service</summary>
-
-If you have already got the `id` of the service:
-
-```shell
-$ ./bin/swctl instance ls --service-id=3
-[{"id":"3","name":"projectD-pid:7909@skywalking-server-0001","attributes":[{"name":"os_name","value":"Linux"},{"name":"host_name","value":"skywalking-server-0001"},{"name":"process_no","value":"7909"},{"name":"ipv4s","value":"192.168.252.12"}],"language":"JAVA","instanceUUID":"ec8a79d7cb58447c978ee85846f6699a"}]
-```
-
-otherwise,
-
-```shell
-$ ./bin/swctl instance ls --service-name=projectC
-[{"id":"3","name":"projectD-pid:7909@skywalking-server-0001","attributes":[{"name":"os_name","value":"Linux"},{"name":"host_name","value":"skywalking-server-0001"},{"name":"process_no","value":"7909"},{"name":"ipv4s","value":"192.168.252.12"}],"language":"JAVA","instanceUUID":"ec8a79d7cb58447c978ee85846f6699a"}]
-```
-
-</details>
-
-<details>
-
-<summary>Query endpoints of a specific service</summary>
-
-If you have already got the `id` of the service:
-
-```shell
-$ ./bin/swctl endpoint ls --service-id=3
-```
-
-otherwise,
-
-```shell
-./bin/swctl service ls projectC | jq '.[].id' | xargs ./bin/swctl endpoint ls --service-id 
-[{"id":"22","name":"/projectC/{value}"}]
-```
-
-</details>
-
-<details>
-
 <summary>Query a linear metrics graph for an instance</summary>
 
 ```shell
@@ -699,43 +431,6 @@ $ ./bin/swctl instance ls --service-name=projectC | jq '.[] | select(.name == "p
 </details>
 
 <details>
-
-<summary>Query a single metrics value for a specific endpoint</summary>
-
-```shell
-export SERVICE_NAME=projectC.business-zone
-export ENDPOINT=/projectC/{value}
-export METRICS_NAME=endpoint_cpm
-./bin/swctl metrics single --name ${METRICS_NAME} --service ${SERVICE_NAME} --endpoint ${ENDPOINT}
-```
-
-Result:
-
-```
-23
-```
-
-</details>
-
-<details>
-
-<summary>Query metrics single values for all endpoints of service `projectC.business-zone`</summary>
-
-```shell
-export SERVICE_NAME=projectC.business-zone
-export METRICS_NAME=endpoint_cpm
-./bin/swctl endpoint ls --service-id=$(./bin/swctl service ls "$SERVICE_NAME" | jq -r '.[0].id') | jq -r '.[].name' | xargs ./bin/swctl metrics single --name "${METRICS_NAME}" --service "${SERVICE_NAME}" --endpoint
-```
-
-Result:
-
-```
-23
-```
-
-</details>
-
-<details>
 <summary>Query multiple metrics values for all percentiles</summary>
 
 ```shell
@@ -759,45 +454,6 @@ $ ./bin/swctl metrics top 5 --name service_sla
 
 <details>
 
-<summary>Query the top 5 instances whose sla is largest</summary>
-
-```shell
-$ ./bin/swctl metrics top 5 --name service_instance_sla     
-[{"name":"load balancer1.system - load balancer1.system","id":"","value":"10000","refId":null},{"name":"load balancer2.system - load balancer2.system","id":"","value":"10000","refId":null},{"name":"projectA.business-zone - eb38c5efeb874734a7b17de780685c55@192.168.252.12","id":"","value":"10000","refId":null},{"name":"projectB.business-zone - 4e72bad0f2c14381a5657eaaca7f33ba@192.168.252.12","id":"","value":"10000","refId":null},{"name":"projectB.business-zone - 6e0e2e1cc63145859a21fc7bf7f [...]
-```
-
-</details>
-
-<details>
-
-<summary>Query the top 5 endpoints whose sla is largest</summary>
-
-```shell
-$ ./bin/swctl metrics top 5 --name endpoint_sla  
-[{"name":"load balancer1.system - /projectA/test","id":"","value":"10000","refId":null},{"name":"load balancer1.system - /","id":"","value":"10000","refId":null},{"name":"load balancer2.system - /projectA/test","id":"","value":"10000","refId":null},{"name":"load balancer2.system - /","id":"","value":"10000","refId":null},{"name":"projectA.business-zone - /projectA/{name}","id":"","value":"10000","refId":null}]
-```
-
-</details>
-
-<details>
-
-<summary>Query the overall heat map</summary>
-
-```shell
-$ ./bin/swctl metrics thermodynamic
-{"values":[{"id":"202008290939","values":[473,3,0,0,0,0,0,0,0,0,323,0,4,0,0,0,0,0,0,0,436]},{"id":"202008290940","values":[434,0,0,0,0,0,0,0,0,0,367,0,4,0,0,0,0,0,0,0,427]},{"id":"202008290941","values":[504,0,0,0,0,0,0,0,0,0,410,0,5,0,1,0,0,0,0,0,377]},{"id":"202008290942","values":[445,0,4,0,0,0,0,0,0,0,350,0,0,0,0,0,0,0,0,0,420]},{"id":"202008290943","values":[436,0,1,0,0,0,0,0,0,0,367,0,3,0,0,0,0,0,0,0,404]},{"id":"202008290944","values":[463,0,0,0,0,0,0,0,0,0,353,0,0,0,0,0,0,0,0,0,4 [...]
-```
-
-```shell
-$ ./bin/swctl --display=graph metrics thermodynamic
-```
-
-![heatmap](http://skywalking.apache.org/screenshots/cli/heatmap.png)
-
-</details>
-
-<details>
-
 <summary>Query the logs</summary>
 
 ```shell
@@ -822,33 +478,40 @@ $ ./bin/swctl event list
 
 <summary>Profile the endpoint</summary>
 
-If your endpoint has performance issue and could not use tracing to find out what's happen, you could try to profile. You could get more information on [this page](https://github.com/apache/skywalking/blob/master/docs/en/guides/backend-profile.md).
+If your endpoint has performance issue and could not use tracing to find out what's happen, you could try to profile.
+You could get more information
+on [this page](https://github.com/apache/skywalking/blob/master/docs/en/guides/backend-profile.md).
 
 create profile task.
+
 ```shell
 $ ./bin/swctl profile create --service-name=service-name --endpoint=endpoint --start-time=1627656127860 --duration=5 --min-duration-threshold=0 --dump-period=10 --max-sampling-count=9
 {"errorReason":null,"id":"1627740677560_ZTJlLXNlcnZpY2UtcHJvdmlkZXI=.1"}
 ```
 
 Query existing task and logs.
+
 ```shell
 $ ./bin/swctl profile list --service-name=service-name --endpoint=endpoint
 [{"id":"1627740677560_ZTJlLXNlcnZpY2UtcHJvdmlkZXI=.1","serviceId":"ZTJlLXNlcnZpY2UtcHJvdmlkZXI=.1","serviceName":"","endpointName":"/info","startTime":1627740917933,"duration":5,"minDurationThreshold":0,"dumpPeriod":10,"maxSamplingCount":9,"logs":[{"id":"1627740677560_ZTJlLXNlcnZpY2UtcHJvdmlkZXI=.1_ZTJlLXNlcnZpY2UtcHJvdmlkZXI=.1_cHJvdmlkZXIx_1_1627740682470","instanceId":"ZTJlLXNlcnZpY2UtcHJvdmlkZXI=.1_cHJvdmlkZXIx","instanceName":"","operationType":"NOTIFIED","operationTime":1627740682470}]}]
 ```
 
 Query profiled segment list.
+
 ```shell
 $ ./bin/swctl profile segment-list --service-name=service-name --endpoint=endpoint
 [{"segmentId":"8f7e9e21221d427cb684a60d352a47ef.71.16277409290420002","endpointNames":["/info"],"duration":603,"start":"1627740929042","isError":false,"traceIds":["8f7e9e21221d427cb684a60d352a47ef.71.16277409290420003"]}]
 ```
 
 Query profiled segment spans.
+
 ```shell
 $ ./bin/swctl profile profiled-segment --segment-id=segment-id
 {"spans":[{"spanId":0,"parentSpanId":-1,"serviceCode":"e2e-service-provider","serviceInstanceName":"","startTime":1627740929042,"endTime":1627740929645,"endpointName":"/info","type":"Entry","peer":"","component":"Tomcat","isError":false,"layer":"Http","tags":[{"key":"url","value":"http://localhost:49553/info"},{"key":"http.method","value":"POST"}],"logs":null}]}
 ```
 
 Analyze profiled segment with time ranges.
+
 ```shell
 $ ./bin/swctl profile profiled-segment --segment-id=segment-id --time-ranges=start-end
 {"tip":null,"trees":[{"elements":[{"id":"1","parentId":"0","codeSignature":"java.lang.Thread.run:748","duration":577,"durationChildExcluded":0,"count":56},{"id":"2","parentId":"1","codeSignature":"org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run:61","duration":577,"durationChildExcluded":0,"count":56}]}]}
@@ -858,30 +521,6 @@ $ ./bin/swctl profile profiled-segment --segment-id=segment-id --time-ranges=sta
 
 <details>
 
-<summary>Display the spans of a trace</summary>
-
-```shell
-$ ./bin/swctl --display graph trace 07841b21-c8ed-4ace-851f-5cf0a635dc9f
-```
-
-![](http://skywalking.apache.org/screenshots/cli/trace.png)
-
-</details>
-
-<details>
-
-<summary>Display the traces</summary>
-
-```shell
-$ ./bin/swctl --display graph trace ls
-```
-
-![](http://skywalking.apache.org/screenshots/cli/trace-ls.png)
-
-</details>
-
-<details>
-
 <summary>Display the global dashboard</summary>
 
 ```shell
@@ -909,44 +548,6 @@ $ ./bin/swctl --display graph db g --template my-global-template.yml
 </details>
 
 <details>
-
-<summary>Automatically convert to server side timezone</summary>
-
-if your backend nodes are deployed in docker and the timezone is UTC, you may not want to convert your timezone to UTC every time you type a command, `--timezone` comes to your rescue.
-
-```shell
-$ ./bin/swctl --debug --timezone="0" service ls
-```
-
-`--timezone="+1200"` and `--timezone="-0900"` are also valid usage.
-
-</details>
-
-<details>
-
-<summary>Check whether OAP server is healthy</summary>
-
-if you want to check health status from GraphQL and the gRPC endpoint listening on 10.0.0.1:8843. 
-
-```shell
-$ ./bin/swctl checkHealth --grpcAddr=10.0.0.1:8843
-```
-
-If you only want to query GraphQL.
-
-```shell
-$ ./bin/swctl checkHealth --grpc=false
-```
-
-Once the gRPC endpoint of OAP encrypts communication by TLS.
-
-```shell
-$ ./bin/swctl checkHealth --grpcTLS=true
-```
-
-</details>
-
-<details>
 <summary>Output manifest of OAP server</summary>
 
 Output manifest with default custom resource
@@ -956,16 +557,19 @@ Output manifest with default custom resource
 ```
 
 Load overlay custom resource from flag
+
 ```shell
 swctl install manifest ui -f oap-cr.yaml
 ```
 
 Load overlay custom resource from stdin
+
 ```shell
 cat ui-cr.yaml | ./bin/swctl install manifest oap -f=-
 ```
 
 Apply directly to Kubernetes
+
 ```shell
 ./bin/swctl install manifest oap -f oap-cr.yaml | kubectl apply -f-
 ```
@@ -983,7 +587,6 @@ spec:
       value: es1.foo:9200
 ```
 
-
 </details>
 
 <details>
@@ -996,16 +599,19 @@ Output manifest with default custom resource
 ```
 
 Load overlay custom resource from flag
+
 ```shell
 swctl install manifest ui -f ui-cr.yaml
 ```
 
 Load overlay custom resource from stdin
+
 ```shell
 cat ui-cr.yaml | ./bin/swctl install manifest ui -f=-
 ```
 
 Apply directly to Kubernetes
+
 ```shell
 ./bin/swctl install manifest ui -f ui-cr.yaml | kubectl apply -f-
 ```
@@ -1013,6 +619,7 @@ Apply directly to Kubernetes
 Some examples of custome resource overlay files(ui-cr.yaml).
 
 1. Set OAP server address to `oap.test`, use an ingress to expose UI
+
 ```yaml
 spec:
   OAPServerAddress: oap.test
@@ -1022,6 +629,7 @@ spec:
 ```
 
 2. Use a Loadbalancer to expose UI
+
 ```yaml
 spec:
   service:
@@ -1075,7 +683,9 @@ jobs:
 </details>
 
 # Contributing
+
 For developers who want to contribute to this project, see [Contribution Guide](CONTRIBUTING.md)
 
 # License
+
 [Apache 2.0 License.](/LICENSE)
diff --git a/assets/assets.gen.go b/assets/assets.gen.go
deleted file mode 100644
index efd15d8..0000000
--- a/assets/assets.gen.go
+++ /dev/null
@@ -1,1648 +0,0 @@
-// 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.
-
-// Code generated by go-bindata. DO NOT EDIT.
-// sources:
-// cr/oap.yaml (942B)
-// cr/ui.yaml (935B)
-// graphqls/dependency/EndpointDependency.graphql (1.207kB)
-// graphqls/dependency/InstanceTopology.graphql (1.272kB)
-// graphqls/dependency/ServiceTopology.graphql (1.137kB)
-// graphqls/event/events.graphql (1.256kB)
-// graphqls/healthcheck/healthcheck.graphql (870B)
-// graphqls/logs/Logs.graphql (1.258kB)
-// graphqls/metadata/AllServices.graphql (911B)
-// graphqls/metadata/Instances.graphql (1.069kB)
-// graphqls/metadata/SearchEndpoints.graphql (975B)
-// graphqls/metadata/SearchService.graphql (930B)
-// graphqls/metadata/ServerTimeInfo.graphql (883B)
-// graphqls/metrics/HeatMap.graphql (1.067kB)
-// graphqls/metrics/LabeledMetricsValues.graphql (1.095kB)
-// graphqls/metrics/ListMetrics.graphql (923B)
-// graphqls/metrics/MetricsValue.graphql (943B)
-// graphqls/metrics/MetricsValues.graphql (1.05kB)
-// graphqls/metrics/SortMetrics.graphql (969B)
-// graphqls/profile/CreateTask.graphql (971B)
-// graphqls/profile/GetProfileAnalyze.graphql (1.16kB)
-// graphqls/profile/GetProfiledSegment.graphql (1.199kB)
-// graphqls/profile/GetTaskList.graphql (1.211kB)
-// graphqls/profile/GetTaskSegmentList.graphql (1.001kB)
-// graphqls/trace/Trace.graphql (1.518kB)
-// graphqls/trace/Traces.graphql (1.077kB)
-// templates/dashboard/global.yml (3.001kB)
-
-package assets
-
-import (
-	"crypto/sha256"
-	"fmt"
-	"io/ioutil"
-	"os"
-	"path/filepath"
-	"strings"
-	"time"
-)
-
-type asset struct {
-	bytes  []byte
-	info   os.FileInfo
-	digest [sha256.Size]byte
-}
-
-type bindataFileInfo struct {
-	name    string
-	size    int64
-	mode    os.FileMode
-	modTime time.Time
-}
-
-func (fi bindataFileInfo) Name() string {
-	return fi.name
-}
-func (fi bindataFileInfo) Size() int64 {
-	return fi.size
-}
-func (fi bindataFileInfo) Mode() os.FileMode {
-	return fi.mode
-}
-func (fi bindataFileInfo) ModTime() time.Time {
-	return fi.modTime
-}
-func (fi bindataFileInfo) IsDir() bool {
-	return false
-}
-func (fi bindataFileInfo) Sys() interface{} {
-	return nil
-}
-
-var _crOapYaml = []byte(`# 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.
-
-apiVersion: operator.skywalking.apache.org/v1alpha1
-kind: OAPServer
-metadata:
-  name: skywalking
-spec:
-  version: 8.3.0
-  instances: 1
- `)
-
-func crOapYamlBytes() ([]byte, error) {
-	return _crOapYaml, nil
-}
-
-func crOapYaml() (*asset, error) {
-	bytes, err := crOapYamlBytes()
-	if err != nil {
-		return nil, err
-	}
-
-	info := bindataFileInfo{name: "cr/oap.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
-	a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xb1, 0xd1, 0x17, 0xf7, 0xde, 0x69, 0x4c, 0x3, 0xab, 0x7a, 0x1f, 0x98, 0x8e, 0x9e, 0x5e, 0xa8, 0x60, 0x5e, 0xe4, 0xe8, 0x79, 0xac, 0x65, 0x2f, 0x73, 0x5b, 0xb1, 0xc1, 0xf5, 0x9a, 0x14, 0x80}}
-	return a, nil
-}
-
-var _crUiYaml = []byte(`# 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.
-
-apiVersion: operator.skywalking.apache.org/v1alpha1
-kind: UI
-metadata:
-  name: skywalking
-spec:
-  version: 8.3.0
-  instances: 1
- `)
-
-func crUiYamlBytes() ([]byte, error) {
-	return _crUiYaml, nil
-}
-
-func crUiYaml() (*asset, error) {
-	bytes, err := crUiYamlBytes()
-	if err != nil {
-		return nil, err
-	}
-
-	info := bindataFileInfo{name: "cr/ui.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
-	a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xdc, 0x65, 0xbc, 0x6, 0xf6, 0x0, 0x70, 0x4d, 0xcc, 0x9f, 0x9e, 0xea, 0x1b, 0x5d, 0xee, 0xcd, 0x95, 0x5b, 0xf2, 0xdf, 0xe7, 0x76, 0xb4, 0x36, 0x96, 0x98, 0x2, 0xa1, 0x8e, 0x2f, 0x27, 0x60}}
-	return a, nil
-}
-
-var _graphqlsDependencyEndpointdependencyGraphql = []byte(`# 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.
-
-query ($endpointId:ID!, $duration: Duration!) {
-    result: getEndpointDependencies(duration: $duration, endpointId: $endpointId) {
-        nodes {
-            id
-            name
-            serviceId
-            serviceName
-            type         
-            isReal
-        }
-        calls {
-            id
-            source
-            target
-            detectPoints
-        }        
-    }
-}
-`)
-
-func graphqlsDependencyEndpointdependencyGraphqlBytes() ([]byte, error) {
-	return _graphqlsDependencyEndpointdependencyGraphql, nil
-}
-
-func graphqlsDependencyEndpointdependencyGraphql() (*asset, error) {
-	bytes, err := graphqlsDependencyEndpointdependencyGraphqlBytes()
-	if err != nil {
-		return nil, err
-	}
-
-	info := bindataFileInfo{name: "graphqls/dependency/EndpointDependency.graphql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
-	a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xed, 0x55, 0x1, 0xe5, 0x9f, 0x2d, 0xaf, 0xe1, 0xad, 0x20, 0xc5, 0xa2, 0xaa, 0x16, 0x1, 0xca, 0xe3, 0xbf, 0x54, 0x54, 0x4a, 0x9d, 0xa6, 0x69, 0x37, 0x8a, 0xa8, 0x1a, 0xe5, 0xed, 0x28, 0xf}}
-	return a, nil
-}
-
-var _graphqlsDependencyInstancetopologyGraphql = []byte(`# 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.
-
-query ($clientServiceId: ID!, $serverServiceId: ID!, $duration: Duration!) {
-    result: getServiceInstanceTopology(duration: $duration, clientServiceId: $clientServiceId, serverServiceId: $serverServiceId) {
-        nodes {
-            id
-            name
-            type
-            isReal
-            serviceName
-            serviceId
-        }
-        calls {
-            id
-            source
-            detectPoints
-            target
-        }
-    }
-}
-`)
-
-func graphqlsDependencyInstancetopologyGraphqlBytes() ([]byte, error) {
-	return _graphqlsDependencyInstancetopologyGraphql, nil
-}
-
-func graphqlsDependencyInstancetopologyGraphql() (*asset, error) {
-	bytes, err := graphqlsDependencyInstancetopologyGraphqlBytes()
-	if err != nil {
-		return nil, err
-	}
-
-	info := bindataFileInfo{name: "graphqls/dependency/InstanceTopology.graphql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
-	a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x8b, 0x83, 0x9c, 0xab, 0x61, 0xdb, 0x37, 0xc6, 0xad, 0x3b, 0x40, 0x65, 0x4b, 0x75, 0x57, 0x99, 0x72, 0xf5, 0xcd, 0x76, 0x49, 0x79, 0xda, 0xf8, 0x2f, 0xb8, 0x30, 0x69, 0x9a, 0x94, 0xa9, 0xf4}}
-	return a, nil
-}
-
-var _graphqlsDependencyServicetopologyGraphql = []byte(`# 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.
-
-query ($serviceId: ID!, $duration: Duration!) {
-    result: getServiceTopology(duration: $duration, serviceId: $serviceId) {
-        nodes {
-            id
-            name
-            type
-            isReal
-        }
-        calls {
-            id
-            source
-            detectPoints
-            target
-        }
-    }
-}
-`)
-
-func graphqlsDependencyServicetopologyGraphqlBytes() ([]byte, error) {
-	return _graphqlsDependencyServicetopologyGraphql, nil
-}
-
-func graphqlsDependencyServicetopologyGraphql() (*asset, error) {
-	bytes, err := graphqlsDependencyServicetopologyGraphqlBytes()
-	if err != nil {
-		return nil, err
-	}
-
-	info := bindataFileInfo{name: "graphqls/dependency/ServiceTopology.graphql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
-	a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xb9, 0xb4, 0x57, 0x4c, 0xe6, 0x57, 0x1c, 0x34, 0xbd, 0xed, 0x73, 0x68, 0x63, 0x5, 0xab, 0x62, 0x44, 0x9, 0xc3, 0x12, 0x9, 0x85, 0x4b, 0xad, 0xb5, 0xb0, 0xa, 0xdb, 0xa8, 0x48, 0x22, 0x54}}
-	return a, nil
-}
-
-var _graphqlsEventEventsGraphql = []byte(`# 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.
-
-query ($condition: EventQueryCondition) {
-    result: queryEvents(condition: $condition) {
-        total
-        events {
-            uuid
-            source {
-                service
-                serviceInstance
-                endpoint
-            }
-            name
-            type
-            message
-            parameters {
-                key
-                value
-            }
-            startTime
-            endTime
-        }
-    }
-}
-`)
-
-func graphqlsEventEventsGraphqlBytes() ([]byte, error) {
-	return _graphqlsEventEventsGraphql, nil
-}
-
-func graphqlsEventEventsGraphql() (*asset, error) {
-	bytes, err := graphqlsEventEventsGraphqlBytes()
-	if err != nil {
-		return nil, err
-	}
-
-	info := bindataFileInfo{name: "graphqls/event/events.graphql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
-	a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xa6, 0x9f, 0x9e, 0xdc, 0x33, 0x45, 0xfe, 0x28, 0x85, 0x6, 0xcf, 0x2b, 0xde, 0xac, 0x21, 0x70, 0x5b, 0xb6, 0x1, 0xaf, 0x21, 0x93, 0x9, 0x95, 0x43, 0x5e, 0xb3, 0x23, 0xc0, 0xc8, 0x93, 0x2e}}
-	return a, nil
-}
-
-var _graphqlsHealthcheckHealthcheckGraphql = []byte(`# 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.
-
-query {
-    checkHealth {
-        score
-        details
-    }
-}
-`)
-
-func graphqlsHealthcheckHealthcheckGraphqlBytes() ([]byte, error) {
-	return _graphqlsHealthcheckHealthcheckGraphql, nil
-}
-
-func graphqlsHealthcheckHealthcheckGraphql() (*asset, error) {
-	bytes, err := graphqlsHealthcheckHealthcheckGraphqlBytes()
-	if err != nil {
-		return nil, err
-	}
-
-	info := bindataFileInfo{name: "graphqls/healthcheck/healthcheck.graphql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
-	a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc0, 0x71, 0x53, 0x13, 0xd0, 0x51, 0xd7, 0x12, 0xd1, 0xed, 0xd9, 0x34, 0x17, 0xef, 0x22, 0xf8, 0xa0, 0xa2, 0x35, 0x57, 0xb, 0x54, 0x6d, 0x5a, 0xb1, 0x8f, 0xbd, 0xb3, 0x40, 0x34, 0xc2, 0x2d}}
-	return a, nil
-}
-
-var _graphqlsLogsLogsGraphql = []byte(`# 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.
-
-query ($condition: LogQueryCondition!) {
-    result: queryLogs(condition: $condition) {
-        total
-        logs {
-            serviceName
-            serviceId
-            serviceInstanceName
-            serviceInstanceId
-            endpointName
-            endpointId
-            traceId
-            timestamp
-            contentType
-            content
-            tags {
-                key
-                value
-            }
-        }
-    }
-}
-`)
-
-func graphqlsLogsLogsGraphqlBytes() ([]byte, error) {
-	return _graphqlsLogsLogsGraphql, nil
-}
-
-func graphqlsLogsLogsGraphql() (*asset, error) {
-	bytes, err := graphqlsLogsLogsGraphqlBytes()
-	if err != nil {
-		return nil, err
-	}
-
-	info := bindataFileInfo{name: "graphqls/logs/Logs.graphql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
-	a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x5, 0xb, 0x5c, 0x60, 0x9b, 0x18, 0x98, 0xa0, 0xdd, 0x60, 0x42, 0x91, 0x53, 0x25, 0xcd, 0x59, 0xa5, 0x1c, 0xff, 0xc3, 0xf7, 0xf0, 0x45, 0xb3, 0xf7, 0xcd, 0xd8, 0x63, 0xee, 0x9f, 0x6a, 0x3a}}
-	return a, nil
-}
-
-var _graphqlsMetadataAllservicesGraphql = []byte(`# 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.
-
-query ($duration: Duration!) {
-    result: getAllServices(duration: $duration) {
-        id name
-    }
-}
-`)
-
-func graphqlsMetadataAllservicesGraphqlBytes() ([]byte, error) {
-	return _graphqlsMetadataAllservicesGraphql, nil
-}
-
-func graphqlsMetadataAllservicesGraphql() (*asset, error) {
-	bytes, err := graphqlsMetadataAllservicesGraphqlBytes()
-	if err != nil {
-		return nil, err
-	}
-
-	info := bindataFileInfo{name: "graphqls/metadata/AllServices.graphql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
-	a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xa1, 0xe0, 0xdf, 0xca, 0xb7, 0xa1, 0xbb, 0x88, 0x28, 0x9b, 0x49, 0x2a, 0x19, 0x51, 0xfc, 0xec, 0xab, 0x17, 0x36, 0xb6, 0x33, 0x17, 0x87, 0xd1, 0xd1, 0x98, 0xd, 0x5, 0xc5, 0x82, 0x82, 0xed}}
-	return a, nil
-}
-
-var _graphqlsMetadataInstancesGraphql = []byte(`# 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.
-
-
-query ($serviceId: ID!, $duration: Duration!) {
-    result: getServiceInstances(duration: $duration, serviceId: $serviceId) {
-        id
-        name
-        language
-        instanceUUID
-        attributes {
-            name
-            value
-        }
-    }
-}
-`)
-
-func graphqlsMetadataInstancesGraphqlBytes() ([]byte, error) {
-	return _graphqlsMetadataInstancesGraphql, nil
-}
-
-func graphqlsMetadataInstancesGraphql() (*asset, error) {
-	bytes, err := graphqlsMetadataInstancesGraphqlBytes()
-	if err != nil {
-		return nil, err
-	}
-
-	info := bindataFileInfo{name: "graphqls/metadata/Instances.graphql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
-	a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x98, 0xdb, 0x11, 0xad, 0x8f, 0x96, 0x8c, 0xf0, 0xf, 0x63, 0x2e, 0x35, 0x83, 0xe5, 0xb9, 0x81, 0xe8, 0x79, 0x98, 0x5d, 0xb, 0xec, 0xc7, 0xdf, 0x67, 0x7b, 0x6e, 0x3f, 0xe3, 0x4, 0x80, 0x9e}}
-	return a, nil
-}
-
-var _graphqlsMetadataSearchendpointsGraphql = []byte(`# 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.
-
-query ($keyword: String!, $serviceId: ID!, $limit: Int!) {
-    result: searchEndpoint(keyword: $keyword, serviceId: $serviceId, limit: $limit) {
-        id name
-    }
-}
-`)
-
-func graphqlsMetadataSearchendpointsGraphqlBytes() ([]byte, error) {
-	return _graphqlsMetadataSearchendpointsGraphql, nil
-}
-
-func graphqlsMetadataSearchendpointsGraphql() (*asset, error) {
-	bytes, err := graphqlsMetadataSearchendpointsGraphqlBytes()
-	if err != nil {
-		return nil, err
-	}
-
-	info := bindataFileInfo{name: "graphqls/metadata/SearchEndpoints.graphql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
-	a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xdb, 0x8b, 0xad, 0xa0, 0x77, 0x43, 0x29, 0x8e, 0x6a, 0x7d, 0x1a, 0x68, 0x73, 0x66, 0x26, 0xe2, 0x66, 0xe3, 0xe3, 0xde, 0xca, 0xb5, 0x7, 0x8e, 0xf8, 0xd2, 0x62, 0x9a, 0x91, 0x3a, 0xab, 0xc9}}
-	return a, nil
-}
-
-var _graphqlsMetadataSearchserviceGraphql = []byte(`# 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.
-
-query searchService($serviceCode: String!) {
-    result: searchService(serviceCode: $serviceCode) {
-        id name
-    }
-}
-`)
-
-func graphqlsMetadataSearchserviceGraphqlBytes() ([]byte, error) {
-	return _graphqlsMetadataSearchserviceGraphql, nil
-}
-
-func graphqlsMetadataSearchserviceGraphql() (*asset, error) {
-	bytes, err := graphqlsMetadataSearchserviceGraphqlBytes()
-	if err != nil {
-		return nil, err
-	}
-
-	info := bindataFileInfo{name: "graphqls/metadata/SearchService.graphql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
-	a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xba, 0x2b, 0x8e, 0x55, 0x40, 0xf3, 0x8e, 0x89, 0x6f, 0x60, 0xff, 0x64, 0x51, 0xe5, 0xe5, 0x63, 0xc4, 0xe2, 0x78, 0x91, 0x39, 0xb6, 0x59, 0x3f, 0x31, 0xb5, 0xe4, 0x47, 0xbc, 0xa6, 0xd6, 0xd2}}
-	return a, nil
-}
-
-var _graphqlsMetadataServertimeinfoGraphql = []byte(`# 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.
-
-query {
-    result: getTimeInfo {
-        timezone, currentTimestamp
-    }
-}
-`)
-
-func graphqlsMetadataServertimeinfoGraphqlBytes() ([]byte, error) {
-	return _graphqlsMetadataServertimeinfoGraphql, nil
-}
-
-func graphqlsMetadataServertimeinfoGraphql() (*asset, error) {
-	bytes, err := graphqlsMetadataServertimeinfoGraphqlBytes()
-	if err != nil {
-		return nil, err
-	}
-
-	info := bindataFileInfo{name: "graphqls/metadata/ServerTimeInfo.graphql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
-	a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x38, 0xa2, 0xfb, 0x31, 0x64, 0x77, 0xd0, 0x20, 0xc1, 0x6b, 0xac, 0x8e, 0x2e, 0x8b, 0xf7, 0x89, 0x4b, 0x7b, 0xe8, 0xbb, 0x7e, 0x90, 0x76, 0x35, 0xc8, 0xb1, 0x5e, 0xad, 0x9a, 0xd2, 0x2c, 0x1c}}
-	return a, nil
-}
-
-var _graphqlsMetricsHeatmapGraphql = []byte(`# 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.
-
-query ($condition: MetricsCondition!, $duration: Duration!) {
-    result: readHeatMap(condition: $condition, duration: $duration) {
-        values {
-            id
-            values
-        }
-        buckets {
-            min
-            max
-        }
-    }
-}
-`)
-
-func graphqlsMetricsHeatmapGraphqlBytes() ([]byte, error) {
-	return _graphqlsMetricsHeatmapGraphql, nil
-}
-
-func graphqlsMetricsHeatmapGraphql() (*asset, error) {
-	bytes, err := graphqlsMetricsHeatmapGraphqlBytes()
-	if err != nil {
-		return nil, err
-	}
-
-	info := bindataFileInfo{name: "graphqls/metrics/HeatMap.graphql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
-	a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x4f, 0x41, 0x5d, 0xdd, 0xfa, 0x49, 0x96, 0x85, 0xc8, 0x61, 0x79, 0x12, 0xcb, 0xa3, 0x4d, 0x45, 0x66, 0x7f, 0x9f, 0x2c, 0x4c, 0xbd, 0xb3, 0xf3, 0xe8, 0x58, 0x3, 0xec, 0x1f, 0x4e, 0x5b, 0xde}}
-	return a, nil
-}
-
-var _graphqlsMetricsLabeledmetricsvaluesGraphql = []byte(`# 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.
-
-query ($condition: MetricsCondition!, $labels: [String!]!, $duration: Duration!) {
-    result: readLabeledMetricsValues(condition: $condition, labels: $labels, duration: $duration) {
-        label
-        values {
-            values {
-                value
-            }
-        }
-    }
-}
-`)
-
-func graphqlsMetricsLabeledmetricsvaluesGraphqlBytes() ([]byte, error) {
-	return _graphqlsMetricsLabeledmetricsvaluesGraphql, nil
-}
-
-func graphqlsMetricsLabeledmetricsvaluesGraphql() (*asset, error) {
-	bytes, err := graphqlsMetricsLabeledmetricsvaluesGraphqlBytes()
-	if err != nil {
-		return nil, err
-	}
-
-	info := bindataFileInfo{name: "graphqls/metrics/LabeledMetricsValues.graphql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
-	a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x74, 0xca, 0xe6, 0xdb, 0x5e, 0x7d, 0x34, 0x8c, 0x8c, 0x33, 0x2d, 0xe9, 0xe3, 0x40, 0xd8, 0x5c, 0xfc, 0xe, 0x76, 0x53, 0x31, 0xac, 0x4e, 0xb4, 0x60, 0x93, 0x4b, 0xca, 0x8a, 0x1a, 0xa7, 0xc1}}
-	return a, nil
-}
-
-var _graphqlsMetricsListmetricsGraphql = []byte(`# 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.
-
-query ($regex: String!) {
-    result: listMetrics(regex: $regex) {
-        name
-        type
-        catalog
-    }
-}
-`)
-
-func graphqlsMetricsListmetricsGraphqlBytes() ([]byte, error) {
-	return _graphqlsMetricsListmetricsGraphql, nil
-}
-
-func graphqlsMetricsListmetricsGraphql() (*asset, error) {
-	bytes, err := graphqlsMetricsListmetricsGraphqlBytes()
-	if err != nil {
-		return nil, err
-	}
-
-	info := bindataFileInfo{name: "graphqls/metrics/ListMetrics.graphql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
-	a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x48, 0x1c, 0x96, 0x32, 0x29, 0x80, 0x57, 0x43, 0x83, 0xc2, 0xd3, 0xd8, 0x48, 0xaf, 0x14, 0x43, 0xd, 0xc6, 0x67, 0x3a, 0x83, 0x66, 0xf, 0xaa, 0x6b, 0xd5, 0xff, 0x85, 0x1, 0x2f, 0x49, 0xdf}}
-	return a, nil
-}
-
-var _graphqlsMetricsMetricsvalueGraphql = []byte(`# 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.
-
-query ($condition: MetricsCondition!, $duration: Duration!) {
-    result: readMetricsValue(condition: $condition, duration: $duration)
-}
-`)
-
-func graphqlsMetricsMetricsvalueGraphqlBytes() ([]byte, error) {
-	return _graphqlsMetricsMetricsvalueGraphql, nil
-}
-
-func graphqlsMetricsMetricsvalueGraphql() (*asset, error) {
-	bytes, err := graphqlsMetricsMetricsvalueGraphqlBytes()
-	if err != nil {
-		return nil, err
-	}
-
-	info := bindataFileInfo{name: "graphqls/metrics/MetricsValue.graphql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
-	a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x5, 0xe, 0xee, 0xbc, 0xfa, 0xbe, 0x4, 0x85, 0xb9, 0x48, 0x6a, 0xda, 0x12, 0x14, 0x77, 0xe4, 0x6d, 0x34, 0x83, 0x79, 0x28, 0x30, 0x7e, 0xf, 0xe3, 0xa5, 0xe5, 0xd8, 0x11, 0x51, 0xa2, 0xfe}}
-	return a, nil
-}
-
-var _graphqlsMetricsMetricsvaluesGraphql = []byte(`# 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.
-
-query ($condition: MetricsCondition!, $duration: Duration!) {
-    result: readMetricsValues(condition: $condition, duration: $duration) {
-        label
-        values {
-            values {
-                value
-            }
-        }
-    }
-}
-`)
-
-func graphqlsMetricsMetricsvaluesGraphqlBytes() ([]byte, error) {
-	return _graphqlsMetricsMetricsvaluesGraphql, nil
-}
-
-func graphqlsMetricsMetricsvaluesGraphql() (*asset, error) {
-	bytes, err := graphqlsMetricsMetricsvaluesGraphqlBytes()
-	if err != nil {
-		return nil, err
-	}
-
-	info := bindataFileInfo{name: "graphqls/metrics/MetricsValues.graphql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
-	a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x9c, 0xc9, 0x71, 0xb6, 0xab, 0x2, 0x23, 0x2f, 0x1b, 0x73, 0xe1, 0xd1, 0x6d, 0xa1, 0x5e, 0xb4, 0xb1, 0xc4, 0x6e, 0xdb, 0x22, 0x7b, 0x68, 0x49, 0x76, 0x1b, 0x8, 0x64, 0xae, 0x15, 0x70, 0xbd}}
-	return a, nil
-}
-
-var _graphqlsMetricsSortmetricsGraphql = []byte(`# 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.
-
-query ($condition:TopNCondition!, $duration: Duration!) {
-    result: sortMetrics(condition: $condition, duration: $duration) {
-        name
-        value
-    }
-}
-`)
-
-func graphqlsMetricsSortmetricsGraphqlBytes() ([]byte, error) {
-	return _graphqlsMetricsSortmetricsGraphql, nil
-}
-
-func graphqlsMetricsSortmetricsGraphql() (*asset, error) {
-	bytes, err := graphqlsMetricsSortmetricsGraphqlBytes()
-	if err != nil {
-		return nil, err
-	}
-
-	info := bindataFileInfo{name: "graphqls/metrics/SortMetrics.graphql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
-	a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x5b, 0xfc, 0xe0, 0x9, 0x92, 0xe3, 0xe5, 0x24, 0x29, 0x7c, 0x4c, 0x8e, 0xe6, 0x2d, 0x54, 0xb0, 0x34, 0xcd, 0x2a, 0x82, 0xd, 0x4e, 0xa9, 0xed, 0x51, 0x64, 0x77, 0x52, 0xbf, 0x48, 0x6f, 0x7a}}
-	return a, nil
-}
-
-var _graphqlsProfileCreatetaskGraphql = []byte(`# 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.
-
-mutation ($condition: ProfileTaskCreationRequest) {
-    result: createProfileTask(creationRequest: $condition) {
-      errorReason: errorReason
-      id: id
-    }
-}
-`)
-
-func graphqlsProfileCreatetaskGraphqlBytes() ([]byte, error) {
-	return _graphqlsProfileCreatetaskGraphql, nil
-}
-
-func graphqlsProfileCreatetaskGraphql() (*asset, error) {
-	bytes, err := graphqlsProfileCreatetaskGraphqlBytes()
-	if err != nil {
-		return nil, err
-	}
-
-	info := bindataFileInfo{name: "graphqls/profile/CreateTask.graphql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
-	a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x4f, 0xcc, 0x41, 0xa2, 0xe6, 0x43, 0x55, 0xfb, 0x37, 0x34, 0x52, 0x74, 0x8c, 0xf3, 0x96, 0x2d, 0x14, 0x43, 0x5e, 0x3c, 0x5a, 0xf1, 0xc2, 0x3b, 0x45, 0xaf, 0xf2, 0xd2, 0xb, 0xbe, 0x38, 0xaf}}
-	return a, nil
-}
-
-var _graphqlsProfileGetprofileanalyzeGraphql = []byte(`# 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.
-
-query ($segmentId: String!, $timeRanges: [ProfileAnalyzeTimeRange!]!) {
-    result: getProfileAnalyze(segmentId: $segmentId, timeRanges: $timeRanges) {
-        trees {
-    		elements {
-              id
-              parentId
-              codeSignature
-              duration
-              durationChildExcluded
-              count
-    		}
-    	}
-    }
-}`)
-
-func graphqlsProfileGetprofileanalyzeGraphqlBytes() ([]byte, error) {
-	return _graphqlsProfileGetprofileanalyzeGraphql, nil
-}
-
-func graphqlsProfileGetprofileanalyzeGraphql() (*asset, error) {
-	bytes, err := graphqlsProfileGetprofileanalyzeGraphqlBytes()
-	if err != nil {
-		return nil, err
-	}
-
-	info := bindataFileInfo{name: "graphqls/profile/GetProfileAnalyze.graphql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
-	a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xa0, 0x24, 0x39, 0x6d, 0x3b, 0x8e, 0x62, 0x8, 0xb, 0xec, 0xa6, 0xa9, 0x51, 0xc8, 0x8a, 0x4, 0xf7, 0x7a, 0x58, 0x1d, 0xf2, 0x6c, 0x5a, 0x1e, 0x8d, 0x8a, 0x87, 0x18, 0xda, 0xc5, 0xe7, 0xe7}}
-	return a, nil
-}
-
-var _graphqlsProfileGetprofiledsegmentGraphql = []byte(`# 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.
-
-query ($segmentId: String!) {
-    result: getProfiledSegment(segmentId: $segmentId) {
-        spans {
-           spanId
-           parentSpanId
-           serviceCode
-           startTime
-           endTime
-           endpointName
-           type
-           peer
-           component
-           isError
-           layer
-           tags {
-               key value
-           }
-        }
-    }
-}`)
-
-func graphqlsProfileGetprofiledsegmentGraphqlBytes() ([]byte, error) {
-	return _graphqlsProfileGetprofiledsegmentGraphql, nil
-}
-
-func graphqlsProfileGetprofiledsegmentGraphql() (*asset, error) {
-	bytes, err := graphqlsProfileGetprofiledsegmentGraphqlBytes()
-	if err != nil {
-		return nil, err
-	}
-
-	info := bindataFileInfo{name: "graphqls/profile/GetProfiledSegment.graphql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
-	a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x4b, 0x91, 0x47, 0x18, 0x20, 0x4b, 0x3f, 0x67, 0xfc, 0x9b, 0x4b, 0xfc, 0x95, 0xf8, 0xe8, 0x5a, 0x5f, 0x5c, 0x81, 0x7d, 0xb1, 0x27, 0xb9, 0x89, 0xf4, 0xc0, 0xfd, 0x4f, 0x1e, 0x5b, 0x69, 0xa5}}
-	return a, nil
-}
-
-var _graphqlsProfileGettasklistGraphql = []byte(`# 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.
-
-query ($serviceId: ID, $endpointName: String) {
-    result: getProfileTaskList(serviceId: $serviceId, endpointName: $endpointName) {
-        id
-        serviceId
-        endpointName
-        startTime
-        duration
-        minDurationThreshold
-        dumpPeriod
-        maxSamplingCount
-        logs {
-          id
-          instanceId
-          operationType
-          operationTime
-        }
-    }
-}`)
-
-func graphqlsProfileGettasklistGraphqlBytes() ([]byte, error) {
-	return _graphqlsProfileGettasklistGraphql, nil
-}
-
-func graphqlsProfileGettasklistGraphql() (*asset, error) {
-	bytes, err := graphqlsProfileGettasklistGraphqlBytes()
-	if err != nil {
-		return nil, err
-	}
-
-	info := bindataFileInfo{name: "graphqls/profile/GetTaskList.graphql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
-	a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x87, 0xe0, 0x1c, 0x5a, 0x5, 0x9c, 0x4a, 0xf7, 0xce, 0x2f, 0x91, 0x6a, 0x2f, 0x5d, 0x9a, 0x7, 0x15, 0xf6, 0xa3, 0x5a, 0x50, 0x40, 0xff, 0x71, 0xfc, 0xde, 0xa7, 0x91, 0x13, 0x77, 0xca, 0xc2}}
-	return a, nil
-}
-
-var _graphqlsProfileGettasksegmentlistGraphql = []byte(`# 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.
-
-query ($taskId: String!) {
-    result: getProfileTaskSegmentList(taskID: $taskId) {
-        segmentId
-        endpointNames
-        duration
-        start
-        isError
-        traceIds
-    }
-}`)
-
-func graphqlsProfileGettasksegmentlistGraphqlBytes() ([]byte, error) {
-	return _graphqlsProfileGettasksegmentlistGraphql, nil
-}
-
-func graphqlsProfileGettasksegmentlistGraphql() (*asset, error) {
-	bytes, err := graphqlsProfileGettasksegmentlistGraphqlBytes()
-	if err != nil {
-		return nil, err
-	}
-
-	info := bindataFileInfo{name: "graphqls/profile/GetTaskSegmentList.graphql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
-	a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xd5, 0xaf, 0xab, 0xf5, 0x2, 0x57, 0xbe, 0x94, 0x9, 0x3f, 0xae, 0x9, 0x51, 0xf3, 0xd6, 0x9b, 0x72, 0x70, 0xc2, 0xba, 0xf7, 0x6c, 0xac, 0x8f, 0x1a, 0x4c, 0xf, 0x28, 0x3e, 0x94, 0x8f, 0x8d}}
-	return a, nil
-}
-
-var _graphqlsTraceTraceGraphql = []byte(`# 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.
-
-query ($traceId: ID!) {
-    result: queryTrace(traceId: $traceId) {
-        spans {
-            traceId
-            segmentId
-            spanId
-            parentSpanId
-            refs {
-                traceId
-                parentSegmentId
-                parentSpanId
-                type
-            }
-            serviceCode
-            serviceInstanceName
-            startTime
-            endTime
-            endpointName
-            type
-            peer
-            component
-            isError
-            layer
-            tags {
-                key value
-            }
-            logs {
-                time data {
-                    key value
-                }
-            }
-        }
-    }
-}
-`)
-
-func graphqlsTraceTraceGraphqlBytes() ([]byte, error) {
-	return _graphqlsTraceTraceGraphql, nil
-}
-
-func graphqlsTraceTraceGraphql() (*asset, error) {
-	bytes, err := graphqlsTraceTraceGraphqlBytes()
-	if err != nil {
-		return nil, err
-	}
-
-	info := bindataFileInfo{name: "graphqls/trace/Trace.graphql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
-	a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x4f, 0x37, 0xaa, 0xc4, 0x71, 0x9f, 0x64, 0xfa, 0xf, 0x97, 0x8c, 0x5a, 0x6c, 0xe8, 0x94, 0xd2, 0x2d, 0x69, 0xbb, 0xbf, 0xf2, 0x1b, 0x3d, 0x11, 0xf3, 0x63, 0xba, 0xc3, 0x16, 0x2a, 0xca, 0xd7}}
-	return a, nil
-}
-
-var _graphqlsTraceTracesGraphql = []byte(`# 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.
-
-query ($condition: TraceQueryCondition!){
-    result: queryBasicTraces(condition: $condition){
-        total
-        traces {
-            segmentId
-            endpointNames
-            duration
-            start
-            isError
-            traceIds
-        }
-    }
-}`)
-
-func graphqlsTraceTracesGraphqlBytes() ([]byte, error) {
-	return _graphqlsTraceTracesGraphql, nil
-}
-
-func graphqlsTraceTracesGraphql() (*asset, error) {
-	bytes, err := graphqlsTraceTracesGraphqlBytes()
-	if err != nil {
-		return nil, err
-	}
-
-	info := bindataFileInfo{name: "graphqls/trace/Traces.graphql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
-	a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x30, 0xfb, 0x68, 0x9b, 0x61, 0x82, 0x37, 0x55, 0x87, 0x27, 0xcf, 0xd4, 0x39, 0x2b, 0x73, 0xf, 0x11, 0x8, 0x1c, 0x5, 0x78, 0x43, 0xb3, 0x49, 0x88, 0xc1, 0x65, 0x12, 0xf, 0xff, 0x4f, 0x66}}
-	return a, nil
-}
-
-var _templatesDashboardGlobalYml = []byte(((((`# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# The command ` + ("`" + `dashboard global`)) + (("`" + ` supports displaying three kinds of data:
-# `) + ("`" + `global metrics`))) + (("`" + (`, ` + "`")) + ((`global response latency` + "`") + (`, ` + "`")))) + (((`Global heat map` + ("`" + `.
-# If you don't want to display an item, you can just delete or comment its whole configuration below.
-# Generally, there is no need to modify properties unless there is a explanatory comment.
-
-# Set the style for the dashboard.
-style:
-  # Xterm colors number, an integer from 0 to 255.
-  # Refer to https://jonasjacek.github.io/colors/ to change to other colors.
-  buttonColor: 220
-  titleColor: 9
-  gaugeColor: 13
-
-# The global metrics, there are four kinds of metrics displaying by default.
-# Each metric will occupy one column to display.
-# Similarly, you can delete or comment corresponding whole configuration to change the metrics to be displayed.
-metrics:
-  - condition:
-      name: "service_cpm"
-      normal: true
-      scope: "Service"
-      # You can modify `)) + (("`" + `topN`) + ("`" + ` to change the amount of results to be displayed, the same below.
-      topN: 10
-      # You can modify `))) + ((("`" + `order`) + ("`" + ` to `)) + (("`" + `ASC`) + ("`" + ` to display the results in ascending order, the same below.
-      order: "DES"
-    title: " Service Load (calls/min) "
-
-  - condition:
-      name: "service_resp_time"
-      normal: true
-      scope: "Service"
-      topN: 10
-      order: "DES"
-    title: "    Slow Services (ms)    "
-
-  - condition:
-      name: "service_apdex"
-      normal: true
-      scope: "Service"
-      topN: 10
-      order: "ASC"
-    title: "Un-Health Services (Apdex)"
-    # The returned apdex data is integer, like '3115',
-    # need to be converted into a number between 0 and 1.
-    aggregation: "/"
-    aggregationNum: 10000
-
-  - condition:
-      name: "endpoint_avg"
-      normal: true
-      scope: "Endpoint"
-      topN: 10
-      order: "DES"
-    title: "    Slow Endpoints (ms)   "
-
-# Global response latency.
-responseLatency:
-  condition:
-    name: "all_percentile"
-    entity:
-      scope: "All"
-      normal: true
-  labels: "P50, P75, P90, P95, P99"
-  labelsIndex: "0, 1, 2, 3, 4"
-  title: "Global Response Latency"
-  unit: "percentile in ms"
-
-# Global heat map.
-heatMap:
-  condition:
-    name: "all_heatmap"
-    entity:
-      scope: "All"
-      normal: true
-  title: "Global Heatmap"
-  unit: "ms"`))))))
-
-func templatesDashboardGlobalYmlBytes() ([]byte, error) {
-	return _templatesDashboardGlobalYml, nil
-}
-
-func templatesDashboardGlobalYml() (*asset, error) {
-	bytes, err := templatesDashboardGlobalYmlBytes()
-	if err != nil {
-		return nil, err
-	}
-
-	info := bindataFileInfo{name: "templates/dashboard/global.yml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
-	a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe, 0x46, 0xab, 0x48, 0xaa, 0x2, 0x58, 0xb6, 0x2b, 0x28, 0x5c, 0xee, 0x7e, 0x5d, 0x77, 0xfb, 0xce, 0x6d, 0x6b, 0x6d, 0xa9, 0xde, 0xed, 0xed, 0x60, 0x9a, 0xfe, 0x47, 0xca, 0xea, 0x33, 0x9f}}
-	return a, nil
-}
-
-// Asset loads and returns the asset for the given name.
-// It returns an error if the asset could not be found or
-// could not be loaded.
-func Asset(name string) ([]byte, error) {
-	canonicalName := strings.Replace(name, "\\", "/", -1)
-	if f, ok := _bindata[canonicalName]; ok {
-		a, err := f()
-		if err != nil {
-			return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err)
-		}
-		return a.bytes, nil
-	}
-	return nil, fmt.Errorf("Asset %s not found", name)
-}
-
-// AssetString returns the asset contents as a string (instead of a []byte).
-func AssetString(name string) (string, error) {
-	data, err := Asset(name)
-	return string(data), err
-}
-
-// MustAsset is like Asset but panics when Asset would return an error.
-// It simplifies safe initialization of global variables.
-func MustAsset(name string) []byte {
-	a, err := Asset(name)
-	if err != nil {
-		panic("asset: Asset(" + name + "): " + err.Error())
-	}
-
-	return a
-}
-
-// MustAssetString is like AssetString but panics when Asset would return an
-// error. It simplifies safe initialization of global variables.
-func MustAssetString(name string) string {
-	return string(MustAsset(name))
-}
-
-// AssetInfo loads and returns the asset info for the given name.
-// It returns an error if the asset could not be found or
-// could not be loaded.
-func AssetInfo(name string) (os.FileInfo, error) {
-	canonicalName := strings.Replace(name, "\\", "/", -1)
-	if f, ok := _bindata[canonicalName]; ok {
-		a, err := f()
-		if err != nil {
-			return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err)
-		}
-		return a.info, nil
-	}
-	return nil, fmt.Errorf("AssetInfo %s not found", name)
-}
-
-// AssetDigest returns the digest of the file with the given name. It returns an
-// error if the asset could not be found or the digest could not be loaded.
-func AssetDigest(name string) ([sha256.Size]byte, error) {
-	canonicalName := strings.Replace(name, "\\", "/", -1)
-	if f, ok := _bindata[canonicalName]; ok {
-		a, err := f()
-		if err != nil {
-			return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s can't read by error: %v", name, err)
-		}
-		return a.digest, nil
-	}
-	return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s not found", name)
-}
-
-// Digests returns a map of all known files and their checksums.
-func Digests() (map[string][sha256.Size]byte, error) {
-	mp := make(map[string][sha256.Size]byte, len(_bindata))
-	for name := range _bindata {
-		a, err := _bindata[name]()
-		if err != nil {
-			return nil, err
-		}
-		mp[name] = a.digest
-	}
-	return mp, nil
-}
-
-// AssetNames returns the names of the assets.
-func AssetNames() []string {
-	names := make([]string, 0, len(_bindata))
-	for name := range _bindata {
-		names = append(names, name)
-	}
-	return names
-}
-
-// _bindata is a table, holding each asset generator, mapped to its name.
-var _bindata = map[string]func() (*asset, error){
-	"cr/oap.yaml": crOapYaml,
-	"cr/ui.yaml":  crUiYaml,
-	"graphqls/dependency/EndpointDependency.graphql": graphqlsDependencyEndpointdependencyGraphql,
-	"graphqls/dependency/InstanceTopology.graphql":   graphqlsDependencyInstancetopologyGraphql,
-	"graphqls/dependency/ServiceTopology.graphql":    graphqlsDependencyServicetopologyGraphql,
-	"graphqls/event/events.graphql":                  graphqlsEventEventsGraphql,
-	"graphqls/healthcheck/healthcheck.graphql":       graphqlsHealthcheckHealthcheckGraphql,
-	"graphqls/logs/Logs.graphql":                     graphqlsLogsLogsGraphql,
-	"graphqls/metadata/AllServices.graphql":          graphqlsMetadataAllservicesGraphql,
-	"graphqls/metadata/Instances.graphql":            graphqlsMetadataInstancesGraphql,
-	"graphqls/metadata/SearchEndpoints.graphql":      graphqlsMetadataSearchendpointsGraphql,
-	"graphqls/metadata/SearchService.graphql":        graphqlsMetadataSearchserviceGraphql,
-	"graphqls/metadata/ServerTimeInfo.graphql":       graphqlsMetadataServertimeinfoGraphql,
-	"graphqls/metrics/HeatMap.graphql":               graphqlsMetricsHeatmapGraphql,
-	"graphqls/metrics/LabeledMetricsValues.graphql":  graphqlsMetricsLabeledmetricsvaluesGraphql,
-	"graphqls/metrics/ListMetrics.graphql":           graphqlsMetricsListmetricsGraphql,
-	"graphqls/metrics/MetricsValue.graphql":          graphqlsMetricsMetricsvalueGraphql,
-	"graphqls/metrics/MetricsValues.graphql":         graphqlsMetricsMetricsvaluesGraphql,
-	"graphqls/metrics/SortMetrics.graphql":           graphqlsMetricsSortmetricsGraphql,
-	"graphqls/profile/CreateTask.graphql":            graphqlsProfileCreatetaskGraphql,
-	"graphqls/profile/GetProfileAnalyze.graphql":     graphqlsProfileGetprofileanalyzeGraphql,
-	"graphqls/profile/GetProfiledSegment.graphql":    graphqlsProfileGetprofiledsegmentGraphql,
-	"graphqls/profile/GetTaskList.graphql":           graphqlsProfileGettasklistGraphql,
-	"graphqls/profile/GetTaskSegmentList.graphql":    graphqlsProfileGettasksegmentlistGraphql,
-	"graphqls/trace/Trace.graphql":                   graphqlsTraceTraceGraphql,
-	"graphqls/trace/Traces.graphql":                  graphqlsTraceTracesGraphql,
-	"templates/dashboard/global.yml":                 templatesDashboardGlobalYml,
-}
-
-// AssetDebug is true if the assets were built with the debug flag enabled.
-const AssetDebug = false
-
-// AssetDir returns the file names below a certain
-// directory embedded in the file by go-bindata.
-// For example if you run go-bindata on data/... and data contains the
-// following hierarchy:
-//     data/
-//       foo.txt
-//       img/
-//         a.png
-//         b.png
-// then AssetDir("data") would return []string{"foo.txt", "img"},
-// AssetDir("data/img") would return []string{"a.png", "b.png"},
-// AssetDir("foo.txt") and AssetDir("notexist") would return an error, and
-// AssetDir("") will return []string{"data"}.
-func AssetDir(name string) ([]string, error) {
-	node := _bintree
-	if len(name) != 0 {
-		canonicalName := strings.Replace(name, "\\", "/", -1)
-		pathList := strings.Split(canonicalName, "/")
-		for _, p := range pathList {
-			node = node.Children[p]
-			if node == nil {
-				return nil, fmt.Errorf("Asset %s not found", name)
-			}
-		}
-	}
-	if node.Func != nil {
-		return nil, fmt.Errorf("Asset %s not found", name)
-	}
-	rv := make([]string, 0, len(node.Children))
-	for childName := range node.Children {
-		rv = append(rv, childName)
-	}
-	return rv, nil
-}
-
-type bintree struct {
-	Func     func() (*asset, error)
-	Children map[string]*bintree
-}
-
-var _bintree = &bintree{nil, map[string]*bintree{
-	"cr": &bintree{nil, map[string]*bintree{
-		"oap.yaml": &bintree{crOapYaml, map[string]*bintree{}},
-		"ui.yaml":  &bintree{crUiYaml, map[string]*bintree{}},
-	}},
-	"graphqls": &bintree{nil, map[string]*bintree{
-		"dependency": &bintree{nil, map[string]*bintree{
-			"EndpointDependency.graphql": &bintree{graphqlsDependencyEndpointdependencyGraphql, map[string]*bintree{}},
-			"InstanceTopology.graphql":   &bintree{graphqlsDependencyInstancetopologyGraphql, map[string]*bintree{}},
-			"ServiceTopology.graphql":    &bintree{graphqlsDependencyServicetopologyGraphql, map[string]*bintree{}},
-		}},
-		"event": &bintree{nil, map[string]*bintree{
-			"events.graphql": &bintree{graphqlsEventEventsGraphql, map[string]*bintree{}},
-		}},
-		"healthcheck": &bintree{nil, map[string]*bintree{
-			"healthcheck.graphql": &bintree{graphqlsHealthcheckHealthcheckGraphql, map[string]*bintree{}},
-		}},
-		"logs": &bintree{nil, map[string]*bintree{
-			"Logs.graphql": &bintree{graphqlsLogsLogsGraphql, map[string]*bintree{}},
-		}},
-		"metadata": &bintree{nil, map[string]*bintree{
-			"AllServices.graphql":     &bintree{graphqlsMetadataAllservicesGraphql, map[string]*bintree{}},
-			"Instances.graphql":       &bintree{graphqlsMetadataInstancesGraphql, map[string]*bintree{}},
-			"SearchEndpoints.graphql": &bintree{graphqlsMetadataSearchendpointsGraphql, map[string]*bintree{}},
-			"SearchService.graphql":   &bintree{graphqlsMetadataSearchserviceGraphql, map[string]*bintree{}},
-			"ServerTimeInfo.graphql":  &bintree{graphqlsMetadataServertimeinfoGraphql, map[string]*bintree{}},
-		}},
-		"metrics": &bintree{nil, map[string]*bintree{
-			"HeatMap.graphql":              &bintree{graphqlsMetricsHeatmapGraphql, map[string]*bintree{}},
-			"LabeledMetricsValues.graphql": &bintree{graphqlsMetricsLabeledmetricsvaluesGraphql, map[string]*bintree{}},
-			"ListMetrics.graphql":          &bintree{graphqlsMetricsListmetricsGraphql, map[string]*bintree{}},
-			"MetricsValue.graphql":         &bintree{graphqlsMetricsMetricsvalueGraphql, map[string]*bintree{}},
-			"MetricsValues.graphql":        &bintree{graphqlsMetricsMetricsvaluesGraphql, map[string]*bintree{}},
-			"SortMetrics.graphql":          &bintree{graphqlsMetricsSortmetricsGraphql, map[string]*bintree{}},
-		}},
-		"profile": &bintree{nil, map[string]*bintree{
-			"CreateTask.graphql":         &bintree{graphqlsProfileCreatetaskGraphql, map[string]*bintree{}},
-			"GetProfileAnalyze.graphql":  &bintree{graphqlsProfileGetprofileanalyzeGraphql, map[string]*bintree{}},
-			"GetProfiledSegment.graphql": &bintree{graphqlsProfileGetprofiledsegmentGraphql, map[string]*bintree{}},
-			"GetTaskList.graphql":        &bintree{graphqlsProfileGettasklistGraphql, map[string]*bintree{}},
-			"GetTaskSegmentList.graphql": &bintree{graphqlsProfileGettasksegmentlistGraphql, map[string]*bintree{}},
-		}},
-		"trace": &bintree{nil, map[string]*bintree{
-			"Trace.graphql":  &bintree{graphqlsTraceTraceGraphql, map[string]*bintree{}},
-			"Traces.graphql": &bintree{graphqlsTraceTracesGraphql, map[string]*bintree{}},
-		}},
-	}},
-	"templates": &bintree{nil, map[string]*bintree{
-		"dashboard": &bintree{nil, map[string]*bintree{
-			"global.yml": &bintree{templatesDashboardGlobalYml, map[string]*bintree{}},
-		}},
-	}},
-}}
-
-// RestoreAsset restores an asset under the given directory.
-func RestoreAsset(dir, name string) error {
-	data, err := Asset(name)
-	if err != nil {
-		return err
-	}
-	info, err := AssetInfo(name)
-	if err != nil {
-		return err
-	}
-	err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755))
-	if err != nil {
-		return err
-	}
-	err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode())
-	if err != nil {
-		return err
-	}
-	return os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime())
-}
-
-// RestoreAssets restores an asset under the given directory recursively.
-func RestoreAssets(dir, name string) error {
-	children, err := AssetDir(name)
-	// File
-	if err != nil {
-		return RestoreAsset(dir, name)
-	}
-	// Dir
-	for _, child := range children {
-		err = RestoreAssets(dir, filepath.Join(name, child))
-		if err != nil {
-			return err
-		}
-	}
-	return nil
-}
-
-func _filePath(dir, name string) string {
-	canonicalName := strings.Replace(name, "\\", "/", -1)
-	return filepath.Join(append([]string{dir}, strings.Split(canonicalName, "/")...)...)
-}
diff --git a/assets/assets.go b/assets/assets.go
index 665e0c3..5265f03 100644
--- a/assets/assets.go
+++ b/assets/assets.go
@@ -18,14 +18,19 @@
 package assets
 
 import (
+	"embed"
+
 	"github.com/apache/skywalking-cli/internal/logger"
 )
 
+//go:embed *
+var assets embed.FS
+
 // Read reads all content from a file under assets, which is packed in to the binary
 func Read(filename string) string {
-	content, err := AssetString(filename)
+	content, err := assets.ReadFile(filename)
 	if err != nil {
 		logger.Log.Fatalln("failed to read asset: ", filename, err)
 	}
-	return content
+	return string(content)
 }
diff --git a/assets/graphqls/dependency/EndpointDependency.graphql b/assets/graphqls/dependency/EndpointDependency.graphql
index 3310b9a..6db3336 100644
--- a/assets/graphqls/dependency/EndpointDependency.graphql
+++ b/assets/graphqls/dependency/EndpointDependency.graphql
@@ -22,7 +22,7 @@ query ($endpointId:ID!, $duration: Duration!) {
             name
             serviceId
             serviceName
-            type         
+            type
             isReal
         }
         calls {
@@ -30,6 +30,6 @@ query ($endpointId:ID!, $duration: Duration!) {
             source
             target
             detectPoints
-        }        
+        }
     }
 }
diff --git a/assets/graphqls/profile/CreateTask.graphql b/assets/graphqls/profile/CreateTask.graphql
index 0ab38df..683f8d8 100644
--- a/assets/graphqls/profile/CreateTask.graphql
+++ b/assets/graphqls/profile/CreateTask.graphql
@@ -17,7 +17,7 @@
 
 mutation ($condition: ProfileTaskCreationRequest) {
     result: createProfileTask(creationRequest: $condition) {
-      errorReason: errorReason
-      id: id
+        errorReason: errorReason
+        id: id
     }
 }
diff --git a/assets/graphqls/profile/GetProfileAnalyze.graphql b/assets/graphqls/profile/GetProfileAnalyze.graphql
index 49af788..a89d410 100644
--- a/assets/graphqls/profile/GetProfileAnalyze.graphql
+++ b/assets/graphqls/profile/GetProfileAnalyze.graphql
@@ -18,14 +18,14 @@
 query ($segmentId: String!, $timeRanges: [ProfileAnalyzeTimeRange!]!) {
     result: getProfileAnalyze(segmentId: $segmentId, timeRanges: $timeRanges) {
         trees {
-    		elements {
-              id
-              parentId
-              codeSignature
-              duration
-              durationChildExcluded
-              count
-    		}
-    	}
+            elements {
+                id
+                parentId
+                codeSignature
+                duration
+                durationChildExcluded
+                count
+            }
+        }
     }
-}
\ No newline at end of file
+}
diff --git a/assets/graphqls/profile/GetProfiledSegment.graphql b/assets/graphqls/profile/GetProfiledSegment.graphql
index 98214bf..80ee9ee 100644
--- a/assets/graphqls/profile/GetProfiledSegment.graphql
+++ b/assets/graphqls/profile/GetProfiledSegment.graphql
@@ -18,20 +18,20 @@
 query ($segmentId: String!) {
     result: getProfiledSegment(segmentId: $segmentId) {
         spans {
-           spanId
-           parentSpanId
-           serviceCode
-           startTime
-           endTime
-           endpointName
-           type
-           peer
-           component
-           isError
-           layer
-           tags {
-               key value
-           }
+            spanId
+            parentSpanId
+            serviceCode
+            startTime
+            endTime
+            endpointName
+            type
+            peer
+            component
+            isError
+            layer
+            tags {
+                key value
+            }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/assets/graphqls/profile/GetTaskList.graphql b/assets/graphqls/profile/GetTaskList.graphql
index 17f32ca..e1602c3 100644
--- a/assets/graphqls/profile/GetTaskList.graphql
+++ b/assets/graphqls/profile/GetTaskList.graphql
@@ -26,10 +26,10 @@ query ($serviceId: ID, $endpointName: String) {
         dumpPeriod
         maxSamplingCount
         logs {
-          id
-          instanceId
-          operationType
-          operationTime
+            id
+            instanceId
+            operationType
+            operationTime
         }
     }
-}
\ No newline at end of file
+}
diff --git a/cmd/swctl/main.go b/cmd/swctl/main.go
index dd4b677..72278b8 100644
--- a/cmd/swctl/main.go
+++ b/cmd/swctl/main.go
@@ -40,8 +40,8 @@ import (
 	"github.com/apache/skywalking-cli/pkg/util"
 
 	"github.com/sirupsen/logrus"
-	"github.com/urfave/cli"
-	"github.com/urfave/cli/altsrc"
+	"github.com/urfave/cli/v2"
+	"github.com/urfave/cli/v2/altsrc"
 )
 
 var log *logrus.Logger
@@ -60,64 +60,89 @@ func main() {
 
 	app := cli.NewApp()
 	app.Usage = "The CLI (Command Line Interface) for Apache SkyWalking."
+	app.UsageText = `Commands in SkyWalking CLI are organized into two levels,
+in the form of "swctl --option <level1> --option <level2> --option",
+there are options in each level, which should follow right after
+the corresponding command, take the following command as example:
+
+	$ swctl --debug service list --start="2019-11-11" --end="2019-11-12"
+
+where "--debug" is is an option of "swctl", and since the "swctl" is
+a top-level command, "--debug" is also called global option, and "--start"
+is an option of the third level command "list", there is no option for the
+second level command "service".
+
+Generally, the second level commands are entity related, there are entities
+like "service", "service instance", "metrics" in SkyWalking, and we have
+corresponding sub-command like "service"; the third level commands are
+operations on the entities, such as "list" command will list all the
+services, service instances, etc.
+`
 	app.Version = version
 
 	flags := []cli.Flag{
-		altsrc.NewStringFlag(cli.StringFlag{
+		altsrc.NewStringFlag(&cli.StringFlag{
 			Name:  "config",
 			Value: "~/.skywalking.yml",
-			Usage: "load configuration `FILE`",
+			Usage: "file `path` of the default configurations.",
 		}),
-		altsrc.NewStringFlag(cli.StringFlag{
+		altsrc.NewStringFlag(&cli.StringFlag{
 			Name:     "base-url",
 			Required: false,
-			Usage:    "base `url` of the OAP backend graphql",
+			Usage:    "base `url` of the OAP backend graphql service",
 			Value:    "http://127.0.0.1:12800/graphql",
 		}),
-		altsrc.NewStringFlag(cli.StringFlag{
-			Name:     "grpcAddr",
-			Usage:    "`host:port` to connect",
+		altsrc.NewStringFlag(&cli.StringFlag{
+			Name:     "grpc-addr",
+			Usage:    "backend gRPC service address `<host:port>`",
 			Value:    "127.0.0.1:11800",
 			Required: false,
 		}),
-		altsrc.NewStringFlag(cli.StringFlag{
+		altsrc.NewStringFlag(&cli.StringFlag{
 			Name:     "username",
 			Required: false,
-			Usage:    "username of basic authorization",
+			Usage:    "`username` of basic authorization",
 			Value:    "",
 		}),
-		altsrc.NewStringFlag(cli.StringFlag{
+		altsrc.NewStringFlag(&cli.StringFlag{
 			Name:     "password",
 			Required: false,
-			Usage:    "password of basic authorization",
+			Usage:    "`password` of basic authorization",
 			Value:    "",
 		}),
-		altsrc.NewStringFlag(cli.StringFlag{
+		altsrc.NewStringFlag(&cli.StringFlag{
 			Name:     "authorization",
 			Required: false,
-			Usage:    "authorization to the OAP backend",
-			Value:    "",
+			Usage: "`authorization` header, can be something like `Basic base64(username:password)` or `Bearer jwt-token`, " +
+				"if `authorization` is set, `--username` and `--password` are ignored",
+			Value: "",
 		}),
-		altsrc.NewStringFlag(cli.StringFlag{
+		altsrc.NewStringFlag(&cli.StringFlag{
 			Name:     "timezone",
 			Required: false,
-			Hidden:   true,
-			Usage:    "the timezone of the server side",
+			Usage: "specifies the `timezone` where `--start` and `--end` are based, in the form of `+0800`. " +
+				"If `--timezone` is given in the command line option, then it's used directly. " +
+				"If the backend support the timezone API (since 6.5.0), CLI will try to get the timezone from backend, " +
+				"and use it. " +
+				"Otherwise, the CLI will use the current timezone in the current machine.",
 		}),
-		altsrc.NewBoolFlag(cli.BoolFlag{
+		altsrc.NewBoolFlag(&cli.BoolFlag{
 			Name:     "debug",
 			Required: false,
-			Usage:    "enable debug mode, will print more detailed logs",
+			Usage:    "enable debug mode, will print more detailed information at runtime",
 		}),
-		altsrc.NewStringFlag(cli.StringFlag{
+		altsrc.NewStringFlag(&cli.StringFlag{
 			Name:     "display",
 			Required: false,
-			Usage:    "display `style` of the result, supported styles are: json, yaml, table, graph",
-			Value:    "",
+			Usage: "display `style` of the result, supported styles are: `json`, `yaml`, `table`, `graph`. " +
+				"(Not all display styles are supported in all commands due to data formats incompatibilities " +
+				"and the limits of Ascii Graph, like coloring in terminal, " +
+				"so in that cases please use `json`  or `yaml` instead.)",
+			Value: "",
 		}),
 	}
 
-	app.Commands = []cli.Command{
+	app.Commands = []*cli.Command{
 		endpoint.Command,
 		instance.Command,
 		service.Command,
@@ -133,18 +158,18 @@ func main() {
 		dependency.Command,
 	}
 
-	app.Before = interceptor.BeforeChain([]cli.BeforeFunc{
+	app.Before = interceptor.BeforeChain(
 		setUpCommandLineContext,
 		expandConfigFile,
 		tryConfigFile(flags),
-	})
+	)
 
 	app.Flags = flags
 	app.CommandNotFound = util.CommandNotFound
 
 	// Enable auto-completion.
 	app.EnableBashCompletion = true
-	cli.BashCompletionFlag = cli.BoolFlag{
+	cli.BashCompletionFlag = &cli.BoolFlag{
 		Name:   "auto_complete",
 		Hidden: true,
 	}
@@ -168,7 +193,7 @@ func tryConfigFile(flags []cli.Flag) cli.BeforeFunc {
 				return err
 			}
 		} else if os.IsNotExist(err) {
-			log.Debugf("open %s no such file, skip loading configuration file\n", c.GlobalString("config"))
+			log.Debugf("open %s no such file, skip loading configuration file\n", c.String("config"))
 		} else {
 			return err
 		}
diff --git a/docs/How-to-release.md b/docs/How-to-release.md
index bb42c55..f1426a4 100644
--- a/docs/How-to-release.md
+++ b/docs/How-to-release.md
@@ -1,21 +1,24 @@
 # Apache SkyWalking CLI Release Guide
 
-This documentation guides the release manager to release the SkyWalking CLI in the Apache Way, and also helps people to check the release for vote.
+This documentation guides the release manager to release the SkyWalking CLI in the Apache Way, and also helps people to
+check the release for vote.
 
 ## Prerequisites
 
-1. Close(if finished, or move to next milestone otherwise) all issues in the current milestone from [skywalking-cli](https://github.com/apache/skywalking-cli/milestones) and [skywalking](https://github.com/apache/skywalking/milestones), create a new milestone if needed.
+1. Close(if finished, or move to next milestone otherwise) all issues in the current milestone
+   from [skywalking-cli](https://github.com/apache/skywalking-cli/milestones)
+   and [skywalking](https://github.com/apache/skywalking/milestones), create a new milestone if needed.
 2. Update [CHANGES.md](../CHANGES.md).
 
-
 ## Add your GPG public key to Apache svn
 
-1. Upload your GPG public key to a public GPG site, such as [MIT's site](http://pgp.mit.edu:11371/). 
+1. Upload your GPG public key to a public GPG site, such as [MIT's site](http://pgp.mit.edu:11371/).
 
 1. Log in [id.apache.org](https://id.apache.org/) and submit your key fingerprint.
 
-1. Add your GPG public key into [SkyWalking GPG KEYS](https://dist.apache.org/repos/dist/release/skywalking/KEYS) file, **you can do this only if you are a PMC member**.  You can ask a PMC member for help. **DO NOT override the existed `KEYS` file content, only append your key at the end of the file.**
-
+1. Add your GPG public key into [SkyWalking GPG KEYS](https://dist.apache.org/repos/dist/release/skywalking/KEYS)
+   file, **you can do this only if you are a PMC member**. You can ask a PMC member for help. **DO NOT override the
+   existed `KEYS` file content, only append your key at the end of the file.**
 
 ## Build and sign the source code package
 
@@ -27,7 +30,8 @@ git push --tags
 make clean && make release
 ```
 
-**In total, six files should be automatically generated in the directory**: `skywalking-cli-${VERSION}-bin.tgz`, `skywalking-cli-${VERSION}-src.tgz`, and their corresponding `asc`, `sha512` files.
+**In total, six files should be automatically generated in the directory**: `skywalking-cli-${VERSION}-bin.tgz`
+, `skywalking-cli-${VERSION}-src.tgz`, and their corresponding `asc`, `sha512` files.
 
 ## Upload to Apache svn
 
@@ -88,8 +92,8 @@ within the next couple of days.
 
 ## Wait at least 48 hours for test responses
 
-Any PMC, committer or contributor can test features for releasing, and feedback.
-Based on that, PMC will decide whether to start a vote or not.
+Any PMC, committer or contributor can test features for releasing, and feedback. Based on that, PMC will decide whether
+to start a vote or not.
 
 ## Call for vote in dev@ mailing list
 
@@ -148,20 +152,22 @@ All PMC members and committers should check these before voting +1:
 1. Features test.
 1. All artifacts in staging repository are published with `.asc`, `.md5`, and `sha` files.
 1. Source codes and distribution packages (`skywalking-cli-$VERSION-{src,bin}.tgz`)
-are in `https://dist.apache.org/repos/dist/dev/skywalking/cli/$VERSION` with `.asc`, `.sha512`.
+   are in `https://dist.apache.org/repos/dist/dev/skywalking/cli/$VERSION` with `.asc`, `.sha512`.
 1. `LICENSE` and `NOTICE` are in source codes and distribution package.
 1. Check `shasum -c skywalking-cli-$VERSION-{src,bin}.tgz.sha512`.
 1. Check `gpg --verify skywalking-cli-$VERSION-{src,bin}.tgz.asc skywalking-cli-$VERSION-{src,bin}.tgz`.
-1. Build distribution from source code package by following this [the build guide](#build-and-sign-the-source-code-package).
+1. Build distribution from source code package by following
+   this [the build guide](#build-and-sign-the-source-code-package).
 1. Licenses check, `make license`.
 
 Vote result should follow these:
 
 1. PMC vote is +1 binding, all others is +1 no binding.
 
-1. Within 72 hours, you get at least 3 (+1 binding), and have more +1 than -1. Vote pass. 
+1. Within 72 hours, you get at least 3 (+1 binding), and have more +1 than -1. Vote pass.
 
-1. **Send the closing vote mail to announce the result**.  When count the binding and no binding votes, please list the names of voters. An example like this:
+1. **Send the closing vote mail to announce the result**. When count the binding and no binding votes, please list the
+   names of voters. An example like this:
 
    ```
    [RESULT][VOTE] Release Apache SkyWalking CLI version $VERSION
@@ -182,7 +188,8 @@ Vote result should follow these:
 
 ## Publish release
 
-1. Move source codes tar balls and distributions to `https://dist.apache.org/repos/dist/release/skywalking/`, **you can do this only if you are a PMC member**.
+1. Move source codes tar balls and distributions to `https://dist.apache.org/repos/dist/release/skywalking/`, **you can
+   do this only if you are a PMC member**.
 
     ```shell
     svn mv https://dist.apache.org/repos/dist/dev/skywalking/cli/$VERSION https://dist.apache.org/repos/dist/release/skywalking/cli -m"Release SkyWalking CLI $VERSION"
@@ -194,11 +201,13 @@ Vote result should follow these:
 make docker.push
 ```
 
-1. Refer to the previous [PR](https://github.com/apache/skywalking-website/pull/212), update the event and download links on the website.
+1. Refer to the previous [PR](https://github.com/apache/skywalking-website/pull/212), update the event and download
+   links on the website.
 
 1. Update [Github release page](https://github.com/apache/skywalking-cli/releases), follow the previous convention.
 
-1. Send ANNOUNCE email to `dev@skywalking.apache.org` and `announce@apache.org`, the sender should use his/her Apache email account, **please check all links before sending the email**.
+1. Send ANNOUNCE email to `dev@skywalking.apache.org` and `announce@apache.org`, the sender should use his/her Apache
+   email account, **please check all links before sending the email**.
 
     ```
     Subject: [ANNOUNCEMENT] Apache SkyWalking CLI $VERSION Released
@@ -226,12 +235,13 @@ make docker.push
     
     The Apache SkyWalking Team
     ```
-   
-1. Add a release on [the report system](https://reporter.apache.org/addrelease.html?skywalking) (**you can do this only if you are a PMC member**).   
 
+1. Add a release on [the report system](https://reporter.apache.org/addrelease.html?skywalking) (**you can do this only
+   if you are a PMC member**).
 
 ## Remove Unnecessary Releases
 
-Please remember to remove all unnecessary releases in the mirror svn (https://dist.apache.org/repos/dist/release/skywalking/), if you don't recommend users to choose those version.
-For example, you have removed the download and documentation links from the website. 
-If they want old ones, the Archive repository has all of them.
+Please remember to remove all unnecessary releases in the mirror
+svn (https://dist.apache.org/repos/dist/release/skywalking/), if you don't recommend users to choose those version. For
+example, you have removed the download and documentation links from the website. If they want old ones, the Archive
+repository has all of them.
diff --git a/examples/.skywalking.yaml b/examples/.skywalking.yaml
index 6e3319b..55125f6 100644
--- a/examples/.skywalking.yaml
+++ b/examples/.skywalking.yaml
@@ -16,6 +16,6 @@
 # under the License.
 
 base-url: http://demo.skywalking.apache.org/graphql
-grpcAddr: 127.0.0.1:11800
+grpc-addr: 127.0.0.1:11800
 username: basic-auth-username
 password: basic-auth-password
diff --git a/assets/assets.go b/examples/assets.go
similarity index 72%
copy from assets/assets.go
copy to examples/assets.go
index 665e0c3..05dc5bb 100644
--- a/assets/assets.go
+++ b/examples/assets.go
@@ -15,17 +15,24 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package assets
+package examples
 
 import (
-	"github.com/apache/skywalking-cli/internal/logger"
+	_ "embed"
+	"strings"
 )
 
-// Read reads all content from a file under assets, which is packed in to the binary
-func Read(filename string) string {
-	content, err := AssetString(filename)
-	if err != nil {
-		logger.Log.Fatalln("failed to read asset: ", filename, err)
+//go:embed .skywalking.yaml
+var example string
+
+func Example() string {
+	s := "\n" + "  Example of the file content:\n"
+	for _, line := range strings.Split(example, "\n") {
+		if strings.HasPrefix(line, "#") {
+			continue
+		}
+		s += strings.Repeat(" ", 2) + line
+		s += "\n"
 	}
-	return content
+	return s
 }
diff --git a/go.mod b/go.mod
index 0b9c241..d82c03a 100644
--- a/go.mod
+++ b/go.mod
@@ -1,6 +1,6 @@
 module github.com/apache/skywalking-cli
 
-go 1.13
+go 1.16
 
 replace golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 => golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f
 
@@ -14,7 +14,7 @@ require (
 	github.com/olekukonko/tablewriter v0.0.2
 	github.com/sirupsen/logrus v1.7.0
 	github.com/spf13/viper v1.7.0
-	github.com/urfave/cli v1.22.1
+	github.com/urfave/cli/v2 v2.3.0 // indirect
 	golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f // indirect
 	google.golang.org/grpc v1.38.0
 	gopkg.in/yaml.v2 v2.4.0
diff --git a/go.sum b/go.sum
index 9bde708..d213767 100644
--- a/go.sum
+++ b/go.sum
@@ -509,6 +509,8 @@ github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGr
 github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
 github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY=
 github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
+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/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=
 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
 github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
@@ -535,7 +537,6 @@ go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A
 go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
 go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A=
 go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
-go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4=
 go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
 go.uber.org/zap v1.8.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
 go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
@@ -585,7 +586,6 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
 golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
 golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
 golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
 golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -833,6 +833,7 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWD
 gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
 gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
@@ -849,7 +850,6 @@ honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWh
 honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
-honnef.co/go/tools v0.0.1-2020.1.3 h1:sXmLre5bzIR6ypkjXCDI3jHPssRhc8KD/Ome589sc3U=
 honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
 k8s.io/api v0.19.2/go.mod h1:IQpK0zFQ1xc5iNIQPqzgoOwuFugaYHK4iCknlAQP9nI=
 k8s.io/api v0.19.3/go.mod h1:VF+5FT1B74Pw3KxMdKyinLo+zynBaMBiAfGMuldcNDs=
diff --git a/internal/commands/completion/bash.go b/internal/commands/completion/bash.go
index aed8075..78ec345 100644
--- a/internal/commands/completion/bash.go
+++ b/internal/commands/completion/bash.go
@@ -20,10 +20,10 @@ package completion
 import (
 	"fmt"
 
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 )
 
-var bashCommand = cli.Command{
+var bashCommand = &cli.Command{
 	Name:      "bash",
 	Aliases:   []string{"b"},
 	Usage:     "Output shell completion code for bash",
diff --git a/internal/commands/completion/completion.go b/internal/commands/completion/completion.go
index c5733e4..3bec0cc 100644
--- a/internal/commands/completion/completion.go
+++ b/internal/commands/completion/completion.go
@@ -18,13 +18,13 @@
 package completion
 
 import (
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 )
 
-var Command = cli.Command{
+var Command = &cli.Command{
 	Name:  "completion",
 	Usage: "Output shell completion code for bash and powershell",
-	Subcommands: []cli.Command{
+	Subcommands: []*cli.Command{
 		bashCommand,
 		powershellCommand,
 	},
diff --git a/internal/commands/completion/powershell.go b/internal/commands/completion/powershell.go
index 1c08123..34234b7 100644
--- a/internal/commands/completion/powershell.go
+++ b/internal/commands/completion/powershell.go
@@ -20,10 +20,10 @@ package completion
 import (
 	"fmt"
 
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 )
 
-var powershellCommand = cli.Command{
+var powershellCommand = &cli.Command{
 	Name:      "powershell",
 	Aliases:   []string{"p"},
 	Usage:     "Output shell completion code for powershell",
diff --git a/internal/commands/dashboard/dashboard.go b/internal/commands/dashboard/dashboard.go
index 5d270da..0791e87 100644
--- a/internal/commands/dashboard/dashboard.go
+++ b/internal/commands/dashboard/dashboard.go
@@ -18,15 +18,15 @@
 package dashboard
 
 import (
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 
 	"github.com/apache/skywalking-cli/internal/commands/dashboard/global"
 )
 
-var Command = cli.Command{
-	Name:      "dashboard",
-	ShortName: "db",
-	Usage:     "Dashboard related sub-command",
+var Command = &cli.Command{
+	Name:    "dashboard",
+	Aliases: []string{"db", "dash"},
+	Usage:   "Dashboard related sub-command",
 	Subcommands: cli.Commands{
 		global.GlobalCommand,
 		global.Metrics,
diff --git a/internal/commands/dashboard/global/global.go b/internal/commands/dashboard/global/global.go
index 99ee12f..319b3dc 100644
--- a/internal/commands/dashboard/global/global.go
+++ b/internal/commands/dashboard/global/global.go
@@ -18,34 +18,33 @@
 package global
 
 import (
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 
 	api "skywalking.apache.org/repo/goapi/query"
 
 	"github.com/apache/skywalking-cli/internal/commands/interceptor"
 	"github.com/apache/skywalking-cli/internal/flags"
-	"github.com/apache/skywalking-cli/internal/logger"
 	"github.com/apache/skywalking-cli/internal/model"
 	"github.com/apache/skywalking-cli/pkg/display"
 	"github.com/apache/skywalking-cli/pkg/display/displayable"
 	"github.com/apache/skywalking-cli/pkg/graphql/dashboard"
 )
 
-var GlobalCommand = cli.Command{
+var GlobalCommand = &cli.Command{
 	Name:        "global",
-	ShortName:   "g",
-	Usage:       "Display global data",
-	Description: "Display global data",
+	Aliases:     []string{"g"},
+	Usage:       "Display global dashboard",
+	Description: "Display global dashboard",
 	Flags: flags.Flags(
 		flags.DurationFlags,
 		[]cli.Flag{
-			cli.StringFlag{
+			&cli.StringFlag{
 				Name:     "template",
 				Usage:    "load dashboard UI template",
 				Required: false,
 				Value:    dashboard.DefaultTemplatePath,
 			},
-			cli.IntFlag{
+			&cli.IntFlag{
 				Name:     "refresh",
 				Usage:    "the auto refreshing interval (s)",
 				Required: false,
@@ -53,10 +52,9 @@ var GlobalCommand = cli.Command{
 			},
 		},
 	),
-	Before: interceptor.BeforeChain([]cli.BeforeFunc{
-		interceptor.TimezoneInterceptor,
+	Before: interceptor.BeforeChain(
 		interceptor.DurationInterceptor,
-	}),
+	),
 	Action: func(ctx *cli.Context) error {
 		end := ctx.String("end")
 		start := ctx.String("start")
@@ -69,7 +67,7 @@ var GlobalCommand = cli.Command{
 		})
 
 		if err != nil {
-			logger.Log.Fatalln(err)
+			return err
 		}
 
 		return display.Display(ctx, &displayable.Displayable{Data: globalData})
diff --git a/internal/commands/dashboard/global/metrics.go b/internal/commands/dashboard/global/metrics.go
index 7d7a5a0..37c9a9a 100644
--- a/internal/commands/dashboard/global/metrics.go
+++ b/internal/commands/dashboard/global/metrics.go
@@ -18,11 +18,10 @@
 package global
 
 import (
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 
 	"github.com/apache/skywalking-cli/internal/commands/interceptor"
 	"github.com/apache/skywalking-cli/internal/flags"
-	"github.com/apache/skywalking-cli/internal/logger"
 	"github.com/apache/skywalking-cli/internal/model"
 	"github.com/apache/skywalking-cli/pkg/display"
 	"github.com/apache/skywalking-cli/pkg/display/displayable"
@@ -31,13 +30,13 @@ import (
 	api "skywalking.apache.org/repo/goapi/query"
 )
 
-var Metrics = cli.Command{
+var Metrics = &cli.Command{
 	Name:  "global-metrics",
 	Usage: "Query global metrics",
 	Flags: flags.Flags(
 		flags.DurationFlags,
 		[]cli.Flag{
-			cli.StringFlag{
+			&cli.StringFlag{
 				Name:     "template",
 				Usage:    "load dashboard UI template",
 				Required: false,
@@ -45,10 +44,9 @@ var Metrics = cli.Command{
 			},
 		},
 	),
-	Before: interceptor.BeforeChain([]cli.BeforeFunc{
-		interceptor.TimezoneInterceptor,
+	Before: interceptor.BeforeChain(
 		interceptor.DurationInterceptor,
-	}),
+	),
 	Action: func(ctx *cli.Context) error {
 		end := ctx.String("end")
 		start := ctx.String("start")
@@ -61,7 +59,7 @@ var Metrics = cli.Command{
 		})
 
 		if err != nil {
-			logger.Log.Fatalln(err)
+			return err
 		}
 
 		return display.Display(ctx, &displayable.Displayable{Data: globalMetrics})
diff --git a/internal/commands/dependency/dependency.go b/internal/commands/dependency/dependency.go
index fa13b33..65e343c 100644
--- a/internal/commands/dependency/dependency.go
+++ b/internal/commands/dependency/dependency.go
@@ -18,13 +18,13 @@
 package dependency
 
 import (
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 )
 
-var Command = cli.Command{
-	Name:      "dependency",
-	ShortName: "dep",
-	Usage:     "Dependency related subcommand",
+var Command = &cli.Command{
+	Name:    "dependency",
+	Aliases: []string{"dep"},
+	Usage:   "Dependency related subcommand",
 	Subcommands: cli.Commands{
 		EndpointCommand,
 		ServiceCommand,
diff --git a/internal/commands/dependency/endpoint.go b/internal/commands/dependency/endpoint.go
index 05bfd3a..8901028 100644
--- a/internal/commands/dependency/endpoint.go
+++ b/internal/commands/dependency/endpoint.go
@@ -18,13 +18,10 @@
 package dependency
 
 import (
-	"fmt"
-
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 
 	"github.com/apache/skywalking-cli/internal/commands/interceptor"
 	"github.com/apache/skywalking-cli/internal/flags"
-	"github.com/apache/skywalking-cli/internal/logger"
 	"github.com/apache/skywalking-cli/internal/model"
 
 	"github.com/apache/skywalking-cli/pkg/display"
@@ -35,24 +32,21 @@ import (
 	api "skywalking.apache.org/repo/goapi/query"
 )
 
-var EndpointCommand = cli.Command{
-	Name:      "endpoint",
-	ShortName: "ep",
-	Usage:     "Query the dependencies of given endpoint",
-	ArgsUsage: "<endpointId>",
+var EndpointCommand = &cli.Command{
+	Name:    "endpoint",
+	Aliases: []string{"ep"},
+	Usage:   "Query the dependencies of the given endpoint",
 	Flags: flags.Flags(
 		flags.DurationFlags,
+		flags.EndpointFlags,
 	),
-	Before: interceptor.BeforeChain([]cli.BeforeFunc{
-		interceptor.TimezoneInterceptor,
+	Before: interceptor.BeforeChain(
 		interceptor.DurationInterceptor,
-	}),
+		interceptor.ParseEndpoint(true),
+	),
 
 	Action: func(ctx *cli.Context) error {
-		if ctx.NArg() == 0 {
-			return fmt.Errorf("command endpoint requires endpointId as argument")
-		}
-
+		endpointID := ctx.String("endpoint-id")
 		end := ctx.String("end")
 		start := ctx.String("start")
 		step := ctx.Generic("step")
@@ -63,10 +57,10 @@ var EndpointCommand = cli.Command{
 			Step:  step.(*model.StepEnumValue).Selected,
 		}
 
-		dependency, err := dependency.EndpointDependency(ctx, ctx.Args().First(), duration)
+		dependency, err := dependency.EndpointDependency(ctx, endpointID, duration)
 
 		if err != nil {
-			logger.Log.Fatalln(err)
+			return err
 		}
 
 		return display.Display(ctx, &displayable.Displayable{Data: dependency})
diff --git a/internal/commands/dependency/instance.go b/internal/commands/dependency/instance.go
index 6285fba..c272601 100644
--- a/internal/commands/dependency/instance.go
+++ b/internal/commands/dependency/instance.go
@@ -18,13 +18,10 @@
 package dependency
 
 import (
-	"fmt"
-
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 
 	"github.com/apache/skywalking-cli/internal/commands/interceptor"
 	"github.com/apache/skywalking-cli/internal/flags"
-	"github.com/apache/skywalking-cli/internal/logger"
 	"github.com/apache/skywalking-cli/internal/model"
 
 	"github.com/apache/skywalking-cli/pkg/display"
@@ -35,23 +32,22 @@ import (
 	api "skywalking.apache.org/repo/goapi/query"
 )
 
-var InstanceCommand = cli.Command{
-	Name:      "instance",
-	ShortName: "instc",
-	Usage:     "Query the instance topology, based on the given clientServiceId and serverServiceId",
-	ArgsUsage: "<clientServiceId> <serverServiceId>",
+var InstanceCommand = &cli.Command{
+	Name:    "instance",
+	Aliases: []string{"instc"},
+	Usage:   "Query the instance topology, based on the given source service and destination service",
 	Flags: flags.Flags(
 		flags.DurationFlags,
+		flags.ServiceRelationFlags,
 	),
-	Before: interceptor.BeforeChain([]cli.BeforeFunc{
-		interceptor.TimezoneInterceptor,
+	Before: interceptor.BeforeChain(
 		interceptor.DurationInterceptor,
-	}),
+		interceptor.ParseServiceRelation(true),
+	),
 
 	Action: func(ctx *cli.Context) error {
-		if ctx.NArg() < 2 {
-			return fmt.Errorf("command instance requires both clientServiceId and serverServiceId as arguments")
-		}
+		srcSvcID := ctx.String("service-id")
+		dstSvcID := ctx.String("dest-service-id")
 
 		end := ctx.String("end")
 		start := ctx.String("start")
@@ -63,10 +59,10 @@ var InstanceCommand = cli.Command{
 			Step:  step.(*model.StepEnumValue).Selected,
 		}
 
-		dependency, err := dependency.InstanceTopology(ctx, ctx.Args().First(), ctx.Args().Get(1), duration)
+		dependency, err := dependency.InstanceTopology(ctx, srcSvcID, dstSvcID, duration)
 
 		if err != nil {
-			logger.Log.Fatalln(err)
+			return err
 		}
 
 		return display.Display(ctx, &displayable.Displayable{Data: dependency})
diff --git a/internal/commands/dependency/service.go b/internal/commands/dependency/service.go
index 4a0abb3..d9ae36d 100644
--- a/internal/commands/dependency/service.go
+++ b/internal/commands/dependency/service.go
@@ -18,13 +18,10 @@
 package dependency
 
 import (
-	"fmt"
-
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 
 	"github.com/apache/skywalking-cli/internal/commands/interceptor"
 	"github.com/apache/skywalking-cli/internal/flags"
-	"github.com/apache/skywalking-cli/internal/logger"
 	"github.com/apache/skywalking-cli/internal/model"
 
 	"github.com/apache/skywalking-cli/pkg/display"
@@ -35,24 +32,22 @@ import (
 	api "skywalking.apache.org/repo/goapi/query"
 )
 
-var ServiceCommand = cli.Command{
+var ServiceCommand = &cli.Command{
 	Name:      "service",
-	ShortName: "svc",
+	Aliases:   []string{"svc"},
 	Usage:     "Query the dependencies of given service",
 	ArgsUsage: "<serviceId>",
 	Flags: flags.Flags(
 		flags.DurationFlags,
+		flags.ServiceFlags,
 	),
-	Before: interceptor.BeforeChain([]cli.BeforeFunc{
-		interceptor.TimezoneInterceptor,
+	Before: interceptor.BeforeChain(
 		interceptor.DurationInterceptor,
-	}),
+		interceptor.ParseService(true),
+	),
 
 	Action: func(ctx *cli.Context) error {
-		if ctx.NArg() == 0 {
-			return fmt.Errorf("command service requires serviceId as argument")
-		}
-
+		serviceID := ctx.String("service-id")
 		end := ctx.String("end")
 		start := ctx.String("start")
 		step := ctx.Generic("step")
@@ -63,10 +58,10 @@ var ServiceCommand = cli.Command{
 			Step:  step.(*model.StepEnumValue).Selected,
 		}
 
-		dependency, err := dependency.ServiceTopology(ctx, ctx.Args().First(), duration)
+		dependency, err := dependency.ServiceTopology(ctx, serviceID, duration)
 
 		if err != nil {
-			logger.Log.Fatalln(err)
+			return err
 		}
 
 		return display.Display(ctx, &displayable.Displayable{Data: dependency})
diff --git a/internal/commands/endpoint/endpoint.go b/internal/commands/endpoint/endpoint.go
index d357224..c1b9675 100644
--- a/internal/commands/endpoint/endpoint.go
+++ b/internal/commands/endpoint/endpoint.go
@@ -18,13 +18,13 @@
 package endpoint
 
 import (
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 )
 
-var Command = cli.Command{
-	Name:      "endpoint",
-	ShortName: "e",
-	Usage:     "Endpoint related sub-command",
+var Command = &cli.Command{
+	Name:    "endpoint",
+	Aliases: []string{"e"},
+	Usage:   "Endpoint related sub-command",
 	Subcommands: cli.Commands{
 		ListCommand,
 	},
diff --git a/internal/commands/endpoint/list.go b/internal/commands/endpoint/list.go
index 4c692e3..b9b3555 100644
--- a/internal/commands/endpoint/list.go
+++ b/internal/commands/endpoint/list.go
@@ -18,9 +18,10 @@
 package endpoint
 
 import (
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 
-	"github.com/apache/skywalking-cli/internal/logger"
+	"github.com/apache/skywalking-cli/internal/commands/interceptor"
+	"github.com/apache/skywalking-cli/internal/flags"
 
 	"github.com/apache/skywalking-cli/pkg/display/displayable"
 
@@ -29,30 +30,42 @@ import (
 	"github.com/apache/skywalking-cli/pkg/display"
 )
 
-var ListCommand = cli.Command{
-	Name:        "list",
-	ShortName:   "ls",
-	Usage:       "List endpoints",
-	Description: "list all endpoints if no <endpoint id> is given, otherwise, only list the given endpoint",
-	Flags: []cli.Flag{
-		cli.StringFlag{
-			Name:     "service-id",
-			Usage:    "`<service id>` whose endpoints are to be searched",
-			Required: true,
-		},
-		cli.IntFlag{
-			Name:     "limit",
-			Usage:    "returns at most `<limit>` endpoints",
-			Required: false,
-			Value:    100,
-		},
-		cli.StringFlag{
-			Name:     "keyword",
-			Usage:    "`<keyword>` of the endpoint name to search for, empty to search all",
-			Required: false,
-			Value:    "",
+var ListCommand = &cli.Command{
+	Name:    "list",
+	Aliases: []string{"ls"},
+	Usage:   `list all monitored endpoints of the given "--service-id" or "--service-name"`,
+	UsageText: `This command lists all endpoints of the service, via service id or service name.
+
+Examples:
+1. List all endpoints of the service by service name "business-zone::projectC":
+$ swctl endpoint ls --service-name business-zone::projectC
+
+2. List all endpoints of the service by service id "YnVzaW5lc3Mtem9uZTo6cHJvamVjdEM=.1":
+$ swctl endpoint ls --service-id YnVzaW5lc3Mtem9uZTo6cHJvamVjdEM=.1
+
+3. Search endpoints like "projectC" of the service "business-zone::projectC":
+$ swctl endpoint ls --service-name business-zone::projectC --keyword projectC`,
+	Flags: flags.Flags(
+		flags.ServiceFlags,
+
+		[]cli.Flag{
+			&cli.IntFlag{
+				Name:     "limit",
+				Usage:    "returns at most `<limit>` endpoints",
+				Required: false,
+				Value:    100,
+			},
+			&cli.StringFlag{
+				Name:     "keyword",
+				Usage:    "`<keyword>` of the endpoint name to search for, empty to search all",
+				Required: false,
+				Value:    "",
+			},
 		},
-	},
+	),
+	Before: interceptor.BeforeChain(
+		interceptor.ParseService(true),
+	),
 	Action: func(ctx *cli.Context) error {
 		serviceID := ctx.String("service-id")
 		limit := ctx.Int("limit")
@@ -61,7 +74,7 @@ var ListCommand = cli.Command{
 		endpoints, err := metadata.SearchEndpoints(ctx, serviceID, keyword, limit)
 
 		if err != nil {
-			logger.Log.Fatalln(err)
+			return err
 		}
 
 		return display.Display(ctx, &displayable.Displayable{Data: endpoints})
diff --git a/internal/commands/event/event.go b/internal/commands/event/event.go
index fbac472..56131f9 100644
--- a/internal/commands/event/event.go
+++ b/internal/commands/event/event.go
@@ -18,13 +18,13 @@
 package event
 
 import (
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 )
 
-var Command = cli.Command{
+var Command = &cli.Command{
 	Name:  "event",
 	Usage: "Event related sub-command",
-	Subcommands: []cli.Command{
+	Subcommands: []*cli.Command{
 		reportCommand,
 		listCommand,
 	},
diff --git a/internal/commands/event/list.go b/internal/commands/event/list.go
index a81ef06..9850962 100644
--- a/internal/commands/event/list.go
+++ b/internal/commands/event/list.go
@@ -23,45 +23,31 @@ import (
 
 	"github.com/apache/skywalking-cli/internal/commands/interceptor"
 	"github.com/apache/skywalking-cli/internal/flags"
-	"github.com/apache/skywalking-cli/internal/logger"
 	"github.com/apache/skywalking-cli/internal/model"
 	"github.com/apache/skywalking-cli/pkg/display"
 	"github.com/apache/skywalking-cli/pkg/display/displayable"
 	eventQl "github.com/apache/skywalking-cli/pkg/graphql/event"
 
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 )
 
 const DefaultPageSize = 15
 
-var listCommand = cli.Command{
-	Name:      "list",
-	ShortName: "ls",
-	Usage:     "List events",
+var listCommand = &cli.Command{
+	Name:    "list",
+	Aliases: []string{"ls"},
+	Usage:   "List events",
 	Flags: flags.Flags(
 		flags.DurationFlags,
+		flags.InstanceFlags,
+		flags.EndpointFlags,
 		[]cli.Flag{
-			cli.StringFlag{
-				Name:     "service",
-				Usage:    "service name",
-				Required: false,
-			},
-			cli.StringFlag{
-				Name:     "instance",
-				Usage:    "service instance name",
-				Required: false,
-			},
-			cli.StringFlag{
-				Name:     "endpoint",
-				Usage:    "endpoint name",
-				Required: false,
-			},
-			cli.StringFlag{
+			&cli.StringFlag{
 				Name:     "name",
 				Usage:    "event name",
 				Required: false,
 			},
-			cli.GenericFlag{
+			&cli.GenericFlag{
 				Name:  "type",
 				Usage: "the type of the event",
 				Value: &model.EventTypeEnumValue{
@@ -72,10 +58,12 @@ var listCommand = cli.Command{
 			},
 		},
 	),
-	Before: interceptor.BeforeChain([]cli.BeforeFunc{
-		interceptor.TimezoneInterceptor,
+	Before: interceptor.BeforeChain(
 		interceptor.DurationInterceptor,
-	}),
+		interceptor.ParseService(false),
+		interceptor.ParseInstance(false),
+		interceptor.ParseEndpoint(false),
+	),
 	Action: func(ctx *cli.Context) error {
 		start := ctx.String("start")
 		end := ctx.String("end")
@@ -86,9 +74,9 @@ var listCommand = cli.Command{
 			End:   end,
 			Step:  step.(*model.StepEnumValue).Selected,
 		}
-		serviceName := ctx.String("service")
-		serviceInstanceName := ctx.String("instance")
-		endpointName := ctx.String("endpoint")
+		serviceName := ctx.String("service-name")
+		serviceInstanceName := ctx.String("instance-name")
+		endpointName := ctx.String("endpoint-name")
 		name := ctx.String("name")
 		eventType := api.EventType(ctx.Generic("type").(*model.EventTypeEnumValue).String())
 		pageNum := 1
@@ -115,7 +103,7 @@ var listCommand = cli.Command{
 		events, err := eventQl.Events(ctx, condition)
 
 		if err != nil {
-			logger.Log.Fatalln(err)
+			return err
 		}
 
 		return display.Display(ctx, &displayable.Displayable{Data: events, Condition: condition})
diff --git a/internal/commands/event/report.go b/internal/commands/event/report.go
index f155ca8..6d009d7 100644
--- a/internal/commands/event/report.go
+++ b/internal/commands/event/report.go
@@ -20,63 +20,57 @@ package event
 import (
 	event "skywalking.apache.org/repo/goapi/collect/event/v3"
 
+	"github.com/apache/skywalking-cli/internal/flags"
 	"github.com/apache/skywalking-cli/internal/logger"
 	"github.com/apache/skywalking-cli/internal/model"
 	pkgevent "github.com/apache/skywalking-cli/pkg/commands/event"
 	"github.com/apache/skywalking-cli/pkg/display"
 	"github.com/apache/skywalking-cli/pkg/display/displayable"
 
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 )
 
-var reportCommand = cli.Command{
+var reportCommand = &cli.Command{
 	Name:      "report",
 	Aliases:   []string{"r"},
 	Usage:     "Report an event to OAP server via gRPC",
 	ArgsUsage: "[parameters...]",
-	Flags: []cli.Flag{
-		cli.StringFlag{
-			Name:  "uuid",
-			Usage: "Unique `ID` of the event.",
-		},
-		cli.StringFlag{
-			Name:  "service",
-			Usage: "The service of the event occurred on.",
-		},
-		cli.StringFlag{
-			Name:  "instance",
-			Usage: "The service instance of the event occurred on.",
-		},
-		cli.StringFlag{
-			Name:  "endpoint",
-			Usage: "The endpoint of the event occurred on",
-		},
-		cli.StringFlag{
-			Name:  "name",
-			Usage: "The name of the event. For example, 'Reboot' and 'Upgrade' etc.",
-		},
-		cli.GenericFlag{
-			Name:  "type",
-			Usage: "The type of the event.",
-			Value: &model.EventTypeEnumValue{
-				Enum:     []event.Type{event.Type_Normal, event.Type_Error},
-				Default:  event.Type_Normal,
-				Selected: event.Type_Normal,
+	Flags: flags.Flags(
+		flags.InstanceFlags,
+		flags.EndpointFlags,
+
+		[]cli.Flag{
+			&cli.StringFlag{
+				Name:  "uuid",
+				Usage: "Unique `ID` of the event.",
+			},
+			&cli.StringFlag{
+				Name:  "name",
+				Usage: "The name of the event. For example, 'Reboot' and 'Upgrade' etc.",
+			},
+			&cli.GenericFlag{
+				Name:  "type",
+				Usage: "The type of the event.",
+				Value: &model.EventTypeEnumValue{
+					Enum:     []event.Type{event.Type_Normal, event.Type_Error},
+					Default:  event.Type_Normal,
+					Selected: event.Type_Normal,
+				},
+			},
+			&cli.StringFlag{
+				Name:  "message",
+				Usage: "The detail of the event. This should be a one-line message that briefly describes why the event is reported.",
+			},
+			&cli.Int64Flag{
+				Name:  "start-time",
+				Usage: "The start time (in milliseconds) of the event, measured between the current time and midnight, January 1, 1970 UTC.",
+			},
+			&cli.Int64Flag{
+				Name:  "end-time",
+				Usage: "The end time (in milliseconds) of the event, measured between the current time and midnight, January 1, 1970 UTC.",
 			},
 		},
-		cli.StringFlag{
-			Name:  "message",
-			Usage: "The detail of the event. This should be a one-line message that briefly describes why the event is reported.",
-		},
-		cli.Int64Flag{
-			Name:  "startTime",
-			Usage: "The start time (in milliseconds) of the event, measured between the current time and midnight, January 1, 1970 UTC.",
-		},
-		cli.Int64Flag{
-			Name:  "endTime",
-			Usage: "The end time (in milliseconds) of the event, measured between the current time and midnight, January 1, 1970 UTC.",
-		},
-	},
+	),
 	Action: func(ctx *cli.Context) error {
 		reply, err := pkgevent.Report(ctx)
 		if err != nil {
diff --git a/internal/commands/healthcheck/healthcheck.go b/internal/commands/healthcheck/healthcheck.go
index 27a20a6..25a52fa 100644
--- a/internal/commands/healthcheck/healthcheck.go
+++ b/internal/commands/healthcheck/healthcheck.go
@@ -18,7 +18,7 @@
 package healthcheck
 
 import (
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 
 	"github.com/apache/skywalking-cli/pkg/healthcheck"
 
@@ -26,17 +26,33 @@ import (
 	hc "github.com/apache/skywalking-cli/pkg/graphql/healthcheck"
 )
 
-var Command = cli.Command{
-	Name:    "checkHealth",
-	Aliases: []string{"ch"},
-	Usage:   "Check the health status of OAP server",
+var Command = &cli.Command{
+	Name:  "health",
+	Usage: "Checks whether OAP server is healthy",
+	UsageText: `Checks whether OAP server is healthy.
+Before using this, please make sure the OAP enables the health checker,
+refer to https://skywalking.apache.org/docs/main/latest/en/setup/backend/backend-health-check/
+
+Note: once enable gRPC TLS, checkHealth command would ignore server's cert.
+
+Examples:
+1. Check health status from GraphQL and the gRPC endpoint listening on 10.0.0.1:8843
+$ swctl health --grpc-addr=10.0.0.1:8843
+
+2. Once the gRPC endpoint of OAP encrypts communication by TLS:
+$ swctl health --grpcTLS=true
+
+3. Check health status from GraphQL service only:
+$ swctl health --grpc=false
+`,
 	Flags: []cli.Flag{
-		cli.BoolTFlag{
+		&cli.BoolFlag{
 			Name:     "grpc",
-			Usage:    "Check gRPC by HealthCheck service",
+			Usage:    "check OAP gRPC by HealthCheck service",
 			Required: false,
+			Value:    true,
 		},
-		cli.BoolFlag{
+		&cli.BoolFlag{
 			Name:     "grpcTLS",
 			Usage:    "use TLS for gRPC",
 			Required: false,
@@ -46,17 +62,17 @@ var Command = cli.Command{
 		healthStatus, err := hc.CheckHealth(ctx)
 
 		if err != nil {
-			logger.Log.Fatalln(err)
+			return err
 		}
 
 		if healthStatus.Score != 0 {
 			return cli.NewExitError(healthStatus.Details, healthStatus.Score)
 		}
 		logger.Log.Println("OAP modules are healthy")
-		if !ctx.BoolT("grpc") {
+		if !ctx.Bool("grpc") {
 			return nil
 		}
-		retCode := healthcheck.HealthCheck(ctx.GlobalString("grpcAddr"), ctx.Bool("grpcTLS"))
+		retCode := healthcheck.HealthCheck(ctx.String("grpc-addr"), ctx.Bool("grpcTLS"))
 		if retCode != 0 {
 			return cli.NewExitError("gRPC: failed to check health", retCode)
 		}
diff --git a/internal/commands/install/install.go b/internal/commands/install/install.go
index e5807ed..a61ec5b 100644
--- a/internal/commands/install/install.go
+++ b/internal/commands/install/install.go
@@ -18,16 +18,16 @@
 package install
 
 import (
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 
 	"github.com/apache/skywalking-cli/internal/commands/install/manifest"
 )
 
-var Command = cli.Command{
-	Name:      "install",
-	ShortName: "i",
-	Usage:     "Generates install manifest and applies it to a cluster",
-	Subcommands: []cli.Command{
+var Command = &cli.Command{
+	Name:    "install",
+	Aliases: []string{"i"},
+	Usage:   "Generates install manifest and applies it to a cluster",
+	Subcommands: []*cli.Command{
 		manifest.Command,
 	},
 }
diff --git a/internal/commands/install/manifest/manifest.go b/internal/commands/install/manifest/manifest.go
index 5d8bf6f..b538eed 100644
--- a/internal/commands/install/manifest/manifest.go
+++ b/internal/commands/install/manifest/manifest.go
@@ -27,35 +27,35 @@ import (
 
 	"github.com/apache/skywalking-swck/pkg/kubernetes"
 	"github.com/apache/skywalking-swck/pkg/operator/repo"
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 	"gopkg.in/yaml.v2"
 	"k8s.io/apimachinery/pkg/runtime"
 )
 
-var Command = cli.Command{
-	Name:      "manifest",
-	ShortName: "mf",
-	Usage:     "Output the Kubernetes manifest for installing OAP server and UI to stdout",
-	Subcommands: []cli.Command{
+var Command = &cli.Command{
+	Name:    "manifest",
+	Aliases: []string{"mf"},
+	Usage:   "Output the Kubernetes manifest for installing OAP server and UI to stdout",
+	Subcommands: []*cli.Command{
 		oapCmd,
 		uiCmd,
 	},
 }
 
 var flags = []cli.Flag{
-	cli.StringFlag{
+	&cli.StringFlag{
 		Name:     "name",
 		Usage:    "The name of prefix of generated resources",
 		Required: false,
 		Value:    "skywalking",
 	},
-	cli.StringFlag{
+	&cli.StringFlag{
 		Name:     "namespace",
 		Usage:    "The namespace where resource will be deployed",
 		Required: false,
 		Value:    "skywalking-system",
 	},
-	cli.StringFlag{
+	&cli.StringFlag{
 		Name:     "f",
 		Usage:    "The custom resource file describing custom resources defined by swck",
 		Required: false,
diff --git a/internal/commands/install/manifest/oap.go b/internal/commands/install/manifest/oap.go
index 82593ab..26f2d0c 100644
--- a/internal/commands/install/manifest/oap.go
+++ b/internal/commands/install/manifest/oap.go
@@ -21,16 +21,16 @@ import (
 	"fmt"
 
 	operatorv1alpha1 "github.com/apache/skywalking-swck/apis/operator/v1alpha1"
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 	"gopkg.in/yaml.v2"
 	controllerruntime "sigs.k8s.io/controller-runtime"
 
 	"github.com/apache/skywalking-cli/assets"
 )
 
-var oapCmd = cli.Command{
+var oapCmd = &cli.Command{
 	Name:      "oap",
-	ShortName: "o",
+	Aliases:   []string{"o"},
 	Usage:     "Output the Kubernetes manifest for installing OAP server to stdout",
 	UsageText: usage("oap"),
 	Flags:     flags,
diff --git a/internal/commands/install/manifest/ui.go b/internal/commands/install/manifest/ui.go
index e72757a..226e687 100644
--- a/internal/commands/install/manifest/ui.go
+++ b/internal/commands/install/manifest/ui.go
@@ -21,16 +21,16 @@ import (
 	"fmt"
 
 	operatorv1alpha1 "github.com/apache/skywalking-swck/apis/operator/v1alpha1"
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 	"gopkg.in/yaml.v2"
 	controllerruntime "sigs.k8s.io/controller-runtime"
 
 	"github.com/apache/skywalking-cli/assets"
 )
 
-var uiCmd = cli.Command{
+var uiCmd = &cli.Command{
 	Name:      "ui",
-	ShortName: "u",
+	Aliases:   []string{"u"},
 	Usage:     "Output the Kubernetes manifest for installing UI to stdout",
 	UsageText: usage("ui"),
 	Flags:     flags,
diff --git a/internal/commands/instance/instance.go b/internal/commands/instance/instance.go
index 9277086..856fa15 100644
--- a/internal/commands/instance/instance.go
+++ b/internal/commands/instance/instance.go
@@ -18,37 +18,15 @@
 package instance
 
 import (
-	"github.com/urfave/cli"
-
-	"github.com/apache/skywalking-cli/pkg/graphql/metadata"
-
-	"github.com/apache/skywalking-cli/internal/logger"
+	"github.com/urfave/cli/v2"
 )
 
-var Command = cli.Command{
-	Name:      "instance",
-	ShortName: "i",
-	Usage:     "Instance related sub-command",
+var Command = &cli.Command{
+	Name:    "instance",
+	Aliases: []string{"i"},
+	Usage:   "Instance related sub-command",
 	Subcommands: cli.Commands{
 		ListCommand,
 		SearchCommand,
 	},
 }
-
-func verifyAndSwitchServiceParameter(ctx *cli.Context) string {
-	serviceID := ctx.String("service-id")
-	serviceName := ctx.String("service-name")
-
-	if serviceID == "" && serviceName == "" {
-		logger.Log.Fatalf("flags \"service-id, service-name\" must set one")
-	}
-
-	if serviceID == "" && serviceName != "" {
-		service, err := metadata.SearchService(ctx, serviceName)
-		if err != nil {
-			logger.Log.Fatalln(err)
-		}
-		serviceID = service.ID
-	}
-	return serviceID
-}
diff --git a/internal/commands/instance/list.go b/internal/commands/instance/list.go
index 1044c1e..11ba23b 100644
--- a/internal/commands/instance/list.go
+++ b/internal/commands/instance/list.go
@@ -18,34 +18,43 @@
 package instance
 
 import (
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 
 	api "skywalking.apache.org/repo/goapi/query"
 
 	"github.com/apache/skywalking-cli/internal/commands/interceptor"
 	"github.com/apache/skywalking-cli/internal/flags"
-	"github.com/apache/skywalking-cli/internal/logger"
 	"github.com/apache/skywalking-cli/internal/model"
 	"github.com/apache/skywalking-cli/pkg/display"
 	"github.com/apache/skywalking-cli/pkg/display/displayable"
 	"github.com/apache/skywalking-cli/pkg/graphql/metadata"
 )
 
-var ListCommand = cli.Command{
-	Name:      "list",
-	ShortName: "ls",
-	Usage:     "List all available instance by given --service-id or --service-name parameter",
-	Flags:     append(flags.DurationFlags, flags.InstanceServiceIDFlags...),
-	Before: interceptor.BeforeChain([]cli.BeforeFunc{
-		interceptor.TimezoneInterceptor,
+var ListCommand = &cli.Command{
+	Name:    "list",
+	Aliases: []string{"ls"},
+	Usage:   `list all monitored instances of the given "--service-id" or "--service-name"`,
+	UsageText: `This command lists all instances of the service, via service id or service name.
+
+Examples:
+1. List all instances of the service by service name "provider":
+$ swctl instance ls --service-name business-zone::projectC
+
+2. List all instances of the service by service id "YnVzaW5lc3Mtem9uZTo6cHJvamVjdEM=.1":
+$ swctl instance ls --service-id YnVzaW5lc3Mtem9uZTo6cHJvamVjdEM=.1`,
+	Flags: flags.Flags(
+		flags.DurationFlags,
+		flags.ServiceFlags,
+	),
+	Before: interceptor.BeforeChain(
 		interceptor.DurationInterceptor,
-	}),
+		interceptor.ParseService(true),
+	),
 	Action: func(ctx *cli.Context) error {
-		serviceID := verifyAndSwitchServiceParameter(ctx)
-
 		end := ctx.String("end")
 		start := ctx.String("start")
 		step := ctx.Generic("step")
+		serviceID := ctx.String("service-id")
 
 		instances, err := metadata.Instances(ctx, serviceID, api.Duration{
 			Start: start,
@@ -54,7 +63,7 @@ var ListCommand = cli.Command{
 		})
 
 		if err != nil {
-			logger.Log.Fatalln(err)
+			return err
 		}
 
 		return display.Display(ctx, &displayable.Displayable{Data: instances})
diff --git a/internal/commands/instance/search.go b/internal/commands/instance/search.go
index dec1c92..a7bee0f 100644
--- a/internal/commands/instance/search.go
+++ b/internal/commands/instance/search.go
@@ -22,32 +22,33 @@ import (
 
 	api "skywalking.apache.org/repo/goapi/query"
 
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 
 	"github.com/apache/skywalking-cli/internal/commands/interceptor"
 	"github.com/apache/skywalking-cli/internal/flags"
-	"github.com/apache/skywalking-cli/internal/logger"
 	"github.com/apache/skywalking-cli/internal/model"
 	"github.com/apache/skywalking-cli/pkg/display"
 	"github.com/apache/skywalking-cli/pkg/display/displayable"
 	"github.com/apache/skywalking-cli/pkg/graphql/metadata"
 )
 
-var SearchCommand = cli.Command{
+var SearchCommand = &cli.Command{
 	Name:  "search",
 	Usage: "Filter the instance from the existing service instance list",
-	Flags: append(flags.DurationFlags, append(flags.SearchRegexFlags, flags.InstanceServiceIDFlags...)...),
-	Before: interceptor.BeforeChain([]cli.BeforeFunc{
-		interceptor.TimezoneInterceptor,
+	Flags: flags.Flags(
+		flags.DurationFlags,
+		flags.SearchRegexFlags,
+		flags.ServiceFlags,
+	),
+	Before: interceptor.BeforeChain(
 		interceptor.DurationInterceptor,
-	}),
+		interceptor.ParseService(true),
+	),
 	Action: func(ctx *cli.Context) error {
-		serviceID := verifyAndSwitchServiceParameter(ctx)
-
+		serviceID := ctx.String("service-id")
 		end := ctx.String("end")
 		start := ctx.String("start")
 		step := ctx.Generic("step")
-
 		regex := ctx.String("regex")
 
 		instances, err := metadata.Instances(ctx, serviceID, api.Duration{
@@ -57,7 +58,7 @@ var SearchCommand = cli.Command{
 		})
 
 		if err != nil {
-			logger.Log.Fatalln(err)
+			return err
 		}
 
 		var result []api.ServiceInstance
diff --git a/internal/commands/interceptor/duration.go b/internal/commands/interceptor/duration.go
index a90bd01..531141c 100644
--- a/internal/commands/interceptor/duration.go
+++ b/internal/commands/interceptor/duration.go
@@ -25,7 +25,7 @@ import (
 
 	"github.com/apache/skywalking-cli/pkg/graphql/utils"
 
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 
 	"github.com/apache/skywalking-cli/internal/logger"
 )
@@ -47,7 +47,7 @@ func TryParseTime(unparsed string) (api.Step, time.Time, error) {
 func DurationInterceptor(ctx *cli.Context) error {
 	start := ctx.String("start")
 	end := ctx.String("end")
-	timezone := ctx.GlobalString("timezone")
+	timezone := ctx.String("timezone")
 
 	startTime, endTime, step, dt := ParseDuration(start, end, timezone)
 
@@ -57,7 +57,7 @@ func DurationInterceptor(ctx *cli.Context) error {
 		return err
 	} else if err := ctx.Set("step", step.String()); err != nil {
 		return err
-	} else if err := ctx.Set("durationType", dt.String()); err != nil {
+	} else if err := ctx.Set("duration-type", dt.String()); err != nil {
 		return err
 	}
 	return nil
diff --git a/internal/commands/interceptor/endpoint.go b/internal/commands/interceptor/endpoint.go
new file mode 100644
index 0000000..296716c
--- /dev/null
+++ b/internal/commands/interceptor/endpoint.go
@@ -0,0 +1,105 @@
+// 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 interceptor
+
+import (
+	"encoding/base64"
+	"fmt"
+	"strings"
+
+	"github.com/urfave/cli/v2"
+)
+
+const (
+	endpointIDFlagName       = "endpoint-id"
+	endpointNameFlagName     = "endpoint-name"
+	destEndpointIDFlagName   = "dest-endpoint-id"
+	destEndpointNameFlagName = "dest-endpoint-name"
+)
+
+// ParseEndpoint parses the endpoint id or endpoint name,
+// and converts the present one to the missing one.
+// See flags.EndpointFlags.
+func ParseEndpoint(required bool) func(*cli.Context) error {
+	return func(ctx *cli.Context) error {
+		if err := ParseService(required)(ctx); err != nil {
+			return err
+		}
+		return parseEndpoint(required, endpointIDFlagName, endpointNameFlagName, serviceIDFlagName)(ctx)
+	}
+}
+
+// ParseEndpointRelation parses the source and destination endpoint id or endpoint name,
+// and converts the present one to the missing one.
+// See flags.EndpointRelationFlags.
+func ParseEndpointRelation(required bool) func(*cli.Context) error {
+	return func(ctx *cli.Context) error {
+		if err := ParseService(required)(ctx); err != nil {
+			return err
+		}
+		if err := ParseEndpoint(required)(ctx); err != nil {
+			return err
+		}
+		return parseEndpoint(required, destEndpointIDFlagName, destEndpointNameFlagName, destServiceIDFlagName)(ctx)
+	}
+}
+
+func parseEndpoint(required bool, idFlagName, nameFlagName, serviceIDFlagName string) func(*cli.Context) error {
+	return func(ctx *cli.Context) error {
+		id := ctx.String(idFlagName)
+		name := ctx.String(nameFlagName)
+		serviceID := ctx.String(serviceIDFlagName)
+
+		if id == "" && name == "" {
+			if required {
+				return fmt.Errorf(`either flags "--%s" or "--%s" must be given`, idFlagName, nameFlagName)
+			}
+			return nil
+		}
+
+		if name != "" {
+			if serviceID == "" {
+				return fmt.Errorf(`"--%s" is specified but its related service name or id is not given`, nameFlagName)
+			}
+			id = serviceID + "_" + b64enc(name)
+		} else if id != "" {
+			parts := strings.Split(id, "_")
+			if len(parts) != 2 {
+				return fmt.Errorf("invalid endpoint id, cannot be splitted into 2 parts. %v", id)
+			}
+			s, err := base64.StdEncoding.DecodeString(parts[1])
+			if err != nil {
+				return err
+			}
+			name = string(s)
+		}
+
+		if err := ctx.Set(idFlagName, id); err != nil {
+			return err
+		}
+		if err := ctx.Set(nameFlagName, name); err != nil {
+			return err
+		}
+
+		return nil
+	}
+}
+
+func b64enc(text string) string {
+	return base64.StdEncoding.EncodeToString([]byte(text))
+}
diff --git a/internal/commands/interceptor/entity.go b/internal/commands/interceptor/entity.go
index cbac791..d8a40e7 100644
--- a/internal/commands/interceptor/entity.go
+++ b/internal/commands/interceptor/entity.go
@@ -18,35 +18,65 @@
 package interceptor
 
 import (
-	"github.com/urfave/cli"
+	"encoding/base64"
+	"fmt"
+	"strings"
+
+	"github.com/urfave/cli/v2"
 
 	"github.com/apache/skywalking-cli/pkg/graphql/utils"
 
 	api "skywalking.apache.org/repo/goapi/query"
 )
 
-func ParseEntity(ctx *cli.Context) *api.Entity {
-	service := ctx.String("service")
-	normal := ctx.BoolT("isNormal")
-	instance := ctx.String("instance")
-	endpoint := ctx.String("endpoint")
+func ParseEntity(ctx *cli.Context) (*api.Entity, error) {
+	serviceID := ctx.String("service-id")
+	instance := ctx.String("instance-name")
+	endpoint := ctx.String("endpoint-name")
+
+	destServiceID := ctx.String("dest-service-id")
+	destInstance := ctx.String("dest-instance-name")
+	destEndpoint := ctx.String("dest-endpoint-name")
+
+	serviceName, isNormal, err := ParseServiceID(serviceID)
+	if err != nil {
+		return nil, err
+	}
 
-	destService := ctx.String("destService")
-	destNormal := ctx.BoolT("isDestNormal")
-	destInstance := ctx.String("destInstance")
-	destEndpoint := ctx.String("destEndpoint")
+	destServiceName, destIsNormal, err := ParseServiceID(destServiceID)
+	if err != nil {
+		return nil, err
+	}
 
 	entity := &api.Entity{
-		ServiceName:             &service,
-		Normal:                  &normal,
+		ServiceName:             &serviceName,
+		Normal:                  &isNormal,
 		ServiceInstanceName:     &instance,
 		EndpointName:            &endpoint,
-		DestServiceName:         &destService,
-		DestNormal:              &destNormal,
+		DestServiceName:         &destServiceName,
+		DestNormal:              &destIsNormal,
 		DestServiceInstanceName: &destInstance,
 		DestEndpointName:        &destEndpoint,
 	}
 	entity.Scope = utils.ParseScope(entity)
 
-	return entity
+	return entity, nil
+}
+
+func ParseServiceID(id string) (name string, isNormal bool, err error) {
+	if id == "" {
+		return "", false, nil
+	}
+	parts := strings.Split(id, ".")
+	if len(parts) != 2 {
+		return "", false, fmt.Errorf("invalid service id, cannot be splitted into 2 parts. %v", id)
+	}
+	nameBytes, err := base64.StdEncoding.DecodeString(parts[0])
+	if err != nil {
+		return "", false, err
+	}
+	name = string(nameBytes)
+	isNormal = parts[1] == "1"
+
+	return name, isNormal, nil
 }
diff --git a/internal/commands/interceptor/event.go b/internal/commands/interceptor/event.go
index 2e30cf0..27d2cfe 100644
--- a/internal/commands/interceptor/event.go
+++ b/internal/commands/interceptor/event.go
@@ -21,14 +21,14 @@ import (
 	"fmt"
 	"strings"
 
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 )
 
 // ParseParameters parses parameters of the event message from args.
 func ParseParameters(paras cli.Args) (map[string]string, error) {
-	ret := make(map[string]string, len(paras))
+	ret := make(map[string]string, paras.Len())
 
-	for _, para := range paras {
+	for _, para := range paras.Slice() {
 		sepIndex := strings.Index(para, "=")
 		// To make sure that len(k) > 0 && len(v) > 0
 		if len(para) >= 3 && sepIndex >= 1 && sepIndex < len(para)-1 {
diff --git a/internal/commands/interceptor/event_test.go b/internal/commands/interceptor/event_test.go
index 6d86437..49fbe27 100644
--- a/internal/commands/interceptor/event_test.go
+++ b/internal/commands/interceptor/event_test.go
@@ -21,7 +21,7 @@ import (
 	"reflect"
 	"testing"
 
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 )
 
 func TestParseParameters(t *testing.T) {
diff --git a/internal/commands/interceptor/instance.go b/internal/commands/interceptor/instance.go
new file mode 100644
index 0000000..742e500
--- /dev/null
+++ b/internal/commands/interceptor/instance.go
@@ -0,0 +1,101 @@
+// 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 interceptor
+
+import (
+	"encoding/base64"
+	"fmt"
+	"strings"
+
+	"github.com/urfave/cli/v2"
+)
+
+const (
+	instanceIDFlagName       = "instance-id"
+	instanceNameFlagName     = "instance-name"
+	destInstanceIDFlagName   = "dest-instance-id"
+	destInstanceNameFlagName = "dest-instance-name"
+)
+
+// ParseInstance parses the service instance id or service instance name,
+// and converts the present one to the missing one.
+// See flags.InstanceFlags.
+func ParseInstance(required bool) func(*cli.Context) error {
+	return func(ctx *cli.Context) error {
+		if err := ParseService(required)(ctx); err != nil {
+			return err
+		}
+		return parseInstance(required, instanceIDFlagName, instanceNameFlagName, serviceIDFlagName)(ctx)
+	}
+}
+
+// ParseInstanceRelation parses the source and destination service instance id or service instance name,
+// and converts the present one to the missing one respectively.
+// See flags.InstanceRelationFlags.
+func ParseInstanceRelation(required bool) func(*cli.Context) error {
+	return func(ctx *cli.Context) error {
+		if err := ParseService(required)(ctx); err != nil {
+			return err
+		}
+		if err := ParseInstance(required)(ctx); err != nil {
+			return err
+		}
+		return parseInstance(required, destInstanceIDFlagName, destInstanceNameFlagName, destServiceIDFlagName)(ctx)
+	}
+}
+
+func parseInstance(required bool, idFlagName, nameFlagName, serviceIDFlagName string) func(*cli.Context) error {
+	return func(ctx *cli.Context) error {
+		id := ctx.String(idFlagName)
+		name := ctx.String(nameFlagName)
+		serviceID := ctx.String(serviceIDFlagName)
+
+		if id == "" && name == "" {
+			if required {
+				return fmt.Errorf(`either flags "--%s" or "--%s" must be given`, idFlagName, nameFlagName)
+			}
+			return nil
+		}
+
+		if name != "" {
+			if serviceID == "" {
+				return fmt.Errorf(`"--%s" is specified but its related service name or id is not given`, nameFlagName)
+			}
+			id = serviceID + "_" + b64enc(name)
+		} else if id != "" {
+			parts := strings.Split(id, "_")
+			if len(parts) != 2 {
+				return fmt.Errorf("invalid instance id, cannot be splitted into 2 parts. %v", id)
+			}
+			s, err := base64.StdEncoding.DecodeString(parts[1])
+			if err != nil {
+				return err
+			}
+			name = string(s)
+		}
+
+		if err := ctx.Set(idFlagName, id); err != nil {
+			return err
+		}
+		if err := ctx.Set(nameFlagName, name); err != nil {
+			return err
+		}
+
+		return nil
+	}
+}
diff --git a/internal/commands/interceptor/interceptor.go b/internal/commands/interceptor/interceptor.go
index d7b89aa..572d11c 100644
--- a/internal/commands/interceptor/interceptor.go
+++ b/internal/commands/interceptor/interceptor.go
@@ -18,12 +18,16 @@
 package interceptor
 
 import (
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 )
 
 // BeforeChain is a convenient function to chain up multiple cli.BeforeFunc
-func BeforeChain(beforeFunctions []cli.BeforeFunc) cli.BeforeFunc {
+func BeforeChain(beforeFunctions ...cli.BeforeFunc) cli.BeforeFunc {
 	return func(ctx *cli.Context) error {
+		// --timezone is global option, it should be applied always.
+		if err := TimezoneInterceptor(ctx); err != nil {
+			return err
+		}
 		for _, beforeFunc := range beforeFunctions {
 			if err := beforeFunc(ctx); err != nil {
 				return err
diff --git a/internal/commands/interceptor/service.go b/internal/commands/interceptor/service.go
new file mode 100644
index 0000000..d359440
--- /dev/null
+++ b/internal/commands/interceptor/service.go
@@ -0,0 +1,98 @@
+// 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 interceptor
+
+import (
+	"encoding/base64"
+	"fmt"
+	"strings"
+
+	"github.com/apache/skywalking-cli/internal/logger"
+	"github.com/urfave/cli/v2"
+
+	"github.com/apache/skywalking-cli/pkg/graphql/metadata"
+)
+
+const (
+	serviceIDFlagName       = "service-id"
+	serviceNameFlagName     = "service-name"
+	destServiceIDFlagName   = "dest-service-id"
+	destServiceNameFlagName = "dest-service-name"
+)
+
+// ParseService parses the service id or service name,
+// and converts the present one to the missing one.
+// See flags.ServiceFlags.
+func ParseService(required bool) func(*cli.Context) error {
+	return parseService(required, serviceIDFlagName, serviceNameFlagName)
+}
+
+// ParseServiceRelation parses the source and destination service id or service name,
+// and converts the present one to the missing one respectively.
+// See flags.ServiceRelationFlags.
+func ParseServiceRelation(required bool) func(*cli.Context) error {
+	return func(ctx *cli.Context) error {
+		if err := ParseService(required)(ctx); err != nil {
+			return err
+		}
+		return parseService(required, destServiceIDFlagName, destServiceNameFlagName)(ctx)
+	}
+}
+
+func parseService(required bool, idFlagName, nameFlagName string) func(*cli.Context) error {
+	return func(ctx *cli.Context) error {
+		id := ctx.String(idFlagName)
+		name := ctx.String(nameFlagName)
+
+		if id == "" && name == "" {
+			if required {
+				return fmt.Errorf(`either flags "--%s" or "--%s" must be given`, idFlagName, nameFlagName)
+			}
+			return nil
+		}
+
+		if name != "" {
+			service, err := metadata.SearchService(ctx, name)
+			if err != nil {
+				return err
+			}
+			id = service.ID
+		} else if id != "" {
+			parts := strings.Split(id, ".")
+			if len(parts) != 2 {
+				return fmt.Errorf("invalid service id, cannot be splitted into 2 parts. %v", id)
+			}
+			s, err := base64.StdEncoding.DecodeString(parts[0])
+			if err != nil {
+				return err
+			}
+			name = string(s)
+		}
+
+		if err := ctx.Set(idFlagName, id); err != nil {
+			return err
+		}
+		if err := ctx.Set(nameFlagName, name); err != nil {
+			return err
+		}
+
+		logger.Log.Debugf("%v=%v, %v=%v", idFlagName, id, nameFlagName, name)
+
+		return nil
+	}
+}
diff --git a/internal/commands/interceptor/timezone.go b/internal/commands/interceptor/timezone.go
index f75c318..83fa904 100644
--- a/internal/commands/interceptor/timezone.go
+++ b/internal/commands/interceptor/timezone.go
@@ -18,9 +18,10 @@
 package interceptor
 
 import (
+	"fmt"
 	"strconv"
 
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 
 	"github.com/apache/skywalking-cli/internal/logger"
 	"github.com/apache/skywalking-cli/pkg/graphql/metadata"
@@ -30,7 +31,7 @@ import (
 // otherwise, sets to local timezone
 func TimezoneInterceptor(ctx *cli.Context) error {
 	// If there is timezone given by the user in command line, use it directly
-	if ctx.GlobalString("timezone") != "" {
+	if ctx.IsSet("timezone") {
 		return nil
 	}
 
@@ -43,7 +44,12 @@ func TimezoneInterceptor(ctx *cli.Context) error {
 
 	if timezone := serverTimeInfo.Timezone; timezone != nil {
 		if _, err := strconv.Atoi(*timezone); err == nil {
-			return ctx.GlobalSet("timezone", *timezone)
+			for _, c := range ctx.Lineage() {
+				if err := c.Set("timezone", *timezone); err == nil {
+					return nil
+				}
+			}
+			return fmt.Errorf("cannot set the timezone flag globally")
 		}
 	}
 
diff --git a/internal/commands/logs/list.go b/internal/commands/logs/list.go
index 9a13881..25ea61c 100644
--- a/internal/commands/logs/list.go
+++ b/internal/commands/logs/list.go
@@ -24,55 +24,42 @@ import (
 
 	"github.com/apache/skywalking-cli/internal/commands/interceptor"
 	"github.com/apache/skywalking-cli/internal/flags"
-	"github.com/apache/skywalking-cli/internal/logger"
 	"github.com/apache/skywalking-cli/internal/model"
 	"github.com/apache/skywalking-cli/pkg/display"
 	"github.com/apache/skywalking-cli/pkg/display/displayable"
 	"github.com/apache/skywalking-cli/pkg/graphql/log"
 
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 )
 
 const DefaultPageSize = 15
 
-var ListCommand = cli.Command{
-	Name:      "list",
-	ShortName: "ls",
-	Usage:     "List logs",
+var ListCommand = &cli.Command{
+	Name:    "list",
+	Aliases: []string{"ls"},
+	Usage:   "List logs",
 	Flags: flags.Flags(
 		flags.DurationFlags,
+		flags.InstanceFlags,
+		flags.EndpointFlags,
 		[]cli.Flag{
-			cli.StringFlag{
-				Name:     "service-id",
-				Usage:    "service id",
-				Required: false,
-			},
-			cli.StringFlag{
-				Name:     "service-instance-id",
-				Usage:    "service instance id",
-				Required: false,
-			},
-			cli.StringFlag{
-				Name:     "endpoint-id",
-				Usage:    "endpoint id",
-				Required: false,
-			},
-			cli.StringFlag{
+			&cli.StringFlag{
 				Name:     "trace-id",
-				Usage:    "relate trace id",
+				Usage:    "related trace id",
 				Required: false,
 			},
-			cli.StringFlag{
+			&cli.StringFlag{
 				Name:     "tags",
 				Usage:    "key=value,key=value",
 				Required: false,
 			},
 		},
 	),
-	Before: interceptor.BeforeChain([]cli.BeforeFunc{
-		interceptor.TimezoneInterceptor,
+	Before: interceptor.BeforeChain(
 		interceptor.DurationInterceptor,
-	}),
+		interceptor.ParseInstance(false),
+		interceptor.ParseEndpoint(false),
+	),
 	Action: func(ctx *cli.Context) error {
 		start := ctx.String("start")
 		end := ctx.String("end")
@@ -84,7 +71,7 @@ var ListCommand = cli.Command{
 			Step:  step.(*model.StepEnumValue).Selected,
 		}
 		serviceID := ctx.String("service-id")
-		serviceInstanceID := ctx.String("service-instance-id")
+		serviceInstanceID := ctx.String("instance-id")
 		endpointID := ctx.String("endpoint-id")
 		traceID := ctx.String("trace-id")
 		pageNum := 1
@@ -118,7 +105,7 @@ var ListCommand = cli.Command{
 		logs, err := log.Logs(ctx, condition)
 
 		if err != nil {
-			logger.Log.Fatalln(err)
+			return err
 		}
 
 		return display.Display(ctx, &displayable.Displayable{Data: logs, Condition: condition})
diff --git a/internal/commands/logs/log.go b/internal/commands/logs/log.go
index 0f02a02..16eb3a7 100644
--- a/internal/commands/logs/log.go
+++ b/internal/commands/logs/log.go
@@ -18,13 +18,13 @@
 package logs
 
 import (
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 )
 
-var Command = cli.Command{
-	Name:      "logs",
-	ShortName: "l",
-	Usage:     "logs related sub-command",
+var Command = &cli.Command{
+	Name:    "logs",
+	Aliases: []string{"l"},
+	Usage:   "Logs related sub-command",
 	Subcommands: cli.Commands{
 		ListCommand,
 	},
diff --git a/internal/commands/metrics/aggregation/topn.go b/internal/commands/metrics/aggregation/topn.go
index 5092299..a6fb673 100644
--- a/internal/commands/metrics/aggregation/topn.go
+++ b/internal/commands/metrics/aggregation/topn.go
@@ -23,7 +23,7 @@ import (
 
 	api "skywalking.apache.org/repo/goapi/query"
 
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 
 	"github.com/apache/skywalking-cli/internal/commands/interceptor"
 	"github.com/apache/skywalking-cli/internal/flags"
@@ -35,15 +35,28 @@ import (
 	"github.com/apache/skywalking-cli/pkg/graphql/utils"
 )
 
-var TopN = cli.Command{
+var TopN = &cli.Command{
 	Name:      "top",
-	Usage:     "query top `n` entities",
+	Usage:     "query the top <n> entities sorted by the specified metrics",
 	ArgsUsage: "<n>",
+	UsageText: `Query the top <n> entities sorted by the specified metrics.
+
+Examples:
+1. Query the top 5 services whose sla are largest:
+$ swctl metrics top --name service_sla 5
+
+2. Query the top 5 endpoints whose sla is largest:
+$ swctl metrics top --name endpoint_sla 5
+
+3. Query the top 5 instances of service "boutique::adservice" whose sla are largest:
+$ swctl metrics top --name service_instance_sla --service-name boutique::adservice 5
+`,
 	Flags: flags.Flags(
 		flags.DurationFlags,
 		flags.MetricsFlags,
+		flags.ServiceFlags,
 		[]cli.Flag{
-			cli.GenericFlag{
+			&cli.GenericFlag{
 				Name:  "order",
 				Usage: "the `order` by which the top entities are sorted",
 				Value: &model.OrderEnumValue{
@@ -54,21 +67,24 @@ var TopN = cli.Command{
 			},
 		},
 	),
-	Before: interceptor.BeforeChain([]cli.BeforeFunc{
-		interceptor.TimezoneInterceptor,
+	Before: interceptor.BeforeChain(
 		interceptor.DurationInterceptor,
-	}),
+		interceptor.ParseService(false),
+	),
 	Action: func(ctx *cli.Context) error {
 		start := ctx.String("start")
 		end := ctx.String("end")
 		step := ctx.Generic("step").(*model.StepEnumValue).Selected
 
 		metricsName := ctx.String("name")
-		normal := ctx.BoolT("isNormal")
 		scope := utils.ParseScopeInTop(metricsName)
 		order := ctx.Generic("order").(*model.OrderEnumValue).Selected
 		topN := 5
-		parentService := ctx.String("service")
+		parentServiceID := ctx.String("service-id")
+		parentService, normal, err := interceptor.ParseServiceID(parentServiceID)
+		if err != nil {
+			return err
+		}
 
 		if ctx.NArg() > 0 {
 			nn, err := strconv.Atoi(ctx.Args().First())
@@ -84,9 +100,7 @@ var TopN = cli.Command{
 			Step:  step,
 		}
 
-		if ctx.Bool("debug") {
-			logger.Log.Debugln(metricsName, scope, topN)
-		}
+		logger.Log.Debugln(metricsName, scope, topN)
 
 		metricsValues, err := metrics.SortMetrics(ctx, api.TopNCondition{
 			Name:          metricsName,
@@ -98,7 +112,7 @@ var TopN = cli.Command{
 		}, duration)
 
 		if err != nil {
-			logger.Log.Fatalln(err)
+			return err
 		}
 
 		return display.Display(ctx, &displayable.Displayable{Data: metricsValues})
diff --git a/internal/commands/metrics/linear/linear-metrics.go b/internal/commands/metrics/linear/linear-metrics.go
index 20ffaf5..54f0b87 100644
--- a/internal/commands/metrics/linear/linear-metrics.go
+++ b/internal/commands/metrics/linear/linear-metrics.go
@@ -20,7 +20,6 @@ package linear
 import (
 	"github.com/apache/skywalking-cli/internal/commands/interceptor"
 	"github.com/apache/skywalking-cli/internal/flags"
-	"github.com/apache/skywalking-cli/internal/logger"
 	"github.com/apache/skywalking-cli/internal/model"
 	"github.com/apache/skywalking-cli/pkg/display"
 	"github.com/apache/skywalking-cli/pkg/display/displayable"
@@ -29,28 +28,33 @@ import (
 
 	api "skywalking.apache.org/repo/goapi/query"
 
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 )
 
-var Single = cli.Command{
+var Single = &cli.Command{
 	Name:  "linear",
 	Usage: "Query linear metrics defined in backend OAL",
 	Flags: flags.Flags(
 		flags.DurationFlags,
 		flags.MetricsFlags,
-		flags.EntityFlags,
+		flags.InstanceRelationFlags,
+		flags.EndpointRelationFlags,
 	),
-	Before: interceptor.BeforeChain([]cli.BeforeFunc{
-		interceptor.TimezoneInterceptor,
+	Before: interceptor.BeforeChain(
 		interceptor.DurationInterceptor,
-	}),
+		interceptor.ParseInstanceRelation(false),
+		interceptor.ParseEndpointRelation(false),
+	),
 	Action: func(ctx *cli.Context) error {
 		end := ctx.String("end")
 		start := ctx.String("start")
 		step := ctx.Generic("step")
 
 		metricsName := ctx.String("name")
-		entity := interceptor.ParseEntity(ctx)
+		entity, err := interceptor.ParseEntity(ctx)
+		if err != nil {
+			return err
+		}
 
 		duration := api.Duration{
 			Start: start,
@@ -64,7 +68,7 @@ var Single = cli.Command{
 		}, duration)
 
 		if err != nil {
-			logger.Log.Fatalln(err)
+			return err
 		}
 
 		return display.Display(ctx, &displayable.Displayable{Data: utils.MetricsValuesToMap(duration, metricsValues)})
diff --git a/internal/commands/metrics/linear/multiple-linear-metrics.go b/internal/commands/metrics/linear/multiple-linear-metrics.go
index b1193ea..88c44ed 100644
--- a/internal/commands/metrics/linear/multiple-linear-metrics.go
+++ b/internal/commands/metrics/linear/multiple-linear-metrics.go
@@ -25,25 +25,25 @@ import (
 
 	"github.com/apache/skywalking-cli/internal/commands/interceptor"
 	"github.com/apache/skywalking-cli/internal/flags"
-	"github.com/apache/skywalking-cli/internal/logger"
 	"github.com/apache/skywalking-cli/internal/model"
 	"github.com/apache/skywalking-cli/pkg/display"
 	"github.com/apache/skywalking-cli/pkg/display/displayable"
 	"github.com/apache/skywalking-cli/pkg/graphql/metrics"
 	"github.com/apache/skywalking-cli/pkg/graphql/utils"
 
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 )
 
-var Multiple = cli.Command{
+var Multiple = &cli.Command{
 	Name:  "multiple-linear",
 	Usage: "Query multiple linear metrics defined in backend OAL",
 	Flags: flags.Flags(
 		flags.DurationFlags,
 		flags.MetricsFlags,
-		flags.EntityFlags,
+		flags.InstanceRelationFlags,
+		flags.EndpointRelationFlags,
 		[]cli.Flag{
-			cli.StringFlag{
+			&cli.StringFlag{
 				Name:     "labels",
 				Usage:    "the labels you need to query",
 				Required: false,
@@ -51,10 +51,11 @@ var Multiple = cli.Command{
 			},
 		},
 	),
-	Before: interceptor.BeforeChain([]cli.BeforeFunc{
-		interceptor.TimezoneInterceptor,
+	Before: interceptor.BeforeChain(
 		interceptor.DurationInterceptor,
-	}),
+		interceptor.ParseInstanceRelation(false),
+		interceptor.ParseEndpointRelation(false),
+	),
 	Action: func(ctx *cli.Context) error {
 		end := ctx.String("end")
 		start := ctx.String("start")
@@ -62,7 +63,10 @@ var Multiple = cli.Command{
 
 		metricsName := ctx.String("name")
 		labels := ctx.String("labels")
-		entity := interceptor.ParseEntity(ctx)
+		entity, err := interceptor.ParseEntity(ctx)
+		if err != nil {
+			return err
+		}
 
 		if *entity.ServiceName == "" && entity.Scope != api.ScopeAll {
 			return fmt.Errorf("the name of service should be specified when metrics' scope is not `All`")
@@ -76,11 +80,11 @@ var Multiple = cli.Command{
 
 		metricsValuesArray, err := metrics.MultipleLinearIntValues(ctx, api.MetricsCondition{
 			Name:   metricsName,
-			Entity: interceptor.ParseEntity(ctx),
+			Entity: entity,
 		}, strings.Split(labels, ","), duration)
 
 		if err != nil {
-			logger.Log.Fatalln(err)
+			return err
 		}
 
 		reshaped := utils.MetricsValuesArrayToMap(duration, metricsValuesArray)
diff --git a/internal/commands/metrics/list/list-metrics.go b/internal/commands/metrics/list/list-metrics.go
index ca67689..21e7828 100644
--- a/internal/commands/metrics/list/list-metrics.go
+++ b/internal/commands/metrics/list/list-metrics.go
@@ -18,21 +18,27 @@
 package list
 
 import (
-	"github.com/urfave/cli"
-
-	"github.com/apache/skywalking-cli/internal/logger"
+	"github.com/urfave/cli/v2"
 
 	"github.com/apache/skywalking-cli/pkg/display"
 	"github.com/apache/skywalking-cli/pkg/display/displayable"
 	"github.com/apache/skywalking-cli/pkg/graphql/metrics"
 )
 
-var Command = cli.Command{
-	Name:      "list",
-	ShortName: "ls",
-	Usage:     "List metrics that could be queried",
+var Command = &cli.Command{
+	Name:    "list",
+	Aliases: []string{"ls"},
+	Usage:   "List metrics that could be queried",
+	UsageText: `With this command, you can list all available metrics
+as well as their types and catalogs that can be used in other metrics command
+to get the details.
+
+Examples:
+
+1. Query the metrics names start with "service_"
+$ swctl metrics list --regex "service_.*"`,
 	Flags: []cli.Flag{
-		cli.StringFlag{
+		&cli.StringFlag{
 			Name:  "regex",
 			Usage: "filter metrics with regex",
 		},
@@ -43,7 +49,7 @@ var Command = cli.Command{
 		metricsValue, err := metrics.ListMetrics(ctx, regex)
 
 		if err != nil {
-			logger.Log.Fatalln(err)
+			return err
 		}
 
 		return display.Display(ctx, &displayable.Displayable{Data: metricsValue})
diff --git a/internal/commands/metrics/metrics.go b/internal/commands/metrics/metrics.go
index 78196d7..ad2fe37 100644
--- a/internal/commands/metrics/metrics.go
+++ b/internal/commands/metrics/metrics.go
@@ -18,7 +18,7 @@
 package metrics
 
 import (
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 
 	"github.com/apache/skywalking-cli/internal/commands/metrics/aggregation"
 	"github.com/apache/skywalking-cli/internal/commands/metrics/list"
@@ -29,7 +29,7 @@ import (
 	"github.com/apache/skywalking-cli/internal/commands/metrics/single"
 )
 
-var Command = cli.Command{
+var Command = &cli.Command{
 	Name:  "metrics",
 	Usage: "Query metrics defined in backend OAL",
 	Subcommands: cli.Commands{
diff --git a/internal/commands/metrics/single/single-metrics.go b/internal/commands/metrics/single/single-metrics.go
index fa07e3f..5c9afa7 100644
--- a/internal/commands/metrics/single/single-metrics.go
+++ b/internal/commands/metrics/single/single-metrics.go
@@ -18,11 +18,10 @@
 package single
 
 import (
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 
 	"github.com/apache/skywalking-cli/internal/commands/interceptor"
 	"github.com/apache/skywalking-cli/internal/flags"
-	"github.com/apache/skywalking-cli/internal/logger"
 	"github.com/apache/skywalking-cli/internal/model"
 	"github.com/apache/skywalking-cli/pkg/display"
 	"github.com/apache/skywalking-cli/pkg/display/displayable"
@@ -31,25 +30,38 @@ import (
 	api "skywalking.apache.org/repo/goapi/query"
 )
 
-var Command = cli.Command{
+var Command = &cli.Command{
 	Name:  "single",
-	Usage: "Query single metrics defined in backend OAL",
+	Usage: "query single-value metrics defined in backend OAL",
+	UsageText: `Query single-value metrics defined in backend OAL.
+
+Examples:
+1. Query the traffic load (calls per minute) of service "business-zone:projectC"
+$ swctl metrics single --name service_cpm --service-name business-zone::projectC
+
+2. Query the traffic load (calls per minute) of service "business-zone:projectC" endpoint "/projectC/{value}"
+$ swctl metrics single --name endpoint_cpm --service-name business-zone::projectC --endpoint-name /projectC/{value}`,
 	Flags: flags.Flags(
 		flags.DurationFlags,
 		flags.MetricsFlags,
-		flags.EntityFlags,
+		flags.InstanceRelationFlags,
+		flags.EndpointRelationFlags,
 	),
-	Before: interceptor.BeforeChain([]cli.BeforeFunc{
-		interceptor.TimezoneInterceptor,
+	Before: interceptor.BeforeChain(
 		interceptor.DurationInterceptor,
-	}),
+		interceptor.ParseInstanceRelation(false),
+		interceptor.ParseEndpointRelation(false),
+	),
 	Action: func(ctx *cli.Context) error {
 		end := ctx.String("end")
 		start := ctx.String("start")
 		step := ctx.Generic("step")
 
 		metricsName := ctx.String("name")
-		entity := interceptor.ParseEntity(ctx)
+		entity, err := interceptor.ParseEntity(ctx)
+		if err != nil {
+			return err
+		}
 
 		duration := api.Duration{
 			Start: start,
@@ -63,7 +75,7 @@ var Command = cli.Command{
 		}, duration)
 
 		if err != nil {
-			logger.Log.Fatalln(err)
+			return err
 		}
 
 		return display.Display(ctx, &displayable.Displayable{Data: metricsValue})
diff --git a/internal/commands/metrics/thermodynamic/thermodynamic.go b/internal/commands/metrics/thermodynamic/thermodynamic.go
index 7987c7c..52d6b1e 100644
--- a/internal/commands/metrics/thermodynamic/thermodynamic.go
+++ b/internal/commands/metrics/thermodynamic/thermodynamic.go
@@ -18,11 +18,10 @@
 package thermodynamic
 
 import (
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 
 	"github.com/apache/skywalking-cli/internal/commands/interceptor"
 	"github.com/apache/skywalking-cli/internal/flags"
-	"github.com/apache/skywalking-cli/internal/logger"
 	"github.com/apache/skywalking-cli/internal/model"
 	"github.com/apache/skywalking-cli/pkg/display"
 	"github.com/apache/skywalking-cli/pkg/display/displayable"
@@ -31,26 +30,37 @@ import (
 	api "skywalking.apache.org/repo/goapi/query"
 )
 
-var Command = cli.Command{
+var Command = &cli.Command{
 	Name:    "thermodynamic",
-	Aliases: []string{"td", "heatmap", "hp"},
-	Usage:   "Query thermodynamic metrics defined in backend OAL",
+	Aliases: []string{"td", "heatmap", "hp", "hm"},
+	Usage:   "query thermodynamic-type metrics defined in backend OAL",
+	UsageText: `Query the thermodynamic-type metrics defined in backend OAL.
+
+Examples:
+1. Query the global heatmap:
+$ swctl metrics thermodynamic --scope all --name all_heatmap
+`,
 	Flags: flags.Flags(
 		flags.DurationFlags,
 		flags.MetricsFlags,
-		flags.EntityFlags,
+		flags.InstanceRelationFlags,
+		flags.EndpointRelationFlags,
 	),
-	Before: interceptor.BeforeChain([]cli.BeforeFunc{
-		interceptor.TimezoneInterceptor,
+	Before: interceptor.BeforeChain(
 		interceptor.DurationInterceptor,
-	}),
+		interceptor.ParseInstanceRelation(false),
+		interceptor.ParseEndpointRelation(false),
+	),
 	Action: func(ctx *cli.Context) error {
 		end := ctx.String("end")
 		start := ctx.String("start")
 		step := ctx.Generic("step")
 
 		metricsName := ctx.String("name")
-		entity := interceptor.ParseEntity(ctx)
+		entity, err := interceptor.ParseEntity(ctx)
+		if err != nil {
+			return err
+		}
 
 		duration := api.Duration{
 			Start: start,
@@ -64,7 +74,7 @@ var Command = cli.Command{
 		}, duration)
 
 		if err != nil {
-			logger.Log.Fatalln(err)
+			return err
 		}
 
 		return display.Display(ctx, &displayable.Displayable{
diff --git a/internal/commands/profile/create.go b/internal/commands/profile/create.go
index 7993ba2..a7fe851 100644
--- a/internal/commands/profile/create.go
+++ b/internal/commands/profile/create.go
@@ -18,76 +18,57 @@
 package profile
 
 import (
-	"fmt"
-
-	"github.com/apache/skywalking-cli/internal/logger"
+	"github.com/apache/skywalking-cli/internal/commands/interceptor"
+	"github.com/apache/skywalking-cli/internal/flags"
 	"github.com/apache/skywalking-cli/pkg/display"
 	"github.com/apache/skywalking-cli/pkg/display/displayable"
-	"github.com/apache/skywalking-cli/pkg/graphql/metadata"
 	"github.com/apache/skywalking-cli/pkg/graphql/profile"
 
 	api "skywalking.apache.org/repo/goapi/query"
 
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 )
 
-var createCommand = cli.Command{
+var createCommand = &cli.Command{
 	Name:      "create",
 	Aliases:   []string{"c"},
 	Usage:     "create a new profile task",
 	ArgsUsage: "[parameters...]",
-	Flags: []cli.Flag{
-		cli.StringFlag{
-			Name:  "service-id",
-			Usage: "<service-id> whose endpoints are to be profile.",
-		},
-		cli.StringFlag{
-			Name:  "service-name",
-			Usage: "<service-name> whose endpoints are to be profile.",
-		},
-		cli.StringFlag{
-			Name:  "endpoint",
-			Usage: "which endpoint should profile.",
-		},
-		cli.Int64Flag{
-			Name:  "start-time",
-			Usage: "profile task start time(millisecond).",
-		},
-		cli.IntFlag{
-			Name:  "duration",
-			Usage: "profile task continuous time(minute).",
-		},
-		cli.IntFlag{
-			Name:  "min-duration-threshold",
-			Usage: "profiled endpoint must greater duration(millisecond).",
-		},
-		cli.IntFlag{
-			Name:  "dump-period",
-			Usage: "profiled endpoint dump period(millisecond).",
-		},
-		cli.IntFlag{
-			Name:  "max-sampling-count",
-			Usage: "profile task max sampling count.",
+	Flags: flags.Flags(
+		flags.EndpointFlags,
+
+		[]cli.Flag{
+			&cli.Int64Flag{
+				Name:  "start-time",
+				Usage: "profile task start time(millisecond).",
+			},
+			&cli.IntFlag{
+				Name:  "duration",
+				Usage: "profile task continuous time(minute).",
+			},
+			&cli.IntFlag{
+				Name:  "min-duration-threshold",
+				Usage: "profiled endpoint must greater duration(millisecond).",
+			},
+			&cli.IntFlag{
+				Name:  "dump-period",
+				Usage: "profiled endpoint dump period(millisecond).",
+			},
+			&cli.IntFlag{
+				Name:  "max-sampling-count",
+				Usage: "profile task max sampling count.",
+			},
 		},
-	},
+	),
+	Before: interceptor.BeforeChain(
+		interceptor.ParseEndpoint(true),
+	),
 	Action: func(ctx *cli.Context) error {
 		serviceID := ctx.String("service-id")
-		if serviceID == "" {
-			serviceName := ctx.String("service-name")
-			if serviceName == "" {
-				return fmt.Errorf(`either flags "service-id" or "service-name" must be set`)
-			}
-			service, err := metadata.SearchService(ctx, serviceName)
-			if err != nil {
-				return err
-			}
-			serviceID = service.ID
-		}
-
 		startTime := ctx.Int64("start-time")
 		request := &api.ProfileTaskCreationRequest{
 			ServiceID:            serviceID,
-			EndpointName:         ctx.String("endpoint"),
+			EndpointName:         ctx.String("endpoint-name"),
 			StartTime:            &startTime,
 			Duration:             ctx.Int("duration"),
 			MinDurationThreshold: ctx.Int("min-duration-threshold"),
@@ -98,7 +79,7 @@ var createCommand = cli.Command{
 		task, err := profile.CreateTask(ctx, request)
 
 		if err != nil {
-			logger.Log.Fatalln(err)
+			return err
 		}
 
 		return display.Display(ctx, &displayable.Displayable{Data: task, Condition: request})
diff --git a/internal/commands/profile/getProfileAnalyze.go b/internal/commands/profile/getProfileAnalyze.go
index 8847ad0..d928820 100644
--- a/internal/commands/profile/getProfileAnalyze.go
+++ b/internal/commands/profile/getProfileAnalyze.go
@@ -21,27 +21,26 @@ import (
 	"strconv"
 	"strings"
 
-	"github.com/apache/skywalking-cli/internal/logger"
 	"github.com/apache/skywalking-cli/pkg/display"
 	"github.com/apache/skywalking-cli/pkg/display/displayable"
 	"github.com/apache/skywalking-cli/pkg/graphql/profile"
 
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 
 	api "skywalking.apache.org/repo/goapi/query"
 )
 
-var getProfiledAnalyzeCommand = cli.Command{
+var getProfiledAnalyzeCommand = &cli.Command{
 	Name:      "profiled-analyze",
 	Aliases:   []string{"pa"},
 	Usage:     "analyze profiled segment.",
 	ArgsUsage: "[parameters...]",
 	Flags: []cli.Flag{
-		cli.StringFlag{
+		&cli.StringFlag{
 			Name:  "segment-id",
 			Usage: "profiled segment id.",
 		},
-		cli.StringFlag{
+		&cli.StringFlag{
 			Name:  "time-ranges",
 			Usage: "need to analyze time ranges in the segment: start-end,start-end",
 		},
@@ -70,7 +69,7 @@ var getProfiledAnalyzeCommand = cli.Command{
 		analysis, err := profile.GetProfileAnalyze(ctx, segmentID, timeRanges)
 
 		if err != nil {
-			logger.Log.Fatalln(err)
+			return err
 		}
 
 		return display.Display(ctx, &displayable.Displayable{Data: analysis, Condition: segmentID})
diff --git a/internal/commands/profile/getProfiledSegment.go b/internal/commands/profile/getProfiledSegment.go
index 5df747b..621c527 100644
--- a/internal/commands/profile/getProfiledSegment.go
+++ b/internal/commands/profile/getProfiledSegment.go
@@ -18,21 +18,20 @@
 package profile
 
 import (
-	"github.com/apache/skywalking-cli/internal/logger"
 	"github.com/apache/skywalking-cli/pkg/display"
 	"github.com/apache/skywalking-cli/pkg/display/displayable"
 	"github.com/apache/skywalking-cli/pkg/graphql/profile"
 
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 )
 
-var getProfiledSegmentCommand = cli.Command{
+var getProfiledSegmentCommand = &cli.Command{
 	Name:      "profiled-segment",
 	Aliases:   []string{"ps"},
 	Usage:     "query profile task segment list",
 	ArgsUsage: "[parameters...]",
 	Flags: []cli.Flag{
-		cli.StringFlag{
+		&cli.StringFlag{
 			Name:  "segment-id",
 			Usage: "profiled segment id.",
 		},
@@ -42,7 +41,7 @@ var getProfiledSegmentCommand = cli.Command{
 		segment, err := profile.GetProfiledSegment(ctx, segmentID)
 
 		if err != nil {
-			logger.Log.Fatalln(err)
+			return err
 		}
 
 		return display.Display(ctx, &displayable.Displayable{Data: segment, Condition: segmentID})
diff --git a/internal/commands/profile/getTaskList.go b/internal/commands/profile/getTaskList.go
index 67317f9..8a0fa47 100644
--- a/internal/commands/profile/getTaskList.go
+++ b/internal/commands/profile/getTaskList.go
@@ -20,30 +20,29 @@ package profile
 import (
 	"fmt"
 
-	"github.com/apache/skywalking-cli/internal/logger"
 	"github.com/apache/skywalking-cli/pkg/display"
 	"github.com/apache/skywalking-cli/pkg/display/displayable"
 	"github.com/apache/skywalking-cli/pkg/graphql/metadata"
 	"github.com/apache/skywalking-cli/pkg/graphql/profile"
 
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 )
 
-var getTaskListCommand = cli.Command{
+var getTaskListCommand = &cli.Command{
 	Name:      "list",
 	Aliases:   []string{"l"},
 	Usage:     "query profile task list",
 	ArgsUsage: "[parameters...]",
 	Flags: []cli.Flag{
-		cli.StringFlag{
+		&cli.StringFlag{
 			Name:  "service-id",
 			Usage: "`<service id>` whose profile task are to be searched",
 		},
-		cli.StringFlag{
+		&cli.StringFlag{
 			Name:  "service-name",
 			Usage: "`<service name>` whose profile task are to be searched",
 		},
-		cli.StringFlag{
+		&cli.StringFlag{
 			Name:  "endpoint",
 			Usage: "`<endpoint>` whose profile task are to be searched",
 		},
@@ -67,7 +66,7 @@ var getTaskListCommand = cli.Command{
 		task, err := profile.GetTaskList(ctx, serviceID, endpoint)
 
 		if err != nil {
-			logger.Log.Fatalln(err)
+			return err
 		}
 
 		return display.Display(ctx, &displayable.Displayable{Data: task, Condition: serviceID})
diff --git a/internal/commands/profile/getTaskSegmentList.go b/internal/commands/profile/getTaskSegmentList.go
index 869241b..6e48cdf 100644
--- a/internal/commands/profile/getTaskSegmentList.go
+++ b/internal/commands/profile/getTaskSegmentList.go
@@ -18,21 +18,20 @@
 package profile
 
 import (
-	"github.com/apache/skywalking-cli/internal/logger"
 	"github.com/apache/skywalking-cli/pkg/display"
 	"github.com/apache/skywalking-cli/pkg/display/displayable"
 	"github.com/apache/skywalking-cli/pkg/graphql/profile"
 
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 )
 
-var getTaskSegmentListCommand = cli.Command{
+var getTaskSegmentListCommand = &cli.Command{
 	Name:      "segment-list",
 	Aliases:   []string{"sl"},
 	Usage:     "query profile task segment list",
 	ArgsUsage: "[parameters...]",
 	Flags: []cli.Flag{
-		cli.StringFlag{
+		&cli.StringFlag{
 			Name:  "task-id",
 			Usage: "`<task id>` whose profiled segment are to be searched",
 		},
@@ -42,7 +41,7 @@ var getTaskSegmentListCommand = cli.Command{
 		segmentList, err := profile.GetTaskSegmentList(ctx, taskID)
 
 		if err != nil {
-			logger.Log.Fatalln(err)
+			return err
 		}
 
 		return display.Display(ctx, &displayable.Displayable{Data: segmentList, Condition: taskID})
diff --git a/internal/commands/profile/profile.go b/internal/commands/profile/profile.go
index 5f9136c..550fa30 100644
--- a/internal/commands/profile/profile.go
+++ b/internal/commands/profile/profile.go
@@ -18,13 +18,13 @@
 package profile
 
 import (
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 )
 
-var Command = cli.Command{
+var Command = &cli.Command{
 	Name:  "profile",
 	Usage: "Profile related sub-command",
-	Subcommands: []cli.Command{
+	Subcommands: []*cli.Command{
 		createCommand,
 		getTaskListCommand,
 		getTaskSegmentListCommand,
diff --git a/internal/commands/service/list.go b/internal/commands/service/list.go
index ee7c765..516a6a7 100644
--- a/internal/commands/service/list.go
+++ b/internal/commands/service/list.go
@@ -18,30 +18,36 @@
 package service
 
 import (
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 
 	api "skywalking.apache.org/repo/goapi/query"
 
 	"github.com/apache/skywalking-cli/internal/commands/interceptor"
 	"github.com/apache/skywalking-cli/internal/flags"
-	"github.com/apache/skywalking-cli/internal/logger"
 	"github.com/apache/skywalking-cli/internal/model"
 	"github.com/apache/skywalking-cli/pkg/display"
 	"github.com/apache/skywalking-cli/pkg/display/displayable"
 	"github.com/apache/skywalking-cli/pkg/graphql/metadata"
 )
 
-var ListCommand = cli.Command{
-	Name:        "list",
-	ShortName:   "ls",
-	Usage:       "List services",
-	ArgsUsage:   "<service name>",
-	Description: "list all services if no <service name> is given, otherwise, only list the given service",
-	Flags:       flags.DurationFlags,
-	Before: interceptor.BeforeChain([]cli.BeforeFunc{
-		interceptor.TimezoneInterceptor,
+var ListCommand = &cli.Command{
+	Name:      "list",
+	Aliases:   []string{"ls"},
+	Usage:     `list the monitored services`,
+	ArgsUsage: "<service name>",
+	UsageText: `This command lists all services if no "<service name>" is given, 
+otherwise, it only lists the services matching the given "<service name>".
+
+Examples:
+1. List all the services:
+$ swctl svc ls
+
+2. List a specific service named "projectC":
+$ swctl svc ls projectC`,
+	Flags: flags.DurationFlags,
+	Before: interceptor.BeforeChain(
 		interceptor.DurationInterceptor,
-	}),
+	),
 	Action: func(ctx *cli.Context) error {
 		end := ctx.String("end")
 		start := ctx.String("start")
@@ -50,19 +56,19 @@ var ListCommand = cli.Command{
 		var services []api.Service
 		var err error
 
-		if args := ctx.Args(); len(args) == 0 {
+		if args := ctx.Args(); args.Len() == 0 {
 			services, err = metadata.AllServices(ctx, api.Duration{
 				Start: start,
 				End:   end,
 				Step:  step.(*model.StepEnumValue).Selected,
 			})
 			if err != nil {
-				logger.Log.Fatalln(err)
+				return err
 			}
 		} else {
 			service, err := metadata.SearchService(ctx, args.First())
 			if err != nil {
-				logger.Log.Fatalln(err)
+				return err
 			}
 			services = []api.Service{service}
 		}
diff --git a/internal/commands/service/service.go b/internal/commands/service/service.go
index 6551609..9e85b2a 100644
--- a/internal/commands/service/service.go
+++ b/internal/commands/service/service.go
@@ -18,13 +18,13 @@
 package service
 
 import (
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 )
 
-var Command = cli.Command{
-	Name:      "service",
-	ShortName: "s",
-	Usage:     "Service related sub-command",
+var Command = &cli.Command{
+	Name:    "service",
+	Aliases: []string{"s", "svc"},
+	Usage:   "Service related sub-command",
 	Subcommands: cli.Commands{
 		ListCommand,
 	},
diff --git a/internal/commands/trace/list.go b/internal/commands/trace/list.go
index bbae370..e6bcc0a 100644
--- a/internal/commands/trace/list.go
+++ b/internal/commands/trace/list.go
@@ -18,15 +18,15 @@
 package trace
 
 import (
+	"fmt"
 	"strings"
 
 	api "skywalking.apache.org/repo/goapi/query"
 
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 
 	"github.com/apache/skywalking-cli/internal/commands/interceptor"
 	"github.com/apache/skywalking-cli/internal/flags"
-	"github.com/apache/skywalking-cli/internal/logger"
 	"github.com/apache/skywalking-cli/internal/model"
 	"github.com/apache/skywalking-cli/pkg/display"
 	"github.com/apache/skywalking-cli/pkg/display/displayable"
@@ -35,41 +35,53 @@ import (
 
 const DefaultPageSize = 15
 
-var ListCommand = cli.Command{
-	Name:      "list",
-	ShortName: "ls",
-	Usage:     "query traces",
+var ListCommand = &cli.Command{
+	Name:    "list",
+	Aliases: []string{"ls"},
+	Usage:   "Query the monitored traces",
+	UsageText: `Query the monitored traces.
+
+Examples:
+1. Query all monitored traces:
+$ swctl trace ls
+
+2. Query all monitored traces of service "business-zone::projectB":
+$ swctl trace ls --service-name "business-zone::projectB"
+
+3. Query all monitored traces of endpoint "/projectB/{value}" of service "business-zone::projectB":
+$ swctl trace ls --service-name "business-zone::projectB" --endpoint-name "/projectB/{value}"
+
+3. Query the monitored trace of id "321661b1-9a31-4e12-ad64-c8f6711f108d":
+$ swctl trace ls --trace-id "321661b1-9a31-4e12-ad64-c8f6711f108d"
+`,
 	Flags: flags.Flags(
 		flags.DurationFlags,
+		flags.InstanceFlags,
+		flags.EndpointFlags,
 		[]cli.Flag{
-			cli.StringFlag{
-				Name:     "service-id",
-				Usage:    "service id",
-				Required: false,
-			},
-			cli.StringFlag{
-				Name:     "service-instance-id",
-				Usage:    "service instance id",
-				Required: false,
-			},
-			cli.StringFlag{
+			&cli.StringFlag{
 				Name:     "trace-id",
-				Usage:    "trace id",
+				Usage:    "`id` of the trace",
 				Required: false,
 			},
-			cli.StringFlag{
+			&cli.StringFlag{
 				Name:     "tags",
-				Usage:    "key=value,key=value",
+				Usage:    "`tags` of the trace, in form of `key=value,key=value`",
 				Required: false,
 			},
+			&cli.StringFlag{
+				Name:  "order",
+				Usage: "`order` of the returned traces, can be `duration` or `startTime`",
+				Value: "duration",
+			},
 		},
 	),
-	Before: interceptor.BeforeChain([]cli.BeforeFunc{
-		interceptor.TimezoneInterceptor,
+	Before: interceptor.BeforeChain(
 		interceptor.DurationInterceptor,
-	}),
+		interceptor.ParseInstance(false),
+		interceptor.ParseEndpoint(false),
+	),
 	Action: func(ctx *cli.Context) error {
-
 		start := ctx.String("start")
 		end := ctx.String("end")
 		step := ctx.Generic("step")
@@ -80,7 +92,8 @@ var ListCommand = cli.Command{
 			Step:  step.(*model.StepEnumValue).Selected,
 		}
 		serviceID := ctx.String("service-id")
-		serviceInstanceID := ctx.String("service-instance-id")
+		endpointID := ctx.String("endpoint-id")
+		serviceInstanceID := ctx.String("instance-id")
 		traceID := ctx.String("trace-id")
 		tagStr := ctx.String("tags")
 		var tags []*api.SpanTag = nil
@@ -100,23 +113,33 @@ var ListCommand = cli.Command{
 			NeedTotal: &needTotal,
 		}
 
+		var order api.QueryOrder
+		switch orderStr := ctx.String("order"); orderStr {
+		case "duration":
+			order = api.QueryOrderByDuration
+		case "startTime":
+			order = api.QueryOrderByStartTime
+		default:
+			return fmt.Errorf(`invalid order %v, must be one of "duration" or "startTime"`, orderStr)
+		}
+
 		condition := &api.TraceQueryCondition{
 			ServiceID:         &serviceID,
 			ServiceInstanceID: &serviceInstanceID,
 			TraceID:           &traceID,
-			EndpointID:        nil,
+			EndpointID:        &endpointID,
 			QueryDuration:     &duration,
 			MinTraceDuration:  nil,
 			MaxTraceDuration:  nil,
 			TraceState:        api.TraceStateAll,
-			QueryOrder:        api.QueryOrderByDuration,
+			QueryOrder:        order,
 			Tags:              tags,
 			Paging:            &paging,
 		}
 		traces, err := trace.Traces(ctx, condition)
 
 		if err != nil {
-			logger.Log.Fatalln(err)
+			return err
 		}
 
 		return display.Display(ctx, &displayable.Displayable{Data: traces, Condition: condition})
diff --git a/internal/commands/trace/trace.go b/internal/commands/trace/trace.go
index 9def645..3ae38c2 100644
--- a/internal/commands/trace/trace.go
+++ b/internal/commands/trace/trace.go
@@ -20,20 +20,26 @@ package trace
 import (
 	"fmt"
 
-	"github.com/apache/skywalking-cli/internal/logger"
-
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 
 	"github.com/apache/skywalking-cli/pkg/display"
 	"github.com/apache/skywalking-cli/pkg/display/displayable"
 	"github.com/apache/skywalking-cli/pkg/graphql/trace"
 )
 
-var Command = cli.Command{
+var Command = &cli.Command{
 	Name:      "trace",
-	ShortName: "t",
-	Usage:     "trace related sub-command",
-	ArgsUsage: "trace id",
+	Aliases:   []string{"t"},
+	Usage:     "Trace related sub-command",
+	ArgsUsage: "<trace id>",
+	UsageText: `This command can be used to query the details of a trace,
+and its sub-command "ls" can be used to list all or part of the traces
+with specified options, like service name, endpoint name, etc.
+
+Examples:
+
+1. Query the trace details (spans) of id "321661b1-9a31-4e12-ad64-c8f6711f108d":
+$ swctl trace "321661b1-9a31-4e12-ad64-c8f6711f108d"`,
 	Action: func(ctx *cli.Context) error {
 		if ctx.NArg() == 0 {
 			return fmt.Errorf("command trace without sub command requires 1 trace id as argument")
@@ -42,7 +48,7 @@ var Command = cli.Command{
 		trace, err := trace.Trace(ctx, ctx.Args().First())
 
 		if err != nil {
-			logger.Log.Fatalln(err)
+			return err
 		}
 
 		return display.Display(ctx, &displayable.Displayable{Data: trace})
diff --git a/internal/flags/duration.go b/internal/flags/duration.go
index eed7b2f..29c4e8f 100644
--- a/internal/flags/duration.go
+++ b/internal/flags/duration.go
@@ -18,26 +18,44 @@
 package flags
 
 import (
-	"github.com/urfave/cli"
+	"strings"
+
+	"github.com/urfave/cli/v2"
 
 	api "skywalking.apache.org/repo/goapi/query"
 
 	"github.com/apache/skywalking-cli/internal/model"
 )
 
+var startEndUsage = strings.Join(strings.Split(`"start" and "end" specify a time range during which the query is preformed, 
+they are both optional and their default values follow the rules below: 
+1. when "start" and "end" are both absent, "start = now - 30 minutes" and "end = now", 
+namely past 30 minutes; 
+2. when "start" and "end" are both present, they are aligned to the same precision by 
+truncating the more precise one, e.g. if "start = 2019-01-01 1234, end = 2019-01-01 18", 
+then "start" is truncated (because it's more precise) to "2019-01-01 12", and "end = 2019-01-01 18"; 
+3. when "start" is absent and "end" is present, will determine the precision of "end" 
+and then use the precision to calculate "start" (minus 30 units), e.g. "end = 2019-11-09 1234", 
+the precision is "MINUTE",  so "start = end - 30 minutes = 2019-11-09 1204", 
+and if "end = 2019-11-09 12", the precision is "HOUR", so "start = end - 30HOUR = 2019-11-08 06"; 
+4. when "start" is present and "end" is absent, will determine the precision of "start" 
+and then use the precision to calculate "end" (plus 30 units), e.g. "start = 2019-11-09 1204", 
+the precision is "MINUTE", so "end = start + 30 minutes = 2019-11-09 1234", 
+and if "start = 2019-11-08 06", the precision is "HOUR", so "end = start + 30HOUR = 2019-11-09 12".`, "\n"), "")
+
 // DurationFlags are healthcheck flags that involves a duration, composed
 // by a start time, an end time, and a step, which is commonly used
 // in most of the commands
 var DurationFlags = []cli.Flag{
-	cli.StringFlag{
+	&cli.StringFlag{
 		Name:  "start",
-		Usage: "query start `TIME`",
+		Usage: startEndUsage,
 	},
-	cli.StringFlag{
+	&cli.StringFlag{
 		Name:  "end",
-		Usage: "query end `TIME`",
+		Usage: `end time of the query duration. Check the usage of "start"`,
 	},
-	cli.GenericFlag{
+	&cli.GenericFlag{
 		Name:   "step",
 		Hidden: true,
 		Value: &model.StepEnumValue{
@@ -46,8 +64,9 @@ var DurationFlags = []cli.Flag{
 			Selected: api.StepMinute,
 		},
 	},
-	cli.StringFlag{
-		Name:  "durationType",
-		Usage: "the type of duration",
+	&cli.StringFlag{
+		Name:   "duration-type",
+		Usage:  "the type of duration",
+		Hidden: true,
 	},
 }
diff --git a/internal/flags/endpoint.go b/internal/flags/endpoint.go
new file mode 100644
index 0000000..06b8367
--- /dev/null
+++ b/internal/flags/endpoint.go
@@ -0,0 +1,56 @@
+// 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 flags
+
+import (
+	"github.com/urfave/cli/v2"
+)
+
+// EndpointFlags take either endpoint id or endpoint name as input,
+// and transform to the other one.
+var EndpointFlags = append(
+	ServiceFlags, // endpoint level requires service level by default
+
+	&cli.StringFlag{
+		Name:     "endpoint-id",
+		Usage:    "`endpoint id`, if you don't have endpoint id, use `--endpoint-name` instead",
+		Required: false,
+	},
+	&cli.StringFlag{
+		Name:     "endpoint-name",
+		Usage:    "`endpoint name`, if you already have endpoint id, prefer to use `--endpoint-id`",
+		Required: false,
+	},
+)
+
+// EndpointRelationFlags take either destination endpoint id or destination endpoint name as input,
+// and transform to the other one.
+var EndpointRelationFlags = append(
+	EndpointFlags,
+
+	&cli.StringFlag{
+		Name:     "dest-endpoint-id",
+		Usage:    "`destination` service endpoint id, if you don't have service endpoint id, use `--dest-endpoint-name` instead",
+		Required: false,
+	},
+	&cli.StringFlag{
+		Name:     "dest-endpoint-name",
+		Usage:    "`destination` service endpoint name, if you already have endpoint id, prefer to use `--dest-endpoint-id`",
+		Required: false,
+	},
+)
diff --git a/internal/flags/flags.go b/internal/flags/flags.go
index ba41e27..c7d2067 100644
--- a/internal/flags/flags.go
+++ b/internal/flags/flags.go
@@ -17,7 +17,7 @@
 
 package flags
 
-import "github.com/urfave/cli"
+import "github.com/urfave/cli/v2"
 
 // Flags concatenates the `flags` into one []cli.Flag
 func Flags(flags ...[]cli.Flag) []cli.Flag {
diff --git a/internal/flags/instance.go b/internal/flags/instance.go
index 28cac45..0a5aa44 100644
--- a/internal/flags/instance.go
+++ b/internal/flags/instance.go
@@ -17,15 +17,38 @@
 
 package flags
 
-import "github.com/urfave/cli"
+import (
+	"github.com/urfave/cli/v2"
+)
 
-var InstanceServiceIDFlags = []cli.Flag{
-	cli.StringFlag{
-		Name:  "service-id",
-		Usage: "query service `ID` (priority over \"--service-name\")",
+// InstanceFlags take either service instance id or service instance name as input,
+// and transform to the other one.
+var InstanceFlags = []cli.Flag{
+	&cli.StringFlag{
+		Name:     "instance-id",
+		Usage:    "`instance id`, if you don't have instance id, use `--instance-name` instead",
+		Required: false,
 	},
-	cli.StringFlag{
-		Name:  "service-name",
-		Usage: "query service `Name`",
+	&cli.StringFlag{
+		Name:     "instance-name",
+		Usage:    "`instance name`, if you already have instance id, prefer to use `--instance-id`",
+		Required: false,
 	},
 }
+
+// InstanceRelationFlags take either destination instance id or destination instance name as input,
+// and transform to the other one.
+var InstanceRelationFlags = append(
+	InstanceFlags,
+
+	&cli.StringFlag{
+		Name:     "dest-instance-id",
+		Usage:    "`destination` instance id, if you don't have instance id, use `--dest-instance-name` instead",
+		Required: false,
+	},
+	&cli.StringFlag{
+		Name:     "dest-instance-name",
+		Usage:    "`destination` instance name, if you already have instance id, prefer to use `--dest-instance-id`",
+		Required: false,
+	},
+)
diff --git a/internal/flags/metrics.go b/internal/flags/metrics.go
index a160aea..e8bf22c 100644
--- a/internal/flags/metrics.go
+++ b/internal/flags/metrics.go
@@ -18,7 +18,7 @@
 package flags
 
 import (
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 
 	"github.com/apache/skywalking-cli/internal/model"
 
@@ -27,25 +27,14 @@ import (
 
 // MetricsFlags can be reused in metrics commands.
 var MetricsFlags = []cli.Flag{
-	cli.StringFlag{
+	&cli.StringFlag{
 		Name:     "name",
-		Usage:    "metrics `name`, which should be defined in OAL script",
+		Usage:    "`metrics` name, which should be defined in OAL files",
 		Required: true,
 	},
-	cli.StringFlag{
-		Name:     "service",
-		Usage:    "the name of the service",
-		Value:    "",
-		Required: false,
-	},
-	cli.BoolTFlag{
-		Name:     "isNormal",
-		Usage:    "set the service to normal or unnormal",
-		Required: false,
-	},
-	cli.GenericFlag{
+	&cli.GenericFlag{
 		Name:  "scope",
-		Usage: "the scope of the metrics entity",
+		Usage: "the `scope` of the metrics entity, see https://skywalking.apache.org/docs/main/latest/en/concepts-and-designs/scope-definitions/",
 		Value: &model.ScopeEnumValue{
 			Enum:     api.AllScope,
 			Default:  api.ScopeService,
diff --git a/internal/flags/search.go b/internal/flags/search.go
index ef48585..ac3ed0d 100644
--- a/internal/flags/search.go
+++ b/internal/flags/search.go
@@ -17,10 +17,10 @@
 
 package flags
 
-import "github.com/urfave/cli"
+import "github.com/urfave/cli/v2"
 
 var SearchRegexFlags = []cli.Flag{
-	cli.StringFlag{
+	&cli.StringFlag{
 		Name:     "regex",
 		Required: true,
 		Usage:    "search `Regex`",
diff --git a/internal/flags/entity.go b/internal/flags/service.go
similarity index 50%
rename from internal/flags/entity.go
rename to internal/flags/service.go
index eefc11c..f3a17d3 100644
--- a/internal/flags/entity.go
+++ b/internal/flags/service.go
@@ -18,44 +18,37 @@
 package flags
 
 import (
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 )
 
-// EntityFlags are attributes of Entity in the metrics v2 protocol.
-var EntityFlags = []cli.Flag{
-	cli.StringFlag{
-		Name:     "instance",
-		Usage:    "the name of the service instance",
-		Value:    "",
+// ServiceFlags take either service id or service name as input,
+// and transform to the other one.
+var ServiceFlags = []cli.Flag{
+	&cli.StringFlag{
+		Name:     "service-id",
+		Usage:    "`service id`, if you don't have service id, use `--service-name` instead",
 		Required: false,
 	},
-	cli.StringFlag{
-		Name:     "endpoint",
-		Usage:    "the name of the endpoint",
-		Value:    "",
+	&cli.StringFlag{
+		Name:     "service-name",
+		Usage:    "`service name`, if you already have service id, prefer to use `--service-id`",
 		Required: false,
 	},
-	cli.StringFlag{
-		Name:     "destService",
-		Usage:    "the name of the destination endpoint",
-		Value:    "",
-		Required: false,
-	},
-	cli.BoolTFlag{
-		Name:     "isDestNormal",
-		Usage:    "set the destination service to normal or unnormal",
-		Required: false,
-	},
-	cli.StringFlag{
-		Name:     "destInstance",
-		Usage:    "the name of the destination endpoint",
-		Value:    "",
+}
+
+// ServiceRelationFlags take either destination service id or destination service name as input,
+// and transform to the other one.
+var ServiceRelationFlags = append(
+	ServiceFlags,
+
+	&cli.StringFlag{
+		Name:     "dest-service-id",
+		Usage:    "`destination` service id, if you don't have service id, use `--dest-service-name` instead",
 		Required: false,
 	},
-	cli.StringFlag{
-		Name:     "destEndpoint",
-		Usage:    "the name of the destination endpoint",
-		Value:    "",
+	&cli.StringFlag{
+		Name:     "dest-service-name",
+		Usage:    "`destination` service name, if you already have service id, prefer to use `--dest-service-id`",
 		Required: false,
 	},
-}
+)
diff --git a/pkg/commands/event/report.go b/pkg/commands/event/report.go
index f1e3432..19ec6c6 100644
--- a/pkg/commands/event/report.go
+++ b/pkg/commands/event/report.go
@@ -22,11 +22,10 @@ import (
 	event "skywalking.apache.org/repo/goapi/collect/event/v3"
 
 	"github.com/apache/skywalking-cli/internal/commands/interceptor"
-	"github.com/apache/skywalking-cli/internal/logger"
 	"github.com/apache/skywalking-cli/internal/model"
 	"github.com/apache/skywalking-cli/pkg/grpc"
 
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 )
 
 func Report(ctx *cli.Context) (*common.Commands, error) {
@@ -38,21 +37,20 @@ func Report(ctx *cli.Context) (*common.Commands, error) {
 	e := event.Event{
 		Uuid: ctx.String("uuid"),
 		Source: &event.Source{
-			Service:         ctx.String("service"),
-			ServiceInstance: ctx.String("instance"),
-			Endpoint:        ctx.String("endpoint"),
+			Service:         ctx.String("service-name"),
+			ServiceInstance: ctx.String("instance-name"),
+			Endpoint:        ctx.String("endpoint-name"),
 		},
 		Name:       ctx.String("name"),
 		Type:       ctx.Generic("type").(*model.EventTypeEnumValue).Selected,
 		Message:    ctx.String("message"),
 		Parameters: parameters,
-		StartTime:  ctx.Int64("startTime"),
-		EndTime:    ctx.Int64("endTime"),
+		StartTime:  ctx.Int64("start-time"),
+		EndTime:    ctx.Int64("end-time"),
 	}
 
-	reply, err := grpc.ReportEvent(ctx.GlobalString("grpcAddr"), &e)
+	reply, err := grpc.ReportEvent(ctx.String("grpc-addr"), &e)
 	if err != nil {
-		logger.Log.Fatalln(err)
 		return nil, err
 	}
 
diff --git a/pkg/display/display.go b/pkg/display/display.go
index 455cfb9..2446923 100644
--- a/pkg/display/display.go
+++ b/pkg/display/display.go
@@ -26,7 +26,7 @@ import (
 
 	"github.com/apache/skywalking-cli/pkg/display/graph"
 
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 
 	"github.com/apache/skywalking-cli/pkg/display/json"
 	"github.com/apache/skywalking-cli/pkg/display/table"
@@ -48,17 +48,23 @@ var style = map[string]string{"dashboard global": "graph",
 	"metrics list":             "table",
 	"service list":             "table",
 	"t":                        "graph",
-	"trace":                    "graph"}
+	"trace":                    "graph",
+}
 
 // Display the object in the style specified in flag --display
 func Display(ctx *cli.Context, displayable *d.Displayable) error {
-	displayStyle := ctx.GlobalString("display")
+	displayStyle := ctx.String("display")
 	if displayStyle == "" {
 		commandFullName := ctx.Command.FullName()
 		if commandFullName != "" {
 			displayStyle = getDisplayStyle(commandFullName)
-		} else if ctx.Parent() != nil {
-			displayStyle = getDisplayStyle(ctx.Parent().Args()[0])
+		} else {
+			for _, c := range ctx.Lineage() {
+				if s := getDisplayStyle(c.Args().First()); s != "" {
+					displayStyle = s
+					break
+				}
+			}
 		}
 	}
 	if displayStyle == "" {
diff --git a/pkg/display/graph/dashboard/global.go b/pkg/display/graph/dashboard/global.go
index fd88887..97c1801 100644
--- a/pkg/display/graph/dashboard/global.go
+++ b/pkg/display/graph/dashboard/global.go
@@ -36,7 +36,7 @@ import (
 	"github.com/mum4k/termdash/linestyle"
 	"github.com/mum4k/termdash/terminal/termbox"
 	"github.com/mum4k/termdash/terminal/terminalapi"
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 
 	"github.com/apache/skywalking-cli/pkg/display/graph/gauge"
 	"github.com/apache/skywalking-cli/pkg/display/graph/heatmap"
@@ -289,7 +289,7 @@ func Display(ctx *cli.Context, data *dashboard.GlobalData) error {
 	}
 
 	refreshInterval := time.Duration(ctx.Int("refresh")) * time.Second
-	dt := utils.DurationType(ctx.String("durationType"))
+	dt := utils.DurationType(ctx.String("duration-type"))
 
 	// Only when users use the relative time, the duration will be adjusted to refresh.
 	if dt != utils.BothPresent {
diff --git a/pkg/display/graph/gauge/gauge.go b/pkg/display/graph/gauge/gauge.go
index 69a54e7..e0ac696 100644
--- a/pkg/display/graph/gauge/gauge.go
+++ b/pkg/display/graph/gauge/gauge.go
@@ -26,7 +26,7 @@ import (
 
 	api "skywalking.apache.org/repo/goapi/query"
 
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 
 	"github.com/apache/skywalking-cli/pkg/graphql/dashboard"
 	"github.com/apache/skywalking-cli/pkg/util"
diff --git a/pkg/display/graph/graph.go b/pkg/display/graph/graph.go
index 835a1e4..8334048 100644
--- a/pkg/display/graph/graph.go
+++ b/pkg/display/graph/graph.go
@@ -24,7 +24,7 @@ import (
 
 	api "skywalking.apache.org/repo/goapi/query"
 
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 
 	d "github.com/apache/skywalking-cli/pkg/display/displayable"
 	db "github.com/apache/skywalking-cli/pkg/display/graph/dashboard"
diff --git a/pkg/display/graph/linear/linear.go b/pkg/display/graph/linear/linear.go
index 37a4c7c..5dc443f 100644
--- a/pkg/display/graph/linear/linear.go
+++ b/pkg/display/graph/linear/linear.go
@@ -32,7 +32,7 @@ import (
 	"github.com/mum4k/termdash/terminal/terminalapi"
 	"github.com/mum4k/termdash/widgets/linechart"
 
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 )
 
 const RootID = "root"
diff --git a/pkg/display/graph/tree/list.go b/pkg/display/graph/tree/list.go
index e61bd4a..a5951b6 100644
--- a/pkg/display/graph/tree/list.go
+++ b/pkg/display/graph/tree/list.go
@@ -28,7 +28,7 @@ import (
 
 	ui "github.com/gizak/termui/v3"
 	"github.com/gizak/termui/v3/widgets"
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 
 	"github.com/apache/skywalking-cli/internal/logger"
 )
diff --git a/pkg/graphql/client/client.go b/pkg/graphql/client/client.go
index 0d71c8d..f265fbc 100644
--- a/pkg/graphql/client/client.go
+++ b/pkg/graphql/client/client.go
@@ -22,13 +22,13 @@ import (
 	"encoding/base64"
 
 	"github.com/machinebox/graphql"
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 
 	"github.com/apache/skywalking-cli/internal/logger"
 )
 
 func newClient(cliCtx *cli.Context) (client *graphql.Client) {
-	client = graphql.NewClient(cliCtx.GlobalString("base-url"))
+	client = graphql.NewClient(cliCtx.String("base-url"))
 	client.Log = func(msg string) {
 		logger.Log.Debugln(msg)
 	}
@@ -37,9 +37,9 @@ func newClient(cliCtx *cli.Context) (client *graphql.Client) {
 
 // ExecuteQuery executes the `request` and parse to the `response`, returning `error` if there is any.
 func ExecuteQuery(cliCtx *cli.Context, request *graphql.Request, response interface{}) error {
-	username := cliCtx.GlobalString("username")
-	password := cliCtx.GlobalString("password")
-	authorization := cliCtx.GlobalString("authorization")
+	username := cliCtx.String("username")
+	password := cliCtx.String("password")
+	authorization := cliCtx.String("authorization")
 	if authorization == "" && username != "" && password != "" {
 		authorization = "Basic " + base64.StdEncoding.EncodeToString([]byte(username+":"+password))
 	}
diff --git a/pkg/graphql/dashboard/global.go b/pkg/graphql/dashboard/global.go
index 00a7077..eb0b2fc 100644
--- a/pkg/graphql/dashboard/global.go
+++ b/pkg/graphql/dashboard/global.go
@@ -26,7 +26,7 @@ import (
 	api "skywalking.apache.org/repo/goapi/query"
 
 	"github.com/spf13/viper"
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 
 	"gopkg.in/yaml.v2"
 
diff --git a/pkg/graphql/dependency/dependency.go b/pkg/graphql/dependency/dependency.go
index 19f3d05..dd189ca 100644
--- a/pkg/graphql/dependency/dependency.go
+++ b/pkg/graphql/dependency/dependency.go
@@ -19,7 +19,7 @@ package dependency
 
 import (
 	"github.com/machinebox/graphql"
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 
 	api "skywalking.apache.org/repo/goapi/query"
 
diff --git a/pkg/graphql/event/event.go b/pkg/graphql/event/event.go
index e235218..d46b035 100644
--- a/pkg/graphql/event/event.go
+++ b/pkg/graphql/event/event.go
@@ -23,7 +23,7 @@ import (
 
 	"github.com/machinebox/graphql"
 
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 
 	api "skywalking.apache.org/repo/goapi/query"
 )
diff --git a/pkg/graphql/healthcheck/healthcheck.go b/pkg/graphql/healthcheck/healthcheck.go
index 2c97f43..a16b9e3 100644
--- a/pkg/graphql/healthcheck/healthcheck.go
+++ b/pkg/graphql/healthcheck/healthcheck.go
@@ -19,7 +19,7 @@ package healthcheck
 
 import (
 	"github.com/machinebox/graphql"
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 
 	api "skywalking.apache.org/repo/goapi/query"
 
diff --git a/pkg/graphql/log/log.go b/pkg/graphql/log/log.go
index bd30bba..153bafe 100644
--- a/pkg/graphql/log/log.go
+++ b/pkg/graphql/log/log.go
@@ -23,7 +23,7 @@ import (
 
 	"github.com/machinebox/graphql"
 
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 
 	api "skywalking.apache.org/repo/goapi/query"
 )
diff --git a/pkg/graphql/metadata/metadata.go b/pkg/graphql/metadata/metadata.go
index f4b7e3b..e1eced6 100644
--- a/pkg/graphql/metadata/metadata.go
+++ b/pkg/graphql/metadata/metadata.go
@@ -25,7 +25,7 @@ import (
 	"github.com/apache/skywalking-cli/assets"
 
 	"github.com/machinebox/graphql"
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 
 	"github.com/apache/skywalking-cli/pkg/graphql/client"
 )
diff --git a/pkg/graphql/metrics/metrics.go b/pkg/graphql/metrics/metrics.go
index 1a100bf..65cadcc 100644
--- a/pkg/graphql/metrics/metrics.go
+++ b/pkg/graphql/metrics/metrics.go
@@ -19,7 +19,7 @@ package metrics
 
 import (
 	"github.com/machinebox/graphql"
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 
 	"github.com/apache/skywalking-cli/assets"
 	"github.com/apache/skywalking-cli/pkg/graphql/client"
diff --git a/pkg/graphql/profile/profile.go b/pkg/graphql/profile/profile.go
index a086afd..9800666 100644
--- a/pkg/graphql/profile/profile.go
+++ b/pkg/graphql/profile/profile.go
@@ -23,7 +23,7 @@ import (
 
 	"github.com/machinebox/graphql"
 
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 
 	api "skywalking.apache.org/repo/goapi/query"
 )
diff --git a/pkg/graphql/trace/trace.go b/pkg/graphql/trace/trace.go
index 233b6df..6071846 100644
--- a/pkg/graphql/trace/trace.go
+++ b/pkg/graphql/trace/trace.go
@@ -19,7 +19,7 @@ package trace
 
 import (
 	"github.com/machinebox/graphql"
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 
 	api "skywalking.apache.org/repo/goapi/query"
 
diff --git a/pkg/util/commandNotFound.go b/pkg/util/commandNotFound.go
index b310cdb..a0a2b0a 100644
--- a/pkg/util/commandNotFound.go
+++ b/pkg/util/commandNotFound.go
@@ -20,7 +20,7 @@ package util
 import (
 	"fmt"
 
-	"github.com/urfave/cli"
+	"github.com/urfave/cli/v2"
 )
 
 const GAP = 3 // Control the appropriate edit distance.
@@ -29,10 +29,10 @@ const GAP = 3 // Control the appropriate edit distance.
 func CommandNotFound(c *cli.Context, s string) {
 	suppose := make([]string, 0)
 	var parentCommand string
-	if c.Parent() == nil {
+	if len(c.Lineage()) == 1 {
 		parentCommand = "swctl"
 	} else {
-		parentCommand = c.Parent().Args()[0]
+		parentCommand = c.Lineage()[1].Args().First()
 	}
 	fmt.Printf("Error: unknown command \"%s\" for \"%s\" \n\n", s, parentCommand)
 	// Record commands whose edit distance is less than GAP to suppose.
@@ -50,7 +50,7 @@ func CommandNotFound(c *cli.Context, s string) {
 		}
 		fmt.Println()
 	}
-	if c.Parent() == nil {
+	if len(c.Lineage()) == 1 {
 		fmt.Printf("Run '%s --help' for usage.\n", parentCommand)
 	} else {
 		fmt.Printf("Run 'swctl %s --help' for usage.\n", parentCommand)
diff --git a/pkg/util/template.go b/pkg/util/template.go
index 614a913..ddf459a 100644
--- a/pkg/util/template.go
+++ b/pkg/util/template.go
@@ -25,7 +25,7 @@ const TextFormat = `
 {{- $green	:="\x1b[0;32m" -}}	{{- $Green	:="\x1b[1;32m" -}}
 {{- $yellow	:="\x1b[0;33m" -}}	{{- $Yellow	:="\x1b[1;33m" -}}
 {{- $blue	:="\x1b[0;34m" -}}	{{- $Blue	:="\x1b[1;34m" -}}
-{{- $pruple	:="\x1b[0;35m" -}}	{{- $Pruple	:="\x1b[1;35m" -}}
+{{- $purple	:="\x1b[0;35m" -}}	{{- $purple	:="\x1b[1;35m" -}}
 {{- $cyan	:="\x1b[0;36m" -}}	{{- $Cyan	:="\x1b[1;36m" -}}
 {{- $white	:="\x1b[0;37m" -}}	{{- $White	:="\x1b[1;37m" -}}
 {{- $plain	:="\x1b[0m" -}}
@@ -37,8 +37,8 @@ NAME:
 
 USAGE:
 	{{$green}}{{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}}
-	{{- if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}}
-	{{- if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{$Yellow}}{{if .Version}}{{if not .HideVersion}}
+	{{- if .VisibleFlags}} [global options]{{end}}{{if .Commands}} command [command options]{{end}}
+	{{- if .ArgsUsage}} {{.ArgsUsage}}{{else}} [arguments...]{{end}}{{end}}{{$Yellow}}{{if .Version}}{{if not .HideVersion}}
 
 VERSION:
 	{{$yellow}}{{.Version}}{{end}}{{end}}{{$Yellow}}{{if .Description}}
@@ -66,11 +66,11 @@ COPYRIGHT:
 
 const CommandHelpTemplate = TextFormat + `{{$Green -}}
 NAME:
-	{{$green}}{{.HelpName}} - {{.Usage}}{{$Green}}
+	{{$green}}{{.HelpName}}{{if .VisibleFlags}} [command options]{{end}}{{- if .ArgsUsage}} {{.ArgsUsage}}{{else}}{{end}} - {{.Usage}}{{$Green}}
 
 USAGE:
-	{{$green}}{{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}}{{if .VisibleFlags}} [command options]{{end}} 
-	{{- if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{$Green}}{{if .Category}}
+	{{$green}}{{if .UsageText}}{{.UsageText | nindent 2 | trim}}{{else}}{{.HelpName}}{{if .VisibleFlags}} [command options]{{end}} 
+	{{- if .ArgsUsage}} {{.ArgsUsage}}{{end}}{{end}}{{$Green}}{{if .Category}}
 
 CATEGORY:
 	{{$green}}{{.Category}}{{end}}{{$Blue}}{{if .Description}}
@@ -85,19 +85,19 @@ OPTIONS:
 
 const SubcommandHelpTemplate = TextFormat + `{{$Green -}}
 NAME:
-   {{$green}}{{.HelpName}} - {{if .Description}}{{.Description}}{{else}}{{.Usage}}{{end}}{{$Green}}
+	{{$green}}{{.HelpName}} - {{if .Description}}{{.Description}}{{else}}{{.Usage}}{{end}}{{$Green}}
 
 USAGE:
-   {{$green}}{{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} command{{if .VisibleFlags}} [command options]{{end}}
-   {{- if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{$Blue}}
+	{{$green}}{{if .UsageText}}{{.UsageText | nindent 2 | trim}}{{else}}{{.HelpName}} command{{if .VisibleFlags}} [command options]{{end}}
+	{{- if .ArgsUsage}} {{.ArgsUsage}}{{else}} [arguments...]{{end}}{{end}}{{$Blue}}
 
 COMMANDS:{{range .VisibleCategories}}{{if .Name}}
 
-   {{.Name}}:{{range .VisibleCommands}}
-   {{$Blue}}{{join .Names ", "}}{{$blue}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{range .VisibleCommands}}
-   {{$Blue}}{{join .Names ", "}}{{$blue}}{{"\t"}}{{.Usage}}{{end}}{{end}}{{end}}{{if .VisibleFlags}}{{$Cyan}}
+	{{.Name}}:{{range .VisibleCommands}}
+	{{$Blue}}{{join .Names ", "}}{{$blue}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{range .VisibleCommands}}
+	{{$Blue}}{{join .Names ", "}}{{$blue}}{{"\t"}}{{.Usage}}{{end}}{{end}}{{end}}{{if .VisibleFlags}}{{$Cyan}}
 
 OPTIONS:
-   {{$cyan}}{{range .VisibleFlags}}{{.}}
-   {{end}}{{end}}{{$plain}}
+	{{$cyan}}{{range .VisibleFlags}}{{.}}
+	{{end}}{{end}}{{$plain}}
 `
diff --git a/scripts/test_commands.sh b/scripts/test_commands.sh
deleted file mode 100755
index f757d90..0000000
--- a/scripts/test_commands.sh
+++ /dev/null
@@ -1,75 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-set -ex
-
-if [ "$(uname)" == "Darwin" ]; then
-  os="darwin"
-else
-  os="linux"
-fi
-
-swctl="bin/swctl-${VERSION}-${os}-amd64 --base-url=http://localhost:12800/graphql"
-
-retries=1
-max_retries=10
-# Check whether OAP server is healthy.
-while ! ${swctl} ch > /dev/null 2>&1; do
-  if [[ $retries -ge $max_retries ]]; then
-    echo "OAP server is not healthy after $retries retires, will exit now"
-    exit 1
-  fi
-  echo "OAP server is not healthy, retrying [$retries/$max_retries] ..."
-  sleep 3
-  retries=$(($retries+1))
-done;
-
-${swctl} --display=json metrics ls > /dev/null 2>&1
-
-${swctl} --display=json service ls > /dev/null 2>&1
-
-${swctl} --display=json endpoint ls --service-id="test" > /dev/null 2>&1
-
-SERVICE_SCOPE_METRICS=(
-  service_resp_time
-  service_sla
-  service_cpm
-  service_apdex
-)
-
-for metrics in "${SERVICE_SCOPE_METRICS[@]}"; do
-  ${swctl} --display=json metrics linear --name="$metrics" --service="test" > /dev/null 2>&1
-
-  ${swctl} --display=json metrics single --name="$metrics" --service="test" > /dev/null 2>&1
-
-  ${swctl} --display=json metrics top 3 --name="$metrics" > /dev/null 2>&1
-done
-
-${swctl} --display=json metrics multiple-linear --name="all_percentile" > /dev/null 2>&1
-
-# Test `metrics thermodynamic`
-${swctl} --display=json metrics hp --name="all_heatmap" >/dev/null 2>&1
-
-${swctl} --display=json trace ls >/dev/null 2>&1
-
-# Test `dashboard global`
-${swctl} --display=json db g >/dev/null 2>&1
-
-# Test `dependency`
-${swctl} --display=json dependency service "test" > /dev/null 2>&1
-
-${swctl} --display=json dependency endpoint "test" > /dev/null 2>&1
-
-${swctl} --display=json dependency instance "test" "test" > /dev/null 2>&1
diff --git a/test/docker-compose.yml b/test/docker-compose.yml
new file mode 100644
index 0000000..0db3d4b
--- /dev/null
+++ b/test/docker-compose.yml
@@ -0,0 +1,74 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+version: '2.1'
+
+services:
+  oap:
+    image: apache/skywalking-oap-server:8.8.1
+    ports:
+      - 11800
+      - 12800
+    networks:
+      - test
+    environment:
+      - SW_STORAGE=h2
+      - SW_HEALTH_CHECKER=default
+      - SW_TELEMETRY=prometheus
+    healthcheck:
+      test: [ "CMD", "sh", "-c", "nc -zn 127.0.0.1 11800" ]
+      interval: 5s
+      timeout: 60s
+      retries: 120
+
+  provider:
+    image: apache/skywalking-python:0.7.0-grpc-py3.9
+    environment:
+      - SW_AGENT_COLLECTOR_BACKEND_SERVICES=oap:11800
+      - SW_AGENT_NAME=provider
+      - SW_AGENT_INSTANCE=provider1
+    volumes:
+      - ./services/provider.py:/app.py
+    entrypoint: [ "sw-python", "run", "python", "/app.py" ]
+    depends_on:
+      oap:
+        condition: service_healthy
+    networks:
+      - test
+    healthcheck:
+      test: [ "CMD", "bash", "-c", "cat < /dev/null > /dev/tcp/127.0.0.1/9091" ]
+      interval: 5s
+      timeout: 60s
+      retries: 120
+
+  consumer:
+    image: apache/skywalking-python:0.7.0-grpc-py3.9
+    ports:
+      - 9090
+    environment:
+      - SW_AGENT_COLLECTOR_BACKEND_SERVICES=oap:11800
+      - SW_AGENT_NAME=consumer
+      - SW_AGENT_INSTANCE=consumer1
+    volumes:
+      - ./services/consumer.py:/app.py
+    entrypoint: [ "sw-python", "run", "python", "/app.py" ]
+    depends_on:
+      provider:
+        condition: service_healthy
+    networks:
+      - test
+
+networks:
+  test:
diff --git a/.asf.yaml b/test/expected/dashboard-global-metrics.yml
similarity index 64%
copy from .asf.yaml
copy to test/expected/dashboard-global-metrics.yml
index 102dba2..f49ef51 100644
--- a/.asf.yaml
+++ b/test/expected/dashboard-global-metrics.yml
@@ -1,4 +1,3 @@
-#
 # Licensed to the Apache Software Foundation (ASF) under one or more
 # contributor license agreements.  See the NOTICE file distributed with
 # this work for additional information regarding copyright ownership.
@@ -13,18 +12,26 @@
 # 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.
-#
 
-github:
-  description: Apache SkyWalking CLI
-  homepage: https://skywalking.apache.org/
-  labels:
-    - skywalking
-    - observability
-    - apm
-    - distributed-tracing
-    - cli
-  enabled_merge_buttons:
-    squash:  true
-    merge:   false
-    rebase:  false
+  { { - contains . } }
+- { { - contains . } }
+  - name: consumer
+    id: ""
+    value: '{{ gt .value "0" }}'
+    refid: ~
+  - name: provider
+    id: ""
+    value: '{{ gt .value "0" }}'
+    refid: ~
+  { { - end } }
+- { { - contains . } }
+  - name: consumer - /users
+    id: ""
+    value: '{{ gt .value "0" }}'
+    refid: ~
+  - name: provider - /users
+    id: ""
+    value: '{{ gt .value "0" }}'
+    refid: ~
+  { { - end } }
+  { { - end } }
diff --git a/.asf.yaml b/test/expected/dashboard-global.yml
similarity index 50%
copy from .asf.yaml
copy to test/expected/dashboard-global.yml
index 102dba2..b27ba96 100644
--- a/.asf.yaml
+++ b/test/expected/dashboard-global.yml
@@ -1,4 +1,3 @@
-#
 # Licensed to the Apache Software Foundation (ASF) under one or more
 # contributor license agreements.  See the NOTICE file distributed with
 # this work for additional information regarding copyright ownership.
@@ -13,18 +12,40 @@
 # 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.
-#
 
-github:
-  description: Apache SkyWalking CLI
-  homepage: https://skywalking.apache.org/
-  labels:
-    - skywalking
-    - observability
-    - apm
-    - distributed-tracing
-    - cli
-  enabled_merge_buttons:
-    squash:  true
-    merge:   false
-    rebase:  false
+metrics:
+  { { - contains .metrics } }
+- { { - contains . } }
+  - name: consumer
+    id: "{{ .id }}"
+    value: '{{ gt .value "0" }}'
+    refid: ~
+  - name: provider
+    id: "{{ .id }}"
+    value: '{{ gt .value "0" }}'
+    refid: ~
+  { { - end } }
+  { { - end } }
+
+responselatency:
+  { { - range .responselatency } }
+  - { { - range $k, $v := . } }
+    { { $k } }: { { $v } }
+    { { - end } }
+  { { - end } }
+
+heatmap:
+  values:
+    { { - contains .heatmap.values } }
+    - id: { { notEmpty .id } }
+      values:
+        { { - contains .values } }
+        - { { gt . 0 } }
+        { { - end } }
+    { { - end } }
+  buckets:
+    { { - range .heatmap.buckets } }
+    - { { - range $k, $v := . } }
+      "{{ $k }}": "{{ $v }}"
+      { { - end } }
+    { { - end } }
diff --git a/.asf.yaml b/test/expected/dependency-endpoint.yml
similarity index 51%
copy from .asf.yaml
copy to test/expected/dependency-endpoint.yml
index 102dba2..8dd79bb 100644
--- a/.asf.yaml
+++ b/test/expected/dependency-endpoint.yml
@@ -1,4 +1,3 @@
-#
 # Licensed to the Apache Software Foundation (ASF) under one or more
 # contributor license agreements.  See the NOTICE file distributed with
 # this work for additional information regarding copyright ownership.
@@ -13,18 +12,29 @@
 # 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.
-#
 
-github:
-  description: Apache SkyWalking CLI
-  homepage: https://skywalking.apache.org/
-  labels:
-    - skywalking
-    - observability
-    - apm
-    - distributed-tracing
-    - cli
-  enabled_merge_buttons:
-    squash:  true
-    merge:   false
-    rebase:  false
+nodes:
+  { { - contains .nodes } }
+- id: { { b64enc "provider" } }.1_{{ b64enc "/users" }}
+  name: /users
+  type: ""
+  isreal: true
+  serviceid: { { b64enc "provider" } }.1
+  servicename: provider
+- id: { { b64enc "consumer" } }.1_{{ b64enc "/users" }}
+  name: /users
+  type: ""
+  isreal: true
+  serviceid: { { b64enc "consumer" } }.1
+  servicename: consumer
+  { { - end } }
+calls:
+  { { - contains .calls } }
+- source: { { b64enc "consumer" } }.1_{{ b64enc "/users" }}
+  sourcecomponents: [ ]
+  target: { { b64enc "provider" } }.1_{{ b64enc "/users" }}
+  targetcomponents: [ ]
+  id: { { b64enc "consumer" } }.1-{{ b64enc "/users" }}-{{ b64enc "provider" }}.1-{{ b64enc "/users" }}
+  detectpoints:
+    - SERVER
+  { { - end } }
diff --git a/test/expected/dependency-instance.yml b/test/expected/dependency-instance.yml
new file mode 100644
index 0000000..5bc3aba
--- /dev/null
+++ b/test/expected/dependency-instance.yml
@@ -0,0 +1,43 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+nodes:
+  { { - contains .nodes } }
+- id: { { b64enc "provider" } }.1_{{ b64enc "provider1" }}
+  name: provider1
+  type: Python
+  isreal: true
+  serviceid: { { b64enc "provider" } }.1
+  servicename: provider
+- id: { { b64enc "consumer" } }.1_{{ b64enc "consumer1" }}
+  name: consumer1
+  type: ""
+  isreal: true
+  serviceid: { { b64enc "consumer" } }.1
+  servicename: consumer
+  { { - end } }
+calls:
+  { { - contains .calls } }
+- source: { { b64enc "consumer" } }.1_{{ b64enc "consumer1" }}
+  sourcecomponents: [ ]
+  target: { { b64enc "provider" } }.1_{{ b64enc "provider1" }}
+  targetcomponents: [ ]
+  id: { { b64enc "consumer" } }.1_{{ b64enc "consumer1" }}-{{ b64enc "provider" }}.1_{{ b64enc "provider1" }}
+  detectpoints:
+    {{- contains .detectpoints }}
+    - SERVER
+    - CLIENT
+    {{- end }}
+  { { - end } }
diff --git a/.asf.yaml b/test/expected/dependency-service.yml
similarity index 61%
copy from .asf.yaml
copy to test/expected/dependency-service.yml
index 102dba2..b0dd0cd 100644
--- a/.asf.yaml
+++ b/test/expected/dependency-service.yml
@@ -1,4 +1,3 @@
-#
 # Licensed to the Apache Software Foundation (ASF) under one or more
 # contributor license agreements.  See the NOTICE file distributed with
 # this work for additional information regarding copyright ownership.
@@ -13,18 +12,26 @@
 # 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.
-#
 
-github:
-  description: Apache SkyWalking CLI
-  homepage: https://skywalking.apache.org/
-  labels:
-    - skywalking
-    - observability
-    - apm
-    - distributed-tracing
-    - cli
-  enabled_merge_buttons:
-    squash:  true
-    merge:   false
-    rebase:  false
+nodes:
+  { { - contains .nodes } }
+- id: { { b64enc "provider" } }.1
+  name: provider
+  type: Python
+  isreal: true
+- id: { { b64enc "consumer" } }.1
+  name: consumer
+  type: Python
+  isreal: true
+  { { - end } }
+calls:
+  { { - contains .calls } }
+- source: { { b64enc "consumer" } }.1
+  sourcecomponents: [ ]
+  target: { { b64enc "provider" } }.1
+  targetcomponents: [ ]
+  id: { { b64enc "consumer" } }.1-{{ b64enc "provider"}}.1
+  detectpoints:
+    - CLIENT
+    - SERVER
+  { { - end } }
diff --git a/.asf.yaml b/test/expected/empty-array.yml
similarity index 74%
copy from .asf.yaml
copy to test/expected/empty-array.yml
index 102dba2..8d30b98 100644
--- a/.asf.yaml
+++ b/test/expected/empty-array.yml
@@ -1,4 +1,3 @@
-#
 # Licensed to the Apache Software Foundation (ASF) under one or more
 # contributor license agreements.  See the NOTICE file distributed with
 # this work for additional information regarding copyright ownership.
@@ -13,18 +12,5 @@
 # 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.
-#
 
-github:
-  description: Apache SkyWalking CLI
-  homepage: https://skywalking.apache.org/
-  labels:
-    - skywalking
-    - observability
-    - apm
-    - distributed-tracing
-    - cli
-  enabled_merge_buttons:
-    squash:  true
-    merge:   false
-    rebase:  false
+[ ]
diff --git a/.asf.yaml b/test/expected/endpoint-list.yml
similarity index 74%
copy from .asf.yaml
copy to test/expected/endpoint-list.yml
index 102dba2..26f23f3 100644
--- a/.asf.yaml
+++ b/test/expected/endpoint-list.yml
@@ -1,4 +1,3 @@
-#
 # Licensed to the Apache Software Foundation (ASF) under one or more
 # contributor license agreements.  See the NOTICE file distributed with
 # this work for additional information regarding copyright ownership.
@@ -13,18 +12,6 @@
 # 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.
-#
 
-github:
-  description: Apache SkyWalking CLI
-  homepage: https://skywalking.apache.org/
-  labels:
-    - skywalking
-    - observability
-    - apm
-    - distributed-tracing
-    - cli
-  enabled_merge_buttons:
-    squash:  true
-    merge:   false
-    rebase:  false
+- id: { { b64enc "provider" } }.1_{{ b64enc "/users" }}
+  name: /users
diff --git a/.asf.yaml b/test/expected/instance-list.yml
similarity index 69%
copy from .asf.yaml
copy to test/expected/instance-list.yml
index 102dba2..dc1c12a 100644
--- a/.asf.yaml
+++ b/test/expected/instance-list.yml
@@ -1,4 +1,3 @@
-#
 # Licensed to the Apache Software Foundation (ASF) under one or more
 # contributor license agreements.  See the NOTICE file distributed with
 # this work for additional information regarding copyright ownership.
@@ -13,18 +12,15 @@
 # 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.
-#
 
-github:
-  description: Apache SkyWalking CLI
-  homepage: https://skywalking.apache.org/
-  labels:
-    - skywalking
-    - observability
-    - apm
-    - distributed-tracing
-    - cli
-  enabled_merge_buttons:
-    squash:  true
-    merge:   false
-    rebase:  false
+  { { - with index . 0 } }
+- id: { { b64enc "provider" } }.1_{{ b64enc "provider1" }}
+  name: provider1
+  attributes:
+    { { - range .attributes } }
+    - name: "{{ .name }}"
+      value: "{{ .value }}"
+    { { - end } }
+  language: { { .language } }
+  instanceuuid: { { b64enc "provider" } }.1_{{ b64enc "provider1" }}
+  { { - end } }
diff --git a/.asf.yaml b/test/expected/metrics-has-value.yml
similarity index 74%
copy from .asf.yaml
copy to test/expected/metrics-has-value.yml
index 102dba2..f90a3a3 100644
--- a/.asf.yaml
+++ b/test/expected/metrics-has-value.yml
@@ -1,4 +1,3 @@
-#
 # Licensed to the Apache Software Foundation (ASF) under one or more
 # contributor license agreements.  See the NOTICE file distributed with
 # this work for additional information regarding copyright ownership.
@@ -13,18 +12,8 @@
 # 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.
-#
 
-github:
-  description: Apache SkyWalking CLI
-  homepage: https://skywalking.apache.org/
-  labels:
-    - skywalking
-    - observability
-    - apm
-    - distributed-tracing
-    - cli
-  enabled_merge_buttons:
-    squash:  true
-    merge:   false
-    rebase:  false
+  { { - contains . } }
+- key: { { notEmpty .key } }
+  value: { { ge .value 1 } }
+  { { - end } }
diff --git a/.asf.yaml b/test/expected/metrics-top-endpoint-sla-provider.yml
similarity index 74%
copy from .asf.yaml
copy to test/expected/metrics-top-endpoint-sla-provider.yml
index 102dba2..b428d33 100644
--- a/.asf.yaml
+++ b/test/expected/metrics-top-endpoint-sla-provider.yml
@@ -1,4 +1,3 @@
-#
 # Licensed to the Apache Software Foundation (ASF) under one or more
 # contributor license agreements.  See the NOTICE file distributed with
 # this work for additional information regarding copyright ownership.
@@ -13,18 +12,8 @@
 # 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.
-#
 
-github:
-  description: Apache SkyWalking CLI
-  homepage: https://skywalking.apache.org/
-  labels:
-    - skywalking
-    - observability
-    - apm
-    - distributed-tracing
-    - cli
-  enabled_merge_buttons:
-    squash:  true
-    merge:   false
-    rebase:  false
+- name: /users
+  id: ""
+  value: '{{- gt (index . 0).value "0" }}'
+  refid: ~
diff --git a/.asf.yaml b/test/expected/metrics-top-service-sla.yml
similarity index 74%
copy from .asf.yaml
copy to test/expected/metrics-top-service-sla.yml
index 102dba2..d047b59 100644
--- a/.asf.yaml
+++ b/test/expected/metrics-top-service-sla.yml
@@ -1,4 +1,3 @@
-#
 # Licensed to the Apache Software Foundation (ASF) under one or more
 # contributor license agreements.  See the NOTICE file distributed with
 # this work for additional information regarding copyright ownership.
@@ -13,18 +12,14 @@
 # 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.
-#
 
-github:
-  description: Apache SkyWalking CLI
-  homepage: https://skywalking.apache.org/
-  labels:
-    - skywalking
-    - observability
-    - apm
-    - distributed-tracing
-    - cli
-  enabled_merge_buttons:
-    squash:  true
-    merge:   false
-    rebase:  false
+{ { - contains . } }
+- name: consumer
+  id: ""
+  value: '{{- gt .value "0" }}'
+  refid: ~
+- name: provider
+  id: ""
+  value: '{{- gt .value "0" }}'
+  refid: ~
+  { { - end } }
diff --git a/.asf.yaml b/test/expected/service-endpoint.yml
similarity index 74%
copy from .asf.yaml
copy to test/expected/service-endpoint.yml
index 102dba2..56683e5 100644
--- a/.asf.yaml
+++ b/test/expected/service-endpoint.yml
@@ -1,4 +1,3 @@
-#
 # Licensed to the Apache Software Foundation (ASF) under one or more
 # contributor license agreements.  See the NOTICE file distributed with
 # this work for additional information regarding copyright ownership.
@@ -13,18 +12,8 @@
 # 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.
-#
 
-github:
-  description: Apache SkyWalking CLI
-  homepage: https://skywalking.apache.org/
-  labels:
-    - skywalking
-    - observability
-    - apm
-    - distributed-tracing
-    - cli
-  enabled_merge_buttons:
-    squash:  true
-    merge:   false
-    rebase:  false
+  { { - contains . } }
+- id: { { b64enc "e2e-service-provider" } }.1_{{ b64enc "POST:/users" }}
+  name: POST:/users
+  { { - end } }
diff --git a/.asf.yaml b/test/expected/service-provider.yml
similarity index 74%
copy from .asf.yaml
copy to test/expected/service-provider.yml
index 102dba2..47cd7cd 100644
--- a/.asf.yaml
+++ b/test/expected/service-provider.yml
@@ -1,4 +1,3 @@
-#
 # Licensed to the Apache Software Foundation (ASF) under one or more
 # contributor license agreements.  See the NOTICE file distributed with
 # this work for additional information regarding copyright ownership.
@@ -13,18 +12,7 @@
 # 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.
-#
 
-github:
-  description: Apache SkyWalking CLI
-  homepage: https://skywalking.apache.org/
-  labels:
-    - skywalking
-    - observability
-    - apm
-    - distributed-tracing
-    - cli
-  enabled_merge_buttons:
-    squash:  true
-    merge:   false
-    rebase:  false
+- id: { { b64enc "provider" } }.1
+  name: provider
+  group: ""
diff --git a/.asf.yaml b/test/expected/service.yml
similarity index 74%
copy from .asf.yaml
copy to test/expected/service.yml
index 102dba2..33b9304 100644
--- a/.asf.yaml
+++ b/test/expected/service.yml
@@ -1,4 +1,3 @@
-#
 # Licensed to the Apache Software Foundation (ASF) under one or more
 # contributor license agreements.  See the NOTICE file distributed with
 # this work for additional information regarding copyright ownership.
@@ -13,18 +12,12 @@
 # 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.
-#
 
-github:
-  description: Apache SkyWalking CLI
-  homepage: https://skywalking.apache.org/
-  labels:
-    - skywalking
-    - observability
-    - apm
-    - distributed-tracing
-    - cli
-  enabled_merge_buttons:
-    squash:  true
-    merge:   false
-    rebase:  false
+  { { - contains . } }
+- id: { { b64enc "provider" } }.1
+  name: provider
+  group: ""
+- id: { { b64enc "consumer" } }.1
+  name: consumer
+  group: ""
+  { { - end } }
diff --git a/test/expected/trace-users-detail.yml b/test/expected/trace-users-detail.yml
new file mode 100644
index 0000000..21f18b8
--- /dev/null
+++ b/test/expected/trace-users-detail.yml
@@ -0,0 +1,99 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+spans:
+  { { - contains .spans } }
+  - traceid: { { .traceid } }
+    segmentid: { { .segmentid } }
+    spanid: { { .spanid } }
+    parentspanid: { { .parentspanid } }
+    refs: [ ]
+    servicecode: consumer
+    serviceinstancename: consumer1
+    starttime: { { gt .starttime 0 } }
+    endtime: { { gt .endtime 0 } }
+    endpointname: /users
+    type: Entry
+    peer: { { .peer } }
+    component: Python
+    iserror: false
+    layer: Http
+    tags:
+      { { - contains .tags } }
+      - key: http.method
+        value: POST
+      - key: http.url
+        value: { { notEmpty .value } }
+      - key: http.status.code
+        value: 200
+      { { - end } }
+    logs: [ ]
+  - traceid: { { notEmpty .traceid } }
+    segmentid: { { .segmentid } }
+    spanid: { { .spanid } }
+    parentspanid: { { .parentspanid } }
+    refs: [ ]
+    servicecode: consumer
+    serviceinstancename: consumer1
+    starttime: { { gt .starttime 0 } }
+    endtime: { { gt .endtime 0 } }
+    endpointname: /users
+    type: Exit
+    peer: { { .peer } }
+    component: Python
+    iserror: false
+    layer: Http
+    tags:
+      { { - contains .tags } }
+      - key: http.method
+        value: POST
+      - key: http.url
+        value: { { notEmpty .value } }
+      - key: http.status.code
+        value: 200
+      { { - end } }
+    logs: [ ]
+  - traceid: { { notEmpty .traceid } }
+    segmentid: { { .segmentid } }
+    spanid: { { .spanid } }
+    parentspanid: { { .parentspanid } }
+    refs:
+      { { - contains .refs } }
+      - traceid: { { notEmpty .traceid } }
+        parentsegmentid: { { .parentsegmentid } }
+        parentspanid: 1
+        type: CROSS_PROCESS
+      { { - end } }
+    servicecode: provider
+    serviceinstancename: provider1
+    starttime: { { gt .starttime 0 } }
+    endtime: { { gt .endtime 0 } }
+    endpointname: /users
+    type: Entry
+    peer: { { .peer } }
+    component: Python
+    iserror: false
+    layer: Http
+    tags:
+      { { - contains .tags } }
+      - key: http.method
+        value: POST
+      - key: http.url
+        value: { { notEmpty .value } }
+      - key: http.status.code
+        value: 200
+      { { - end } }
+    logs: [ ]
+  { { - end } }
diff --git a/.asf.yaml b/test/expected/traces-list.yml
similarity index 73%
copy from .asf.yaml
copy to test/expected/traces-list.yml
index 102dba2..215914e 100644
--- a/.asf.yaml
+++ b/test/expected/traces-list.yml
@@ -1,4 +1,3 @@
-#
 # Licensed to the Apache Software Foundation (ASF) under one or more
 # contributor license agreements.  See the NOTICE file distributed with
 # this work for additional information regarding copyright ownership.
@@ -13,18 +12,16 @@
 # 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.
-#
 
-github:
-  description: Apache SkyWalking CLI
-  homepage: https://skywalking.apache.org/
-  labels:
-    - skywalking
-    - observability
-    - apm
-    - distributed-tracing
-    - cli
-  enabled_merge_buttons:
-    squash:  true
-    merge:   false
-    rebase:  false
+traces:
+  { { - contains .traces } }
+- segmentid: { { notEmpty .segmentid } }
+  endpointnames:
+    - /users
+  duration: { { ge .duration 0 } }
+  start: "{{ notEmpty .start}}"
+  iserror: false
+  traceids:
+    - { { index .traceids 0 } }
+  { { - end } }
+total: { { gt .total 0 } }
diff --git a/.asf.yaml b/test/expected/value.yml
similarity index 74%
copy from .asf.yaml
copy to test/expected/value.yml
index 102dba2..4973e00 100644
--- a/.asf.yaml
+++ b/test/expected/value.yml
@@ -1,4 +1,3 @@
-#
 # Licensed to the Apache Software Foundation (ASF) under one or more
 # contributor license agreements.  See the NOTICE file distributed with
 # this work for additional information regarding copyright ownership.
@@ -13,18 +12,5 @@
 # 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.
-#
 
-github:
-  description: Apache SkyWalking CLI
-  homepage: https://skywalking.apache.org/
-  labels:
-    - skywalking
-    - observability
-    - apm
-    - distributed-tracing
-    - cli
-  enabled_merge_buttons:
-    squash:  true
-    merge:   false
-    rebase:  false
+{ { gt . 0 } }
diff --git a/test/services/consumer.py b/test/services/consumer.py
new file mode 100644
index 0000000..a496818
--- /dev/null
+++ b/test/services/consumer.py
@@ -0,0 +1,42 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+from urllib import request
+
+if __name__ == '__main__':
+    import socketserver
+    from http.server import BaseHTTPRequestHandler
+
+    class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):
+        def do_POST(self):
+            self.send_response(200)
+            self.send_header('Content-Type', 'application/json; charset=utf-8')
+            self.end_headers()
+
+            data = '{"name": "whatever"}'.encode('utf8')
+            req = request.Request('http://provider:9091/users')
+            req.add_header('Content-Type', 'application/json; charset=utf-8')
+            req.add_header('Content-Length', str(len(data)))
+            with request.urlopen(req, data):
+                self.wfile.write(data)
+
+    PORT = 9090
+    Handler = SimpleHTTPRequestHandler
+
+    with socketserver.TCPServer(("", PORT), Handler) as httpd:
+        print("serving at port", PORT)
+        httpd.serve_forever()
diff --git a/.asf.yaml b/test/services/provider.py
similarity index 56%
copy from .asf.yaml
copy to test/services/provider.py
index 102dba2..ece6db3 100644
--- a/.asf.yaml
+++ b/test/services/provider.py
@@ -15,16 +15,23 @@
 # limitations under the License.
 #
 
-github:
-  description: Apache SkyWalking CLI
-  homepage: https://skywalking.apache.org/
-  labels:
-    - skywalking
-    - observability
-    - apm
-    - distributed-tracing
-    - cli
-  enabled_merge_buttons:
-    squash:  true
-    merge:   false
-    rebase:  false
+import time
+
+if __name__ == '__main__':
+    import socketserver
+    from http.server import BaseHTTPRequestHandler
+
+    class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):
+
+        def do_POST(self):
+            time.sleep(0.5)
+            self.send_response(200)
+            self.send_header('Content-Type', 'application/json')
+            self.end_headers()
+            self.wfile.write('{"song": "Despacito", "artist": "Luis Fonsi"}'.encode('ascii'))
+
+    PORT = 9091
+    Handler = SimpleHTTPRequestHandler
+
+    with socketserver.TCPServer(("", PORT), Handler) as httpd:
+        httpd.serve_forever()
diff --git a/test/test.yaml b/test/test.yaml
new file mode 100644
index 0000000..0861490
--- /dev/null
+++ b/test/test.yaml
@@ -0,0 +1,95 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This file is used to show how to write configuration files and can be used to test.
+
+setup:
+  env: compose
+  file: docker-compose.yml
+  timeout: 1200
+  steps:
+    - name: install yq
+      command: yq > /dev/null 2>&1 || go install github.com/mikefarah/yq/v4@latest
+    - name: install swctl
+      command: make install DESTDIR=/usr/local/bin > /dev/null 2>&1
+
+trigger:
+  action: http
+  interval: 3s
+  times: 10
+  url: http://${consumer_host}:${consumer_9090}/users
+  method: POST
+
+verify:
+  retry:
+    count: 200
+    interval: 5s
+  cases:
+    - query: swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql dashboard global
+      expected: expected/dashboard-global.yml
+    - query: swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql dashboard global-metrics
+      expected: expected/dashboard-global-metrics.yml
+
+    - query: swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql dependency endpoint --service-name provider --endpoint-name /users
+      expected: expected/dependency-endpoint.yml
+    - query: swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql dependency instance --service-name consumer --dest-service-name provider
+      expected: expected/dependency-instance.yml
+    - query: swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql dependency service --service-name consumer
+      expected: expected/dependency-service.yml
+
+    - query: swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql endpoint ls --service-name provider
+      expected: expected/endpoint-list.yml
+
+    - query: swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql instance ls --service-name provider
+      expected: expected/instance-list.yml
+    - query: swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql instance search --service-name provider --regex ".*vid.*"
+      expected: expected/instance-list.yml
+    - query: swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql instance search --service-name provider --regex not-exist
+      expected: expected/empty-array.yml
+
+    - query: swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql metrics top 5 --name service_sla
+      expected: expected/metrics-top-service-sla.yml
+    - query: swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql metrics top 5 --name endpoint_sla --service-name provider
+      expected: expected/metrics-top-endpoint-sla-provider.yml
+
+    - query: swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql metrics linear --name=service_instance_resp_time --service-name provider --instance-name provider1 | yq e 'to_entries' -
+      expected: expected/metrics-has-value.yml
+    - query: swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql metrics linear --name=service_resp_time --service-name provider | yq e 'to_entries' -
+      expected: expected/metrics-has-value.yml
+    - query: swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql metrics linear --name=endpoint_sla --service-name provider --endpoint-name /users | yq e 'to_entries' -
+      expected: expected/metrics-has-value.yml
+
+    - query: swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql metrics single --name endpoint_cpm --service-name provider --endpoint-name /users
+      expected: expected/value.yml
+    - query: swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql metrics single --name service_cpm --service-name provider
+      expected: expected/value.yml
+    - query: swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql metrics single --name endpoint_cpm --service-name provider --endpoint-name /users
+      expected: expected/value.yml
+    - query: swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql metrics single --name service_instance_cpm --service-name provider --instance-name provider1
+      expected: expected/value.yml
+
+    - query: swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql service list
+      expected: expected/service.yml
+    - query: swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql service list provider
+      expected: expected/service-provider.yml
+
+    - query: swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql trace ls
+      expected: expected/traces-list.yml
+    - query: |
+        swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql trace $( \
+          swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql trace ls \
+            | yq e '.traces | select(.[].endpointnames[0]=="/users") | .[0].traceids[0]' -
+        )
+      expected: expected/trace-users-detail.yml