Merge remote-tracking branch 'apache/master' into feature/graphql-client
diff --git a/.asf.yaml b/.asf.yaml
index 3f2645a..c1f6dfa 100644
--- a/.asf.yaml
+++ b/.asf.yaml
@@ -1,3 +1,20 @@
+#
+# Licensed to the 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.
+# The 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.
+#
+
github:
description: Apache SkyWalking CLI
homepage: https://skywalking.apache.org/
diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml
index bdc008c..1abc12e 100644
--- a/.github/workflows/go.yml
+++ b/.github/workflows/go.yml
@@ -23,22 +23,22 @@
runs-on: ubuntu-latest
steps:
- - name: Set up Go 1.13
- uses: actions/setup-go@v1
- with:
- go-version: 1.13
- id: go
+ - name: Set up Go 1.13
+ uses: actions/setup-go@v1
+ with:
+ go-version: 1.13
+ id: go
- - name: Check out code into the Go module directory
- uses: actions/checkout@v1
+ - name: Check out code into the Go module directory
+ uses: actions/checkout@v1
- - name: Get dependencies
- run: |
- go get -v -t -d ./...
- if [ -f Gopkg.toml ]; then
- curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
- dep ensure
- fi
+ - name: Get dependencies
+ run: |
+ go get -v -t -d ./...
+ if [ -f Gopkg.toml ]; then
+ curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
+ dep ensure
+ fi
- - name: Build
- run: make
+ - name: Build
+ run: make
diff --git a/Makefile b/Makefile
index 03d2d59..3273175 100644
--- a/Makefile
+++ b/Makefile
@@ -19,4 +19,7 @@
build:
GO_BUILD_FLAGS="-v" ./scripts/build
- ./bin/swctl --version
\ No newline at end of file
+ ./bin/swctl --version
+
+clean:
+ -rm -rf ./bin
\ No newline at end of file
diff --git a/commands/interceptor.go b/commands/interceptor.go
new file mode 100644
index 0000000..6837529
--- /dev/null
+++ b/commands/interceptor.go
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the 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.
+ * The 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 commands
+
+import (
+ "github.com/apache/skywalking-cli/graphql/schema"
+ "github.com/apache/skywalking-cli/logger"
+ "github.com/urfave/cli"
+ "time"
+)
+
+// Convenient function to chain up multiple cli.BeforeFunc
+func BeforeChain(beforeFunctions []cli.BeforeFunc) cli.BeforeFunc {
+ return func(ctx *cli.Context) error {
+ for _, beforeFunc := range beforeFunctions {
+ if err := beforeFunc(ctx); err != nil {
+ return err
+ }
+ }
+ return nil
+ }
+}
+
+var StepFormats = map[schema.Step]string{
+ schema.StepMonth: "2006-01-02",
+ schema.StepDay: "2006-01-02",
+ schema.StepHour: "2006-01-02 15",
+ schema.StepMinute: "2006-01-02 1504",
+ schema.StepSecond: "2006-01-02 1504",
+}
+
+// Set the duration if not set, and format it according to
+// the given step
+func SetUpDuration(ctx *cli.Context) error {
+ step := ctx.Generic("step").(*StepEnumValue).Selected
+ end := ctx.String("end")
+ if len(end) == 0 {
+ end = time.Now().Format(StepFormats[step])
+ logger.Log.Debugln("Missing --end, defaults to", end)
+ if err := ctx.Set("end", end); err != nil {
+ return err
+ }
+ }
+
+ start := ctx.String("start")
+ if len(start) == 0 {
+ start = time.Now().Add(-15 * time.Minute).Format(StepFormats[step])
+ logger.Log.Debugln("Missing --start, defaults to", start)
+ if err := ctx.Set("start", start); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
diff --git a/commands/model.go b/commands/model.go
new file mode 100644
index 0000000..9da2fba
--- /dev/null
+++ b/commands/model.go
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the 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.
+ * The 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 commands
+
+import (
+ "fmt"
+ "github.com/apache/skywalking-cli/graphql/schema"
+ "strings"
+)
+
+type StepEnumValue struct {
+ Enum []schema.Step
+ Default schema.Step
+ Selected schema.Step
+}
+
+func (s *StepEnumValue) Set(value string) error {
+ for _, enum := range s.Enum {
+ if enum.String() == value {
+ s.Selected = enum
+ return nil
+ }
+ }
+ steps := make([]string, len(schema.AllStep))
+ for i, step := range schema.AllStep {
+ steps[i] = step.String()
+ }
+ return fmt.Errorf("allowed steps are %s", strings.Join(steps, ", "))
+}
+
+func (s StepEnumValue) String() string {
+ return s.Selected.String()
+}
diff --git a/commands/service/list.go b/commands/service/list.go
new file mode 100644
index 0000000..e2c91af
--- /dev/null
+++ b/commands/service/list.go
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the 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.
+ * The 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 service
+
+import (
+ "encoding/json"
+ "fmt"
+ "github.com/apache/skywalking-cli/commands"
+ "github.com/apache/skywalking-cli/graphql/client"
+ "github.com/apache/skywalking-cli/graphql/schema"
+ "github.com/urfave/cli"
+)
+
+var ListCommand = cli.Command{
+ Name: "list",
+ ShortName: "ls",
+ Usage: "List all available services",
+ Flags: []cli.Flag{
+ cli.StringFlag{
+ Name: "start",
+ Usage: "Query start time",
+ },
+ cli.StringFlag{
+ Name: "end",
+ Usage: "Query end time",
+ },
+ cli.GenericFlag{
+ Name: "step",
+ Value: &commands.StepEnumValue{
+ Enum: schema.AllStep,
+ Default: schema.StepMinute,
+ Selected: schema.StepMinute,
+ },
+ },
+ },
+ Before: commands.BeforeChain([]cli.BeforeFunc{
+ commands.SetUpDuration,
+ }),
+ Action: func(ctx *cli.Context) error {
+ end := ctx.String("end")
+ start := ctx.String("start")
+ step := ctx.Generic("step")
+ services := client.Services(schema.Duration{
+ Start: start,
+ End: end,
+ Step: step.(*commands.StepEnumValue).Selected,
+ })
+
+ if bytes, e := json.Marshal(services); e != nil {
+ return e
+ } else {
+ fmt.Printf("%v\n", string(bytes))
+ }
+
+ return nil
+ },
+}
diff --git a/commands/service/service.go b/commands/service/service.go
new file mode 100644
index 0000000..5760adf
--- /dev/null
+++ b/commands/service/service.go
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the 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.
+ * The 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 service
+
+import (
+ "github.com/urfave/cli"
+)
+
+var Command = cli.Command{
+ Name: "service",
+ ShortName: "s",
+ Usage: "Service related sub-command",
+ Subcommands: cli.Commands{
+ ListCommand,
+ },
+}
diff --git a/config/config.go b/config/config.go
new file mode 100644
index 0000000..bc33da2
--- /dev/null
+++ b/config/config.go
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the 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.
+ * The 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 config
+
+var Config struct {
+ Global struct {
+ BaseUrl string `yaml:"base-url"`
+ }
+}
diff --git a/go.mod b/go.mod
index 8d79e73..062d750 100644
--- a/go.mod
+++ b/go.mod
@@ -3,7 +3,8 @@
go 1.13
require (
- github.com/lytics/logrus v0.0.0-20170528191427-4389a17ed024 // indirect
+ github.com/machinebox/graphql v0.2.2
+ github.com/pkg/errors v0.8.1 // indirect
github.com/sirupsen/logrus v1.4.2
github.com/urfave/cli v1.22.1
)
diff --git a/go.sum b/go.sum
index 7860264..7627702 100644
--- a/go.sum
+++ b/go.sum
@@ -5,6 +5,10 @@
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/lytics/logrus v0.0.0-20170528191427-4389a17ed024 h1:QaKVrqyQRNPbdBNCpiU0Ei3iDQko3qoiUUXMiTWhzZM=
github.com/lytics/logrus v0.0.0-20170528191427-4389a17ed024/go.mod h1:SkQviJ2s7rFyzyuxdVp6osZceHOabU91ZhKsEXF0RWg=
+github.com/machinebox/graphql v0.2.2 h1:dWKpJligYKhYKO5A2gvNhkJdQMNZeChZYyBbrZkBZfo=
+github.com/machinebox/graphql v0.2.2/go.mod h1:F+kbVMHuwrQ5tYgU9JXlnskM8nOaFxCAEolaQybkjWA=
+github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
+github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
@@ -19,4 +23,5 @@
golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
diff --git a/graphql/client/client.go b/graphql/client/client.go
new file mode 100644
index 0000000..10a680a
--- /dev/null
+++ b/graphql/client/client.go
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the 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.
+ * The 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 client
+
+import (
+ "context"
+ "github.com/apache/skywalking-cli/config"
+ "github.com/apache/skywalking-cli/graphql/schema"
+ "github.com/apache/skywalking-cli/logger"
+ "github.com/machinebox/graphql"
+)
+
+func Services(duration schema.Duration) []schema.Service {
+ ctx := context.Background()
+ client := graphql.NewClient(config.Config.Global.BaseUrl)
+ client.Log = func(msg string) {
+ logger.Log.Debugln(msg)
+ }
+
+ var services map[string][]schema.Service
+ request := graphql.NewRequest(`
+ query ($duration: Duration!) {
+ services: getAllServices(duration: $duration) {
+ id name
+ }
+ }
+ `)
+ request.Var("duration", duration)
+ if err := client.Run(ctx, request, &services); err != nil {
+ logger.Log.Fatalln(err)
+ panic(err)
+ }
+
+ return services["services"]
+}
diff --git a/graphql/schema/schema.go b/graphql/schema/schema.go
new file mode 100644
index 0000000..d3848d5
--- /dev/null
+++ b/graphql/schema/schema.go
@@ -0,0 +1,750 @@
+/*
+ * Licensed to the 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.
+ * The 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 schema
+
+import (
+ "fmt"
+ "io"
+ "strconv"
+)
+
+type AlarmMessage struct {
+ StartTime int64 `json:"startTime"`
+ Scope *Scope `json:"scope"`
+ ID string `json:"id"`
+ Message string `json:"message"`
+}
+
+type AlarmTrend struct {
+ NumOfAlarm []*int `json:"numOfAlarm"`
+}
+
+type Alarms struct {
+ Msgs []*AlarmMessage `json:"msgs"`
+ Total int `json:"total"`
+}
+
+type Attribute struct {
+ Name string `json:"name"`
+ Value string `json:"value"`
+}
+
+type BasicTrace struct {
+ SegmentID string `json:"segmentId"`
+ EndpointNames []string `json:"endpointNames"`
+ Duration int `json:"duration"`
+ Start string `json:"start"`
+ IsError *bool `json:"isError"`
+ TraceIds []string `json:"traceIds"`
+}
+
+type BatchMetricConditions struct {
+ Name string `json:"name"`
+ Ids []string `json:"ids"`
+}
+
+type Call struct {
+ Source string `json:"source"`
+ SourceComponents []string `json:"sourceComponents"`
+ Target string `json:"target"`
+ TargetComponents []string `json:"targetComponents"`
+ ID string `json:"id"`
+ DetectPoints []DetectPoint `json:"detectPoints"`
+}
+
+type ClusterBrief struct {
+ NumOfService int `json:"numOfService"`
+ NumOfEndpoint int `json:"numOfEndpoint"`
+ NumOfDatabase int `json:"numOfDatabase"`
+ NumOfCache int `json:"numOfCache"`
+ NumOfMq int `json:"numOfMQ"`
+}
+
+type Database struct {
+ ID string `json:"id"`
+ Name string `json:"name"`
+ Type string `json:"type"`
+}
+
+type Duration struct {
+ Start string `json:"start"`
+ End string `json:"end"`
+ Step Step `json:"step"`
+}
+
+type Endpoint struct {
+ ID string `json:"id"`
+ Name string `json:"name"`
+}
+
+type EndpointInfo struct {
+ ID string `json:"id"`
+ Name string `json:"name"`
+ ServiceID string `json:"serviceId"`
+ ServiceName string `json:"serviceName"`
+}
+
+type IntValues struct {
+ Values []*KVInt `json:"values"`
+}
+
+type KVInt struct {
+ ID string `json:"id"`
+ Value int64 `json:"value"`
+}
+
+type KeyValue struct {
+ Key string `json:"key"`
+ Value *string `json:"value"`
+}
+
+type Log struct {
+ ServiceName *string `json:"serviceName"`
+ ServiceID *string `json:"serviceId"`
+ ServiceInstanceName *string `json:"serviceInstanceName"`
+ ServiceInstanceID *string `json:"serviceInstanceId"`
+ EndpointName *string `json:"endpointName"`
+ EndpointID *string `json:"endpointId"`
+ TraceID *string `json:"traceId"`
+ Timestamp string `json:"timestamp"`
+ IsError *bool `json:"isError"`
+ StatusCode *string `json:"statusCode"`
+ ContentType ContentType `json:"contentType"`
+ Content *string `json:"content"`
+}
+
+type LogEntity struct {
+ Time int64 `json:"time"`
+ Data []*KeyValue `json:"data"`
+}
+
+type LogQueryCondition struct {
+ MetricName *string `json:"metricName"`
+ ServiceID *string `json:"serviceId"`
+ ServiceInstanceID *string `json:"serviceInstanceId"`
+ EndpointID *string `json:"endpointId"`
+ TraceID *string `json:"traceId"`
+ QueryDuration *Duration `json:"queryDuration"`
+ State LogState `json:"state"`
+ StateCode *string `json:"stateCode"`
+ Paging *Pagination `json:"paging"`
+}
+
+type Logs struct {
+ Logs []*Log `json:"logs"`
+ Total int `json:"total"`
+}
+
+type MetricCondition struct {
+ Name string `json:"name"`
+ ID *string `json:"id"`
+}
+
+type Node struct {
+ ID string `json:"id"`
+ Name string `json:"name"`
+ Type *string `json:"type"`
+ IsReal bool `json:"isReal"`
+}
+
+type Pagination struct {
+ PageNum *int `json:"pageNum"`
+ PageSize int `json:"pageSize"`
+ NeedTotal *bool `json:"needTotal"`
+}
+
+type Ref struct {
+ TraceID string `json:"traceId"`
+ ParentSegmentID string `json:"parentSegmentId"`
+ ParentSpanID int `json:"parentSpanId"`
+ Type RefType `json:"type"`
+}
+
+type Service struct {
+ ID string `json:"id"`
+ Name string `json:"name"`
+}
+
+type ServiceInstance struct {
+ ID string `json:"id"`
+ Name string `json:"name"`
+ Attributes []*Attribute `json:"attributes"`
+ Language Language `json:"language"`
+ InstanceUUID string `json:"instanceUUID"`
+}
+
+type Span struct {
+ TraceID string `json:"traceId"`
+ SegmentID string `json:"segmentId"`
+ SpanID int `json:"spanId"`
+ ParentSpanID int `json:"parentSpanId"`
+ Refs []*Ref `json:"refs"`
+ ServiceCode string `json:"serviceCode"`
+ StartTime int64 `json:"startTime"`
+ EndTime int64 `json:"endTime"`
+ EndpointName *string `json:"endpointName"`
+ Type string `json:"type"`
+ Peer *string `json:"peer"`
+ Component *string `json:"component"`
+ IsError *bool `json:"isError"`
+ Layer *string `json:"layer"`
+ Tags []*KeyValue `json:"tags"`
+ Logs []*LogEntity `json:"logs"`
+}
+
+type Thermodynamic struct {
+ Nodes [][]*int `json:"nodes"`
+ AxisYStep int `json:"axisYStep"`
+}
+
+type TimeInfo struct {
+ Timezone *string `json:"timezone"`
+ CurrentTimestamp *int64 `json:"currentTimestamp"`
+}
+
+type TopNEntity struct {
+ Name string `json:"name"`
+ ID string `json:"id"`
+ Value int64 `json:"value"`
+}
+
+type TopNRecord struct {
+ Statement *string `json:"statement"`
+ Latency int64 `json:"latency"`
+ TraceID *string `json:"traceId"`
+}
+
+type TopNRecordsCondition struct {
+ ServiceID string `json:"serviceId"`
+ MetricName string `json:"metricName"`
+ TopN int `json:"topN"`
+ Order Order `json:"order"`
+ Duration *Duration `json:"duration"`
+}
+
+type Topology struct {
+ Nodes []*Node `json:"nodes"`
+ Calls []*Call `json:"calls"`
+}
+
+type Trace struct {
+ Spans []*Span `json:"spans"`
+}
+
+type TraceBrief struct {
+ Traces []*BasicTrace `json:"traces"`
+ Total int `json:"total"`
+}
+
+type TraceQueryCondition struct {
+ ServiceID *string `json:"serviceId"`
+ ServiceInstanceID *string `json:"serviceInstanceId"`
+ TraceID *string `json:"traceId"`
+ EndpointID *string `json:"endpointId"`
+ EndpointName *string `json:"endpointName"`
+ QueryDuration *Duration `json:"queryDuration"`
+ MinTraceDuration *int `json:"minTraceDuration"`
+ MaxTraceDuration *int `json:"maxTraceDuration"`
+ TraceState TraceState `json:"traceState"`
+ QueryOrder QueryOrder `json:"queryOrder"`
+ Paging *Pagination `json:"paging"`
+}
+
+type ContentType string
+
+const (
+ ContentTypeText ContentType = "TEXT"
+ ContentTypeJSON ContentType = "JSON"
+ ContentTypeNone ContentType = "NONE"
+)
+
+var AllContentType = []ContentType{
+ ContentTypeText,
+ ContentTypeJSON,
+ ContentTypeNone,
+}
+
+func (e ContentType) IsValid() bool {
+ switch e {
+ case ContentTypeText, ContentTypeJSON, ContentTypeNone:
+ return true
+ }
+ return false
+}
+
+func (e ContentType) String() string {
+ return string(e)
+}
+
+func (e *ContentType) UnmarshalGQL(v interface{}) error {
+ str, ok := v.(string)
+ if !ok {
+ return fmt.Errorf("enums must be strings")
+ }
+
+ *e = ContentType(str)
+ if !e.IsValid() {
+ return fmt.Errorf("%s is not a valid ContentType", str)
+ }
+ return nil
+}
+
+func (e ContentType) MarshalGQL(w io.Writer) {
+ fmt.Fprint(w, strconv.Quote(e.String()))
+}
+
+type DetectPoint string
+
+const (
+ DetectPointClient DetectPoint = "CLIENT"
+ DetectPointServer DetectPoint = "SERVER"
+ DetectPointProxy DetectPoint = "PROXY"
+)
+
+var AllDetectPoint = []DetectPoint{
+ DetectPointClient,
+ DetectPointServer,
+ DetectPointProxy,
+}
+
+func (e DetectPoint) IsValid() bool {
+ switch e {
+ case DetectPointClient, DetectPointServer, DetectPointProxy:
+ return true
+ }
+ return false
+}
+
+func (e DetectPoint) String() string {
+ return string(e)
+}
+
+func (e *DetectPoint) UnmarshalGQL(v interface{}) error {
+ str, ok := v.(string)
+ if !ok {
+ return fmt.Errorf("enums must be strings")
+ }
+
+ *e = DetectPoint(str)
+ if !e.IsValid() {
+ return fmt.Errorf("%s is not a valid DetectPoint", str)
+ }
+ return nil
+}
+
+func (e DetectPoint) MarshalGQL(w io.Writer) {
+ fmt.Fprint(w, strconv.Quote(e.String()))
+}
+
+type Language string
+
+const (
+ LanguageUnknown Language = "UNKNOWN"
+ LanguageJava Language = "JAVA"
+ LanguageDotnet Language = "DOTNET"
+ LanguageNodejs Language = "NODEJS"
+ LanguagePython Language = "PYTHON"
+ LanguageRuby Language = "RUBY"
+)
+
+var AllLanguage = []Language{
+ LanguageUnknown,
+ LanguageJava,
+ LanguageDotnet,
+ LanguageNodejs,
+ LanguagePython,
+ LanguageRuby,
+}
+
+func (e Language) IsValid() bool {
+ switch e {
+ case LanguageUnknown, LanguageJava, LanguageDotnet, LanguageNodejs, LanguagePython, LanguageRuby:
+ return true
+ }
+ return false
+}
+
+func (e Language) String() string {
+ return string(e)
+}
+
+func (e *Language) UnmarshalGQL(v interface{}) error {
+ str, ok := v.(string)
+ if !ok {
+ return fmt.Errorf("enums must be strings")
+ }
+
+ *e = Language(str)
+ if !e.IsValid() {
+ return fmt.Errorf("%s is not a valid Language", str)
+ }
+ return nil
+}
+
+func (e Language) MarshalGQL(w io.Writer) {
+ fmt.Fprint(w, strconv.Quote(e.String()))
+}
+
+type LogState string
+
+const (
+ LogStateAll LogState = "ALL"
+ LogStateSuccess LogState = "SUCCESS"
+ LogStateError LogState = "ERROR"
+)
+
+var AllLogState = []LogState{
+ LogStateAll,
+ LogStateSuccess,
+ LogStateError,
+}
+
+func (e LogState) IsValid() bool {
+ switch e {
+ case LogStateAll, LogStateSuccess, LogStateError:
+ return true
+ }
+ return false
+}
+
+func (e LogState) String() string {
+ return string(e)
+}
+
+func (e *LogState) UnmarshalGQL(v interface{}) error {
+ str, ok := v.(string)
+ if !ok {
+ return fmt.Errorf("enums must be strings")
+ }
+
+ *e = LogState(str)
+ if !e.IsValid() {
+ return fmt.Errorf("%s is not a valid LogState", str)
+ }
+ return nil
+}
+
+func (e LogState) MarshalGQL(w io.Writer) {
+ fmt.Fprint(w, strconv.Quote(e.String()))
+}
+
+type NodeType string
+
+const (
+ NodeTypeService NodeType = "SERVICE"
+ NodeTypeEndpoint NodeType = "ENDPOINT"
+ NodeTypeUser NodeType = "USER"
+)
+
+var AllNodeType = []NodeType{
+ NodeTypeService,
+ NodeTypeEndpoint,
+ NodeTypeUser,
+}
+
+func (e NodeType) IsValid() bool {
+ switch e {
+ case NodeTypeService, NodeTypeEndpoint, NodeTypeUser:
+ return true
+ }
+ return false
+}
+
+func (e NodeType) String() string {
+ return string(e)
+}
+
+func (e *NodeType) UnmarshalGQL(v interface{}) error {
+ str, ok := v.(string)
+ if !ok {
+ return fmt.Errorf("enums must be strings")
+ }
+
+ *e = NodeType(str)
+ if !e.IsValid() {
+ return fmt.Errorf("%s is not a valid NodeType", str)
+ }
+ return nil
+}
+
+func (e NodeType) MarshalGQL(w io.Writer) {
+ fmt.Fprint(w, strconv.Quote(e.String()))
+}
+
+type Order string
+
+const (
+ OrderAsc Order = "ASC"
+ OrderDes Order = "DES"
+)
+
+var AllOrder = []Order{
+ OrderAsc,
+ OrderDes,
+}
+
+func (e Order) IsValid() bool {
+ switch e {
+ case OrderAsc, OrderDes:
+ return true
+ }
+ return false
+}
+
+func (e Order) String() string {
+ return string(e)
+}
+
+func (e *Order) UnmarshalGQL(v interface{}) error {
+ str, ok := v.(string)
+ if !ok {
+ return fmt.Errorf("enums must be strings")
+ }
+
+ *e = Order(str)
+ if !e.IsValid() {
+ return fmt.Errorf("%s is not a valid Order", str)
+ }
+ return nil
+}
+
+func (e Order) MarshalGQL(w io.Writer) {
+ fmt.Fprint(w, strconv.Quote(e.String()))
+}
+
+type QueryOrder string
+
+const (
+ QueryOrderByStartTime QueryOrder = "BY_START_TIME"
+ QueryOrderByDuration QueryOrder = "BY_DURATION"
+)
+
+var AllQueryOrder = []QueryOrder{
+ QueryOrderByStartTime,
+ QueryOrderByDuration,
+}
+
+func (e QueryOrder) IsValid() bool {
+ switch e {
+ case QueryOrderByStartTime, QueryOrderByDuration:
+ return true
+ }
+ return false
+}
+
+func (e QueryOrder) String() string {
+ return string(e)
+}
+
+func (e *QueryOrder) UnmarshalGQL(v interface{}) error {
+ str, ok := v.(string)
+ if !ok {
+ return fmt.Errorf("enums must be strings")
+ }
+
+ *e = QueryOrder(str)
+ if !e.IsValid() {
+ return fmt.Errorf("%s is not a valid QueryOrder", str)
+ }
+ return nil
+}
+
+func (e QueryOrder) MarshalGQL(w io.Writer) {
+ fmt.Fprint(w, strconv.Quote(e.String()))
+}
+
+type RefType string
+
+const (
+ RefTypeCrossProcess RefType = "CROSS_PROCESS"
+ RefTypeCrossThread RefType = "CROSS_THREAD"
+)
+
+var AllRefType = []RefType{
+ RefTypeCrossProcess,
+ RefTypeCrossThread,
+}
+
+func (e RefType) IsValid() bool {
+ switch e {
+ case RefTypeCrossProcess, RefTypeCrossThread:
+ return true
+ }
+ return false
+}
+
+func (e RefType) String() string {
+ return string(e)
+}
+
+func (e *RefType) UnmarshalGQL(v interface{}) error {
+ str, ok := v.(string)
+ if !ok {
+ return fmt.Errorf("enums must be strings")
+ }
+
+ *e = RefType(str)
+ if !e.IsValid() {
+ return fmt.Errorf("%s is not a valid RefType", str)
+ }
+ return nil
+}
+
+func (e RefType) MarshalGQL(w io.Writer) {
+ fmt.Fprint(w, strconv.Quote(e.String()))
+}
+
+type Scope string
+
+const (
+ ScopeService Scope = "Service"
+ ScopeServiceInstance Scope = "ServiceInstance"
+ ScopeEndpoint Scope = "Endpoint"
+ ScopeServiceRelation Scope = "ServiceRelation"
+ ScopeServiceInstanceRelation Scope = "ServiceInstanceRelation"
+ ScopeEndpointRelation Scope = "EndpointRelation"
+)
+
+var AllScope = []Scope{
+ ScopeService,
+ ScopeServiceInstance,
+ ScopeEndpoint,
+ ScopeServiceRelation,
+ ScopeServiceInstanceRelation,
+ ScopeEndpointRelation,
+}
+
+func (e Scope) IsValid() bool {
+ switch e {
+ case ScopeService, ScopeServiceInstance, ScopeEndpoint, ScopeServiceRelation, ScopeServiceInstanceRelation, ScopeEndpointRelation:
+ return true
+ }
+ return false
+}
+
+func (e Scope) String() string {
+ return string(e)
+}
+
+func (e *Scope) UnmarshalGQL(v interface{}) error {
+ str, ok := v.(string)
+ if !ok {
+ return fmt.Errorf("enums must be strings")
+ }
+
+ *e = Scope(str)
+ if !e.IsValid() {
+ return fmt.Errorf("%s is not a valid Scope", str)
+ }
+ return nil
+}
+
+func (e Scope) MarshalGQL(w io.Writer) {
+ fmt.Fprint(w, strconv.Quote(e.String()))
+}
+
+type Step string
+
+const (
+ StepMonth Step = "MONTH"
+ StepDay Step = "DAY"
+ StepHour Step = "HOUR"
+ StepMinute Step = "MINUTE"
+ StepSecond Step = "SECOND"
+)
+
+var AllStep = []Step{
+ StepMonth,
+ StepDay,
+ StepHour,
+ StepMinute,
+ StepSecond,
+}
+
+func (e Step) IsValid() bool {
+ switch e {
+ case StepMonth, StepDay, StepHour, StepMinute, StepSecond:
+ return true
+ }
+ return false
+}
+
+func (e Step) String() string {
+ return string(e)
+}
+
+func (e *Step) UnmarshalGQL(v interface{}) error {
+ str, ok := v.(string)
+ if !ok {
+ return fmt.Errorf("enums must be strings")
+ }
+
+ *e = Step(str)
+ if !e.IsValid() {
+ return fmt.Errorf("%s is not a valid Step", str)
+ }
+ return nil
+}
+
+func (e Step) MarshalGQL(w io.Writer) {
+ fmt.Fprint(w, strconv.Quote(e.String()))
+}
+
+type TraceState string
+
+const (
+ TraceStateAll TraceState = "ALL"
+ TraceStateSuccess TraceState = "SUCCESS"
+ TraceStateError TraceState = "ERROR"
+)
+
+var AllTraceState = []TraceState{
+ TraceStateAll,
+ TraceStateSuccess,
+ TraceStateError,
+}
+
+func (e TraceState) IsValid() bool {
+ switch e {
+ case TraceStateAll, TraceStateSuccess, TraceStateError:
+ return true
+ }
+ return false
+}
+
+func (e TraceState) String() string {
+ return string(e)
+}
+
+func (e *TraceState) UnmarshalGQL(v interface{}) error {
+ str, ok := v.(string)
+ if !ok {
+ return fmt.Errorf("enums must be strings")
+ }
+
+ *e = TraceState(str)
+ if !e.IsValid() {
+ return fmt.Errorf("%s is not a valid TraceState", str)
+ }
+ return nil
+}
+
+func (e TraceState) MarshalGQL(w io.Writer) {
+ fmt.Fprint(w, strconv.Quote(e.String()))
+}
diff --git a/scripts/build b/scripts/build
index 2e48690..7a20563 100755
--- a/scripts/build
+++ b/scripts/build
@@ -20,7 +20,7 @@
cli_build() {
out="bin"
CGO_ENABLED=0 go build $GO_BUILD_FLAGS \
- -o "${out}/swctl" cmd/* || return
+ -o "${out}/swctl" swctl/* || return
}
if echo "$0" | grep "build$" > /dev/null; then
diff --git a/swctl/main.go b/swctl/main.go
new file mode 100644
index 0000000..5619a28
--- /dev/null
+++ b/swctl/main.go
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the 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.
+ * The 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 main
+
+import (
+ "encoding/json"
+ "github.com/apache/skywalking-cli/commands/service"
+ "github.com/apache/skywalking-cli/config"
+ "github.com/sirupsen/logrus"
+ "github.com/urfave/cli"
+ "gopkg.in/yaml.v2"
+ "io/ioutil"
+ "os"
+
+ "github.com/apache/skywalking-cli/logger"
+)
+
+var log *logrus.Logger
+
+func init() {
+ log = logger.Log
+}
+
+func main() {
+ app := cli.NewApp()
+ app.Usage = "The CLI (Command Line Interface) for Apache SkyWalking."
+ app.Flags = []cli.Flag{
+ cli.StringFlag{
+ Name: "config",
+ Value: "./settings.yml",
+ Usage: "load configuration `FILE`, default to ./settings.yml",
+ },
+ cli.BoolFlag{
+ Name: "debug",
+ Required: false,
+ Usage: "enable debug mode, will print more detailed logs",
+ },
+ }
+ app.Commands = []cli.Command{
+ service.Command,
+ }
+
+ app.Before = BeforeCommand
+
+ if err := app.Run(os.Args); err != nil {
+ log.Fatalln(err)
+ }
+}
+
+func BeforeCommand(c *cli.Context) error {
+ if c.Bool("debug") {
+ log.SetLevel(logrus.DebugLevel)
+ log.Debugln("Debug mode is enabled")
+ }
+
+ configFile := c.String("config")
+ log.Debugln("Using configuration file:", configFile)
+
+ if bytes, err := ioutil.ReadFile(configFile); err != nil {
+ return err
+ } else if err := yaml.Unmarshal(bytes, &config.Config); err != nil {
+ return err
+ }
+
+ if bytes, err := json.Marshal(config.Config); err == nil {
+ log.Debugln("Configurations: ", string(bytes))
+ }
+
+ return nil
+}