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

littlecui pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-service-center.git


The following commit(s) were added to refs/heads/master by this push:
     new 36f7e05  SCB-1092 More abundant metrics information (#519)
36f7e05 is described below

commit 36f7e051fb49518e8457b3cc27d06b79b26ca429
Author: little-cui <[email protected]>
AuthorDate: Fri Dec 28 11:19:41 2018 +0800

    SCB-1092 More abundant metrics information (#519)
---
 integration/health-metrics-grafana.json            | 652 +++++++++++++++++++--
 pkg/etcdsync/mutex.go                              |  14 +-
 pkg/notify/notice.go                               |  16 +-
 pkg/notify/notification_test.go                    |   2 +-
 server/core/backend/lease.go                       |   1 +
 server/core/backend/metrics.go                     |  36 +-
 server/notify/metrics.go                           |  61 ++
 server/notify/stream.go                            |   1 +
 server/notify/websocket.go                         |  12 +-
 server/plugin/pkg/discovery/etcd/cacher_kv.go      |   3 +
 .../pkg/{registry/etcd => discovery}/metrics.go    |  35 +-
 server/plugin/pkg/registry/etcd/common.go          |  34 ++
 server/plugin/pkg/registry/etcd/etcd.go            |  71 ++-
 server/plugin/pkg/registry/{etcd => }/metrics.go   |  38 +-
 server/service/event/event.go                      |   1 +
 .../service/event/schema_summary_event_handler.go  |  53 ++
 server/service/metrics/metrics.go                  |  15 +-
 17 files changed, 955 insertions(+), 90 deletions(-)

diff --git a/integration/health-metrics-grafana.json 
b/integration/health-metrics-grafana.json
index 7b435ba..0cf10b1 100644
--- a/integration/health-metrics-grafana.json
+++ b/integration/health-metrics-grafana.json
@@ -109,7 +109,7 @@
       },
       "gridPos": {
         "h": 3,
-        "w": 4,
+        "w": 3,
         "x": 0,
         "y": 0
       },
@@ -192,10 +192,10 @@
       "gridPos": {
         "h": 3,
         "w": 3,
-        "x": 4,
+        "x": 3,
         "y": 0
       },
-      "id": 26,
+      "id": 19,
       "interval": null,
       "links": [],
       "mappingType": 1,
@@ -233,7 +233,7 @@
       "tableColumn": "",
       "targets": [
         {
-          "expr": 
"max(service_center_db_domain_total{job=\"service-center\"})",
+          "expr": 
"max(service_center_db_backend_total{job=\"service-center\"})",
           "format": "time_series",
           "instant": false,
           "intervalFactor": 2,
@@ -241,7 +241,7 @@
         }
       ],
       "thresholds": "",
-      "title": "Domain Volume",
+      "title": "Backends",
       "type": "singlestat",
       "valueFontSize": "80%",
       "valueMaps": [
@@ -263,7 +263,7 @@
       "gridPos": {
         "h": 5,
         "w": 8,
-        "x": 7,
+        "x": 6,
         "y": 0
       },
       "height": "",
@@ -358,7 +358,7 @@
       "gridPos": {
         "h": 5,
         "w": 9,
-        "x": 15,
+        "x": 14,
         "y": 0
       },
       "id": 25,
@@ -412,11 +412,11 @@
       },
       "gridPos": {
         "h": 3,
-        "w": 4,
+        "w": 3,
         "x": 0,
         "y": 3
       },
-      "id": 19,
+      "id": 26,
       "interval": null,
       "links": [],
       "mappingType": 1,
@@ -454,7 +454,7 @@
       "tableColumn": "",
       "targets": [
         {
-          "expr": 
"max(service_center_db_backend_total{job=\"service-center\"})",
+          "expr": 
"max(service_center_db_domain_total{job=\"service-center\"})",
           "format": "time_series",
           "instant": false,
           "intervalFactor": 2,
@@ -462,7 +462,7 @@
         }
       ],
       "thresholds": "",
-      "title": "Backends",
+      "title": "Domain Volume",
       "type": "singlestat",
       "valueFontSize": "80%",
       "valueMaps": [
@@ -495,10 +495,10 @@
       "gridPos": {
         "h": 3,
         "w": 3,
-        "x": 4,
+        "x": 3,
         "y": 3
       },
-      "id": 20,
+      "id": 21,
       "interval": null,
       "links": [],
       "mappingType": 1,
@@ -533,10 +533,10 @@
         "lineColor": "rgb(31, 120, 193)",
         "show": false
       },
-      "tableColumn": "",
+      "tableColumn": "Value",
       "targets": [
         {
-          "expr": 
"max(sum(service_center_db_service_total{job=\"service-center\"}) by 
(instance))",
+          "expr": 
"max(service_center_db_instance_total{job=\"service-center\"})",
           "format": "time_series",
           "instant": false,
           "intervalFactor": 2,
@@ -544,7 +544,7 @@
         }
       ],
       "thresholds": "",
-      "title": "Microservice Volume",
+      "title": "Instance Volume",
       "type": "singlestat",
       "valueFontSize": "80%",
       "valueMaps": [
@@ -566,7 +566,7 @@
       "gridPos": {
         "h": 5,
         "w": 8,
-        "x": 7,
+        "x": 6,
         "y": 5
       },
       "height": "",
@@ -663,7 +663,7 @@
       "gridPos": {
         "h": 5,
         "w": 3,
-        "x": 15,
+        "x": 14,
         "y": 5
       },
       "id": 31,
@@ -712,7 +712,7 @@
       "gridPos": {
         "h": 5,
         "w": 3,
-        "x": 18,
+        "x": 17,
         "y": 5
       },
       "id": 32,
@@ -761,7 +761,7 @@
       "gridPos": {
         "h": 5,
         "w": 3,
-        "x": 21,
+        "x": 20,
         "y": 5
       },
       "id": 33,
@@ -816,10 +816,92 @@
       "gridPos": {
         "h": 3,
         "w": 3,
-        "x": 4,
+        "x": 0,
         "y": 6
       },
-      "id": 21,
+      "id": 20,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "minSpan": 4,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": true,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "expr": 
"max(sum(service_center_db_service_total{job=\"service-center\"}) by 
(instance))",
+          "format": "time_series",
+          "instant": false,
+          "intervalFactor": 2,
+          "refId": "A"
+        }
+      ],
+      "thresholds": "",
+      "title": "Microservice Volume",
+      "type": "singlestat",
+      "valueFontSize": "80%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "current"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "#299c46",
+        "rgba(237, 129, 40, 0.89)",
+        "#d44a3a"
+      ],
+      "datasource": "${DS_LOCAL}",
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 3,
+        "x": 3,
+        "y": 6
+      },
+      "id": 39,
       "interval": null,
       "links": [],
       "mappingType": 1,
@@ -857,7 +939,7 @@
       "tableColumn": "Value",
       "targets": [
         {
-          "expr": 
"max(service_center_db_instance_total{job=\"service-center\"})",
+          "expr": 
"max(service_center_db_schema_total{job=\"service-center\"})",
           "format": "time_series",
           "instant": false,
           "intervalFactor": 2,
@@ -865,7 +947,7 @@
         }
       ],
       "thresholds": "",
-      "title": "Instance Volume",
+      "title": "Schema Volume",
       "type": "singlestat",
       "valueFontSize": "80%",
       "valueMaps": [
@@ -1403,6 +1485,96 @@
       }
     },
     {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": "${DS_LOCAL}",
+      "fill": 1,
+      "gridPos": {
+        "h": 6,
+        "w": 8,
+        "x": 8,
+        "y": 19
+      },
+      "height": "",
+      "id": 34,
+      "legend": {
+        "alignAsTable": true,
+        "avg": true,
+        "current": true,
+        "max": true,
+        "min": true,
+        "show": true,
+        "sort": null,
+        "sortDesc": null,
+        "total": false,
+        "values": true
+      },
+      "lines": true,
+      "linewidth": 1,
+      "links": [],
+      "minSpan": 4,
+      "nullPointMode": "null",
+      "percentage": false,
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "expr": 
"max(avg_over_time(service_center_db_heartbeat_durations_microseconds{job=\"service-center\"}[1m]))
 by (status)",
+          "format": "time_series",
+          "instant": false,
+          "intervalFactor": 2,
+          "legendFormat": "{{status}}",
+          "refId": "A"
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeShift": null,
+      "title": "Heartbeat Latency",
+      "tooltip": {
+        "shared": true,
+        "sort": 0,
+        "value_type": "individual"
+      },
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "µs",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        },
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
       "content": "<div class=\"text-center dashboard-header\">\n  
<span>INSTANCE METRICS</span>\n</div>\n",
       "gridPos": {
         "h": 3,
@@ -1569,6 +1741,13 @@
           "intervalFactor": 2,
           "legendFormat": "{{instance}}> {{method}} {{api}}",
           "refId": "A"
+        },
+        {
+          "expr": 
"sum(irate(service_center_db_heartbeat_total{job=\"service-center\"}[1m])) by 
(instance)",
+          "format": "time_series",
+          "intervalFactor": 1,
+          "legendFormat": "{{instance}}> RENEW Lease",
+          "refId": "B"
         }
       ],
       "thresholds": [],
@@ -1667,7 +1846,7 @@
       "thresholds": [],
       "timeFrom": null,
       "timeShift": null,
-      "title": "Read Latency",
+      "title": "API Read Latency",
       "tooltip": {
         "shared": true,
         "sort": 0,
@@ -1756,12 +1935,19 @@
           "intervalFactor": 2,
           "legendFormat": "{{instance}}> {{method}} {{api}}",
           "refId": "A"
+        },
+        {
+          "expr": 
"max(avg_over_time(service_center_db_heartbeat_durations_microseconds{job=\"service-center\"}[1m]))
 by (instance)",
+          "format": "time_series",
+          "intervalFactor": 1,
+          "legendFormat": "{{instance}}> RENEW Lease",
+          "refId": "B"
         }
       ],
       "thresholds": [],
       "timeFrom": null,
       "timeShift": null,
-      "title": "Write Latency",
+      "title": "API Write Latency",
       "tooltip": {
         "shared": true,
         "sort": 0,
@@ -1800,13 +1986,403 @@
       }
     },
     {
-      "content": "<div class=\"text-center dashboard-header\">\n  
<span>RESOURCES</span>\n</div>\n",
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": "${DS_LOCAL}",
+      "fill": 1,
       "gridPos": {
-        "h": 3,
-        "w": 24,
+        "h": 6,
+        "w": 6,
         "x": 0,
         "y": 34
       },
+      "height": "",
+      "id": 35,
+      "legend": {
+        "alignAsTable": false,
+        "avg": false,
+        "current": false,
+        "hideEmpty": true,
+        "hideZero": true,
+        "max": false,
+        "min": false,
+        "rightSide": false,
+        "show": false,
+        "sort": "avg",
+        "sortDesc": true,
+        "total": false,
+        "values": false
+      },
+      "lines": true,
+      "linewidth": 1,
+      "links": [],
+      "minSpan": 4,
+      "nullPointMode": "null",
+      "percentage": false,
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "expr": 
"sum(service_center_notify_publish_total{job=\"service-center\"}) by 
(instance,source)",
+          "format": "time_series",
+          "instant": false,
+          "intervalFactor": 2,
+          "legendFormat": "{{instance}}> {{source}}",
+          "refId": "A"
+        },
+        {
+          "expr": 
"sum(service_center_db_backend_event_total{job=\"service-center\"}) by 
(instance)",
+          "format": "time_series",
+          "intervalFactor": 1,
+          "legendFormat": "{{instance}}> BACKEND",
+          "refId": "B"
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeShift": null,
+      "title": "Events Total",
+      "tooltip": {
+        "shared": true,
+        "sort": 0,
+        "value_type": "individual"
+      },
+      "transparent": false,
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "decimals": 0,
+          "format": "none",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        },
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": "${DS_LOCAL}",
+      "fill": 1,
+      "gridPos": {
+        "h": 6,
+        "w": 6,
+        "x": 6,
+        "y": 34
+      },
+      "height": "",
+      "id": 36,
+      "legend": {
+        "alignAsTable": false,
+        "avg": true,
+        "current": false,
+        "hideEmpty": true,
+        "hideZero": true,
+        "max": true,
+        "min": true,
+        "rightSide": true,
+        "show": false,
+        "sort": "avg",
+        "sortDesc": true,
+        "total": false,
+        "values": true
+      },
+      "lines": true,
+      "linewidth": 1,
+      "links": [],
+      "minSpan": 4,
+      "nullPointMode": "null",
+      "percentage": false,
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "expr": 
"max(avg_over_time(service_center_notify_publish_durations_microseconds{job=\"service-center\"}[1m]))
 by (instance,source)",
+          "format": "time_series",
+          "intervalFactor": 1,
+          "legendFormat": "{{instance}}> {{source}}",
+          "refId": "B"
+        },
+        {
+          "expr": 
"max(avg_over_time(service_center_db_backend_event_durations_microseconds{job=\"service-center\"}[1m]))
 by (instance)",
+          "format": "time_series",
+          "intervalFactor": 1,
+          "legendFormat": "{{instance}}> BACKEND",
+          "refId": "A"
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeShift": null,
+      "title": "Events Latency",
+      "tooltip": {
+        "shared": true,
+        "sort": 0,
+        "value_type": "individual"
+      },
+      "transparent": false,
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "µs",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        },
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": "${DS_LOCAL}",
+      "fill": 1,
+      "gridPos": {
+        "h": 6,
+        "w": 6,
+        "x": 12,
+        "y": 34
+      },
+      "height": "",
+      "id": 37,
+      "legend": {
+        "alignAsTable": false,
+        "avg": false,
+        "current": false,
+        "hideEmpty": true,
+        "hideZero": true,
+        "max": false,
+        "min": false,
+        "rightSide": false,
+        "show": false,
+        "sort": "avg",
+        "sortDesc": true,
+        "total": false,
+        "values": false
+      },
+      "lines": true,
+      "linewidth": 1,
+      "links": [],
+      "minSpan": 4,
+      "nullPointMode": "null",
+      "percentage": false,
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "expr": 
"sum(service_center_db_backend_operation_total{job=\"service-center\"}) by 
(instance,operation)",
+          "format": "time_series",
+          "instant": false,
+          "intervalFactor": 2,
+          "legendFormat": "{{instance}}> {{operation}}",
+          "refId": "A"
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeShift": null,
+      "title": "Backend Operation Total",
+      "tooltip": {
+        "shared": true,
+        "sort": 0,
+        "value_type": "individual"
+      },
+      "transparent": false,
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "decimals": 0,
+          "format": "none",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        },
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": "${DS_LOCAL}",
+      "fill": 1,
+      "gridPos": {
+        "h": 6,
+        "w": 6,
+        "x": 18,
+        "y": 34
+      },
+      "height": "",
+      "id": 38,
+      "legend": {
+        "alignAsTable": false,
+        "avg": true,
+        "current": false,
+        "hideEmpty": true,
+        "hideZero": true,
+        "max": true,
+        "min": true,
+        "rightSide": true,
+        "show": false,
+        "sort": "avg",
+        "sortDesc": true,
+        "total": false,
+        "values": true
+      },
+      "lines": true,
+      "linewidth": 1,
+      "links": [],
+      "minSpan": 4,
+      "nullPointMode": "null",
+      "percentage": false,
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "expr": 
"max(avg_over_time(service_center_db_backend_operation_durations_microseconds{job=\"service-center\"}[1m]))
 by (instance,operation)",
+          "format": "time_series",
+          "intervalFactor": 1,
+          "legendFormat": "{{instance}}> {{operation}}",
+          "refId": "B"
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeShift": null,
+      "title": "Backend Operation Latency",
+      "tooltip": {
+        "shared": true,
+        "sort": 0,
+        "value_type": "individual"
+      },
+      "transparent": false,
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "µs",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        },
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "content": "<div class=\"text-center dashboard-header\">\n  
<span>RESOURCES</span>\n</div>\n",
+      "gridPos": {
+        "h": 3,
+        "w": 24,
+        "x": 0,
+        "y": 40
+      },
       "height": "1px",
       "id": 4,
       "links": [],
@@ -1826,7 +2402,7 @@
         "h": 7,
         "w": 8,
         "x": 0,
-        "y": 37
+        "y": 43
       },
       "height": "",
       "id": 2,
@@ -1915,7 +2491,7 @@
         "h": 7,
         "w": 8,
         "x": 8,
-        "y": 37
+        "y": 43
       },
       "height": "",
       "id": 9,
@@ -2002,7 +2578,7 @@
         "h": 7,
         "w": 8,
         "x": 16,
-        "y": 37
+        "y": 43
       },
       "height": "",
       "id": 8,
@@ -2089,7 +2665,7 @@
         "h": 7,
         "w": 8,
         "x": 0,
-        "y": 44
+        "y": 50
       },
       "id": 5,
       "legend": {
@@ -2174,7 +2750,7 @@
         "h": 7,
         "w": 8,
         "x": 8,
-        "y": 44
+        "y": 50
       },
       "id": 6,
       "legend": {
@@ -2259,7 +2835,7 @@
         "h": 7,
         "w": 8,
         "x": 16,
-        "y": 44
+        "y": 50
       },
       "id": 14,
       "legend": {
@@ -2344,7 +2920,7 @@
         "h": 7,
         "w": 24,
         "x": 0,
-        "y": 51
+        "y": 57
       },
       "id": 7,
       "legend": {
@@ -2437,7 +3013,7 @@
     "list": []
   },
   "time": {
-    "from": "now-5m",
+    "from": "now-15m",
     "to": "now"
   },
   "timepicker": {
@@ -2468,5 +3044,5 @@
   "timezone": "",
   "title": "ServiceCenter",
   "uid": "Zg6NoHGiz",
-  "version": 47
+  "version": 15
 }
\ No newline at end of file
diff --git a/pkg/etcdsync/mutex.go b/pkg/etcdsync/mutex.go
index 4f0c53b..94e7acd 100644
--- a/pkg/etcdsync/mutex.go
+++ b/pkg/etcdsync/mutex.go
@@ -34,6 +34,8 @@ const (
        DEFAULT_LOCK_TTL    = 60
        DEFAULT_RETRY_TIMES = 3
        ROOT_PATH           = "/cse/etcdsync"
+
+       OperationGlobalLock = "GLOBAL_LOCK"
 )
 
 type DLockFactory struct {
@@ -44,8 +46,9 @@ type DLockFactory struct {
 }
 
 type DLock struct {
-       builder *DLockFactory
-       id      string
+       builder  *DLockFactory
+       id       string
+       createAt time.Time
 }
 
 var (
@@ -77,9 +80,11 @@ func (m *DLockFactory) NewDLock(wait bool) (l *DLock, err 
error) {
        if !IsDebug {
                m.mutex.Lock()
        }
+       now := time.Now()
        l = &DLock{
-               builder: m,
-               id:      fmt.Sprintf("%v-%v-%v", hostname, pid, 
time.Now().Format("20060102-15:04:05.999999999")),
+               builder:  m,
+               id:       fmt.Sprintf("%v-%v-%v", hostname, pid, 
now.Format("20060102-15:04:05.999999999")),
+               createAt: now,
        }
        for try := 1; try <= DEFAULT_RETRY_TIMES; try++ {
                err = l.Lock(wait)
@@ -168,6 +173,7 @@ func (m *DLock) Unlock() (err error) {
                if !IsDebug {
                        m.builder.mutex.Unlock()
                }
+               registry.ReportBackendOperationCompleted(OperationGlobalLock, 
nil, m.createAt)
        }()
 
        opts := []registry.PluginOpOption{
diff --git a/pkg/notify/notice.go b/pkg/notify/notice.go
index 836d47b..87c0862 100644
--- a/pkg/notify/notice.go
+++ b/pkg/notify/notice.go
@@ -16,16 +16,20 @@
  */
 package notify
 
+import "time"
+
 type Event interface {
        Type() Type
        Subject() string // required!
        Group() string   // broadcast all the subscriber of the same subject if 
group is empty
+       CreateAt() time.Time
 }
 
 type baseEvent struct {
-       nType   Type
-       subject string
-       group   string
+       nType    Type
+       subject  string
+       group    string
+       createAt time.Time
 }
 
 func (s *baseEvent) Type() Type {
@@ -40,6 +44,10 @@ func (s *baseEvent) Group() string {
        return s.group
 }
 
+func (s *baseEvent) CreateAt() time.Time {
+       return s.createAt
+}
+
 func NewEvent(t Type, s string, g string) Event {
-       return &baseEvent{t, s, g}
+       return &baseEvent{t, s, g, time.Now()}
 }
diff --git a/pkg/notify/notification_test.go b/pkg/notify/notification_test.go
index f130c27..9b6a06c 100644
--- a/pkg/notify/notification_test.go
+++ b/pkg/notify/notification_test.go
@@ -59,7 +59,7 @@ func TestGetNotifyService(t *testing.T) {
        if err != nil {
                t.Fatalf("TestGetNotifyService failed, %v", err)
        }
-       j := &baseEvent{INSTANCE, "s", "g"}
+       j := &baseEvent{INSTANCE, "s", "g", time.Now()}
        err = notifyService.Publish(j)
        if err != nil {
                t.Fatalf("TestGetNotifyService failed")
diff --git a/server/core/backend/lease.go b/server/core/backend/lease.go
index 6d3eef9..5c6c2b3 100644
--- a/server/core/backend/lease.go
+++ b/server/core/backend/lease.go
@@ -44,6 +44,7 @@ func (lat *LeaseTask) Key() string {
 func (lat *LeaseTask) Do(ctx context.Context) (err error) {
        recv, start := lat.ReceiveTime(), time.Now()
        lat.TTL, err = lat.Client.LeaseRenew(ctx, lat.LeaseID)
+       ReportHeartbeatCompleted(err, recv)
        if err != nil {
                log.Errorf(err, "[%s]task[%s] renew lease[%d] failed(recv: %s, 
send: %s)",
                        time.Now().Sub(recv),
diff --git a/server/core/backend/metrics.go b/server/core/backend/metrics.go
index d20d21a..8150766 100644
--- a/server/core/backend/metrics.go
+++ b/server/core/backend/metrics.go
@@ -19,6 +19,12 @@ package backend
 import (
        "github.com/apache/servicecomb-service-center/server/metric"
        "github.com/prometheus/client_golang/prometheus"
+       "time"
+)
+
+const (
+       success = "SUCCESS"
+       failure = "FAILURE"
 )
 
 var (
@@ -29,13 +35,41 @@ var (
                        Name:      "sc_total",
                        Help:      "Counter of the Service Center instance",
                }, []string{"instance"})
+
+       heartbeatCounter = prometheus.NewCounterVec(
+               prometheus.CounterOpts{
+                       Namespace: metric.FamilyName,
+                       Subsystem: "db",
+                       Name:      "heartbeat_total",
+                       Help:      "Counter of heartbeat renew",
+               }, []string{"instance", "status"})
+
+       heartbeatLatency = prometheus.NewSummaryVec(
+               prometheus.SummaryOpts{
+                       Namespace:  metric.FamilyName,
+                       Subsystem:  "db",
+                       Name:       "heartbeat_durations_microseconds",
+                       Help:       "Latency of heartbeat renew",
+                       Objectives: prometheus.DefObjectives,
+               }, []string{"instance", "status"})
 )
 
 func init() {
-       prometheus.MustRegister(scCounter)
+       prometheus.MustRegister(scCounter, heartbeatCounter, heartbeatLatency)
 }
 
 func ReportScInstance() {
        instance := metric.InstanceName()
        scCounter.WithLabelValues(instance).Add(1)
 }
+
+func ReportHeartbeatCompleted(err error, start time.Time) {
+       instance := metric.InstanceName()
+       elapsed := float64(time.Since(start).Nanoseconds()) / 
float64(time.Microsecond)
+       status := success
+       if err != nil {
+               status = failure
+       }
+       heartbeatLatency.WithLabelValues(instance, status).Observe(elapsed)
+       heartbeatCounter.WithLabelValues(instance, status).Inc()
+}
diff --git a/server/notify/metrics.go b/server/notify/metrics.go
new file mode 100644
index 0000000..eac4c52
--- /dev/null
+++ b/server/notify/metrics.go
@@ -0,0 +1,61 @@
+// 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 notify
+
+import (
+       "github.com/apache/servicecomb-service-center/server/metric"
+       "github.com/prometheus/client_golang/prometheus"
+       "time"
+)
+
+const (
+       success = "SUCCESS"
+       failure = "FAILURE"
+)
+
+var (
+       notifyCounter = prometheus.NewCounterVec(
+               prometheus.CounterOpts{
+                       Namespace: metric.FamilyName,
+                       Subsystem: "notify",
+                       Name:      "publish_total",
+                       Help:      "Counter of publishing instance events",
+               }, []string{"instance", "source", "status"})
+
+       notifyLatency = prometheus.NewSummaryVec(
+               prometheus.SummaryOpts{
+                       Namespace:  metric.FamilyName,
+                       Subsystem:  "notify",
+                       Name:       "publish_durations_microseconds",
+                       Help:       "Latency of publishing instance events",
+                       Objectives: prometheus.DefObjectives,
+               }, []string{"instance", "source", "status"})
+)
+
+func init() {
+       prometheus.MustRegister(notifyCounter, notifyLatency)
+}
+
+func ReportPublishCompleted(source string, err error, start time.Time) {
+       instance := metric.InstanceName()
+       elapsed := float64(time.Since(start).Nanoseconds()) / 
float64(time.Microsecond)
+       status := success
+       if err != nil {
+               status = failure
+       }
+       notifyLatency.WithLabelValues(instance, source, status).Observe(elapsed)
+       notifyCounter.WithLabelValues(instance, source, status).Inc()
+}
diff --git a/server/notify/stream.go b/server/notify/stream.go
index 0bc17cd..0e4e2d7 100644
--- a/server/notify/stream.go
+++ b/server/notify/stream.go
@@ -49,6 +49,7 @@ func HandleWatchJob(watcher *InstanceEventListWatcher, stream 
pb.ServiceInstance
                                watcher.Subject(), watcher.Group())
 
                        err = stream.Send(resp)
+                       ReportPublishCompleted(INSTANCE.String(), err, 
job.CreateAt())
                        if err != nil {
                                log.Errorf(err, "send message error, subject: 
%s, group: %s",
                                        watcher.Subject(), watcher.Group())
diff --git a/server/notify/websocket.go b/server/notify/websocket.go
index 64f6203..2f0a6d8 100644
--- a/server/notify/websocket.go
+++ b/server/notify/websocket.go
@@ -169,8 +169,11 @@ func (wh *WebSocket) Pick() interface{} {
 func (wh *WebSocket) HandleWatchWebSocketJob(o interface{}) {
        defer wh.SetReady()
 
-       remoteAddr := wh.conn.RemoteAddr().String()
-       var message []byte
+       var (
+               job        *InstanceEvent
+               message    []byte
+               remoteAddr = wh.conn.RemoteAddr().String()
+       )
 
        switch o.(type) {
        case error:
@@ -195,7 +198,7 @@ func (wh *WebSocket) HandleWatchWebSocketJob(o interface{}) 
{
                wh.heartbeat(websocket.PingMessage)
                return
        case *InstanceEvent:
-               job := o.(*InstanceEvent)
+               job = o.(*InstanceEvent)
                resp := job.Response
 
                providerFlag := fmt.Sprintf("%s/%s/%s", resp.Key.AppId, 
resp.Key.ServiceName, resp.Key.Version)
@@ -227,6 +230,9 @@ func (wh *WebSocket) HandleWatchWebSocketJob(o interface{}) 
{
        }
 
        err := wh.conn.WriteMessage(websocket.TextMessage, message)
+       if job != nil {
+               ReportPublishCompleted(INSTANCE.String(), err, job.CreateAt())
+       }
        if err != nil {
                log.Errorf(err, "watcher[%s] catch an err, subject: %s, group: 
%s",
                        remoteAddr, wh.watcher.Subject(), wh.watcher.Group())
diff --git a/server/plugin/pkg/discovery/etcd/cacher_kv.go 
b/server/plugin/pkg/discovery/etcd/cacher_kv.go
index 6ea25d8..aa82b42 100644
--- a/server/plugin/pkg/discovery/etcd/cacher_kv.go
+++ b/server/plugin/pkg/discovery/etcd/cacher_kv.go
@@ -367,6 +367,7 @@ func (c *KvCacher) deferHandle(ctx context.Context) {
 }
 
 func (c *KvCacher) onEvents(evts []discovery.KvEvent) {
+       start := time.Now()
        init := !c.IsReady()
        for i, evt := range evts {
                key := util.BytesToStringWithNoCopy(evt.KV.Key)
@@ -403,6 +404,8 @@ func (c *KvCacher) onEvents(evts []discovery.KvEvent) {
        }
 
        c.notify(evts)
+
+       discovery.ReportProcessEventCompleted(evts, start)
 }
 
 func (c *KvCacher) notify(evts []discovery.KvEvent) {
diff --git a/server/plugin/pkg/registry/etcd/metrics.go 
b/server/plugin/pkg/discovery/metrics.go
similarity index 55%
copy from server/plugin/pkg/registry/etcd/metrics.go
copy to server/plugin/pkg/discovery/metrics.go
index 90c8fdd..4e3737b 100644
--- a/server/plugin/pkg/registry/etcd/metrics.go
+++ b/server/plugin/pkg/discovery/metrics.go
@@ -14,28 +14,49 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package etcd
+package discovery
 
 import (
        "github.com/apache/servicecomb-service-center/server/metric"
        "github.com/prometheus/client_golang/prometheus"
+       "time"
+)
+
+const (
+       success = "SUCCESS"
+       failure = "FAILURE"
 )
 
 var (
-       backendCounter = prometheus.NewGaugeVec(
+       eventsCounter = prometheus.NewGaugeVec(
                prometheus.GaugeOpts{
                        Namespace: metric.FamilyName,
                        Subsystem: "db",
-                       Name:      "backend_total",
-                       Help:      "Gauge of the backend instance",
+                       Name:      "backend_event_total",
+                       Help:      "Counter of backend events",
+               }, []string{"instance"})
+
+       eventsLatency = prometheus.NewSummaryVec(
+               prometheus.SummaryOpts{
+                       Namespace:  metric.FamilyName,
+                       Subsystem:  "db",
+                       Name:       "backend_event_durations_microseconds",
+                       Help:       "Latency of backend events processing",
+                       Objectives: prometheus.DefObjectives,
                }, []string{"instance"})
 )
 
 func init() {
-       prometheus.MustRegister(backendCounter)
+       prometheus.MustRegister(eventsCounter, eventsLatency)
 }
 
-func ReportBackendInstance(c int) {
+func ReportProcessEventCompleted(evts []KvEvent, start time.Time) {
+       l := float64(len(evts))
+       if l == 0 {
+               return
+       }
        instance := metric.InstanceName()
-       backendCounter.WithLabelValues(instance).Set(float64(c))
+       elapsed := float64(time.Since(start).Nanoseconds()) / 
float64(time.Microsecond)
+       eventsLatency.WithLabelValues(instance).Observe(elapsed / l)
+       eventsCounter.WithLabelValues(instance).Add(l)
 }
diff --git a/server/plugin/pkg/registry/etcd/common.go 
b/server/plugin/pkg/registry/etcd/common.go
new file mode 100644
index 0000000..d8d9832
--- /dev/null
+++ b/server/plugin/pkg/registry/etcd/common.go
@@ -0,0 +1,34 @@
+// 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 etcd
+
+import "time"
+
+const (
+       // here will new an etcd connection after about 30s(=5s * 3 + 
(backoff:8s))
+       // when the connected etcd member was hung but tcp is still alive
+       healthCheckTimeout    = 5 * time.Second
+       healthCheckRetryTimes = 3
+)
+
+const (
+       OperationCompact     = "COMPACT"
+       OperationTxn         = "TXN"
+       OperationLeaseGrant  = "LEASE_GRANT"
+       OperationLeaseRenew  = "LEASE_RENEW"
+       OperationLeaseRevoke = "LEASE_REVOKE"
+       OperationSyncMembers = "SYNC"
+)
diff --git a/server/plugin/pkg/registry/etcd/etcd.go 
b/server/plugin/pkg/registry/etcd/etcd.go
index 5dc3e5c..9aca3be 100644
--- a/server/plugin/pkg/registry/etcd/etcd.go
+++ b/server/plugin/pkg/registry/etcd/etcd.go
@@ -39,13 +39,6 @@ import (
        "time"
 )
 
-const (
-       // here will new an etcd connection after about 30s(=5s * 3 + 
(backoff:8s))
-       // when the connected etcd member was hung but tcp is still alive
-       healthCheckTimeout    = 5 * time.Second
-       healthCheckRetryTimes = 3
-)
-
 var firstEndpoint string
 
 func init() {
@@ -133,7 +126,7 @@ func (c *EtcdClient) newClient() (*clientv3.Client, error) {
                return nil, err
        }
 
-       ReportBackendInstance(len(resp.Members))
+       registry.ReportBackendInstance(len(resp.Members))
 
        if len(c.Endpoints) == 1 {
                // no need to check remote endpoints
@@ -192,6 +185,7 @@ func (c *EtcdClient) Compact(ctx context.Context, reserve 
int64) error {
 
        t := time.Now()
        _, err := c.Client.Compact(ctx, revToCompact, 
clientv3.WithCompactPhysical())
+       registry.ReportBackendOperationCompleted(OperationCompact, err, t)
        if err != nil {
                log.Errorf(err, "compact %s failed, revision is %d(current: %d, 
reserve %d)",
                        eps, revToCompact, curRev, reserve)
@@ -460,12 +454,13 @@ func (c *EtcdClient) Do(ctx context.Context, opts 
...registry.PluginOpOption) (*
 
        start := time.Now()
        op := registry.OptionsToOp(opts...)
-
        span := TracingBegin(ctx, "etcd:do", op)
-       defer TracingEnd(span, err)
-
        otCtx, cancel := registry.WithTimeout(ctx)
-       defer cancel()
+       defer func() {
+               registry.ReportBackendOperationCompleted(op.Action.String(), 
err, start)
+               TracingEnd(span, err)
+               cancel()
+       }()
 
        switch op.Action {
        case registry.Get:
@@ -539,9 +534,6 @@ func (c *EtcdClient) Txn(ctx context.Context, opts 
[]registry.PluginOp) (*regist
 func (c *EtcdClient) TxnWithCmp(ctx context.Context, success 
[]registry.PluginOp, cmps []registry.CompareOp, fail []registry.PluginOp) 
(*registry.PluginResponse, error) {
        var err error
 
-       otCtx, cancel := registry.WithTimeout(ctx)
-       defer cancel()
-
        start := time.Now()
        etcdCmps := c.toCompares(cmps)
        etcdSuccessOps := c.toTxnRequest(success)
@@ -555,7 +547,12 @@ func (c *EtcdClient) TxnWithCmp(ctx context.Context, 
success []registry.PluginOp
        }
 
        span := TracingBegin(ctx, "etcd:txn", traceOps[0])
-       defer TracingEnd(span, err)
+       otCtx, cancel := registry.WithTimeout(ctx)
+       defer func() {
+               registry.ReportBackendOperationCompleted(OperationTxn, err, 
start)
+               TracingEnd(span, err)
+               cancel()
+       }()
 
        kvc := clientv3.NewKV(c.Client)
        txn := kvc.Txn(otCtx)
@@ -592,13 +589,16 @@ func (c *EtcdClient) TxnWithCmp(ctx context.Context, 
success []registry.PluginOp
 
 func (c *EtcdClient) LeaseGrant(ctx context.Context, TTL int64) (int64, error) 
{
        var err error
+
+       start := time.Now()
        span := TracingBegin(ctx, "etcd:grant",
                registry.PluginOp{Action: registry.Put, Key: 
util.StringToBytesWithNoCopy(strconv.FormatInt(TTL, 10))})
-       defer TracingEnd(span, err)
-
        otCtx, cancel := registry.WithTimeout(ctx)
-       defer cancel()
-       start := time.Now()
+       defer func() {
+               registry.ReportBackendOperationCompleted(OperationLeaseGrant, 
err, start)
+               TracingEnd(span, err)
+               cancel()
+       }()
        etcdResp, err := c.Client.Grant(otCtx, TTL)
        if err != nil {
                return 0, err
@@ -609,13 +609,17 @@ func (c *EtcdClient) LeaseGrant(ctx context.Context, TTL 
int64) (int64, error) {
 
 func (c *EtcdClient) LeaseRenew(ctx context.Context, leaseID int64) (int64, 
error) {
        var err error
+
+       start := time.Now()
        span := TracingBegin(ctx, "etcd:keepalive",
                registry.PluginOp{Action: registry.Put, Key: 
util.StringToBytesWithNoCopy(strconv.FormatInt(leaseID, 10))})
-       defer TracingEnd(span, err)
-
        otCtx, cancel := registry.WithTimeout(ctx)
-       defer cancel()
-       start := time.Now()
+       defer func() {
+               registry.ReportBackendOperationCompleted(OperationLeaseRenew, 
err, start)
+               TracingEnd(span, err)
+               cancel()
+       }()
+
        etcdResp, err := c.Client.KeepAliveOnce(otCtx, 
clientv3.LeaseID(leaseID))
        if err != nil {
                if err.Error() == grpc.ErrorDesc(rpctypes.ErrGRPCLeaseNotFound) 
{
@@ -629,13 +633,17 @@ func (c *EtcdClient) LeaseRenew(ctx context.Context, 
leaseID int64) (int64, erro
 
 func (c *EtcdClient) LeaseRevoke(ctx context.Context, leaseID int64) error {
        var err error
+
+       start := time.Now()
        span := TracingBegin(ctx, "etcd:revoke",
                registry.PluginOp{Action: registry.Delete, Key: 
util.StringToBytesWithNoCopy(strconv.FormatInt(leaseID, 10))})
-       defer TracingEnd(span, err)
-
        otCtx, cancel := registry.WithTimeout(ctx)
-       defer cancel()
-       start := time.Now()
+       defer func() {
+               registry.ReportBackendOperationCompleted(OperationLeaseRevoke, 
err, start)
+               TracingEnd(span, err)
+               cancel()
+       }()
+
        _, err = c.Client.Revoke(otCtx, clientv3.LeaseID(leaseID))
        if err != nil {
                if err.Error() == grpc.ErrorDesc(rpctypes.ErrGRPCLeaseNotFound) 
{
@@ -767,7 +775,12 @@ func (c *EtcdClient) parseEndpoints() {
 }
 
 func (c *EtcdClient) SyncMembers(ctx context.Context) error {
-       if err := c.Client.Sync(ctx); err != nil && err != c.Client.Ctx().Err() 
{
+       var err error
+
+       start := time.Now()
+       defer registry.ReportBackendOperationCompleted(OperationSyncMembers, 
err, start)
+
+       if err = c.Client.Sync(ctx); err != nil && err != c.Client.Ctx().Err() {
                return err
        }
        return nil
diff --git a/server/plugin/pkg/registry/etcd/metrics.go 
b/server/plugin/pkg/registry/metrics.go
similarity index 53%
rename from server/plugin/pkg/registry/etcd/metrics.go
rename to server/plugin/pkg/registry/metrics.go
index 90c8fdd..d0fa6fc 100644
--- a/server/plugin/pkg/registry/etcd/metrics.go
+++ b/server/plugin/pkg/registry/metrics.go
@@ -14,11 +14,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package etcd
+package registry
 
 import (
        "github.com/apache/servicecomb-service-center/server/metric"
        "github.com/prometheus/client_golang/prometheus"
+       "time"
+)
+
+const (
+       success = "SUCCESS"
+       failure = "FAILURE"
 )
 
 var (
@@ -29,13 +35,41 @@ var (
                        Name:      "backend_total",
                        Help:      "Gauge of the backend instance",
                }, []string{"instance"})
+
+       operationCounter = prometheus.NewCounterVec(
+               prometheus.CounterOpts{
+                       Namespace: metric.FamilyName,
+                       Subsystem: "db",
+                       Name:      "backend_operation_total",
+                       Help:      "Counter of backend operation",
+               }, []string{"instance", "operation", "status"})
+
+       operationLatency = prometheus.NewSummaryVec(
+               prometheus.SummaryOpts{
+                       Namespace:  metric.FamilyName,
+                       Subsystem:  "db",
+                       Name:       "backend_operation_durations_microseconds",
+                       Help:       "Latency of backend operation",
+                       Objectives: prometheus.DefObjectives,
+               }, []string{"instance", "operation", "status"})
 )
 
 func init() {
-       prometheus.MustRegister(backendCounter)
+       prometheus.MustRegister(backendCounter, operationCounter, 
operationLatency)
 }
 
 func ReportBackendInstance(c int) {
        instance := metric.InstanceName()
        backendCounter.WithLabelValues(instance).Set(float64(c))
 }
+
+func ReportBackendOperationCompleted(operation string, err error, start 
time.Time) {
+       instance := metric.InstanceName()
+       elapsed := float64(time.Since(start).Nanoseconds()) / 
float64(time.Microsecond)
+       status := success
+       if err != nil {
+               status = failure
+       }
+       operationLatency.WithLabelValues(instance, operation, 
status).Observe(elapsed)
+       operationCounter.WithLabelValues(instance, operation, status).Inc()
+}
diff --git a/server/service/event/event.go b/server/service/event/event.go
index 1472c4a..9399105 100644
--- a/server/service/event/event.go
+++ b/server/service/event/event.go
@@ -28,4 +28,5 @@ func init() {
        discovery.AddEventHandler(NewTagEventHandler())
        discovery.AddEventHandler(NewDependencyEventHandler())
        discovery.AddEventHandler(NewDependencyRuleEventHandler())
+       discovery.AddEventHandler(NewSchemaSummaryEventHandler())
 }
diff --git a/server/service/event/schema_summary_event_handler.go 
b/server/service/event/schema_summary_event_handler.go
new file mode 100644
index 0000000..79d85f1
--- /dev/null
+++ b/server/service/event/schema_summary_event_handler.go
@@ -0,0 +1,53 @@
+/*
+ * 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 event
+
+import (
+       "github.com/apache/servicecomb-service-center/server/core"
+       "github.com/apache/servicecomb-service-center/server/core/backend"
+       pb "github.com/apache/servicecomb-service-center/server/core/proto"
+       
"github.com/apache/servicecomb-service-center/server/plugin/pkg/discovery"
+       "github.com/apache/servicecomb-service-center/server/service/metrics"
+       "strings"
+)
+
+type SchemaSummaryEventHandler struct {
+}
+
+func (h *SchemaSummaryEventHandler) Type() discovery.Type {
+       return backend.SCHEMA_SUMMARY
+}
+
+func (h *SchemaSummaryEventHandler) OnEvent(evt discovery.KvEvent) {
+       action := evt.Type
+       switch action {
+       case pb.EVT_INIT, pb.EVT_CREATE, pb.EVT_DELETE:
+               domainProject, _, _ := 
core.GetInfoFromSchemaSummaryKV(evt.KV.Key)
+               idx := strings.Index(domainProject, "/")
+               newDomain := domainProject[:idx]
+               if pb.EVT_DELETE == action {
+                       metrics.ReportSchemas(newDomain, -1)
+               } else {
+                       metrics.ReportSchemas(newDomain, 1)
+               }
+       default:
+       }
+}
+
+func NewSchemaSummaryEventHandler() *SchemaSummaryEventHandler {
+       return &SchemaSummaryEventHandler{}
+}
diff --git a/server/service/metrics/metrics.go 
b/server/service/metrics/metrics.go
index 05c366e..35399dd 100644
--- a/server/service/metrics/metrics.go
+++ b/server/service/metrics/metrics.go
@@ -45,10 +45,18 @@ var (
                        Name:      "instance_total",
                        Help:      "Gauge of microservice created in Service 
Center",
                }, []string{"instance", "domain"})
+
+       schemaCounter = prometheus.NewGaugeVec(
+               prometheus.GaugeOpts{
+                       Namespace: metric.FamilyName,
+                       Subsystem: "db",
+                       Name:      "schema_total",
+                       Help:      "Gauge of schema created in Service Center",
+               }, []string{"instance", "domain"})
 )
 
 func init() {
-       prometheus.MustRegister(domainCounter, serviceCounter, instanceCounter)
+       prometheus.MustRegister(domainCounter, serviceCounter, instanceCounter, 
schemaCounter)
 }
 
 func ReportDomains(c float64) {
@@ -65,3 +73,8 @@ func ReportInstances(domain string, c float64) {
        instance := metric.InstanceName()
        instanceCounter.WithLabelValues(instance, domain).Add(c)
 }
+
+func ReportSchemas(domain string, c float64) {
+       instance := metric.InstanceName()
+       schemaCounter.WithLabelValues(instance, domain).Add(c)
+}

Reply via email to