Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add latency switch #77

Merged
merged 1 commit into from
Jul 18, 2023
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
3 changes: 3 additions & 0 deletions charts/crds/kdoctor.io_apphttphealthies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,9 @@ spec:
type: string
bodyConfigmapNamespace:
type: string
enableLatencyMetric:
default: false
type: boolean
header:
items:
type: string
Expand Down
3 changes: 3 additions & 0 deletions charts/crds/kdoctor.io_netdnses.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,9 @@ spec:
x-kubernetes-map-type: atomic
target:
properties:
enableLatencyMetric:
default: false
type: boolean
targetDns:
properties:
serviceName:
Expand Down
3 changes: 3 additions & 0 deletions charts/crds/kdoctor.io_netreaches.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,9 @@ spec:
clusterIP:
default: true
type: boolean
enableLatencyMetric:
default: false
type: boolean
endpoint:
default: true
type: boolean
Expand Down
4 changes: 4 additions & 0 deletions pkg/k8s/apis/kdoctor.io/v1beta1/apphttphealthy_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ type AppHttpHealthyTarget struct {

// +kubebuilder:validation:Optional
Header []string `json:"header,omitempty"`

// +kubebuilder:default=false
// +kubebuilder:validation:Optional
EnableLatencyMetric bool `json:"enableLatencyMetric,omitempty"`
}

// scope(Namespaced or Cluster)
Expand Down
4 changes: 4 additions & 0 deletions pkg/k8s/apis/kdoctor.io/v1beta1/netdns_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ type NetDnsTarget struct {
NetDnsTargetUser *NetDnsTargetUserSpec `json:"targetUser,omitempty"`
// +kubebuilder:validation:Optional
NetDnsTargetDns *NetDnsTargetDnsSpec `json:"targetDns,omitempty"`

// +kubebuilder:default=false
// +kubebuilder:validation:Optional
EnableLatencyMetric bool `json:"enableLatencyMetric,omitempty"`
}

type NetDnsTargetUserSpec struct {
Expand Down
4 changes: 4 additions & 0 deletions pkg/k8s/apis/kdoctor.io/v1beta1/netreach_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ type NetReachTarget struct {

// +kubebuilder:default=false
Ingress bool `json:"ingress,omitempty"`

// +kubebuilder:default=false
// +kubebuilder:validation:Optional
EnableLatencyMetric bool `json:"enableLatencyMetric,omitempty"`
}

// scope(Namespaced or Cluster)
Expand Down
14 changes: 8 additions & 6 deletions pkg/loadRequest/loadDns/dns.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ type DnsRequestData struct {
PerRequestTimeoutInMs int
Qps int
DurationInSecond int
EnableLatencyMetric bool
}

func DnsRequest(logger *zap.Logger, reqData *DnsRequestData) (result *v1beta1.DNSMetrics, err error) {
Expand All @@ -52,12 +53,13 @@ func DnsRequest(logger *zap.Logger, reqData *DnsRequestData) (result *v1beta1.DN
duration := time.Duration(reqData.DurationInSecond) * time.Second

w := &Work{
Concurrency: config.AgentConfig.Configmap.NetdnsDefaultConcurrency,
QPS: reqData.Qps,
Timeout: reqData.PerRequestTimeoutInMs,
Msg: new(dns.Msg).SetQuestion(reqData.TargetDomain, reqData.DnsType),
Protocol: string(reqData.Protocol),
ServerAddr: reqData.DnsServerAddr,
Concurrency: config.AgentConfig.Configmap.NetdnsDefaultConcurrency,
QPS: reqData.Qps,
Timeout: reqData.PerRequestTimeoutInMs,
Msg: new(dns.Msg).SetQuestion(reqData.TargetDomain, reqData.DnsType),
Protocol: string(reqData.Protocol),
ServerAddr: reqData.DnsServerAddr,
EnableLatencyMetric: reqData.EnableLatencyMetric,
}
w.Init()

Expand Down
20 changes: 10 additions & 10 deletions pkg/loadRequest/loadDns/dns_reporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,9 @@ import (
"time"
)

// We report for max 1M results.
const maxRes = 1000000

type report struct {
enableLatencyMetric bool

avgTotal float64
average float64
tps float64
Expand All @@ -27,13 +26,14 @@ type report struct {
ReplyCode map[string]int
}

func newReport(results chan *result) *report {
func newReport(results chan *result, enableLatencyMetric bool) *report {
return &report{
results: results,
done: make(chan bool, 1),
errorDist: make(map[string]int),
lats: make([]float32, 0, maxRes),
ReplyCode: make(map[string]int),
results: results,
done: make(chan bool, 1),
errorDist: make(map[string]int),
lats: make([]float32, 0),
ReplyCode: make(map[string]int),
enableLatencyMetric: enableLatencyMetric,
}
}

Expand All @@ -46,7 +46,7 @@ func runReporter(r *report) {
r.failedCount++
} else {
r.avgTotal += res.duration.Seconds()
if len(r.lats) < maxRes {
if r.enableLatencyMetric {
r.lats = append(r.lats, float32(res.duration.Milliseconds()))
}
rcodeStr := dns.RcodeToString[res.msg.Rcode]
Expand Down
34 changes: 19 additions & 15 deletions pkg/loadRequest/loadDns/dns_requester.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ type Work struct {
// Qps is the rate limit in queries per second.
QPS int

EnableLatencyMetric bool

initOnce sync.Once
results chan *result
stopCh chan struct{}
Expand All @@ -57,7 +59,7 @@ func (b *Work) Init() {
func (b *Work) Run() {
b.Init()
b.startTime = metav1.Now()
b.report = newReport(b.results)
b.report = newReport(b.results, b.EnableLatencyMetric)
// Run the reporter first, it polls the result channel until it is closed.
go func() {
runReporter(b.report)
Expand Down Expand Up @@ -141,26 +143,28 @@ func (b *Work) runWorkers() {
func (b *Work) AggregateMetric() *v1beta1.DNSMetrics {
latency := v1beta1.LatencyDistribution{}

t, _ := stats.Mean(b.report.lats)
latency.Mean = t
if b.EnableLatencyMetric {
t, _ := stats.Mean(b.report.lats)
latency.Mean = t

t, _ = stats.Max(b.report.lats)
latency.Max = t
t, _ = stats.Max(b.report.lats)
latency.Max = t

t, _ = stats.Min(b.report.lats)
latency.Min = t
t, _ = stats.Min(b.report.lats)
latency.Min = t

t, _ = stats.Percentile(b.report.lats, 50)
latency.P50 = t
t, _ = stats.Percentile(b.report.lats, 50)
latency.P50 = t

t, _ = stats.Percentile(b.report.lats, 90)
latency.P90 = t
t, _ = stats.Percentile(b.report.lats, 90)
latency.P90 = t

t, _ = stats.Percentile(b.report.lats, 95)
latency.P95 = t
t, _ = stats.Percentile(b.report.lats, 95)
latency.P95 = t

t, _ = stats.Percentile(b.report.lats, 99)
latency.P99 = t
t, _ = stats.Percentile(b.report.lats, 99)
latency.P99 = t
}

metric := &v1beta1.DNSMetrics{
StartTime: b.startTime,
Expand Down
31 changes: 31 additions & 0 deletions pkg/loadRequest/loadDns/dns_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,37 @@ var _ = Describe("test dns ", Label("dns"), func() {

})

It("test latency ", func() {

dnsServer := "223.5.5.5:53"
req := &loadDns.DnsRequestData{
Protocol: loadDns.RequestMethodUdp,
DnsType: dns.TypeA,
TargetDomain: "www.baidu.com",
DnsServerAddr: dnsServer,
PerRequestTimeoutInMs: 1000,
DurationInSecond: 1,
Qps: 10,
EnableLatencyMetric: true,
}

log := logger.NewStdoutLogger("debug", "test")
result, e := loadDns.DnsRequest(log, req)
Expect(e).NotTo(HaveOccurred(), "failed to execute , error=%v", e)
Expect(int(result.FailedCounts)).To(Equal(0))
Expect(len(result.ReplyCode)).To(Equal(1))
Expect(result.ReplyCode).Should(HaveKey(dns.RcodeToString[dns.RcodeSuccess]))

jsongByte, e := json.Marshal(result)
Expect(e).NotTo(HaveOccurred(), "failed to Marshal , error=%v", e)

var out bytes.Buffer
e = json.Indent(&out, jsongByte, "", "\t")
Expect(e).NotTo(HaveOccurred(), "failed to Indent , error=%v", e)
fmt.Printf("%s\n", out.String())

})

It("test tcp ", func() {

dnsServer := "223.5.5.5:53"
Expand Down
24 changes: 13 additions & 11 deletions pkg/loadRequest/loadHttp/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ type HttpRequestData struct {
DisableKeepAlives bool
DisableCompression bool
ExpectStatusCode *int
EnableLatencyMetric bool
}

func HttpRequest(logger *zap.Logger, reqData *HttpRequestData) *v1beta1.HttpMetrics {
Expand All @@ -56,17 +57,18 @@ func HttpRequest(logger *zap.Logger, reqData *HttpRequestData) *v1beta1.HttpMetr
logger.Sugar().Infof("http request Concurrency=%d", config.AgentConfig.Configmap.NethttpDefaultConcurrency)

w := &Work{
Request: req,
Concurrency: config.AgentConfig.Configmap.NethttpDefaultConcurrency,
QPS: reqData.Qps,
Timeout: reqData.PerRequestTimeoutMS,
DisableCompression: reqData.DisableCompression,
DisableKeepAlives: reqData.DisableKeepAlives,
Http2: reqData.Http2,
Cert: reqData.ClientCert,
CertPool: reqData.CaCertPool,
ExpectStatusCode: reqData.ExpectStatusCode,
RequestBody: reqData.Body,
Request: req,
Concurrency: config.AgentConfig.Configmap.NethttpDefaultConcurrency,
QPS: reqData.Qps,
Timeout: reqData.PerRequestTimeoutMS,
DisableCompression: reqData.DisableCompression,
DisableKeepAlives: reqData.DisableKeepAlives,
Http2: reqData.Http2,
Cert: reqData.ClientCert,
CertPool: reqData.CaCertPool,
ExpectStatusCode: reqData.ExpectStatusCode,
RequestBody: reqData.Body,
EnableLatencyMetric: reqData.EnableLatencyMetric,
}
logger.Sugar().Infof("do http requests work=%v", w)
w.Init()
Expand Down
20 changes: 9 additions & 11 deletions pkg/loadRequest/loadHttp/http_reporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,8 @@ import (
"time"
)

// We report for max 1M results.
// todo (ii2day) configmap limit
const maxRes = 1000000

type report struct {
enableLatencyMetric bool
// transactions Per Second
tps float64

Expand All @@ -43,13 +40,14 @@ type report struct {
totalCount int64
}

func newReport(results chan *result, n int) *report {
func newReport(results chan *result, enableLatencyMetric bool) *report {
return &report{
results: results,
done: make(chan bool, 1),
errorDist: make(map[string]int),
latencies: make([]float32, 0, maxRes),
statusCodes: make(map[int]int),
results: results,
done: make(chan bool, 1),
errorDist: make(map[string]int),
latencies: make([]float32, 0),
statusCodes: make(map[int]int),
enableLatencyMetric: enableLatencyMetric,
}
}

Expand All @@ -61,7 +59,7 @@ func runReporter(r *report) {
if res.err != nil {
r.errorDist[res.err.Error()]++
} else {
if len(r.latencies) < maxRes {
if r.enableLatencyMetric {
r.latencies = append(r.latencies, float32(res.duration.Milliseconds()))
}
if res.contentLength > 0 {
Expand Down
37 changes: 21 additions & 16 deletions pkg/loadRequest/loadHttp/http_requester.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import (
"golang.org/x/net/http2"
"io"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"math"
"net/http"
"net/http/httptrace"
"net/url"
Expand Down Expand Up @@ -133,6 +132,10 @@ type Work struct {
// Optional.
ExpectStatusCode *int

// EnableLatencyMetric is collect latency metric . default false
// Optional.
EnableLatencyMetric bool

initOnce sync.Once
results chan *result
stopCh chan struct{}
Expand All @@ -155,7 +158,7 @@ func (b *Work) Run() {
b.Init()
b.startTime = metav1.Now()
b.start = time.Since(b.startTime.Time)
b.report = newReport(b.results, math.MaxInt32)
b.report = newReport(b.results, b.EnableLatencyMetric)
// Run the reporter first, it polls the result channel until it is closed.
go func() {
runReporter(b.report)
Expand Down Expand Up @@ -319,26 +322,28 @@ func (b *Work) now() time.Duration { return time.Since(b.startTime.Time) }
func (b *Work) AggregateMetric() *v1beta1.HttpMetrics {
latency := v1beta1.LatencyDistribution{}

t, _ := stats.Mean(b.report.latencies)
latency.Mean = t
if b.EnableLatencyMetric {
t, _ := stats.Mean(b.report.latencies)
latency.Mean = t

t, _ = stats.Max(b.report.latencies)
latency.Max = t
t, _ = stats.Max(b.report.latencies)
latency.Max = t

t, _ = stats.Min(b.report.latencies)
latency.Min = t
t, _ = stats.Min(b.report.latencies)
latency.Min = t

t, _ = stats.Percentile(b.report.latencies, 50)
latency.P50 = t
t, _ = stats.Percentile(b.report.latencies, 50)
latency.P50 = t

t, _ = stats.Percentile(b.report.latencies, 90)
latency.P90 = t
t, _ = stats.Percentile(b.report.latencies, 90)
latency.P90 = t

t, _ = stats.Percentile(b.report.latencies, 95)
latency.P95 = t
t, _ = stats.Percentile(b.report.latencies, 95)
latency.P95 = t

t, _ = stats.Percentile(b.report.latencies, 99)
latency.P99 = t
t, _ = stats.Percentile(b.report.latencies, 99)
latency.P99 = t
}

var errNum int64
for _, v := range b.report.errorDist {
Expand Down
1 change: 1 addition & 0 deletions pkg/pluginManager/apphttphealthy/agentExecuteTask.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ func (s *PluginAppHttpHealthy) AgentExecuteTask(logger *zap.Logger, ctx context.
RequestTimeSecond: request.DurationInSecond,
Http2: target.Http2,
ExpectStatusCode: instance.Spec.SuccessCondition.StatusCode,
EnableLatencyMetric: instance.Spec.Target.EnableLatencyMetric,
}

// https cert
Expand Down
Loading