Skip to content

Commit

Permalink
spiderpool metrics pkg optimization
Browse files Browse the repository at this point in the history
Signed-off-by: Icarus9913 <icaruswu66@qq.com>
  • Loading branch information
Icarus9913 committed Apr 21, 2022
1 parent e6558e2 commit 2179714
Show file tree
Hide file tree
Showing 51 changed files with 1,707 additions and 2,162 deletions.
29 changes: 12 additions & 17 deletions go.sum
Expand Up @@ -499,30 +499,25 @@ go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUz
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4=
go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo=
go.opentelemetry.io/otel v1.4.0/go.mod h1:jeAqMFKy2uLIxCtKxoFj0FAL5zAPKQagc3+GtBWakzk=
go.opentelemetry.io/otel v1.6.0 h1:YV6GkGe/Ag2PKsm4rjlqdSNs0w0A5ZzxeGkxhx1T+t4=
go.opentelemetry.io/otel v1.6.0/go.mod h1:bfJD2DZVw0LBxghOTlgnlI0CV3hLDu9XF/QKOUXMTQQ=
go.opentelemetry.io/otel v1.6.3 h1:FLOfo8f9JzFVFVyU+MSRJc2HdEAXQgm7pIv2uFKRSZE=
go.opentelemetry.io/otel v1.6.3/go.mod h1:7BgNga5fNlF/iZjG06hM3yofffp0ofKCDwSXx1GC4dI=
go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM=
go.opentelemetry.io/otel/exporters/prometheus v0.27.0 h1:HcGi6HmYRuszR3stcvN2GctJjQtvp44nw/VdfJCo/Ec=
go.opentelemetry.io/otel/exporters/prometheus v0.27.0/go.mod h1:u0vTzijx2B6gGDa8FuIVoESW6z0HdKkXZWZMSTsoJKs=
go.opentelemetry.io/otel/internal/metric v0.27.0 h1:9dAVGAfFiiEq5NVB9FUJ5et+btbDQAUIJehJ+ikyryk=
go.opentelemetry.io/otel/internal/metric v0.27.0/go.mod h1:n1CVxRqKqYZtqyTh9U/onvKapPGv7y/rpyOTI+LFNzw=
go.opentelemetry.io/otel/exporters/prometheus v0.29.0 h1:jOrFr8pCPj52GCPNq3qd69SEug3QmqDJTzbrefUxkpw=
go.opentelemetry.io/otel/exporters/prometheus v0.29.0/go.mod h1:Er2VVJQZbHysogooLNchdZ3MLYoI7+d15mHmrRlRJCU=
go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU=
go.opentelemetry.io/otel/metric v0.27.0 h1:HhJPsGhJoKRSegPQILFbODU56NS/L1UE4fS1sC5kIwQ=
go.opentelemetry.io/otel/metric v0.27.0/go.mod h1:raXDJ7uP2/Jc0nVZWQjJtzoyssOYWu/+pjZqRzfvZ7g=
go.opentelemetry.io/otel/metric v0.29.0 h1:7unM/I13Dbc1VHw8lTPQ7zfNIgkhcb8BZhujXOS4jKc=
go.opentelemetry.io/otel/metric v0.29.0/go.mod h1:HahKFp1OC1RNTsuO/HNMBHHJR+dmHZ7wLARRgGDwjLQ=
go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw=
go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc=
go.opentelemetry.io/otel/sdk v1.4.0/go.mod h1:71GJPNJh4Qju6zJuYl1CrYtXbrgfau/M9UAggqiy1UE=
go.opentelemetry.io/otel/sdk v1.6.0 h1:JoriAoiNENuxxIQApR1O0k2h1Md5QegZhbentcRJpWk=
go.opentelemetry.io/otel/sdk v1.6.0/go.mod h1:PjLRUfDsoPy0zl7yrDGSUqjj43tL7rEtFdCEiGlxXRM=
go.opentelemetry.io/otel/sdk v1.6.3 h1:prSHYdwCQOX5DrsEzxowH3nLhoAzEBdZhvrR79scfLs=
go.opentelemetry.io/otel/sdk v1.6.3/go.mod h1:A4iWF7HTXa+GWL/AaqESz28VuSBIcZ+0CV+IzJ5NMiQ=
go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE=
go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE=
go.opentelemetry.io/otel/sdk/metric v0.27.0 h1:CDEu96Js5IP7f4bJ8eimxF09V5hKYmE7CeyKSjmAL1s=
go.opentelemetry.io/otel/sdk/metric v0.27.0/go.mod h1:lOgrT5C3ORdbqp2LsDrx+pBj6gbZtQ5Omk27vH3EaW0=
go.opentelemetry.io/otel/sdk/metric v0.29.0 h1:OCEp2igPFXQrGxSR/nwd/bDjkPlPlOVjIULA/ob0dNw=
go.opentelemetry.io/otel/sdk/metric v0.29.0/go.mod h1:IFkFNKI8Gq8zBdqOKdODCL9+LInBZLXaGpqSIKphNuU=
go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw=
go.opentelemetry.io/otel/trace v1.4.0/go.mod h1:uc3eRsqDfWs9R7b92xbQbU42/eTNz4N+gLP8qJCi4aE=
go.opentelemetry.io/otel/trace v1.6.0 h1:NDzPermp9ISkhxIaJXjBTi2O60xOSHDHP/EezjOL2wo=
go.opentelemetry.io/otel/trace v1.6.0/go.mod h1:qs7BrU5cZ8dXQHBGxHMOxwME/27YH2qEp4/+tZLLwJE=
go.opentelemetry.io/otel/trace v1.6.3 h1:IqN4L+5b0mPNjdXIiZ90Ni4Bl5BRkDQywePLWemd9bc=
go.opentelemetry.io/otel/trace v1.6.3/go.mod h1:GNJQusJlUgZl9/TQBPKU/Y/ty+0iVB5fjhKeJGZPGFs=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
Expand Down
27 changes: 15 additions & 12 deletions pkg/metrics/metrics.go
Expand Up @@ -11,6 +11,9 @@ import (
"go.opentelemetry.io/otel/exporters/prometheus"
"go.opentelemetry.io/otel/metric"
"go.opentelemetry.io/otel/metric/global"
"go.opentelemetry.io/otel/metric/instrument"
"go.opentelemetry.io/otel/metric/instrument/syncfloat64"
"go.opentelemetry.io/otel/metric/instrument/syncint64"
"go.opentelemetry.io/otel/sdk/metric/aggregator/histogram"
controller "go.opentelemetry.io/otel/sdk/metric/controller/basic"
"go.opentelemetry.io/otel/sdk/metric/export/aggregation"
Expand All @@ -23,7 +26,7 @@ var meter metric.Meter

// InitMetricController will set up meter with the input param(required) and create a prometheus exporter.
// returns http handler and error
func InitMetricController(meterName string) (func(w http.ResponseWriter, r *http.Request), error) {
func InitMetricController(meterName string) (http.Handler, error) {
if len(meterName) == 0 {
return nil, fmt.Errorf("Failed to init metric controller, meter name is asked to be set!")
}
Expand All @@ -48,25 +51,25 @@ func InitMetricController(meterName string) (func(w http.ResponseWriter, r *http
m := global.Meter(meterName)
meter = m

return exporter.ServeHTTP, nil
return exporter, nil
}

// NewMetricInt64Counter will create otel Int64Counter metric. The first param metricName is required and
// the second param is optional.
func NewMetricInt64Counter(metricName string, description string) (metric.Int64Counter, error) {
// NewMetricInt64Counter will create otel Int64Counter metric.
// The first param metricName is required and the second param is optional.
func NewMetricInt64Counter(metricName string, description string) (syncint64.Counter, error) {
if len(metricName) == 0 {
return metric.Int64Counter{}, fmt.Errorf("Failed to create metric Int64Counter, metric name is asked to be set.")
return nil, fmt.Errorf("Failed to create metric Int64Counter, metric name is asked to be set.")
}
return metric.Must(meter).NewInt64Counter(metricName, metric.WithDescription(description)), nil
return meter.SyncInt64().Counter(metricName, instrument.WithDescription(description))
}

// NewMetricFloat64Histogram will create otel Float64Histogram metric. The first param metricName is required and
// the second param is optional.
func NewMetricFloat64Histogram(metricName string, description string) (metric.Float64Histogram, error) {
// NewMetricFloat64Histogram will create otel Float64Histogram metric.
// The first param metricName is required and the second param is optional.
func NewMetricFloat64Histogram(metricName string, description string) (syncfloat64.Histogram, error) {
if len(metricName) == 0 {
return metric.Float64Histogram{}, fmt.Errorf("Failed to create metric Float64Histogram, metric name is asked to be set.")
return nil, fmt.Errorf("Failed to create metric Float64Histogram, metric name is asked to be set.")
}
return metric.Must(meter).NewFloat64Histogram(metricName, metric.WithDescription(description)), nil
return meter.SyncFloat64().Histogram(metricName, instrument.WithDescription(description))
}

var _ TimeRecorder = &timeRecorder{}
Expand Down
130 changes: 108 additions & 22 deletions pkg/metrics/metrics_test.go
Expand Up @@ -4,18 +4,32 @@
package metrics_test

import (
"bufio"
"context"
"io"
"net"
"net/http"
"strconv"
"strings"
"time"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"

"github.com/spidernet-io/spiderpool/pkg/metrics"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/metric"
"go.opentelemetry.io/otel/metric/instrument/syncfloat64"
"go.opentelemetry.io/otel/metric/instrument/syncint64"
)

const (
OTEL_COUNTS_SIGNAL = "ippool=\"default_pool\""
)

var (
verifyCount int

MetricsTestServerAddr = ""
SpiderPoolMeter = "spider_pool_meter"
MetricNodeIPAllocationCountsName = "Node_IP_Allocation_Counts"
MetricNodeIPAllocationDurationName = "Node_IP_Allocation_Duration"
Expand All @@ -25,25 +39,53 @@ type IPAllocation struct {
NodeName string
PoolName string
// ....
MetricNodeIPAllocationCounts metric.Int64Counter
MetricNodeIPAllocationDuration metric.Float64Histogram
MetricNodeIPAllocationCounts syncint64.Counter
MetricNodeIPAllocationDuration syncfloat64.Histogram
}

var _ = Describe("check otel with prometheus", Ordered, func() {
var httpHandle func(http.ResponseWriter, *http.Request)
var _ = Describe("metrics", Label("unitest", "metrics_test"), Ordered, func() {
var httpHandle http.Handler
var server http.Server
var err error
var listener net.Listener

// start a http server to set up an otel exporter
BeforeAll(func() {
/* Obtain a reference to a local port for the given sock,
* if snum is zero it means select any available local port.
*/
listener, err = net.Listen("tcp", net.JoinHostPort("0.0.0.0", "0"))
if nil != err {
if strings.Contains(err.Error(), "address already in use") {

}
}

Expect(err).NotTo(HaveOccurred())

MetricsTestServerAddr = "http://" + listener.Addr().String()

httpHandle, err = metrics.InitMetricController(SpiderPoolMeter)
Expect(err).NotTo(HaveOccurred())

http.HandleFunc("/metrics", httpHandle)
server.Addr = MetricsTestServerAddr
server.Handler = httpHandle

go func() {
_ = http.ListenAndServe(":2222", nil)
err = server.Serve(listener)
Expect(err).NotTo(HaveOccurred())
}()

})

// close http listener
AfterAll(func() {
err := listener.Close()
Expect(err).NotTo(HaveOccurred())
})

It("use prometheus as exporter", func() {

c := make(chan bool)
ctx := context.Background()

Expand All @@ -60,25 +102,69 @@ var _ = Describe("check otel with prometheus", Ordered, func() {
Expect(err).NotTo(HaveOccurred())
ipAllocation.MetricNodeIPAllocationDuration = histogram

// ip allocation logics....
timeRecorder := metrics.NewTimeRecorder()
// ....
// verifyRecord willverify whether the metrics record correctly
verifyRecord := func(duration float64) {
resp, err := http.Get(MetricsTestServerAddr)
Expect(err).NotTo(HaveOccurred())
defer func(Body io.ReadCloser) {
err = Body.Close()
Expect(err).NotTo(HaveOccurred())
}(resp.Body)

reader := bufio.NewReader(resp.Body)

for {
line, err := reader.ReadString('\n')
if nil != err || io.EOF == err {
if line == "" {
break
}
}

// verify counts instrument
if strings.Contains(line, MetricNodeIPAllocationCountsName) && strings.Contains(line, OTEL_COUNTS_SIGNAL) {
split := strings.Split(line, " ")
Expect(err).NotTo(HaveOccurred())
Expect(split[len(split)-1]).Should(Equal("2\n"))
verifyCount++
}

// verify histogram instrument
if strings.Contains(line, MetricNodeIPAllocationDurationName+"_sum") {
split := strings.Split(line, " ")
Expect(err).NotTo(HaveOccurred())
Expect(split[len(split)-1]).Should(Equal(strconv.FormatFloat(duration, 'f', -1, 64) + "\n"))
verifyCount++
}
}
Expect(verifyCount).Should(Equal(2))
}

// metrics record data
go func() {
// ip allocation logics....
timeRecorder := metrics.NewTimeRecorder()
// ....

// ip allocation succeed
// record the counter metric without labels.
ipAllocation.MetricNodeIPAllocationCounts.Add(ctx, 1, attribute.Key("ippool").String("default_pool"))

// ip allocation succeed
// record the counter metric without labels.
ipAllocation.MetricNodeIPAllocationCounts.Add(ctx, 1)
time.Sleep(time.Second * 5)
ipAllocation.MetricNodeIPAllocationCounts.Add(ctx, 1, attribute.Key("ippool").String("default_pool"))

time.Sleep(time.Second * 10)
ipAllocation.MetricNodeIPAllocationCounts.Add(ctx, 1)
// record histogram metric with labels.
duration := timeRecorder.SinceInSeconds()
ipAllocation.MetricNodeIPAllocationDuration.Record(ctx, duration,
attribute.Key("hostname").String("node1"),
attribute.Key("type").String("total"))

// record histogram metric with labels.
duration := timeRecorder.SinceInSeconds()
ipAllocation.MetricNodeIPAllocationDuration.Record(ctx, duration,
attribute.Key("hostname").String("node1"),
attribute.Key("type").String("total"))
time.Sleep(time.Second * 1)
verifyRecord(duration)

close(c)
}()

close(c)
//Consistently(c, "60s").Should(BeClosed())
Eventually(c, "20s").Should(BeClosed())
})
})
50 changes: 48 additions & 2 deletions vendor/go.opentelemetry.io/otel/CHANGELOG.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion vendor/go.opentelemetry.io/otel/README.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 2179714

Please sign in to comment.