This is an automated email from the ASF dual-hosted git repository.

liuhan pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-go.git


The following commit(s) were added to refs/heads/main by this push:
     new 0b729dd  feat: support manual reporting of metrics in toolkit (#205)
0b729dd is described below

commit 0b729dde37b3ac0dac3e18fa7f8e65b3d248a87d
Author: Shyunn <[email protected]>
AuthorDate: Mon Sep 23 12:26:19 2024 +0800

    feat: support manual reporting of metrics in toolkit (#205)
---
 .github/workflows/plugin-tests.yaml                |  1 +
 CHANGES.md                                         |  1 +
 go.work                                            |  1 +
 plugins/toolkit-activation/instrument.go           | 57 ++++++++++++++++
 .../metric/counter_get_intercepter.go              | 32 ++++++---
 .../metric/counter_inc_intercepter.go              | 31 ++++++---
 .../metric/gauge_get_intercepter.go                | 32 ++++++---
 .../metric/histogram_observe_intercepter.go        | 49 +++++---------
 .../histogram_observewithcount_intercepter.go      | 49 +++++---------
 .../metric/meter_opt_intercepter.go                | 26 ++++---
 .../metric/new_counter_intercepter.go              | 61 +++++++----------
 .../metric/new_gauge_intercepter.go                | 62 +++++++----------
 .../metric/new_histogram_intercepter.go            | 62 +++++++----------
 .../scenarios/metric-activation/bin/startup.sh     | 22 ++++++
 .../metric-activation/config/excepted.yml          | 79 ++++++++++++++++++++++
 test/plugins/scenarios/metric-activation/go.mod    |  3 +
 test/plugins/scenarios/metric-activation/main.go   | 64 ++++++++++++++++++
 .../plugins/scenarios/metric-activation/plugin.yml | 28 ++++++++
 .../scenarios/metric-activation/test_service.go    | 57 ++++++++++++++++
 toolkit/metric/api.go                              | 16 ++++-
 toolkit/metric/metrics.go                          | 14 +---
 21 files changed, 514 insertions(+), 233 deletions(-)

diff --git a/.github/workflows/plugin-tests.yaml 
b/.github/workflows/plugin-tests.yaml
index 27710f1..94293a5 100644
--- a/.github/workflows/plugin-tests.yaml
+++ b/.github/workflows/plugin-tests.yaml
@@ -93,6 +93,7 @@ jobs:
           - irisv12
           - trace-activation
           - logging-activation
+          - metric-activation
           - fasthttp
           - discard-reporter
           - fiber
diff --git a/CHANGES.md b/CHANGES.md
index c84e0d3..a4248df 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -8,6 +8,7 @@ Release Notes.
 
 * support attaching events to span in the toolkit.
 * support record log in the toolkit.
+* support manually report metrics in the toolkit.
 
 #### Plugins
 * Support [goframev2](https://github.com/gogf/gf) goframev2.
diff --git a/go.work b/go.work
index 05a3142..1dfe2c1 100644
--- a/go.work
+++ b/go.work
@@ -65,6 +65,7 @@ use (
        ./test/plugins/scenarios/segmentio-kafka
        ./test/plugins/scenarios/go-elasticsearchv8
        ./test/plugins/scenarios/logging-activation
+       ./test/plugins/scenarios/metric-activation
        ./test/plugins/scenarios/goframe
 
        ./tools/go-agent
diff --git a/plugins/toolkit-activation/instrument.go 
b/plugins/toolkit-activation/instrument.go
index 095e523..105ed78 100644
--- a/plugins/toolkit-activation/instrument.go
+++ b/plugins/toolkit-activation/instrument.go
@@ -54,9 +54,66 @@ func (i *Instrument) Points() []*instrument.Point {
        // append toolkit/logging related enhancements Point
        instPoints = append(instPoints, loggingPoint()...)
 
+       // append toolkit/metric related enhancements Point
+       instPoints = append(instPoints, metricPoint()...)
+
        return instPoints
 }
 
+func metricPoint() []*instrument.Point {
+       return []*instrument.Point{
+               // Counter metric type related enhancement point
+               {
+                       PackagePath: "metric", At: 
instrument.NewStructEnhance("CounterRef"),
+               },
+               {
+                       PackagePath: "metric", At: 
instrument.NewStaticMethodEnhance("NewCounter"),
+                       Interceptor: "NewCounterInterceptor",
+               },
+               {
+                       PackagePath: "metric", At: 
instrument.NewMethodEnhance("*CounterRef", "Get"),
+                       Interceptor: "CounterGetInterceptor",
+               },
+               {
+                       PackagePath: "metric", At: 
instrument.NewMethodEnhance("*CounterRef", "Inc"),
+                       Interceptor: "CounterIncInterceptor",
+               },
+               // Gauge metric type related enhancement point
+               {
+                       PackagePath: "metric", At: 
instrument.NewStructEnhance("GaugeRef"),
+               },
+               {
+                       PackagePath: "metric", At: 
instrument.NewStaticMethodEnhance("NewGauge"),
+                       Interceptor: "NewGaugeInterceptor",
+               },
+               {
+                       PackagePath: "metric", At: 
instrument.NewMethodEnhance("*GaugeRef", "Get"),
+                       Interceptor: "GaugeGetInterceptor",
+               },
+               // Histogram metric type related enhancement point
+               {
+                       PackagePath: "metric", At: 
instrument.NewStructEnhance("HistogramRef"),
+               },
+               {
+                       PackagePath: "metric", At: 
instrument.NewStaticMethodEnhance("NewHistogram"),
+                       Interceptor: "NewHistogramInterceptor",
+               },
+               {
+                       PackagePath: "metric", At: 
instrument.NewMethodEnhance("*HistogramRef", "Observe"),
+                       Interceptor: "HistogramObserveInterceptor",
+               },
+               {
+                       PackagePath: "metric", At: 
instrument.NewMethodEnhance("*HistogramRef", "ObserveWithCount"),
+                       Interceptor: "HistogramObserveWithCountInterceptor",
+               },
+               // metric options related enhancement point
+               {
+                       PackagePath: "metric", At: 
instrument.NewStaticMethodEnhance("WithLabels"),
+                       Interceptor: "WithLabelsInterceptor",
+               },
+       }
+}
+
 func tracePoint() []*instrument.Point {
        return []*instrument.Point{
                {
diff --git a/toolkit/metric/api.go 
b/plugins/toolkit-activation/metric/counter_get_intercepter.go
similarity index 54%
copy from toolkit/metric/api.go
copy to plugins/toolkit-activation/metric/counter_get_intercepter.go
index daa27e4..ed7415e 100644
--- a/toolkit/metric/api.go
+++ b/plugins/toolkit-activation/metric/counter_get_intercepter.go
@@ -6,7 +6,7 @@
 // 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
+//     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
@@ -17,17 +17,27 @@
 
 package metric
 
-// NewCounter creates a new counter metrics.
-func NewCounter(name string, opt ...MeterOpt) *CounterRef {
-       return &CounterRef{}
-}
+import (
+       "github.com/apache/skywalking-go/plugins/core/metrics"
+       "github.com/apache/skywalking-go/plugins/core/operator"
+)
+
+type CounterGetInterceptor struct{}
 
-// NewGauge creates a new gauge metrics.
-func NewGauge(name string, watcher func() float64, opts ...MeterOpt) *GaugeRef 
{
-       return &GaugeRef{}
+func (h *CounterGetInterceptor) BeforeInvoke(_ operator.Invocation) error {
+       return nil
 }
 
-// NewHistogram creates a new histogram metrics.
-func NewHistogram(name string, steps []float64, opts ...MeterOpt) *Histogram {
-       return &Histogram{}
+func (h *CounterGetInterceptor) AfterInvoke(invocation operator.Invocation, _ 
...interface{}) error {
+       enhanced, ok := invocation.CallerInstance().(operator.EnhancedInstance)
+       if !ok {
+               return nil
+       }
+
+       counter, ok := enhanced.GetSkyWalkingDynamicField().(metrics.Counter)
+       if ok && counter != nil {
+               val := counter.Get()
+               invocation.DefineReturnValues(val)
+       }
+       return nil
 }
diff --git a/toolkit/metric/api.go 
b/plugins/toolkit-activation/metric/counter_inc_intercepter.go
similarity index 54%
copy from toolkit/metric/api.go
copy to plugins/toolkit-activation/metric/counter_inc_intercepter.go
index daa27e4..ca7e77a 100644
--- a/toolkit/metric/api.go
+++ b/plugins/toolkit-activation/metric/counter_inc_intercepter.go
@@ -6,7 +6,7 @@
 // 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
+//     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
@@ -17,17 +17,26 @@
 
 package metric
 
-// NewCounter creates a new counter metrics.
-func NewCounter(name string, opt ...MeterOpt) *CounterRef {
-       return &CounterRef{}
-}
+import (
+       "github.com/apache/skywalking-go/plugins/core/metrics"
+       "github.com/apache/skywalking-go/plugins/core/operator"
+)
+
+type CounterIncInterceptor struct{}
 
-// NewGauge creates a new gauge metrics.
-func NewGauge(name string, watcher func() float64, opts ...MeterOpt) *GaugeRef 
{
-       return &GaugeRef{}
+func (h *CounterIncInterceptor) BeforeInvoke(_ operator.Invocation) error {
+       return nil
 }
 
-// NewHistogram creates a new histogram metrics.
-func NewHistogram(name string, steps []float64, opts ...MeterOpt) *Histogram {
-       return &Histogram{}
+func (h *CounterIncInterceptor) AfterInvoke(invocation operator.Invocation, _ 
...interface{}) error {
+       enhanced, ok := invocation.CallerInstance().(operator.EnhancedInstance)
+       if !ok {
+               return nil
+       }
+
+       counter, ok := enhanced.GetSkyWalkingDynamicField().(metrics.Counter)
+       if ok && counter != nil {
+               counter.Inc(invocation.Args()[0].(float64))
+       }
+       return nil
 }
diff --git a/toolkit/metric/api.go 
b/plugins/toolkit-activation/metric/gauge_get_intercepter.go
similarity index 54%
copy from toolkit/metric/api.go
copy to plugins/toolkit-activation/metric/gauge_get_intercepter.go
index daa27e4..63d4be6 100644
--- a/toolkit/metric/api.go
+++ b/plugins/toolkit-activation/metric/gauge_get_intercepter.go
@@ -6,7 +6,7 @@
 // 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
+//     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
@@ -17,17 +17,27 @@
 
 package metric
 
-// NewCounter creates a new counter metrics.
-func NewCounter(name string, opt ...MeterOpt) *CounterRef {
-       return &CounterRef{}
-}
+import (
+       "github.com/apache/skywalking-go/plugins/core/metrics"
+       "github.com/apache/skywalking-go/plugins/core/operator"
+)
+
+type GaugeGetInterceptor struct{}
 
-// NewGauge creates a new gauge metrics.
-func NewGauge(name string, watcher func() float64, opts ...MeterOpt) *GaugeRef 
{
-       return &GaugeRef{}
+func (h *GaugeGetInterceptor) BeforeInvoke(_ operator.Invocation) error {
+       return nil
 }
 
-// NewHistogram creates a new histogram metrics.
-func NewHistogram(name string, steps []float64, opts ...MeterOpt) *Histogram {
-       return &Histogram{}
+func (h *GaugeGetInterceptor) AfterInvoke(invocation operator.Invocation, 
result ...interface{}) error {
+       enhanced, ok := invocation.CallerInstance().(operator.EnhancedInstance)
+       if !ok {
+               return nil
+       }
+
+       gauge, ok := enhanced.GetSkyWalkingDynamicField().(metrics.Gauge)
+       if ok && gauge != nil {
+               val := gauge.Get()
+               invocation.DefineReturnValues(val)
+       }
+       return nil
 }
diff --git a/toolkit/metric/metrics.go 
b/plugins/toolkit-activation/metric/histogram_observe_intercepter.go
similarity index 53%
copy from toolkit/metric/metrics.go
copy to plugins/toolkit-activation/metric/histogram_observe_intercepter.go
index fdf433b..26da9a8 100644
--- a/toolkit/metric/metrics.go
+++ b/plugins/toolkit-activation/metric/histogram_observe_intercepter.go
@@ -17,41 +17,26 @@
 
 package metric
 
-type CounterRef struct{}
+import (
+       "github.com/apache/skywalking-go/plugins/core/metrics"
+       "github.com/apache/skywalking-go/plugins/core/operator"
+)
 
-// Get returns the current value of the counter.
-func (c *CounterRef) Get() float64 {
-       return -1
-}
-
-// Inc increments the counter with value.
-func (c *CounterRef) Inc(val float64) {}
-
-type GaugeRef struct {
-}
+type HistogramObserveInterceptor struct{}
 
-// Get returns the current value of the gauge.
-func (g *GaugeRef) Get() float64 {
-       return -1
+func (h *HistogramObserveInterceptor) BeforeInvoke(_ operator.Invocation) 
error {
+       return nil
 }
 
-type Histogram struct {
-}
-
-// Observe find the value associate bucket and add 1.
-func (h *Histogram) Observe(val float64) {
-
-}
-
-// ObserveWithCount find the value associate bucket and add specific count.
-func (h *Histogram) ObserveWithCount(val float64, count int64) {
-
-}
-
-type MeterOpt struct {
-}
+func (h *HistogramObserveInterceptor) AfterInvoke(invocation 
operator.Invocation, result ...interface{}) error {
+       enhanced, ok := invocation.CallerInstance().(operator.EnhancedInstance)
+       if !ok {
+               return nil
+       }
 
-// WithLabels Add labels for metric
-func WithLabels(key, val string) MeterOpt {
-       return MeterOpt{}
+       histogram, ok := 
enhanced.GetSkyWalkingDynamicField().(metrics.Histogram)
+       if ok && histogram != nil {
+               histogram.Observe(invocation.Args()[0].(float64))
+       }
+       return nil
 }
diff --git a/toolkit/metric/metrics.go 
b/plugins/toolkit-activation/metric/histogram_observewithcount_intercepter.go
similarity index 53%
copy from toolkit/metric/metrics.go
copy to 
plugins/toolkit-activation/metric/histogram_observewithcount_intercepter.go
index fdf433b..8cc1783 100644
--- a/toolkit/metric/metrics.go
+++ 
b/plugins/toolkit-activation/metric/histogram_observewithcount_intercepter.go
@@ -17,41 +17,26 @@
 
 package metric
 
-type CounterRef struct{}
+import (
+       "github.com/apache/skywalking-go/plugins/core/metrics"
+       "github.com/apache/skywalking-go/plugins/core/operator"
+)
 
-// Get returns the current value of the counter.
-func (c *CounterRef) Get() float64 {
-       return -1
-}
-
-// Inc increments the counter with value.
-func (c *CounterRef) Inc(val float64) {}
-
-type GaugeRef struct {
-}
+type HistogramObserveWithCountInterceptor struct{}
 
-// Get returns the current value of the gauge.
-func (g *GaugeRef) Get() float64 {
-       return -1
+func (h *HistogramObserveWithCountInterceptor) BeforeInvoke(_ 
operator.Invocation) error {
+       return nil
 }
 
-type Histogram struct {
-}
-
-// Observe find the value associate bucket and add 1.
-func (h *Histogram) Observe(val float64) {
-
-}
-
-// ObserveWithCount find the value associate bucket and add specific count.
-func (h *Histogram) ObserveWithCount(val float64, count int64) {
-
-}
-
-type MeterOpt struct {
-}
+func (h *HistogramObserveWithCountInterceptor) AfterInvoke(invocation 
operator.Invocation, result ...interface{}) error {
+       enhanced, ok := invocation.CallerInstance().(operator.EnhancedInstance)
+       if !ok {
+               return nil
+       }
 
-// WithLabels Add labels for metric
-func WithLabels(key, val string) MeterOpt {
-       return MeterOpt{}
+       histogram, ok := 
enhanced.GetSkyWalkingDynamicField().(metrics.Histogram)
+       if ok && histogram != nil {
+               histogram.ObserveWithCount(invocation.Args()[0].(float64), 
invocation.Args()[1].(int64))
+       }
+       return nil
 }
diff --git a/toolkit/metric/api.go 
b/plugins/toolkit-activation/metric/meter_opt_intercepter.go
similarity index 57%
copy from toolkit/metric/api.go
copy to plugins/toolkit-activation/metric/meter_opt_intercepter.go
index daa27e4..a72676e 100644
--- a/toolkit/metric/api.go
+++ b/plugins/toolkit-activation/metric/meter_opt_intercepter.go
@@ -6,7 +6,7 @@
 // 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
+//     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
@@ -17,17 +17,21 @@
 
 package metric
 
-// NewCounter creates a new counter metrics.
-func NewCounter(name string, opt ...MeterOpt) *CounterRef {
-       return &CounterRef{}
-}
+import (
+       "github.com/apache/skywalking-go/plugins/core/metrics"
+       "github.com/apache/skywalking-go/plugins/core/operator"
+)
+
+type WithLabelsInterceptor struct{}
 
-// NewGauge creates a new gauge metrics.
-func NewGauge(name string, watcher func() float64, opts ...MeterOpt) *GaugeRef 
{
-       return &GaugeRef{}
+func (h *WithLabelsInterceptor) BeforeInvoke(_ operator.Invocation) error {
+       return nil
 }
 
-// NewHistogram creates a new histogram metrics.
-func NewHistogram(name string, steps []float64, opts ...MeterOpt) *Histogram {
-       return &Histogram{}
+func (h *WithLabelsInterceptor) AfterInvoke(invocation operator.Invocation, _ 
...interface{}) error {
+       key := invocation.Args()[0].(string)
+       val := invocation.Args()[1].(string)
+       withLabelOpt := metrics.WithLabel(key, val)
+       invocation.DefineReturnValues(withLabelOpt)
+       return nil
 }
diff --git a/toolkit/metric/metrics.go 
b/plugins/toolkit-activation/metric/new_counter_intercepter.go
similarity index 52%
copy from toolkit/metric/metrics.go
copy to plugins/toolkit-activation/metric/new_counter_intercepter.go
index fdf433b..193a256 100644
--- a/toolkit/metric/metrics.go
+++ b/plugins/toolkit-activation/metric/new_counter_intercepter.go
@@ -17,41 +17,28 @@
 
 package metric
 
-type CounterRef struct{}
-
-// Get returns the current value of the counter.
-func (c *CounterRef) Get() float64 {
-       return -1
-}
-
-// Inc increments the counter with value.
-func (c *CounterRef) Inc(val float64) {}
-
-type GaugeRef struct {
-}
-
-// Get returns the current value of the gauge.
-func (g *GaugeRef) Get() float64 {
-       return -1
-}
-
-type Histogram struct {
-}
-
-// Observe find the value associate bucket and add 1.
-func (h *Histogram) Observe(val float64) {
-
-}
-
-// ObserveWithCount find the value associate bucket and add specific count.
-func (h *Histogram) ObserveWithCount(val float64, count int64) {
-
-}
-
-type MeterOpt struct {
-}
-
-// WithLabels Add labels for metric
-func WithLabels(key, val string) MeterOpt {
-       return MeterOpt{}
+import (
+       "github.com/apache/skywalking-go/plugins/core/metrics"
+       "github.com/apache/skywalking-go/plugins/core/operator"
+       "github.com/apache/skywalking-go/toolkit/metric"
+)
+
+type NewCounterInterceptor struct{}
+
+func (h *NewCounterInterceptor) BeforeInvoke(_ operator.Invocation) error {
+       return nil
+}
+
+func (h *NewCounterInterceptor) AfterInvoke(invocation operator.Invocation, 
result ...interface{}) error {
+       enhanced := result[0].(operator.EnhancedInstance)
+       metricName := invocation.Args()[0].(string)
+       var opts []metrics.Opt
+       for _, o := range invocation.Args()[1].([]metric.MeterOpt) {
+               opt := o.(metrics.Opt)
+               opts = append(opts, opt)
+       }
+
+       counter := metrics.NewCounter(metricName, opts...)
+       enhanced.SetSkyWalkingDynamicField(counter)
+       return nil
 }
diff --git a/toolkit/metric/metrics.go 
b/plugins/toolkit-activation/metric/new_gauge_intercepter.go
similarity index 51%
copy from toolkit/metric/metrics.go
copy to plugins/toolkit-activation/metric/new_gauge_intercepter.go
index fdf433b..0a053f6 100644
--- a/toolkit/metric/metrics.go
+++ b/plugins/toolkit-activation/metric/new_gauge_intercepter.go
@@ -17,41 +17,29 @@
 
 package metric
 
-type CounterRef struct{}
-
-// Get returns the current value of the counter.
-func (c *CounterRef) Get() float64 {
-       return -1
-}
-
-// Inc increments the counter with value.
-func (c *CounterRef) Inc(val float64) {}
-
-type GaugeRef struct {
-}
-
-// Get returns the current value of the gauge.
-func (g *GaugeRef) Get() float64 {
-       return -1
-}
-
-type Histogram struct {
-}
-
-// Observe find the value associate bucket and add 1.
-func (h *Histogram) Observe(val float64) {
-
-}
-
-// ObserveWithCount find the value associate bucket and add specific count.
-func (h *Histogram) ObserveWithCount(val float64, count int64) {
-
-}
-
-type MeterOpt struct {
-}
-
-// WithLabels Add labels for metric
-func WithLabels(key, val string) MeterOpt {
-       return MeterOpt{}
+import (
+       "github.com/apache/skywalking-go/plugins/core/metrics"
+       "github.com/apache/skywalking-go/plugins/core/operator"
+       "github.com/apache/skywalking-go/toolkit/metric"
+)
+
+type NewGaugeInterceptor struct{}
+
+func (h *NewGaugeInterceptor) BeforeInvoke(_ operator.Invocation) error {
+       return nil
+}
+
+func (h *NewGaugeInterceptor) AfterInvoke(invocation operator.Invocation, 
result ...interface{}) error {
+       enhanced := result[0].(operator.EnhancedInstance)
+       metricName := invocation.Args()[0].(string)
+       getterFn := invocation.Args()[1].(func() float64)
+       var opts []metrics.Opt
+       for _, o := range invocation.Args()[2].([]metric.MeterOpt) {
+               opt := o.(metrics.Opt)
+               opts = append(opts, opt)
+       }
+
+       gauge := metrics.NewGauge(metricName, getterFn, opts...)
+       enhanced.SetSkyWalkingDynamicField(gauge)
+       return nil
 }
diff --git a/toolkit/metric/metrics.go 
b/plugins/toolkit-activation/metric/new_histogram_intercepter.go
similarity index 51%
copy from toolkit/metric/metrics.go
copy to plugins/toolkit-activation/metric/new_histogram_intercepter.go
index fdf433b..f1935a8 100644
--- a/toolkit/metric/metrics.go
+++ b/plugins/toolkit-activation/metric/new_histogram_intercepter.go
@@ -17,41 +17,29 @@
 
 package metric
 
-type CounterRef struct{}
-
-// Get returns the current value of the counter.
-func (c *CounterRef) Get() float64 {
-       return -1
-}
-
-// Inc increments the counter with value.
-func (c *CounterRef) Inc(val float64) {}
-
-type GaugeRef struct {
-}
-
-// Get returns the current value of the gauge.
-func (g *GaugeRef) Get() float64 {
-       return -1
-}
-
-type Histogram struct {
-}
-
-// Observe find the value associate bucket and add 1.
-func (h *Histogram) Observe(val float64) {
-
-}
-
-// ObserveWithCount find the value associate bucket and add specific count.
-func (h *Histogram) ObserveWithCount(val float64, count int64) {
-
-}
-
-type MeterOpt struct {
-}
-
-// WithLabels Add labels for metric
-func WithLabels(key, val string) MeterOpt {
-       return MeterOpt{}
+import (
+       "github.com/apache/skywalking-go/plugins/core/metrics"
+       "github.com/apache/skywalking-go/plugins/core/operator"
+       "github.com/apache/skywalking-go/toolkit/metric"
+)
+
+type NewHistogramInterceptor struct{}
+
+func (h *NewHistogramInterceptor) BeforeInvoke(_ operator.Invocation) error {
+       return nil
+}
+
+func (h *NewHistogramInterceptor) AfterInvoke(invocation operator.Invocation, 
result ...interface{}) error {
+       enhanced := result[0].(operator.EnhancedInstance)
+       metricName := invocation.Args()[0].(string)
+       steps := invocation.Args()[1].([]float64)
+       var opts []metrics.Opt
+       for _, o := range invocation.Args()[2].([]metric.MeterOpt) {
+               opt := o.(metrics.Opt)
+               opts = append(opts, opt)
+       }
+
+       gauge := metrics.NewHistogram(metricName, steps, opts...)
+       enhanced.SetSkyWalkingDynamicField(gauge)
+       return nil
 }
diff --git a/test/plugins/scenarios/metric-activation/bin/startup.sh 
b/test/plugins/scenarios/metric-activation/bin/startup.sh
new file mode 100644
index 0000000..8e39d23
--- /dev/null
+++ b/test/plugins/scenarios/metric-activation/bin/startup.sh
@@ -0,0 +1,22 @@
+# 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.
+
+home="$(cd "$(dirname $0)"; pwd)"
+go build ${GO_BUILD_OPTS} -o metric-activation
+
+export SW_AGENT_METER_COLLECT_INTERVAL=1
+
+./metric-activation
\ No newline at end of file
diff --git a/test/plugins/scenarios/metric-activation/config/excepted.yml 
b/test/plugins/scenarios/metric-activation/config/excepted.yml
new file mode 100644
index 0000000..754d6d9
--- /dev/null
+++ b/test/plugins/scenarios/metric-activation/config/excepted.yml
@@ -0,0 +1,79 @@
+# 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.
+
+segmentItems: []
+meterItems:
+  - serviceName: metric-activation
+    meterSize: ge 4
+    meters:
+      - meterId:
+          name: request_counter
+          tags: []
+        singleValue: ge 1
+      - meterId:
+          name: request_counter_with_label
+          tags:
+            - { name: foo, value: bar }
+        singleValue: ge 1
+      - meterId:
+          name: cpu_usage_gauge
+          tags: []
+        singleValue: ge 50
+      - meterId:
+          name: cpu_usage_gauge_with_label
+          tags:
+            - { name: foo, value: bar }
+        singleValue: ge 30
+      - meterId:
+          name: request_duration
+          tags: []
+        histogramBuckets:
+          - 0.0
+          - 5.0
+          - 20.0
+          - 50.0
+          - 100.0
+          - 500.0
+          - 1000.0
+        histogramValues:
+          - 0
+          - 1
+          - 3
+          - 0
+          - 1
+          - 0
+          - 1
+      - meterId:
+          name: request_duration_with_label
+          tags:
+            - { name: foo, value: bar }
+        histogramBuckets:
+          - 0.0
+          - 5.0
+          - 20.0
+          - 50.0
+          - 100.0
+          - 500.0
+          - 1000.0
+        histogramValues:
+          - 0
+          - 1
+          - 0
+          - 0
+          - 2
+          - 2
+          - 1
+logItems: []
diff --git a/test/plugins/scenarios/metric-activation/go.mod 
b/test/plugins/scenarios/metric-activation/go.mod
new file mode 100644
index 0000000..bd3ea7b
--- /dev/null
+++ b/test/plugins/scenarios/metric-activation/go.mod
@@ -0,0 +1,3 @@
+module test/plugins/scenarios/metric-activation
+
+go 1.19
diff --git a/test/plugins/scenarios/metric-activation/main.go 
b/test/plugins/scenarios/metric-activation/main.go
new file mode 100644
index 0000000..f075b3d
--- /dev/null
+++ b/test/plugins/scenarios/metric-activation/main.go
@@ -0,0 +1,64 @@
+// 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 main
+
+import (
+       "io"
+       "log"
+       "net/http"
+       "time"
+
+       _ "github.com/apache/skywalking-go"
+)
+
+func providerHandler(w http.ResponseWriter, r *http.Request) {
+       testCounter()
+       testGauge()
+       testHistogram()
+
+       time.Sleep(2 * time.Second) // make sure the meter already uploaded
+       _, _ = w.Write([]byte("success"))
+}
+
+func consumerHandler(w http.ResponseWriter, r *http.Request) {
+       resp, err := http.Get("http://localhost:8080/provider?test=1";)
+       if err != nil {
+               log.Printf("request provider error: %v", err)
+               w.WriteHeader(http.StatusInternalServerError)
+               return
+       }
+       defer resp.Body.Close()
+       body, err := io.ReadAll(resp.Body)
+       if err != nil {
+               log.Print(err)
+               w.WriteHeader(http.StatusInternalServerError)
+               return
+       }
+       _, _ = w.Write(body)
+}
+
+func main() {
+       http.HandleFunc("/provider", providerHandler)
+       http.HandleFunc("/consumer", consumerHandler)
+
+       http.HandleFunc("/health", func(writer http.ResponseWriter, request 
*http.Request) {
+               writer.WriteHeader(http.StatusOK)
+       })
+
+       _ = http.ListenAndServe(":8080", nil)
+}
diff --git a/test/plugins/scenarios/metric-activation/plugin.yml 
b/test/plugins/scenarios/metric-activation/plugin.yml
new file mode 100644
index 0000000..f8316f3
--- /dev/null
+++ b/test/plugins/scenarios/metric-activation/plugin.yml
@@ -0,0 +1,28 @@
+# 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.
+
+entry-service: http://${HTTP_HOST}:${HTTP_PORT}/consumer
+health-checker: http://${HTTP_HOST}:${HTTP_PORT}/health
+start-script: ./bin/startup.sh
+framework: go
+export-port: 8080
+support-version:
+  - go: 1.19
+  - go: 1.20
+  - go: 1.21
+  - go: 1.22
+  - go: 1.23
+toolkit: true
diff --git a/test/plugins/scenarios/metric-activation/test_service.go 
b/test/plugins/scenarios/metric-activation/test_service.go
new file mode 100644
index 0000000..b83045b
--- /dev/null
+++ b/test/plugins/scenarios/metric-activation/test_service.go
@@ -0,0 +1,57 @@
+// 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 main
+
+import (
+       "github.com/apache/skywalking-go/toolkit/metric"
+)
+
+func testCounter() {
+       requestCounter := metric.NewCounter("request_counter")
+       requestCounter.Inc(1)
+
+       requestCounterWithLabel := 
metric.NewCounter("request_counter_with_label", metric.WithLabels("foo", "bar"))
+       requestCounterWithLabel.Inc(1)
+}
+
+func testGauge() {
+       metric.NewGauge("cpu_usage_gauge", func() float64 {
+               return 50
+       })
+
+       metric.NewGauge("cpu_usage_gauge_with_label", func() float64 {
+               return 30
+       }, metric.WithLabels("foo", "bar"))
+}
+
+func testHistogram() {
+       steps := []float64{5, 20, 50, 100, 500, 1000}
+       histogram := metric.NewHistogram("request_duration", steps)
+       histogram.Observe(10)
+       histogram.Observe(200)
+       histogram.Observe(1500)
+       histogram.ObserveWithCount(20, 1)
+       histogram.ObserveWithCount(20, 2)
+
+       histogramWithLabel := 
metric.NewHistogram("request_duration_with_label", steps, 
metric.WithLabels("foo", "bar"))
+       histogramWithLabel.Observe(10)
+       histogramWithLabel.Observe(200)
+       histogramWithLabel.Observe(1500)
+       histogramWithLabel.ObserveWithCount(100, 1)
+       histogramWithLabel.ObserveWithCount(500, 2)
+}
diff --git a/toolkit/metric/api.go b/toolkit/metric/api.go
index daa27e4..826b8d5 100644
--- a/toolkit/metric/api.go
+++ b/toolkit/metric/api.go
@@ -23,11 +23,21 @@ func NewCounter(name string, opt ...MeterOpt) *CounterRef {
 }
 
 // NewGauge creates a new gauge metrics.
-func NewGauge(name string, watcher func() float64, opts ...MeterOpt) *GaugeRef 
{
+func NewGauge(name string, getter func() float64, opts ...MeterOpt) *GaugeRef {
        return &GaugeRef{}
 }
 
 // NewHistogram creates a new histogram metrics.
-func NewHistogram(name string, steps []float64, opts ...MeterOpt) *Histogram {
-       return &Histogram{}
+func NewHistogram(name string, steps []float64, opts ...MeterOpt) 
*HistogramRef {
+       return &HistogramRef{}
+}
+
+// MeterOpt Defines common options apply for Meter.
+// This is implemented in core/metrics package and converted in interceptors.
+type MeterOpt interface {
+}
+
+// WithLabels Add labels for metric
+func WithLabels(key, val string) MeterOpt {
+       return nil
 }
diff --git a/toolkit/metric/metrics.go b/toolkit/metric/metrics.go
index fdf433b..3dea739 100644
--- a/toolkit/metric/metrics.go
+++ b/toolkit/metric/metrics.go
@@ -35,23 +35,15 @@ func (g *GaugeRef) Get() float64 {
        return -1
 }
 
-type Histogram struct {
+type HistogramRef struct {
 }
 
 // Observe find the value associate bucket and add 1.
-func (h *Histogram) Observe(val float64) {
+func (h *HistogramRef) Observe(val float64) {
 
 }
 
 // ObserveWithCount find the value associate bucket and add specific count.
-func (h *Histogram) ObserveWithCount(val float64, count int64) {
+func (h *HistogramRef) ObserveWithCount(val float64, count int64) {
 
 }
-
-type MeterOpt struct {
-}
-
-// WithLabels Add labels for metric
-func WithLabels(key, val string) MeterOpt {
-       return MeterOpt{}
-}

Reply via email to