package org.dstadler.commons.metrics;

import java.io.IOException;
import java.util.logging.Logger;

import org.apache.commons.io.IOUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.dstadler.commons.http.HttpClientWrapper;
import org.dstadler.commons.http.NanoHTTPD;
import org.dstadler.commons.logging.jdk.LoggerFactory;

/**
 * Helper class for sending simple metrics to an Elasticsearch instance.
 */
public class MetricsUtils {
    private static final Logger log = LoggerFactory.make();

    /**
     * Send the given value for the given metric and timestamp.
     *
     * Authentication can be provided via the configured {@link HttpClient} instance.
     *
     * @param metric The key of the metric
     * @param value The value of the measurement
     * @param ts The timestamp of the measurement
     * @param url The base URL where Elasticsearch is available.
     * @param user The username for basic authentication of the HTTP connection, empty if unused
     * @param password The password for basic authentication of the HTTP connection, null if unused
     *
     * @throws IOException If the HTTP call fails with an HTTP status code.
     */
    public static void sendMetric(String metric, int value, long ts, String url, String user, String password) throws IOException {
        try (HttpClientWrapper metrics = new HttpClientWrapper(user, password, 60_000)) {
            sendMetric(metric, value, ts, metrics.getHttpClient(), url);
        }
    }

    /**
     * Send the given value for the given metric and timestamp.
     *
     * Authentication can be provided via the configured {@link HttpClient} instance.
     *
     * @param metric The key of the metric
     * @param value The value of the measurement
     * @param ts The timestamp of the measurement
     * @param httpClient The HTTP Client that can be used to send metrics.
     *                   This can also contain credentials for basic authentication if necessary
     * @param url The base URL where Elasticsearch is available.
     *
     * @throws IOException If the HTTP call fails with an HTTP status code.
     */
    public static void sendMetric(String metric, int value, long ts, CloseableHttpClient httpClient, String url) throws IOException {
        sendMetric(null, metric, value, ts, httpClient, url);
    }

    /**
     * Send the given value for the given metric and timestamp.
     *
     * Authentication can be provided via the configured {@link HttpClient} instance.
     *
     * @param splitting Allows to define multiple values for one metric at one point in time, e.g. by machine, ...
     *                  Can be null if no splitting should be set
     * @param metric The key of the metric
     * @param value The value of the measurement
     * @param ts The timestamp of the measurement
     * @param httpClient The HTTP Client that can be used to send metrics.
     *                   This can also contain credentials for basic authentication if necessary
     * @param url The base URL where Elasticsearch is available.
     *
     * @throws IOException If the HTTP call fails with an HTTP status code.
     */
    public static void sendMetric(String splitting, String metric, int value, long ts,
                                  CloseableHttpClient httpClient, String url) throws IOException {
        sendDocument("{ \"timestamp\": " + ts + "," +
                        (splitting != null ? "  \"splitting\": \"" + splitting + "\"," : "") +
                        "  \"metric\": \"" + metric + "\"," +
                        "  \"value\": " + value + "}",
                httpClient, url);
    }

    /**
     * Send the given document to the given Elasticsearch URL/Index
     *
     * Authentication can be provided via the configured {@link HttpClient} instance.
     *
     * @param json The json-string to store as document
     * @param httpClient The HTTP Client that can be used to send metrics.
     *                   This can also contain credentials for basic authentication if necessary
     * @param url The base URL where Elasticsearch is available.
     *
     * @throws IOException If the HTTP call fails with an HTTP status code.
     */
    public static void sendDocument(String json, CloseableHttpClient httpClient, String url) throws IOException {
        final HttpPut httpPut = new HttpPut(url);
        httpPut.addHeader("Content-Type", NanoHTTPD.MIME_JSON);
        httpPut.setEntity(new StringEntity(
                json, ContentType.APPLICATION_JSON));

        try (CloseableHttpResponse response = httpClient.execute(httpPut)) {
            int statusCode = response.getStatusLine().getStatusCode();
            if(statusCode > 201) {
                String msg = "Had HTTP StatusCode " + statusCode + " for request: " + url + ", response: " + response.getStatusLine().getReasonPhrase() + "\n" +
                        "Response: " + IOUtils.toString(response.getEntity().getContent(), "UTF-8");
                log.warning(msg);

                throw new IOException(msg);
            }
            HttpEntity entity = response.getEntity();

            try {
                log.info("Had result when sending document to Elasticsearch at " + url + ": " + IOUtils.toString(entity.getContent(), "UTF-8"));
            } finally {
                // ensure all content is taken out to free resources
                EntityUtils.consume(entity);
            }
        }
    }
}

@@ -36,70 +36,8 @@
 s;%0A%0A
-import java.io.IOException;%0Aimport java.util.logging.Logger;%0A%0A
 impo
@@ -591,16 +591,78 @@
 ctory;%0A%0A
+import java.io.IOException;%0Aimport java.util.logging.Logger;%0A%0A
 /**%0A * H
@@ -4943,508 +4943,73 @@
     
-int statusCode = response.getStatusLine().getStatusCode();%0A            if(statusCode %3E 201) %7B%0A                String msg = %22Had HTTP StatusCode %22 + statusCode + %22 for request: %22 + url + %22, response: %22 + response.getStatusLine().getReasonPhrase() + %22%5Cn%22 +%0A                        %22Response: %22 + IOUtils.toString(response.getEntity().getContent(), %22UTF-8%22);%0A                log.warning(msg);%0A%0A                throw new IOException(msg);%0A            %7D%0A            HttpEntity entity = response.getEntity(
+HttpEntity entity = HttpClientWrapper.checkAndFetch(response, url
 );%0A%0A

Remove some code-duplication