From 415452f3c8cafa46c49d3d46ff478f2f92854463 Mon Sep 17 00:00:00 2001 From: Felix Barnsteiner Date: Thu, 28 Jun 2018 16:27:28 +0200 Subject: [PATCH 1/2] Check and log status of the APM server connection --- .../report/ApmServerHttpPayloadSender.java | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/apm-agent-core/src/main/java/co/elastic/apm/report/ApmServerHttpPayloadSender.java b/apm-agent-core/src/main/java/co/elastic/apm/report/ApmServerHttpPayloadSender.java index 99b1d0eadc..ad886f3fcd 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/report/ApmServerHttpPayloadSender.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/report/ApmServerHttpPayloadSender.java @@ -36,6 +36,11 @@ import java.io.IOException; import java.util.Objects; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; public class ApmServerHttpPayloadSender implements PayloadSender { private static final Logger logger = LoggerFactory.getLogger(ApmServerHttpPayloadSender.class); @@ -45,6 +50,7 @@ public class ApmServerHttpPayloadSender implements PayloadSender { private final OkHttpClient httpClient; private final ReporterConfiguration reporterConfiguration; private final PayloadSerializer payloadSerializer; + private final ScheduledExecutorService healthCheckExecutorService; private long droppedTransactions = 0; public ApmServerHttpPayloadSender(OkHttpClient httpClient, PayloadSerializer payloadSerializer, @@ -52,6 +58,16 @@ public ApmServerHttpPayloadSender(OkHttpClient httpClient, PayloadSerializer pay this.httpClient = httpClient; this.reporterConfiguration = reporterConfiguration; this.payloadSerializer = payloadSerializer; + healthCheckExecutorService = Executors.newScheduledThreadPool(1, new ThreadFactory() { + @Override + public Thread newThread(Runnable r) { + final Thread thread = new Thread(r); + thread.setName("apm-server-healthcheck"); + thread.setDaemon(true); + return thread; + } + }); + healthCheckExecutorService.scheduleWithFixedDelay(new ApmServerHealthChecker(httpClient, reporterConfiguration), 0, 10, TimeUnit.SECONDS); } @Override @@ -127,4 +143,44 @@ public long getDroppedTransactions() { return droppedTransactions; } + private static class ApmServerHealthChecker implements Runnable { + private final OkHttpClient httpClient; + private final ReporterConfiguration reporterConfiguration; + private final AtomicBoolean serverHealthy = new AtomicBoolean(true); + + ApmServerHealthChecker(OkHttpClient httpClient, ReporterConfiguration reporterConfiguration) { + this.httpClient = httpClient; + this.reporterConfiguration = reporterConfiguration; + } + + @Override + public void run() { + boolean success; + String message = null; + try { + final int status = httpClient.newCall(new Request.Builder() + .url(reporterConfiguration.getServerUrl() + "/healthcheck") + .build()) + .execute() + .code(); + success = status == 200; + if (!success) { + message = Integer.toString(status); + } + } catch (IOException e) { + message = e.getMessage(); + success = false; + } + + if (success) { + if (!serverHealthy.getAndSet(true)) { + logger.info("Elastic APM server is available"); + } + } else { + if (serverHealthy.getAndSet(false)) { + logger.warn("Elastic APM server is not available ({})", message); + } + } + } + } } From f599408c43d298b4b970634ce94c18aecabf8a2b Mon Sep 17 00:00:00 2001 From: Felix Barnsteiner Date: Fri, 29 Jun 2018 09:33:29 +0200 Subject: [PATCH 2/2] Fix tests --- .../elastic/apm/report/ApmServerReporterIntegrationTest.java | 4 +++- .../apm/servlet/AbstractServletContainerIntegrationTest.java | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/apm-agent-core/src/test/java/co/elastic/apm/report/ApmServerReporterIntegrationTest.java b/apm-agent-core/src/test/java/co/elastic/apm/report/ApmServerReporterIntegrationTest.java index da0532887c..9da8567fa1 100644 --- a/apm-agent-core/src/test/java/co/elastic/apm/report/ApmServerReporterIntegrationTest.java +++ b/apm-agent-core/src/test/java/co/elastic/apm/report/ApmServerReporterIntegrationTest.java @@ -75,7 +75,9 @@ static void stopServer() { @BeforeEach void setUp() { handler = exchange -> { - receivedHttpRequests.incrementAndGet(); + if (!exchange.getRequestPath().equals("/healthcheck")) { + receivedHttpRequests.incrementAndGet(); + } exchange.setStatusCode(200).endExchange(); }; receivedHttpRequests.set(0); diff --git a/integration-tests/simple-webapp-integration-test/src/test/java/co/elastic/apm/servlet/AbstractServletContainerIntegrationTest.java b/integration-tests/simple-webapp-integration-test/src/test/java/co/elastic/apm/servlet/AbstractServletContainerIntegrationTest.java index 6cb5f01891..fae69d5698 100644 --- a/integration-tests/simple-webapp-integration-test/src/test/java/co/elastic/apm/servlet/AbstractServletContainerIntegrationTest.java +++ b/integration-tests/simple-webapp-integration-test/src/test/java/co/elastic/apm/servlet/AbstractServletContainerIntegrationTest.java @@ -111,6 +111,7 @@ private static void checkFilePresent(String pathToWar) { public final void setUpMockServer() { mockServerContainer.getClient().when(request("/v1/transactions")).respond(HttpResponse.response().withStatusCode(200)); mockServerContainer.getClient().when(request("/v1/errors")).respond(HttpResponse.response().withStatusCode(200)); + mockServerContainer.getClient().when(request("/healthcheck")).respond(HttpResponse.response().withStatusCode(200)); servletContainer.waitingFor(Wait.forHttp(contextPath + "/status.jsp").forPort(webPort)); servletContainer.start(); }