Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Release Notes.
* Add the `trace-v2 list` command for adapt the new trace query API by @mrproliu in https://github.com/apache/skywalking-cli/pull/225
* Add the duration field in the `trace list` command by @mrproliu in https://github.com/apache/skywalking-cli/pull/225
* Remove the oldest `queryTraceFromColdStage` query call in the `trace list` command by @mrproliu in https://github.com/apache/skywalking-cli/pull/225
* Add the sub-command `profiling pprof` for pprof query API by @JophieQu in https://github.com/apache/skywalking-cli/pull/226

### Bug Fixes

Expand Down
24 changes: 24 additions & 0 deletions assets/graphqls/profiling/pprof/CreateTask.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# 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: PprofTaskCreationRequest!) {
result: createPprofTask(pprofTaskCreationRequest: $condition) {
errorReason
code
id
}
}
30 changes: 30 additions & 0 deletions assets/graphqls/profiling/pprof/GetAnalysis.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# 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: PprofAnalyzationRequest!) {
result: queryPprofAnalyze(request: $condition) {
tree {
elements {
id
parentId
codeSignature
total
self
}
}
}
}
31 changes: 31 additions & 0 deletions assets/graphqls/profiling/pprof/GetTaskList.graphql
Original file line number Diff line number Diff line change
@@ -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 ($condition: PprofTaskListRequest!) {
result: queryPprofTaskList(request: $condition) {
errorReason
tasks {
serviceId
serviceInstanceIds
createTime
events
duration
dumpPeriod
id
}
}
}
30 changes: 30 additions & 0 deletions assets/graphqls/profiling/pprof/GetTaskProgress.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# 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: queryPprofTaskProgress(taskId: $taskId) {
errorInstanceIds
successInstanceIds
logs {
id
instanceId
instanceName
operationType
operationTime
}
}
}
2 changes: 1 addition & 1 deletion dist/LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ The text of each license is also included at licenses/license-[project].txt.
sigs.k8s.io/controller-runtime v0.20.4 Apache-2.0
sigs.k8s.io/randfill v1.0.0 Apache-2.0
sigs.k8s.io/structured-merge-diff/v4 v4.7.0 Apache-2.0
skywalking.apache.org/repo/goapi v0.0.0-20250918024206-7be91673cadc Apache-2.0
skywalking.apache.org/repo/goapi v0.0.0-20251011100214-efff910f2031 Apache-2.0

========================================================================
Apache-2.0 and BSD-3-Clause licenses
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ require (
gopkg.in/yaml.v2 v2.4.0
k8s.io/apimachinery v0.33.1
sigs.k8s.io/controller-runtime v0.20.4
skywalking.apache.org/repo/goapi v0.0.0-20250918024206-7be91673cadc
skywalking.apache.org/repo/goapi v0.0.0-20251011100214-efff910f2031
)

require (
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -543,5 +543,5 @@ sigs.k8s.io/structured-merge-diff/v4 v4.7.0 h1:qPeWmscJcXP0snki5IYF79Z8xrl8ETFxg
sigs.k8s.io/structured-merge-diff/v4 v4.7.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps=
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
skywalking.apache.org/repo/goapi v0.0.0-20250918024206-7be91673cadc h1:HhlLDl0aOIgiIdJl9p0a7PHHdZbs9epKEnewB7AWdZs=
skywalking.apache.org/repo/goapi v0.0.0-20250918024206-7be91673cadc/go.mod h1:Vj9vINJYsTQASPsbQ1i81YgH8nFC/Xds4GjcXvmRYwM=
skywalking.apache.org/repo/goapi v0.0.0-20251011100214-efff910f2031 h1:iMd6gzltWrWOtV3COm0mWydeXhpy7r1vkNlTsm7Co0g=
skywalking.apache.org/repo/goapi v0.0.0-20251011100214-efff910f2031/go.mod h1:Vj9vINJYsTQASPsbQ1i81YgH8nFC/Xds4GjcXvmRYwM=
1 change: 1 addition & 0 deletions internal/commands/interceptor/instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ func parseInstanceList(required bool, idListFlagName, nameListFlagName, serviceI

if idsArg == "" && namesArgs == "" {
if required {
_ = cli.ShowSubcommandHelp(ctx)
return fmt.Errorf(`either flags "--%s" or "--%s" must be given`, idListFlagName, nameListFlagName)
}
return nil
Expand Down
1 change: 1 addition & 0 deletions internal/commands/interceptor/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ func parseService(required bool, idFlagName, nameFlagName string, nodeType nodeT

if id == "" && name == "" {
if required {
_ = cli.ShowSubcommandHelp(ctx)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this necessary?

return fmt.Errorf(`either flags "--%s" or "--%s" must be given`, idFlagName, nameFlagName)
}
return nil
Expand Down
96 changes: 96 additions & 0 deletions internal/commands/profiling/pprof/create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// 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 pprof

import (
"strings"

"github.com/urfave/cli/v2"
"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/model/pprof"
"github.com/apache/skywalking-cli/pkg/display"
"github.com/apache/skywalking-cli/pkg/display/displayable"
"github.com/apache/skywalking-cli/pkg/graphql/profiling"
)

var createCommand = &cli.Command{
Name: "create",
Aliases: []string{"c"},
Usage: "Create a new pprof task",
UsageText: `Create a new pprof task

Examples:
1. Create pprof task
$ swctl profiling pprof create --service-name=service-name --duration=10 --events=mutex \
--instance-name-list=instance-name1,instance-name2 --dump-period=1`,
Flags: flags.Flags(
flags.ServiceFlags,
flags.InstanceListFlags,
[]cli.Flag{
&cli.IntFlag{
Name: "duration",
Usage: "task continuous time(minute), required for cpu, block and mutex events. ",
},
&cli.GenericFlag{
Name: "events",
Usage: "which event types this task needs to collect.",
Required: true,
Value: &pprof.ProfilingEventTypeEnumValue{
Enum: query.AllPprofEventType,
Default: query.PprofEventTypeCPU,
},
},
&cli.StringFlag{
Name: "dump-period",
Usage: "pprof dump period parameters, required for block and mutex events. ",
},
},
),
Before: interceptor.BeforeChain(
interceptor.ParseService(true),
interceptor.ParseInstanceList(true),
),
Action: func(ctx *cli.Context) error {
serviceID := ctx.String("service-id")
instanceIDs := strings.Split(ctx.String("instance-id-list"), ",")
eventTypes := ctx.Generic("events").(*pprof.ProfilingEventTypeEnumValue).Selected
var dumpPeriod, duration *int
if durationtime := ctx.Int("duration"); durationtime != 0 {
duration = &durationtime
}
if period := ctx.Int("dump-period"); period != 0 {
dumpPeriod = &period
}
request := &query.PprofTaskCreationRequest{
ServiceID: serviceID,
ServiceInstanceIds: instanceIDs,
Duration: duration,
Events: eventTypes,
DumpPeriod: dumpPeriod,
}
task, err := profiling.CreatePprofTask(ctx.Context, request)
if err != nil {
return err
}

return display.Display(ctx.Context, &displayable.Displayable{Data: task, Condition: request})
},
}
74 changes: 74 additions & 0 deletions internal/commands/profiling/pprof/getAnalyze.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// 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 pprof

import (
"strings"

"github.com/urfave/cli/v2"
"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/pkg/display"
"github.com/apache/skywalking-cli/pkg/display/displayable"
"github.com/apache/skywalking-cli/pkg/graphql/profiling"
)

var analysisCommand = &cli.Command{
Name: "analysis",
Aliases: []string{"a"},
Usage: "Query pprof analysis",
UsageText: `Query pprof analysis

Examples:
1. Query the flame graph produced by pprof
$ swctl profiling pprof analysis --service-name=service-name --task-id=task-id \
--instance-name-list=instance-name1,instance-name2`,
Flags: flags.Flags(
flags.ServiceFlags,
flags.InstanceListFlags,
[]cli.Flag{
&cli.StringFlag{
Name: "task-id",
Usage: "pprof task id",
Required: true,
},
},
),
Before: interceptor.BeforeChain(
interceptor.ParseService(true),
interceptor.ParseInstanceList(true),
),
Action: func(ctx *cli.Context) error {
taskID := ctx.String("task-id")
instances := strings.Split(ctx.String("instance-id-list"), ",")

request := &query.PprofAnalyzationRequest{
TaskID: taskID,
InstanceIds: instances,
}

analyze, err := profiling.GetPprofAnalyze(ctx.Context, request)
if err != nil {
return err
}

return display.Display(ctx.Context, &displayable.Displayable{Data: analyze, Condition: request})
},
}
Loading
Loading