blob: 2a33aecd83849d50abc53fae69702a5a29ca592d [file] [log] [blame]
// Licensed to 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. Apache Software Foundation (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 layer4
import "github.com/apache/skywalking-rover/pkg/profiling/task/network/analyze/base"
type Metrics struct {
// basic statics
// read/write
WriteCounter *SocketDataCounterWithHistory
ReadCounter *SocketDataCounterWithHistory
// write RTT
WriteRTTCounter *SocketDataCounterWithHistory
// histograms
// write execute time and RTT
WriteRTTHistogram *SocketDataHistogramWithHistory
WriteExeTimeHistogram *SocketDataHistogramWithHistory
// read execute time
ReadExeTimeHistogram *SocketDataHistogramWithHistory
// the connection connect or close execute time
ConnectExecuteTime uint64
CloseExecuteTime uint64
ConnectCounter *SocketDataCounterWithHistory
CloseCounter *SocketDataCounterWithHistory
ConnectExeTimeHistogram *SocketDataHistogramWithHistory
CloseExeTimeHistogram *SocketDataHistogramWithHistory
// exception counters
RetransmitCounter *SocketDataCounterWithHistory
DropCounter *SocketDataCounterWithHistory
}
func NewLayer4Metrics() *Metrics {
return &Metrics{
WriteCounter: NewSocketDataCounterWithHistory(),
ReadCounter: NewSocketDataCounterWithHistory(),
WriteRTTCounter: NewSocketDataCounterWithHistory(),
WriteRTTHistogram: NewSocketDataHistogramWithHistory(HistogramDataUnitUS),
WriteExeTimeHistogram: NewSocketDataHistogramWithHistory(HistogramDataUnitNS),
ReadExeTimeHistogram: NewSocketDataHistogramWithHistory(HistogramDataUnitNS),
ConnectCounter: NewSocketDataCounterWithHistory(),
ConnectExeTimeHistogram: NewSocketDataHistogramWithHistory(HistogramDataUnitNS),
CloseCounter: NewSocketDataCounterWithHistory(),
CloseExeTimeHistogram: NewSocketDataHistogramWithHistory(HistogramDataUnitNS),
RetransmitCounter: NewSocketDataCounterWithHistory(),
DropCounter: NewSocketDataCounterWithHistory(),
}
}
func (l *Metrics) MergeMetricsFromConnection(connection *base.ConnectionContext, data base.ConnectionMetrics) {
metrics := data.(*Metrics)
l.WriteCounter.IncreaseToCurrent(metrics.WriteCounter.CalculateIncrease())
l.ReadCounter.IncreaseToCurrent(metrics.ReadCounter.CalculateIncrease())
l.WriteRTTCounter.IncreaseToCurrent(metrics.WriteRTTCounter.CalculateIncrease())
l.WriteRTTHistogram.IncreaseToCurrent(metrics.WriteRTTHistogram.CalculateIncrease())
l.WriteExeTimeHistogram.IncreaseToCurrent(metrics.WriteExeTimeHistogram.CalculateIncrease())
l.ReadExeTimeHistogram.IncreaseToCurrent(metrics.ReadExeTimeHistogram.CalculateIncrease())
l.RetransmitCounter.IncreaseToCurrent(metrics.RetransmitCounter.CalculateIncrease())
l.DropCounter.IncreaseToCurrent(metrics.DropCounter.CalculateIncrease())
if connection.FlushDataCount == 0 && metrics.ConnectExecuteTime > 0 {
l.ConnectCounter.IncreaseToCurrent(NewSocketDataCounterWithValue(0, 1, metrics.ConnectExecuteTime))
l.ConnectExeTimeHistogram.Cur.IncreaseByValue(metrics.ConnectExecuteTime)
}
if connection.FlushDataCount == 0 && metrics.CloseExecuteTime > 0 {
l.CloseCounter.IncreaseToCurrent(NewSocketDataCounterWithValue(0, 1, metrics.CloseExecuteTime))
l.CloseExeTimeHistogram.Cur.IncreaseByValue(metrics.CloseExecuteTime)
}
}
type SocketDataCounter struct {
Bytes uint64
Count uint64
ExeTime uint64
}
func NewSocketDataCounter() *SocketDataCounter {
return &SocketDataCounter{}
}
func NewSocketDataCounterWithValue(bytes, count, exeTime uint64) *SocketDataCounter {
ret := &SocketDataCounter{}
ret.IncreaseByValue(bytes, count, exeTime)
return ret
}
func (s *SocketDataCounter) Increase(d *SocketDataCounter) {
s.IncreaseByValue(d.Bytes, d.Count, d.ExeTime)
}
func (s *SocketDataCounter) IncreaseByValue(bytes, count, exeTime uint64) {
s.Bytes += bytes
s.Count += count
s.ExeTime += exeTime
}
func (s *SocketDataCounter) NotEmpty() bool {
return s.Count > 0
}
// SocketDataCounterWithHistory means the socket send/receive data metrics
type SocketDataCounterWithHistory struct {
Pre *SocketDataCounter
Cur *SocketDataCounter
}
func NewSocketDataCounterWithHistory() *SocketDataCounterWithHistory {
return &SocketDataCounterWithHistory{
Pre: NewSocketDataCounter(),
Cur: NewSocketDataCounter(),
}
}
func (c *SocketDataCounterWithHistory) RefreshCurrent() {
c.Pre = c.Cur
c.Cur = NewSocketDataCounterWithValue(c.Cur.Bytes, c.Cur.Count, c.Cur.ExeTime)
}
func (c *SocketDataCounterWithHistory) UpdateToCurrent(bytes, count, exeTime uint64) {
c.Pre = c.Cur
c.Cur = &SocketDataCounter{
Bytes: bytes,
Count: count,
ExeTime: exeTime,
}
}
func (c *SocketDataCounterWithHistory) IncreaseToCurrent(other *SocketDataCounter) {
c.Cur.Increase(other)
}
func (c *SocketDataCounterWithHistory) CalculateIncrease() *SocketDataCounter {
return &SocketDataCounter{
Bytes: subtractionValue(c.Cur.Bytes, c.Pre.Bytes),
Count: subtractionValue(c.Cur.Count, c.Pre.Count),
ExeTime: subtractionValue(c.Cur.ExeTime, c.Pre.ExeTime),
}
}
// SocketHistogramBucketsNs means the histogram bucket: 0ms, 0.01ms, 0.05ms, 0.1ms, 0.5ms, 1ms, 1.2ms, 1.5ms, 1.7ms, 2ms,
// 2.5ms, 3ms, 5ms, 7ms, 10ms, 13ms, 16ms, 20ms, 25ms, 30ms, 35ms, 40ms, 45ms, 50ms, 70ms, 100ms, 150ms,
// 200ms, 300ms, 500ms, 1s, 2s, 3s, 5s
// value unit: ns
var SocketHistogramBucketsNs = []float64{0, 10000, 50000, 100000, 500000, 1000000, 1200000, 1500000, 1700000, 2000000,
2500000, 3000000, 5000000, 7000000, 10000000, 13000000, 16000000, 20000000, 25000000, 30000000, 35000000, 40000000,
45000000, 50000000, 70000000, 100000000, 150000000, 200000000, 300000000, 500000000, 1000000000, 2000000000,
3000000000, 5000000000}
// SocketHistogramBucketsUs same with SocketHistogramBucketsNs, but the value unit: us
var SocketHistogramBucketsUs = []float64{0, 10, 50, 100, 500, 1000, 1200, 1500, 1700, 2000,
2500, 3000, 5000, 7000, 10000, 13000, 16000, 20000, 25000, 30000, 35000, 40000,
45000, 50000, 70000, 100000, 150000, 200000, 300000, 500000, 1000000, 2000000,
3000000, 5000000}
var SocketHistogramBucketsCount = len(SocketHistogramBucketsNs)
type SocketDataHistogram struct {
Unit HistogramDataUnit
Buckets map[uint64]uint32
}
func (h *SocketDataHistogram) Overwrite(other *SocketDataHistogram) {
for k, v := range other.Buckets {
h.Buckets[k] = v
}
}
func (h *SocketDataHistogram) Update(bucket uint64, value uint32) {
h.Buckets[bucket] = value
}
func (h *SocketDataHistogram) Increase(other *SocketDataHistogram) {
for k, v := range other.Buckets {
h.Buckets[k] += v
}
}
func (h *SocketDataHistogram) IncreaseByValue(val uint64) {
floatVal := float64(val)
for inx, curVal := range SocketHistogramBucketsNs {
if inx > 0 && curVal > floatVal {
h.Buckets[uint64(inx-1)]++
return
}
}
h.Buckets[uint64(len(SocketHistogramBucketsNs)-1)]++
}
func (h *SocketDataHistogram) NotEmpty() bool {
for _, v := range h.Buckets {
if v > 0 {
return true
}
}
return false
}
func NewSocketDataHistogram(unit HistogramDataUnit) *SocketDataHistogram {
buckets := make(map[uint64]uint32, SocketHistogramBucketsCount)
for i := 0; i < SocketHistogramBucketsCount; i++ {
buckets[uint64(i)] = 0
}
return &SocketDataHistogram{
Unit: unit,
Buckets: buckets,
}
}
type HistogramDataUnit int
const (
HistogramDataUnitNS HistogramDataUnit = 1
HistogramDataUnitUS HistogramDataUnit = 2
)
type SocketDataHistogramWithHistory struct {
Pre *SocketDataHistogram
Cur *SocketDataHistogram
}
func NewSocketDataHistogramWithHistory(unit HistogramDataUnit) *SocketDataHistogramWithHistory {
return &SocketDataHistogramWithHistory{
Pre: NewSocketDataHistogram(unit),
Cur: NewSocketDataHistogram(unit),
}
}
func (h *SocketDataHistogramWithHistory) RefreshCurrent() {
// storage the current value to the previous buckets
h.Pre.Overwrite(h.Cur)
}
func (h *SocketDataHistogramWithHistory) UpdateToCurrent(bucket uint64, val uint32) {
h.Cur.Update(bucket, val)
}
func (h *SocketDataHistogramWithHistory) IncreaseToCurrent(other *SocketDataHistogram) {
h.Cur.Increase(other)
}
func (h *SocketDataHistogramWithHistory) CalculateIncrease() *SocketDataHistogram {
histogram := NewSocketDataHistogram(h.Cur.Unit)
var increaseVal uint32
for curK, curV := range h.Cur.Buckets {
if increaseVal = curV - h.Pre.Buckets[curK]; increaseVal > 0 {
histogram.Buckets[curK] = increaseVal
}
}
return histogram
}
func subtractionValue(v1, v2 uint64) uint64 {
if v1 > v2 {
return v1 - v2
}
return 0
}