diff --git a/CHANGES.md b/CHANGES.md index ca7a1075..31b9d691 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -17,6 +17,9 @@ Release Notes. - [Breaking Change] Remove `total` field in `trace list` and `logs list` commands.(#152) - [Breaking Change] Remove `total` field in `event list`, `browser logs list`, `alarm list` commands.(#153) - Add `aggregate` flag in `profiling ebpf analysis` commands.(#154) +- Add the sub-command `profiling ebpf create network` and `profiling ebpf keep network` to create and keep the network eBPF profiling task.(#158) +- Add the sub-command `dependency process` to query the process relation.(#158) +- Support query the metrics of process relation.(#158) 0.10.0 ------------------ diff --git a/assets/graphqls/dependency/ProcessTopology.graphql b/assets/graphqls/dependency/ProcessTopology.graphql new file mode 100644 index 00000000..ec2dd0da --- /dev/null +++ b/assets/graphqls/dependency/ProcessTopology.graphql @@ -0,0 +1,36 @@ +# 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 ($serviceInstanceId: ID!, $duration: Duration!){ + result: getProcessTopology(serviceInstanceId: $serviceInstanceId, duration: $duration) { + nodes { + id + serviceId + serviceName + serviceInstanceId + serviceInstanceName + name + isReal + } + calls { + source + target + id + detectPoints + } + } +} \ No newline at end of file diff --git a/assets/graphqls/profiling/ebpf/CreateEBPFNetworkProfilingTask.graphql b/assets/graphqls/profiling/ebpf/CreateEBPFNetworkProfilingTask.graphql new file mode 100644 index 00000000..e3b45a68 --- /dev/null +++ b/assets/graphqls/profiling/ebpf/CreateEBPFNetworkProfilingTask.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 ($request: EBPFProfilingNetworkTaskRequest!){ + result: createEBPFNetworkProfiling(request: $request) { + status + id + errorReason + } +} \ No newline at end of file diff --git a/assets/graphqls/profiling/ebpf/KeepNetworkProfilingTask.graphql b/assets/graphqls/profiling/ebpf/KeepNetworkProfilingTask.graphql new file mode 100644 index 00000000..83525bc4 --- /dev/null +++ b/assets/graphqls/profiling/ebpf/KeepNetworkProfilingTask.graphql @@ -0,0 +1,23 @@ +# Licensed to Apache Software Foundation (ASF) under one or more contributor +# license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright +# ownership. Apache Software Foundation (ASF) licenses this file to you under +# the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +mutation ($taskId: ID!){ + result: keepEBPFNetworkProfiling(taskId: $taskId) { + status + errorReason + } +} \ No newline at end of file diff --git a/go.mod b/go.mod index 8efc146b..89b19608 100644 --- a/go.mod +++ b/go.mod @@ -24,5 +24,5 @@ require ( gopkg.in/yaml.v2 v2.4.0 k8s.io/apimachinery v0.21.1 sigs.k8s.io/controller-runtime v0.7.0 - skywalking.apache.org/repo/goapi v0.0.0-20220519102801-965f76fbe437 + skywalking.apache.org/repo/goapi v0.0.0-20220714130828-0d56d1f4c592 ) diff --git a/go.sum b/go.sum index d5540697..009af6f5 100644 --- a/go.sum +++ b/go.sum @@ -950,5 +950,5 @@ sigs.k8s.io/structured-merge-diff/v4 v4.1.0/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= 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-20220519102801-965f76fbe437 h1:tWUESKwKU50ZEzQJsOQv50qPvPHj72MjIxFwgeoM7Hg= -skywalking.apache.org/repo/goapi v0.0.0-20220519102801-965f76fbe437/go.mod h1:uWwwvhcwe2MD/nJCg0c1EE/eL6KzaBosLHDfMFoEJ30= +skywalking.apache.org/repo/goapi v0.0.0-20220714130828-0d56d1f4c592 h1:3UbXoMUpGBoYLvuUCaKPzlHCM9Q+enaaOcQ19QbTDr8= +skywalking.apache.org/repo/goapi v0.0.0-20220714130828-0d56d1f4c592/go.mod h1:uWwwvhcwe2MD/nJCg0c1EE/eL6KzaBosLHDfMFoEJ30= diff --git a/internal/commands/dependency/dependency.go b/internal/commands/dependency/dependency.go index 65e343cf..4b373e1b 100644 --- a/internal/commands/dependency/dependency.go +++ b/internal/commands/dependency/dependency.go @@ -29,5 +29,6 @@ var Command = &cli.Command{ EndpointCommand, ServiceCommand, InstanceCommand, + ProcessCommand, }, } diff --git a/internal/commands/dependency/process.go b/internal/commands/dependency/process.go new file mode 100644 index 00000000..8a896798 --- /dev/null +++ b/internal/commands/dependency/process.go @@ -0,0 +1,67 @@ +// 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 dependency + +import ( + "github.com/apache/skywalking-cli/internal/commands/interceptor" + "github.com/apache/skywalking-cli/internal/flags" + "github.com/apache/skywalking-cli/internal/model" + "github.com/apache/skywalking-cli/pkg/display" + "github.com/apache/skywalking-cli/pkg/display/displayable" + "github.com/apache/skywalking-cli/pkg/graphql/dependency" + + "github.com/urfave/cli/v2" + + api "skywalking.apache.org/repo/goapi/query" +) + +var ProcessCommand = &cli.Command{ + Name: "process", + Aliases: []string{"pros"}, + Usage: "Query the process topology, based on the given service instance", + Flags: flags.Flags( + flags.DurationFlags, + flags.ServiceRelationFlags, + flags.InstanceRelationFlags, + ), + Before: interceptor.BeforeChain( + interceptor.DurationInterceptor, + interceptor.ParseInstance(true), + ), + + Action: func(ctx *cli.Context) error { + instanceID := ctx.String("instance-id") + + end := ctx.String("end") + start := ctx.String("start") + step := ctx.Generic("step") + + duration := api.Duration{ + Start: start, + End: end, + Step: step.(*model.StepEnumValue).Selected, + } + + dependency, err := dependency.ProcessTopology(ctx, instanceID, duration) + if err != nil { + return err + } + + return display.Display(ctx, &displayable.Displayable{Data: dependency}) + }, +} diff --git a/internal/commands/interceptor/entity.go b/internal/commands/interceptor/entity.go index 8b110a6a..d03f3e2d 100644 --- a/internal/commands/interceptor/entity.go +++ b/internal/commands/interceptor/entity.go @@ -36,10 +36,12 @@ func ParseEntity(ctx *cli.Context) (*api.Entity, error) { serviceID := ctx.String("service-id") instance := ctx.String("instance-name") endpoint := ctx.String("endpoint-name") + process := ctx.String("process-name") destServiceID := ctx.String("dest-service-id") destInstance := ctx.String("dest-instance-name") destEndpoint := ctx.String("dest-endpoint-name") + destProcess := ctx.String("dest-process-name") serviceName, isNormal, err := ParseServiceID(serviceID) if err != nil { @@ -56,13 +58,23 @@ func ParseEntity(ctx *cli.Context) (*api.Entity, error) { Normal: &isNormal, ServiceInstanceName: &instance, EndpointName: &endpoint, + ProcessName: &process, DestServiceName: &destServiceName, DestNormal: &destIsNormal, DestServiceInstanceName: &destInstance, DestEndpointName: &destEndpoint, + DestProcessName: &destProcess, } entity.Scope = utils.ParseScope(entity) + // adapt for the old version of backend + if *entity.ProcessName == "" { + entity.ProcessName = nil + } + if *entity.DestProcessName == "" { + entity.DestProcessName = nil + } + if logger.Log.GetLevel() <= logrus.DebugLevel { s, _ := json.Marshal(&entity) logger.Log.Debugf("entity: %+v", string(s)) diff --git a/internal/commands/interceptor/process.go b/internal/commands/interceptor/process.go new file mode 100644 index 00000000..eaa59687 --- /dev/null +++ b/internal/commands/interceptor/process.go @@ -0,0 +1,91 @@ +// Licensed to Apache Software Foundation (ASF) under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Apache Software Foundation (ASF) licenses this file to you under +// the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package interceptor + +import ( + "crypto/sha256" + "fmt" + + "github.com/urfave/cli/v2" +) + +const ( + processIDFlagName = "process-id" + processNameFlagName = "process-name" + destProcessNameFlagName = "dest-process-name" +) + +// ParseProcess parses the process id or process name, +// and converts the present one to the missing one. +// See flags.InstanceFlags. +func ParseProcess(required bool) func(*cli.Context) error { + return func(ctx *cli.Context) error { + if err := ParseService(required)(ctx); err != nil { + return err + } + if err := ParseInstance(required)(ctx); err != nil { + return err + } + return parseProcess(required, processIDFlagName, processNameFlagName, instanceIDFlagName)(ctx) + } +} + +// ParseProcessRelation parses the source and destination service instance id or service instance name, +// and converts the present one to the missing one respectively. +// See flags.InstanceRelationFlags. +func ParseProcessRelation(required bool) func(*cli.Context) error { + return func(ctx *cli.Context) error { + if err := ParseService(required)(ctx); err != nil { + return err + } + if err := ParseInstance(required)(ctx); err != nil { + return err + } + if err := ParseProcess(required)(ctx); err != nil { + return err + } + if ctx.String(destProcessNameFlagName) == "" && required { + return fmt.Errorf(`flag "--%s" must given`, destProcessNameFlagName) + } + return nil + } +} + +func parseProcess(required bool, idFlagName, nameFlagName, instanceIDFlagName string) func(*cli.Context) error { + return func(ctx *cli.Context) error { + id := ctx.String(idFlagName) + name := ctx.String(nameFlagName) + instanceID := ctx.String(instanceIDFlagName) + + if id == "" && name == "" { + if required { + return fmt.Errorf(`either flags "--%s" or "--%s" must be given`, idFlagName, nameFlagName) + } + return nil + } + + if name != "" { + if instanceID == "" { + return fmt.Errorf(`"--%s" is specified but its related service name or id is not given`, nameFlagName) + } + id = fmt.Sprintf("%x", sha256.New().Sum([]byte(fmt.Sprintf("%s_%s", instanceID, name)))) + } + + return ctx.Set(idFlagName, id) + } +} diff --git a/internal/commands/metrics/linear/linear-metrics.go b/internal/commands/metrics/linear/linear-metrics.go index 25930c40..d6c4d9a0 100644 --- a/internal/commands/metrics/linear/linear-metrics.go +++ b/internal/commands/metrics/linear/linear-metrics.go @@ -52,11 +52,13 @@ $ swctl metrics linear --name=service_relation_client_cpm --service-name consume flags.MetricsFlags, flags.InstanceRelationFlags, flags.EndpointRelationFlags, + flags.ProcessRelationFlags, ), Before: interceptor.BeforeChain( interceptor.DurationInterceptor, interceptor.ParseEndpointRelation(false), interceptor.ParseInstanceRelation(false), + interceptor.ParseProcessRelation(false), ), Action: func(ctx *cli.Context) error { end := ctx.String("end") diff --git a/internal/commands/metrics/linear/multiple-linear-metrics.go b/internal/commands/metrics/linear/multiple-linear-metrics.go index 5e987e0a..3ffd1ebf 100644 --- a/internal/commands/metrics/linear/multiple-linear-metrics.go +++ b/internal/commands/metrics/linear/multiple-linear-metrics.go @@ -51,6 +51,7 @@ $ swctl metrics multiple-linear --name all_percentile --labels=0,1,2,3,4 --relab flags.MetricsFlags, flags.InstanceRelationFlags, flags.EndpointRelationFlags, + flags.ProcessRelationFlags, []cli.Flag{ &cli.StringFlag{ Name: "labels", @@ -71,6 +72,7 @@ $ swctl metrics multiple-linear --name all_percentile --labels=0,1,2,3,4 --relab interceptor.DurationInterceptor, interceptor.ParseEndpointRelation(false), interceptor.ParseInstanceRelation(false), + interceptor.ParseProcessRelation(false), ), Action: func(ctx *cli.Context) error { end := ctx.String("end") diff --git a/internal/commands/metrics/single/single-metrics.go b/internal/commands/metrics/single/single-metrics.go index 98764853..f10dac5c 100644 --- a/internal/commands/metrics/single/single-metrics.go +++ b/internal/commands/metrics/single/single-metrics.go @@ -46,11 +46,13 @@ $ swctl metrics single --name endpoint_cpm --service-name business-zone::project flags.MetricsFlags, flags.InstanceRelationFlags, flags.EndpointRelationFlags, + flags.ProcessRelationFlags, ), Before: interceptor.BeforeChain( interceptor.DurationInterceptor, interceptor.ParseEndpointRelation(false), interceptor.ParseInstanceRelation(false), + interceptor.ParseProcessRelation(false), ), Action: func(ctx *cli.Context) error { end := ctx.String("end") diff --git a/internal/commands/metrics/thermodynamic/thermodynamic.go b/internal/commands/metrics/thermodynamic/thermodynamic.go index a34199b1..dbc83038 100644 --- a/internal/commands/metrics/thermodynamic/thermodynamic.go +++ b/internal/commands/metrics/thermodynamic/thermodynamic.go @@ -45,11 +45,13 @@ $ swctl metrics thermodynamic --scope all --name all_heatmap flags.MetricsFlags, flags.InstanceRelationFlags, flags.EndpointRelationFlags, + flags.ProcessRelationFlags, ), Before: interceptor.BeforeChain( interceptor.DurationInterceptor, interceptor.ParseEndpointRelation(false), interceptor.ParseInstanceRelation(false), + interceptor.ParseProcessRelation(false), ), Action: func(ctx *cli.Context) error { end := ctx.String("end") diff --git a/internal/commands/profiling/ebpf/create/create.go b/internal/commands/profiling/ebpf/create/create.go index bf233b19..e3829d40 100644 --- a/internal/commands/profiling/ebpf/create/create.go +++ b/internal/commands/profiling/ebpf/create/create.go @@ -25,5 +25,6 @@ var CreateCommand = &cli.Command{ Subcommands: []*cli.Command{ PrepareCreateCommand, FixedTimeCreateCommand, + NetworkCreateCommand, }, } diff --git a/internal/commands/profiling/ebpf/create/network.go b/internal/commands/profiling/ebpf/create/network.go new file mode 100644 index 00000000..aadf2c8f --- /dev/null +++ b/internal/commands/profiling/ebpf/create/network.go @@ -0,0 +1,63 @@ +// 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 create + +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" + "github.com/apache/skywalking-cli/pkg/graphql/profiling" + + "github.com/urfave/cli/v2" + + api "skywalking.apache.org/repo/goapi/query" +) + +var NetworkCreateCommand = &cli.Command{ + Name: "network", + Aliases: []string{"net"}, + Usage: "Create a new ebpf network profiling task", + UsageText: `Create a new ebpf network profiling task + +Examples: +1. Create ebpf network profiling task +$ swctl profiling ebpf create network --service-instance-id=abc`, + Flags: flags.Flags( + flags.ServiceFlags, + flags.InstanceFlags, + ), + Before: interceptor.BeforeChain( + interceptor.ParseInstance(true), + ), + Action: func(ctx *cli.Context) error { + instanceID := ctx.String("instance-id") + + request := &api.EBPFProfilingNetworkTaskRequest{ + InstanceID: instanceID, + } + + task, err := profiling.CreateEBPFNetworkProfilingTask(ctx, request) + + if err != nil { + return err + } + + return display.Display(ctx, &displayable.Displayable{Data: task, Condition: request}) + }, +} diff --git a/internal/commands/profiling/ebpf/ebpf.go b/internal/commands/profiling/ebpf/ebpf.go index e9c99268..02c42622 100644 --- a/internal/commands/profiling/ebpf/ebpf.go +++ b/internal/commands/profiling/ebpf/ebpf.go @@ -19,6 +19,7 @@ package ebpf import ( "github.com/apache/skywalking-cli/internal/commands/profiling/ebpf/create" + "github.com/apache/skywalking-cli/internal/commands/profiling/ebpf/keep" "github.com/urfave/cli/v2" ) @@ -28,6 +29,7 @@ var Command = &cli.Command{ Usage: "eBPF Profiling related sub-command", Subcommands: []*cli.Command{ create.CreateCommand, + keep.KeepCommand, ListTaskCommand, ListScheduleCommand, AnalyzationCommand, diff --git a/internal/commands/profiling/ebpf/keep/keep.go b/internal/commands/profiling/ebpf/keep/keep.go new file mode 100644 index 00000000..22af29ea --- /dev/null +++ b/internal/commands/profiling/ebpf/keep/keep.go @@ -0,0 +1,28 @@ +// 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 keep + +import "github.com/urfave/cli/v2" + +var KeepCommand = &cli.Command{ + Name: "keep", + Usage: "eBPF Profiling task keep-alive related sub-command", + Subcommands: []*cli.Command{ + NetworkKeepCommand, + }, +} diff --git a/internal/commands/profiling/ebpf/keep/network.go b/internal/commands/profiling/ebpf/keep/network.go new file mode 100644 index 00000000..8d86f6d0 --- /dev/null +++ b/internal/commands/profiling/ebpf/keep/network.go @@ -0,0 +1,57 @@ +// Licensed to Apache Software Foundation (ASF) under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Apache Software Foundation (ASF) licenses this file to you under +// the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package keep + +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" +) + +var NetworkKeepCommand = &cli.Command{ + Name: "network", + Aliases: []string{"net"}, + Usage: "Keep alive the exist ebpf network profiling task", + UsageText: `Keep alive the exist ebpf network profiling task + +Examples: +1. Keep alive the ebpf network profiling task +$ swctl profiling ebpf keep network --task-id=abc`, + Flags: flags.Flags( + []cli.Flag{ + &cli.StringFlag{ + Name: "task-id", + Usage: "the `task-id` of the network profiling task", + Required: true, + }, + }, + ), + Action: func(ctx *cli.Context) error { + taskID := ctx.String("task-id") + + keepResult, err := profiling.KeepNetworkProfilingTask(ctx, taskID) + if err != nil { + return err + } + + return display.Display(ctx, &displayable.Displayable{Data: keepResult}) + }, +} diff --git a/internal/flags/process.go b/internal/flags/process.go new file mode 100644 index 00000000..86060594 --- /dev/null +++ b/internal/flags/process.go @@ -0,0 +1,46 @@ +// Licensed to Apache Software Foundation (ASF) under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Apache Software Foundation (ASF) licenses this file to you under +// the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package flags + +import "github.com/urfave/cli/v2" + +// ProcessFlags take either process id or process name as input, +// and transform to the other one. +var ProcessFlags = []cli.Flag{ + &cli.StringFlag{ + Name: "process-id", + Usage: "`process id`, if you don't have process id, use `--process-name` instead", + Required: false, + }, + &cli.StringFlag{ + Name: "process-name", + Usage: "`process name`", + Required: false, + }, +} + +// ProcessRelationFlags take either destination process name as input, +var ProcessRelationFlags = append( + ProcessFlags, + + &cli.StringFlag{ + Name: "dest-process-name", + Usage: "`destination` process name", + Required: false, + }, +) diff --git a/pkg/graphql/dependency/dependency.go b/pkg/graphql/dependency/dependency.go index dd189ca0..ea5fe1ab 100644 --- a/pkg/graphql/dependency/dependency.go +++ b/pkg/graphql/dependency/dependency.go @@ -63,3 +63,15 @@ func InstanceTopology(ctx *cli.Context, clientServiceID, serverServiceID string, return response["result"], err } + +func ProcessTopology(ctx *cli.Context, instanceID string, duration api.Duration) (api.ProcessTopology, error) { + var response map[string]api.ProcessTopology + + request := graphql.NewRequest(assets.Read("graphqls/dependency/ProcessTopology.graphql")) + request.Var("serviceInstanceId", instanceID) + request.Var("duration", duration) + + err := client.ExecuteQuery(ctx, request, &response) + + return response["result"], err +} diff --git a/pkg/graphql/profiling/ebpf.go b/pkg/graphql/profiling/ebpf.go index 2d9c10ca..c75e392a 100644 --- a/pkg/graphql/profiling/ebpf.go +++ b/pkg/graphql/profiling/ebpf.go @@ -40,6 +40,17 @@ func CreateEBPFProfilingFixedTimeTask(ctx *cli.Context, return response["result"], err } +func CreateEBPFNetworkProfilingTask(ctx *cli.Context, condition *api.EBPFProfilingNetworkTaskRequest) (api.EBPFProfilingTaskCreationResult, error) { + var response map[string]api.EBPFProfilingTaskCreationResult + + request := graphql.NewRequest(assets.Read("graphqls/profiling/ebpf/CreateEBPFNetworkProfilingTask.graphql")) + request.Var("request", condition) + + err := client.ExecuteQuery(ctx, request, &response) + + return response["result"], err +} + func QueryPrepareCreateEBPFProfilingTaskData(ctx *cli.Context, serviceID string) (*api.EBPFProfilingTaskPrepare, error) { var response map[string]*api.EBPFProfilingTaskPrepare @@ -86,3 +97,14 @@ func AnalysisEBPFProfilingResult(ctx *cli.Context, scheduleIDList []string, return response["result"], err } + +func KeepNetworkProfilingTask(ctx *cli.Context, taskID string) (*api.EBPFNetworkKeepProfilingResult, error) { + var response map[string]*api.EBPFNetworkKeepProfilingResult + + request := graphql.NewRequest(assets.Read("graphqls/profiling/ebpf/KeepNetworkProfilingTask.graphql")) + request.Var("taskId", taskID) + + err := client.ExecuteQuery(ctx, request, &response) + + return response["result"], err +} diff --git a/pkg/graphql/utils/parser.go b/pkg/graphql/utils/parser.go index 037ceddb..15925c53 100644 --- a/pkg/graphql/utils/parser.go +++ b/pkg/graphql/utils/parser.go @@ -27,7 +27,9 @@ import ( func ParseScope(entity *api.Entity) api.Scope { scope := api.ScopeAll - if *entity.DestEndpointName != "" { + if *entity.DestProcessName != "" { + scope = api.ScopeProcessRelation + } else if *entity.DestEndpointName != "" { scope = api.ScopeEndpointRelation } else if *entity.DestServiceInstanceName != "" { scope = api.ScopeServiceInstanceRelation diff --git a/pkg/graphql/utils/parser_test.go b/pkg/graphql/utils/parser_test.go index 91289793..9adb0207 100644 --- a/pkg/graphql/utils/parser_test.go +++ b/pkg/graphql/utils/parser_test.go @@ -23,6 +23,7 @@ import ( api "skywalking.apache.org/repo/goapi/query" ) +//nolint:funlen // disable function length check for the test case count func TestParseScope(t *testing.T) { empty := "" nonEmpty := "test" @@ -37,9 +38,11 @@ func TestParseScope(t *testing.T) { ServiceName: &empty, ServiceInstanceName: &empty, EndpointName: &empty, + ProcessName: &empty, DestServiceName: &empty, DestServiceInstanceName: &empty, DestEndpointName: &empty, + DestProcessName: &empty, }, want: api.ScopeAll, }, @@ -49,11 +52,13 @@ func TestParseScope(t *testing.T) { ServiceName: &nonEmpty, ServiceInstanceName: &nonEmpty, EndpointName: &nonEmpty, + ProcessName: &nonEmpty, DestServiceName: &nonEmpty, DestServiceInstanceName: &nonEmpty, DestEndpointName: &nonEmpty, + DestProcessName: &nonEmpty, }, - want: api.ScopeEndpointRelation, + want: api.ScopeProcessRelation, }, { name: "only serviceName is not empty", @@ -61,9 +66,11 @@ func TestParseScope(t *testing.T) { ServiceName: &nonEmpty, ServiceInstanceName: &empty, EndpointName: &empty, + ProcessName: &empty, DestServiceName: &empty, DestServiceInstanceName: &empty, DestEndpointName: &empty, + DestProcessName: &empty, }, want: api.ScopeService, }, @@ -73,9 +80,11 @@ func TestParseScope(t *testing.T) { ServiceName: &nonEmpty, ServiceInstanceName: &nonEmpty, EndpointName: &empty, + ProcessName: &empty, DestServiceName: &empty, DestServiceInstanceName: &empty, DestEndpointName: &empty, + DestProcessName: &empty, }, want: api.ScopeServiceInstance, }, @@ -85,9 +94,11 @@ func TestParseScope(t *testing.T) { ServiceName: &nonEmpty, ServiceInstanceName: &empty, EndpointName: &nonEmpty, + ProcessName: &empty, DestServiceName: &empty, DestServiceInstanceName: &empty, DestEndpointName: &empty, + DestProcessName: &empty, }, want: api.ScopeEndpoint, }, @@ -97,9 +108,11 @@ func TestParseScope(t *testing.T) { ServiceName: &nonEmpty, ServiceInstanceName: &empty, EndpointName: &empty, + ProcessName: &empty, DestServiceName: &nonEmpty, DestServiceInstanceName: &empty, DestEndpointName: &empty, + DestProcessName: &empty, }, want: api.ScopeServiceRelation, }, @@ -109,12 +122,28 @@ func TestParseScope(t *testing.T) { ServiceName: &nonEmpty, ServiceInstanceName: &nonEmpty, EndpointName: &empty, + ProcessName: &empty, DestServiceName: &nonEmpty, DestServiceInstanceName: &nonEmpty, DestEndpointName: &empty, + DestProcessName: &empty, }, want: api.ScopeServiceInstanceRelation, }, + { + name: "destProcess is not empty", + args: &api.Entity{ + ServiceName: &nonEmpty, + ServiceInstanceName: &nonEmpty, + EndpointName: &empty, + ProcessName: &nonEmpty, + DestServiceName: &nonEmpty, + DestServiceInstanceName: &nonEmpty, + DestEndpointName: &empty, + DestProcessName: &nonEmpty, + }, + want: api.ScopeProcessRelation, + }, } for _, tt := range tests {