Support sampling config in network profiling (#171)
diff --git a/CHANGES.md b/CHANGES.md
index 76d865b..fea6fa6 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -33,6 +33,7 @@
* Add compatibility documentation by @mrproliu in https://github.com/apache/skywalking-cli/pull/164
* Add the sub-command `records list` for adapt the new record query API by @mrproliu in https://github.com/apache/skywalking-cli/pull/167
* Add the attached events fields into the `trace` sub-command by @mrproliu in https://github.com/apache/skywalking-cli/pull/169
+* Add the sampling config file into the `profiling ebpf create network` sub-command by @mrproliu in https://github.com/apache/skywalking-cli/pull/171
0.10.0
------------------
diff --git a/dist/LICENSE b/dist/LICENSE
index d9b8a30..a9a7c66 100644
--- a/dist/LICENSE
+++ b/dist/LICENSE
@@ -213,7 +213,7 @@
k8s.io/utils v0.0.0-20210802155522-efc7438f0176 Apache-2.0
sigs.k8s.io/controller-runtime v0.10.0 Apache-2.0
sigs.k8s.io/structured-merge-diff/v4 v4.1.2 Apache-2.0
- skywalking.apache.org/repo/goapi v0.0.0-20221019074310-53ebda305187 Apache-2.0
+ skywalking.apache.org/repo/goapi v0.0.0-20221123034834-51b3101f6c9f Apache-2.0
========================================================================
BSD-2-Clause licenses
diff --git a/examples/network-sampling.yaml b/examples/network-sampling.yaml
new file mode 100644
index 0000000..4d86561
--- /dev/null
+++ b/examples/network-sampling.yaml
@@ -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.
+
+# The command `dashboard global` supports displaying three kinds of data:
+# `global metrics`, `global response latency`, `Global heat map`.
+# If you don't want to display an item, you can just delete or comment its whole configuration below.
+# Generally, there is no need to modify properties unless there is a explanatory comment.
+
+# Sampling config
+# samplings: the sampling config list
+# - uri_pattern: <optional> string. The match pattern for HTTP request. This is HTTP URI-oriented. matches all requests if not set
+# min_duration: <optional> int(ms). The minimal request duration to activate the network data(HTTP request/response raw data) sampling.
+# when_4xx: <required> bool. Collecting requests when the response code is 400-499.
+# when_5xx: <required> bool. Collecting requests when the response code is 500-599.
+# setting: define how to collect sampled data
+# require_request: <required> bool. Require to collect the complete request.
+# max_request_size: <optional> int. The max size of request context. The unit is byte.
+# require_response: <required> bool. Require to collect the complete response.
+# max_response_size: <optional> int. The max size of response context. The unit is byte.
+
+samplings:
+ # define collecting full request data when the response code is 400-499 and 500-599 .
+ - when_4xx: true
+ when_5xx: true
+ setting:
+ require_request: true
+ require_response: false
+ # define collecting first 1KB response data when the response code is 500-599 and the duration bigger than or equals 10ms.
+ - uri_pattern: /index.html
+ when_4xx: false
+ when_5xx: true
+ min_duration: 10
+ setting:
+ require_request: false
+ require_response: true
+ max_response_size: 1024
\ No newline at end of file
diff --git a/go.mod b/go.mod
index a5beccc..a86f33f 100644
--- a/go.mod
+++ b/go.mod
@@ -20,7 +20,7 @@
gopkg.in/yaml.v2 v2.4.0
k8s.io/apimachinery v0.22.1
sigs.k8s.io/controller-runtime v0.10.0
- skywalking.apache.org/repo/goapi v0.0.0-20221019074310-53ebda305187
+ skywalking.apache.org/repo/goapi v0.0.0-20221123034834-51b3101f6c9f
)
require (
diff --git a/go.sum b/go.sum
index 4bc7dae..5204896 100644
--- a/go.sum
+++ b/go.sum
@@ -857,5 +857,5 @@
sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4=
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
-skywalking.apache.org/repo/goapi v0.0.0-20221019074310-53ebda305187 h1:6JgAg9aohcHd72VplZUGycZgCNo6iQrz735nmtOTCnE=
-skywalking.apache.org/repo/goapi v0.0.0-20221019074310-53ebda305187/go.mod h1:lxmYWY1uAP5SLVKNymAyDzn7KG6dhPWN+pYHmyt+0vo=
+skywalking.apache.org/repo/goapi v0.0.0-20221123034834-51b3101f6c9f h1:iRQHKYsca0gbSxGWFjlkQ/WIuLyKReFUk2PscgzBqAw=
+skywalking.apache.org/repo/goapi v0.0.0-20221123034834-51b3101f6c9f/go.mod h1:lxmYWY1uAP5SLVKNymAyDzn7KG6dhPWN+pYHmyt+0vo=
diff --git a/internal/commands/profiling/ebpf/create/network.go b/internal/commands/profiling/ebpf/create/network.go
index aadf2c8..b30c86b 100644
--- a/internal/commands/profiling/ebpf/create/network.go
+++ b/internal/commands/profiling/ebpf/create/network.go
@@ -18,17 +18,41 @@
package create
import (
+ "fmt"
+ "os"
+
"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"
+ "gopkg.in/yaml.v2"
+
"github.com/urfave/cli/v2"
api "skywalking.apache.org/repo/goapi/query"
)
+type SamplingConfig struct {
+ Samplings []*SamplingRule `yaml:"samplings"`
+}
+
+type SamplingRule struct {
+ URIPattern *string `yaml:"uri_pattern"`
+ MinDuration *int `yaml:"min_duration"`
+ When4xx *bool `yaml:"when_4xx"`
+ When5xx *bool `yaml:"when_5xx"`
+ Setting *SamplingSetting `yaml:"setting"`
+}
+
+type SamplingSetting struct {
+ RequireRequest *bool `yaml:"require_request"`
+ MaxRequestSize *int `yaml:"max_request_size"`
+ RequireResponse *bool `yaml:"require_response"`
+ MaxResponseSize *int `yaml:"max_response_size"`
+}
+
var NetworkCreateCommand = &cli.Command{
Name: "network",
Aliases: []string{"net"},
@@ -41,6 +65,13 @@
Flags: flags.Flags(
flags.ServiceFlags,
flags.InstanceFlags,
+ []cli.Flag{
+ &cli.StringFlag{
+ Name: "sampling-config",
+ Usage: "the `sampling-config` file define how to sampling the network data, if not then then ignore data sampling",
+ Required: false,
+ },
+ },
),
Before: interceptor.BeforeChain(
interceptor.ParseInstance(true),
@@ -48,8 +79,29 @@
Action: func(ctx *cli.Context) error {
instanceID := ctx.String("instance-id")
+ samplingConfigFile := ctx.String("sampling-config")
+
+ // convert the sampling rule
+ var samplings = make([]*api.EBPFNetworkSamplingRule, 0)
+ if samplingConfigFile != "" {
+ config, err := os.ReadFile(samplingConfigFile)
+ if err != nil {
+ return err
+ }
+ r := &SamplingConfig{}
+ if e := yaml.Unmarshal(config, r); e != nil {
+ return e
+ }
+
+ samplings, err = parsingNetworkSampling(r)
+ if err != nil {
+ return err
+ }
+ }
+
request := &api.EBPFProfilingNetworkTaskRequest{
InstanceID: instanceID,
+ Samplings: samplings,
}
task, err := profiling.CreateEBPFNetworkProfilingTask(ctx, request)
@@ -61,3 +113,44 @@
return display.Display(ctx, &displayable.Displayable{Data: task, Condition: request})
},
}
+
+func parsingNetworkSampling(config *SamplingConfig) ([]*api.EBPFNetworkSamplingRule, error) {
+ rules := make([]*api.EBPFNetworkSamplingRule, 0)
+ if config == nil || len(config.Samplings) == 0 {
+ return rules, nil
+ }
+ for _, conf := range config.Samplings {
+ rule := &api.EBPFNetworkSamplingRule{}
+ rule.URIRegex = conf.URIPattern
+ rule.MinDuration = conf.MinDuration
+ if conf.When4xx == nil {
+ return nil, fmt.Errorf("the when_4xx is required")
+ }
+ rule.When4xx = *conf.When4xx
+ if conf.When5xx == nil {
+ return nil, fmt.Errorf("the when_5xx is required")
+ }
+ rule.When5xx = *conf.When5xx
+
+ confSetting := conf.Setting
+ if confSetting == nil {
+ return nil, fmt.Errorf("the sampling settings is required")
+ }
+ setting := &api.EBPFNetworkDataCollectingSettings{}
+ rule.Settings = setting
+ if confSetting.RequireRequest == nil {
+ return nil, fmt.Errorf("the sampling request is required")
+ }
+ setting.RequireCompleteRequest = *confSetting.RequireRequest
+ setting.MaxRequestSize = confSetting.MaxRequestSize
+ if confSetting.RequireResponse == nil {
+ return nil, fmt.Errorf("the sampling response is required")
+ }
+ setting.RequireCompleteResponse = *confSetting.RequireResponse
+ setting.MaxResponseSize = confSetting.MaxResponseSize
+
+ rules = append(rules, rule)
+ }
+
+ return rules, nil
+}