diff --git a/src/main/java/org/dstadler/commons/metrics/MetricsUtils.java b/src/main/java/org/dstadler/commons/metrics/MetricsUtils.java
new file mode 100644
index 00000000..1af3173f
--- /dev/null
+++ b/src/main/java/org/dstadler/commons/metrics/MetricsUtils.java
@@ -0,0 +1,63 @@
+package org.dstadler.commons.metrics;
+
+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.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.util.EntityUtils;
+import org.dstadler.commons.logging.jdk.LoggerFactory;
+
+import java.io.IOException;
+import java.util.logging.Logger;
+
+/**
+ * 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 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 {
+        final HttpPut httpPut = new HttpPut(url);
+        httpPut.addHeader("Content-Type", "application/json");
+        httpPut.setEntity(new StringEntity(
+                "{ \"timestamp\": " + ts + "," +
+                        "  \"metric\": \"" + metric + "\"," +
+                        "  \"value\": " + value + "}"));
+
+        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 metric to Elasticsearch: " + IOUtils.toString(entity.getContent(), "UTF-8"));
+            } finally {
+                // ensure all content is taken out to free resources
+                EntityUtils.consume(entity);
+            }
+        }
+    }
+}
diff --git a/src/test/java/org/dstadler/commons/metrics/MetricsUtilsTest.java b/src/test/java/org/dstadler/commons/metrics/MetricsUtilsTest.java
new file mode 100644
index 00000000..e5a2d67b
--- /dev/null
+++ b/src/test/java/org/dstadler/commons/metrics/MetricsUtilsTest.java
@@ -0,0 +1,33 @@
+package org.dstadler.commons.metrics;
+
+import org.dstadler.commons.http.HttpClientWrapper;
+import org.dstadler.commons.testing.MockRESTServer;
+import org.junit.Test;
+
+import java.io.IOException;
+
+public class MetricsUtilsTest {
+    @Test
+    public void testSendMetric() throws Exception {
+        try (MockRESTServer server = new MockRESTServer("200", "application/json", "OK");
+                HttpClientWrapper metrics = new HttpClientWrapper("", null, 60_000)) {
+            String url = "http://localhost:" + server.getPort();
+            MetricsUtils.sendMetric("testmetric", 123, System.currentTimeMillis(), metrics.getHttpClient(), url);
+        }
+    }
+
+    @Test(expected = IOException.class)
+    public void testSendMetricFails() throws Exception {
+        try (MockRESTServer server = new MockRESTServer("503", "application/json", "ERROR");
+                HttpClientWrapper metrics = new HttpClientWrapper("", null, 60_000)) {
+            String url = "http://localhost:" + server.getPort();
+            MetricsUtils.sendMetric("testmetric", 123, System.currentTimeMillis(), metrics.getHttpClient(), url);
+        }
+    }
+
+    // helper method to get coverage of the unused constructor
+    @Test
+    public void testPrivateConstructor() throws Exception {
+        org.dstadler.commons.testing.PrivateConstructorCoverage.executePrivateConstructor(MetricsUtils.class);
+    }
+}