You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by li...@apache.org on 2018/12/28 03:19:45 UTC

[servicecomb-service-center] branch master updated: SCB-1092 More abundant metrics information (#519)

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 <su...@qq.com>
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)
+}