-
Notifications
You must be signed in to change notification settings - Fork 73
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Icarus9913 <icaruswu66@qq.com>
- Loading branch information
1 parent
dd0f999
commit e6558e2
Showing
511 changed files
with
120,662 additions
and
55 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
// Copyright 2022 Authors of spidernet-io | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package metrics | ||
|
||
import ( | ||
"fmt" | ||
"net/http" | ||
"time" | ||
|
||
"go.opentelemetry.io/otel/exporters/prometheus" | ||
"go.opentelemetry.io/otel/metric" | ||
"go.opentelemetry.io/otel/metric/global" | ||
"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" | ||
processor "go.opentelemetry.io/otel/sdk/metric/processor/basic" | ||
selector "go.opentelemetry.io/otel/sdk/metric/selector/simple" | ||
) | ||
|
||
// meter is a global creator of metric instruments. | ||
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) { | ||
if len(meterName) == 0 { | ||
return nil, fmt.Errorf("Failed to init metric controller, meter name is asked to be set!") | ||
} | ||
|
||
config := prometheus.Config{ | ||
DefaultHistogramBoundaries: []float64{1, 5, 7, 10, 15, 20, 30}, | ||
} | ||
c := controller.New( | ||
processor.NewFactory( | ||
selector.NewWithHistogramDistribution( | ||
histogram.WithExplicitBoundaries(config.DefaultHistogramBoundaries)), | ||
aggregation.CumulativeTemporalitySelector(), | ||
processor.WithMemory(true), | ||
), | ||
) | ||
exporter, err := prometheus.New(config, c) | ||
if nil != err { | ||
return nil, err | ||
} | ||
global.SetMeterProvider(exporter.MeterProvider()) | ||
|
||
m := global.Meter(meterName) | ||
meter = m | ||
|
||
return exporter.ServeHTTP, 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) { | ||
if len(metricName) == 0 { | ||
return metric.Int64Counter{}, fmt.Errorf("Failed to create metric Int64Counter, metric name is asked to be set.") | ||
} | ||
return metric.Must(meter).NewInt64Counter(metricName, metric.WithDescription(description)), nil | ||
} | ||
|
||
// 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) { | ||
if len(metricName) == 0 { | ||
return metric.Float64Histogram{}, fmt.Errorf("Failed to create metric Float64Histogram, metric name is asked to be set.") | ||
} | ||
return metric.Must(meter).NewFloat64Histogram(metricName, metric.WithDescription(description)), nil | ||
} | ||
|
||
var _ TimeRecorder = &timeRecorder{} | ||
|
||
// timeRecorder owns a field to record start time. | ||
type timeRecorder struct { | ||
startTime time.Time | ||
} | ||
|
||
// TimeRecorder will help you to compute time duration. | ||
type TimeRecorder interface { | ||
SinceInSeconds() float64 | ||
} | ||
|
||
// NewTimeRecorder will create TimeRecorder and record the current time. | ||
func NewTimeRecorder() TimeRecorder { | ||
t := timeRecorder{} | ||
t.startTime = time.Now() | ||
return &t | ||
} | ||
|
||
// SinceInSeconds returns the duration of time since the start time as a float64. | ||
func (t *timeRecorder) SinceInSeconds() float64 { | ||
return float64(time.Since(t.startTime)) / 1e9 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// Copyright 2022 Authors of spidernet-io | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package metrics_test | ||
|
||
import ( | ||
"testing" | ||
|
||
. "github.com/onsi/ginkgo/v2" | ||
. "github.com/onsi/gomega" | ||
) | ||
|
||
func TestMetrics(t *testing.T) { | ||
RegisterFailHandler(Fail) | ||
RunSpecs(t, "Metrics Suite") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
// Copyright 2022 Authors of spidernet-io | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package metrics_test | ||
|
||
import ( | ||
"context" | ||
"net/http" | ||
"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" | ||
) | ||
|
||
var ( | ||
SpiderPoolMeter = "spider_pool_meter" | ||
MetricNodeIPAllocationCountsName = "Node_IP_Allocation_Counts" | ||
MetricNodeIPAllocationDurationName = "Node_IP_Allocation_Duration" | ||
) | ||
|
||
type IPAllocation struct { | ||
NodeName string | ||
PoolName string | ||
// .... | ||
MetricNodeIPAllocationCounts metric.Int64Counter | ||
MetricNodeIPAllocationDuration metric.Float64Histogram | ||
} | ||
|
||
var _ = Describe("check otel with prometheus", Ordered, func() { | ||
var httpHandle func(http.ResponseWriter, *http.Request) | ||
var err error | ||
|
||
BeforeAll(func() { | ||
httpHandle, err = metrics.InitMetricController(SpiderPoolMeter) | ||
Expect(err).NotTo(HaveOccurred()) | ||
|
||
http.HandleFunc("/metrics", httpHandle) | ||
go func() { | ||
_ = http.ListenAndServe(":2222", nil) | ||
}() | ||
}) | ||
|
||
It("use prometheus as exporter", func() { | ||
c := make(chan bool) | ||
ctx := context.Background() | ||
|
||
ipAllocation := IPAllocation{ | ||
NodeName: "node1", | ||
PoolName: "default/poo1", | ||
} | ||
|
||
// register metrics | ||
metricInt64Counter, err := metrics.NewMetricInt64Counter(MetricNodeIPAllocationCountsName, "The total counts of node IP allocations") | ||
Expect(err).NotTo(HaveOccurred()) | ||
ipAllocation.MetricNodeIPAllocationCounts = metricInt64Counter | ||
histogram, err := metrics.NewMetricFloat64Histogram(MetricNodeIPAllocationDurationName, "The duration of node IP allocations") | ||
Expect(err).NotTo(HaveOccurred()) | ||
ipAllocation.MetricNodeIPAllocationDuration = histogram | ||
|
||
// ip allocation logics.... | ||
timeRecorder := metrics.NewTimeRecorder() | ||
// .... | ||
|
||
// ip allocation succeed | ||
// record the counter metric without labels. | ||
ipAllocation.MetricNodeIPAllocationCounts.Add(ctx, 1) | ||
|
||
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")) | ||
|
||
close(c) | ||
//Consistently(c, "60s").Should(BeClosed()) | ||
Eventually(c, "20s").Should(BeClosed()) | ||
}) | ||
}) |
Oops, something went wrong.