diff --git a/README.md b/README.md index c3d6c64b..c6cef7e3 100644 --- a/README.md +++ b/README.md @@ -564,6 +564,22 @@ You can imitate the content of [the default template file](examples/global.yml) ### `dependency` +#### `service` + +
+ +dependency service [--start=start-time] [--end=end-time] + +`dependency service` shows all the dependencies of given `[service-id]` in the time range of `[start, end]`. + +| argument | description | default | +| :--- | :--- | :--- | +| `service-id` | The service id whose dependencies are to displayed. | | +| `--start` | See [Common options](#common-options) | See [Common options](#common-options) | +| `--end` | See [Common options](#common-options) | See [Common options](#common-options) | + +
+ #### `endpoint`
diff --git a/assets/assets.gen.go b/assets/assets.gen.go index ee5279ec..de5df31e 100644 --- a/assets/assets.gen.go +++ b/assets/assets.gen.go @@ -20,6 +20,7 @@ // cr/oap.yaml (942B) // cr/ui.yaml (935B) // graphqls/dependency/EndpointDependency.graphql (1.207kB) +// graphqls/dependency/ServiceTopology.graphql (1.137kB) // graphqls/event/events.graphql (1.256kB) // graphqls/healthcheck/healthcheck.graphql (870B) // graphqls/logs/Logs.graphql (1.258kB) @@ -221,6 +222,56 @@ func graphqlsDependencyEndpointdependencyGraphql() (*asset, error) { return a, nil } +var _graphqlsDependencyServicetopologyGraphql = []byte(`# Licensed to Apache Software Foundation (ASF) under one or more contributor +# license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright +# ownership. Apache Software Foundation (ASF) licenses this file to you under +# the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +query ($serviceId: ID!, $duration: Duration!) { + result: getServiceTopology(duration: $duration, serviceId: $serviceId) { + nodes { + id + name + type + isReal + } + calls { + id + source + detectPoints + target + } + } +} +`) + +func graphqlsDependencyServicetopologyGraphqlBytes() ([]byte, error) { + return _graphqlsDependencyServicetopologyGraphql, nil +} + +func graphqlsDependencyServicetopologyGraphql() (*asset, error) { + bytes, err := graphqlsDependencyServicetopologyGraphqlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "graphqls/dependency/ServiceTopology.graphql", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xb9, 0xb4, 0x57, 0x4c, 0xe6, 0x57, 0x1c, 0x34, 0xbd, 0xed, 0x73, 0x68, 0x63, 0x5, 0xab, 0x62, 0x44, 0x9, 0xc3, 0x12, 0x9, 0x85, 0x4b, 0xad, 0xb5, 0xb0, 0xa, 0xdb, 0xa8, 0x48, 0x22, 0x54}} + return a, nil +} + var _graphqlsEventEventsGraphql = []byte(`# Licensed to Apache Software Foundation (ASF) under one or more contributor # license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright @@ -1377,6 +1428,7 @@ var _bindata = map[string]func() (*asset, error){ "cr/oap.yaml": crOapYaml, "cr/ui.yaml": crUiYaml, "graphqls/dependency/EndpointDependency.graphql": graphqlsDependencyEndpointdependencyGraphql, + "graphqls/dependency/ServiceTopology.graphql": graphqlsDependencyServicetopologyGraphql, "graphqls/event/events.graphql": graphqlsEventEventsGraphql, "graphqls/healthcheck/healthcheck.graphql": graphqlsHealthcheckHealthcheckGraphql, "graphqls/logs/Logs.graphql": graphqlsLogsLogsGraphql, @@ -1452,6 +1504,7 @@ var _bintree = &bintree{nil, map[string]*bintree{ "graphqls": &bintree{nil, map[string]*bintree{ "dependency": &bintree{nil, map[string]*bintree{ "EndpointDependency.graphql": &bintree{graphqlsDependencyEndpointdependencyGraphql, map[string]*bintree{}}, + "ServiceTopology.graphql": &bintree{graphqlsDependencyServicetopologyGraphql, map[string]*bintree{}}, }}, "event": &bintree{nil, map[string]*bintree{ "events.graphql": &bintree{graphqlsEventEventsGraphql, map[string]*bintree{}}, diff --git a/assets/graphqls/dependency/ServiceTopology.graphql b/assets/graphqls/dependency/ServiceTopology.graphql new file mode 100644 index 00000000..bc08f0e7 --- /dev/null +++ b/assets/graphqls/dependency/ServiceTopology.graphql @@ -0,0 +1,33 @@ +# Licensed to Apache Software Foundation (ASF) under one or more contributor +# license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright +# ownership. Apache Software Foundation (ASF) licenses this file to you under +# the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +query ($serviceId: ID!, $duration: Duration!) { + result: getServiceTopology(duration: $duration, serviceId: $serviceId) { + nodes { + id + name + type + isReal + } + calls { + id + source + detectPoints + target + } + } +} diff --git a/internal/commands/dependency/dependency.go b/internal/commands/dependency/dependency.go index c0601651..b7192934 100644 --- a/internal/commands/dependency/dependency.go +++ b/internal/commands/dependency/dependency.go @@ -27,5 +27,6 @@ var Command = cli.Command{ Usage: "Dependency related subcommand", Subcommands: cli.Commands{ EndpointCommand, + ServiceCommand, }, } diff --git a/internal/commands/dependency/service.go b/internal/commands/dependency/service.go new file mode 100644 index 00000000..4a0abb3c --- /dev/null +++ b/internal/commands/dependency/service.go @@ -0,0 +1,74 @@ +// Licensed to Apache Software Foundation (ASF) under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Apache Software Foundation (ASF) licenses this file to you under +// the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package dependency + +import ( + "fmt" + + "github.com/urfave/cli" + + "github.com/apache/skywalking-cli/internal/commands/interceptor" + "github.com/apache/skywalking-cli/internal/flags" + "github.com/apache/skywalking-cli/internal/logger" + "github.com/apache/skywalking-cli/internal/model" + + "github.com/apache/skywalking-cli/pkg/display" + "github.com/apache/skywalking-cli/pkg/display/displayable" + + "github.com/apache/skywalking-cli/pkg/graphql/dependency" + + api "skywalking.apache.org/repo/goapi/query" +) + +var ServiceCommand = cli.Command{ + Name: "service", + ShortName: "svc", + Usage: "Query the dependencies of given service", + ArgsUsage: "", + Flags: flags.Flags( + flags.DurationFlags, + ), + Before: interceptor.BeforeChain([]cli.BeforeFunc{ + interceptor.TimezoneInterceptor, + interceptor.DurationInterceptor, + }), + + Action: func(ctx *cli.Context) error { + if ctx.NArg() == 0 { + return fmt.Errorf("command service requires serviceId as argument") + } + + 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.ServiceTopology(ctx, ctx.Args().First(), duration) + + if err != nil { + logger.Log.Fatalln(err) + } + + return display.Display(ctx, &displayable.Displayable{Data: dependency}) + }, +} diff --git a/pkg/graphql/dependency/dependency.go b/pkg/graphql/dependency/dependency.go index b84c8d4f..8b28ea66 100644 --- a/pkg/graphql/dependency/dependency.go +++ b/pkg/graphql/dependency/dependency.go @@ -38,3 +38,15 @@ func EndpointDependency(ctx *cli.Context, endpointID string, duration api.Durati return response["result"], err } + +func ServiceTopology(ctx *cli.Context, serviceID string, duration api.Duration) (api.Topology, error) { + var response map[string]api.Topology + + request := graphql.NewRequest(assets.Read("graphqls/dependency/ServiceTopology.graphql")) + request.Var("serviceId", serviceID) + request.Var("duration", duration) + + err := client.ExecuteQuery(ctx, request, &response) + + return response["result"], err +} diff --git a/scripts/test_commands.sh b/scripts/test_commands.sh index e72d3d18..59f41f05 100755 --- a/scripts/test_commands.sh +++ b/scripts/test_commands.sh @@ -66,3 +66,8 @@ ${swctl} --display=json trace ls >/dev/null 2>&1 # Test `dashboard global` ${swctl} --display=json db g >/dev/null 2>&1 + +# Test `dependency` +${swctl} --display=json dependency service "test" > /dev/null 2>&1 + +${swctl} --display=json dependency endpoint "test" > /dev/null 2>&1 \ No newline at end of file