[ 
https://issues.apache.org/jira/browse/SCB-983?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16664942#comment-16664942
 ] 

ASF GitHub Bot commented on SCB-983:
------------------------------------

little-cui closed pull request #467: SCB-983 Output the QPS per domain
URL: https://github.com/apache/incubator-servicecomb-service-center/pull/467
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/server/metric/calculator.go b/server/metric/calculator.go
index 523f7f52..7f0a8909 100644
--- a/server/metric/calculator.go
+++ b/server/metric/calculator.go
@@ -24,6 +24,7 @@ var (
        DefaultCalculator Calculator = &CommonCalculator{}
 )
 
+// Calculator is the interface to implement customize algorithm of MetricFamily
 type Calculator interface {
        Calc(mf *dto.MetricFamily) *Details
 }
@@ -53,14 +54,14 @@ func (c *CommonCalculator) Calc(mf *dto.MetricFamily) 
*Details {
 
 func metricGaugeOf(details *Details, m []*dto.Metric) {
        for _, d := range m {
-               details.Value += d.GetGauge().GetValue()
+               details.Summary += d.GetGauge().GetValue()
                details.Put(d.GetLabel(), d.GetGauge().GetValue())
        }
 }
 
 func metricCounterOf(details *Details, m []*dto.Metric) {
        for _, d := range m {
-               details.Value += d.GetCounter().GetValue()
+               details.Summary += d.GetCounter().GetValue()
                details.Put(d.GetLabel(), d.GetCounter().GetValue())
        }
 }
@@ -80,7 +81,7 @@ func metricSummaryOf(details *Details, m []*dto.Metric) {
                return
        }
 
-       details.Value = sum / float64(count)
+       details.Summary = sum / float64(count)
 }
 
 func metricHistogramOf(details *Details, m []*dto.Metric) {
@@ -98,7 +99,7 @@ func metricHistogramOf(details *Details, m []*dto.Metric) {
                return
        }
 
-       details.Value = sum / float64(count)
+       details.Summary = sum / float64(count)
 }
 
 func RegisterCalculator(c Calculator) {
diff --git a/server/metric/calculator_test.go b/server/metric/calculator_test.go
index 4634530c..41ce510f 100644
--- a/server/metric/calculator_test.go
+++ b/server/metric/calculator_test.go
@@ -45,7 +45,7 @@ func TestCommonCalculator_Calc(t *testing.T) {
        mf = &dto.MetricFamily{Type: &mt, Metric: []*dto.Metric{
                {Gauge: &dto.Gauge{Value: &v1}}, {Gauge: &dto.Gauge{Value: 
&v2}}}}
        details := c.Calc(mf)
-       if details.Value != 3 {
+       if details.Summary != 3 {
                t.Fatalf("TestCommonCalculator_Calc failed")
        }
 
@@ -54,7 +54,7 @@ func TestCommonCalculator_Calc(t *testing.T) {
        mf = &dto.MetricFamily{Type: &mt, Metric: []*dto.Metric{
                {Counter: &dto.Counter{Value: &v1}}, {Counter: 
&dto.Counter{Value: &v1}}}}
        details = c.Calc(mf)
-       if details.Value != 2 {
+       if details.Summary != 2 {
                t.Fatalf("TestCommonCalculator_Calc failed")
        }
 
@@ -64,7 +64,7 @@ func TestCommonCalculator_Calc(t *testing.T) {
        mf = &dto.MetricFamily{Type: &mt, Metric: []*dto.Metric{
                {Summary: &dto.Summary{SampleCount: &n, SampleSum: &v1}}, 
{Summary: &dto.Summary{SampleCount: &n, SampleSum: &v1}}}}
        details = c.Calc(mf)
-       if details.Value != v1/float64(n) {
+       if details.Summary != v1/float64(n) {
                t.Fatalf("TestCommonCalculator_Calc failed")
        }
 }
diff --git a/server/metric/metrics.go b/server/metric/metrics.go
index d828cb91..cc428122 100644
--- a/server/metric/metrics.go
+++ b/server/metric/metrics.go
@@ -36,8 +36,10 @@ func NewDetails() *Details {
        }
 }
 
+// Details is the struct to hold the calculated result and index by metric 
label
 type Details struct {
-       Value float64
+       // Summary is the calculation results of the details
+       Summary float64
 
        mapper *util.ConcurrentMap
        buffer *buffer.Pool
@@ -68,6 +70,13 @@ func (cm *Details) toLabels(key string) (p []*dto.LabelPair) 
{
        return
 }
 
+func (cm *Details) Get(labels []*dto.LabelPair) (val float64) {
+       if v, ok := cm.mapper.Get(cm.toKey(labels)); ok {
+               val = v.(float64)
+       }
+       return
+}
+
 func (cm *Details) Put(labels []*dto.LabelPair, val float64) {
        cm.mapper.Put(cm.toKey(labels), val)
        return
@@ -81,6 +90,7 @@ func (cm *Details) ForEach(f func(labels []*dto.LabelPair, v 
float64) (next bool
        })
 }
 
+// Metrics is the struct to hold the Details objects store and index by metric 
name
 type Metrics struct {
        mapper *util.ConcurrentMap
 }
@@ -89,9 +99,9 @@ func (cm *Metrics) Put(key string, val *Details) {
        cm.mapper.Put(key, val)
 }
 
-func (cm *Metrics) Get(key string) (val float64) {
+func (cm *Metrics) Get(key string) (val *Details) {
        if v, ok := cm.mapper.Get(key); ok {
-               val = v.(*Details).Value
+               val = v.(*Details)
        }
        return
 }
@@ -103,3 +113,10 @@ func (cm *Metrics) ForEach(f func(k string, v *Details) 
(next bool)) {
                return f(k, v)
        })
 }
+
+func (cm *Metrics) Summary(key string) (sum float64) {
+       if v, ok := cm.mapper.Get(key); ok {
+               sum = v.(*Details).Summary
+       }
+       return
+}
diff --git a/server/metric/metrics_test.go b/server/metric/metrics_test.go
index 1e4a11d0..2f3b4b19 100644
--- a/server/metric/metrics_test.go
+++ b/server/metric/metrics_test.go
@@ -62,4 +62,34 @@ func TestDetails_ForEach(t *testing.T) {
        if l != 3 {
                t.Fatalf("TestDetails_ForEach failed")
        }
+
+       ms := NewMetrics()
+       if ms.Summary("x") != 0 {
+               t.Fatalf("TestMetrics_Summary failed")
+       }
+       if ms.Get("x") != nil {
+               t.Fatalf("TestMetrics_Details failed")
+       }
+       find := false
+       ms.ForEach(func(k string, v *Details) (next bool) {
+               find = true
+               return true
+       })
+       if find {
+               t.Fatalf("TestMetrics_ForEach failed")
+       }
+       ms.Put("a", d)
+       if ms.Summary("a") != 0 {
+               t.Fatalf("TestMetrics_Summary failed")
+       }
+       if ms.Get("a") != d {
+               t.Fatalf("TestMetrics_Get failed")
+       }
+       ms.ForEach(func(k string, v *Details) (next bool) {
+               find = true
+               return true
+       })
+       if !find {
+               t.Fatalf("TestMetrics_ForEach failed")
+       }
 }
diff --git a/server/metric/reporter.go b/server/metric/reporter.go
index d19a8493..bb67dc2a 100644
--- a/server/metric/reporter.go
+++ b/server/metric/reporter.go
@@ -20,6 +20,7 @@ import 
"github.com/apache/incubator-servicecomb-service-center/pkg/log"
 
 var reporters = make(map[string]Reporter)
 
+// Reporter is the interface to implement handler to process metrics after 
calculate
 type Reporter interface {
        Report()
 }
diff --git a/server/plugin/pkg/discovery/etcd/metrics_test.go 
b/server/plugin/pkg/discovery/etcd/metrics_test.go
index a64b4348..5f3b5b4a 100644
--- a/server/plugin/pkg/discovery/etcd/metrics_test.go
+++ b/server/plugin/pkg/discovery/etcd/metrics_test.go
@@ -32,13 +32,13 @@ func TestReportCacheSize(t *testing.T) {
        if err != nil {
                t.Fatalf("TestReportCacheSize failed")
        }
-       if metric.Gatherer.Records.Get("local_cache_size_bytes") != 100 {
+       if metric.Gatherer.Records.Summary("local_cache_size_bytes") != 100 {
                t.Fatalf("TestReportCacheSize failed")
        }
 
        ReportCacheSize("", "b", 200)
        err = metric.Gatherer.Collect()
-       if metric.Gatherer.Records.Get("local_cache_size_bytes") != 100 {
+       if metric.Gatherer.Records.Summary("local_cache_size_bytes") != 100 {
                t.Fatalf("TestReportCacheSize failed")
        }
 }
diff --git a/server/rest/metrics.go b/server/rest/metrics.go
index 2aabd456..78717a31 100644
--- a/server/rest/metrics.go
+++ b/server/rest/metrics.go
@@ -18,6 +18,7 @@ package rest
 
 import (
        "github.com/apache/incubator-servicecomb-service-center/pkg/rest"
+       "github.com/apache/incubator-servicecomb-service-center/pkg/util"
        "github.com/apache/incubator-servicecomb-service-center/server/metric"
        "github.com/prometheus/client_golang/prometheus"
        "net/http"
@@ -33,7 +34,7 @@ var (
                        Subsystem: "http",
                        Name:      "request_total",
                        Help:      "Counter of requests received into ROA 
handler",
-               }, []string{"method", "code", "instance", "api"})
+               }, []string{"method", "code", "instance", "api", "domain"})
 
        successfulRequests = prometheus.NewCounterVec(
                prometheus.CounterOpts{
@@ -41,7 +42,7 @@ var (
                        Subsystem: "http",
                        Name:      "success_total",
                        Help:      "Counter of successful requests processed by 
ROA handler",
-               }, []string{"method", "code", "instance", "api"})
+               }, []string{"method", "code", "instance", "api", "domain"})
 
        reqDurations = prometheus.NewSummaryVec(
                prometheus.SummaryOpts{
@@ -50,11 +51,19 @@ var (
                        Name:       "request_durations_microseconds",
                        Help:       "HTTP request latency summary of ROA 
handler",
                        Objectives: prometheus.DefObjectives,
-               }, []string{"method", "instance", "api"})
+               }, []string{"method", "instance", "api", "domain"})
+
+       queryPerSeconds = prometheus.NewGaugeVec(
+               prometheus.GaugeOpts{
+                       Namespace: metric.FamilyName,
+                       Subsystem: "http",
+                       Name:      "query_per_seconds",
+                       Help:      "HTTP requests per seconds of ROA handler",
+               }, []string{"method", "instance", "api", "domain"})
 )
 
 func init() {
-       prometheus.MustRegister(incomingRequests, successfulRequests, 
reqDurations)
+       prometheus.MustRegister(incomingRequests, successfulRequests, 
reqDurations, queryPerSeconds)
 
        RegisterServerHandler("/metrics", prometheus.Handler())
 }
@@ -63,17 +72,18 @@ func ReportRequestCompleted(w http.ResponseWriter, r 
*http.Request, start time.T
        instance := metric.InstanceName()
        elapsed := float64(time.Since(start).Nanoseconds()) / 
float64(time.Microsecond)
        route, _ := r.Context().Value(rest.CTX_MATCH_FUNC).(string)
+       domain := util.ParseDomain(r.Context())
 
        if strings.Index(r.Method, "WATCH") != 0 {
-               reqDurations.WithLabelValues(r.Method, instance, 
route).Observe(elapsed)
+               reqDurations.WithLabelValues(r.Method, instance, route, 
domain).Observe(elapsed)
        }
 
        success, code := codeOf(w.Header())
 
-       incomingRequests.WithLabelValues(r.Method, code, instance, route).Inc()
+       incomingRequests.WithLabelValues(r.Method, code, instance, route, 
domain).Inc()
 
        if success {
-               successfulRequests.WithLabelValues(r.Method, code, instance, 
route).Inc()
+               successfulRequests.WithLabelValues(r.Method, code, instance, 
route, domain).Inc()
        }
 }
 
diff --git a/server/rest/reporter.go b/server/rest/reporter.go
new file mode 100644
index 00000000..d103ade0
--- /dev/null
+++ b/server/rest/reporter.go
@@ -0,0 +1,68 @@
+// 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.
+
+package rest
+
+import (
+       "github.com/apache/incubator-servicecomb-service-center/server/metric"
+       dto "github.com/prometheus/client_model/go"
+)
+
+const (
+       httpRequestTotal = "http_request_total"
+)
+
+var qpsLabelMap = map[string]int{
+       "method":   0,
+       "instance": 1,
+       "api":      2,
+       "domain":   3,
+}
+
+type APIReporter struct {
+       cache *metric.Details
+}
+
+func (r *APIReporter) Report() {
+       details := metric.Gatherer.Records.Get(httpRequestTotal)
+       defer func() { r.cache = details }()
+
+       if r.cache == nil {
+               return
+       }
+       details.ForEach(func(labels []*dto.LabelPair, v float64) (next bool) {
+               old := r.cache.Get(labels)
+               queryPerSeconds.WithLabelValues(r.toLabels(labels)...).Set((v - 
old) / metric.Period.Seconds())
+               return true
+       })
+}
+
+func (r *APIReporter) toLabels(pairs []*dto.LabelPair) (labels []string) {
+       labels = make([]string, len(qpsLabelMap))
+       for _, pair := range pairs {
+               if i, ok := qpsLabelMap[pair.GetName()]; ok {
+                       labels[i] = pair.GetValue()
+               }
+       }
+       return
+}
+
+func init() {
+       metric.RegisterReporter("rest", NewAPIReporter())
+}
+
+func NewAPIReporter() *APIReporter {
+       return &APIReporter{}
+}


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
[email protected]


> Output the QPS per domain
> -------------------------
>
>                 Key: SCB-983
>                 URL: https://issues.apache.org/jira/browse/SCB-983
>             Project: Apache ServiceComb
>          Issue Type: Improvement
>          Components: Service-Center
>            Reporter: little-cui
>            Assignee: little-cui
>            Priority: Major
>             Fix For: service-center-1.1.0
>
>




--
This message was sent by Atlassian JIRA
(v7.6.3#76005)

Reply via email to