package com.sf.monitor.utils;

import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.collect.Iterables;
import com.sf.log.Logger;
import com.sf.monitor.Config;
import com.sf.monitor.Event;
import com.sf.monitor.Resources;
import com.sf.prometheus.PrometheusQueryService;
import io.prometheus.client.metrics.Gauge;
import org.apache.commons.lang.StringUtils;
import org.joda.time.DateTime;

import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class PrometheusUtils {
  private static final Logger log = new Logger(PrometheusUtils.class);
  private static final Map<String, Gauge> gauges = new HashMap<>();

  private static Gauge getGauge(String name) {
    Gauge gauge = gauges.get(name);
    if (gauge != null) {
      return gauge;
    }
    synchronized (gauges) {
      gauge = Gauge.newBuilder().namespace(Config.config.prometheus.namespace).name(name).documentation(
        String.format(
          "mectric for %s model",
          name
        )
      ).build();
      gauges.put(name, gauge);
    }
    return gauge;
  }

  public static void saveEvents(String modelName, List<Event> events) {
    try {
      log.debug("saveEvents, modelName: %s, events: %s", modelName, Resources.jsonMapper.writeValueAsString(events));
    } catch (Exception e) {
    }
    Gauge gauge = getGauge(modelName);
    for (Event event : events) {
      Gauge.Partial p = gauge.newPartial();
      for (Map.Entry<String, String> e : event.tags.entrySet()) {
        p.labelPair(e.getKey(), e.getValue());
      }
      p.labelPair("metricName", event.metricName);
      p.apply().set(event.metricValue);
    }
  }

  public static Map<String, List<Event>> getEvents(
    String modelName,
    Map<String, String> tags,
    DateTime start,
    DateTime end
  ) {
    String query = Config.config.prometheus.namespace + "_" + modelName;
    query += "{";
    query += Joiner.on(",").join(
      Iterables.transform(
        tags.entrySet(), new Function<Map.Entry<String, String>, String>() {
          @Nullable
          @Override
          public String apply(Map.Entry<String, String> e) {
            return String.format("%s=\"%s\"", e.getKey(), e.getValue());
          }
        }
      )
    );
    query += "}";
    PrometheusQueryService.Result res = Resources.prometheusQuery.query(query, start.getMillis(), end.getMillis());
    try {
      log.debug("getEvents, query: %s, res: %s", query, Resources.jsonMapper.writeValueAsString(res));
    } catch (Exception e) {
    }
    if (!"success".equals(res.status)) {
      log.error("Prometheus query[%s] errorType: %s, error: %s", query, res.errorType, res.error);
      return Collections.emptyMap();
    }
    Map<String, List<Event>> mappedEvents = new HashMap<>();
    for (PrometheusQueryService.MetricItem item : res.data.result) {
      String metricName = item.metric.get("metricName");
      if (StringUtils.isEmpty(metricName)) {
        continue;
      }
      List<Event> events = mappedEvents.get(metricName);
      if (events == null) {
        events = new ArrayList<>();
        mappedEvents.put(metricName, events);
      }
      for (Object[] vs : item.values) {
        Event event = new Event();
        event.metricName = metricName;
        event.timeStamp =  (long) ((double) vs[0]) * 1000;
        event.metricValue = Double.valueOf((String) vs[1]);
        events.add(event);
      }
    }
    return mappedEvents;
  }
}

@@ -1267,32 +1267,68 @@
 ts) %7B%0A    try %7B%0A
+      if (log.isDebugEnabled()) %7B%0A  
       log.debug(
@@ -1425,24 +1425,32 @@
 g(events));%0A
+      %7D%0A
     %7D catch 
@@ -3433,17 +3433,16 @@
 eStamp =
- 
  (long) 

check debug mode, save some cpu