package io.dropwizard.metrics.influxdb; import io.dropwizard.metrics.influxdb.data.InfluxDbPoint; import io.dropwizard.metrics.influxdb.data.InfluxDbWriteObject; import io.dropwizard.metrics.influxdb.utils.InfluxDbWriteObjectSerializer; import org.apache.http.HttpResponse; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.CredentialsProvider; import org.apache.http.client.ResponseHandler; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.protocol.HttpClientContext; import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.BasicCredentialsProvider; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; import java.io.IOException; import java.net.URL; import java.util.HashSet; import java.util.Map; import java.util.concurrent.TimeUnit; /** * An implementation of InfluxDbSender that writes to InfluxDb via http. */ public class InfluxDbHttpSender implements InfluxDbSender { private final CloseableHttpClient closeableHttpClient; private final URL url; private final String username; private final String password; private final InfluxDbWriteObject influxDbWriteObject; private final InfluxDbWriteObjectSerializer influxDbWriteObjectSerializer; /** * Creates a new http sender given connection details. * * @param hostname the influxDb hostname * @param port the influxDb http port * @param database the influxDb database to write to * @param username the username used to connect to influxDb * @param password the password used to connect to influxDb * @throws Exception exception while creating the influxDb sender(MalformedURLException) */ public InfluxDbHttpSender(final String hostname, final int port, final String database, final String username, final String password) throws Exception { this(hostname, port, database, username, password, TimeUnit.MILLISECONDS); } /** * Creates a new http sender given connection details. * * @param hostname the influxDb hostname * @param port the influxDb http port * @param database the influxDb database to write to * @param username the influxDb username * @param password the influxDb password * @param timePrecision the time precision of the metrics * @throws Exception exception while creating the influxDb sender(MalformedURLException) */ public InfluxDbHttpSender(final String hostname, final int port, final String database, final String username, final String password, final TimeUnit timePrecision) throws Exception { this.url = new URL("http", hostname, port, "/write"); this.closeableHttpClient = HttpClients.createDefault(); this.username = username; this.password = password; this.influxDbWriteObject = new InfluxDbWriteObject(database, timePrecision); this.influxDbWriteObjectSerializer = new InfluxDbWriteObjectSerializer(); } @Override public void flush() { influxDbWriteObject.setPoints(new HashSet<InfluxDbPoint>()); } @Override public boolean hasSeriesData() { return influxDbWriteObject.getPoints() != null && !influxDbWriteObject.getPoints().isEmpty(); } @Override public void appendPoints(final InfluxDbPoint point) { if (point != null) { influxDbWriteObject.getPoints().add(point); } } private RequestConfig getRequestConfig() { return RequestConfig .custom() .setConnectTimeout(1000) .setConnectionRequestTimeout(1000) .build(); } private HttpClientContext getHttpClientContext() { HttpClientContext httpClientContext = null; if (username != null && !username.isEmpty() && password != null && !password.isEmpty()) { httpClientContext = HttpClientContext.create(); AuthScope authScope = new AuthScope(url.getHost(), url.getPort()); UsernamePasswordCredentials usernamePasswordCredentials = new UsernamePasswordCredentials(username, password); CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); credentialsProvider.setCredentials(authScope, usernamePasswordCredentials); httpClientContext.setCredentialsProvider(credentialsProvider); } return httpClientContext; } @Override public int writeData() throws Exception { final String json = influxDbWriteObjectSerializer.getJsonString(influxDbWriteObject); HttpPost httpPost = new HttpPost(this.url.toURI()); httpPost.setEntity(new StringEntity(json, ContentType.APPLICATION_JSON)); httpPost.setConfig(getRequestConfig()); Integer responseCode = closeableHttpClient.execute(httpPost, new ResponseHandler<Integer>() { @Override public Integer handleResponse(HttpResponse httpResponse) throws ClientProtocolException, IOException { int statusCode = httpResponse.getStatusLine().getStatusCode(); EntityUtils.consumeQuietly(httpResponse.getEntity()); if (statusCode >= 200 && statusCode < 300) { return statusCode; } else { throw new ClientProtocolException("Server returned HTTP response code: " + statusCode + "for URL: " + url + " with content :'" + httpResponse.getStatusLine().getReasonPhrase() + "'" ); } } }, getHttpClientContext()); return responseCode; } @Override public void setTags(final Map<String, String> tags) { if (tags != null) { influxDbWriteObject.setTags(tags); } } }