You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by ma...@apache.org on 2023/03/11 13:20:59 UTC

[iotdb] branch IOTDB-5663 updated: implement LinuxNetMetricManager

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

marklau99 pushed a commit to branch IOTDB-5663
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to refs/heads/IOTDB-5663 by this push:
     new 8092301cea implement LinuxNetMetricManager
8092301cea is described below

commit 8092301ceab3f989b538b1267fdf512f65801bfc
Author: LiuXuxin <li...@outlook.com>
AuthorDate: Sat Mar 11 21:20:51 2023 +0800

    implement LinuxNetMetricManager
---
 .../metricsets/net/LinuxNetMetricManager.java      | 178 ++++++++++++++++++++-
 1 file changed, 177 insertions(+), 1 deletion(-)

diff --git a/metrics/interface/src/main/java/org/apache/iotdb/metrics/metricsets/net/LinuxNetMetricManager.java b/metrics/interface/src/main/java/org/apache/iotdb/metrics/metricsets/net/LinuxNetMetricManager.java
index 0c9c3da024..800e39c685 100644
--- a/metrics/interface/src/main/java/org/apache/iotdb/metrics/metricsets/net/LinuxNetMetricManager.java
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/metricsets/net/LinuxNetMetricManager.java
@@ -19,4 +19,180 @@
 
 package org.apache.iotdb.metrics.metricsets.net;
 
-public class LinuxNetMetricManager implements INetMetricManager {}
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Scanner;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public class LinuxNetMetricManager implements INetMetricManager {
+  private final Logger log = LoggerFactory.getLogger(LinuxNetMetricManager.class);
+
+  @SuppressWarnings("squid:S1075")
+  private static final String IFACE_ID_PATH = "/sys/class/net/";
+
+  @SuppressWarnings("squid:S1075")
+  private static final String NET_STATUS_PATH = "/proc/net/dev";
+
+  private static final String BYTES = "bytes";
+  private static final String PACKETS = "packets";
+  private static final long UPDATE_INTERVAL = 10_000L;
+
+  private static final int IFACE_NAME_INDEX = 0;
+  // initialized after reading status file
+  private static int RECEIVED_BYTES_INDEX = 0;
+  private static int TRANSMITTED_BYTES_INDEX = 0;
+  private static int RECEIVED_PACKETS_INDEX = 0;
+  private static int TRANSMITTED_PACKETS_INDEX = 0;
+  private Set<String> iFaceSet;
+
+  private final Map<String, Long> receivedBytesMapForIface;
+  private final Map<String, Long> transmittedBytesMapForIface;
+  private final Map<String, Long> receivedPacketsMapForIface;
+  private final Map<String, Long> transmittedPacketsMapForIface;
+
+  public LinuxNetMetricManager() {
+    collectIfaces();
+    // leave one entry to avoid hashmap resizing
+    receivedBytesMapForIface = new HashMap<>(iFaceSet.size() + 1, 1);
+    transmittedBytesMapForIface = new HashMap<>(iFaceSet.size() + 1, 1);
+    receivedPacketsMapForIface = new HashMap<>(iFaceSet.size() + 1, 1);
+    transmittedPacketsMapForIface = new HashMap<>(iFaceSet.size() + 1, 1);
+    collectNetStatusIndex();
+  }
+
+  private long lastUpdateTime = 0L;
+
+  @Override
+  public Set<String> getIfaceSet() {
+    checkUpdate();
+    return iFaceSet;
+  }
+
+  @Override
+  public Map<String, Long> getReceivedByte() {
+    checkUpdate();
+    return receivedBytesMapForIface;
+  }
+
+  @Override
+  public Map<String, Long> getTransmittedBytes() {
+    checkUpdate();
+    return transmittedBytesMapForIface;
+  }
+
+  @Override
+  public Map<String, Long> getReceivedPackets() {
+    checkUpdate();
+    return receivedPacketsMapForIface;
+  }
+
+  @Override
+  public Map<String, Long> getTransmittedPackets() {
+    checkUpdate();
+    return transmittedPacketsMapForIface;
+  }
+
+  private void checkUpdate() {
+    if (System.currentTimeMillis() - lastUpdateTime >= UPDATE_INTERVAL) {
+      updateNetStatus();
+    }
+  }
+
+  private void collectIfaces() {
+    File iFaceIdFolder = new File(IFACE_ID_PATH);
+    if (!iFaceIdFolder.exists()) {
+      iFaceSet = Collections.emptySet();
+      log.warn("Cannot find {}", IFACE_ID_PATH);
+      return;
+    }
+    iFaceSet =
+        new ArrayList<>(Arrays.asList(Objects.requireNonNull(iFaceIdFolder.listFiles())))
+            .stream().map(File::getName).collect(Collectors.toSet());
+  }
+
+  private void collectNetStatusIndex() {
+    File netStatusFile = new File(NET_STATUS_PATH);
+    if (!netStatusFile.exists()) {
+      log.warn("Cannot find {}", NET_STATUS_PATH);
+      return;
+    }
+    try (FileInputStream inputStream = new FileInputStream(netStatusFile)) {
+      Scanner scanner = new Scanner(inputStream);
+      // skip the first line
+      scanner.nextLine();
+      String headerLine = scanner.nextLine();
+      String[] seperatedHeaderLine = headerLine.split("\\|");
+      String[] receiveStatusHeader = seperatedHeaderLine[1].split("\\s+");
+      String[] transmitStatusHeader = seperatedHeaderLine[2].split("\\s+");
+      for (int i = 0, length = receiveStatusHeader.length; i < length; ++i) {
+        if (receiveStatusHeader[i].equals(BYTES)) {
+          RECEIVED_BYTES_INDEX = i + 1;
+        } else if (receiveStatusHeader[i].equals(PACKETS)) {
+          RECEIVED_PACKETS_INDEX = i + 1;
+        }
+      }
+      for (int i = 0, length = transmitStatusHeader.length; i < length; ++i) {
+        if (transmitStatusHeader[i].equals(BYTES)) {
+          TRANSMITTED_BYTES_INDEX = i + length + 1;
+        } else if (transmitStatusHeader[i].equals(PACKETS)) {
+          TRANSMITTED_PACKETS_INDEX = i + length + 1;
+        }
+      }
+    } catch (IOException e) {
+      log.error("Meets exception when reading {}", NET_STATUS_PATH, e);
+    }
+  }
+
+  private void updateNetStatus() {
+    lastUpdateTime = System.currentTimeMillis();
+    File netStatusFile = new File(NET_STATUS_PATH);
+    if (!netStatusFile.exists()) {
+      return;
+    }
+    try (FileInputStream inputStream = new FileInputStream(netStatusFile)) {
+      Scanner scanner = new Scanner(inputStream);
+      // skip the starting two lines
+      // because they are the meta info
+      scanner.nextLine();
+      scanner.nextLine();
+
+      // reading the actual status info for iface
+      while (scanner.hasNextLine()) {
+        String line = scanner.nextLine();
+        // we wrap the string array as array list to execute the removing step
+        List<String> statusInfoAsList = new ArrayList<>(Arrays.asList(line.split("\\s")));
+        // remove all empty string
+        statusInfoAsList.removeIf(x -> x.equals(""));
+
+        String iface = statusInfoAsList.get(IFACE_NAME_INDEX);
+        // since the read iface format is "IFACE:"
+        // we need to remove the last letter
+        iface = iface.substring(0, iface.length() - 1);
+
+        long receivedBytes = Long.parseLong(statusInfoAsList.get(RECEIVED_BYTES_INDEX));
+        long transmittedBytes = Long.parseLong(statusInfoAsList.get(TRANSMITTED_BYTES_INDEX));
+        long receivedPackets = Long.parseLong(statusInfoAsList.get(RECEIVED_PACKETS_INDEX));
+        long transmittedPackets = Long.parseLong(statusInfoAsList.get(TRANSMITTED_PACKETS_INDEX));
+
+        receivedBytesMapForIface.put(iface, receivedBytes);
+        transmittedBytesMapForIface.put(iface, transmittedBytes);
+        receivedPacketsMapForIface.put(iface, receivedPackets);
+        transmittedPacketsMapForIface.put(iface, transmittedPackets);
+      }
+    } catch (IOException e) {
+      log.error("Meets error when reading {} for net status", NET_STATUS_PATH, e);
+    }
+  }
+}