All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.mvnsearch.boot.xtermjs.commands.SpringCommands Maven / Gradle / Ivy

There is a newer version: 1.3.3
Show newest version
package org.mvnsearch.boot.xtermjs.commands;

import io.micrometer.core.instrument.Meter;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Tag;
import org.apache.commons.io.input.ReversedLinesFileReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.SpringBootVersion;
import org.springframework.boot.actuate.endpoint.web.annotation.WebEndpointDiscoverer;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthComponent;
import org.springframework.boot.actuate.health.HealthEndpoint;
import org.springframework.boot.actuate.health.ReactiveHealthIndicator;
import org.springframework.context.ApplicationContext;
import org.springframework.core.env.AbstractEnvironment;
import org.springframework.core.env.EnumerablePropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.shell.standard.ShellComponent;
import org.springframework.shell.standard.ShellMethod;
import org.springframework.shell.standard.ShellOption;
import org.springframework.util.ClassUtils;
import reactor.core.publisher.Mono;

import java.io.File;
import java.net.InetAddress;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Spring commands: include spring framework, spring boot, spring cloud etc
 *
 * @author linux_china
 */
@ShellComponent
public class SpringCommands implements CommandsSupport {

	private String startedTime = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss:SSS'Z'").format(new Date());

	@Autowired
	private ApplicationContext applicationContext;

	@Autowired
	private AbstractEnvironment env;

	@Autowired
	private ConfigurableListableBeanFactory beanFactory;

	@Autowired
	private HealthEndpoint healthEndpoint;

	@Autowired
	private MeterRegistry meterRegistry;

	@Autowired
	private WebEndpointDiscoverer endpointDiscoverer;

	@ShellMethod("Display application info")
	public String app() {
		List lines = new ArrayList<>();
		if (env.getProperty("spring.application.name") != null) {
			lines.add("Application name: " + env.getProperty("spring.application.name"));
		}
		lines.add("User Home: " + env.getProperty("user.home"));
		lines.add("Work Dir: " + env.getProperty("user.dir"));
		lines.add("Shell: " + env.getProperty("SHELL", ""));
		if (env.getProperty("PID") != null) {
			lines.add("PID: " + env.getProperty("PID"));
		}
		lines.add("Started Time: " + startedTime);
		lines.add("Java Version: " + System.getProperty("java.version"));
		lines.add("OS Name: " + System.getProperty("os.name"));
		lines.add("OS Version: " + System.getProperty("os.version"));
		lines.add("OS Arch: " + System.getProperty("os.arch"));
		lines.add("Spring Boot Version: " + SpringBootVersion.getVersion());
		// cpu + memory + disk
		int mb = 1024 * 1024;
		int gb = mb * 1024;
		Runtime runtime = Runtime.getRuntime();
		lines.add("CPU Cores: " + runtime.availableProcessors());
		lines.add("Total Memory(M): " + runtime.totalMemory() / mb);
		lines.add("Free Memory(M): " + runtime.freeMemory() / mb);
		lines.add("Used Memory(M): " + (runtime.totalMemory() - runtime.freeMemory()) / mb);
		lines.add("Max Memory(M): " + runtime.maxMemory() / mb);
		File path = new File(".");
		lines.add("Total Space(G): " + path.getTotalSpace() / gb);
		lines.add("Free Space(G): " + path.getUsableSpace() / gb);
		try {
			InetAddress inetAddress = InetAddress.getLocalHost();
			lines.add("IP: " + inetAddress.getHostAddress());
			lines.add("Host: " + inetAddress.getHostName());
		}
		catch (Exception ignore) {

		}
		return linesToString(lines);
	}

	@ShellMethod("Context list")
	public List contexts() {
		List contexts = new ArrayList<>();
		Map beansWithAnnotation = applicationContext.getBeansWithAnnotation(ShellComponent.class);
		for (Object bean : beansWithAnnotation.values()) {
			ShellComponent shellComponent = bean.getClass().getAnnotation(ShellComponent.class);
			String value = shellComponent.value();
			if (value.contains(": ")) {
				contexts.add(value);
			}
		}
		if (contexts.isEmpty()) {
			contexts.add("No context found");
		}
		return contexts;
	}

	@ShellMethod("Execute SpEL")
	public String spel() {
		return "Not implemented";
	}

	@ShellMethod("Display beans info")
	public String beans() {
		List lines = new ArrayList<>(Arrays.asList(beanFactory.getBeanDefinitionNames()));
		lines.add("");
		lines.add("Beans: " + beanFactory.getBeanDefinitionNames().length);
		return linesToString(lines);
	}

	@ShellMethod("Display bean info")
	public String bean(@ShellOption(help = "Bean name or class") String beanNameOrClass) {
		List lines = new ArrayList<>();
		String nameForSearch = beanNameOrClass;
		if (beanNameOrClass.contains("*")) {
			nameForSearch = beanNameOrClass.replaceAll("\\*", "").toLowerCase();
		}
		for (String beanName : beanFactory.getBeanDefinitionNames()) {
			BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
			String beanClassName = beanDefinition.getBeanClassName();
			Object bean = applicationContext.getBean(beanName);
			if (beanClassName == null) {
				beanClassName = bean.getClass().getCanonicalName();
				if (beanClassName == null) {
					beanClassName = bean.getClass().getSimpleName();
				}
			}
			boolean matched;
			if (beanNameOrClass.contains("*")) {
				matched = beanName.toLowerCase().contains(nameForSearch)
						|| beanClassName.toLowerCase().contains(nameForSearch);
			}
			else {
				matched = beanNameOrClass.equalsIgnoreCase(beanName) || beanNameOrClass.equalsIgnoreCase(beanClassName);
			}
			if (matched) {
				if (!lines.isEmpty()) {
					lines.add("-------------------------------");
				}
				lines.add("Name: " + beanName);
				lines.add("Class: " + beanClassName);
				if (beanDefinition.getFactoryBeanName() != null) {
					lines.add("Factory Bean: " + beanDefinition.getFactoryBeanName());
				}
				if (beanDefinition.getFactoryMethodName() != null) {
					lines.add("Factory Method: " + beanDefinition.getFactoryMethodName());
				}
				if (beanDefinition.getScope() != null && !beanDefinition.getScope().isEmpty()) {
					lines.add("Scope: " + beanDefinition.getScope());
				}
				if (beanDefinition.getDependsOn() != null && beanDefinition.getDependsOn().length > 0) {
					lines.add("DependsOn: " + String.join("\n", beanDefinition.getDependsOn()));
				}
				if (beanDefinition.getParentName() != null) {
					lines.add("Parent: " + beanDefinition.getParentName());
				}
				Class[] allInterfaces = ClassUtils.getAllInterfaces(bean);
				for (Class beanInterface : allInterfaces) {
					lines.add("=========" + beanInterface.getCanonicalName() + " ========");
					Arrays.stream(beanInterface.getDeclaredMethods()).map(method -> {
						if (method.getParameterCount() == 0) {
							return formatClassName(method.getGenericReturnType().getTypeName()) + " " + method.getName()
									+ "()";
						}
						else {
							String parameterTypes = Arrays.stream(method.getParameters()).map(parameter -> {
								String parameterName = parameter.getName();
								return formatClassName(parameter.getParameterizedType().getTypeName()) + " "
										+ parameterName;
							}).collect(Collectors.joining(", "));
							return formatClassName(method.getGenericReturnType().getTypeName()) + " " + method.getName()
									+ "(" + parameterTypes + ")";
						}
					}).forEach(lines::add);
				}
			}

		}
		return linesToString(lines);
	}

	@ShellMethod("Display env info")
	public String env(@ShellOption(help = "env name", defaultValue = "") String envName) {
		List lines = new ArrayList<>();
		if (!envName.isEmpty()) {
			String key = envName;
			String value = env.getProperty(key);
			if (value == null) {
				key = envName.toUpperCase();
				value = env.getProperty(key);
			}
			if (value == null) {
				lines.add("Env name not found!");
			}
			else {
				lines.add(key + ": " + value);
			}
		}
		else {
			for (PropertySource propertySource : env.getPropertySources()) {
				if (propertySource instanceof EnumerablePropertySource) {
					EnumerablePropertySource enumerablePropertySource = (EnumerablePropertySource) propertySource;
					for (String propertyName : enumerablePropertySource.getPropertyNames()) {
						lines.add(propertyName + ": " + env.getProperty(propertyName));
					}
				}
			}
			lines.add("");
			lines.add("Env names: " + (lines.size() - 1));
		}
		return linesToString(lines);
	}

	@ShellMethod("Display metrics")
	public String metrics(@ShellOption(help = "metrics name", defaultValue = "") String metricsName) {
		List lines = new ArrayList<>();
		if (!metricsName.isEmpty()) {
			for (Meter meter : meterRegistry.getMeters()) {
				String meterName = meter.getId().getName();
				if (meterName.contains(metricsName)) {
					lines.add(meterName(metricsName, meter.getId().getTags()) + ": "
							+ meter.measure().iterator().next().getValue());
				}
			}
		}
		else {
			for (Meter meter : meterRegistry.getMeters()) {
				lines.add(meterName(meter.getId().getName(), meter.getId().getTags()) + ": "
						+ meter.measure().iterator().next().getValue());
			}
			lines.add("");
			lines.add("Metrics Count: " + (lines.size() - 1));
		}
		return linesToString(lines);
	}

	@ShellMethod("Display health")
	public Object health(@ShellOption(help = "health component name", defaultValue = "") String componentName) {
		try {
			ReactiveHealthIndicator healthIndicator = applicationContext.getBean(ReactiveHealthIndicator.class);
			return healthIndicator.health().map(health -> health.getStatus().getCode());
		}
		catch (Exception e) {
			return new Exception("Failed to get health:" + e.getMessage());
		}
	}

	@ShellMethod("Display profiles")
	public String profiles() {
		String[] profiles = env.getActiveProfiles();
		if (profiles.length > 0) {
			return "Active Profiles: [" + String.join(",", profiles) + "]";
		}
		return "No active profiles";
	}

	@ShellMethod("Display logfile")
	public List log() throws Exception {
		String loggingFilePath = env.getProperty("logging.file.path");
		String loggingFileName = env.getProperty("logging.file.name");
		if (loggingFilePath == null || loggingFileName == null) {
			throw new Exception("Missing 'logging.file.name' or 'logging.file.path' properties");
		}
		File loggingFile = new File(loggingFilePath, loggingFileName);
		if (!loggingFile.exists()) {
			throw new Exception("Logging file not found: " + loggingFile.getAbsolutePath());
		}
		ReversedLinesFileReader object = new ReversedLinesFileReader(loggingFile, StandardCharsets.UTF_8);
		List lines = new ArrayList<>();
		for (int i = 0; i < 100; i++) {
			String line = object.readLine();
			if (line == null)
				break;
			lines.add(line);
		}
		Collections.reverse(lines);
		return lines;
	}

	@ShellMethod("Display actuator")
	public Mono actuator(@ShellOption(help = "health component name", defaultValue = "") String endpoint) {
		if (endpoint.isEmpty()) {
			return Mono.just(endpointDiscoverer.getEndpoints().stream()
					.map(exposableWebEndpoint -> exposableWebEndpoint.getEndpointId().toLowerCaseString())
					.collect(Collectors.joining(",")));
		}
		String serverPort = env.getProperty("server.port");
		if (serverPort == null || serverPort.equals("-1")) {
			serverPort = "8080";
		}
		String managementPort = env.getProperty("management.server.port", serverPort);
		String managementPath = env.getProperty("management.endpoints.web.base-path", "/actuator");
		return CurlCommand.webClient.get().uri("http://127.0.0.1:" + managementPort + managementPath + "/" + endpoint)
				.retrieve().bodyToMono(String.class);
	}

	private static String meterName(String name, List tags) {
		if (tags != null && tags.size() > 0) {
			return tags.stream().map(tag -> tag.getKey() + ":" + tag.getValue())
					.collect(Collectors.joining(",", name + "(", ")"));
		}
		return name;
	}

	private static String healthName(String name, HealthComponent healthComponent) {
		if (healthComponent instanceof Health) {
			Map details = ((Health) healthComponent).getDetails();
			if (details != null && !details.isEmpty()) {
				return details.entrySet().stream().map(entry -> entry.getKey() + ":" + entry.getValue().toString())
						.collect(Collectors.joining(",", name + "(", ")"));
			}
		}
		return name;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy