Help Center/ Enterprise Router/ User Guide/ Monitoring and Audit/ Cloud Eye Monitoring/ Configuring Average Latency and Connectivity Rate Metrics to Monitor the Enterprise Router Network Connectivity Quality
Updated on 2026-07-14 GMT+08:00

Configuring Average Latency and Connectivity Rate Metrics to Monitor the Enterprise Router Network Connectivity Quality

You can perform the following operations to configure the average latency and connectivity rate metrics for the enterprise router network. After the configuration is complete, you can view the real-time monitoring data on the Cloud Eye console to monitor the network connectivity quality of the enterprise router. The monitoring metrics are as follows:

  • Average latency (avg_latency): average response time of all requests in a single test. It reflects the network transmission speed, link congestion, and network smoothness.
  • Connectivity rate (connectivity_rate): the percentage of requests that successfully establish connections and complete data exchange in a test. It reflects the network link connectivity and stability and the overall network availability.

Solution Architecture

In this solution, enterprise router (er-x) enables communications between vpc-web (192.168.0.0/16) and vpc-client (172.16.0.0/16) in the same region. ecs-web is deployed in vpc-web as the server, and ecs-client is deployed in vpc-client as the client. Based on this networking, configure average latency and connectivity rate metrics to monitor the network communication quality between the client and the server in real time.

Figure 1 Network planning

Network Planning

Figure 1 and Table 1 show the network planning and its description for communications among two VPCs attached to an enterprise router in the same region.

Table 1 Network planning description

Resource

Description

VPC

  • The CIDR blocks of the VPCs to be connected cannot overlap with each other.
  • Each VPC has a default route table.
  • The routes (Table 2) in the default route table of the VPC are described as follows:
    • Local: a system route for IPv4 communications between subnets in a VPC.
    • Three routes to fixed CIDR blocks: 10.0.0.0/8, 172.16.0.0/12, and 192.168.0.0/16. If you enable Auto Add Routes when attaching a VPC to an enterprise router, static routes will be automatically added to the VPC route table. If there are multiple VPCs attached to the enterprise router, these routes will forward traffic between them to the enterprise router first, and then to the next-hop network instance.
      CAUTION:

      If a VPC route table already has routes with destinations that conflict with 10.0.0.0/8, 172.16.0.0/12, and 192.168.0.0/16, routes pointing to these CIDR blocks will fail to be added. In this case, do not enable Auto Add Routes. After the attachment is created, manually add the routes.

Enterprise router

After Default Route Table Association and Default Route Table Propagation are enabled and the VPC attachments are created, the system will automatically:
  • Associate the two VPC attachments with the default route table of the enterprise router.
  • Propagate the VPC attachments with the default route table of the enterprise router. The route table automatically learns the VPC CIDR blocks as the destinations of routes. For details, see Table 3.

ECS

Two ECSs are in different VPCs. If the ECSs are in different security groups, add rules to the security groups to allow access to each other.

Table 2 VPC route table

Destination

Next Hop

Route Type

Fixed CIDR block: 10.0.0.0/8

Enterprise router er-x

Static route (custom)

Fixed CIDR block: 172.16.0.0/12

Enterprise router er-x

Static route (custom)

Fixed CIDR block: 192.168.0.0/16

Enterprise router er-x

Static route (custom)

Table 3 Enterprise router route table

Destination

Next Hop

Route Type

vpc-web CIDR block: 192.168.0.0/16

VPC 1 attachment: er-attach-web

Propagated route

vpc-client CIDR block: 172.16.0.0/16

VPC 2 attachment: er-attach-client

Propagated route

Resource Planning

The enterprise router, VPCs, and ECSs must be in the same region, but they can be in different AZs.

The following resource details are only examples. You can modify them as required.

Table 4 Resource planning

Resource

Quantity

Description

VPC

2

Two VPCs are required. One is used to deploy the ECS as the server, and the other is used to deploy the ECS as the client. Both VPCs need to be attached to the enterprise router.
  • VPC name: Set it based on site requirements. In this example, the VPC where the ECS as the server is deployed is vpc-web, and the VPC where the ECS as the client is deployed is vpc-client.
  • VPC IPv4 CIDR block: Set it based on site requirements. In this example, the CIDR block for vpc-web is 192.168.0.0/16 and that for vpc-client is 172.16.0.0/16.
  • Subnet name: Set it based on site requirements. In this example, subnet-web-01 and subnet-client-01 are used.
  • Subnet IPv4 CIDR block: Set it based on site requirements. In this example, the CIDR block for subnet-web-01 is 192.168.0.0/24 and that for subnet-client-01 is 172.16.0.0/24.

Enterprise router

1

  • Name: Set it based on site requirements. In this example, er-x is used.
  • ASN: Set it based on site requirements. In this example, 64513 is used.
  • Default Route Table Association: Enable this option.
  • Default Route Table Propagation: Enable this option.
  • Auto Accept Shared Attachments: Set it based on site requirements. In this example, enable this option.
  • In this example, you need to add two VPC attachments to the enterprise router.
    • VPC 1 attachment: er-attach-web
    • VPC 2 attachment: er-attach-client

ECS

2

Two ECSs are required. One acts as the server, and the other acts as the client.

  • ECS Name: Set it based on site requirements. In this example, the server ECS is ecs-web, and the client ECS is ecs-client.
  • Image: Set it based on site requirements. In this example, public image Huawei Cloud EulerOS 2.0 Standard 64 bit is used.
  • Network
    • VPC: Select a VPC based on site requirements. In this example, select vpc-web for ecs-web and vpc-client for ecs-client.
    • Subnet: Select a subnet based on site requirements. In this example, select subnet-web-01 for ecs-web and subnet-client-01 for ecs-client.
  • Security Group: Select a security group based on site requirements. In this example, the two ECSs share the security group sg-x.
  • Private IP address: In this example, the private IP address of ecs-web is 192.168.0.164, and that of ecs-client is 172.16.0.60.
  • EIP: Bind an EIP to ecs-web. To deploy the Nginx service on the server ECS, you need to connect to the Internet.

In this example, only one client ECS is deployed for demonstration. In practice, you are advised to deploy one client ECS in each AZ of the enterprise router to comprehensively monitor the network status.

Step 1: Obtain Environment Information

Prepare the environment information required for 3.c in advance. For details about the environment information to be obtained and how to obtain it, see Table 5.

Table 5 Environment information

Environment

Example Value

How to Obtain

Project corresponding to the region where the resource is located: {project_name}

cn-east-x

Obtaining Account, IAM User, Group, Project, Region, and Agency Information

Project ID corresponding to the region where the resource is located: {project_id}

15289aca74exxxxxx37dea0315d99

Name of the account used to create the IAM user

IAM-er-test

IAM username

er-test

Private IP address of the server ECS

192.168.0.164

  1. Log in to the ECS console.
  2. Locate the row that contains the target ECS and view its private IP address in the IP Address column.

Custom listening port

8000

Listening port configured in 3.c. You can customize it.

Enterprise router ID

cd711600-xxxx-xxxx-938f-e41eb64f5e25

  1. Go to the enterprise router list.
  2. Locate the target enterprise router and view its ID.

Step 2: Create Resources

For details about the resource planning in this example, see Table 4.

  1. Create an enterprise router in region A.

    For details, see Creating an Enterprise Router.

  2. Create two VPCs in region A.

    For details, see Creating a VPC with a Subnet.

  3. Create two ECSs in region A.

    In this example, bind an EIP to ecs-web for deploying the Nginx service.

    For details, see Purchasing an ECS in Custom Config Mode.

Step 3: Create VPC Attachments to the Enterprise Router

  1. Attach the two VPCs to the enterprise router.

    When creating the VPC attachment, enable Auto Add Routes.

    If this option is enabled, routes with this enterprise router as the next hop and 10.0.0.0/8, 172.16.0.0/12, and 192.168.0.0/16 as the destinations will be automatically added to all route tables of the VPC.

    For details, see Creating VPC Attachments for the Enterprise Router.

  2. Check the routes with destinations set to the VPC CIDR blocks in the enterprise router route tables.

    In this example, Default Route Table Association and Default Route Table Propagation are enabled for the enterprise router, and routes with destinations set to VPC CIDR blocks are automatically added when you attach the VPCs to the enterprise router.

    For enterprise router route details, see Table 3.

    To view enterprise routes, see Viewing Routes.

  3. Log in to any ECS and take the following steps to check the network connectivity:

    Multiple methods are available for logging in to an ECS. For details, see Logging In to an ECS.

    In this example, use VNC provided on the management console to log in to an ECS.

    For example, log in to ecs-web and run the following command to check whether the two VPCs can communicate with each other:

    ping Private IP address of ecs-client

    Example command:

    ping 172.16.0.60

    If information similar to the following is displayed, the two VPCs can communicate with each other.
    [root@ecs-web ~]# ping 172.16.0.60
    PING 172.16.0.60 (172.16.0.60) 56(84) bytes of data.
    64 bytes from 172.16.0.60: icmp_seq=1 ttl=63 time=2.02 ms
    64 bytes from 172.16.0.60: icmp_seq=2 ttl=63 time=1.86 ms
    ^C
    --- 172.16.0.60 ping statistics ---
    2 packets transmitted, 2 received, 0% packet loss, time 1000ms
    rtt min/avg/max/mdev = 1.859/1.941/2.023/0.082 ms

Step 4: Deploy Nginx on the Server ECS

  1. Log in to the server ECS (ecs-web) as the root user.

    Multiple methods are available for logging in to an ECS. For details, see Logging In to an ECS.

    In this example, use VNC provided on the management console to log in to an ECS.

  2. Run the following command to install Nginx:

    yum install nginx

    If information similar to the following is displayed, the installation is complete:
    [root@ecs-web ~]# yum install nginx
    Last metadata expiration check: 0:24:32 ago on Thu 11 Jun 2026 02:01:16 PM CST.
    Dependencies resolved.
    ...                                                                                                      
    Complete!
  3. Perform the following steps to configure a custom listening port:
    1. Run the following command to open the /etc/nginx/nginx.conf file:

      vim /etc/nginx/nginx.conf

    2. Press i to enter the editing mode.
    3. Locate the server { ... } configuration information in the file and change the default value in listen 80; and listen [::]:80; to the custom port. In this example, the port is changed to 8000.
      server {
          listen       8000;       # Modify the value.
          listen       [::]:8000;  # Modify the value. (IPv6 listening, optional)
          server_name  _;
          root         /usr/share/nginx/html;
          ...
      }
    4. Press ESC to exit the editing mode and enter :wq! to save the configuration.
  4. Run the following command to check whether the syntax of the Nginx configuration file is correct:

    nginx -t

    If information similar to the following is displayed, the configuration is correct:
    [root@ecs-web ~]# nginx -t
    nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
    nginx: configuration file /etc/nginx/nginx.conf test is successful
  5. Run the following command to start Nginx:

    nginx

Step 5: Deploy the Configuration Script on the Client ECS

  1. Log in to the client ECS (ecs-client).

    Multiple methods are available for logging in to an ECS. For details, see Logging In to an ECS.

    In this example, use VNC provided on the management console to log in to an ECS.

  2. Perform the following steps to create an automatic configuration script for monitoring metrics:
    1. Run the following command to create the ces.py script file:

      vim ces.py

    2. Press i to enter the editing mode.
    3. Add the configuration information to the ces.py file:
      import asyncio
      import sys
      from urllib.parse import urlparse
      import requests
      import time
      import concurrent.futures
      import yaml
      def load_parameter(file_path):
          with open(file_path, 'r', encoding='utf-8') as file:
              parameter = yaml.safe_load(file)
          return parameter
      def check_connectivity_with_curl(url):
          parsed_url = urlparse(url)
          host = parsed_url.hostname
          port = parsed_url.port or (443 if parsed_url.scheme == "https" else 80)
          path = parsed_url.path or "/"
          if parsed_url.query:
              path += f"?{parsed_url.query}"
          async def _raw_socket_request():
              start_time = time.perf_counter()
              reader, writer = None, None
              try:
                  if parsed_url.scheme == "https":
                      import ssl
                      ssl_context = ssl._create_unverified_context()
                      reader, writer = await asyncio.wait_for(
                          asyncio.open_connection(host, port, ssl=ssl_context), timeout=5.0
                      )
                  else:
                      reader, writer = await asyncio.wait_for(
                          asyncio.open_connection(host, port), timeout=5.0
                      )
                  request_header = (
                      f"GET {path} HTTP/1.1\r\n"
                      f"Host: {host}\r\n"
                      f"User-Agent: curl/7.29.0\r\n"
                      f"Connection: close\r\n\r\n"
                  )
                  writer.write(request_header.encode('utf-8'))
                  await writer.drain()
                  response_line = await asyncio.wait_for(reader.readline(), timeout=5.0)
                  duration_ms = (time.perf_counter() - start_time) * 1000
                  status_code = int(response_line.split()[1])
                  return status_code, duration_ms
              except Exception:
                  duration_ms = (time.perf_counter() - start_time) * 1000
                  return -1, duration_ms
              finally:
                  if writer:
                      writer.close()
                      try:
                          await writer.wait_closed()
                      except Exception:
                          pass
          try:
              loop = asyncio.get_event_loop()
          except RuntimeError:
              loop = asyncio.new_event_loop()
              asyncio.set_event_loop(loop)
          return loop.run_until_complete(_raw_socket_request())
      def get_connectivity_stats(url, total_requests=100, max_workers=100):
          latencies = []
          success_count = 0
          with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
              futures = [executor.submit(check_connectivity_with_curl, url) for _ in range(total_requests)]
              for future in concurrent.futures.as_completed(futures):
                  status_code, latency = future.result()
                  if status_code == 200:
                      success_count += 1
                      latencies.append(latency)
          connectivity_rate = (success_count / total_requests) * 100
          avg_latency = sum(latencies) / len(latencies) if latencies else 0
          return connectivity_rate, avg_latency
      def get_connectivity_rate(parameter, rate):
          return {
              "metric": {
                  "namespace": parameter['namespace'],
                  "dimensions": [{
                      "name": parameter['dimensions_name'],
                      "value": parameter['dimensions_value']
                  }],
                  "metric_name": parameter['metric_name_connectivity_rate']
              },
              "ttl": int(parameter['ttl']),
              "collect_time": int(time.time() * 1000),
              "value": rate,
              "unit": parameter['unit_connectivity_rate'],
              "type": parameter['type']
          }
      def get_avg_latency(parameter, latency):
          return {
              "metric": {
                  "namespace": parameter['namespace'],
                  "dimensions": [{
                      "name": parameter['dimensions_name'],
                      "value": parameter['dimensions_value']
                  }],
                  "metric_name": parameter['metric_name_avg_latency']
              },
              "ttl": int(parameter['ttl']),
              "collect_time": int(time.time() * 1000),
              "value": latency,
              "unit": parameter['unit_avg_latency'],
              "type": parameter['type']
          }
      class TokenManager:
          def __init__(self, parameter):
              self.token = None
              self.auth_url = parameter['auth_url']
              self.auth_body = {"auth": {"identity": {"methods": ["password"], "password": {
                  "user": {"name": parameter['iam_user'], "domain": {"name": parameter['iam_domain']}, "password": parameter['iam_password']}}},
                                         "scope": {"project": {"name": parameter['iam_project']}}}}
              self.refresh_token()
          def refresh_token(self):
              headers = {'Content-Type': 'application/json'}
              try:
                  response = requests.post(self.auth_url, json=self.auth_body, headers=headers, verify=False)
                  new_token = response.headers.get('X-Subject-Token')
                  if new_token:
                      self.token = new_token
                  else:
                      print("not found X-Subject-Token")
              except Exception as e:
                  print(f"get Token failed: {e}")
      def create_metric_data(create_metric_data_url, token, data):
          headers = {'X-Auth-Token': token}
          try:
              res = requests.post(create_metric_data_url, json=data,
                                     headers=headers, verify=False, timeout=5)
              return res.status_code
          except Exception as e:
              print(f"error: {e}")
      def main_job(parameter, token_manager):
          while True:
              rate, latency = get_connectivity_stats(parameter['target_url'], int(parameter['total_requests']), int(parameter['max_workers']))
              data = [get_connectivity_rate(parameter, rate), get_avg_latency(parameter, latency)]
              for i in range(3):
                  status = create_metric_data(parameter['create_metric_data_url'], token_manager.token, data)
                  if status == 401:
                      token_manager.refresh_token()
                      continue
                  break
              time.sleep(10)
      if __name__ == "__main__":
          parameter = load_parameter(sys.argv[1].strip())
          parameter['iam_password'] = sys.argv[2].strip()
          manager = TokenManager(parameter)
          main_job(parameter, manager)
    4. Press ESC to exit the editing mode and enter :wq! to save the configuration.
  3. Perform the following steps to add the environment information required for running the script:
    1. Run the following command to create the parameter.yml file:

      vim parameter.yml

    2. Press i to enter the editing mode.
    3. Add the configuration information to the parameter.yml file:
      Review the comments and replace the examples with the environment information obtained in Step 1: Obtain Environment Information.
      # URL for obtaining the token. Replace {project_name} with the project corresponding to the region where the resource is located.
      auth_url: https://iam.{project_name}.myhuaweicloud.com/v3/auth/tokens
      # URL for reporting monitoring data. Replace {project_name} and {project_id} with the project name and project ID corresponding to the region where the resource is located.
      create_metric_data_url: https://ces.{project_name}.myhuaweicloud.com/V1.0/{project_id}/metric-data
      # Name of the account used to create the IAM user. The following is only an example. Replace it with the actual name.
      iam_domain: IAM-er-test
      # IAM username. The following is only an example. Replace it with the actual username.
      iam_user: er-test
      # Project of the account used to create the IAM user, that is, the project corresponding to the region where the resource is located. Replace it with the actual value.
      iam_project: {project_name}
      # Server URL. The following is only an example. Replace the IP address with the private IP address of the server ECS and the port number with the custom listening port.
      target_url: http://172.16.0.245:8000
      # Number of requests sent in a single test. The recommended value is 100 or set it based on the site requirements.
      total_requests: 100
      # Maximum number of concurrent requests in a single test. The recommended value is 100 or set it based on the site requirements.
      max_workers: 100
      # Service namespace. The value is in the format of service.item, where service and item are separated by a period (.).
      # service and item each must start with a letter. They can contain letters, digits, and underscores (_). The value allows 3 to 32 characters.
      # Example: TEST.ER
      namespace: "TEST.ER"
      # Data validity period, in seconds. If the validity period expires, data will be automatically deleted. The value is an integer ranging from 1 to 604800.
      ttl: 172800
      # Metric resource dimension name, which can be fixed to er_instance_id.
      dimensions_name: er_instance_id
      # Metric resource dimension value, that is, the enterprise router ID. The following is only an example. Replace it with the actual value.
      dimensions_value: eb97488a-070c-4db8-a719-ee5e66490e8d
      # Connectivity rate metric ID, which can be fixed to connectivity_rate.
      metric_name_connectivity_rate: connectivity_rate
      # Latency metric ID, which can be fixed to avg_latency.
      metric_name_avg_latency: avg_latency
      # Connectivity rate metric unit, which can be fixed to %.
      unit_connectivity_rate: "%"
      # Latency metric unit, which can be fixed to ms.
      unit_avg_latency: ms
      # Metric data type, which can be fixed to float.
      type: float
    4. Press ESC to exit the editing mode and enter :wq! to save the configuration.
  4. Run the following command to start ces.py and parameter.yml:

    nohup python3 ces.py parameter.yml Password &

    Replace the password in the command with the actual password of the current account.

  5. After the scripts are executed, perform the following steps to view the monitoring metrics on the Cloud Eye console:
    1. Go to the Cloud Eye console and choose Custom Monitoring.

      You can view the service namespace set in 3.c. In this example, the namespace is TEST.ER.

      Figure 2 TEST.ER
    2. Locate the row that contains the enterprise router to be monitored and click View Metric in the Operation column.
      On the displayed page, you can view the monitoring metric data reported in real time.
      • Average latency (avg_latency): average response time of all requests in a single test. It reflects the network transmission speed, link congestion, and network smoothness.
      • Connectivity rate (connectivity_rate): the percentage of requests that successfully establish connections and complete data exchange in a test. It reflects the network link connectivity and stability and the overall network availability.
      Figure 3 Monitoring metric details