package org.argeo.slc.systemd.dbus; import static java.lang.System.Logger.Level.DEBUG; import static java.lang.System.Logger.Level.INFO; import static java.lang.System.Logger.Level.WARNING; import java.io.IOException; import java.io.Writer; import java.lang.System.Logger; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.time.Instant; import java.time.ZoneOffset; import java.time.format.DateTimeFormatter; import org.argeo.cms.util.CsvWriter; import org.freedesktop.dbus.exceptions.DBusException; import de.thjom.java.systemd.Manager; import de.thjom.java.systemd.Service; import de.thjom.java.systemd.Systemd; import de.thjom.java.systemd.types.UnitType; /** Gathers statistics about the runnign process, if it is a systemd unit. */ public class ServiceStatistics { private final static Logger logger = System.getLogger(ServiceStatistics.class.getName()); private Manager manager; private String unitName; private Service service; private long frequency = 60 * 1000; public void start() { final long pid = ProcessHandle.current().pid(); try { manager = Systemd.get().getManager(); // find own service for (UnitType unitType : manager.listUnits()) { if (unitType.isService()) { Service s = manager.getService(unitType.getUnitName()); if (s.getMainPID() == pid) { service = s; unitName = unitType.getUnitName(); logger.log(INFO, "Systemd service found for pid " + pid + ": " + unitName); } } } } catch (DBusException e) { logger.log(WARNING, "Cannot connect to systemd", e); } if (service == null) { logger.log(DEBUG, () -> "No systemd service found for pid " + pid + ", disconnecting from DBus..."); manager = null; Systemd.disconnect(); } else { // start collecting collectStatistics(); } } public void stop() { if (manager != null) { Systemd.disconnect(); manager = null; notifyAll(); } } protected void collectStatistics() { // standard systemd property String logsDirectory = System.getenv("LOGS_DIRECTORY"); if (logsDirectory == null) { logsDirectory = System.getProperty("user.dir"); } // MainPID,CPUUsageNSec,MemoryCurrent,IPIngressBytes,IPEgressBytes,IOReadBytes,IOWriteBytes,TasksCurrent Path basePath = Paths.get(logsDirectory); logger.log(DEBUG, () -> "Writing statistics for " + unitName + " to " + basePath); try { while (manager != null) { String dateSuffix = Instant.now().atOffset(ZoneOffset.UTC).format(DateTimeFormatter.ISO_LOCAL_DATE); Path csvPath = basePath.resolve("statistics-" + unitName + "-" + dateSuffix + ".csv"); boolean writeHeader = !Files.exists(csvPath); try (Writer writer = Files.newBufferedWriter(csvPath, StandardCharsets.UTF_8, StandardOpenOption.APPEND)) { CsvWriter csvWriter = new CsvWriter(writer); if (writeHeader)// header csvWriter.writeLine("CurrentTimeMillis", "CPUUsageNSec", "MemoryCurrent", "IPIngressBytes", "IPEgressBytes", "IOReadBytes", "IOWriteBytes", "TasksCurrent"); // TODO better synchronise with stop csvWriter.writeLine(System.currentTimeMillis(), service.getCPUUsageNSec(), service.getMemoryCurrent(), service.getIPIngressBytes(), service.getIPEgressBytes(), service.getIOReadBytes(), service.getIOWriteBytes(), service.getTasksCurrent()); } Thread.sleep(frequency); } } catch (IOException e) { throw new IllegalStateException("Cannot collect statistics", e); } catch (InterruptedException e) { logger.log(WARNING, "Statistics collection interrupted for " + unitName); } } public static void main(String[] args) throws Exception { try { Systemd systemd = Systemd.get(); Service service = systemd.getManager().getService("ipsec.service"); System.out.println(service.getCPUUsageNSec()); for (UnitType unitType : systemd.getManager().listUnits()) { if (unitType.isService()) { System.out.println(unitType.getUnitName()); } } } finally { Systemd.disconnect(); } } }