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 2022/01/11 09:29:51 UTC

[servicecomb-service-center] 01/01: Feature: add resource usage service

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

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

commit 7af98936f9b29c86683d69b80feee1b39be996f3
Author: little-cui <su...@qq.com>
AuthorDate: Tue Jan 11 14:23:18 2022 +0800

    Feature: add resource usage service
---
 server/plugin/quota/buildin/account.go       | 32 -----------
 server/plugin/quota/buildin/buildin.go       | 12 ++--
 server/plugin/quota/buildin/instance.go      | 33 -----------
 server/plugin/quota/buildin/instance_test.go | 66 ----------------------
 server/plugin/quota/buildin/role.go          | 32 -----------
 server/plugin/quota/buildin/schema.go        | 36 ------------
 server/plugin/quota/buildin/schema_test.go   | 71 ------------------------
 server/plugin/quota/buildin/service.go       | 33 -----------
 server/plugin/quota/buildin/service_test.go  | 60 --------------------
 server/service/disco/instance.go             |  8 +++
 server/service/disco/instance_test.go        | 61 +++++++++++++++-----
 server/service/disco/metadata.go             |  8 +++
 server/service/disco/metadata_test.go        | 83 +++++++++++++++++++---------
 server/service/disco/schema.go               | 11 ++++
 server/service/disco/schema_test.go          | 55 +++++++++++++++---
 server/service/disco/tag_test.go             |  2 +-
 server/service/quota/service_test.go         |  3 +-
 server/service/rbac/account_service.go       |  8 +++
 server/service/rbac/role_service.go          |  8 +++
 19 files changed, 205 insertions(+), 417 deletions(-)

diff --git a/server/plugin/quota/buildin/account.go b/server/plugin/quota/buildin/account.go
deleted file mode 100644
index a5ec0af..0000000
--- a/server/plugin/quota/buildin/account.go
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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 buildin
-
-import (
-	"context"
-
-	"github.com/apache/servicecomb-service-center/datasource/rbac"
-)
-
-func AccountUsage(ctx context.Context) (int64, error) {
-	_, used, err := rbac.Instance().ListAccount(ctx)
-	if err != nil {
-		return 0, err
-	}
-	return used, nil
-}
diff --git a/server/plugin/quota/buildin/buildin.go b/server/plugin/quota/buildin/buildin.go
index 5068687..aab18cf 100644
--- a/server/plugin/quota/buildin/buildin.go
+++ b/server/plugin/quota/buildin/buildin.go
@@ -26,7 +26,9 @@ import (
 	"github.com/apache/servicecomb-service-center/pkg/util"
 	"github.com/apache/servicecomb-service-center/server/config"
 	"github.com/apache/servicecomb-service-center/server/plugin/quota"
+	"github.com/apache/servicecomb-service-center/server/service/disco"
 	quotasvc "github.com/apache/servicecomb-service-center/server/service/quota"
+	"github.com/apache/servicecomb-service-center/server/service/rbac"
 	pb "github.com/go-chassis/cari/discovery"
 )
 
@@ -99,24 +101,24 @@ func (q *Quota) RemandQuotas(ctx context.Context, resourceType quota.ResourceTyp
 func (q *Quota) Usage(ctx context.Context, req *quota.Request) (int64, error) {
 	switch req.QuotaType {
 	case quotasvc.TypeInstance:
-		return InstanceUsage(ctx, &pb.GetServiceCountRequest{
+		return disco.InstanceUsage(ctx, &pb.GetServiceCountRequest{
 			Domain:  util.ParseDomain(ctx),
 			Project: util.ParseProject(ctx),
 		})
 	case quotasvc.TypeService:
-		return ServiceUsage(ctx, &pb.GetServiceCountRequest{
+		return disco.ServiceUsage(ctx, &pb.GetServiceCountRequest{
 			Domain:  util.ParseDomain(ctx),
 			Project: util.ParseProject(ctx),
 		})
 	case quotasvc.TypeSchema:
-		return SchemaUsage(ctx, req.ServiceID)
+		return disco.Usage(ctx, req.ServiceID)
 	case quotasvc.TypeTag:
 		// always re-create the service old tags
 		return 0, nil
 	case quotasvc.TypeAccount:
-		return AccountUsage(ctx)
+		return rbac.AccountUsage(ctx)
 	case quotasvc.TypeRole:
-		return RoleUsage(ctx)
+		return rbac.RoleUsage(ctx)
 	default:
 		return 0, nil
 	}
diff --git a/server/plugin/quota/buildin/instance.go b/server/plugin/quota/buildin/instance.go
deleted file mode 100644
index 5b485ba..0000000
--- a/server/plugin/quota/buildin/instance.go
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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 buildin
-
-import (
-	"context"
-
-	"github.com/apache/servicecomb-service-center/datasource"
-	pb "github.com/go-chassis/cari/discovery"
-)
-
-func InstanceUsage(ctx context.Context, request *pb.GetServiceCountRequest) (int64, error) {
-	resp, err := datasource.GetMetadataManager().CountInstance(ctx, request)
-	if err != nil {
-		return 0, err
-	}
-	return resp.Count, nil
-}
diff --git a/server/plugin/quota/buildin/instance_test.go b/server/plugin/quota/buildin/instance_test.go
deleted file mode 100644
index 6352c59..0000000
--- a/server/plugin/quota/buildin/instance_test.go
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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 buildin_test
-
-import (
-	"context"
-	"testing"
-
-	_ "github.com/apache/servicecomb-service-center/test"
-
-	"github.com/apache/servicecomb-service-center/pkg/util"
-	"github.com/apache/servicecomb-service-center/server/plugin/quota/buildin"
-	"github.com/apache/servicecomb-service-center/server/service/disco"
-	pb "github.com/go-chassis/cari/discovery"
-	"github.com/stretchr/testify/assert"
-)
-
-func TestInstanceUsage(t *testing.T) {
-	t.Run("get domain/project without instance usage, should return 0", func(t *testing.T) {
-		usage, err := buildin.InstanceUsage(context.Background(), &pb.GetServiceCountRequest{
-			Domain:  "domain_without_service",
-			Project: "project_without_service",
-		})
-		assert.NoError(t, err)
-		assert.Equal(t, int64(0), usage)
-	})
-
-	t.Run("get domain/project with 1 instance usage, should return 1", func(t *testing.T) {
-		ctx := util.SetDomainProject(context.Background(), "domain_with_service", "project_with_service")
-		resp, err := disco.RegisterService(ctx, &pb.CreateServiceRequest{
-			Service: &pb.MicroService{
-				ServiceName: "test",
-			},
-		})
-		assert.NoError(t, err)
-		defer disco.UnregisterService(ctx, &pb.DeleteServiceRequest{ServiceId: resp.ServiceId, Force: true})
-
-		_, err = disco.RegisterInstance(ctx, &pb.RegisterInstanceRequest{Instance: &pb.MicroServiceInstance{
-			ServiceId: resp.ServiceId,
-			HostName:  "test",
-		}})
-		assert.NoError(t, err)
-
-		usage, err := buildin.InstanceUsage(context.Background(), &pb.GetServiceCountRequest{
-			Domain:  "domain_with_service",
-			Project: "project_with_service",
-		})
-		assert.NoError(t, err)
-		assert.Equal(t, int64(1), usage)
-	})
-}
diff --git a/server/plugin/quota/buildin/role.go b/server/plugin/quota/buildin/role.go
deleted file mode 100644
index c7cb44f..0000000
--- a/server/plugin/quota/buildin/role.go
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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 buildin
-
-import (
-	"context"
-
-	"github.com/apache/servicecomb-service-center/datasource/rbac"
-)
-
-func RoleUsage(ctx context.Context) (int64, error) {
-	_, used, err := rbac.Instance().ListRole(ctx)
-	if err != nil {
-		return 0, err
-	}
-	return used, nil
-}
diff --git a/server/plugin/quota/buildin/schema.go b/server/plugin/quota/buildin/schema.go
deleted file mode 100644
index 418c316..0000000
--- a/server/plugin/quota/buildin/schema.go
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * 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 buildin
-
-import (
-	"context"
-
-	discosvc "github.com/apache/servicecomb-service-center/server/service/disco"
-	"github.com/go-chassis/cari/discovery"
-)
-
-func SchemaUsage(ctx context.Context, serviceID string) (int64, error) {
-	schemas, err := discosvc.ListSchema(ctx, &discovery.GetAllSchemaRequest{
-		ServiceId:  serviceID,
-		WithSchema: false,
-	})
-	if err != nil {
-		return 0, err
-	}
-	return int64(len(schemas)), nil
-}
diff --git a/server/plugin/quota/buildin/schema_test.go b/server/plugin/quota/buildin/schema_test.go
deleted file mode 100644
index b1dba0a..0000000
--- a/server/plugin/quota/buildin/schema_test.go
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * 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 buildin_test
-
-import (
-	"context"
-	"testing"
-
-	_ "github.com/apache/servicecomb-service-center/test"
-	"github.com/go-chassis/cari/pkg/errsvc"
-
-	"github.com/apache/servicecomb-service-center/pkg/util"
-	"github.com/apache/servicecomb-service-center/server/plugin/quota/buildin"
-	"github.com/apache/servicecomb-service-center/server/service/disco"
-	pb "github.com/go-chassis/cari/discovery"
-	"github.com/stretchr/testify/assert"
-)
-
-func TestSchemaUsage(t *testing.T) {
-	ctx := util.WithNoCache(util.SetDomainProject(context.Background(), "default", "default"))
-
-	resp, err := disco.RegisterService(ctx, &pb.CreateServiceRequest{
-		Service: &pb.MicroService{
-			ServiceName: "TestSchemaUsage",
-		},
-	})
-	assert.NoError(t, err)
-	serviceID := resp.ServiceId
-	defer disco.UnregisterService(ctx, &pb.DeleteServiceRequest{ServiceId: serviceID, Force: true})
-
-	t.Run("get not exist service schema usage, should failed", func(t *testing.T) {
-		_, err := buildin.SchemaUsage(ctx, "note_exist_service_id")
-		testErr := err.(*errsvc.Error)
-		assert.Error(t, testErr)
-		assert.Equal(t, pb.ErrServiceNotExists, testErr.Code)
-	})
-
-	t.Run("get usage without schemas, should return 0", func(t *testing.T) {
-		usage, err := buildin.SchemaUsage(ctx, serviceID)
-		assert.NoError(t, err)
-		assert.Equal(t, int64(0), usage)
-	})
-
-	t.Run("get usage with schemas, should return 1", func(t *testing.T) {
-		err := disco.PutSchema(ctx, &pb.ModifySchemaRequest{
-			ServiceId: serviceID,
-			SchemaId:  "schemaID_1",
-			Schema:    "schema_1",
-		})
-		assert.NoError(t, err)
-
-		usage, err := buildin.SchemaUsage(ctx, serviceID)
-		assert.NoError(t, err)
-		assert.Equal(t, int64(1), usage)
-	})
-}
diff --git a/server/plugin/quota/buildin/service.go b/server/plugin/quota/buildin/service.go
deleted file mode 100644
index a243889..0000000
--- a/server/plugin/quota/buildin/service.go
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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 buildin
-
-import (
-	"context"
-
-	"github.com/apache/servicecomb-service-center/datasource"
-	pb "github.com/go-chassis/cari/discovery"
-)
-
-func ServiceUsage(ctx context.Context, request *pb.GetServiceCountRequest) (int64, error) {
-	resp, err := datasource.GetMetadataManager().CountService(ctx, request)
-	if err != nil {
-		return 0, err
-	}
-	return resp.Count, nil
-}
diff --git a/server/plugin/quota/buildin/service_test.go b/server/plugin/quota/buildin/service_test.go
deleted file mode 100644
index 11ffa66..0000000
--- a/server/plugin/quota/buildin/service_test.go
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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 buildin_test
-
-import (
-	"context"
-	"testing"
-
-	_ "github.com/apache/servicecomb-service-center/test"
-
-	"github.com/apache/servicecomb-service-center/pkg/util"
-	"github.com/apache/servicecomb-service-center/server/plugin/quota/buildin"
-	"github.com/apache/servicecomb-service-center/server/service/disco"
-	pb "github.com/go-chassis/cari/discovery"
-	"github.com/stretchr/testify/assert"
-)
-
-func TestServiceUsage(t *testing.T) {
-	t.Run("get domain/project without service usage, should return 0", func(t *testing.T) {
-		usage, err := buildin.ServiceUsage(context.Background(), &pb.GetServiceCountRequest{
-			Domain:  "domain_without_service",
-			Project: "project_without_service",
-		})
-		assert.NoError(t, err)
-		assert.Equal(t, int64(0), usage)
-	})
-
-	t.Run("get domain/project with 1 service usage, should return 1", func(t *testing.T) {
-		ctx := util.SetDomainProject(context.Background(), "domain_with_service", "project_with_service")
-		resp, err := disco.RegisterService(ctx, &pb.CreateServiceRequest{
-			Service: &pb.MicroService{
-				ServiceName: "test",
-			},
-		})
-		assert.NoError(t, err)
-		defer disco.UnregisterService(ctx, &pb.DeleteServiceRequest{ServiceId: resp.ServiceId, Force: true})
-
-		usage, err := buildin.ServiceUsage(context.Background(), &pb.GetServiceCountRequest{
-			Domain:  "domain_with_service",
-			Project: "project_with_service",
-		})
-		assert.NoError(t, err)
-		assert.Equal(t, int64(1), usage)
-	})
-}
diff --git a/server/service/disco/instance.go b/server/service/disco/instance.go
index 95689b8..b2fa07d 100644
--- a/server/service/disco/instance.go
+++ b/server/service/disco/instance.go
@@ -377,3 +377,11 @@ func checkInstanceQuota(ctx context.Context) error {
 	}
 	return nil
 }
+
+func InstanceUsage(ctx context.Context, request *pb.GetServiceCountRequest) (int64, error) {
+	resp, err := datasource.GetMetadataManager().CountInstance(ctx, request)
+	if err != nil {
+		return 0, err
+	}
+	return resp.Count, nil
+}
diff --git a/server/service/disco/instance_test.go b/server/service/disco/instance_test.go
index ad89a02..0c22de1 100644
--- a/server/service/disco/instance_test.go
+++ b/server/service/disco/instance_test.go
@@ -121,9 +121,9 @@ func TestRegisterInstance(t *testing.T) {
 					Url:      TOO_LONG_URL[:len(TOO_LONG_URL)-1],
 				},
 				DataCenterInfo: &pb.DataCenterInfo{
-					Name:          TOO_LONG_SERVICENAME[:len(TOO_LONG_SERVICENAME)-1],
-					Region:        TOO_LONG_SERVICENAME[:len(TOO_LONG_SERVICENAME)-1],
-					AvailableZone: TOO_LONG_SERVICENAME[:len(TOO_LONG_SERVICENAME)-1],
+					Name:          TooLongServiceName[:len(TooLongServiceName)-1],
+					Region:        TooLongServiceName[:len(TooLongServiceName)-1],
+					AvailableZone: TooLongServiceName[:len(TooLongServiceName)-1],
 				},
 			},
 		})
@@ -674,7 +674,7 @@ func TestFindManyInstances(t *testing.T) {
 			Services: []*pb.FindService{
 				{
 					Service: &pb.MicroServiceKey{
-						AppId:       TOO_LONG_APPID,
+						AppId:       TooLongAppID,
 						ServiceName: "query_instance_service",
 					},
 				},
@@ -720,7 +720,7 @@ func TestFindManyInstances(t *testing.T) {
 				{
 					Service: &pb.MicroServiceKey{
 						AppId:       "query_instance",
-						ServiceName: TOO_LONG_EXISTENCE,
+						ServiceName: TooLongExistence,
 					},
 				},
 			},
@@ -1345,7 +1345,7 @@ func TestFindInstances(t *testing.T) {
 	t.Run("when query invalid parameters, should be failed", func(t *testing.T) {
 		_, err := discosvc.FindInstances(ctx, &pb.FindInstancesRequest{
 			ConsumerServiceId: serviceId1,
-			AppId:             TOO_LONG_APPID,
+			AppId:             TooLongAppID,
 			ServiceName:       "query_instance_service",
 		})
 		testErr := err.(*errsvc.Error)
@@ -1373,7 +1373,7 @@ func TestFindInstances(t *testing.T) {
 		_, err = discosvc.FindInstances(ctx, &pb.FindInstancesRequest{
 			ConsumerServiceId: serviceId1,
 			AppId:             "query_instance",
-			ServiceName:       TOO_LONG_EXISTENCE,
+			ServiceName:       TooLongExistence,
 		})
 		testErr = err.(*errsvc.Error)
 		assert.Error(t, testErr)
@@ -1740,7 +1740,7 @@ func TestUnregisterInstance(t *testing.T) {
 		assert.Equal(t, pb.ErrInvalidParams, testErr.Code)
 
 		err = discosvc.UnregisterInstance(ctx, &pb.UnregisterInstanceRequest{
-			ServiceId:  TOO_LONG_SERVICEID,
+			ServiceId:  TooLongServiceID,
 			InstanceId: instanceId,
 		})
 		testErr = err.(*errsvc.Error)
@@ -1773,7 +1773,7 @@ func TestUnregisterInstance(t *testing.T) {
 
 		err = discosvc.UnregisterInstance(ctx, &pb.UnregisterInstanceRequest{
 			ServiceId:  serviceId,
-			InstanceId: TOO_LONG_SERVICEID,
+			InstanceId: TooLongServiceID,
 		})
 		testErr = err.(*errsvc.Error)
 		assert.Error(t, testErr)
@@ -1855,7 +1855,7 @@ func TestSendHeartbeat(t *testing.T) {
 		assert.Equal(t, pb.ErrInvalidParams, testErr.Code)
 
 		err = discosvc.SendHeartbeat(ctx, &pb.HeartbeatRequest{
-			ServiceId:  TOO_LONG_SERVICEID,
+			ServiceId:  TooLongServiceID,
 			InstanceId: instanceId1,
 		})
 		testErr = err.(*errsvc.Error)
@@ -1880,7 +1880,7 @@ func TestSendHeartbeat(t *testing.T) {
 
 		err = discosvc.SendHeartbeat(ctx, &pb.HeartbeatRequest{
 			ServiceId:  serviceId,
-			InstanceId: TOO_LONG_SERVICEID,
+			InstanceId: TooLongServiceID,
 		})
 		testErr = err.(*errsvc.Error)
 		assert.Error(t, testErr)
@@ -2132,7 +2132,7 @@ func TestUpdateInstance(t *testing.T) {
 		assert.Equal(t, pb.ErrInvalidParams, testErr.Code)
 
 		err = discosvc.PutInstanceProperties(ctx, &pb.UpdateInstancePropsRequest{
-			ServiceId:  TOO_LONG_SERVICEID,
+			ServiceId:  TooLongServiceID,
 			InstanceId: instanceId,
 			Properties: map[string]string{
 				"test": "test",
@@ -2166,7 +2166,7 @@ func TestUpdateInstance(t *testing.T) {
 
 		err = discosvc.PutInstanceProperties(ctx, &pb.UpdateInstancePropsRequest{
 			ServiceId:  serviceId,
-			InstanceId: TOO_LONG_SERVICEID,
+			InstanceId: TooLongServiceID,
 			Properties: map[string]string{
 				"test": "test",
 			},
@@ -2204,3 +2204,38 @@ func assertInstanceContain(t *testing.T, instances []*pb.MicroServiceInstance, i
 	}
 	assert.True(t, found)
 }
+
+func TestInstanceUsage(t *testing.T) {
+	t.Run("get domain/project without instance usage, should return 0", func(t *testing.T) {
+		usage, err := discosvc.InstanceUsage(context.Background(), &pb.GetServiceCountRequest{
+			Domain:  "domain_without_service",
+			Project: "project_without_service",
+		})
+		assert.NoError(t, err)
+		assert.Equal(t, int64(0), usage)
+	})
+
+	t.Run("get domain/project with 1 instance usage, should return 1", func(t *testing.T) {
+		ctx := util.SetDomainProject(context.Background(), "domain_with_service", "project_with_service")
+		resp, err := discosvc.RegisterService(ctx, &pb.CreateServiceRequest{
+			Service: &pb.MicroService{
+				ServiceName: "test",
+			},
+		})
+		assert.NoError(t, err)
+		defer discosvc.UnregisterService(ctx, &pb.DeleteServiceRequest{ServiceId: resp.ServiceId, Force: true})
+
+		_, err = discosvc.RegisterInstance(ctx, &pb.RegisterInstanceRequest{Instance: &pb.MicroServiceInstance{
+			ServiceId: resp.ServiceId,
+			HostName:  "test",
+		}})
+		assert.NoError(t, err)
+
+		usage, err := discosvc.InstanceUsage(context.Background(), &pb.GetServiceCountRequest{
+			Domain:  "domain_with_service",
+			Project: "project_with_service",
+		})
+		assert.NoError(t, err)
+		assert.Equal(t, int64(1), usage)
+	})
+}
diff --git a/server/service/disco/metadata.go b/server/service/disco/metadata.go
index 04455dd..87b801b 100644
--- a/server/service/disco/metadata.go
+++ b/server/service/disco/metadata.go
@@ -243,3 +243,11 @@ func PutServiceProperties(ctx context.Context, request *pb.UpdateServicePropsReq
 
 	return datasource.GetMetadataManager().PutServiceProperties(ctx, request)
 }
+
+func ServiceUsage(ctx context.Context, request *pb.GetServiceCountRequest) (int64, error) {
+	resp, err := datasource.GetMetadataManager().CountService(ctx, request)
+	if err != nil {
+		return 0, err
+	}
+	return resp.Count, nil
+}
diff --git a/server/service/disco/metadata_test.go b/server/service/disco/metadata_test.go
index 40c1fcd..3519dd7 100644
--- a/server/service/disco/metadata_test.go
+++ b/server/service/disco/metadata_test.go
@@ -18,10 +18,12 @@
 package disco_test
 
 import (
+	"context"
 	"strconv"
 	"strings"
 	"testing"
 
+	"github.com/apache/servicecomb-service-center/pkg/util"
 	"github.com/apache/servicecomb-service-center/server/core"
 	"github.com/apache/servicecomb-service-center/server/service/disco"
 	quotasvc "github.com/apache/servicecomb-service-center/server/service/quota"
@@ -31,14 +33,14 @@ import (
 )
 
 var (
-	TOO_LONG_APPID       = strings.Repeat("x", 161)
-	TOO_LONG_SCHEMAID    = strings.Repeat("x", 161)
-	TOO_LONG_SERVICEID   = strings.Repeat("x", 65)
-	TOO_LONG_SERVICENAME = strings.Repeat("x", 129)
-	TOO_LONG_EXISTENCE   = strings.Repeat("x", 128+160+2)
-	TOO_LONG_ALIAS       = strings.Repeat("x", 129)
-	TOO_LONG_FRAMEWORK   = strings.Repeat("x", 65)
-	TOO_LONG_DESCRIPTION = strings.Repeat("x", 257)
+	TooLongAppID       = strings.Repeat("x", 161)
+	TooLongSchemaID    = strings.Repeat("x", 161)
+	TooLongServiceID   = strings.Repeat("x", 65)
+	TooLongServiceName = strings.Repeat("x", 129)
+	TooLongExistence   = strings.Repeat("x", 128+160+2)
+	TooLongAlias       = strings.Repeat("x", 129)
+	TooLongFramework   = strings.Repeat("x", 65)
+	TooLongDescription = strings.Repeat("x", 257)
 )
 
 func TestRegisterService(t *testing.T) {
@@ -64,18 +66,18 @@ func TestRegisterService(t *testing.T) {
 		}
 		r := &pb.CreateServiceRequest{
 			Service: &pb.MicroService{
-				AppId:       TOO_LONG_APPID[:len(TOO_LONG_APPID)-1],
-				ServiceName: TOO_LONG_SERVICENAME[:len(TOO_LONG_SERVICENAME)-1],
+				AppId:       TooLongAppID[:len(TooLongAppID)-1],
+				ServiceName: TooLongServiceName[:len(TooLongServiceName)-1],
 				Version:     "32767.32767.32767.32767",
-				Alias:       TOO_LONG_ALIAS[:len(TOO_LONG_ALIAS)-1],
+				Alias:       TooLongAlias[:len(TooLongAlias)-1],
 				Level:       "BACK",
 				Status:      "UP",
-				Schemas:     []string{TOO_LONG_SCHEMAID[:len(TOO_LONG_SCHEMAID)-1]},
+				Schemas:     []string{TooLongSchemaID[:len(TooLongSchemaID)-1]},
 				Paths:       paths,
 				Properties:  properties,
 				Framework: &pb.FrameWork{
-					Name:    TOO_LONG_FRAMEWORK[:len(TOO_LONG_FRAMEWORK)-1],
-					Version: TOO_LONG_FRAMEWORK[:len(TOO_LONG_FRAMEWORK)-1],
+					Name:    TooLongFramework[:len(TooLongFramework)-1],
+					Version: TooLongFramework[:len(TooLongFramework)-1],
 				},
 				RegisterBy: "SDK",
 			},
@@ -440,7 +442,7 @@ func TestRegisterService(t *testing.T) {
 
 		r = &pb.CreateServiceRequest{
 			Service: &pb.MicroService{
-				AppId:       TOO_LONG_APPID,
+				AppId:       TooLongAppID,
 				ServiceName: "service-validate",
 				Version:     "1.0.0",
 				Level:       "BACK",
@@ -569,7 +571,7 @@ func TestRegisterService(t *testing.T) {
 			Service: &pb.MicroService{
 				AppId:       "default",
 				ServiceName: "service-validate-alias",
-				Alias:       TOO_LONG_ALIAS,
+				Alias:       TooLongAlias,
 				Version:     "1.0.0",
 				Level:       "BACK",
 				Status:      "UP",
@@ -587,7 +589,7 @@ func TestRegisterService(t *testing.T) {
 				Version:     "1.0.4",
 				Level:       "BACK",
 				Framework: &pb.FrameWork{
-					Version: TOO_LONG_FRAMEWORK,
+					Version: TooLongFramework,
 				},
 				Properties: make(map[string]string),
 				Status:     "UP",
@@ -605,7 +607,7 @@ func TestRegisterService(t *testing.T) {
 				Version:     "1.0.5",
 				Level:       "BACK",
 				Framework: &pb.FrameWork{
-					Name: TOO_LONG_FRAMEWORK,
+					Name: TooLongFramework,
 				},
 				Properties: make(map[string]string),
 				Status:     "UP",
@@ -656,7 +658,7 @@ func TestRegisterService(t *testing.T) {
 				Version:     "1.0.6",
 				Level:       "BACK",
 				Status:      "UP",
-				Description: TOO_LONG_DESCRIPTION,
+				Description: TooLongDescription,
 			},
 		}
 		_, err = disco.RegisterService(ctx, r)
@@ -670,7 +672,7 @@ func TestRegisterService(t *testing.T) {
 				ServiceName: "schema-test",
 				Level:       "BACK",
 				Status:      "UP",
-				Schemas:     []string{TOO_LONG_SCHEMAID},
+				Schemas:     []string{TooLongSchemaID},
 			},
 		}
 		_, err = disco.RegisterService(ctx, r)
@@ -806,7 +808,7 @@ func TestUnregisterService(t *testing.T) {
 		assert.Equal(t, pb.ErrInvalidParams, testErr.Code)
 
 		err = disco.UnregisterService(ctx, &pb.DeleteServiceRequest{
-			ServiceId: TOO_LONG_SERVICEID,
+			ServiceId: TooLongServiceID,
 			Force:     true,
 		})
 		testErr = err.(*errsvc.Error)
@@ -939,7 +941,7 @@ func TestUnregisterManyService(t *testing.T) {
 		assert.Equal(t, pb.ErrInvalidParams, testErr.Code)
 
 		_, err = disco.UnregisterManyService(getContext(), &pb.DelServicesRequest{
-			ServiceIds: []string{TOO_LONG_SERVICEID},
+			ServiceIds: []string{TooLongServiceID},
 			Force:      false,
 		})
 		testErr = err.(*errsvc.Error)
@@ -1056,7 +1058,7 @@ func TestExistService(t *testing.T) {
 	t.Run("when param is invalid, should be failed", func(t *testing.T) {
 		_, err := disco.ExistService(ctx, &pb.GetExistenceRequest{
 			Type:        "microservice",
-			ServiceName: TOO_LONG_EXISTENCE,
+			ServiceName: TooLongExistence,
 			Version:     "1.0.0",
 			AppId:       "exist_appId",
 		})
@@ -1076,7 +1078,7 @@ func TestExistService(t *testing.T) {
 
 		_, err = disco.ExistService(ctx, &pb.GetExistenceRequest{
 			Type:        "microservice",
-			AppId:       TOO_LONG_APPID,
+			AppId:       TooLongAppID,
 			ServiceName: "exist-invalid-appid",
 			Version:     "3.0.0",
 		})
@@ -1316,7 +1318,7 @@ func TestUpdateService(t *testing.T) {
 
 	t.Run("when request is invalid, should be failed", func(t *testing.T) {
 		r := &pb.UpdateServicePropsRequest{
-			ServiceId:  TOO_LONG_SERVICEID,
+			ServiceId:  TooLongServiceID,
 			Properties: map[string]string{},
 		}
 		err := disco.PutServiceProperties(ctx, r)
@@ -1351,7 +1353,7 @@ func TestListService(t *testing.T) {
 		assert.Nil(t, service)
 
 		service, err = disco.GetService(getContext(), &pb.GetServiceRequest{
-			ServiceId: TOO_LONG_SERVICEID,
+			ServiceId: TooLongServiceID,
 		})
 		testErr = err.(*errsvc.Error)
 		assert.Error(t, testErr)
@@ -1359,3 +1361,32 @@ func TestListService(t *testing.T) {
 		assert.Nil(t, service)
 	})
 }
+
+func TestServiceUsage(t *testing.T) {
+	t.Run("get domain/project without service usage, should return 0", func(t *testing.T) {
+		usage, err := disco.ServiceUsage(context.Background(), &pb.GetServiceCountRequest{
+			Domain:  "domain_without_service",
+			Project: "project_without_service",
+		})
+		assert.NoError(t, err)
+		assert.Equal(t, int64(0), usage)
+	})
+
+	t.Run("get domain/project with 1 service usage, should return 1", func(t *testing.T) {
+		ctx := util.SetDomainProject(context.Background(), "domain_with_service", "project_with_service")
+		resp, err := disco.RegisterService(ctx, &pb.CreateServiceRequest{
+			Service: &pb.MicroService{
+				ServiceName: "test",
+			},
+		})
+		assert.NoError(t, err)
+		defer disco.UnregisterService(ctx, &pb.DeleteServiceRequest{ServiceId: resp.ServiceId, Force: true})
+
+		usage, err := disco.ServiceUsage(context.Background(), &pb.GetServiceCountRequest{
+			Domain:  "domain_with_service",
+			Project: "project_with_service",
+		})
+		assert.NoError(t, err)
+		assert.Equal(t, int64(1), usage)
+	})
+}
diff --git a/server/service/disco/schema.go b/server/service/disco/schema.go
index a84087c..5c59015 100644
--- a/server/service/disco/schema.go
+++ b/server/service/disco/schema.go
@@ -358,3 +358,14 @@ func checkSchemaQuota(ctx context.Context, serviceID string, schemaID string) er
 	}
 	return nil
 }
+
+func Usage(ctx context.Context, serviceID string) (int64, error) {
+	schemas, err := ListSchema(ctx, &pb.GetAllSchemaRequest{
+		ServiceId:  serviceID,
+		WithSchema: false,
+	})
+	if err != nil {
+		return 0, err
+	}
+	return int64(len(schemas)), nil
+}
diff --git a/server/service/disco/schema_test.go b/server/service/disco/schema_test.go
index 3c75867..c77f9b0 100644
--- a/server/service/disco/schema_test.go
+++ b/server/service/disco/schema_test.go
@@ -17,12 +17,14 @@
 package disco_test
 
 import (
+	"context"
 	"strconv"
 	"strings"
 	"testing"
 
 	"github.com/apache/servicecomb-service-center/datasource"
 	"github.com/apache/servicecomb-service-center/datasource/schema"
+	"github.com/apache/servicecomb-service-center/pkg/util"
 	"github.com/apache/servicecomb-service-center/server/service/disco"
 	quotasvc "github.com/apache/servicecomb-service-center/server/service/quota"
 	pb "github.com/go-chassis/cari/discovery"
@@ -35,7 +37,7 @@ const (
 )
 
 var (
-	TOO_LONG_SUMMARY = strings.Repeat("x", 129)
+	TooLongSummary = strings.Repeat("x", 129)
 )
 
 func TestPutSchema(t *testing.T) {
@@ -132,7 +134,7 @@ func TestPutSchema(t *testing.T) {
 			ServiceId: serviceIdDev,
 			SchemaId:  "com.huawei.test",
 			Schema:    "create schema",
-			Summary:   TOO_LONG_SUMMARY,
+			Summary:   TooLongSummary,
 		})
 		testErr = err.(*errsvc.Error)
 		assert.Error(t, testErr)
@@ -228,7 +230,7 @@ func TestPutSchema(t *testing.T) {
 				{
 					SchemaId: "com.huawei.test",
 					Schema:   "create schema",
-					Summary:  TOO_LONG_SUMMARY,
+					Summary:  TooLongSummary,
 				},
 			},
 		})
@@ -539,7 +541,7 @@ func TestExistSchema(t *testing.T) {
 
 		_, err = disco.ExistSchema(getContext(), &pb.GetSchemaRequest{
 			ServiceId: serviceId,
-			SchemaId:  TOO_LONG_SCHEMAID,
+			SchemaId:  TooLongSchemaID,
 		})
 		testErr = err.(*errsvc.Error)
 		assert.Error(t, testErr)
@@ -708,7 +710,7 @@ func TestGetSchema(t *testing.T) {
 		assert.Equal(t, pb.ErrInvalidParams, testErr.Code)
 
 		_, err = disco.GetSchema(getContext(), &pb.GetSchemaRequest{
-			ServiceId: TOO_LONG_SERVICEID,
+			ServiceId: TooLongServiceID,
 			SchemaId:  "com.huawei.test",
 		})
 		testErr = err.(*errsvc.Error)
@@ -716,7 +718,7 @@ func TestGetSchema(t *testing.T) {
 		assert.Equal(t, pb.ErrInvalidParams, testErr.Code)
 
 		_, err = disco.ListSchema(getContext(), &pb.GetAllSchemaRequest{
-			ServiceId: TOO_LONG_SERVICEID,
+			ServiceId: TooLongServiceID,
 		})
 		testErr = err.(*errsvc.Error)
 		assert.Error(t, testErr)
@@ -740,7 +742,7 @@ func TestGetSchema(t *testing.T) {
 
 		_, err = disco.GetSchema(getContext(), &pb.GetSchemaRequest{
 			ServiceId: serviceId,
-			SchemaId:  TOO_LONG_SCHEMAID,
+			SchemaId:  TooLongSchemaID,
 		})
 		testErr = err.(*errsvc.Error)
 		assert.Error(t, testErr)
@@ -1088,3 +1090,42 @@ func findSchemaBySchemaID(schemas []*pb.Schema, schemaID string) *pb.Schema {
 	}
 	return nil
 }
+
+func TestSchemaUsage(t *testing.T) {
+	ctx := util.WithNoCache(util.SetDomainProject(context.Background(), "default", "default"))
+
+	resp, err := disco.RegisterService(ctx, &pb.CreateServiceRequest{
+		Service: &pb.MicroService{
+			ServiceName: "TestSchemaUsage",
+		},
+	})
+	assert.NoError(t, err)
+	serviceID := resp.ServiceId
+	defer disco.UnregisterService(ctx, &pb.DeleteServiceRequest{ServiceId: serviceID, Force: true})
+
+	t.Run("get not exist service schema usage, should failed", func(t *testing.T) {
+		_, err := disco.Usage(ctx, "note_exist_service_id")
+		testErr := err.(*errsvc.Error)
+		assert.Error(t, testErr)
+		assert.Equal(t, pb.ErrServiceNotExists, testErr.Code)
+	})
+
+	t.Run("get usage without schemas, should return 0", func(t *testing.T) {
+		usage, err := disco.Usage(ctx, serviceID)
+		assert.NoError(t, err)
+		assert.Equal(t, int64(0), usage)
+	})
+
+	t.Run("get usage with schemas, should return 1", func(t *testing.T) {
+		err := disco.PutSchema(ctx, &pb.ModifySchemaRequest{
+			ServiceId: serviceID,
+			SchemaId:  "schemaID_1",
+			Schema:    "schema_1",
+		})
+		assert.NoError(t, err)
+
+		usage, err := disco.Usage(ctx, serviceID)
+		assert.NoError(t, err)
+		assert.Equal(t, int64(1), usage)
+	})
+}
diff --git a/server/service/disco/tag_test.go b/server/service/disco/tag_test.go
index 6a87fa7..e370765 100644
--- a/server/service/disco/tag_test.go
+++ b/server/service/disco/tag_test.go
@@ -198,7 +198,7 @@ func TestListTag(t *testing.T) {
 		assert.Equal(t, pb.ErrInvalidParams, testErr.Code)
 
 		_, err = disco.ListTag(ctx, &pb.GetServiceTagsRequest{
-			ServiceId: TOO_LONG_SERVICEID,
+			ServiceId: TooLongServiceID,
 		})
 		testErr = err.(*errsvc.Error)
 		assert.Error(t, testErr)
diff --git a/server/service/quota/service_test.go b/server/service/quota/service_test.go
index 2a3884b..664cadd 100644
--- a/server/service/quota/service_test.go
+++ b/server/service/quota/service_test.go
@@ -21,10 +21,9 @@ import (
 	"context"
 	"testing"
 
-	_ "github.com/apache/servicecomb-service-center/test"
-
 	"github.com/apache/servicecomb-service-center/pkg/util"
 	quotasvc "github.com/apache/servicecomb-service-center/server/service/quota"
+	_ "github.com/apache/servicecomb-service-center/test"
 	"github.com/stretchr/testify/assert"
 )
 
diff --git a/server/service/rbac/account_service.go b/server/service/rbac/account_service.go
index 04d0fa4..0b4297d 100644
--- a/server/service/rbac/account_service.go
+++ b/server/service/rbac/account_service.go
@@ -181,3 +181,11 @@ func illegalAccountCheck(ctx context.Context, target string) error {
 	}
 	return nil
 }
+
+func AccountUsage(ctx context.Context) (int64, error) {
+	_, used, err := rbac.Instance().ListAccount(ctx)
+	if err != nil {
+		return 0, err
+	}
+	return used, nil
+}
diff --git a/server/service/rbac/role_service.go b/server/service/rbac/role_service.go
index 9bb24ee..98b3236 100644
--- a/server/service/rbac/role_service.go
+++ b/server/service/rbac/role_service.go
@@ -136,3 +136,11 @@ func illegalRoleCheck(role string) error {
 	}
 	return nil
 }
+
+func RoleUsage(ctx context.Context) (int64, error) {
+	_, used, err := rbac.Instance().ListRole(ctx)
+	if err != nil {
+		return 0, err
+	}
+	return used, nil
+}