From d2355a0fc6c48d6b23cc325d6a3c350797977c98 Mon Sep 17 00:00:00 2001 From: zhengziyi Date: Wed, 23 Oct 2024 19:57:38 +0800 Subject: [PATCH 01/24] feat: add asyncprofiler support --- .../asyncprofiler/CreateTask.graphql | 24 +++++++ .../asyncprofiler/GetAnalysis.graphql | 32 +++++++++ .../asyncprofiler/GetTaskList.graphql | 31 ++++++++ .../asyncprofiler/GetTaskProgress.graphql | 30 ++++++++ go.mod | 2 +- go.sum | 6 +- .../profiling/asyncprofiler/asyncprofiler.go | 17 +++++ .../profiling/asyncprofiler/create.go | 70 +++++++++++++++++++ .../profiling/asyncprofiler/getAnalyze.go | 54 ++++++++++++++ .../profiling/asyncprofiler/getTaskList.go | 38 ++++++++++ .../asyncprofiler/getTaskProgress.go | 36 ++++++++++ internal/commands/profiling/profiling.go | 2 + pkg/graphql/profiling/asyncprofiler.go | 53 ++++++++++++++ 13 files changed, 392 insertions(+), 3 deletions(-) create mode 100644 assets/graphqls/profiling/asyncprofiler/CreateTask.graphql create mode 100644 assets/graphqls/profiling/asyncprofiler/GetAnalysis.graphql create mode 100644 assets/graphqls/profiling/asyncprofiler/GetTaskList.graphql create mode 100644 assets/graphqls/profiling/asyncprofiler/GetTaskProgress.graphql create mode 100644 internal/commands/profiling/asyncprofiler/asyncprofiler.go create mode 100644 internal/commands/profiling/asyncprofiler/create.go create mode 100644 internal/commands/profiling/asyncprofiler/getAnalyze.go create mode 100644 internal/commands/profiling/asyncprofiler/getTaskList.go create mode 100644 internal/commands/profiling/asyncprofiler/getTaskProgress.go create mode 100644 pkg/graphql/profiling/asyncprofiler.go diff --git a/assets/graphqls/profiling/asyncprofiler/CreateTask.graphql b/assets/graphqls/profiling/asyncprofiler/CreateTask.graphql new file mode 100644 index 0000000..03037c8 --- /dev/null +++ b/assets/graphqls/profiling/asyncprofiler/CreateTask.graphql @@ -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: AsyncProfilerCreationRequest) { + result: createAsyncProfilerTask(asyncProfilerTaskCreationRequest: $condition) { + errorReason + errorCode + id + } +} \ No newline at end of file diff --git a/assets/graphqls/profiling/asyncprofiler/GetAnalysis.graphql b/assets/graphqls/profiling/asyncprofiler/GetAnalysis.graphql new file mode 100644 index 0000000..4dbe480 --- /dev/null +++ b/assets/graphqls/profiling/asyncprofiler/GetAnalysis.graphql @@ -0,0 +1,32 @@ +# 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: AsyncProfilerAnalyzationRequest) { + result queryAsyncProfilerAnalyze(request: $condition) { + errorReason + tree { + type + elements { + id + parentId + codeSignature + total + self + } + } + } +} \ No newline at end of file diff --git a/assets/graphqls/profiling/asyncprofiler/GetTaskList.graphql b/assets/graphqls/profiling/asyncprofiler/GetTaskList.graphql new file mode 100644 index 0000000..5bac260 --- /dev/null +++ b/assets/graphqls/profiling/asyncprofiler/GetTaskList.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 ($condition: AsyncProfilerTaskListRequest) { + result: queryAsyncProfilerTaskList(request: $condition) { + errorReason + tasks { + serviceId + serviceInstanceIds + createTime + events + duration + execArgs + id + } + } +} diff --git a/assets/graphqls/profiling/asyncprofiler/GetTaskProgress.graphql b/assets/graphqls/profiling/asyncprofiler/GetTaskProgress.graphql new file mode 100644 index 0000000..5eca495 --- /dev/null +++ b/assets/graphqls/profiling/asyncprofiler/GetTaskProgress.graphql @@ -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 queryAsyncProfilerTaskProgress(taskId: $taskId) { + errorInstanceIds + successInstanceIds + logs { + id + instanceId + instanceName + operationType + operationTime + } + } +} \ No newline at end of file diff --git a/go.mod b/go.mod index c030ac6..4a771a3 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( gopkg.in/yaml.v2 v2.4.0 k8s.io/apimachinery v0.22.1 sigs.k8s.io/controller-runtime v0.10.0 - skywalking.apache.org/repo/goapi v0.0.0-20240227092755-edee3273b361 + skywalking.apache.org/repo/goapi v0.0.0-20241023080050-2514649a8007 ) require ( diff --git a/go.sum b/go.sum index c815258..10af630 100644 --- a/go.sum +++ b/go.sum @@ -879,5 +879,7 @@ sigs.k8s.io/structured-merge-diff/v4 v4.1.2 h1:Hr/htKFmJEbtMgS/UD0N+gtgctAqz81t3 sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= -skywalking.apache.org/repo/goapi v0.0.0-20240227092755-edee3273b361 h1:FCGGU4Tut3LI/zMRXSgJgUL/kmSQ4b7QktFgRBhqaDs= -skywalking.apache.org/repo/goapi v0.0.0-20240227092755-edee3273b361/go.mod h1:+n8BMuS8eRdzdnGh15ElRGBXPi0eYZSs2TKySBDmRTE= +skywalking.apache.org/repo/goapi v0.0.0-20240920052516-d4a23d9da0e0 h1:7IW+T+mciD/GJXvgglZho414N30KSWgUTzBmEP867eI= +skywalking.apache.org/repo/goapi v0.0.0-20240920052516-d4a23d9da0e0/go.mod h1:+n8BMuS8eRdzdnGh15ElRGBXPi0eYZSs2TKySBDmRTE= +skywalking.apache.org/repo/goapi v0.0.0-20241023080050-2514649a8007 h1:MQU9yOZxgbs7fU145wd400/E3ES/HWoxTtTCudaCBoA= +skywalking.apache.org/repo/goapi v0.0.0-20241023080050-2514649a8007/go.mod h1:+n8BMuS8eRdzdnGh15ElRGBXPi0eYZSs2TKySBDmRTE= diff --git a/internal/commands/profiling/asyncprofiler/asyncprofiler.go b/internal/commands/profiling/asyncprofiler/asyncprofiler.go new file mode 100644 index 0000000..42328c0 --- /dev/null +++ b/internal/commands/profiling/asyncprofiler/asyncprofiler.go @@ -0,0 +1,17 @@ +package asyncprofiler + +import ( + "github.com/urfave/cli/v2" +) + +var Command = &cli.Command{ + Name: "asyncprofiler", + Usage: "async profiler related sub-command", + UsageText: `todo`, + Subcommands: []*cli.Command{ + createCommand, + getTaskListCommand, + getTaskProgressCommand, + analysisCommand, + }, +} diff --git a/internal/commands/profiling/asyncprofiler/create.go b/internal/commands/profiling/asyncprofiler/create.go new file mode 100644 index 0000000..2f08db0 --- /dev/null +++ b/internal/commands/profiling/asyncprofiler/create.go @@ -0,0 +1,70 @@ +package asyncprofiler + +import ( + "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" + "github.com/urfave/cli/v2" + "skywalking.apache.org/repo/goapi/query" + "strings" +) + +var createCommand = &cli.Command{ + Name: "create", + Aliases: []string{"c"}, + Usage: "Create a new async profiler task", + UsageText: `Create a new async profiler task + +Examples: +1. Create async-profiler task +$ swctl profiling asyncprofiler create todo`, + Flags: flags.Flags( + flags.EndpointFlags, + + []cli.Flag{ + &cli.StringSliceFlag{ + Name: "service-instance-ids", + Usage: "which instances to execute task.", + }, + &cli.IntFlag{ + Name: "duration", + Usage: "task continuous time(second).", + }, + &cli.StringSliceFlag{ + Name: "events", + Usage: "which event types this task needs to collect.", + }, + &cli.StringFlag{ + Name: "exec-args", + Usage: "other async-profiler execution options, e.g. alloc=2k,lock=2s.", + }, + }, + ), + Action: func(ctx *cli.Context) error { + serviceID := ctx.String("service-id") + + events := ctx.StringSlice("events") + eventTypes := make([]query.AsyncProfilerEventType, 0) + for _, event := range events { + upperCaseEvent := strings.ToUpper(event) + eventTypes = append(eventTypes, query.AsyncProfilerEventType(upperCaseEvent)) + } + + execArgs := ctx.String("exec-args") + + request := &query.AsyncProfilerTaskCreationRequest{ + ServiceID: serviceID, + ServiceInstanceIds: ctx.StringSlice("service-instance-ids"), + Duration: ctx.Int("duration"), + Events: make([]query.AsyncProfilerEventType, 0), + ExecArgs: &execArgs, + } + task, err := profiling.CreateAsyncProfilerTask(ctx, request) + if err != nil { + return err + } + + return display.Display(ctx, &displayable.Displayable{Data: task, Condition: request}) + }, +} diff --git a/internal/commands/profiling/asyncprofiler/getAnalyze.go b/internal/commands/profiling/asyncprofiler/getAnalyze.go new file mode 100644 index 0000000..6008dd1 --- /dev/null +++ b/internal/commands/profiling/asyncprofiler/getAnalyze.go @@ -0,0 +1,54 @@ +package asyncprofiler + +import ( + "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" + "github.com/urfave/cli/v2" + query "skywalking.apache.org/repo/goapi/query" + "strings" +) + +var analysisCommand = &cli.Command{ + Name: "analysis", + Aliases: []string{"pa"}, + Usage: "Analyze profiled stacktrace", + UsageText: ``, + Flags: flags.Flags( + flags.EndpointFlags, + + []cli.Flag{ + &cli.IntFlag{ + Name: "task-id", + Usage: "async-profiler task id", + }, + &cli.StringSliceFlag{ + Name: "service-instance-ids", + Usage: "select which service instances' jfr files to analyze", + }, + &cli.StringFlag{ + Name: "event", + Usage: "which event types this task needs to collect.", + }, + }, + ), + Action: func(ctx *cli.Context) error { + event := ctx.String("events") + eventType := query.JFREventType(strings.ToUpper(event)) + + request := &query.AsyncProfilerAnalyzationRequest{ + TaskID: ctx.String("task-id"), + InstanceIds: ctx.StringSlice("service-instance-ids"), + EventType: eventType, + } + + analyze, err := profiling.GetAsyncProfilerAnalyze(ctx, request) + + if err != nil { + return err + } + + return display.Display(ctx, &displayable.Displayable{Data: analyze, Condition: request}) + }, +} diff --git a/internal/commands/profiling/asyncprofiler/getTaskList.go b/internal/commands/profiling/asyncprofiler/getTaskList.go new file mode 100644 index 0000000..463f622 --- /dev/null +++ b/internal/commands/profiling/asyncprofiler/getTaskList.go @@ -0,0 +1,38 @@ +package asyncprofiler + +import ( + "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" + "github.com/urfave/cli/v2" + "skywalking.apache.org/repo/goapi/query" +) + +var getTaskListCommand = &cli.Command{ + Name: "list", + Aliases: []string{"l"}, + Usage: "Query async-profiler task list", + UsageText: ``, + Flags: flags.Flags(), + Action: func(ctx *cli.Context) error { + serviceID := ctx.String("service-id") + startTime := ctx.Int64("start-time") + endTime := ctx.Int64("end-time") + limit := ctx.Int("limit") + request := &query.AsyncProfilerTaskListRequest{ + ServiceID: serviceID, + StartTime: &startTime, + EndTime: &endTime, + Limit: &limit, + } + + tasks, err := profiling.GetAsyncProfilerTaskList(ctx, request) + + if err != nil { + return err + } + + return display.Display(ctx, &displayable.Displayable{Data: tasks, Condition: request}) + }, +} diff --git a/internal/commands/profiling/asyncprofiler/getTaskProgress.go b/internal/commands/profiling/asyncprofiler/getTaskProgress.go new file mode 100644 index 0000000..7568580 --- /dev/null +++ b/internal/commands/profiling/asyncprofiler/getTaskProgress.go @@ -0,0 +1,36 @@ +package asyncprofiler + +import ( + "github.com/apache/skywalking-cli/pkg/display" + "github.com/apache/skywalking-cli/pkg/display/displayable" + "github.com/apache/skywalking-cli/pkg/graphql/profiling" + "github.com/urfave/cli/v2" +) + +var getTaskProgressCommand = &cli.Command{ + Name: "progress", + Aliases: []string{"logs,p"}, + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "task-id", + Usage: "async profiler task id.", + }, + }, + Usage: "Query trace profiling task log list", + UsageText: `Query trace profiling task log list + +Examples: +1. Query all trace profiling logs of task id "task-id" +$ swctl profiling trace logs --task-id=task-id`, + Action: func(ctx *cli.Context) error { + taskID := ctx.String("task-id") + + data, err := profiling.GetAsyncProfilerTaskProgress(ctx, taskID) + + if err != nil { + return err + } + + return display.Display(ctx, &displayable.Displayable{Data: data, Condition: taskID}) + }, +} diff --git a/internal/commands/profiling/profiling.go b/internal/commands/profiling/profiling.go index 6059b76..ba936f8 100644 --- a/internal/commands/profiling/profiling.go +++ b/internal/commands/profiling/profiling.go @@ -18,6 +18,7 @@ package profiling import ( + "github.com/apache/skywalking-cli/internal/commands/profiling/asyncprofiler" "github.com/urfave/cli/v2" "github.com/apache/skywalking-cli/internal/commands/profiling/continuous" @@ -34,5 +35,6 @@ Please following sub-command to get more information.`, trace.Command, ebpf.Command, continuous.Command, + asyncprofiler.Command, }, } diff --git a/pkg/graphql/profiling/asyncprofiler.go b/pkg/graphql/profiling/asyncprofiler.go new file mode 100644 index 0000000..16a3f52 --- /dev/null +++ b/pkg/graphql/profiling/asyncprofiler.go @@ -0,0 +1,53 @@ +package profiling + +import ( + "github.com/apache/skywalking-cli/assets" + "github.com/apache/skywalking-cli/pkg/graphql/client" + "github.com/machinebox/graphql" + "github.com/urfave/cli/v2" + api "skywalking.apache.org/repo/goapi/query" +) + +func CreateAsyncProfilerTask(ctx *cli.Context, condition *api.AsyncProfilerTaskCreationRequest) (api.AsyncProfilerTaskCreationResult, error) { + var response map[string]api.AsyncProfilerTaskCreationResult + + request := graphql.NewRequest(assets.Read("graphqls/profiling/asyncprofiler/CreateTask.graphql")) + request.Var("condition", condition) + + err := client.ExecuteQuery(ctx, request, &response) + + return response["result"], err +} + +func GetAsyncProfilerTaskList(ctx *cli.Context, condition *api.AsyncProfilerTaskListRequest) (api.AsyncProfilerTaskListResult, error) { + var response map[string]api.AsyncProfilerTaskListResult + + request := graphql.NewRequest(assets.Read("graphqls/profiling/asyncprofiler/GetTaskList.graphql")) + request.Var("condition", condition) + + err := client.ExecuteQuery(ctx, request, &response) + + return response["result"], err +} + +func GetAsyncProfilerTaskProgress(ctx *cli.Context, taskID string) (api.AsyncProfilerTaskProgress, error) { + var response map[string]api.AsyncProfilerTaskProgress + + request := graphql.NewRequest(assets.Read("graphqls/profiling/asyncprofiler/GetTaskProgress.graphql")) + request.Var("taskId", taskID) + + err := client.ExecuteQuery(ctx, request, &response) + + return response["result"], err +} + +func GetAsyncProfilerAnalyze(ctx *cli.Context, condition *api.AsyncProfilerAnalyzationRequest) (api.AsyncProfilerAnalyzation, error) { + var response map[string]api.AsyncProfilerAnalyzation + + request := graphql.NewRequest(assets.Read("graphqls/profiling/trace/GetAnalysis.graphql")) + request.Var("condition", condition) + + err := client.ExecuteQuery(ctx, request, &response) + + return response["result"], err +} From 37550c62e4612ab69560a27b4a39fc0077f85360 Mon Sep 17 00:00:00 2001 From: zhengziyi Date: Wed, 23 Oct 2024 20:08:01 +0800 Subject: [PATCH 02/24] fix: alias --- internal/commands/profiling/asyncprofiler/getAnalyze.go | 2 +- internal/commands/profiling/asyncprofiler/getTaskProgress.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/commands/profiling/asyncprofiler/getAnalyze.go b/internal/commands/profiling/asyncprofiler/getAnalyze.go index 6008dd1..a4e5124 100644 --- a/internal/commands/profiling/asyncprofiler/getAnalyze.go +++ b/internal/commands/profiling/asyncprofiler/getAnalyze.go @@ -12,7 +12,7 @@ import ( var analysisCommand = &cli.Command{ Name: "analysis", - Aliases: []string{"pa"}, + Aliases: []string{"a"}, Usage: "Analyze profiled stacktrace", UsageText: ``, Flags: flags.Flags( diff --git a/internal/commands/profiling/asyncprofiler/getTaskProgress.go b/internal/commands/profiling/asyncprofiler/getTaskProgress.go index 7568580..9833a34 100644 --- a/internal/commands/profiling/asyncprofiler/getTaskProgress.go +++ b/internal/commands/profiling/asyncprofiler/getTaskProgress.go @@ -9,7 +9,7 @@ import ( var getTaskProgressCommand = &cli.Command{ Name: "progress", - Aliases: []string{"logs,p"}, + Aliases: []string{"logs", "p"}, Flags: []cli.Flag{ &cli.StringFlag{ Name: "task-id", From 8e10fe0255e5e3c24654937a0e43600de1dd402c Mon Sep 17 00:00:00 2001 From: zhengziyi Date: Thu, 24 Oct 2024 21:31:30 +0800 Subject: [PATCH 03/24] feat: support asyncprofiler --- .../asyncprofiler/CreateTask.graphql | 4 +-- .../asyncprofiler/GetAnalysis.graphql | 5 ++- .../asyncprofiler/GetTaskProgress.graphql | 4 +-- go.sum | 2 -- .../profiling/asyncprofiler/create.go | 26 ++++++++------ .../profiling/asyncprofiler/getAnalyze.go | 33 ++++++++++-------- .../profiling/asyncprofiler/getTaskList.go | 34 ++++++++++++++++--- .../asyncprofiler/getTaskProgress.go | 8 ++--- pkg/graphql/profiling/asyncprofiler.go | 2 +- 9 files changed, 75 insertions(+), 43 deletions(-) diff --git a/assets/graphqls/profiling/asyncprofiler/CreateTask.graphql b/assets/graphqls/profiling/asyncprofiler/CreateTask.graphql index 03037c8..2e53fbd 100644 --- a/assets/graphqls/profiling/asyncprofiler/CreateTask.graphql +++ b/assets/graphqls/profiling/asyncprofiler/CreateTask.graphql @@ -15,10 +15,10 @@ # specific language governing permissions and limitations # under the License. -mutation ($condition: AsyncProfilerCreationRequest) { +mutation ($condition: AsyncProfilerTaskCreationRequest!) { result: createAsyncProfilerTask(asyncProfilerTaskCreationRequest: $condition) { errorReason - errorCode + code id } } \ No newline at end of file diff --git a/assets/graphqls/profiling/asyncprofiler/GetAnalysis.graphql b/assets/graphqls/profiling/asyncprofiler/GetAnalysis.graphql index 4dbe480..a8cd925 100644 --- a/assets/graphqls/profiling/asyncprofiler/GetAnalysis.graphql +++ b/assets/graphqls/profiling/asyncprofiler/GetAnalysis.graphql @@ -15,9 +15,8 @@ # specific language governing permissions and limitations # under the License. -query ($condition: AsyncProfilerAnalyzationRequest) { - result queryAsyncProfilerAnalyze(request: $condition) { - errorReason +query ($condition: AsyncProfilerAnalyzationRequest!) { + result: queryAsyncProfilerAnalyze(request: $condition) { tree { type elements { diff --git a/assets/graphqls/profiling/asyncprofiler/GetTaskProgress.graphql b/assets/graphqls/profiling/asyncprofiler/GetTaskProgress.graphql index 5eca495..a81c4c0 100644 --- a/assets/graphqls/profiling/asyncprofiler/GetTaskProgress.graphql +++ b/assets/graphqls/profiling/asyncprofiler/GetTaskProgress.graphql @@ -15,8 +15,8 @@ # specific language governing permissions and limitations # under the License. -query ($taskId: String){ - result queryAsyncProfilerTaskProgress(taskId: $taskId) { +query ($taskId: String!){ + result: queryAsyncProfilerTaskProgress(taskId: $taskId) { errorInstanceIds successInstanceIds logs { diff --git a/go.sum b/go.sum index 10af630..14f447f 100644 --- a/go.sum +++ b/go.sum @@ -879,7 +879,5 @@ sigs.k8s.io/structured-merge-diff/v4 v4.1.2 h1:Hr/htKFmJEbtMgS/UD0N+gtgctAqz81t3 sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= -skywalking.apache.org/repo/goapi v0.0.0-20240920052516-d4a23d9da0e0 h1:7IW+T+mciD/GJXvgglZho414N30KSWgUTzBmEP867eI= -skywalking.apache.org/repo/goapi v0.0.0-20240920052516-d4a23d9da0e0/go.mod h1:+n8BMuS8eRdzdnGh15ElRGBXPi0eYZSs2TKySBDmRTE= skywalking.apache.org/repo/goapi v0.0.0-20241023080050-2514649a8007 h1:MQU9yOZxgbs7fU145wd400/E3ES/HWoxTtTCudaCBoA= skywalking.apache.org/repo/goapi v0.0.0-20241023080050-2514649a8007/go.mod h1:+n8BMuS8eRdzdnGh15ElRGBXPi0eYZSs2TKySBDmRTE= diff --git a/internal/commands/profiling/asyncprofiler/create.go b/internal/commands/profiling/asyncprofiler/create.go index 2f08db0..3f8c052 100644 --- a/internal/commands/profiling/asyncprofiler/create.go +++ b/internal/commands/profiling/asyncprofiler/create.go @@ -1,6 +1,7 @@ package asyncprofiler import ( + "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" @@ -18,22 +19,24 @@ var createCommand = &cli.Command{ Examples: 1. Create async-profiler task -$ swctl profiling asyncprofiler create todo`, +$ swctl profiling asyncprofiler create --service-name=someservicename --duration=60 --events=cpu --service-instance-ids=someinstance`, Flags: flags.Flags( - flags.EndpointFlags, - + flags.ServiceFlags, []cli.Flag{ &cli.StringSliceFlag{ - Name: "service-instance-ids", - Usage: "which instances to execute task.", + Name: "service-instance-ids", + Usage: "which instances to execute task.", + Required: true, }, &cli.IntFlag{ - Name: "duration", - Usage: "task continuous time(second).", + Name: "duration", + Usage: "task continuous time(second).", + Required: true, }, &cli.StringSliceFlag{ - Name: "events", - Usage: "which event types this task needs to collect.", + Name: "events", + Usage: "which event types this task needs to collect.", + Required: true, }, &cli.StringFlag{ Name: "exec-args", @@ -41,6 +44,9 @@ $ swctl profiling asyncprofiler create todo`, }, }, ), + Before: interceptor.BeforeChain( + interceptor.ParseService(false), + ), Action: func(ctx *cli.Context) error { serviceID := ctx.String("service-id") @@ -57,7 +63,7 @@ $ swctl profiling asyncprofiler create todo`, ServiceID: serviceID, ServiceInstanceIds: ctx.StringSlice("service-instance-ids"), Duration: ctx.Int("duration"), - Events: make([]query.AsyncProfilerEventType, 0), + Events: eventTypes, ExecArgs: &execArgs, } task, err := profiling.CreateAsyncProfilerTask(ctx, request) diff --git a/internal/commands/profiling/asyncprofiler/getAnalyze.go b/internal/commands/profiling/asyncprofiler/getAnalyze.go index a4e5124..bf766b2 100644 --- a/internal/commands/profiling/asyncprofiler/getAnalyze.go +++ b/internal/commands/profiling/asyncprofiler/getAnalyze.go @@ -11,30 +11,35 @@ import ( ) var analysisCommand = &cli.Command{ - Name: "analysis", - Aliases: []string{"a"}, - Usage: "Analyze profiled stacktrace", - UsageText: ``, - Flags: flags.Flags( - flags.EndpointFlags, + Name: "analysis", + Aliases: []string{"a"}, + Usage: "Query async-profiler analysis", + UsageText: `Query async-profiler analysis +Examples: +1. Query the flame graph produced by async-profiler +$ /swctl-dev-37550c6-darwin-arm64 profiling asyncprofiler analysis --task-id=task-id --service-instance-ids=instanceIds --event=execution_sample`, + Flags: flags.Flags( []cli.Flag{ - &cli.IntFlag{ - Name: "task-id", - Usage: "async-profiler task id", + &cli.StringFlag{ + Name: "task-id", + Usage: "async-profiler task id", + Required: true, }, &cli.StringSliceFlag{ - Name: "service-instance-ids", - Usage: "select which service instances' jfr files to analyze", + Name: "service-instance-ids", + Usage: "select which service instances' jfr files to analyze", + Required: true, }, &cli.StringFlag{ - Name: "event", - Usage: "which event types this task needs to collect.", + Name: "event", + Usage: "which event types this task needs to collect.", + Required: true, }, }, ), Action: func(ctx *cli.Context) error { - event := ctx.String("events") + event := ctx.String("event") eventType := query.JFREventType(strings.ToUpper(event)) request := &query.AsyncProfilerAnalyzationRequest{ diff --git a/internal/commands/profiling/asyncprofiler/getTaskList.go b/internal/commands/profiling/asyncprofiler/getTaskList.go index 463f622..29a4ee0 100644 --- a/internal/commands/profiling/asyncprofiler/getTaskList.go +++ b/internal/commands/profiling/asyncprofiler/getTaskList.go @@ -1,6 +1,7 @@ package asyncprofiler import ( + "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" @@ -10,11 +11,34 @@ import ( ) var getTaskListCommand = &cli.Command{ - Name: "list", - Aliases: []string{"l"}, - Usage: "Query async-profiler task list", - UsageText: ``, - Flags: flags.Flags(), + Name: "list", + Aliases: []string{"l"}, + Usage: "Query async-profiler task list", + UsageText: `Query async-profiler task list + +Examples: +1. Query all async-profiler tasks +$ swctl profiling asyncprofiler list --service-name=TEST_AGENT`, + Flags: flags.Flags( + flags.ServiceFlags, + []cli.Flag{ + &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.IntFlag{ + Name: "limit", + Usage: "Limit defines the number of the tasks to be returned.", + }, + }, + ), + Before: interceptor.BeforeChain( + interceptor.ParseService(true), + ), Action: func(ctx *cli.Context) error { serviceID := ctx.String("service-id") startTime := ctx.Int64("start-time") diff --git a/internal/commands/profiling/asyncprofiler/getTaskProgress.go b/internal/commands/profiling/asyncprofiler/getTaskProgress.go index 9833a34..83c643f 100644 --- a/internal/commands/profiling/asyncprofiler/getTaskProgress.go +++ b/internal/commands/profiling/asyncprofiler/getTaskProgress.go @@ -16,12 +16,12 @@ var getTaskProgressCommand = &cli.Command{ Usage: "async profiler task id.", }, }, - Usage: "Query trace profiling task log list", - UsageText: `Query trace profiling task log list + Usage: "Query async-profiler task progress", + UsageText: `Query async-profiler task progress Examples: -1. Query all trace profiling logs of task id "task-id" -$ swctl profiling trace logs --task-id=task-id`, +1. Query task progress, including task logs and successInstances and errorInstances +$ swctl-dev-37550c6-darwin-arm64 profiling asyncprofiler progress --task-id=task-id`, Action: func(ctx *cli.Context) error { taskID := ctx.String("task-id") diff --git a/pkg/graphql/profiling/asyncprofiler.go b/pkg/graphql/profiling/asyncprofiler.go index 16a3f52..9b4021e 100644 --- a/pkg/graphql/profiling/asyncprofiler.go +++ b/pkg/graphql/profiling/asyncprofiler.go @@ -44,7 +44,7 @@ func GetAsyncProfilerTaskProgress(ctx *cli.Context, taskID string) (api.AsyncPro func GetAsyncProfilerAnalyze(ctx *cli.Context, condition *api.AsyncProfilerAnalyzationRequest) (api.AsyncProfilerAnalyzation, error) { var response map[string]api.AsyncProfilerAnalyzation - request := graphql.NewRequest(assets.Read("graphqls/profiling/trace/GetAnalysis.graphql")) + request := graphql.NewRequest(assets.Read("graphqls/profiling/asyncprofiler/GetAnalysis.graphql")) request.Var("condition", condition) err := client.ExecuteQuery(ctx, request, &response) From 5694b3a3281132bbf48d5d6a47364cb5944235b0 Mon Sep 17 00:00:00 2001 From: zhengziyi0117 <91662408+zhengziyi0117@users.noreply.github.com> Date: Fri, 25 Oct 2024 10:08:09 +0800 Subject: [PATCH 04/24] Update assets/graphqls/profiling/asyncprofiler/GetTaskList.graphql Co-authored-by: mrproliu <741550557@qq.com> --- assets/graphqls/profiling/asyncprofiler/GetTaskList.graphql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/graphqls/profiling/asyncprofiler/GetTaskList.graphql b/assets/graphqls/profiling/asyncprofiler/GetTaskList.graphql index 5bac260..f62ca30 100644 --- a/assets/graphqls/profiling/asyncprofiler/GetTaskList.graphql +++ b/assets/graphqls/profiling/asyncprofiler/GetTaskList.graphql @@ -15,7 +15,7 @@ # specific language governing permissions and limitations # under the License. -query ($condition: AsyncProfilerTaskListRequest) { +query ($condition: AsyncProfilerTaskListRequest!) { result: queryAsyncProfilerTaskList(request: $condition) { errorReason tasks { From b8af7e44cb5a3abd443457a58308d2f2e09f3755 Mon Sep 17 00:00:00 2001 From: zhengziyi0117 <91662408+zhengziyi0117@users.noreply.github.com> Date: Fri, 25 Oct 2024 10:10:19 +0800 Subject: [PATCH 05/24] Update internal/commands/profiling/asyncprofiler/getAnalyze.go Co-authored-by: mrproliu <741550557@qq.com> --- internal/commands/profiling/asyncprofiler/getAnalyze.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/commands/profiling/asyncprofiler/getAnalyze.go b/internal/commands/profiling/asyncprofiler/getAnalyze.go index bf766b2..a418797 100644 --- a/internal/commands/profiling/asyncprofiler/getAnalyze.go +++ b/internal/commands/profiling/asyncprofiler/getAnalyze.go @@ -18,7 +18,7 @@ var analysisCommand = &cli.Command{ Examples: 1. Query the flame graph produced by async-profiler -$ /swctl-dev-37550c6-darwin-arm64 profiling asyncprofiler analysis --task-id=task-id --service-instance-ids=instanceIds --event=execution_sample`, +$ swctl profiling asyncprofiler analysis --task-id=task-id --service-instance-ids=instanceIds --event=execution_sample`, Flags: flags.Flags( []cli.Flag{ &cli.StringFlag{ From ecd88bd6cf4995755e1b62839ca87a81f7389cce Mon Sep 17 00:00:00 2001 From: zhengziyi Date: Fri, 25 Oct 2024 10:12:22 +0800 Subject: [PATCH 06/24] fix: license header --- .../profiling/asyncprofiler/asyncprofiler.go | 17 +++++++++++++++++ .../commands/profiling/asyncprofiler/create.go | 17 +++++++++++++++++ .../profiling/asyncprofiler/getAnalyze.go | 17 +++++++++++++++++ .../profiling/asyncprofiler/getTaskList.go | 17 +++++++++++++++++ .../profiling/asyncprofiler/getTaskProgress.go | 17 +++++++++++++++++ 5 files changed, 85 insertions(+) diff --git a/internal/commands/profiling/asyncprofiler/asyncprofiler.go b/internal/commands/profiling/asyncprofiler/asyncprofiler.go index 42328c0..296c571 100644 --- a/internal/commands/profiling/asyncprofiler/asyncprofiler.go +++ b/internal/commands/profiling/asyncprofiler/asyncprofiler.go @@ -1,3 +1,20 @@ +// 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 asyncprofiler import ( diff --git a/internal/commands/profiling/asyncprofiler/create.go b/internal/commands/profiling/asyncprofiler/create.go index 3f8c052..75d77cf 100644 --- a/internal/commands/profiling/asyncprofiler/create.go +++ b/internal/commands/profiling/asyncprofiler/create.go @@ -1,3 +1,20 @@ +// 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 asyncprofiler import ( diff --git a/internal/commands/profiling/asyncprofiler/getAnalyze.go b/internal/commands/profiling/asyncprofiler/getAnalyze.go index bf766b2..af7d86e 100644 --- a/internal/commands/profiling/asyncprofiler/getAnalyze.go +++ b/internal/commands/profiling/asyncprofiler/getAnalyze.go @@ -1,3 +1,20 @@ +// 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 asyncprofiler import ( diff --git a/internal/commands/profiling/asyncprofiler/getTaskList.go b/internal/commands/profiling/asyncprofiler/getTaskList.go index 29a4ee0..cf5ea53 100644 --- a/internal/commands/profiling/asyncprofiler/getTaskList.go +++ b/internal/commands/profiling/asyncprofiler/getTaskList.go @@ -1,3 +1,20 @@ +// 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 asyncprofiler import ( diff --git a/internal/commands/profiling/asyncprofiler/getTaskProgress.go b/internal/commands/profiling/asyncprofiler/getTaskProgress.go index 83c643f..b2834fd 100644 --- a/internal/commands/profiling/asyncprofiler/getTaskProgress.go +++ b/internal/commands/profiling/asyncprofiler/getTaskProgress.go @@ -1,3 +1,20 @@ +// 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 asyncprofiler import ( From 071d2f18a86016418b07b416515406590b261696 Mon Sep 17 00:00:00 2001 From: zhengziyi0117 <91662408+zhengziyi0117@users.noreply.github.com> Date: Fri, 25 Oct 2024 10:13:37 +0800 Subject: [PATCH 07/24] Update internal/commands/profiling/asyncprofiler/getTaskProgress.go Co-authored-by: mrproliu <741550557@qq.com> --- internal/commands/profiling/asyncprofiler/getTaskProgress.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/commands/profiling/asyncprofiler/getTaskProgress.go b/internal/commands/profiling/asyncprofiler/getTaskProgress.go index 83c643f..0925a2f 100644 --- a/internal/commands/profiling/asyncprofiler/getTaskProgress.go +++ b/internal/commands/profiling/asyncprofiler/getTaskProgress.go @@ -21,7 +21,7 @@ var getTaskProgressCommand = &cli.Command{ Examples: 1. Query task progress, including task logs and successInstances and errorInstances -$ swctl-dev-37550c6-darwin-arm64 profiling asyncprofiler progress --task-id=task-id`, +$ swctl profiling asyncprofiler progress --task-id=task-id`, Action: func(ctx *cli.Context) error { taskID := ctx.String("task-id") From 693a787b6acb26f55c743099ebd8140b6ba0764e Mon Sep 17 00:00:00 2001 From: zhengziyi Date: Fri, 25 Oct 2024 12:56:05 +0800 Subject: [PATCH 08/24] fix: pr comment --- .../profiling/asyncprofiler/asyncprofiler.go | 8 ++-- .../profiling/asyncprofiler/create.go | 36 +++++++++------ .../profiling/asyncprofiler/getAnalyze.go | 17 ++++--- .../profiling/asyncprofiler/getTaskList.go | 22 ++++++--- .../asyncprofiler/getTaskProgress.go | 7 +-- .../asyncprofiler/asyncProfilerEventType.go | 45 +++++++++++++++++++ internal/model/asyncprofiler/jfrEventType.go | 31 +++++++++++++ 7 files changed, 135 insertions(+), 31 deletions(-) create mode 100644 internal/model/asyncprofiler/asyncProfilerEventType.go create mode 100644 internal/model/asyncprofiler/jfrEventType.go diff --git a/internal/commands/profiling/asyncprofiler/asyncprofiler.go b/internal/commands/profiling/asyncprofiler/asyncprofiler.go index 296c571..c5212c4 100644 --- a/internal/commands/profiling/asyncprofiler/asyncprofiler.go +++ b/internal/commands/profiling/asyncprofiler/asyncprofiler.go @@ -22,9 +22,11 @@ import ( ) var Command = &cli.Command{ - Name: "asyncprofiler", - Usage: "async profiler related sub-command", - UsageText: `todo`, + Name: "async", + Usage: "async profiler related sub-command", + UsageText: `If your endpoint has performance issue and could not use tracing to find out what's happening, +you could try it. You could get more information +on https://skywalking.apache.org/docs/main/next/en/concepts-and-designs/profiling.`, Subcommands: []*cli.Command{ createCommand, getTaskListCommand, diff --git a/internal/commands/profiling/asyncprofiler/create.go b/internal/commands/profiling/asyncprofiler/create.go index 75d77cf..43d5068 100644 --- a/internal/commands/profiling/asyncprofiler/create.go +++ b/internal/commands/profiling/asyncprofiler/create.go @@ -20,6 +20,7 @@ package asyncprofiler import ( "github.com/apache/skywalking-cli/internal/commands/interceptor" "github.com/apache/skywalking-cli/internal/flags" + "github.com/apache/skywalking-cli/internal/model/asyncprofiler" "github.com/apache/skywalking-cli/pkg/display" "github.com/apache/skywalking-cli/pkg/display/displayable" "github.com/apache/skywalking-cli/pkg/graphql/profiling" @@ -36,11 +37,12 @@ var createCommand = &cli.Command{ Examples: 1. Create async-profiler task -$ swctl profiling asyncprofiler create --service-name=someservicename --duration=60 --events=cpu --service-instance-ids=someinstance`, +$ swctl profiling asyncprofiler create --service-name=someservicename --duration=60 --events=cpu,alloc \ + --service-instance-ids=someinstance1,someinstance2 --exec-args=interval=50ms`, Flags: flags.Flags( flags.ServiceFlags, []cli.Flag{ - &cli.StringSliceFlag{ + &cli.StringFlag{ Name: "service-instance-ids", Usage: "which instances to execute task.", Required: true, @@ -50,10 +52,13 @@ $ swctl profiling asyncprofiler create --service-name=someservicename --duration Usage: "task continuous time(second).", Required: true, }, - &cli.StringSliceFlag{ + &cli.GenericFlag{ Name: "events", Usage: "which event types this task needs to collect.", Required: true, + Value: &asyncprofiler.AsyncProfilerEventTypeEnumValue{ + Enum: query.AllAsyncProfilerEventType, + }, }, &cli.StringFlag{ Name: "exec-args", @@ -66,22 +71,27 @@ $ swctl profiling asyncprofiler create --service-name=someservicename --duration ), Action: func(ctx *cli.Context) error { serviceID := ctx.String("service-id") + instanceIds := strings.Split(ctx.String("service-instance-ids"), ",") + duration := ctx.Int("duration") + //events := strings.Split(ctx.String("events"), ",") + //eventTypes := make([]query.AsyncProfilerEventType, 0) + //for _, event := range events { + // upperCaseEvent := strings.ToUpper(event) + // eventTypes = append(eventTypes, query.AsyncProfilerEventType(upperCaseEvent)) + //} + eventTypes := ctx.Generic("events").(*asyncprofiler.AsyncProfilerEventTypeEnumValue).Selected - events := ctx.StringSlice("events") - eventTypes := make([]query.AsyncProfilerEventType, 0) - for _, event := range events { - upperCaseEvent := strings.ToUpper(event) - eventTypes = append(eventTypes, query.AsyncProfilerEventType(upperCaseEvent)) + var execArgs *string + if args := ctx.String("exec-args"); args != "" { + execArgs = &args } - execArgs := ctx.String("exec-args") - request := &query.AsyncProfilerTaskCreationRequest{ ServiceID: serviceID, - ServiceInstanceIds: ctx.StringSlice("service-instance-ids"), - Duration: ctx.Int("duration"), + ServiceInstanceIds: instanceIds, + Duration: duration, Events: eventTypes, - ExecArgs: &execArgs, + ExecArgs: execArgs, } task, err := profiling.CreateAsyncProfilerTask(ctx, request) if err != nil { diff --git a/internal/commands/profiling/asyncprofiler/getAnalyze.go b/internal/commands/profiling/asyncprofiler/getAnalyze.go index 2fc7c96..7258fc8 100644 --- a/internal/commands/profiling/asyncprofiler/getAnalyze.go +++ b/internal/commands/profiling/asyncprofiler/getAnalyze.go @@ -19,6 +19,7 @@ package asyncprofiler import ( "github.com/apache/skywalking-cli/internal/flags" + "github.com/apache/skywalking-cli/internal/model/asyncprofiler" "github.com/apache/skywalking-cli/pkg/display" "github.com/apache/skywalking-cli/pkg/display/displayable" "github.com/apache/skywalking-cli/pkg/graphql/profiling" @@ -43,25 +44,29 @@ $ swctl profiling asyncprofiler analysis --task-id=task-id --service-instance-i Usage: "async-profiler task id", Required: true, }, - &cli.StringSliceFlag{ + &cli.StringFlag{ Name: "service-instance-ids", Usage: "select which service instances' jfr files to analyze", Required: true, }, - &cli.StringFlag{ + &cli.GenericFlag{ Name: "event", Usage: "which event types this task needs to collect.", Required: true, + Value: &asyncprofiler.JFREventTypeEnumValue{ + Enum: query.AllJFREventType, + }, }, }, ), Action: func(ctx *cli.Context) error { - event := ctx.String("event") - eventType := query.JFREventType(strings.ToUpper(event)) + taskID := ctx.String("task-id") + instances := strings.Split(ctx.String("service-instance-ids"), ",") + eventType := ctx.Generic("event").(*asyncprofiler.JFREventTypeEnumValue).Selected request := &query.AsyncProfilerAnalyzationRequest{ - TaskID: ctx.String("task-id"), - InstanceIds: ctx.StringSlice("service-instance-ids"), + TaskID: taskID, + InstanceIds: instances, EventType: eventType, } diff --git a/internal/commands/profiling/asyncprofiler/getTaskList.go b/internal/commands/profiling/asyncprofiler/getTaskList.go index cf5ea53..7ecec92 100644 --- a/internal/commands/profiling/asyncprofiler/getTaskList.go +++ b/internal/commands/profiling/asyncprofiler/getTaskList.go @@ -58,14 +58,24 @@ $ swctl profiling asyncprofiler list --service-name=TEST_AGENT`, ), Action: func(ctx *cli.Context) error { serviceID := ctx.String("service-id") - startTime := ctx.Int64("start-time") - endTime := ctx.Int64("end-time") - limit := ctx.Int("limit") + var startTime *int64 + if startTimeArg := ctx.Int64("start-time"); startTimeArg != 0 { + startTime = &startTimeArg + } + var endTime *int64 + if endTimeArg := ctx.Int64("end-time"); endTimeArg != 0 { + endTime = &endTimeArg + } + var limit *int + if limitArg := ctx.Int("limit"); limitArg != 0 { + limit = &limitArg + } + request := &query.AsyncProfilerTaskListRequest{ ServiceID: serviceID, - StartTime: &startTime, - EndTime: &endTime, - Limit: &limit, + StartTime: startTime, + EndTime: endTime, + Limit: limit, } tasks, err := profiling.GetAsyncProfilerTaskList(ctx, request) diff --git a/internal/commands/profiling/asyncprofiler/getTaskProgress.go b/internal/commands/profiling/asyncprofiler/getTaskProgress.go index 0e5bf84..5b78794 100644 --- a/internal/commands/profiling/asyncprofiler/getTaskProgress.go +++ b/internal/commands/profiling/asyncprofiler/getTaskProgress.go @@ -26,11 +26,12 @@ import ( var getTaskProgressCommand = &cli.Command{ Name: "progress", - Aliases: []string{"logs", "p"}, + Aliases: []string{"p"}, Flags: []cli.Flag{ &cli.StringFlag{ - Name: "task-id", - Usage: "async profiler task id.", + Name: "task-id", + Usage: "async profiler task id.", + Required: true, }, }, Usage: "Query async-profiler task progress", diff --git a/internal/model/asyncprofiler/asyncProfilerEventType.go b/internal/model/asyncprofiler/asyncProfilerEventType.go new file mode 100644 index 0000000..7c6fea0 --- /dev/null +++ b/internal/model/asyncprofiler/asyncProfilerEventType.go @@ -0,0 +1,45 @@ +package asyncprofiler + +import ( + "fmt" + api "skywalking.apache.org/repo/goapi/query" + "strings" +) + +type AsyncProfilerEventTypeEnumValue struct { + Enum []api.AsyncProfilerEventType + Default []api.AsyncProfilerEventType + Selected []api.AsyncProfilerEventType +} + +func (e *AsyncProfilerEventTypeEnumValue) Set(value string) error { + values := strings.Split(value, ",") + types := make([]api.AsyncProfilerEventType, 0) + for _, v := range values { + for _, enum := range e.Enum { + if strings.EqualFold(enum.String(), v) { + types = append(types, enum) + break + } + } + } + + if len(types) != 0 { + e.Selected = types + return nil + } + + orders := make([]string, len(api.AllAsyncProfilerEventType)) + for i, order := range api.AllAsyncProfilerEventType { + orders[i] = order.String() + } + return fmt.Errorf("allowed analysis aggregate type are %s", strings.Join(orders, ", ")) +} + +func (e *AsyncProfilerEventTypeEnumValue) String() string { + selected := make([]string, len(e.Selected)) + for i, item := range e.Selected { + selected[i] = item.String() + } + return strings.Join(selected, ",") +} diff --git a/internal/model/asyncprofiler/jfrEventType.go b/internal/model/asyncprofiler/jfrEventType.go new file mode 100644 index 0000000..d2d8d5a --- /dev/null +++ b/internal/model/asyncprofiler/jfrEventType.go @@ -0,0 +1,31 @@ +package asyncprofiler + +import ( + "fmt" + api "skywalking.apache.org/repo/goapi/query" + "strings" +) + +type JFREventTypeEnumValue struct { + Enum []api.JFREventType + Default api.JFREventType + Selected api.JFREventType +} + +func (e *JFREventTypeEnumValue) Set(value string) error { + for _, enum := range e.Enum { + if strings.EqualFold(enum.String(), value) { + e.Selected = enum + return nil + } + } + orders := make([]string, len(api.AllJFREventType)) + for i, order := range api.AllJFREventType { + orders[i] = order.String() + } + return fmt.Errorf("allowed analysis aggregate type are %s", strings.Join(orders, ", ")) +} + +func (e *JFREventTypeEnumValue) String() string { + return e.Selected.String() +} From d4222fb0b6c862e192a1bc9079f93d7229e20adf Mon Sep 17 00:00:00 2001 From: zhengziyi Date: Fri, 25 Oct 2024 13:00:26 +0800 Subject: [PATCH 09/24] fix: license header --- .../asyncprofiler/asyncProfilerEventType.go | 17 +++++++++++++++++ internal/model/asyncprofiler/jfrEventType.go | 17 +++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/internal/model/asyncprofiler/asyncProfilerEventType.go b/internal/model/asyncprofiler/asyncProfilerEventType.go index 7c6fea0..bcc58e1 100644 --- a/internal/model/asyncprofiler/asyncProfilerEventType.go +++ b/internal/model/asyncprofiler/asyncProfilerEventType.go @@ -1,3 +1,20 @@ +// 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 asyncprofiler import ( diff --git a/internal/model/asyncprofiler/jfrEventType.go b/internal/model/asyncprofiler/jfrEventType.go index d2d8d5a..2e1110d 100644 --- a/internal/model/asyncprofiler/jfrEventType.go +++ b/internal/model/asyncprofiler/jfrEventType.go @@ -1,3 +1,20 @@ +// 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 asyncprofiler import ( From 5a38d582fdfb5f475fc498e1f3fb26860cd5ab63 Mon Sep 17 00:00:00 2001 From: zhengziyi Date: Fri, 25 Oct 2024 14:07:56 +0800 Subject: [PATCH 10/24] fix: license header --- pkg/graphql/profiling/asyncprofiler.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/pkg/graphql/profiling/asyncprofiler.go b/pkg/graphql/profiling/asyncprofiler.go index 9b4021e..7bbedd8 100644 --- a/pkg/graphql/profiling/asyncprofiler.go +++ b/pkg/graphql/profiling/asyncprofiler.go @@ -1,3 +1,20 @@ +// 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 profiling import ( From 4e144c7a5e088a11390d8eff24beb4db2b148514 Mon Sep 17 00:00:00 2001 From: zhengziyi Date: Fri, 25 Oct 2024 14:35:08 +0800 Subject: [PATCH 11/24] fix: license header --- dist/LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist/LICENSE b/dist/LICENSE index b53f5be..4bb722f 100644 --- a/dist/LICENSE +++ b/dist/LICENSE @@ -213,7 +213,7 @@ The text of each license is also included at licenses/license-[project].txt. k8s.io/utils v0.0.0-20210802155522-efc7438f0176 Apache-2.0 sigs.k8s.io/controller-runtime v0.10.0 Apache-2.0 sigs.k8s.io/structured-merge-diff/v4 v4.1.2 Apache-2.0 - skywalking.apache.org/repo/goapi v0.0.0-20240227092755-edee3273b361 Apache-2.0 + skywalking.apache.org/repo/goapi v0.0.0-20241023080050-2514649a8007 Apache-2.0 ======================================================================== BSD-2-Clause licenses From ac0314b8449279f6adb9c6580acacaa0a680e590 Mon Sep 17 00:00:00 2001 From: zhengziyi Date: Fri, 25 Oct 2024 15:29:34 +0800 Subject: [PATCH 12/24] test: golint version --- .github/workflows/CI.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/CI.yaml b/.github/workflows/CI.yaml index 423387a..d14c28d 100644 --- a/.github/workflows/CI.yaml +++ b/.github/workflows/CI.yaml @@ -92,7 +92,7 @@ jobs: - name: golangci-lint uses: golangci/golangci-lint-action@v3 with: - version: v1.50.0 + version: v6.1.1 args: --timeout 5m From d9e2e71756b348c23bafde8a95c996488cb0de14 Mon Sep 17 00:00:00 2001 From: zhengziyi Date: Fri, 25 Oct 2024 15:34:10 +0800 Subject: [PATCH 13/24] test: golint version --- .github/workflows/CI.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/CI.yaml b/.github/workflows/CI.yaml index d14c28d..1b24526 100644 --- a/.github/workflows/CI.yaml +++ b/.github/workflows/CI.yaml @@ -90,9 +90,9 @@ jobs: go-version: 1.18 - name: golangci-lint - uses: golangci/golangci-lint-action@v3 + uses: golangci/golangci-lint-action@v6 with: - version: v6.1.1 + version: v1.50.0 args: --timeout 5m From 83959330111cceb4caa47f854acc643b3054f54e Mon Sep 17 00:00:00 2001 From: zhengziyi Date: Sat, 26 Oct 2024 11:21:15 +0800 Subject: [PATCH 14/24] fix: go ci lint --- internal/commands/profiling/asyncprofiler/create.go | 9 ++------- internal/commands/profiling/asyncprofiler/getAnalyze.go | 3 ++- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/internal/commands/profiling/asyncprofiler/create.go b/internal/commands/profiling/asyncprofiler/create.go index 43d5068..bd1fa82 100644 --- a/internal/commands/profiling/asyncprofiler/create.go +++ b/internal/commands/profiling/asyncprofiler/create.go @@ -18,6 +18,8 @@ package asyncprofiler import ( + "strings" + "github.com/apache/skywalking-cli/internal/commands/interceptor" "github.com/apache/skywalking-cli/internal/flags" "github.com/apache/skywalking-cli/internal/model/asyncprofiler" @@ -26,7 +28,6 @@ import ( "github.com/apache/skywalking-cli/pkg/graphql/profiling" "github.com/urfave/cli/v2" "skywalking.apache.org/repo/goapi/query" - "strings" ) var createCommand = &cli.Command{ @@ -73,12 +74,6 @@ $ swctl profiling asyncprofiler create --service-name=someservicename --duration serviceID := ctx.String("service-id") instanceIds := strings.Split(ctx.String("service-instance-ids"), ",") duration := ctx.Int("duration") - //events := strings.Split(ctx.String("events"), ",") - //eventTypes := make([]query.AsyncProfilerEventType, 0) - //for _, event := range events { - // upperCaseEvent := strings.ToUpper(event) - // eventTypes = append(eventTypes, query.AsyncProfilerEventType(upperCaseEvent)) - //} eventTypes := ctx.Generic("events").(*asyncprofiler.AsyncProfilerEventTypeEnumValue).Selected var execArgs *string diff --git a/internal/commands/profiling/asyncprofiler/getAnalyze.go b/internal/commands/profiling/asyncprofiler/getAnalyze.go index 7258fc8..12c8d4f 100644 --- a/internal/commands/profiling/asyncprofiler/getAnalyze.go +++ b/internal/commands/profiling/asyncprofiler/getAnalyze.go @@ -18,6 +18,8 @@ package asyncprofiler import ( + "strings" + "github.com/apache/skywalking-cli/internal/flags" "github.com/apache/skywalking-cli/internal/model/asyncprofiler" "github.com/apache/skywalking-cli/pkg/display" @@ -25,7 +27,6 @@ import ( "github.com/apache/skywalking-cli/pkg/graphql/profiling" "github.com/urfave/cli/v2" query "skywalking.apache.org/repo/goapi/query" - "strings" ) var analysisCommand = &cli.Command{ From 63167d93e78cc2bf47b627089fccd4b2de4428d5 Mon Sep 17 00:00:00 2001 From: zhengziyi Date: Sat, 26 Oct 2024 13:02:04 +0800 Subject: [PATCH 15/24] feat: add instanceSlice interceptor --- internal/commands/interceptor/instance.go | 107 +++++++++++++++--- .../profiling/asyncprofiler/create.go | 18 ++- .../profiling/asyncprofiler/getAnalyze.go | 15 +-- .../profiling/asyncprofiler/getTaskList.go | 2 +- .../asyncprofiler/getTaskProgress.go | 2 +- internal/flags/instance.go | 15 +++ .../asyncprofiler/asyncProfilerEventType.go | 9 +- internal/model/asyncprofiler/jfrEventType.go | 3 +- 8 files changed, 129 insertions(+), 42 deletions(-) diff --git a/internal/commands/interceptor/instance.go b/internal/commands/interceptor/instance.go index 78f5ad1..2537fc6 100644 --- a/internal/commands/interceptor/instance.go +++ b/internal/commands/interceptor/instance.go @@ -26,10 +26,12 @@ import ( ) const ( - instanceIDFlagName = "instance-id" - instanceNameFlagName = "instance-name" - destInstanceIDFlagName = "dest-instance-id" - destInstanceNameFlagName = "dest-instance-name" + instanceIDFlagName = "instance-id" + instanceNameFlagName = "instance-name" + destInstanceIDFlagName = "dest-instance-id" + destInstanceNameFlagName = "dest-instance-name" + InstanceIDSliceFlagName = "instance-id-slice" + instanceNameSliceFlagName = "instance-name-slice" ) // ParseInstance parses the service instance id or service instance name, @@ -44,6 +46,18 @@ func ParseInstance(required bool) func(*cli.Context) error { } } +// ParseInstanceSlice parses the service instance id slice or service instance name slice, +// and converts the present one to the missing one. +// See flags.InstanceSliceFlags. +func ParseInstanceSlice(required bool) func(*cli.Context) error { + return func(ctx *cli.Context) error { + if err := ParseService(required)(ctx); err != nil { + return err + } + return parseInstanceSlice(required, InstanceIDSliceFlagName, instanceNameSliceFlagName, 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. @@ -72,26 +86,85 @@ func parseInstance(required bool, idFlagName, nameFlagName, serviceIDFlagName st return nil } - if id != "" { - parts := strings.Split(id, "_") - if len(parts) != 2 { - return fmt.Errorf("invalid instance id, cannot be splitted into 2 parts. %v", id) + id, name, err := encode(serviceID, nameFlagName, id, name) + if err != nil { + return err + } + + if err := ctx.Set(idFlagName, id); err != nil { + return err + } + return ctx.Set(nameFlagName, name) + } +} + +func parseInstanceSlice(required bool, idSliceFlagName, nameSliceFlagName, serviceIDFlagName string) func(*cli.Context) error { + return func(ctx *cli.Context) error { + idsArg := ctx.String(idSliceFlagName) + namesArgs := ctx.String(nameSliceFlagName) + serviceID := ctx.String(serviceIDFlagName) + + if idsArg == "" && namesArgs == "" { + if required { + return fmt.Errorf(`either flags "--%s" or "--%s" must be given`, idSliceFlagName, nameSliceFlagName) + } + return nil + } + + ids := strings.Split(idsArg, ",") + names := strings.Split(namesArgs, ",") + var sliceSize int + if l := len(ids); idsArg != "" && l != 0 { + sliceSize = l + } else { + sliceSize = len(names) + } + instanceIDSlice := make([]string, sliceSize) + instanceNameSlice := make([]string, sliceSize) + for i := 0; i < sliceSize; i++ { + id := "" + name := "" + if len(ids) > i { + id = ids[i] + } + if len(names) > i { + name = names[i] } - s, err := base64.StdEncoding.DecodeString(parts[1]) + + id, name, err := encode(serviceID, nameSliceFlagName, id, name) if err != nil { return err } - name = string(s) - } else 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) + + instanceIDSlice[i] = id + instanceNameSlice[i] = name } - if err := ctx.Set(idFlagName, id); err != nil { + instanceIDSliceString := strings.Join(instanceIDSlice, ",") + instanceNameSliceString := strings.Join(instanceNameSlice, ",") + if err := ctx.Set(idSliceFlagName, instanceIDSliceString); err != nil { return err } - return ctx.Set(nameFlagName, name) + return ctx.Set(nameSliceFlagName, instanceNameSliceString) + } +} + +func encode(serviceID, nameFlagName, id, name string) (string, string, error) { + 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) + } else 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) } + return id, name, nil } diff --git a/internal/commands/profiling/asyncprofiler/create.go b/internal/commands/profiling/asyncprofiler/create.go index bd1fa82..7ff403b 100644 --- a/internal/commands/profiling/asyncprofiler/create.go +++ b/internal/commands/profiling/asyncprofiler/create.go @@ -38,16 +38,12 @@ var createCommand = &cli.Command{ Examples: 1. Create async-profiler task -$ swctl profiling asyncprofiler create --service-name=someservicename --duration=60 --events=cpu,alloc \ - --service-instance-ids=someinstance1,someinstance2 --exec-args=interval=50ms`, +$ swctl profiling async create --service-name=service-name --duration=60 --events=cpu,alloc \ + --instance-name-slice=instance-name1,instance-name2 --exec-args=interval=50ms`, Flags: flags.Flags( flags.ServiceFlags, + flags.InstanceSliceFlags, []cli.Flag{ - &cli.StringFlag{ - Name: "service-instance-ids", - Usage: "which instances to execute task.", - Required: true, - }, &cli.IntFlag{ Name: "duration", Usage: "task continuous time(second).", @@ -57,7 +53,7 @@ $ swctl profiling asyncprofiler create --service-name=someservicename --duration Name: "events", Usage: "which event types this task needs to collect.", Required: true, - Value: &asyncprofiler.AsyncProfilerEventTypeEnumValue{ + Value: &asyncprofiler.ProfilerEventTypeEnumValue{ Enum: query.AllAsyncProfilerEventType, }, }, @@ -68,13 +64,13 @@ $ swctl profiling asyncprofiler create --service-name=someservicename --duration }, ), Before: interceptor.BeforeChain( - interceptor.ParseService(false), + interceptor.ParseInstanceSlice(true), ), Action: func(ctx *cli.Context) error { serviceID := ctx.String("service-id") - instanceIds := strings.Split(ctx.String("service-instance-ids"), ",") + instanceIds := strings.Split(ctx.String("instance-id-slice"), ",") duration := ctx.Int("duration") - eventTypes := ctx.Generic("events").(*asyncprofiler.AsyncProfilerEventTypeEnumValue).Selected + eventTypes := ctx.Generic("events").(*asyncprofiler.ProfilerEventTypeEnumValue).Selected var execArgs *string if args := ctx.String("exec-args"); args != "" { diff --git a/internal/commands/profiling/asyncprofiler/getAnalyze.go b/internal/commands/profiling/asyncprofiler/getAnalyze.go index 12c8d4f..382f2ed 100644 --- a/internal/commands/profiling/asyncprofiler/getAnalyze.go +++ b/internal/commands/profiling/asyncprofiler/getAnalyze.go @@ -20,6 +20,7 @@ package asyncprofiler import ( "strings" + "github.com/apache/skywalking-cli/internal/commands/interceptor" "github.com/apache/skywalking-cli/internal/flags" "github.com/apache/skywalking-cli/internal/model/asyncprofiler" "github.com/apache/skywalking-cli/pkg/display" @@ -37,19 +38,16 @@ var analysisCommand = &cli.Command{ Examples: 1. Query the flame graph produced by async-profiler -$ swctl profiling asyncprofiler analysis --task-id=task-id --service-instance-ids=instanceIds --event=execution_sample`, +$ swctl profiling async analysis --service-name=service-name --task-id=task-id --service-instance-ids=instance-name1,instance-name2 --event=execution_sample`, Flags: flags.Flags( + flags.ServiceFlags, + flags.InstanceSliceFlags, []cli.Flag{ &cli.StringFlag{ Name: "task-id", Usage: "async-profiler task id", Required: true, }, - &cli.StringFlag{ - Name: "service-instance-ids", - Usage: "select which service instances' jfr files to analyze", - Required: true, - }, &cli.GenericFlag{ Name: "event", Usage: "which event types this task needs to collect.", @@ -60,9 +58,12 @@ $ swctl profiling asyncprofiler analysis --task-id=task-id --service-instance-i }, }, ), + Before: interceptor.BeforeChain( + interceptor.ParseInstanceSlice(true), + ), Action: func(ctx *cli.Context) error { taskID := ctx.String("task-id") - instances := strings.Split(ctx.String("service-instance-ids"), ",") + instances := strings.Split(ctx.String("instance-id-slice"), ",") eventType := ctx.Generic("event").(*asyncprofiler.JFREventTypeEnumValue).Selected request := &query.AsyncProfilerAnalyzationRequest{ diff --git a/internal/commands/profiling/asyncprofiler/getTaskList.go b/internal/commands/profiling/asyncprofiler/getTaskList.go index 7ecec92..a480ef5 100644 --- a/internal/commands/profiling/asyncprofiler/getTaskList.go +++ b/internal/commands/profiling/asyncprofiler/getTaskList.go @@ -35,7 +35,7 @@ var getTaskListCommand = &cli.Command{ Examples: 1. Query all async-profiler tasks -$ swctl profiling asyncprofiler list --service-name=TEST_AGENT`, +$ swctl profiling async list --service-name=service-name`, Flags: flags.Flags( flags.ServiceFlags, []cli.Flag{ diff --git a/internal/commands/profiling/asyncprofiler/getTaskProgress.go b/internal/commands/profiling/asyncprofiler/getTaskProgress.go index 5b78794..b7a3e48 100644 --- a/internal/commands/profiling/asyncprofiler/getTaskProgress.go +++ b/internal/commands/profiling/asyncprofiler/getTaskProgress.go @@ -39,7 +39,7 @@ var getTaskProgressCommand = &cli.Command{ Examples: 1. Query task progress, including task logs and successInstances and errorInstances -$ swctl profiling asyncprofiler progress --task-id=task-id`, +$ swctl profiling async progress --task-id=task-id`, Action: func(ctx *cli.Context) error { taskID := ctx.String("task-id") diff --git a/internal/flags/instance.go b/internal/flags/instance.go index 0a5aa44..85f4248 100644 --- a/internal/flags/instance.go +++ b/internal/flags/instance.go @@ -52,3 +52,18 @@ var InstanceRelationFlags = append( Required: false, }, ) + +// InstanceSliceFlags take either service instance id list or service instance name list as input, +// and transform to the other one. +var InstanceSliceFlags = []cli.Flag{ + &cli.StringFlag{ + Name: "instance-id-slice", + Usage: "`instance id slice`, if you don't have instance id slice, use `--instances-name` instead", + Required: false, + }, + &cli.StringFlag{ + Name: "instance-name-slice", + Usage: "`instance name slice`, if you already have instance id slice, prefer to use `--instances-id`", + Required: false, + }, +} diff --git a/internal/model/asyncprofiler/asyncProfilerEventType.go b/internal/model/asyncprofiler/asyncProfilerEventType.go index bcc58e1..da3db0c 100644 --- a/internal/model/asyncprofiler/asyncProfilerEventType.go +++ b/internal/model/asyncprofiler/asyncProfilerEventType.go @@ -19,17 +19,18 @@ package asyncprofiler import ( "fmt" - api "skywalking.apache.org/repo/goapi/query" "strings" + + api "skywalking.apache.org/repo/goapi/query" ) -type AsyncProfilerEventTypeEnumValue struct { +type ProfilerEventTypeEnumValue struct { Enum []api.AsyncProfilerEventType Default []api.AsyncProfilerEventType Selected []api.AsyncProfilerEventType } -func (e *AsyncProfilerEventTypeEnumValue) Set(value string) error { +func (e *ProfilerEventTypeEnumValue) Set(value string) error { values := strings.Split(value, ",") types := make([]api.AsyncProfilerEventType, 0) for _, v := range values { @@ -53,7 +54,7 @@ func (e *AsyncProfilerEventTypeEnumValue) Set(value string) error { return fmt.Errorf("allowed analysis aggregate type are %s", strings.Join(orders, ", ")) } -func (e *AsyncProfilerEventTypeEnumValue) String() string { +func (e *ProfilerEventTypeEnumValue) String() string { selected := make([]string, len(e.Selected)) for i, item := range e.Selected { selected[i] = item.String() diff --git a/internal/model/asyncprofiler/jfrEventType.go b/internal/model/asyncprofiler/jfrEventType.go index 2e1110d..a216872 100644 --- a/internal/model/asyncprofiler/jfrEventType.go +++ b/internal/model/asyncprofiler/jfrEventType.go @@ -19,8 +19,9 @@ package asyncprofiler import ( "fmt" - api "skywalking.apache.org/repo/goapi/query" "strings" + + api "skywalking.apache.org/repo/goapi/query" ) type JFREventTypeEnumValue struct { From 3eedb053110ccc26bf12eef9450eae221d9090ea Mon Sep 17 00:00:00 2001 From: zhengziyi Date: Sat, 26 Oct 2024 13:03:57 +0800 Subject: [PATCH 16/24] feat: update CHANGES.md --- CHANGES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index a7323dc..410cea7 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -7,6 +7,8 @@ Release Notes. ### Features +* add the sub-command `profiling async` for async-profiler query API by @zhengziyi0117 in https://github.com/apache/skywalking-cli/pull/203 + ### Bug Fixes 0.14.0 From 8a00dee381aaa4dae8fb6358b081ab03ebabd087 Mon Sep 17 00:00:00 2001 From: Megrez Lu Date: Sat, 26 Oct 2024 16:08:22 +0800 Subject: [PATCH 17/24] fix style and lint --- internal/commands/profiling/asyncprofiler/create.go | 5 +++-- internal/commands/profiling/asyncprofiler/getAnalyze.go | 8 +++++--- internal/commands/profiling/asyncprofiler/getTaskList.go | 5 +++-- .../commands/profiling/asyncprofiler/getTaskProgress.go | 3 ++- internal/commands/profiling/profiling.go | 2 +- pkg/graphql/profiling/asyncprofiler.go | 5 +++-- 6 files changed, 17 insertions(+), 11 deletions(-) diff --git a/internal/commands/profiling/asyncprofiler/create.go b/internal/commands/profiling/asyncprofiler/create.go index 7ff403b..eff6af1 100644 --- a/internal/commands/profiling/asyncprofiler/create.go +++ b/internal/commands/profiling/asyncprofiler/create.go @@ -20,14 +20,15 @@ package asyncprofiler 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/asyncprofiler" "github.com/apache/skywalking-cli/pkg/display" "github.com/apache/skywalking-cli/pkg/display/displayable" "github.com/apache/skywalking-cli/pkg/graphql/profiling" - "github.com/urfave/cli/v2" - "skywalking.apache.org/repo/goapi/query" ) var createCommand = &cli.Command{ diff --git a/internal/commands/profiling/asyncprofiler/getAnalyze.go b/internal/commands/profiling/asyncprofiler/getAnalyze.go index 382f2ed..09c0050 100644 --- a/internal/commands/profiling/asyncprofiler/getAnalyze.go +++ b/internal/commands/profiling/asyncprofiler/getAnalyze.go @@ -20,14 +20,15 @@ package asyncprofiler 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/asyncprofiler" "github.com/apache/skywalking-cli/pkg/display" "github.com/apache/skywalking-cli/pkg/display/displayable" "github.com/apache/skywalking-cli/pkg/graphql/profiling" - "github.com/urfave/cli/v2" - query "skywalking.apache.org/repo/goapi/query" ) var analysisCommand = &cli.Command{ @@ -38,7 +39,8 @@ var analysisCommand = &cli.Command{ Examples: 1. Query the flame graph produced by async-profiler -$ swctl profiling async analysis --service-name=service-name --task-id=task-id --service-instance-ids=instance-name1,instance-name2 --event=execution_sample`, +$ swctl profiling async analysis --service-name=service-name --task-id=task-id \ + --service-instance-ids=instance-name1,instance-name2 --event=execution_sample`, Flags: flags.Flags( flags.ServiceFlags, flags.InstanceSliceFlags, diff --git a/internal/commands/profiling/asyncprofiler/getTaskList.go b/internal/commands/profiling/asyncprofiler/getTaskList.go index a480ef5..067a3e2 100644 --- a/internal/commands/profiling/asyncprofiler/getTaskList.go +++ b/internal/commands/profiling/asyncprofiler/getTaskList.go @@ -18,13 +18,14 @@ package asyncprofiler import ( + "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" - "github.com/urfave/cli/v2" - "skywalking.apache.org/repo/goapi/query" ) var getTaskListCommand = &cli.Command{ diff --git a/internal/commands/profiling/asyncprofiler/getTaskProgress.go b/internal/commands/profiling/asyncprofiler/getTaskProgress.go index b7a3e48..3943e84 100644 --- a/internal/commands/profiling/asyncprofiler/getTaskProgress.go +++ b/internal/commands/profiling/asyncprofiler/getTaskProgress.go @@ -18,10 +18,11 @@ package asyncprofiler import ( + "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/profiling" - "github.com/urfave/cli/v2" ) var getTaskProgressCommand = &cli.Command{ diff --git a/internal/commands/profiling/profiling.go b/internal/commands/profiling/profiling.go index ba936f8..54144b6 100644 --- a/internal/commands/profiling/profiling.go +++ b/internal/commands/profiling/profiling.go @@ -18,9 +18,9 @@ package profiling import ( - "github.com/apache/skywalking-cli/internal/commands/profiling/asyncprofiler" "github.com/urfave/cli/v2" + "github.com/apache/skywalking-cli/internal/commands/profiling/asyncprofiler" "github.com/apache/skywalking-cli/internal/commands/profiling/continuous" "github.com/apache/skywalking-cli/internal/commands/profiling/ebpf" "github.com/apache/skywalking-cli/internal/commands/profiling/trace" diff --git a/pkg/graphql/profiling/asyncprofiler.go b/pkg/graphql/profiling/asyncprofiler.go index 7bbedd8..5db697f 100644 --- a/pkg/graphql/profiling/asyncprofiler.go +++ b/pkg/graphql/profiling/asyncprofiler.go @@ -18,11 +18,12 @@ package profiling import ( - "github.com/apache/skywalking-cli/assets" - "github.com/apache/skywalking-cli/pkg/graphql/client" "github.com/machinebox/graphql" "github.com/urfave/cli/v2" api "skywalking.apache.org/repo/goapi/query" + + "github.com/apache/skywalking-cli/assets" + "github.com/apache/skywalking-cli/pkg/graphql/client" ) func CreateAsyncProfilerTask(ctx *cli.Context, condition *api.AsyncProfilerTaskCreationRequest) (api.AsyncProfilerTaskCreationResult, error) { From 0f6665c80ce19e03faa9b6619698123f74b17735 Mon Sep 17 00:00:00 2001 From: zhengziyi Date: Sat, 26 Oct 2024 16:14:39 +0800 Subject: [PATCH 18/24] fix: golint --- internal/commands/interceptor/instance.go | 2 +- internal/commands/profiling/asyncprofiler/asyncprofiler.go | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/internal/commands/interceptor/instance.go b/internal/commands/interceptor/instance.go index 2537fc6..7335ae8 100644 --- a/internal/commands/interceptor/instance.go +++ b/internal/commands/interceptor/instance.go @@ -149,7 +149,7 @@ func parseInstanceSlice(required bool, idSliceFlagName, nameSliceFlagName, servi } } -func encode(serviceID, nameFlagName, id, name string) (string, string, error) { +func encode(serviceID, nameFlagName, id, name string) (encodedId, encodedName string, err error) { if id != "" { parts := strings.Split(id, "_") if len(parts) != 2 { diff --git a/internal/commands/profiling/asyncprofiler/asyncprofiler.go b/internal/commands/profiling/asyncprofiler/asyncprofiler.go index c5212c4..e68086c 100644 --- a/internal/commands/profiling/asyncprofiler/asyncprofiler.go +++ b/internal/commands/profiling/asyncprofiler/asyncprofiler.go @@ -17,9 +17,7 @@ package asyncprofiler -import ( - "github.com/urfave/cli/v2" -) +import "github.com/urfave/cli/v2" var Command = &cli.Command{ Name: "async", From 5f9bdc04b60b1aed7f88286cdb7e629b0cad3f2a Mon Sep 17 00:00:00 2001 From: zhengziyi Date: Sat, 26 Oct 2024 16:18:43 +0800 Subject: [PATCH 19/24] fix: golint --- internal/commands/interceptor/instance.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/commands/interceptor/instance.go b/internal/commands/interceptor/instance.go index 7335ae8..87cffdb 100644 --- a/internal/commands/interceptor/instance.go +++ b/internal/commands/interceptor/instance.go @@ -149,7 +149,7 @@ func parseInstanceSlice(required bool, idSliceFlagName, nameSliceFlagName, servi } } -func encode(serviceID, nameFlagName, id, name string) (encodedId, encodedName string, err error) { +func encode(serviceID, nameFlagName, id, name string) (encodedID, encodedName string, err error) { if id != "" { parts := strings.Split(id, "_") if len(parts) != 2 { From ba0d3663a9bfe57fdf039f7084f143f9f40c3e6e Mon Sep 17 00:00:00 2001 From: zhengziyi Date: Sun, 27 Oct 2024 22:00:26 +0800 Subject: [PATCH 20/24] fix: command test ci --- test/cases/basic/expected/dependency-endpoint.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/test/cases/basic/expected/dependency-endpoint.yml b/test/cases/basic/expected/dependency-endpoint.yml index b8d11d0..e0f4b75 100644 --- a/test/cases/basic/expected/dependency-endpoint.yml +++ b/test/cases/basic/expected/dependency-endpoint.yml @@ -28,6 +28,7 @@ nodes: serviceid: {{ b64enc "consumer" }}.1 servicename: consumer {{- end }} +debuggingtrace: {} calls: {{- contains .calls }} - source: {{ b64enc "consumer" }}.1_{{ b64enc "/users" }} From c1b95196137f1eb9141ffb9eeae48ff3e7e4c4e9 Mon Sep 17 00:00:00 2001 From: zhengziyi Date: Mon, 28 Oct 2024 00:04:22 +0800 Subject: [PATCH 21/24] fix: arguments name --- internal/commands/interceptor/instance.go | 20 +++++++++---------- .../profiling/asyncprofiler/create.go | 8 ++++---- .../profiling/asyncprofiler/getAnalyze.go | 8 ++++---- internal/flags/instance.go | 12 +++++------ 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/internal/commands/interceptor/instance.go b/internal/commands/interceptor/instance.go index 87cffdb..91f7617 100644 --- a/internal/commands/interceptor/instance.go +++ b/internal/commands/interceptor/instance.go @@ -46,15 +46,15 @@ func ParseInstance(required bool) func(*cli.Context) error { } } -// ParseInstanceSlice parses the service instance id slice or service instance name slice, +// ParseInstanceList parses the service instance id slice or service instance name slice, // and converts the present one to the missing one. // See flags.InstanceSliceFlags. -func ParseInstanceSlice(required bool) func(*cli.Context) error { +func ParseInstanceList(required bool) func(*cli.Context) error { return func(ctx *cli.Context) error { if err := ParseService(required)(ctx); err != nil { return err } - return parseInstanceSlice(required, InstanceIDSliceFlagName, instanceNameSliceFlagName, serviceIDFlagName)(ctx) + return parseInstanceList(required, InstanceIDSliceFlagName, instanceNameSliceFlagName, serviceIDFlagName)(ctx) } } @@ -98,15 +98,15 @@ func parseInstance(required bool, idFlagName, nameFlagName, serviceIDFlagName st } } -func parseInstanceSlice(required bool, idSliceFlagName, nameSliceFlagName, serviceIDFlagName string) func(*cli.Context) error { +func parseInstanceList(required bool, idListFlagName, nameListFlagName, serviceIDFlagName string) func(*cli.Context) error { return func(ctx *cli.Context) error { - idsArg := ctx.String(idSliceFlagName) - namesArgs := ctx.String(nameSliceFlagName) + idsArg := ctx.String(idListFlagName) + namesArgs := ctx.String(nameListFlagName) serviceID := ctx.String(serviceIDFlagName) if idsArg == "" && namesArgs == "" { if required { - return fmt.Errorf(`either flags "--%s" or "--%s" must be given`, idSliceFlagName, nameSliceFlagName) + return fmt.Errorf(`either flags "--%s" or "--%s" must be given`, idListFlagName, nameListFlagName) } return nil } @@ -131,7 +131,7 @@ func parseInstanceSlice(required bool, idSliceFlagName, nameSliceFlagName, servi name = names[i] } - id, name, err := encode(serviceID, nameSliceFlagName, id, name) + id, name, err := encode(serviceID, nameListFlagName, id, name) if err != nil { return err } @@ -142,10 +142,10 @@ func parseInstanceSlice(required bool, idSliceFlagName, nameSliceFlagName, servi instanceIDSliceString := strings.Join(instanceIDSlice, ",") instanceNameSliceString := strings.Join(instanceNameSlice, ",") - if err := ctx.Set(idSliceFlagName, instanceIDSliceString); err != nil { + if err := ctx.Set(idListFlagName, instanceIDSliceString); err != nil { return err } - return ctx.Set(nameSliceFlagName, instanceNameSliceString) + return ctx.Set(nameListFlagName, instanceNameSliceString) } } diff --git a/internal/commands/profiling/asyncprofiler/create.go b/internal/commands/profiling/asyncprofiler/create.go index eff6af1..1d21938 100644 --- a/internal/commands/profiling/asyncprofiler/create.go +++ b/internal/commands/profiling/asyncprofiler/create.go @@ -40,10 +40,10 @@ var createCommand = &cli.Command{ Examples: 1. Create async-profiler task $ swctl profiling async create --service-name=service-name --duration=60 --events=cpu,alloc \ - --instance-name-slice=instance-name1,instance-name2 --exec-args=interval=50ms`, + --instance-name-list=instance-name1,instance-name2 --exec-args=interval=50ms`, Flags: flags.Flags( flags.ServiceFlags, - flags.InstanceSliceFlags, + flags.InstanceListFlags, []cli.Flag{ &cli.IntFlag{ Name: "duration", @@ -65,11 +65,11 @@ $ swctl profiling async create --service-name=service-name --duration=60 --event }, ), Before: interceptor.BeforeChain( - interceptor.ParseInstanceSlice(true), + interceptor.ParseInstanceList(true), ), Action: func(ctx *cli.Context) error { serviceID := ctx.String("service-id") - instanceIds := strings.Split(ctx.String("instance-id-slice"), ",") + instanceIds := strings.Split(ctx.String("instance-id-list"), ",") duration := ctx.Int("duration") eventTypes := ctx.Generic("events").(*asyncprofiler.ProfilerEventTypeEnumValue).Selected diff --git a/internal/commands/profiling/asyncprofiler/getAnalyze.go b/internal/commands/profiling/asyncprofiler/getAnalyze.go index 09c0050..c1b0387 100644 --- a/internal/commands/profiling/asyncprofiler/getAnalyze.go +++ b/internal/commands/profiling/asyncprofiler/getAnalyze.go @@ -40,10 +40,10 @@ var analysisCommand = &cli.Command{ Examples: 1. Query the flame graph produced by async-profiler $ swctl profiling async analysis --service-name=service-name --task-id=task-id \ - --service-instance-ids=instance-name1,instance-name2 --event=execution_sample`, + --instance-name-list=instance-name1,instance-name2 --event=execution_sample`, Flags: flags.Flags( flags.ServiceFlags, - flags.InstanceSliceFlags, + flags.InstanceListFlags, []cli.Flag{ &cli.StringFlag{ Name: "task-id", @@ -61,11 +61,11 @@ $ swctl profiling async analysis --service-name=service-name --task-id=task-id \ }, ), Before: interceptor.BeforeChain( - interceptor.ParseInstanceSlice(true), + interceptor.ParseInstanceList(true), ), Action: func(ctx *cli.Context) error { taskID := ctx.String("task-id") - instances := strings.Split(ctx.String("instance-id-slice"), ",") + instances := strings.Split(ctx.String("instance-id-list"), ",") eventType := ctx.Generic("event").(*asyncprofiler.JFREventTypeEnumValue).Selected request := &query.AsyncProfilerAnalyzationRequest{ diff --git a/internal/flags/instance.go b/internal/flags/instance.go index 85f4248..af3b254 100644 --- a/internal/flags/instance.go +++ b/internal/flags/instance.go @@ -53,17 +53,17 @@ var InstanceRelationFlags = append( }, ) -// InstanceSliceFlags take either service instance id list or service instance name list as input, +// InstanceListFlags take either service instance id list or service instance name list as input, // and transform to the other one. -var InstanceSliceFlags = []cli.Flag{ +var InstanceListFlags = []cli.Flag{ &cli.StringFlag{ - Name: "instance-id-slice", - Usage: "`instance id slice`, if you don't have instance id slice, use `--instances-name` instead", + Name: "instance-id-list", + Usage: "`instance id list`, if you don't have instance id list, use `--instances-name` instead", Required: false, }, &cli.StringFlag{ - Name: "instance-name-slice", - Usage: "`instance name slice`, if you already have instance id slice, prefer to use `--instances-id`", + Name: "instance-name-list", + Usage: "`instance name list`, if you already have instance id list, prefer to use `--instances-id`", Required: false, }, } From a20535ef0cd9f3beb189b96c7f5fa33a7f2aecc2 Mon Sep 17 00:00:00 2001 From: zhengziyi Date: Mon, 28 Oct 2024 00:09:43 +0800 Subject: [PATCH 22/24] fix: arguments name --- internal/commands/interceptor/instance.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/internal/commands/interceptor/instance.go b/internal/commands/interceptor/instance.go index 91f7617..d381717 100644 --- a/internal/commands/interceptor/instance.go +++ b/internal/commands/interceptor/instance.go @@ -26,12 +26,12 @@ import ( ) const ( - instanceIDFlagName = "instance-id" - instanceNameFlagName = "instance-name" - destInstanceIDFlagName = "dest-instance-id" - destInstanceNameFlagName = "dest-instance-name" - InstanceIDSliceFlagName = "instance-id-slice" - instanceNameSliceFlagName = "instance-name-slice" + instanceIDFlagName = "instance-id" + instanceNameFlagName = "instance-name" + destInstanceIDFlagName = "dest-instance-id" + destInstanceNameFlagName = "dest-instance-name" + InstanceIDListFlagName = "instance-id-list" + instanceNameListFlagName = "instance-name-list" ) // ParseInstance parses the service instance id or service instance name, @@ -54,7 +54,7 @@ func ParseInstanceList(required bool) func(*cli.Context) error { if err := ParseService(required)(ctx); err != nil { return err } - return parseInstanceList(required, InstanceIDSliceFlagName, instanceNameSliceFlagName, serviceIDFlagName)(ctx) + return parseInstanceList(required, InstanceIDListFlagName, instanceNameListFlagName, serviceIDFlagName)(ctx) } } From b4c5cf785dc25ac74f36ae5de04528e8ad884573 Mon Sep 17 00:00:00 2001 From: Megrez Lu Date: Mon, 28 Oct 2024 09:37:10 +0800 Subject: [PATCH 23/24] fix dependency test cases --- test/cases/basic/expected/dependency-endpoint.yml | 2 +- test/cases/basic/expected/dependency-instance.yml | 1 + test/cases/basic/expected/dependency-service.yml | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/test/cases/basic/expected/dependency-endpoint.yml b/test/cases/basic/expected/dependency-endpoint.yml index e0f4b75..e2d8453 100644 --- a/test/cases/basic/expected/dependency-endpoint.yml +++ b/test/cases/basic/expected/dependency-endpoint.yml @@ -28,7 +28,7 @@ nodes: serviceid: {{ b64enc "consumer" }}.1 servicename: consumer {{- end }} -debuggingtrace: {} +debuggingtrace: null calls: {{- contains .calls }} - source: {{ b64enc "consumer" }}.1_{{ b64enc "/users" }} diff --git a/test/cases/basic/expected/dependency-instance.yml b/test/cases/basic/expected/dependency-instance.yml index bfa7f05..33dd279 100644 --- a/test/cases/basic/expected/dependency-instance.yml +++ b/test/cases/basic/expected/dependency-instance.yml @@ -41,3 +41,4 @@ calls: - CLIENT {{- end }} {{- end }} +debuggingtrace: null diff --git a/test/cases/basic/expected/dependency-service.yml b/test/cases/basic/expected/dependency-service.yml index 6bf530f..41c789e 100644 --- a/test/cases/basic/expected/dependency-service.yml +++ b/test/cases/basic/expected/dependency-service.yml @@ -41,3 +41,4 @@ calls: - CLIENT - SERVER {{- end }} +debuggingtrace: null \ No newline at end of file From 9593efc36919d00a88f28265b0d7acd0150aefda Mon Sep 17 00:00:00 2001 From: Megrez Lu Date: Mon, 28 Oct 2024 09:55:01 +0800 Subject: [PATCH 24/24] fix trace cases --- test/cases/basic/expected/trace-users-detail.yml | 1 + test/cases/basic/expected/traces-list.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/test/cases/basic/expected/trace-users-detail.yml b/test/cases/basic/expected/trace-users-detail.yml index ab8b888..a286162 100644 --- a/test/cases/basic/expected/trace-users-detail.yml +++ b/test/cases/basic/expected/trace-users-detail.yml @@ -100,3 +100,4 @@ spans: logs: [ ] attachedevents: [] {{- end }} +debuggingtrace: null \ No newline at end of file diff --git a/test/cases/basic/expected/traces-list.yml b/test/cases/basic/expected/traces-list.yml index 3150040..a51cb7f 100644 --- a/test/cases/basic/expected/traces-list.yml +++ b/test/cases/basic/expected/traces-list.yml @@ -24,3 +24,4 @@ traces: traceids: - {{ index .traceids 0 }} {{- end }} +debuggingtrace: null \ No newline at end of file