You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by li...@apache.org on 2021/08/01 05:06:05 UTC

[skywalking-cli] branch master updated: Profile command support (#104)

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

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


The following commit(s) were added to refs/heads/master by this push:
     new fd89634  Profile command support (#104)
fd89634 is described below

commit fd896344969a366786bf45ead2f23e230b61b6b9
Author: mrproliu <74...@qq.com>
AuthorDate: Sun Aug 1 13:05:59 2021 +0800

    Profile command support (#104)
    
    * Support profile protocol
    
    Co-authored-by: Mrproliu <mr...@lagou.com>
---
 README.md                                          | 110 +++++++++
 assets/assets.gen.go                               | 255 +++++++++++++++++++++
 assets/graphqls/profile/CreateTask.graphql         |  23 ++
 assets/graphqls/profile/GetProfileAnalyze.graphql  |  31 +++
 assets/graphqls/profile/GetProfiledSegment.graphql |  37 +++
 assets/graphqls/profile/GetTaskList.graphql        |  35 +++
 assets/graphqls/profile/GetTaskSegmentList.graphql |  27 +++
 cmd/swctl/main.go                                  |   2 +
 internal/commands/profile/create.go                | 106 +++++++++
 internal/commands/profile/getProfileAnalyze.go     |  78 +++++++
 internal/commands/profile/getProfiledSegment.go    |  50 ++++
 internal/commands/profile/getTaskList.go           |  75 ++++++
 internal/commands/profile/getTaskSegmentList.go    |  50 ++++
 internal/commands/profile/profile.go               |  34 +++
 pkg/graphql/profile/profile.go                     |  86 +++++++
 15 files changed, 999 insertions(+)

diff --git a/README.md b/README.md
index 48837c7..1648d3b 100644
--- a/README.md
+++ b/README.md
@@ -418,6 +418,78 @@ You can imitate the content of [the default template file](examples/global.yml)
 
 </details>
 
+### `profile`
+
+#### `create`
+
+<details>
+
+<summary>profile create [--service-id=service-id] [--service-name=service-name] [--endpoint=endpoint] [--start-time=start-time] [--duration=duration] [--min-duration-threshold=min-duration-threshold] [--dump-period=dump-period] [--max-sampling-count=max-sampling-count] </summary>
+
+| argument | description | default |
+| :--- | :--- | :--- |
+| `service-id` | <service-id> whose endpoints are to be profile. |  |
+| `service-name` | <service-name> whose endpoints are to be profile. |  |
+| `endpoint` | which endpoint should profile. |  |
+| `start-time` | profile task start time(millisecond). |  |
+| `duration` | profile task continuous time(minute). | |
+| `min-duration-threshold` | profiled endpoint must greater duration(millisecond). | |
+| `dump-period` | profiled endpoint dump period(millisecond). | |
+| `max-sampling-count` | profile task max sampling count. | |
+
+</details>
+
+#### `list`
+
+<details>
+
+<summary>profile list [--service-id=service-id] [--service-name=service-name] [--endpoint=endpoint] </summary>
+
+| argument | description | default |
+| :--- | :--- | :--- |
+| `service-id` | `<service id>` whose profile task are to be searched. |  |
+| `service-name` | `<service name>` whose profile task are to be searched. |  |
+| `endpoint` | `<endpoint>` whose profile task are to be searched |  |
+
+</details>
+
+#### `segment-list`
+
+<details>
+
+<summary>profile segment-list [--task-id=task-id] </summary>
+
+| argument | description | default |
+| :--- | :--- | :--- |
+| `task-id` | `<task id>` whose profiled segment are to be searched. |  |
+
+</details>
+
+#### `profiled-segment`
+
+<details>
+
+<summary>profile profiled-segment [--segment-id=segment-id] </summary>
+
+| argument | description | default |
+| :--- | :--- | :--- |
+| `segment-id` | profiled segment id. |  |
+
+</details>
+
+#### `profiled-analyze`
+
+<details>
+
+<summary>profile profiled-analyze [--segment-id=segment-id] [--time-ranges=time-ranges] </summary>
+
+| argument | description | default |
+| :--- | :--- | :--- |
+| `segment-id` | profiled segment id. |  |
+| `time-ranges` | need to analyze time ranges in the segment: start-end,start-end. |  |
+
+</details>
+
 # Use Cases
 
 <details>
@@ -600,6 +672,44 @@ $ ./bin/swctl logs list
 
 <details>
 
+<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).
+
+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}]}]}
+```
+
+</details>
+
+<details>
+
 <summary>Display the spans of a trace</summary>
 
 ```shell
diff --git a/assets/assets.gen.go b/assets/assets.gen.go
index dca3aab..86a8b42 100644
--- a/assets/assets.gen.go
+++ b/assets/assets.gen.go
@@ -32,6 +32,11 @@
 // 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.161kB)
+// graphqls/profile/GetProfiledSegment.graphql (1.2kB)
+// graphqls/profile/GetTaskList.graphql (1.212kB)
+// graphqls/profile/GetTaskSegmentList.graphql (1.002kB)
 // graphqls/trace/Trace.graphql (1.518kB)
 // graphqls/trace/Traces.graphql (1.077kB)
 // templates/dashboard/global.yml (3.001kB)
@@ -712,6 +717,244 @@ func graphqlsMetricsSortmetricsGraphql() (*asset, error) {
 	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{0xf6, 0x37, 0x86, 0xaa, 0x43, 0x4b, 0x29, 0x39, 0x2b, 0xee, 0xdb, 0x51, 0x22, 0xb9, 0xf8, 0xd6, 0x8a, 0x96, 0x5d, 0xe1, 0xb1, 0x8c, 0xd3, 0x1e, 0xe1, 0x6, 0x63, 0xdd, 0x51, 0x5b, 0xfa, 0x1d}}
+	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{0xe8, 0xf1, 0xcb, 0x40, 0xbc, 0x1f, 0xc7, 0x7a, 0xa, 0x57, 0x29, 0x4b, 0x1c, 0xdd, 0x48, 0x7c, 0x81, 0x5b, 0xed, 0x80, 0xf2, 0x3, 0xc3, 0xa4, 0x7, 0x18, 0x90, 0x55, 0xe8, 0x6, 0x21, 0xf7}}
+	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{0xe8, 0xf0, 0x74, 0x1, 0xe2, 0xbb, 0x9c, 0x3e, 0xc5, 0x29, 0x7e, 0x8f, 0x6b, 0x4a, 0x50, 0x21, 0xc3, 0xb, 0x28, 0x6c, 0x65, 0x5a, 0xcc, 0x51, 0x8e, 0x3e, 0x10, 0xc0, 0x85, 0xec, 0x68, 0x82}}
+	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{0xbb, 0xac, 0x15, 0xf8, 0x73, 0x38, 0x2f, 0xc, 0xdf, 0xcb, 0x2b, 0x43, 0x16, 0x30, 0x9d, 0x3e, 0xbf, 0x47, 0x0, 0x88, 0x35, 0x4c, 0x9b, 0xfa, 0x7, 0x5d, 0x32, 0x5, 0xbf, 0x51, 0x31, 0xdc}}
+	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
@@ -1040,6 +1283,11 @@ var _bindata = map[string]func() (*asset, error){
 	"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,
@@ -1115,6 +1363,13 @@ var _bintree = &bintree{nil, 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{}},
diff --git a/assets/graphqls/profile/CreateTask.graphql b/assets/graphqls/profile/CreateTask.graphql
new file mode 100644
index 0000000..0ab38df
--- /dev/null
+++ b/assets/graphqls/profile/CreateTask.graphql
@@ -0,0 +1,23 @@
+# 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
+    }
+}
diff --git a/assets/graphqls/profile/GetProfileAnalyze.graphql b/assets/graphqls/profile/GetProfileAnalyze.graphql
new file mode 100644
index 0000000..49af788
--- /dev/null
+++ b/assets/graphqls/profile/GetProfileAnalyze.graphql
@@ -0,0 +1,31 @@
+# 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
+    		}
+    	}
+    }
+}
\ No newline at end of file
diff --git a/assets/graphqls/profile/GetProfiledSegment.graphql b/assets/graphqls/profile/GetProfiledSegment.graphql
new file mode 100644
index 0000000..98214bf
--- /dev/null
+++ b/assets/graphqls/profile/GetProfiledSegment.graphql
@@ -0,0 +1,37 @@
+# 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
+           }
+        }
+    }
+}
\ No newline at end of file
diff --git a/assets/graphqls/profile/GetTaskList.graphql b/assets/graphqls/profile/GetTaskList.graphql
new file mode 100644
index 0000000..17f32ca
--- /dev/null
+++ b/assets/graphqls/profile/GetTaskList.graphql
@@ -0,0 +1,35 @@
+# 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
+        }
+    }
+}
\ No newline at end of file
diff --git a/assets/graphqls/profile/GetTaskSegmentList.graphql b/assets/graphqls/profile/GetTaskSegmentList.graphql
new file mode 100644
index 0000000..9d4e474
--- /dev/null
+++ b/assets/graphqls/profile/GetTaskSegmentList.graphql
@@ -0,0 +1,27 @@
+# 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
+    }
+}
\ No newline at end of file
diff --git a/cmd/swctl/main.go b/cmd/swctl/main.go
index de5759f..bfbe23e 100644
--- a/cmd/swctl/main.go
+++ b/cmd/swctl/main.go
@@ -30,6 +30,7 @@ import (
 	"github.com/apache/skywalking-cli/internal/commands/interceptor"
 	"github.com/apache/skywalking-cli/internal/commands/logs"
 	"github.com/apache/skywalking-cli/internal/commands/metrics"
+	"github.com/apache/skywalking-cli/internal/commands/profile"
 	"github.com/apache/skywalking-cli/internal/commands/service"
 	"github.com/apache/skywalking-cli/internal/commands/trace"
 	"github.com/apache/skywalking-cli/internal/logger"
@@ -122,6 +123,7 @@ func main() {
 		install.Command,
 		event.Command,
 		logs.Command,
+		profile.Command,
 	}
 
 	app.Before = interceptor.BeforeChain([]cli.BeforeFunc{
diff --git a/internal/commands/profile/create.go b/internal/commands/profile/create.go
new file mode 100644
index 0000000..7993ba2
--- /dev/null
+++ b/internal/commands/profile/create.go
@@ -0,0 +1,106 @@
+// 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 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"
+
+	api "skywalking.apache.org/repo/goapi/query"
+
+	"github.com/urfave/cli"
+)
+
+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.",
+		},
+	},
+	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"),
+			StartTime:            &startTime,
+			Duration:             ctx.Int("duration"),
+			MinDurationThreshold: ctx.Int("min-duration-threshold"),
+			DumpPeriod:           ctx.Int("dump-period"),
+			MaxSamplingCount:     ctx.Int("max-sampling-count"),
+		}
+
+		task, err := profile.CreateTask(ctx, request)
+
+		if err != nil {
+			logger.Log.Fatalln(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
new file mode 100644
index 0000000..8847ad0
--- /dev/null
+++ b/internal/commands/profile/getProfileAnalyze.go
@@ -0,0 +1,78 @@
+// 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 profile
+
+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"
+
+	api "skywalking.apache.org/repo/goapi/query"
+)
+
+var getProfiledAnalyzeCommand = cli.Command{
+	Name:      "profiled-analyze",
+	Aliases:   []string{"pa"},
+	Usage:     "analyze profiled segment.",
+	ArgsUsage: "[parameters...]",
+	Flags: []cli.Flag{
+		cli.StringFlag{
+			Name:  "segment-id",
+			Usage: "profiled segment id.",
+		},
+		cli.StringFlag{
+			Name:  "time-ranges",
+			Usage: "need to analyze time ranges in the segment: start-end,start-end",
+		},
+	},
+	Action: func(ctx *cli.Context) error {
+		segmentID := ctx.String("segment-id")
+
+		tagStr := ctx.String("time-ranges")
+		var timeRanges []*api.ProfileAnalyzeTimeRange = nil
+		if tagStr != "" {
+			tagArr := strings.Split(tagStr, ",")
+			for _, tag := range tagArr {
+				kv := strings.Split(tag, "-")
+				start, err := strconv.ParseInt(kv[0], 10, 64)
+				if err != nil {
+					return err
+				}
+				end, err := strconv.ParseInt(kv[1], 10, 64)
+				if err != nil {
+					return err
+				}
+				timeRanges = append(timeRanges, &api.ProfileAnalyzeTimeRange{Start: start, End: end})
+			}
+		}
+
+		analysis, err := profile.GetProfileAnalyze(ctx, segmentID, timeRanges)
+
+		if err != nil {
+			logger.Log.Fatalln(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
new file mode 100644
index 0000000..5df747b
--- /dev/null
+++ b/internal/commands/profile/getProfiledSegment.go
@@ -0,0 +1,50 @@
+// 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 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"
+)
+
+var getProfiledSegmentCommand = cli.Command{
+	Name:      "profiled-segment",
+	Aliases:   []string{"ps"},
+	Usage:     "query profile task segment list",
+	ArgsUsage: "[parameters...]",
+	Flags: []cli.Flag{
+		cli.StringFlag{
+			Name:  "segment-id",
+			Usage: "profiled segment id.",
+		},
+	},
+	Action: func(ctx *cli.Context) error {
+		segmentID := ctx.String("segment-id")
+		segment, err := profile.GetProfiledSegment(ctx, segmentID)
+
+		if err != nil {
+			logger.Log.Fatalln(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
new file mode 100644
index 0000000..67317f9
--- /dev/null
+++ b/internal/commands/profile/getTaskList.go
@@ -0,0 +1,75 @@
+// 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 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"
+)
+
+var getTaskListCommand = cli.Command{
+	Name:      "list",
+	Aliases:   []string{"l"},
+	Usage:     "query profile task list",
+	ArgsUsage: "[parameters...]",
+	Flags: []cli.Flag{
+		cli.StringFlag{
+			Name:  "service-id",
+			Usage: "`<service id>` whose profile task are to be searched",
+		},
+		cli.StringFlag{
+			Name:  "service-name",
+			Usage: "`<service name>` whose profile task are to be searched",
+		},
+		cli.StringFlag{
+			Name:  "endpoint",
+			Usage: "`<endpoint>` whose profile task are to be searched",
+		},
+	},
+	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
+		}
+
+		endpoint := ctx.String("endpoint")
+
+		task, err := profile.GetTaskList(ctx, serviceID, endpoint)
+
+		if err != nil {
+			logger.Log.Fatalln(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
new file mode 100644
index 0000000..869241b
--- /dev/null
+++ b/internal/commands/profile/getTaskSegmentList.go
@@ -0,0 +1,50 @@
+// 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 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"
+)
+
+var getTaskSegmentListCommand = cli.Command{
+	Name:      "segment-list",
+	Aliases:   []string{"sl"},
+	Usage:     "query profile task segment list",
+	ArgsUsage: "[parameters...]",
+	Flags: []cli.Flag{
+		cli.StringFlag{
+			Name:  "task-id",
+			Usage: "`<task id>` whose profiled segment are to be searched",
+		},
+	},
+	Action: func(ctx *cli.Context) error {
+		taskID := ctx.String("task-id")
+		segmentList, err := profile.GetTaskSegmentList(ctx, taskID)
+
+		if err != nil {
+			logger.Log.Fatalln(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
new file mode 100644
index 0000000..5f9136c
--- /dev/null
+++ b/internal/commands/profile/profile.go
@@ -0,0 +1,34 @@
+// 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 profile
+
+import (
+	"github.com/urfave/cli"
+)
+
+var Command = cli.Command{
+	Name:  "profile",
+	Usage: "Profile related sub-command",
+	Subcommands: []cli.Command{
+		createCommand,
+		getTaskListCommand,
+		getTaskSegmentListCommand,
+		getProfiledSegmentCommand,
+		getProfiledAnalyzeCommand,
+	},
+}
diff --git a/pkg/graphql/profile/profile.go b/pkg/graphql/profile/profile.go
new file mode 100644
index 0000000..a086afd
--- /dev/null
+++ b/pkg/graphql/profile/profile.go
@@ -0,0 +1,86 @@
+// 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 profile
+
+import (
+	"github.com/apache/skywalking-cli/assets"
+	"github.com/apache/skywalking-cli/pkg/graphql/client"
+
+	"github.com/machinebox/graphql"
+
+	"github.com/urfave/cli"
+
+	api "skywalking.apache.org/repo/goapi/query"
+)
+
+func CreateTask(ctx *cli.Context, condition *api.ProfileTaskCreationRequest) (api.ProfileTaskCreationResult, error) {
+	var response map[string]api.ProfileTaskCreationResult
+
+	request := graphql.NewRequest(assets.Read("graphqls/profile/CreateTask.graphql"))
+	request.Var("condition", condition)
+
+	err := client.ExecuteQuery(ctx, request, &response)
+
+	return response["result"], err
+}
+
+func GetTaskList(ctx *cli.Context, serviceID, endpointName string) ([]*api.ProfileTask, error) {
+	var response map[string][]*api.ProfileTask
+
+	request := graphql.NewRequest(assets.Read("graphqls/profile/GetTaskList.graphql"))
+	request.Var("serviceId", serviceID)
+	request.Var("endpointName", endpointName)
+
+	err := client.ExecuteQuery(ctx, request, &response)
+
+	return response["result"], err
+}
+
+func GetTaskSegmentList(ctx *cli.Context, taskID string) ([]*api.BasicTrace, error) {
+	var response map[string][]*api.BasicTrace
+
+	request := graphql.NewRequest(assets.Read("graphqls/profile/GetTaskSegmentList.graphql"))
+	request.Var("taskId", taskID)
+
+	err := client.ExecuteQuery(ctx, request, &response)
+
+	return response["result"], err
+}
+
+func GetProfiledSegment(ctx *cli.Context, segmentID string) (api.ProfiledSegment, error) {
+	var response map[string]api.ProfiledSegment
+
+	request := graphql.NewRequest(assets.Read("graphqls/profile/GetProfiledSegment.graphql"))
+	request.Var("segmentId", segmentID)
+
+	err := client.ExecuteQuery(ctx, request, &response)
+
+	return response["result"], err
+}
+
+func GetProfileAnalyze(ctx *cli.Context, segmentID string, timeRanges []*api.ProfileAnalyzeTimeRange) (api.ProfileAnalyzation, error) {
+	var response map[string]api.ProfileAnalyzation
+
+	request := graphql.NewRequest(assets.Read("graphqls/profile/GetProfileAnalyze.graphql"))
+	request.Var("segmentId", segmentID)
+	request.Var("timeRanges", timeRanges)
+
+	err := client.ExecuteQuery(ctx, request, &response)
+
+	return response["result"], err
+}