diff --git a/scripts/version/versioned_files.json b/scripts/version/versioned_files.json index 6a8928cd..3cc0c8aa 100644 --- a/scripts/version/versioned_files.json +++ b/scripts/version/versioned_files.json @@ -13,4 +13,4 @@ "path": "/src/main/resources/config/application.yml" } ] -} \ No newline at end of file +} diff --git a/src/main/java/org/assimbly/gateway/service/HealthService.java b/src/main/java/org/assimbly/gateway/service/HealthService.java new file mode 100644 index 00000000..eb7b27f1 --- /dev/null +++ b/src/main/java/org/assimbly/gateway/service/HealthService.java @@ -0,0 +1,24 @@ +package org.assimbly.gateway.service; + +/** + * Service Interface for managing Integration. + */ +public interface HealthService { + + /** + * Convert double size to long Kb + * + * @param var1 the value to convert + * @return Kb + */ + long convertSizeToKb(double var1); + + /** + * Invoke system method + * + * @param methodName to invoke + * @return object with method call response + */ + Object invokeMethod(String methodName); + +} diff --git a/src/main/java/org/assimbly/gateway/service/impl/HealthServiceImpl.java b/src/main/java/org/assimbly/gateway/service/impl/HealthServiceImpl.java new file mode 100644 index 00000000..a2ac1993 --- /dev/null +++ b/src/main/java/org/assimbly/gateway/service/impl/HealthServiceImpl.java @@ -0,0 +1,56 @@ +package org.assimbly.gateway.service.impl; + +import org.assimbly.gateway.service.HealthService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.lang.management.ManagementFactory; +import java.lang.management.OperatingSystemMXBean; + +/** + * Service Implementation for managing Integration. + */ +@Service +@Transactional +public class HealthServiceImpl implements HealthService { + + private final Logger log = LoggerFactory.getLogger(getClass()); + + private final OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.getOperatingSystemMXBean(); + + public HealthServiceImpl() { + // + } + + /** + * Convert double size to long Kb + * + * @param size the value to convert + * @return Kb + */ + @Override + public long convertSizeToKb(double size) { + return (long) (size / 1024); + } + + /** + * Invoke system method + * + * @param methodName to invoke + * @return object with method call response + */ + @Override + public Object invokeMethod(String methodName) { + try { + Class unixOS = Class.forName("com.sun.management.UnixOperatingSystemMXBean"); + + if (unixOS.isInstance(operatingSystemMXBean)) + return unixOS.getMethod(methodName).invoke(operatingSystemMXBean); + + } catch (Throwable ignored) { } + + return "Unknown"; + } +} diff --git a/src/main/java/org/assimbly/gateway/service/response/BackendResponse.java b/src/main/java/org/assimbly/gateway/service/response/BackendResponse.java new file mode 100644 index 00000000..c6a181ea --- /dev/null +++ b/src/main/java/org/assimbly/gateway/service/response/BackendResponse.java @@ -0,0 +1,43 @@ +package org.assimbly.gateway.service.response; + +import java.util.HashMap; +import java.util.Map; + +public class BackendResponse { + + private Map jvm = new HashMap<>(); + private Map memory = new HashMap<>(); + private Map threads = new HashMap<>(); + + public Map getMemory() { + return memory; + } + public void setMemory(Map memory) { + this.memory = memory; + } + public void addMemory(String key, Long value) { + this.memory.put(key, value); + } + + public Map getThreads() { + return threads; + } + public void setThreads(Map threads) { + this.threads = threads; + } + public void addThread(String key, Integer value) { + this.threads.put(key, value); + } + + public Map getJvm() { + return jvm; + } + public void setJvm(Map jvm) { + this.jvm = jvm; + } + public void addJvm(String key, Object value) { + this.jvm.put(key, value); + } + + +} diff --git a/src/main/java/org/assimbly/gateway/web/rest/broker/HealthBrokerResource.java b/src/main/java/org/assimbly/gateway/web/rest/broker/HealthBrokerResource.java new file mode 100644 index 00000000..2cd65b7a --- /dev/null +++ b/src/main/java/org/assimbly/gateway/web/rest/broker/HealthBrokerResource.java @@ -0,0 +1,62 @@ +package org.assimbly.gateway.web.rest.broker; + +import com.fasterxml.jackson.databind.ObjectMapper; +import io.swagger.v3.oas.annotations.Parameter; +import org.assimbly.brokerrest.ManagedBrokerRuntime; +import org.assimbly.gateway.service.HealthService; +import org.assimbly.util.rest.ResponseUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.actuate.audit.AuditEvent; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.io.ByteArrayOutputStream; +import java.nio.charset.StandardCharsets; +import java.util.Map; + +/** + * REST controller for getting the {@link AuditEvent}s. + */ +@RestController +@RequestMapping("/health") +public class HealthBrokerResource { + + protected Logger log = LoggerFactory.getLogger(getClass()); + + public HealthBrokerResource(HealthService healthService) { } + + @Autowired + private ManagedBrokerRuntime managedBroker; + + private boolean plainResponse; + + @GetMapping( + path = "/broker", + produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE, MediaType.TEXT_PLAIN_VALUE} + ) + public ResponseEntity getBrokerStats(@Parameter(hidden = true) @RequestHeader("Accept") String mediaType) throws Exception { + + plainResponse = true; + long connectorId = 1; + + try { + final ByteArrayOutputStream out = new ByteArrayOutputStream(); + final ObjectMapper mapper = new ObjectMapper(); + + Map statsMap = managedBroker.getStats("classic"); + + mapper.writeValue(out, statsMap); + + return ResponseUtil.createSuccessResponse(connectorId, mediaType, "/health/broker", out.toString(StandardCharsets.UTF_8), plainResponse); + } catch (Exception e) { + log.error("Get broker failed",e); + return ResponseUtil.createFailureResponse(connectorId, mediaType,"/health/broker",e.getMessage()); + } + } +} diff --git a/src/main/java/org/assimbly/gateway/web/rest/integration/HealthIntegrationResource.java b/src/main/java/org/assimbly/gateway/web/rest/integration/HealthIntegrationResource.java new file mode 100644 index 00000000..5578b2f4 --- /dev/null +++ b/src/main/java/org/assimbly/gateway/web/rest/integration/HealthIntegrationResource.java @@ -0,0 +1,102 @@ +package org.assimbly.gateway.web.rest.integration; + +import com.fasterxml.jackson.databind.ObjectMapper; +import io.swagger.v3.oas.annotations.Parameter; +import org.assimbly.gateway.service.HealthService; +import org.assimbly.gateway.service.response.BackendResponse; +import org.assimbly.integration.Integration; +import org.assimbly.integrationrest.IntegrationRuntime; +import org.assimbly.util.rest.ResponseUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.actuate.audit.AuditEvent; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.io.ByteArrayOutputStream; +import java.lang.management.ManagementFactory; +import java.lang.management.MemoryUsage; +import java.lang.management.ThreadMXBean; +import java.nio.charset.StandardCharsets; + +/** + * REST controller for getting the {@link AuditEvent}s. + */ +@RestController +@RequestMapping("/health") +public class HealthIntegrationResource { + + protected Logger log = LoggerFactory.getLogger(getClass()); + + private final HealthService healthService; + + public HealthIntegrationResource(HealthService healthService) { + this.healthService = healthService; + } + + @Autowired + private IntegrationRuntime integrationRuntime; + + private Integration integration; + + private boolean plainResponse; + + @GetMapping( + path = "/jvm", + produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE, MediaType.TEXT_PLAIN_VALUE} + ) + public ResponseEntity getJvmStats(@Parameter(hidden = true) @RequestHeader("Accept") String mediaType) throws Exception { + + plainResponse = true; + long connectorId = 1; + + try { + final ByteArrayOutputStream out = new ByteArrayOutputStream(); + final ObjectMapper mapper = new ObjectMapper(); + final BackendResponse backendResponse = new BackendResponse(); + final ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); + + MemoryUsage mem = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage(); + + backendResponse.addMemory("current", healthService.convertSizeToKb(mem.getUsed())); + backendResponse.addMemory("max", healthService.convertSizeToKb(mem.getMax())); + backendResponse.addMemory("committed", healthService.convertSizeToKb(mem.getCommitted())); + backendResponse.addMemory("cached", healthService.convertSizeToKb(mem.getCommitted() - mem.getUsed())); + backendResponse.addMemory("currentUsedPercentage", (mem.getUsed() * 100 / mem.getMax())); + + backendResponse.addThread("threadCount", threadMXBean.getThreadCount()); + backendResponse.addThread("peakThreadCount", threadMXBean.getPeakThreadCount()); + + backendResponse.addJvm("openFileDescriptors", healthService.invokeMethod("getOpenFileDescriptorCount")); + backendResponse.addJvm("maxFileDescriptors", healthService.invokeMethod("getMaxFileDescriptorCount")); + + mapper.writeValue(out, backendResponse); + return org.assimbly.util.rest.ResponseUtil.createSuccessResponse(connectorId, mediaType, "/health/jvm", out.toString(StandardCharsets.UTF_8), plainResponse); + } catch (Exception e) { + log.error("Get jvm failed",e); + return ResponseUtil.createFailureResponse(connectorId, mediaType,"/health/jvm",e.getMessage()); + } + } + + @GetMapping( + path = "/flow", + produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE, MediaType.TEXT_PLAIN_VALUE} + ) + public ResponseEntity getFlowStats(@Parameter(hidden = true) @RequestHeader("Accept") String mediaType) throws Exception { + + plainResponse = true; + long connectorId = 1; + integration = integrationRuntime.getIntegration(); + + try { + String stats = integration.getStats(mediaType); + if(stats.startsWith("Error")||stats.startsWith("Warning")) {plainResponse = false;} + return org.assimbly.util.rest.ResponseUtil.createSuccessResponse(connectorId, mediaType, "/health/flow", stats, plainResponse); + } catch (Exception e) { + log.error("Get flow failed",e); + return ResponseUtil.createFailureResponse(connectorId, mediaType,"/health/flow",e.getMessage()); + } + } +}