001package org.avaje.metric.elastic; 002 003import okhttp3.MediaType; 004import okhttp3.OkHttpClient; 005import okhttp3.Request; 006import okhttp3.RequestBody; 007import okhttp3.Response; 008import org.avaje.metric.report.MetricReporter; 009import org.avaje.metric.report.ReportMetrics; 010import org.slf4j.Logger; 011import org.slf4j.LoggerFactory; 012 013import java.io.StringWriter; 014import java.net.ConnectException; 015import java.time.LocalDate; 016 017/** 018 * Http(s) based Reporter that sends JSON formatted metrics directly to Elastic. 019 */ 020public class ElasticHttpReporter implements MetricReporter { 021 022 private static final Logger logger = LoggerFactory.getLogger(ElasticHttpReporter.class); 023 024 private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8"); 025 026 private final OkHttpClient client = new OkHttpClient(); 027 028 private final String bulkUrl; 029 030 private final ElasticReporterConfig config; 031 032 public ElasticHttpReporter(ElasticReporterConfig config) { 033 this.config = config; 034 this.bulkUrl = config.getUrl() + "/_bulk"; 035 036 // put the template to elastic if it is not already there 037 new TemplateApply(client, config.getUrl(), config.getTemplateName()).run(); 038 } 039 040 /** 041 * Send the non-empty metrics that were collected to the remote repository. 042 */ 043 @Override 044 public void report(ReportMetrics reportMetrics) { 045 046 String today = today(); 047 String json = null; 048 try { 049 StringWriter writer = new StringWriter(1000); 050 BulkJsonWriteVisitor jsonVisitor = new BulkJsonWriteVisitor(writer, reportMetrics, config, today); 051 jsonVisitor.write(); 052 053 json = writer.toString(); 054 055 if (logger.isTraceEnabled()) { 056 logger.trace("Sending:\n{}", json); 057 } 058 059 RequestBody body = RequestBody.create(JSON, json); 060 Request request = new Request.Builder() 061 .url(bulkUrl) 062 .post(body) 063 .build(); 064 065 Response response = client.newCall(request).execute(); 066 if (!response.isSuccessful()) { 067 logger.warn("Unsuccessful sending metrics payload to server - {}", response.body().string()); 068 storeJsonForResend(json); 069 } else if (logger.isTraceEnabled()) { 070 logger.trace("Bulk Response - {}", response.body().string()); 071 } 072 073 } catch (ConnectException e) { 074 logger.info("Connection error sending metrics to server: " + e.getMessage()); 075 storeJsonForResend(json); 076 077 } catch (Exception e) { 078 logger.error("Unexpected error sending metrics to server", e); 079 storeJsonForResend(json); 080 } 081 } 082 083 private String today() { 084 return LocalDate.now().toString(); 085 } 086 087 protected void storeJsonForResend(String json) { 088 // override this to support store and re-send 089 } 090 091 092 @Override 093 public void cleanup() { 094 // Do nothing 095 } 096 097}