mirror of https://github.com/rusefi/rusefi-1.git
heartbeat log, json age
This commit is contained in:
parent
977a0d2ea4
commit
ebdd6eeb19
|
@ -10,6 +10,7 @@ public class ApplicationConnectionState {
|
||||||
@NotNull
|
@NotNull
|
||||||
private final IoStream clientStream;
|
private final IoStream clientStream;
|
||||||
private final ControllerConnectionState state;
|
private final ControllerConnectionState state;
|
||||||
|
private final Birthday birthday = new Birthday();
|
||||||
|
|
||||||
public ApplicationConnectionState(UserDetails userDetails, IoStream clientStream, ControllerConnectionState state) {
|
public ApplicationConnectionState(UserDetails userDetails, IoStream clientStream, ControllerConnectionState state) {
|
||||||
this.userDetails = Objects.requireNonNull(userDetails, "userDetails");
|
this.userDetails = Objects.requireNonNull(userDetails, "userDetails");
|
||||||
|
@ -31,6 +32,10 @@ public class ApplicationConnectionState {
|
||||||
return userDetails;
|
return userDetails;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Birthday getBirthday() {
|
||||||
|
return birthday;
|
||||||
|
}
|
||||||
|
|
||||||
public void close() {
|
public void close() {
|
||||||
try {
|
try {
|
||||||
clientStream.close();
|
clientStream.close();
|
||||||
|
|
|
@ -34,8 +34,10 @@ import static com.devexperts.logging.Logging.getLogging;
|
||||||
import static com.rusefi.Timeouts.SECOND;
|
import static com.rusefi.Timeouts.SECOND;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See NetworkConnectorStartup
|
* See NetworkConnectorStartup - NetworkConnector connects an ECU to this backend
|
||||||
*
|
*
|
||||||
|
* @see ControllerConnectionState ECU session
|
||||||
|
* @see ApplicationConnectionState tuning application session
|
||||||
* @see BackendLauncher
|
* @see BackendLauncher
|
||||||
*/
|
*/
|
||||||
public class Backend implements Closeable {
|
public class Backend implements Closeable {
|
||||||
|
@ -51,6 +53,7 @@ public class Backend implements Closeable {
|
||||||
* @see BinaryProtocolProxy#USER_IO_TIMEOUT
|
* @see BinaryProtocolProxy#USER_IO_TIMEOUT
|
||||||
*/
|
*/
|
||||||
private static final int APPLICATION_INACTIVITY_TIMEOUT = 3 * Timeouts.MINUTE;
|
private static final int APPLICATION_INACTIVITY_TIMEOUT = 3 * Timeouts.MINUTE;
|
||||||
|
static final String AGE = "age";
|
||||||
|
|
||||||
private final FkRegex showOnlineControllers = new FkRegex(ProxyClient.LIST_CONTROLLERS_PATH,
|
private final FkRegex showOnlineControllers = new FkRegex(ProxyClient.LIST_CONTROLLERS_PATH,
|
||||||
(Take) req -> getControllersOnline()
|
(Take) req -> getControllersOnline()
|
||||||
|
@ -261,6 +264,7 @@ public class Backend implements Closeable {
|
||||||
JsonObject applicationObject = Json.createObjectBuilder()
|
JsonObject applicationObject = Json.createObjectBuilder()
|
||||||
.add(UserDetails.USER_ID, application.getUserDetails().getUserId())
|
.add(UserDetails.USER_ID, application.getUserDetails().getUserId())
|
||||||
.add(UserDetails.USERNAME, application.getUserDetails().getUserName())
|
.add(UserDetails.USERNAME, application.getUserDetails().getUserName())
|
||||||
|
.add(AGE, application.getBirthday().getDuration())
|
||||||
.add(MAX_PACKET_GAP, application.getClientStream().getStreamStats().getMaxPacketGap())
|
.add(MAX_PACKET_GAP, application.getClientStream().getStreamStats().getMaxPacketGap())
|
||||||
.build();
|
.build();
|
||||||
builder.add(applicationObject);
|
builder.add(applicationObject);
|
||||||
|
@ -281,6 +285,7 @@ public class Backend implements Closeable {
|
||||||
JsonObjectBuilder objectBuilder = Json.createObjectBuilder()
|
JsonObjectBuilder objectBuilder = Json.createObjectBuilder()
|
||||||
.add(UserDetails.USER_ID, client.getUserDetails().getUserId())
|
.add(UserDetails.USER_ID, client.getUserDetails().getUserId())
|
||||||
.add(UserDetails.USERNAME, client.getUserDetails().getUserName())
|
.add(UserDetails.USERNAME, client.getUserDetails().getUserName())
|
||||||
|
.add(AGE, client.getBirthday().getDuration())
|
||||||
.add(ProxyClient.IS_USED, client.getTwoKindSemaphore().isUsed())
|
.add(ProxyClient.IS_USED, client.getTwoKindSemaphore().isUsed())
|
||||||
.add(ControllerStateDetails.RPM, rpm)
|
.add(ControllerStateDetails.RPM, rpm)
|
||||||
.add(ControllerStateDetails.CLT, clt)
|
.add(ControllerStateDetails.CLT, clt)
|
||||||
|
@ -351,6 +356,10 @@ public class Backend implements Closeable {
|
||||||
isClosed = true;
|
isClosed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isClosed() {
|
||||||
|
return isClosed;
|
||||||
|
}
|
||||||
|
|
||||||
public List<ControllerConnectionState> getControllers() {
|
public List<ControllerConnectionState> getControllers() {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
return new ArrayList<>(controllers);
|
return new ArrayList<>(controllers);
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
package com.rusefi.server;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
|
||||||
|
public class Birthday {
|
||||||
|
private final long createAt = System.currentTimeMillis();
|
||||||
|
|
||||||
|
public String getDuration() {
|
||||||
|
return humanReadableFormat(System.currentTimeMillis() - createAt);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
static String humanReadableFormat(long millis) {
|
||||||
|
return humanReadableFormat(Duration.ofMillis(millis));
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
static String humanReadableFormat(Duration duration) {
|
||||||
|
return duration.toString()
|
||||||
|
.substring(2)
|
||||||
|
.replaceAll("(\\d[HMS])(?!$)", "$1 ")
|
||||||
|
.toLowerCase();
|
||||||
|
}
|
||||||
|
}
|
|
@ -36,6 +36,7 @@ public class ControllerConnectionState {
|
||||||
|
|
||||||
private final TwoKindSemaphore twoKindSemaphore = new TwoKindSemaphore();
|
private final TwoKindSemaphore twoKindSemaphore = new TwoKindSemaphore();
|
||||||
private final SensorsHolder sensorsHolder = new SensorsHolder();
|
private final SensorsHolder sensorsHolder = new SensorsHolder();
|
||||||
|
private final Birthday birthday = new Birthday();
|
||||||
|
|
||||||
public ControllerConnectionState(Socket clientSocket, UserDetailsResolver userDetailsResolver) {
|
public ControllerConnectionState(Socket clientSocket, UserDetailsResolver userDetailsResolver) {
|
||||||
this.clientSocket = clientSocket;
|
this.clientSocket = clientSocket;
|
||||||
|
@ -48,6 +49,10 @@ public class ControllerConnectionState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Birthday getBirthday() {
|
||||||
|
return birthday;
|
||||||
|
}
|
||||||
|
|
||||||
public IoStream getStream() {
|
public IoStream getStream() {
|
||||||
return stream;
|
return stream;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.rusefi.server;
|
package com.rusefi.server;
|
||||||
|
|
||||||
|
import com.devexperts.logging.Logging;
|
||||||
import com.rusefi.rusEFIVersion;
|
import com.rusefi.rusEFIVersion;
|
||||||
import com.rusefi.tools.online.ProxyClient;
|
import com.rusefi.tools.online.ProxyClient;
|
||||||
import org.takes.Take;
|
import org.takes.Take;
|
||||||
|
@ -13,15 +14,22 @@ import java.lang.management.ManagementFactory;
|
||||||
import java.lang.management.OperatingSystemMXBean;
|
import java.lang.management.OperatingSystemMXBean;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
|
import static com.rusefi.Timeouts.SECOND;
|
||||||
|
import static com.rusefi.binaryprotocol.BinaryProtocol.sleep;
|
||||||
|
|
||||||
public class Monitoring {
|
public class Monitoring {
|
||||||
public static final String STATUS = "/status";
|
public static final String STATUS = "/status";
|
||||||
|
private static final Logging log = Logging.getLogging(Monitoring.class);
|
||||||
|
private static final int PERIOD = 10 * SECOND;
|
||||||
final FkRegex showStatistics;
|
final FkRegex showStatistics;
|
||||||
private final Backend backend;
|
private final Backend backend;
|
||||||
|
|
||||||
|
private final Birthday birthday = new Birthday();
|
||||||
|
|
||||||
public Monitoring(Backend backend) {
|
public Monitoring(Backend backend) {
|
||||||
this.backend = backend;
|
this.backend = backend;
|
||||||
showStatistics = new FkRegex(STATUS,
|
showStatistics = new FkRegex(STATUS, (Take) req -> getStatus());
|
||||||
(Take) req -> getStatus());
|
startHeartbeatThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String formatSize(long v) {
|
private static String formatSize(long v) {
|
||||||
|
@ -30,6 +38,26 @@ public class Monitoring {
|
||||||
return String.format("%.1f %sB", (double) v / (1L << (z * 10)), " KMGTPE".charAt(z));
|
return String.format("%.1f %sB", (double) v / (1L << (z * 10)), " KMGTPE".charAt(z));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void startHeartbeatThread() {
|
||||||
|
new Thread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
while (!backend.isClosed()) {
|
||||||
|
writeLogEntry();
|
||||||
|
sleep(PERIOD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, "heartbeat").start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeLogEntry() {
|
||||||
|
OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.getOperatingSystemMXBean();
|
||||||
|
log.info("cpu=" + operatingSystemMXBean.getSystemLoadAverage() +
|
||||||
|
",free=" + Runtime.getRuntime().freeMemory() +
|
||||||
|
",sessions=" + Backend.totalSessions.get() +
|
||||||
|
",threads=" + Thread.getAllStackTraces().size());
|
||||||
|
}
|
||||||
|
|
||||||
private RsJson getStatus() throws IOException {
|
private RsJson getStatus() throws IOException {
|
||||||
JsonObjectBuilder builder = Json.createObjectBuilder();
|
JsonObjectBuilder builder = Json.createObjectBuilder();
|
||||||
OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.getOperatingSystemMXBean();
|
OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.getOperatingSystemMXBean();
|
||||||
|
@ -46,6 +74,7 @@ public class Monitoring {
|
||||||
builder.add("framework version", rusEFIVersion.CONSOLE_VERSION);
|
builder.add("framework version", rusEFIVersion.CONSOLE_VERSION);
|
||||||
builder.add("compiled", new Date(rusEFIVersion.classBuildTimeMillis()).toString());
|
builder.add("compiled", new Date(rusEFIVersion.classBuildTimeMillis()).toString());
|
||||||
builder.add("now", System.currentTimeMillis());
|
builder.add("now", System.currentTimeMillis());
|
||||||
|
builder.add(Backend.AGE, birthday.getDuration());
|
||||||
|
|
||||||
return new RsJson(builder.build());
|
return new RsJson(builder.build());
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
package com.rusefi.server;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static com.rusefi.Timeouts.MINUTE;
|
||||||
|
import static com.rusefi.Timeouts.SECOND;
|
||||||
|
import static com.rusefi.server.Birthday.humanReadableFormat;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
public class BirthdayTest {
|
||||||
|
@Test
|
||||||
|
public void testDurationString() {
|
||||||
|
assertEquals("1s", humanReadableFormat(SECOND));
|
||||||
|
assertEquals("1m", humanReadableFormat(MINUTE));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue