From 9ce2320148d3b9b72ce6bc726705aa0291794639 Mon Sep 17 00:00:00 2001 From: kezhenxu94 Date: Sat, 9 Oct 2021 13:51:50 +0800 Subject: [PATCH] Add missing `dest-service-id` `dest-service-name` to `metrics linear` command --- README.md | 314 +----------------- internal/commands/interceptor/endpoint.go | 14 +- internal/commands/interceptor/entity.go | 8 + internal/commands/interceptor/instance.go | 12 +- internal/commands/interceptor/service.go | 14 +- .../commands/metrics/linear/linear-metrics.go | 5 +- .../metrics/linear/multiple-linear-metrics.go | 2 +- .../commands/metrics/single/single-metrics.go | 2 +- .../metrics/thermodynamic/thermodynamic.go | 2 +- internal/flags/endpoint.go | 2 +- test/test.yaml | 4 + 11 files changed, 48 insertions(+), 331 deletions(-) diff --git a/README.md b/README.md index ae0945a1..95c1dfdd 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Apache SkyWalking CLI ![](https://github.com/apache/skywalking-cli/workflows/Build/badge.svg?branch=master) ![](https://codecov.io/gh/apache/skywalking-cli/branch/master/graph/badge.svg) -Sky Walking logo +Sky Walking logo The CLI (Command Line Interface) for [Apache SkyWalking](https://github.com/apache/skywalking). @@ -103,314 +103,16 @@ command to create `$profile` file: New-Item -Type file -Force $profile ``` -After reloading your shell, swctl auto-completion should be working. - -### `metrics` - -#### `metrics linear` - -
- -metrics linear [--start=start-time] [--end=end-time] --name=metrics-name [--service=service-name] [--instance=instance-name] [--endpoint=endpoint-name] [--destService=dest-service-name] [--destInstance=dest-instance-name] [--destEndpoint=dest-endpoint-name] [--isDestNormal=true/false] - -| option | description | default | -| :--- | :--- | :--- | -| `--name` | Metrics name, defined in [OAL](https://github.com/apache/skywalking/blob/master/oap-server/server-bootstrap/src/main/resources/oal/core.oal). | -| `--service` | The name of the service. | "" | -| `--instance` | The name of the service instance. | "" | -| `--endpoint` | The name of the endpoint. | "" | -| `--destService` | The name of the destination service. | "" | -| `--destInstance` | The name of the destination instance. | "" | -| `--destEndpoint` | The name of the destination endpoint. | "" | -| `--isDestNormal` | Set the destination service to normal or unnormal. | `true` | -| `--start` | See [Common options](#common-options) | See [Common options](#common-options) | -| `--end` | See [Common options](#common-options) | See [Common options](#common-options) | - -
- -#### `metrics multiple-linear` - -
- -metrics multiple-linear [--start=start-time] [--end=end-time] --name=metrics-name [--service=service-name] [--num=number-of-linear-metrics] [--instance=instance-name] [--endpoint=endpoint-name] [--isNormal=true/false] [--destService=dest-service-name] [--destInstance=dest-instance-name] [--destEndpoint=dest-endpoint-name] [--isDestNormal=true/false] - -| option | description | default | -| :--- | :--- | :--- | -| `--name` | Metrics name that ends with `_percentile`, defined in [OAL](https://github.com/apache/skywalking/blob/master/oap-server/server-bootstrap/src/main/resources/oal/core.oal), such as `all_percentile`, etc. | -| `--service` | The name of the service, when scope is `All`, no name is required. | "" | -| `--labels` | The labels you need to query | `0,1,2,3,4` | -| `--instance` | The name of the service instance. | "" | -| `--endpoint` | The name of the endpoint. | "" | -| `--isNormal` | Set the service to normal or unnormal. | `true` | -| `--destService` | The name of the destination service. | "" | -| `--destInstance` | The name of the destination instance. | "" | -| `--destEndpoint` | The name of the destination endpoint. | "" | -| `--isDestNormal` | Set the destination service to normal or unnormal. | `true` | -| `--start` | See [Common options](#common-options) | See [Common options](#common-options) | -| `--end` | See [Common options](#common-options) | See [Common options](#common-options) | - -
- -#### `metrics single` - -
- -metrics single [--start=start-time] [--end=end-time] --name=metrics-name --service=service-name [--instance=instance-name] [--endpoint=endpoint-name] [--isNormal=true/false] [--destService=dest-service-name] [--destInstance=dest-instance-name] [--destEndpoint=dest-endpoint-name] [--isDestNormal=true/false] - -| option | description | default | -| :--- | :--- | :--- | -| `--name` | Metrics name, defined in [OAL](https://github.com/apache/skywalking/blob/master/oap-server/server-bootstrap/src/main/resources/oal/core.oal), such as `service_sla`, etc. | -| `--service` | The name of the service. | "" | -| `--instance` | The name of the service instance. | "" | -| `--endpoint` | The name of the endpoint. | "" | -| `--isNormal` | Set the service to normal or unnormal. | `true` | -| `--destService` | The name of the destination service. | "" | -| `--destInstance` | The name of the destination instance. | "" | -| `--destEndpoint` | The name of the destination endpoint. | "" | -| `--isDestNormal` | Set the destination service to normal or unnormal. | `true` | -| `--start` | See [Common options](#common-options) | See [Common options](#common-options) | -| `--end` | See [Common options](#common-options) | See [Common options](#common-options) | - -
- -### `dashboard` - -#### `dashboard global-metrics` - -
- -dashboard global-metrics [--template=template] - -`dashboard global-metrics` displays global metrics in the form of a dashboard. - -| argument | description | default | -| :--- | :--- | :--- | -| `--template` | The template file to customize how to display information | `templates/Dashboard.Global.json` | -| `--start` | See [Common options](#common-options) | See [Common options](#common-options) | -| `--end` | See [Common options](#common-options) | See [Common options](#common-options) | - -You can imitate the content of [the default template file](examples/global.yml) to customize the dashboard. - -
- -#### `dashboard global` - -
- -dashboard global [--template=template] - -`dashboard global` displays global metrics, global response latency and global heat map in the form of a dashboard. - -| argument | description | default | -| :--- | :--- | :--- | -| `--template` | The template file to customize how to display information | `templates/dashboard/global.yml` | -| `--refresh` | The interval of auto-refresh (s). When `start` and `end` are both present, auto-refresh is disabled. | `6` | -| `--start` | See [Common options](#common-options) | See [Common options](#common-options) | -| `--end` | See [Common options](#common-options) | See [Common options](#common-options) | - -You can imitate the content of [the default template file](examples/global.yml) to customize the dashboard. - -
- -### `install` - -#### `manifest` - -
- -install manifest oap|ui [--name=string] [--namespace=string] [-f=filepath/-] - -| argument | description | default | -| :--- | :--- | :--- | -| `--name` | The name of prefix of generated resources | `skywalking` | -| `--namespace` | The namespace where resource will be deployed | `skywalking-system` | -| `-f` | The custom resource file describing custom resources defined by swck | | - -
- -### `event` - -#### `report` - -
- -event report [--uuid=uuid] [--service=service] [--name=name] [--message=message] [--startTime=startTime] [--endTime=endTime] [--instance=instance] [--endpoint=endpoint] [--type=type] [parameters...] - -`event report` reports an event to OAP server via gRPC. - -| argument | description | default | -| :--- | :--- | :--- | -| `uuid` | The unique ID of the event. | | -| `service` | The service of the event occurred on. | | -| `instance` | The service instance of the event occurred on. | | -| `endpoint` | The endpoint of the event occurred on. | | -| `name` | The name of the event. For example, 'Reboot' and 'Upgrade' etc. | | -| `type` | The type of the event, could be `Normal` or `Error`. | `Normal` | -| `message` | The detail of the event. This should be a one-line message that briefly describes why the event is reported. | | -| `startTime` | The start time (in milliseconds) of the event, measured between the current time and midnight, January 1, 1970 UTC. | | -| `endTime` | The end time (in milliseconds) of the event, measured between the current time and midnight, January 1, 1970 UTC. | | - -
- -#### `list` - -
- -event list [--service=service] [--instance=instance] [--endpoint=endpoint] [--name=name] [--type=type] [--start=start-time] [--end=end-time] - -| argument | description | default | -| :--- | :--- | :--- | -| `service` | The service name whose events are to displayed. | | -| `instance` | The service instance name whose events are to displayed. | | -| `endpoint` | The endpoint name whose logs are to displayed. | | -| `name` | The name of the event. | | -| `type` | The type of the event, could be `Normal` or `Error`. | `Normal` | - -
- -### `logs` - -#### `list` +After reloading your shell, `swctl` auto-completion should be working. -
- -logs list [--service-id=service-id] [--instance-id=instance-id] [--endpoint-id=endpoint-id] [--trace-id=trace-id] [--tags=tags] [--start=start-time] [--end=end-time] - -| argument | description | default | -| :--- | :--- | :--- | -| `service-id` | The service id whose logs are to displayed. | | -| `instance-id` | The service instance id whose logs are to displayed. | | -| `endpoint-id` | The service endpoint id whose logs are to displayed. | | -| `trace-id` | The trace id whose logs are to displayed. | | -| `tags` | Only tags defined in the core/default/searchableLogsTags are searchable. Check more details on the Configuration Vocabulary page | See [Configuration Vocabulary page](https://github.com/apache/skywalking/blob/master/docs/en/setup/backend/configuration-vocabulary.md) | - -
- -### `profile` - -#### `create` - -
- -profile create [--service-id=service-id] [--service-name=service-name] [--endpoint=endpoint] [--start-time=start-time] [--duration=duration] [--min-duration-threshold=min-duration-threshold] [--dump-period=dump-period] [--max-sampling-count=max-sampling-count] - -| argument | description | default | -| :--- | :--- | :--- | -| `service-id` | whose endpoints are to be profile. | | -| `service-name` | whose endpoints are to be profile. | | -| `endpoint` | which endpoint should profile. | | -| `start-time` | profile task start time(millisecond). | | -| `duration` | profile task continuous time(minute). | | -| `min-duration-threshold` | profiled endpoint must greater duration(millisecond). | | -| `dump-period` | profiled endpoint dump period(millisecond). | | -| `max-sampling-count` | profile task max sampling count. | | - -
- -#### `list` - -
- -profile list [--service-id=service-id] [--service-name=service-name] [--endpoint=endpoint] +## Help / Manual -| argument | description | default | -| :--- | :--- | :--- | -| `service-id` | `` whose profile task are to be searched. | | -| `service-name` | `` whose profile task are to be searched. | | -| `endpoint` | `` whose profile task are to be searched | | - -
- -#### `segment-list` - -
- -profile segment-list [--task-id=task-id] - -| argument | description | default | -| :--- | :--- | :--- | -| `task-id` | `` whose profiled segment are to be searched. | | - -
- -#### `profiled-segment` - -
- -profile profiled-segment [--segment-id=segment-id] - -| argument | description | default | -| :--- | :--- | :--- | -| `segment-id` | profiled segment id. | | - -
- -#### `profiled-analyze` - -
- -profile profiled-analyze [--segment-id=segment-id] [--time-ranges=time-ranges] - -| argument | description | default | -| :--- | :--- | :--- | -| `segment-id` | profiled segment id. | | -| `time-ranges` | need to analyze time ranges in the segment: start-end,start-end. | | - -
- -### `dependency` - -#### `service` - -
- -dependency service [service-id] [--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` - -
- -dependency endpoint [endpoint-id] [--start=start-time] [--end=end-time] - -`dependency endpoint` shows all the dependencies of given `[endpoint-id]` in the time range of `[start, end]`. - -| argument | description | default | -| :--- | :--- | :--- | -| `endpoint-id` | The service endpoint 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) | - -
- -#### `instance` - -
- -dependency instance [clientService-id] [serverService-id] [--start=start-time] [--end=end-time] - -`dependency instance` shows the instance topology of given `[clientService-id]` and `[serverService-id]` in the time -range of `[start, end]`. - -| argument | description | default | -| :--- | :--- | :--- | -| `clientService-id` | The service id of the client. | | -| `serverService-id` | The service id of the server. | | -| `--start` | See [Common options](#common-options) | See [Common options](#common-options) | -| `--end` | See [Common options](#common-options) | See [Common options](#common-options) | - -
+`swctl` builds the help manual inside the command itself with some useful example commands, please type `swctl help` +after installation. If you want to look up detail manual for a specific sub-command, insert `help` before the last +sub-command, for example, `swctl service help list` shows the manual for command `swctl service list`, +and `swctl install manifest help oap` shows the manual for `swctl install manifest oap`. -# Use Cases +# More Use Cases
Report events in CD workflows - GitHub Actions diff --git a/internal/commands/interceptor/endpoint.go b/internal/commands/interceptor/endpoint.go index d4c42d1c..5131ef85 100644 --- a/internal/commands/interceptor/endpoint.go +++ b/internal/commands/interceptor/endpoint.go @@ -49,7 +49,7 @@ func ParseEndpoint(required bool) func(*cli.Context) error { // See flags.EndpointRelationFlags. func ParseEndpointRelation(required bool) func(*cli.Context) error { return func(ctx *cli.Context) error { - if err := ParseService(required)(ctx); err != nil { + if err := ParseServiceRelation(required)(ctx); err != nil { return err } if err := ParseEndpoint(required)(ctx); err != nil { @@ -72,12 +72,7 @@ func parseEndpoint(required bool, idFlagName, nameFlagName, serviceIDFlagName st return nil } - 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) - } else if id != "" { + if id != "" { parts := strings.Split(id, "_") if len(parts) != 2 { return fmt.Errorf("invalid endpoint id, cannot be splitted into 2 parts. %v", id) @@ -87,6 +82,11 @@ func parseEndpoint(required bool, idFlagName, nameFlagName, serviceIDFlagName st 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) } if err := ctx.Set(idFlagName, id); err != nil { diff --git a/internal/commands/interceptor/entity.go b/internal/commands/interceptor/entity.go index d8a40e73..8b110a6a 100644 --- a/internal/commands/interceptor/entity.go +++ b/internal/commands/interceptor/entity.go @@ -19,11 +19,14 @@ package interceptor import ( "encoding/base64" + "encoding/json" "fmt" "strings" + "github.com/sirupsen/logrus" "github.com/urfave/cli/v2" + "github.com/apache/skywalking-cli/internal/logger" "github.com/apache/skywalking-cli/pkg/graphql/utils" api "skywalking.apache.org/repo/goapi/query" @@ -60,6 +63,11 @@ func ParseEntity(ctx *cli.Context) (*api.Entity, error) { } entity.Scope = utils.ParseScope(entity) + if logger.Log.GetLevel() <= logrus.DebugLevel { + s, _ := json.Marshal(&entity) + logger.Log.Debugf("entity: %+v", string(s)) + } + return entity, nil } diff --git a/internal/commands/interceptor/instance.go b/internal/commands/interceptor/instance.go index a33ff11d..78f5ad15 100644 --- a/internal/commands/interceptor/instance.go +++ b/internal/commands/interceptor/instance.go @@ -72,12 +72,7 @@ func parseInstance(required bool, idFlagName, nameFlagName, serviceIDFlagName st return nil } - 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) - } else if id != "" { + if id != "" { parts := strings.Split(id, "_") if len(parts) != 2 { return fmt.Errorf("invalid instance id, cannot be splitted into 2 parts. %v", id) @@ -87,6 +82,11 @@ func parseInstance(required bool, idFlagName, nameFlagName, serviceIDFlagName st 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) } if err := ctx.Set(idFlagName, id); err != nil { diff --git a/internal/commands/interceptor/service.go b/internal/commands/interceptor/service.go index f1b7036c..f87fd884 100644 --- a/internal/commands/interceptor/service.go +++ b/internal/commands/interceptor/service.go @@ -66,13 +66,7 @@ func parseService(required bool, idFlagName, nameFlagName string) func(*cli.Cont return nil } - if name != "" { - service, err := metadata.SearchService(ctx, name) - if err != nil { - return err - } - id = service.ID - } else if id != "" { + if id != "" { parts := strings.Split(id, ".") if len(parts) != 2 { return fmt.Errorf("invalid service id, cannot be splitted into 2 parts. %v", id) @@ -82,6 +76,12 @@ func parseService(required bool, idFlagName, nameFlagName string) func(*cli.Cont return err } name = string(s) + } else if name != "" { + service, err := metadata.SearchService(ctx, name) + if err != nil { + return err + } + id = service.ID } if err := ctx.Set(idFlagName, id); err != nil { diff --git a/internal/commands/metrics/linear/linear-metrics.go b/internal/commands/metrics/linear/linear-metrics.go index a89a33a1..25930c40 100644 --- a/internal/commands/metrics/linear/linear-metrics.go +++ b/internal/commands/metrics/linear/linear-metrics.go @@ -43,6 +43,9 @@ $ swctl metrics linear --name=service_resp_time --service-name business-zone::pr 2. Query the response time of service instance $ swctl metrics linear --name=service_instance_resp_time --service-name business-zone::projectB \ --instance-name d708c6bfea9f4d50902d1743302a6f50@10.170.0.12 + +3. Query the traffic (calls per minutes) between service "consumer" to service "provider" +$ swctl metrics linear --name=service_relation_client_cpm --service-name consumer --dest-service-name provider `, Flags: flags.Flags( flags.DurationFlags, @@ -52,8 +55,8 @@ $ swctl metrics linear --name=service_instance_resp_time --service-name business ), Before: interceptor.BeforeChain( interceptor.DurationInterceptor, - interceptor.ParseInstanceRelation(false), interceptor.ParseEndpointRelation(false), + interceptor.ParseInstanceRelation(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 72e7ffd4..af4a4078 100644 --- a/internal/commands/metrics/linear/multiple-linear-metrics.go +++ b/internal/commands/metrics/linear/multiple-linear-metrics.go @@ -58,8 +58,8 @@ $ swctl metrics multiple-linear --name all_percentile`, ), Before: interceptor.BeforeChain( interceptor.DurationInterceptor, - interceptor.ParseInstanceRelation(false), interceptor.ParseEndpointRelation(false), + interceptor.ParseInstanceRelation(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 5c9afa7b..98764853 100644 --- a/internal/commands/metrics/single/single-metrics.go +++ b/internal/commands/metrics/single/single-metrics.go @@ -49,8 +49,8 @@ $ swctl metrics single --name endpoint_cpm --service-name business-zone::project ), Before: interceptor.BeforeChain( interceptor.DurationInterceptor, - interceptor.ParseInstanceRelation(false), interceptor.ParseEndpointRelation(false), + interceptor.ParseInstanceRelation(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 52d6b1ed..a34199b1 100644 --- a/internal/commands/metrics/thermodynamic/thermodynamic.go +++ b/internal/commands/metrics/thermodynamic/thermodynamic.go @@ -48,8 +48,8 @@ $ swctl metrics thermodynamic --scope all --name all_heatmap ), Before: interceptor.BeforeChain( interceptor.DurationInterceptor, - interceptor.ParseInstanceRelation(false), interceptor.ParseEndpointRelation(false), + interceptor.ParseInstanceRelation(false), ), Action: func(ctx *cli.Context) error { end := ctx.String("end") diff --git a/internal/flags/endpoint.go b/internal/flags/endpoint.go index 06b83676..ac91e49c 100644 --- a/internal/flags/endpoint.go +++ b/internal/flags/endpoint.go @@ -41,7 +41,7 @@ var EndpointFlags = append( // EndpointRelationFlags take either destination endpoint id or destination endpoint name as input, // and transform to the other one. var EndpointRelationFlags = append( - EndpointFlags, + append(EndpointFlags[len(ServiceFlags):], ServiceRelationFlags...), &cli.StringFlag{ Name: "dest-endpoint-id", diff --git a/test/test.yaml b/test/test.yaml index 75bbbbe1..4cfc28c7 100644 --- a/test/test.yaml +++ b/test/test.yaml @@ -70,6 +70,10 @@ verify: expected: expected/metrics-has-value.yml - query: swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql metrics linear --name=endpoint_sla --service-name provider --endpoint-name /users | yq e 'to_entries' - expected: expected/metrics-has-value.yml + - query: swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql metrics linear --name=service_relation_client_cpm --service-name consumer --dest-service-name provider | yq e 'to_entries' - + expected: expected/metrics-has-value.yml + - query: swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql metrics linear --name=service_instance_relation_client_cpm --service-name consumer --instance-name consumer1 --dest-service-name provider --dest-instance-name provider1 | yq e 'to_entries' - + expected: expected/metrics-has-value.yml - query: swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql metrics single --name endpoint_cpm --service-name provider --endpoint-name /users expected: expected/value.yml