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

com.blossomproject.ui.web.system.dashboard.DashboardController Maven / Gradle / Ivy

package com.blossomproject.ui.web.system.dashboard;

import com.google.common.collect.Lists;
import com.blossomproject.ui.menu.OpenedMenu;
import com.blossomproject.ui.stereotype.BlossomController;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Statistic;
import java.util.List;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthEndpoint;
import org.springframework.boot.actuate.metrics.MetricsEndpoint;
import org.springframework.boot.actuate.metrics.MetricsEndpoint.MetricResponse;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

/**
 * Created by Maël Gargadennnec on 04/05/2017.
 */
@BlossomController
@RequestMapping("/system/dashboard")
@OpenedMenu("dashboard")
@PreAuthorize("hasAuthority('system:dashboard:manager')")
public class DashboardController {

  private final static Logger logger = LoggerFactory.getLogger(DashboardController.class);

  private final HealthEndpoint healthEndpoint;
  private final MetricsEndpoint metricsEndpoint;

  @Autowired
  private MeterRegistry registry;

  public DashboardController(HealthEndpoint healthEndpoint, MetricsEndpoint metricsEndpoint) {
    this.healthEndpoint = healthEndpoint;
    this.metricsEndpoint = metricsEndpoint;
  }

  @GetMapping
  public ModelAndView dashboard() {
    return new ModelAndView("blossom/system/dashboard/dashboard");
  }

  @GetMapping("/status")
  public ModelAndView status(Model model) {
    Health health = healthEndpoint.health();
    model.addAttribute("health", health);
    model.addAttribute("uptime",
      1000 * metricsEndpoint.metric("process.uptime", null).getMeasurements().get(0).getValue());
    return new ModelAndView("blossom/system/dashboard/panel/status", model.asMap());
  }

  @GetMapping("/memory")
  public ModelAndView memory() {
    JVMMemoryUsage memoryUsage = new JVMMemoryUsage(
      metric("jvm.memory.max").longValue(),
      metric("jvm.memory.max").longValue() - metric("jvm.memory.used").longValue());
    MemoryUsage heap = new MemoryUsage(
      0,
      metric("jvm.memory.used", Lists.newArrayList("area:heap")).longValue(),
      metric("jvm.memory.committed", Lists.newArrayList("area:heap")).longValue(),
      metric("jvm.memory.max", Lists.newArrayList("area:heap")).longValue());
    MemoryUsage nonheap = new MemoryUsage(
      0,
      metric("jvm.memory.used", Lists.newArrayList("area:nonheap")).longValue(),
      metric("jvm.memory.committed", Lists.newArrayList("area:nonheap")).longValue(),
      metric("jvm.memory.max", Lists.newArrayList("area:nonheap")).longValue());

    MemoryMetrics memoryMetrics = new MemoryMetrics(memoryUsage, heap, nonheap);

    return new ModelAndView("blossom/system/dashboard/panel/memory", "memory", memoryMetrics);
  }

  @GetMapping("/jvm")
  public ModelAndView jvm() {
    ClassMetrics classes = new ClassMetrics(
      metric("jvm.classes.loaded").intValue(),
      metric("jvm.classes.unloaded").intValue());

    GCMetrics gcs = new GCMetrics(
      metricsEndpoint.metric("jvm.gc.pause", null).getAvailableTags()
        .stream()
        .filter(t -> t.getTag().equals("action")).flatMap(action -> action.getValues().stream())
        .map(value -> {
          MetricResponse metric = metricsEndpoint
            .metric("jvm.gc.pause", Lists.newArrayList("action:" + value));
          return new GCMetric(
            value,
            metric.getMeasurements().stream().filter(m -> m.getStatistic() == Statistic.COUNT)
              .findFirst().get().getValue().longValue(),
            metric.getMeasurements().stream().filter(m -> m.getStatistic() == Statistic.TOTAL_TIME)
              .findFirst().get().getValue().doubleValue()
          );
        })
        .collect(Collectors.toList())
    );

    ThreadMetrics threads = new ThreadMetrics(
      metric("jvm.threads.live").intValue(),
      metric("jvm.threads.peak").intValue(),
      metric("jvm.threads.daemon").intValue());
    ProcessorMetrics processors = new ProcessorMetrics(
      metric("system.cpu.count").intValue()
    );

    JVMMetrics jvmMetrics = new JVMMetrics(classes, gcs, threads, processors);
    return new ModelAndView("blossom/system/dashboard/panel/jvm", "jvm", jvmMetrics);
  }

  @GetMapping("/charts")
  public ModelAndView requests() {
    return new ModelAndView("blossom/system/dashboard/panel/charts");
  }

  private Double metric(String name) {
    return this.metricsEndpoint.metric(name, null).getMeasurements().get(0).getValue();
  }

  private Double metric(String name, List tags) {
    return this.metricsEndpoint.metric(name, tags).getMeasurements().get(0).getValue();
  }

  public static String humanReadableByteCount(long bytes, boolean si) {
    int unit = si ? 1000 : 1024;
    if (bytes < unit) {
      return bytes + " B";
    }
    int exp = (int) (Math.log(bytes) / Math.log(unit));
    String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp - 1) + (si ? "" : "i");
    return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre);
  }

  public class MemoryMetrics {

    private final JVMMemoryUsage jvm;
    private final MemoryUsage heap;
    private final MemoryUsage nonheap;

    public MemoryMetrics(JVMMemoryUsage jvm, MemoryUsage heap, MemoryUsage nonheap) {
      this.jvm = jvm;
      this.heap = heap;
      this.nonheap = nonheap;
    }

    public JVMMemoryUsage getJvm() {
      return jvm;
    }

    public MemoryUsage getHeap() {
      return heap;
    }

    public MemoryUsage getNonheap() {
      return nonheap;
    }

  }


  public static class JVMMemoryUsage {

    private final long total;
    private final long free;

    public JVMMemoryUsage(long total, long free) {
      this.total = total;
      this.free = free;
    }

    public String getTotal() {
      return humanReadableByteCount(total, true);
    }

    public String getFree() {
      return humanReadableByteCount(free, true);
    }

    public String getUsed() {
      return humanReadableByteCount(total - free, true);
    }

    public float getPercentage() {
      return ((float) total - (float) free) / (float) total * 100;
    }
  }

  public static class MemoryUsage {

    private final long init;
    private final long used;
    private final long committed;
    private final long max;

    public MemoryUsage(long init, long used, long committed, long max) {
      this.init = init;
      this.used = used;
      this.committed = committed;
      this.max = max;
    }

    public String getInit() {
      return humanReadableByteCount(init, true);
    }

    public String getUsed() {
      return humanReadableByteCount(used, true);
    }

    public String getCommitted() {
      return humanReadableByteCount(committed, true);
    }

    public String getMax() {
      return humanReadableByteCount(max, true);
    }

    public float getPercentage() {
      return (float) used / (float) committed * 100;
    }
  }

  public class JVMMetrics {

    private final ClassMetrics classes;
    private final GCMetrics gcs;
    private final ThreadMetrics threads;
    private final ProcessorMetrics processors;

    public JVMMetrics(ClassMetrics classes, GCMetrics gcs, ThreadMetrics threads,
      ProcessorMetrics processors) {
      this.classes = classes;
      this.gcs = gcs;
      this.threads = threads;
      this.processors = processors;
    }

    public ClassMetrics getClasses() {
      return classes;
    }

    public GCMetrics getGcs() {
      return gcs;
    }

    public ThreadMetrics getThreads() {
      return threads;
    }

    public ProcessorMetrics getProcessors() {
      return processors;
    }

  }


  public static class ClassMetrics {

    private final long total;
    private final long loaded;
    private final long unloaded;

    public ClassMetrics(long loaded, long unloaded) {
      this.total = loaded + unloaded;
      this.loaded = loaded;
      this.unloaded = unloaded;
    }

    public long getTotal() {
      return total;
    }

    public long getLoaded() {
      return loaded;
    }

    public long getUnloaded() {
      return unloaded;
    }
  }

  public static class GCMetrics {

    private final List types;

    public GCMetrics(List types) {
      this.types = types;
    }

    public List getTypes() {
      return types;
    }

  }

  public static class GCMetric {

    private final String name;
    private final long count;
    private final double time;

    public GCMetric(String name, long count, double time) {
      this.name = name;
      this.count = count;
      this.time = time;
    }

    public String getName() {
      return name;
    }

    public long getCount() {
      return count;
    }

    public double getTime() {
      return time;
    }
  }

  public static class ThreadMetrics {

    private final long live;
    private final long peak;
    private final long daemon;

    public ThreadMetrics(long live, long peak, long daemon) {
      this.live = live;
      this.peak = peak;
      this.daemon = daemon;
    }

    public long getLive() {
      return live;
    }

    public long getPeak() {
      return peak;
    }

    public long getDaemon() {
      return daemon;
    }
  }

  public static class ProcessorMetrics {

    private final int total;

    public ProcessorMetrics(int total) {
      this.total = total;
    }

    public int getTotal() {
      return total;
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy