package alien4cloud.webconfiguration;

import java.lang.management.ManagementFactory;

import javax.annotation.PostConstruct;

import lombok.extern.slf4j.Slf4j;

import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.boot.context.embedded.FilterRegistrationBean;
import org.springframework.boot.context.embedded.ServletRegistrationBean;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;

import com.codahale.metrics.JmxReporter;
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.health.HealthCheckRegistry;
import com.codahale.metrics.jvm.BufferPoolMetricSet;
import com.codahale.metrics.jvm.FileDescriptorRatioGauge;
import com.codahale.metrics.jvm.GarbageCollectorMetricSet;
import com.codahale.metrics.jvm.MemoryUsageGaugeSet;
import com.codahale.metrics.jvm.ThreadStatesGaugeSet;
import com.codahale.metrics.servlets.MetricsServlet;
import com.ryantenney.metrics.spring.config.annotation.EnableMetrics;
import com.ryantenney.metrics.spring.config.annotation.MetricsConfigurerAdapter;

@Slf4j
@Configuration
@EnableMetrics(proxyTargetClass = true)
public class MetricsConfiguration extends MetricsConfigurerAdapter implements EnvironmentAware {
    private static final String ENV_METRICS = "metrics.";
    private static final String PROP_JMX_ENABLED = "jmx.enabled";
    private static final String PROP_METRIC_REG_JVM_MEMORY = "jvm.memory";
    private static final String PROP_METRIC_REG_JVM_GARBAGE = "jvm.garbage";
    private static final String PROP_METRIC_REG_JVM_THREADS = "jvm.threads";
    private static final String PROP_METRIC_REG_JVM_FILES = "jvm.files";
    private static final String PROP_METRIC_REG_JVM_BUFFERS = "jvm.buffers";
    private static final MetricRegistry METRIC_REGISTRY = new MetricRegistry();
    private static final HealthCheckRegistry HEALTH_CHECK_REGISTRY = new HealthCheckRegistry();
    private RelaxedPropertyResolver propertyResolver;

    @Override
    public void setEnvironment(Environment environment) {
        this.propertyResolver = new RelaxedPropertyResolver(environment, ENV_METRICS);
    }

    @PostConstruct
    public void init() {
        log.info("Registering JVM gauges");
        METRIC_REGISTRY.register(PROP_METRIC_REG_JVM_MEMORY, new MemoryUsageGaugeSet());
        METRIC_REGISTRY.register(PROP_METRIC_REG_JVM_GARBAGE, new GarbageCollectorMetricSet());
        METRIC_REGISTRY.register(PROP_METRIC_REG_JVM_THREADS, new ThreadStatesGaugeSet());
        METRIC_REGISTRY.register(PROP_METRIC_REG_JVM_FILES, new FileDescriptorRatioGauge());
        METRIC_REGISTRY.register(PROP_METRIC_REG_JVM_BUFFERS, new BufferPoolMetricSet(ManagementFactory.getPlatformMBeanServer()));
        if (propertyResolver.getProperty(PROP_JMX_ENABLED, Boolean.class, false)) {
            log.info("Initializing Metrics JMX reporting");
            final JmxReporter jmxReporter = JmxReporter.forRegistry(METRIC_REGISTRY).build();
            jmxReporter.start();
        }
    }

    @Override
    @Bean
    public MetricRegistry getMetricRegistry() {
        return METRIC_REGISTRY;
    }

    @Override
    @Bean
    public HealthCheckRegistry getHealthCheckRegistry() {
        return HEALTH_CHECK_REGISTRY;
    }

    @Bean
    public MetricsServlet metricsServlet(MetricRegistry metricRegistry) {
        return new MetricsServlet(metricRegistry);
    }

    @Bean
    public FilterRegistrationBean metricsFilterRegistration(MetricRegistry metricRegistry) {
        log.info("Registering Metrics filter.");
        return new FilterRegistrationBean(new MetricsFilter(METRIC_REGISTRY));
    }

    @Bean
    public ServletRegistrationBean metricsRegistration(MetricsServlet metricsServlet) {
        ServletRegistrationBean registration = new ServletRegistrationBean(metricsServlet);
        registration.addUrlMappings("/rest/admin/metrics/metrics/*");
        return registration;
    }
}
@@ -118,16 +118,52 @@
 nstruct;
+%0Aimport javax.annotation.PreDestroy;
 %0A%0Aimport
@@ -2130,16 +2130,53 @@
 esolver;
+%0A    private JmxReporter jmxReporter;
 %0A%0A    @O
@@ -3084,26 +3084,8 @@
     
-final JmxReporter 
 jmxR
@@ -3186,32 +3186,268 @@
        %7D%0A    %7D%0A%0A
+    @PreDestroy%0A    public void destoy() %7B%0A        for (String name : METRIC_REGISTRY.getNames()) %7B%0A            METRIC_REGISTRY.remove(name);%0A        %7D%0A        if (jmxReporter != null) %7B%0A            jmxReporter.stop();%0A        %7D%0A    %7D%0A%0A
     @Override%0A  

prepare for ha : add destroy to metrics