Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ Release Notes.
* 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
------------------
Expand Down
2 changes: 1 addition & 1 deletion dist/LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ The text of each license is also included at licenses/license-[project].txt.
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
Expand Down
49 changes: 49 additions & 0 deletions examples/network-sampling.yaml
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ require (
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 (
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -857,5 +857,5 @@ sigs.k8s.io/structured-merge-diff/v4 v4.1.2 h1:Hr/htKFmJEbtMgS/UD0N+gtgctAqz81t3
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=
93 changes: 93 additions & 0 deletions internal/commands/profiling/ebpf/create/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"},
Expand All @@ -41,15 +65,43 @@ $ swctl profiling ebpf create network --service-instance-id=abc`,
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),
),
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)
Expand All @@ -61,3 +113,44 @@ $ swctl profiling ebpf create network --service-instance-id=abc`,
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
}