Skip to content

Commit

Permalink
Merge pull request #792 from assimbly/feature/health-check-endpoints
Browse files Browse the repository at this point in the history
Health Check endpoints
  • Loading branch information
skin27 authored Jul 11, 2023
2 parents 68920e8 + 74e0458 commit a1a3265
Show file tree
Hide file tree
Showing 6 changed files with 288 additions and 1 deletion.
2 changes: 1 addition & 1 deletion scripts/version/versioned_files.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@
"path": "/src/main/resources/config/application.yml"
}
]
}
}
24 changes: 24 additions & 0 deletions src/main/java/org/assimbly/gateway/service/HealthService.java
Original file line number Diff line number Diff line change
@@ -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);

}
Original file line number Diff line number Diff line change
@@ -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";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package org.assimbly.gateway.service.response;

import java.util.HashMap;
import java.util.Map;

public class BackendResponse {

private Map<String, Object> jvm = new HashMap<>();
private Map<String, Long> memory = new HashMap<>();
private Map<String, Integer> threads = new HashMap<>();

public Map<String, Long> getMemory() {
return memory;
}
public void setMemory(Map<String, Long> memory) {
this.memory = memory;
}
public void addMemory(String key, Long value) {
this.memory.put(key, value);
}

public Map<String, Integer> getThreads() {
return threads;
}
public void setThreads(Map<String, Integer> threads) {
this.threads = threads;
}
public void addThread(String key, Integer value) {
this.threads.put(key, value);
}

public Map<String, Object> getJvm() {
return jvm;
}
public void setJvm(Map<String, Object> jvm) {
this.jvm = jvm;
}
public void addJvm(String key, Object value) {
this.jvm.put(key, value);
}


}
Original file line number Diff line number Diff line change
@@ -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<String> 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<String, Object> 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());
}
}
}
Original file line number Diff line number Diff line change
@@ -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<String> 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<String> 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());
}
}
}

0 comments on commit a1a3265

Please sign in to comment.