package com.sequenceiq.cloudbreak.service.metrics;

import javax.inject.Inject;

import org.springframework.boot.actuate.metrics.CounterService;
import org.springframework.boot.actuate.metrics.GaugeService;
import org.springframework.stereotype.Service;

import com.sequenceiq.cloudbreak.common.type.MetricType;
import com.sequenceiq.cloudbreak.domain.Stack;
import com.sequenceiq.cloudbreak.domain.view.StackView;

@Service
public class MetricService {

    private static final String METRIC_PREFIX = "cloudbreak.";

    @Inject
    private CounterService counterService;

    @Inject
    private GaugeService gaugeService;

    /**
     * Increment a counter based metric.
     *
     * @param metric Metric name
     */
    public void incrementMetricCounter(MetricType metric) {
        incrementMetricCounter(metric.getMetricName());
    }

    /**
     * Increment a counter based metric. If the stack is provided then the metric's name
     * will be extended with the cloud platform. If the stack is null the original metric name will be used.
     *
     * @param metric Metric name
     * @param stack  Stack, used to determine the cloud platform
     */
    public void incrementMetricCounter(MetricType metric, StackView stack) {
        if (stack != null && stack.getPlatformVariant() != null) {
            incrementMetricCounter(getMetricNameWithPlatform(metric, stack.cloudPlatform()));
        } else {
            incrementMetricCounter(metric.getMetricName());
        }
    }

    /**
     * Increment a counter based metric. If the stack is provided then the metric's name
     * will be extended with the cloud platform. If the stack is null the original metric name will be used.
     *
     * @param metric Metric name
     * @param stack  Stack, used to determine the cloud platform
     */
    public void incrementMetricCounter(MetricType metric, Stack stack) {
        if (stack != null && stack.getPlatformVariant() != null) {
            incrementMetricCounter(getMetricNameWithPlatform(metric, stack.cloudPlatform()));
        } else {
            incrementMetricCounter(metric.getMetricName());
        }
    }

    /**
     * Set the specified gauge value.
     *
     * @param metric Metric name
     * @param value  Metric value
     */
    public void submit(String metric, double value) {
        gaugeService.submit(METRIC_PREFIX + metric.toLowerCase(), value);
    }

    private void incrementMetricCounter(String metric) {
        counterService.increment(METRIC_PREFIX + metric.toLowerCase());
    }

    private String getMetricNameWithPlatform(MetricType metric, String cloudPlatform) {
        return getMetricNameWithPlatform(metric.getMetricName(), cloudPlatform);
    }

    private String getMetricNameWithPlatform(String metric, String cloudPlatform) {
        return metric + '.' + cloudPlatform.toLowerCase();
    }
}

@@ -45,16 +45,55 @@
 trics;%0A%0A
+import javax.annotation.PostConstruct;%0A
 import j
@@ -270,28 +270,220 @@
 ork.
-stereotype.Service;%0A
+boot.actuate.metrics.writer.Delta;%0Aimport org.springframework.boot.actuate.metrics.writer.MetricWriter;%0Aimport org.springframework.stereotype.Service;%0A%0Aimport com.sequenceiq.cloudbreak.common.type.CloudConstants;
 %0Aimp
@@ -751,110 +751,866 @@
     
-@Inject%0A    private CounterService counterService;%0A%0A    @Inject%0A    private GaugeService gaugeService;
+private static final String JMX_COUNTER_TYPE = %22counter.%22;%0A%0A    @Inject%0A    private MetricWriter metricWriter;%0A%0A    @Inject%0A    private CounterService counterService;%0A%0A    @Inject%0A    private GaugeService gaugeService;%0A%0A    @PostConstruct%0A    public void init() %7B%0A        for (MetricType metricType : MetricType.values()) %7B%0A            String metricName = metricType.getMetricName();%0A            if (metricName.startsWith(%22stack%22) %7C%7C metricName.startsWith(%22cluster%22)) %7B%0A                initJmxMetricCounter(metricName, CloudConstants.AWS);%0A                initJmxMetricCounter(metricName, CloudConstants.AZURE);%0A                initJmxMetricCounter(metricName, CloudConstants.GCP);%0A                initJmxMetricCounter(metricName, CloudConstants.OPENSTACK);%0A                initJmxMetricCounter(metricName, CloudConstants.YARN);%0A            %7D%0A        %7D%0A    %7D
 %0A%0A  
@@ -3516,32 +3516,249 @@
 Case());%0A    %7D%0A%0A
+    private void initJmxMetricCounter(String metric, String cloudPlatform) %7B%0A        metricWriter.increment(new Delta%3C%3E(JMX_COUNTER_TYPE + METRIC_PREFIX + getMetricNameWithPlatform(metric, cloudPlatform), 0));%0A    %7D%0A%0A
     private Stri

initialize the stack and cluster related metrics for proper prometheus alerts