Commit 7eca329e authored by Matteo Melli's avatar Matteo Melli

Refactor to use serializer and UnsignerLong instead of BigInteger

parent da2b7502
/*
* 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 com.ongres.pgio.main;
import com.google.common.base.Charsets;
import java.io.FileInputStream;
import java.nio.file.Path;
import java.util.Scanner;
public class PostgresPidFileParser {
private final Path dataDir;
public PostgresPidFileParser(Path dataDir) {
this.dataDir = dataDir;
}
public int parse() throws Exception {
Path postmasterPid = dataDir.resolve("postmaster.pid");
try (Scanner scanner = new Scanner(
new FileInputStream(postmasterPid.toFile()),
Charsets.UTF_8.name())) {
if (scanner.hasNext()) {
String line = scanner.nextLine();
return Integer.parseInt(line);
}
}
throw new IllegalStateException("Error reading pid from file " + postmasterPid);
}
}
......@@ -19,35 +19,44 @@
package com.ongres.pgio.main.config;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.ongres.pgio.main.stats.ProcessGroupInfo;
import com.ongres.pgio.main.stats.groups.DefaultPostgresGroups;
import java.nio.file.Path;
import java.util.Optional;
public class Config {
private final Path dataDir;
private final long interval;
private final Optional<Integer> ppid;
private final boolean prometheusFormat;
private final boolean printHeader;
private final boolean noPrintHeader;
private final boolean showSystem;
private final boolean showOther;
private final Optional<ImmutableList<ProcessGroupInfo>> processGroups;
private Config(long interval, Optional<Integer> ppid,
private Config(Path dataDir, long interval, Optional<Integer> ppid,
boolean prometheusFormat,
boolean printHeader, boolean showSystem, boolean showOther,
boolean noPrintHeader, boolean showSystem, boolean showOther,
Optional<ImmutableList<ProcessGroupInfo>> processGroups) {
super();
this.dataDir = dataDir;
this.interval = interval;
this.ppid = ppid;
this.prometheusFormat = prometheusFormat;
this.printHeader = printHeader;
this.noPrintHeader = noPrintHeader;
this.showSystem = showSystem;
this.showOther = showOther;
this.processGroups = processGroups;
}
public Path getDataDir() {
return dataDir;
}
public long getInterval() {
return interval;
}
......@@ -60,8 +69,8 @@ public class Config {
return prometheusFormat;
}
public boolean isPrintHeader() {
return printHeader;
public boolean isNoPrintHeader() {
return noPrintHeader;
}
public boolean isShowOther() {
......@@ -77,13 +86,20 @@ public class Config {
}
public static class Builder {
private Path dataDir;
private long interval;
private Optional<Integer> ppid = Optional.empty();
private boolean prometheusFormat;
private boolean printHeader;
private boolean noPrintHeader;
private boolean showSystem;
private boolean showOther;
private Optional<ImmutableList<ProcessGroupInfo>> processGroups = Optional.empty();
private Optional<ImmutableList<ProcessGroupInfo>> processGroups =
Optional.of(DefaultPostgresGroups.GROUPS);
public Builder withDataDir(Path dataDir) {
this.dataDir = dataDir;
return this;
}
public Builder withInterval(long interval) {
this.interval = interval;
......@@ -100,8 +116,8 @@ public class Config {
return this;
}
public Builder withPrintHeader(boolean printHeader) {
this.printHeader = printHeader;
public Builder withNoPrintHeader(boolean noPrintHeader) {
this.noPrintHeader = noPrintHeader;
return this;
}
......@@ -120,9 +136,22 @@ public class Config {
return this;
}
public Builder appendProcessGroups(ImmutableList<ProcessGroupInfo> processGroups) {
this.processGroups = Optional.of(this.processGroups.map(currentProcessGroups -> ImmutableList
.<ProcessGroupInfo>builder()
.addAll(currentProcessGroups)
.addAll(processGroups)
.build())
.orElse(processGroups));
return this;
}
public Config build() {
return new Config(interval, ppid,
prometheusFormat, printHeader, showSystem, showOther,
Preconditions.checkArgument(dataDir != null,
"no database directory specified and environment variable PGDATA unset");
return new Config(dataDir, interval, ppid,
prometheusFormat, noPrintHeader, showSystem, showOther,
processGroups);
}
}
......
......@@ -18,19 +18,12 @@
*/
package com.ongres.pgio.main.stats;
import static com.ongres.pgio.main.stats.StatUtil.bigIntegerIfPresentOrZero;
import static com.ongres.pgio.main.stats.StatUtil.protectString;
import static com.ongres.pgio.main.stats.StatUtil.protectStringForPrometheus;
import com.google.common.primitives.UnsignedLong;
import com.google.common.collect.ImmutableMap;
import java.io.PrintStream;
import java.math.BigInteger;
import java.time.Instant;
import java.util.Map;
import java.util.Optional;
public class GroupStat {
public class GroupStat implements IoStat {
private final GroupInfo group;
private final ProcessGroupStat stat;
......@@ -53,23 +46,43 @@ public class GroupStat {
return stat.getTimestamp();
}
public Optional<BigInteger> getRchar() {
@Override
public String getLabel() {
return group.getName();
}
@Override
public Optional<Integer> getPid() {
return Optional.empty();
}
@Override
public Optional<Integer> getPpid() {
return Optional.empty();
}
@Override
public Optional<UnsignedLong> getRchar() {
return stat.getRchar();
}
public Optional<BigInteger> getWchar() {
@Override
public Optional<UnsignedLong> getWchar() {
return stat.getWchar();
}
public Optional<BigInteger> getReadBytes() {
@Override
public Optional<UnsignedLong> getReadBytes() {
return stat.getReadBytes();
}
public Optional<BigInteger> getWriteBytes() {
@Override
public Optional<UnsignedLong> getWriteBytes() {
return stat.getWriteBytes();
}
public Optional<BigInteger> getCancelledWriteBytes() {
@Override
public Optional<UnsignedLong> getCancelledWriteBytes() {
return stat.getCancelledWriteBytes();
}
......@@ -77,47 +90,4 @@ public class GroupStat {
public String toString() {
return "GroupStat [group=" + group + ", stat=" + stat + "]";
}
public void serialize(PrintStream out) {
out.print(getTimestamp());
out.print(',');
out.print(',');
out.print(',');
out.print(protectString(group.getName()));
out.print(',');
out.print(bigIntegerIfPresentOrZero(getRchar()));
out.print(',');
out.print(bigIntegerIfPresentOrZero(getWchar()));
out.print(',');
out.print(bigIntegerIfPresentOrZero(getReadBytes()));
out.print(',');
out.print(bigIntegerIfPresentOrZero(getWriteBytes()));
out.print(',');
out.print(bigIntegerIfPresentOrZero(getCancelledWriteBytes()));
out.println();
}
public void serializeForPrometheus(PrintStream out) {
for (Map.Entry<String, BigInteger> entry : ImmutableMap.of(
"rchar", bigIntegerIfPresentOrZero(getRchar()),
"wchar", bigIntegerIfPresentOrZero(getWchar()),
"read_bytes", bigIntegerIfPresentOrZero(getReadBytes()),
"write_bytes", bigIntegerIfPresentOrZero(getWriteBytes()),
"cancelled_write_bytes", bigIntegerIfPresentOrZero(getCancelledWriteBytes())
).entrySet()) {
String label = entry.getKey();
BigInteger value = entry.getValue();
out.print("# TYPE ");
out.print(label);
out.println(" gauge");
out.print(label);
out.print(" { label=");
out.print(protectStringForPrometheus(group.getName()));
out.print(" } ");
out.print(value);
out.print(" [");
out.print(getTimestamp().toEpochMilli());
out.println(']');
}
}
}
/*
* 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 com.ongres.pgio.main.stats;
import com.google.common.primitives.UnsignedLong;
import com.ongres.pgio.main.stats.serializer.StatSerializer;
import java.time.Instant;
import java.util.Optional;
public interface IoStat {
public Instant getTimestamp();
public String getLabel();
public Optional<Integer> getPid();
public Optional<Integer> getPpid();
public Optional<UnsignedLong> getRchar();
public Optional<UnsignedLong> getWchar();
public Optional<UnsignedLong> getReadBytes();
public Optional<UnsignedLong> getWriteBytes();
public Optional<UnsignedLong> getCancelledWriteBytes();
public default void serialize(StatSerializer serializer) {
serializer.serialize(this);
}
}
......@@ -18,17 +18,12 @@
*/
package com.ongres.pgio.main.stats;
import static com.ongres.pgio.main.stats.StatUtil.bigIntegerIfPresentOrZero;
import com.google.common.primitives.UnsignedLong;
import com.google.common.collect.ImmutableMap;
import java.io.PrintStream;
import java.math.BigInteger;
import java.time.Instant;
import java.util.Map;
import java.util.Optional;
public class OtherStat {
public class OtherStat implements IoStat {
private final SystemStat systemStat;
private final ProcessStatAccumulator processStatAccumulator;
......@@ -39,57 +34,50 @@ public class OtherStat {
this.processStatAccumulator = processStatAccumulator;
}
@Override
public Instant getTimestamp() {
return systemStat.getTimestamp();
}
public Optional<BigInteger> getReadBytes() {
return systemStat.getReadBytes().map(readBytes -> readBytes
.subtract(processStatAccumulator.getReadBytes()).max(BigInteger.ZERO));
@Override
public String getLabel() {
return "<other>";
}
@Override
public Optional<Integer> getPid() {
return Optional.empty();
}
@Override
public Optional<Integer> getPpid() {
return Optional.empty();
}
@Override
public Optional<UnsignedLong> getRchar() {
return Optional.empty();
}
@Override
public Optional<UnsignedLong> getWchar() {
return Optional.empty();
}
public Optional<BigInteger> getWriteBytes() {
return systemStat.getWriteBytes().map(writeBytes -> writeBytes
.subtract(processStatAccumulator.getWriteBytes()).max(BigInteger.ZERO));
@Override
public Optional<UnsignedLong> getReadBytes() {
return systemStat.getReadBytes().map(readBytes -> StatUtil
.subtract(readBytes, processStatAccumulator.getReadBytes()));
}
public void serialize(PrintStream out) {
out.print(systemStat.getTimestamp());
out.print(',');
out.print("");
out.print(',');
out.print("");
out.print(',');
out.print("<other>");
out.print(',');
out.print('0');
out.print(',');
out.print('0');
out.print(',');
out.print(bigIntegerIfPresentOrZero(getReadBytes()));
out.print(',');
out.print(bigIntegerIfPresentOrZero(getWriteBytes()));
out.print(',');
out.print('0');
out.println();
@Override
public Optional<UnsignedLong> getWriteBytes() {
return systemStat.getWriteBytes().map(writeBytes -> StatUtil
.subtract(writeBytes, processStatAccumulator.getWriteBytes()));
}
public void serializeForPrometheus(PrintStream out) {
for (Map.Entry<String, BigInteger> entry : ImmutableMap.of(
"read_bytes", bigIntegerIfPresentOrZero(getReadBytes()),
"write_bytes", bigIntegerIfPresentOrZero(getWriteBytes())
).entrySet()) {
String label = entry.getKey();
BigInteger value = entry.getValue();
out.print("# TYPE ");
out.print(label);
out.println(" gauge");
out.print(label);
out.print(" { label=<other> } ");
out.print(value);
out.print(" [");
out.print(getTimestamp().toEpochMilli());
out.println(']');
}
@Override
public Optional<UnsignedLong> getCancelledWriteBytes() {
return Optional.empty();
}
}
......@@ -19,8 +19,8 @@
package com.ongres.pgio.main.stats;
import com.google.common.collect.ImmutableList;
import com.google.common.primitives.UnsignedLong;
import java.math.BigInteger;
import java.time.Instant;
import java.util.Optional;
import java.util.function.Function;
......@@ -39,32 +39,32 @@ public class ProcessGroupStat {
return timestamp;
}
public Optional<BigInteger> getRchar() {
public Optional<UnsignedLong> getRchar() {
return reduceFromStats(stat -> stat.getRchar());
}
public Optional<BigInteger> getWchar() {
public Optional<UnsignedLong> getWchar() {
return reduceFromStats(stat -> stat.getWchar());
}
public Optional<BigInteger> getReadBytes() {
public Optional<UnsignedLong> getReadBytes() {
return reduceFromStats(stat -> stat.getReadBytes());
}
public Optional<BigInteger> getWriteBytes() {
public Optional<UnsignedLong> getWriteBytes() {
return reduceFromStats(stat -> stat.getWriteBytes());
}
public Optional<BigInteger> getCancelledWriteBytes() {
public Optional<UnsignedLong> getCancelledWriteBytes() {
return reduceFromStats(stat -> stat.getCancelledWriteBytes());
}
private Optional<BigInteger> reduceFromStats(
Function<ProcessStat, Optional<BigInteger>> valueSupplier) {
private Optional<UnsignedLong> reduceFromStats(
Function<ProcessStat, Optional<UnsignedLong>> valueSupplier) {
return stats.stream()
.reduce(Optional.<BigInteger>empty(),
.reduce(Optional.<UnsignedLong>empty(),
(result, stat) -> valueSupplier.apply(stat)
.map(value -> result.orElse(BigInteger.ZERO).add(value)),
.map(value -> result.orElse(UnsignedLong.ZERO).plus(value)),
(u, v) -> v);
}
......
......@@ -19,20 +19,20 @@
package com.ongres.pgio.main.stats;
import com.google.common.base.Preconditions;
import com.google.common.primitives.UnsignedLong;
import java.math.BigInteger;
import java.time.Instant;
public class ProcessIo {
private final Instant timestamp;
private final BigInteger rchar;
private final BigInteger wchar;
private final BigInteger readBytes;
private final BigInteger writeBytes;
private final BigInteger cancelledWriteBytes;
private final UnsignedLong rchar;
private final UnsignedLong wchar;
private final UnsignedLong readBytes;
private final UnsignedLong writeBytes;
private final UnsignedLong cancelledWriteBytes;
private ProcessIo(Instant timestamp, BigInteger rchar, BigInteger wchar,
BigInteger readBytes, BigInteger writeBytes, BigInteger cancelledWriteBytes) {
private ProcessIo(Instant timestamp, UnsignedLong rchar, UnsignedLong wchar,
UnsignedLong readBytes, UnsignedLong writeBytes, UnsignedLong cancelledWriteBytes) {
super();
this.timestamp = timestamp;
this.rchar = rchar;
......@@ -46,23 +46,23 @@ public class ProcessIo {
return timestamp;
}
public BigInteger getRchar() {
public UnsignedLong getRchar() {
return rchar;
}
public BigInteger getWchar() {
public UnsignedLong getWchar() {
return wchar;
}
public BigInteger getReadBytes() {
public UnsignedLong getReadBytes() {
return readBytes;
}
public BigInteger getWriteBytes() {
public UnsignedLong getWriteBytes() {
return writeBytes;
}
public BigInteger getCancelledWriteBytes() {
public UnsignedLong getCancelledWriteBytes() {
return cancelledWriteBytes;
}
......@@ -75,43 +75,34 @@ public class ProcessIo {
public static class Builder {
private final Instant timestamp = Instant.now();
private BigInteger rchar;
private BigInteger wchar;
private BigInteger readBytes;
private BigInteger writeBytes;
private BigInteger cancelledWriteBytes;
private UnsignedLong rchar;
private UnsignedLong wchar;
private UnsignedLong readBytes;
private UnsignedLong writeBytes;
private UnsignedLong cancelledWriteBytes;
public Builder withRchar(String rchar) {
this.rchar = new BigInteger(rchar);
this.rchar = UnsignedLong.valueOf(rchar);
return this;
}
public Builder withWchar(String wchar) {
this.wchar = new BigInteger(wchar);
this.wchar = UnsignedLong.valueOf(wchar);
return this;
}
public Builder withReadBytes(String readBytes) {
this.readBytes = new BigInteger(readBytes);
this.readBytes = UnsignedLong.valueOf(readBytes);
return this;
}
public Builder withWriteBytes(String writeBytes) {
this.writeBytes = new BigInteger(writeBytes);
this.writeBytes = UnsignedLong.valueOf(writeBytes);
return this;
}
public Builder withCancelledWriteBytes(String cancelledWriteBytes) {
this.cancelledWriteBytes = new BigInteger(cancelledWriteBytes);
return this;
}
public Builder fromAccumulator(ProcessStatAccumulator processIoAccumulator) {
this.rchar = BigInteger.ZERO;
this.wchar = BigInteger.ZERO;
this.readBytes = processIoAccumulator.getReadBytes();
this.writeBytes = processIoAccumulator.getWriteBytes();
this.cancelledWriteBytes = BigInteger.ZERO;
this.cancelledWriteBytes = UnsignedLong.valueOf(cancelledWriteBytes);
return this;
}
......
......@@ -18,21 +18,14 @@
*/
package com.ongres.pgio.main.stats;
import static com.ongres.pgio.main.stats.StatUtil.bigIntegerIfPresentOrZero;
import static com.ongres.pgio.main.stats.StatUtil.difference;
import static com.ongres.pgio.main.stats.StatUtil.protectString;
import static com.ongres.pgio.main.stats.StatUtil.protectStringForPrometheus;
import static com.ongres.pgio.main.stats.StatUtil.stringIfPresentOrEmpty;
import com.google.common.collect.ImmutableMap;
import com.google.common.primitives.UnsignedLong;
import java.io.PrintStream;
import java.math.BigInteger;
import java.time.Instant;
import java.util.Map;
import java.util.Optional;
public class ProcessStat {
public class ProcessStat implements IoStat {
private final ProcessInfo info;
private final ProcessIo currentIo;
......@@ -64,31 +57,52 @@ public class ProcessStat {
return previousIo;
}
@Override
public String getLabel() {
return info.getLabel();
}
@Override
public Optional<Integer> getPid() {
return Optional.of(info.getPid());
}
@Override
public Optional<Integer> getPpid() {
return info.getPpid();
}
@Override
public Instant getTimestamp() {
return currentIo.getTimestamp();
}
public Optional<BigInteger> getRchar() {
@Override
public Optional<UnsignedLong> getRchar() {
return previousIo
.map(previousIo -> difference(currentIo.getRchar(), previousIo.getRchar()));
}
public Optional<BigInteger> getWchar() {
@Override
public Optional<UnsignedLong> getWchar() {
return previousIo
.map(previousIo -> difference(currentIo.getWchar(), previousIo.getWchar()));
}
public Optional<BigInteger> getReadBytes() {
@Override
public Optional<UnsignedLong> getReadBytes() {
return previousIo
.map(previousIo -> difference(currentIo.getReadBytes(), previousIo.getReadBytes()));
}
public Optional<BigInteger> getWriteBytes() {
@Override
public Optional<UnsignedLong> getWriteBytes() {
return previousIo
.map(previousIo -> difference(currentIo.getWriteBytes(), previousIo.getWriteBytes()));
}