From cee7b409082c1c8ab81e53b536f03c79bf50c26b Mon Sep 17 00:00:00 2001 From: imbajin Date: Tue, 22 Oct 2024 15:32:42 +0800 Subject: [PATCH] add comment version --- .../store/node/metrics/ProcFileHandler.java | 147 ++++++++++++++++++ .../store/node/metrics/ProcfsEntry.java | 13 +- .../store/node/metrics/ProcfsMetrics.java | 24 ++- .../store/node/metrics/ProcfsReader.java | 142 ----------------- .../store/node/metrics/SystemMemoryStats.java | 4 +- 5 files changed, 166 insertions(+), 164 deletions(-) create mode 100644 hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/metrics/ProcFileHandler.java delete mode 100644 hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/metrics/ProcfsReader.java diff --git a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/metrics/ProcFileHandler.java b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/metrics/ProcFileHandler.java new file mode 100644 index 0000000000..1b0e6e22c5 --- /dev/null +++ b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/metrics/ProcFileHandler.java @@ -0,0 +1,147 @@ +/* + * 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 org.apache.hugegraph.store.node.metrics; + +import static java.util.Locale.ENGLISH; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import lombok.Getter; + +class ProcFileHandler { + + // Cache duration in milliseconds + private static final long CACHE_DURATION_MS = 100; + // Singleton instances of ProcFileHandler + private static final Map handlerInstances = new HashMap<>(); + private static final Object handlerLock = new Object(); + // Cached data + private static final Map> cachedContent = new HashMap<>(); + private static final Object contentLock = new Object(); + // Base path for proc filesystem + private static final Path PROC_BASE_PATH = Paths.get("/proc", "self"); + private final Path filePath; + private final boolean isOSSupported; + private long lastReadTimestamp = -1; + + // Private constructor to initialize the handler + private ProcFileHandler(String entry) { + this(PROC_BASE_PATH, entry, false); + } + + // Package-private constructor for testing + ProcFileHandler(Path base, String entry) { + this(base, entry, true); + } + + // Private constructor with an OS support flag + private ProcFileHandler(Path base, String entry, boolean forceOSSupport) { + Objects.requireNonNull(base); + Objects.requireNonNull(entry); + + this.filePath = base.resolve(entry); + this.isOSSupported = forceOSSupport || + System.getProperty("os.name").toLowerCase(ENGLISH).startsWith("linux"); + } + + // Get an instance of ProcFileHandler + static ProcFileHandler getInstance(String key) { + Objects.requireNonNull(key); + + synchronized (handlerLock) { + ProcFileHandler handler = handlerInstances.get(key); + if (handler == null) { + handler = new ProcFileHandler(key); + handlerInstances.put(key, handler); + } + return handler; + } + } + + // Get the file path + Path getFilePath() { + return filePath; + } + + // Read the proc file + ReadResult readFile() throws IOException { + return readFile(currentTimeMillis()); + } + + // Read the proc file with a specific time + ReadResult readFile(long currentTimeMillis) throws IOException { + synchronized (contentLock) { + final Path key = getFilePath().getFileName(); + + final ReadResult readResult; + if (lastReadTimestamp == -1 || + lastReadTimestamp + CACHE_DURATION_MS < currentTimeMillis) { + final List lines = readFilePath(filePath); + cacheContent(key, lines); + lastReadTimestamp = currentTimeMillis(); + readResult = new ReadResult(lines, lastReadTimestamp); + } else { + readResult = new ReadResult(cachedContent.get(key), lastReadTimestamp); + } + return readResult; + } + } + + // Read the content of the path + List readFilePath(Path path) throws IOException { + Objects.requireNonNull(path); + + if (!isOSSupported) { + return Collections.emptyList(); + } + return Files.readAllLines(path); + } + + // Cache the result + void cacheContent(Path key, List lines) { + Objects.requireNonNull(key); + Objects.requireNonNull(lines); + + cachedContent.put(key, lines); + } + + // Get the current time in milliseconds + long currentTimeMillis() { + return System.currentTimeMillis(); + } + + // Result of reading the proc file + @Getter + static class ReadResult { + + private final List lines; + private final long readTime; + + ReadResult(List lines, long readTime) { + this.lines = Objects.requireNonNull(lines); + this.readTime = readTime; + } + } +} diff --git a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/metrics/ProcfsEntry.java b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/metrics/ProcfsEntry.java index eedcc55f38..7d67ab0022 100644 --- a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/metrics/ProcfsEntry.java +++ b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/metrics/ProcfsEntry.java @@ -16,7 +16,7 @@ */ package org.apache.hugegraph.store.node.metrics; -import static org.apache.hugegraph.store.node.metrics.ProcfsReader.ReadResult; +import static org.apache.hugegraph.store.node.metrics.ProcFileHandler.ReadResult; import java.io.IOException; import java.util.Collection; @@ -31,26 +31,27 @@ abstract class ProcfsRecord { private final Object syncLock = new Object(); - private final ProcfsReader fileReader; + private final ProcFileHandler fileReader; private long lastProcessedTime = -1; - protected ProcfsRecord(ProcfsReader fileReader) { + protected ProcfsRecord(ProcFileHandler fileReader) { this.fileReader = Objects.requireNonNull(fileReader); } protected final void gatherData() { synchronized (syncLock) { try { - final ReadResult readResult = fileReader.read(); - if (readResult != null && (lastProcessedTime == -1 || lastProcessedTime != readResult.getReadTime())) { + final ReadResult readResult = fileReader.readFile(); + if (readResult != null && + (lastProcessedTime == -1 || lastProcessedTime != readResult.getReadTime())) { clear(); process(readResult.getLines()); lastProcessedTime = readResult.getReadTime(); } } catch (IOException e) { clear(); - logger.warn("Failed reading '" + fileReader.getEntryPath() + "'!", e); + logger.warn("Failed reading '" + fileReader.getFilePath() + "'!", e); } } } diff --git a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/metrics/ProcfsMetrics.java b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/metrics/ProcfsMetrics.java index f0f4472fb6..c5a649e62b 100644 --- a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/metrics/ProcfsMetrics.java +++ b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/metrics/ProcfsMetrics.java @@ -20,11 +20,6 @@ import io.micrometer.core.instrument.Gauge; import io.micrometer.core.instrument.MeterRegistry; -/** - * 2022/3/1 - * - * @version 0.1.0 - */ public class ProcfsMetrics { public final static String PREFIX = "process_memory"; @@ -47,19 +42,20 @@ private static void registerMeters() { } private static void registerProcessGauge() { - Gauge.builder(PREFIX + ".rss.bytes", () -> smaps.getMetric(SystemMemoryStats.KEY.RSS)) - .register(registry); + Gauge.builder(PREFIX + ".rss.bytes", + () -> smaps.getMetric(SystemMemoryStats.MetricKey.RSS)).register(registry); - Gauge.builder(PREFIX + ".pss.bytes", () -> smaps.getMetric(SystemMemoryStats.KEY.PSS)) - .register(registry); + Gauge.builder(PREFIX + ".pss.bytes", + () -> smaps.getMetric(SystemMemoryStats.MetricKey.PSS)).register(registry); - Gauge.builder(PREFIX + ".vss.bytes", () -> smaps.getMetric(SystemMemoryStats.KEY.VSS)) - .register(registry); + Gauge.builder(PREFIX + ".vss.bytes", + () -> smaps.getMetric(SystemMemoryStats.MetricKey.VSS)).register(registry); - Gauge.builder(PREFIX + ".swap.bytes", () -> smaps.getMetric(SystemMemoryStats.KEY.SWAP)) - .register(registry); + Gauge.builder(PREFIX + ".swap.bytes", + () -> smaps.getMetric(SystemMemoryStats.MetricKey.SWAP)).register(registry); - Gauge.builder(PREFIX + ".swappss.bytes", () -> smaps.getMetric(SystemMemoryStats.KEY.SWAPPSS)) + Gauge.builder(PREFIX + ".swappss.bytes", + () -> smaps.getMetric(SystemMemoryStats.MetricKey.SWAPPSS)) .register(registry); } diff --git a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/metrics/ProcfsReader.java b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/metrics/ProcfsReader.java deleted file mode 100644 index b378244f9f..0000000000 --- a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/metrics/ProcfsReader.java +++ /dev/null @@ -1,142 +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 org.apache.hugegraph.store.node.metrics; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Objects; - -// TODO: refer license later, 90% match, maybe refer to metrics-jvm-extras (0.1.3) APL2.0 -class ProcfsReader { - - /* default */ static final long CACHE_DURATION_MS = 100; - private static final Map instances = new HashMap<>(); - private static final Object instancesLock = new Object(); - private static final Map> data = new HashMap<>(); - private static final Object dataLock = new Object(); - private static final Path BASE = Paths.get("/proc", "self"); - private final Path entryPath; - private final boolean osSupport; - /* default */ long lastReadTime = -1; - - private ProcfsReader(String entry) { - this(BASE, entry, false); - } - - /* default */ ProcfsReader(Path base, String entry) { - this(base, entry, true); - } - - private ProcfsReader(Path base, String entry, boolean forceOSSupport) { - Objects.requireNonNull(base); - Objects.requireNonNull(entry); - - this.entryPath = base.resolve(entry); - - this.osSupport = forceOSSupport - || System.getProperty("os.name").toLowerCase(Locale.ENGLISH) - .startsWith("linux"); - } - - /* default */ - static ProcfsReader getInstance(String entry) { - Objects.requireNonNull(entry); - - synchronized (instancesLock) { - ProcfsReader reader = instances.get(entry); - if (reader == null) { - reader = new ProcfsReader(entry); - instances.put(entry, reader); - } - return reader; - } - } - - /* default */ Path getEntryPath() { - return entryPath; - } - - /* default */ ReadResult read() throws IOException { - return read(currentTime()); - } - - /* default */ ReadResult read(long currentTimeMillis) throws IOException { - synchronized (dataLock) { - final Path key = getEntryPath().getFileName(); - - final ReadResult readResult; - if (lastReadTime == -1 || lastReadTime + CACHE_DURATION_MS < currentTimeMillis) { - final List lines = readPath(entryPath); - cacheResult(key, lines); - lastReadTime = currentTime(); - readResult = new ReadResult(lines, lastReadTime); - } else { - readResult = new ReadResult(data.get(key), lastReadTime); - } - return readResult; - } - } - - /* default */ List readPath(Path path) throws IOException { - Objects.requireNonNull(path); - - if (!osSupport) { - return Collections.emptyList(); - } - return Files.readAllLines(path); - } - - /* default */ void cacheResult(Path key, List lines) { - Objects.requireNonNull(key); - Objects.requireNonNull(lines); - - data.put(key, lines); - } - - /* default */ long currentTime() { - return System.currentTimeMillis(); - } - - /* default */ static class ReadResult { - - private final List lines; - - private final long readTime; - - /* default */ ReadResult(List lines, long readTime) { - this.lines = Objects.requireNonNull(lines); - this.readTime = readTime; - } - - public long getReadTime() { - return readTime; - } - - public List getLines() { - return lines; - } - - } - -} diff --git a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/metrics/SystemMemoryStats.java b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/metrics/SystemMemoryStats.java index 6cfd8fed21..f008e99259 100644 --- a/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/metrics/SystemMemoryStats.java +++ b/hugegraph-store/hg-store-node/src/main/java/org/apache/hugegraph/store/node/metrics/SystemMemoryStats.java @@ -29,10 +29,10 @@ public class SystemMemoryStats extends ProcfsRecord { private final Map metrics = new HashMap<>(); public SystemMemoryStats() { - super(ProcfsReader.getInstance("smaps")); + super(ProcFileHandler.getInstance("smaps")); } - /* default */ SystemMemoryStats(ProcfsReader reader) { + /* default */ SystemMemoryStats(ProcFileHandler reader) { super(reader); }