You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by gh...@apache.org on 2017/05/08 07:13:00 UTC

svn commit: r1794289 - in /sling/trunk/bundles/extensions/healthcheck/core/src: main/java/org/apache/sling/hc/core/impl/servlet/ test/java/org/apache/sling/hc/core/impl/servlet/

Author: ghenzler
Date: Mon May  8 07:13:00 2017
New Revision: 1794289

URL: http://svn.apache.org/viewvc?rev=1794289&view=rev
Log:
SLING-6834 new verbose text format (.verbose.txt) for HC servlet

Added:
    sling/trunk/bundles/extensions/healthcheck/core/src/main/java/org/apache/sling/hc/core/impl/servlet/ResultTxtVerboseSerializer.java   (with props)
Modified:
    sling/trunk/bundles/extensions/healthcheck/core/src/main/java/org/apache/sling/hc/core/impl/servlet/HealthCheckExecutorServlet.java
    sling/trunk/bundles/extensions/healthcheck/core/src/main/java/org/apache/sling/hc/core/impl/servlet/ResultHtmlSerializer.java
    sling/trunk/bundles/extensions/healthcheck/core/src/main/java/org/apache/sling/hc/core/impl/servlet/ResultTxtSerializer.java
    sling/trunk/bundles/extensions/healthcheck/core/src/test/java/org/apache/sling/hc/core/impl/servlet/HealthCheckExecutorServletTest.java

Modified: sling/trunk/bundles/extensions/healthcheck/core/src/main/java/org/apache/sling/hc/core/impl/servlet/HealthCheckExecutorServlet.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/healthcheck/core/src/main/java/org/apache/sling/hc/core/impl/servlet/HealthCheckExecutorServlet.java?rev=1794289&r1=1794288&r2=1794289&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/healthcheck/core/src/main/java/org/apache/sling/hc/core/impl/servlet/HealthCheckExecutorServlet.java (original)
+++ sling/trunk/bundles/extensions/healthcheck/core/src/main/java/org/apache/sling/hc/core/impl/servlet/HealthCheckExecutorServlet.java Mon May  8 07:13:00 2017
@@ -38,7 +38,6 @@ import org.apache.felix.scr.annotations.
 import org.apache.felix.scr.annotations.Deactivate;
 import org.apache.felix.scr.annotations.Property;
 import org.apache.felix.scr.annotations.Reference;
-import org.apache.felix.scr.annotations.Service;
 import org.apache.sling.commons.osgi.PropertiesUtil;
 import org.apache.sling.hc.api.Result;
 import org.apache.sling.hc.api.Result.Status;
@@ -109,6 +108,7 @@ public class HealthCheckExecutorServlet
     static final String FORMAT_JSON = "json";
     static final String FORMAT_JSONP = "jsonp";
     static final String FORMAT_TXT = "txt";
+    static final String FORMAT_VERBOSE_TXT = "verbose.txt";
 
     private static final String CONTENT_TYPE_HTML = "text/html";
     private static final String CONTENT_TYPE_TXT = "text/plain";
@@ -148,6 +148,9 @@ public class HealthCheckExecutorServlet
     @Reference
     ResultTxtSerializer txtSerializer;
 
+    @Reference
+    ResultTxtVerboseSerializer verboseTxtSerializer;
+
     @Activate
     protected final void activate(final ComponentContext context) {
         final Dictionary<?, ?> properties = context.getProperties();
@@ -160,7 +163,7 @@ public class HealthCheckExecutorServlet
         servletsToRegister.put(this.servletPath + "." + FORMAT_JSON, new ProxyServlet(FORMAT_JSON));
         servletsToRegister.put(this.servletPath + "." + FORMAT_JSONP, new ProxyServlet(FORMAT_JSONP));
         servletsToRegister.put(this.servletPath + "." + FORMAT_TXT, new ProxyServlet(FORMAT_TXT));
-
+        servletsToRegister.put(this.servletPath + "." + FORMAT_VERBOSE_TXT, new ProxyServlet(FORMAT_VERBOSE_TXT));
 
         if (disabled) {
             LOG.info("Health Check Servlet is disabled by configuration");
@@ -197,12 +200,13 @@ public class HealthCheckExecutorServlet
     }
 
     protected void doGet(final HttpServletRequest request, final HttpServletResponse response, final String format) throws ServletException, IOException {
-        String tagsStr = StringUtils.defaultIfEmpty(StringUtils.substringBeforeLast(request.getPathInfo(), "."), "").replace("/", "");
+        String pathInfo = request.getPathInfo();
+        String tagsStr = StringUtils.removeStart(splitFormat(pathInfo)[0], "/");
         if (StringUtils.isBlank(tagsStr)) {
             // if not provided via path use parameter or default
             tagsStr = StringUtils.defaultIfEmpty(request.getParameter(PARAM_TAGS.name), "");
         }
-        final String[] tags = tagsStr.split("[, ;]+");
+        final String[] tags = tagsStr.split("[,;]+");
 
         final Boolean includeDebug = Boolean.valueOf(request.getParameter(PARAM_INCLUDE_DEBUG.name));
         final Map<Result.Status, Integer> statusMapping = request.getParameter(PARAM_HTTP_STATUS.name) != null ? getStatusMapping(request
@@ -241,29 +245,44 @@ public class HealthCheckExecutorServlet
         } else if (FORMAT_JSONP.equals(format)) {
             String jsonpCallback = StringUtils.defaultIfEmpty(request.getParameter(PARAM_JSONP_CALLBACK.name), JSONP_CALLBACK_DEFAULT);
             sendJsonResponse(overallResult, executionResults, jsonpCallback, response, includeDebug);
-        } else if (FORMAT_TXT.equals(format)) {
-            sendTxtResponse(overallResult, response);
+        } else if (StringUtils.endsWith(format, FORMAT_TXT)) {
+            sendTxtResponse(overallResult, response, StringUtils.equals(format, FORMAT_VERBOSE_TXT), executionResults, includeDebug);
         } else {
             response.setContentType("text/plain");
-            response.getWriter().println("Invalid format " + format + " - supported formats: html|json|jsonp|txt");
+            response.getWriter().println("Invalid format " + format + " - supported formats: html|json|jsonp|txt|verbose.txt");
         }
     }
 
     @Override
     protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException {
-        String format = StringUtils.substringAfterLast(request.getPathInfo(), ".");
+        String pathInfo = request.getPathInfo();
+        String format = splitFormat(pathInfo)[1];
         if (StringUtils.isBlank(format)) {
             // if not provided via extension use parameter or default
             format = StringUtils.defaultIfEmpty(request.getParameter(PARAM_FORMAT.name), FORMAT_HTML);
         }
-
         doGet(request, response, format);
     }
 
-    private void sendTxtResponse(final Result overallResult, final HttpServletResponse response) throws IOException {
+    private String[] splitFormat(String pathInfo) {
+        for (String format : new String[] { FORMAT_HTML, FORMAT_JSON, FORMAT_JSONP, FORMAT_VERBOSE_TXT, FORMAT_TXT }) {
+            String formatWithDot = "." + format;
+            if (StringUtils.endsWith(pathInfo, formatWithDot)) {
+                return new String[] { StringUtils.substringBeforeLast(pathInfo, formatWithDot), format };
+            }
+        }
+        return new String[] { pathInfo, null };
+    }
+
+    private void sendTxtResponse(final Result overallResult, final HttpServletResponse response, boolean verbose,
+            List<HealthCheckExecutionResult> executionResults, boolean includeDebug) throws IOException {
         response.setContentType(CONTENT_TYPE_TXT);
         response.setCharacterEncoding("UTF-8");
-        response.getWriter().write(txtSerializer.serialize(overallResult));
+        if (verbose) {
+            response.getWriter().write(verboseTxtSerializer.serialize(overallResult, executionResults, includeDebug));
+        } else {
+            response.getWriter().write(txtSerializer.serialize(overallResult));
+        }
     }
 
     private void sendJsonResponse(final Result overallResult, final List<HealthCheckExecutionResult> executionResults, final String jsonpCallback,

Modified: sling/trunk/bundles/extensions/healthcheck/core/src/main/java/org/apache/sling/hc/core/impl/servlet/ResultHtmlSerializer.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/healthcheck/core/src/main/java/org/apache/sling/hc/core/impl/servlet/ResultHtmlSerializer.java?rev=1794289&r1=1794288&r2=1794289&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/healthcheck/core/src/main/java/org/apache/sling/hc/core/impl/servlet/ResultHtmlSerializer.java (original)
+++ sling/trunk/bundles/extensions/healthcheck/core/src/main/java/org/apache/sling/hc/core/impl/servlet/ResultHtmlSerializer.java Mon May  8 07:13:00 2017
@@ -41,8 +41,7 @@ import org.osgi.service.component.Compon
 
 /** Serializes health check results into html format. */
 @Service(ResultHtmlSerializer.class)
-@Component(metatype = true, name="Apache Sling Health Check Result Serializer",
-    description="Serializer for health check results")
+@Component(metatype = true, name = "Apache Sling Health Check Result HTML Serializer", description = "Serializer for health check results in HTML format")
 public class ResultHtmlSerializer {
     private static final String CSS_STYLE_DEFAULT = "body { font-size:12px; font-family:arial,verdana,sans-serif;background-color:#FFFDF1; }\n"
             + "h1 { font-size:20px;}\n"

Modified: sling/trunk/bundles/extensions/healthcheck/core/src/main/java/org/apache/sling/hc/core/impl/servlet/ResultTxtSerializer.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/healthcheck/core/src/main/java/org/apache/sling/hc/core/impl/servlet/ResultTxtSerializer.java?rev=1794289&r1=1794288&r2=1794289&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/healthcheck/core/src/main/java/org/apache/sling/hc/core/impl/servlet/ResultTxtSerializer.java (original)
+++ sling/trunk/bundles/extensions/healthcheck/core/src/main/java/org/apache/sling/hc/core/impl/servlet/ResultTxtSerializer.java Mon May  8 07:13:00 2017
@@ -21,6 +21,8 @@ import org.apache.felix.scr.annotations.
 import org.apache.felix.scr.annotations.Service;
 import org.apache.sling.hc.api.Result;
 
+/** Serializes health check results into a simple text message (ideal to be used by a load balancer that would discard
+ * further information). */
 @Component
 @Service(ResultTxtSerializer.class)
 public class ResultTxtSerializer {

Added: sling/trunk/bundles/extensions/healthcheck/core/src/main/java/org/apache/sling/hc/core/impl/servlet/ResultTxtVerboseSerializer.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/healthcheck/core/src/main/java/org/apache/sling/hc/core/impl/servlet/ResultTxtVerboseSerializer.java?rev=1794289&view=auto
==============================================================================
--- sling/trunk/bundles/extensions/healthcheck/core/src/main/java/org/apache/sling/hc/core/impl/servlet/ResultTxtVerboseSerializer.java (added)
+++ sling/trunk/bundles/extensions/healthcheck/core/src/main/java/org/apache/sling/hc/core/impl/servlet/ResultTxtVerboseSerializer.java Mon May  8 07:13:00 2017
@@ -0,0 +1,153 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The SF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ */
+package org.apache.sling.hc.core.impl.servlet;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.WordUtils;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.commons.osgi.PropertiesUtil;
+import org.apache.sling.hc.api.Result;
+import org.apache.sling.hc.api.ResultLog;
+import org.apache.sling.hc.api.execution.HealthCheckExecutionResult;
+import org.apache.sling.hc.util.FormattingResultLog;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Serializes health check results into a verbose text message. */
+@Component(label = "Apache Sling Health Check Verbose Text Serializer", description = "Serializes health check results to a verbose text format", metatype = true)
+@Service(ResultTxtVerboseSerializer.class)
+public class ResultTxtVerboseSerializer {
+
+    private static final Logger LOG = LoggerFactory.getLogger(ResultTxtVerboseSerializer.class);
+
+    private static final String NEWLINE = "\n"; // not using system prop 'line.separator' as not the local but the calling system is relevant.
+
+    public static final int PROP_TOTAL_WIDTH_DEFAULT = 140;
+    public static final String PROP_TOTAL_WIDTH = "totalWidth";
+    @Property(name = PROP_TOTAL_WIDTH, label = "Total Width", description = "Total width of all columns in verbose txt rendering (in characters)", intValue = PROP_TOTAL_WIDTH_DEFAULT)
+    private int totalWidth;
+
+    public static final int PROP_COL_WIDTH_NAME_DEFAULT = 30;
+    public static final String PROP_COL_WIDTH_NAME = "colWidthName";
+    @Property(name = PROP_COL_WIDTH_NAME, label = "Name Column Width", description = "Column width of health check name (in characters)", intValue = PROP_COL_WIDTH_NAME_DEFAULT)
+    private int colWidthName;
+
+    public static final int PROP_COL_WIDTH_RESULT_DEFAULT = 9;
+    public static final String PROP_COL_WIDTH_RESULT = "colWidthResult";
+    @Property(name = PROP_COL_WIDTH_RESULT, label = "Result Column Width", description = "Column width of health check result (in characters)", intValue = PROP_COL_WIDTH_RESULT_DEFAULT)
+    private int colWidthResult;
+
+    public static final int PROP_COL_WIDTH_TIMING_DEFAULT = 22;
+    public static final String PROP_COL_WIDTH_TIMING = "colWidthTiming";
+    @Property(name = PROP_COL_WIDTH_TIMING, label = "Timing Column Width", description = "Column width of health check timing (in characters)", intValue = PROP_COL_WIDTH_TIMING_DEFAULT)
+    private int colWidthTiming;
+
+    private int colWidthWithoutLog;
+    private int colWidthLog;
+
+    @Activate
+    protected final void activate(Map<?, ?> properties) {
+        this.totalWidth = PropertiesUtil.toInteger(properties.get(PROP_TOTAL_WIDTH), PROP_TOTAL_WIDTH_DEFAULT);
+        this.colWidthName = PropertiesUtil.toInteger(properties.get(PROP_COL_WIDTH_NAME), PROP_COL_WIDTH_NAME_DEFAULT);
+        this.colWidthResult = PropertiesUtil.toInteger(properties.get(PROP_COL_WIDTH_RESULT), PROP_COL_WIDTH_RESULT_DEFAULT);
+        this.colWidthTiming = PropertiesUtil.toInteger(properties.get(PROP_COL_WIDTH_TIMING), PROP_COL_WIDTH_TIMING_DEFAULT);
+
+        colWidthWithoutLog = colWidthName + colWidthResult + colWidthTiming;
+        colWidthLog = totalWidth - colWidthWithoutLog;
+    }
+
+    public String serialize(final Result overallResult, final List<HealthCheckExecutionResult> executionResults, boolean includeDebug) {
+
+        LOG.debug("Sending verbose txt response... ");
+        
+        StringBuilder resultStr = new StringBuilder();
+
+        resultStr.append(StringUtils.repeat("-", totalWidth) + NEWLINE);
+        resultStr.append(StringUtils.center("Overall Health Result: " + overallResult.getStatus().toString(), totalWidth) + NEWLINE);
+        resultStr.append(StringUtils.repeat("-", totalWidth) + NEWLINE);
+        resultStr.append(StringUtils.rightPad("Name", colWidthName));
+        resultStr.append(StringUtils.rightPad("Result", colWidthResult));
+        resultStr.append(StringUtils.rightPad("Timing", colWidthTiming));
+        resultStr.append("Logs" + NEWLINE);
+        resultStr.append(StringUtils.repeat("-", totalWidth) + NEWLINE);
+
+        final DateFormat dfShort = new SimpleDateFormat("HH:mm:ss.SSS");
+
+        for (HealthCheckExecutionResult healthCheckResult : executionResults) {
+            appendVerboseTxtForResult(resultStr, healthCheckResult, includeDebug, dfShort);
+        }
+        resultStr.append(StringUtils.repeat("-", totalWidth) + NEWLINE);
+
+        return resultStr.toString();
+
+    }
+
+    private void appendVerboseTxtForResult(StringBuilder resultStr, HealthCheckExecutionResult healthCheckResult, boolean includeDebug, DateFormat dfShort) {
+
+        String wrappedName = WordUtils.wrap(healthCheckResult.getHealthCheckMetadata().getName(), colWidthName);
+
+        String relevantNameStringForPadding = StringUtils.contains(wrappedName, "\n") ? StringUtils.substringAfterLast(wrappedName, "\n") : wrappedName;
+        int paddingSize = colWidthName - relevantNameStringForPadding.length();
+
+        resultStr.append(wrappedName + StringUtils.repeat(" ", paddingSize));
+        resultStr.append(StringUtils.rightPad(healthCheckResult.getHealthCheckResult().getStatus().toString(), colWidthResult));
+        resultStr.append(StringUtils.rightPad("[" + dfShort.format(healthCheckResult.getFinishedAt())
+                + "|" + FormattingResultLog.msHumanReadable(healthCheckResult.getElapsedTimeInMs()) + "]", colWidthTiming));
+
+        boolean isFirst = true;
+        for (ResultLog.Entry logEntry : healthCheckResult.getHealthCheckResult()) {
+            if (!includeDebug && logEntry.getStatus() == Result.Status.DEBUG) {
+                continue;
+            }
+            if(isFirst) {
+                isFirst = false;
+            } else {
+                resultStr.append(StringUtils.repeat(" ", colWidthWithoutLog));
+            }
+
+            String oneLineMessage = getStatusForTxtLog(logEntry) + logEntry.getMessage();
+            String messageToPrint = WordUtils.wrap(oneLineMessage, colWidthLog, "\n" + StringUtils.repeat(" ", colWidthWithoutLog), true);
+
+            resultStr.append(messageToPrint);
+            resultStr.append(NEWLINE);
+        }
+        
+        if (isFirst) {
+            // no log entry exists, ensure newline
+            resultStr.append(NEWLINE);
+        }
+
+    }
+
+    private String getStatusForTxtLog(ResultLog.Entry logEntry) {
+        if (logEntry.getStatus() == Result.Status.OK || logEntry.getStatus() == Result.Status.INFO) {
+            return "";
+        } else {
+            return logEntry.getStatus().toString() + " ";
+        }
+    }
+
+}

Propchange: sling/trunk/bundles/extensions/healthcheck/core/src/main/java/org/apache/sling/hc/core/impl/servlet/ResultTxtVerboseSerializer.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: sling/trunk/bundles/extensions/healthcheck/core/src/test/java/org/apache/sling/hc/core/impl/servlet/HealthCheckExecutorServletTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/healthcheck/core/src/test/java/org/apache/sling/hc/core/impl/servlet/HealthCheckExecutorServletTest.java?rev=1794289&r1=1794288&r2=1794289&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/healthcheck/core/src/test/java/org/apache/sling/hc/core/impl/servlet/HealthCheckExecutorServletTest.java (original)
+++ sling/trunk/bundles/extensions/healthcheck/core/src/test/java/org/apache/sling/hc/core/impl/servlet/HealthCheckExecutorServletTest.java Mon May  8 07:13:00 2017
@@ -20,11 +20,13 @@ package org.apache.sling.hc.core.impl.se
 import static org.junit.Assert.assertEquals;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.argThat;
-import static org.mockito.Matchers.eq;
 import static org.mockito.Matchers.contains;
+import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.MockitoAnnotations.initMocks;
 
 import java.io.IOException;
 import java.io.PrintWriter;
@@ -47,14 +49,17 @@ import org.hamcrest.Description;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.ArgumentMatcher;
+import org.mockito.InjectMocks;
 import org.mockito.Mock;
+import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceReference;
 
 public class HealthCheckExecutorServletTest {
 
-    private HealthCheckExecutorServlet healthCheckExecutorServlet;
+    @InjectMocks
+    private HealthCheckExecutorServlet healthCheckExecutorServlet = new HealthCheckExecutorServlet();
 
     @Mock
     private HttpServletRequest request;
@@ -75,6 +80,9 @@ public class HealthCheckExecutorServletT
     private ResultTxtSerializer txtSerializer;
 
     @Mock
+    private ResultTxtVerboseSerializer verboseTxtSerializer;
+
+    @Mock
     private ServiceReference hcServiceRef;
 
     @Mock
@@ -82,14 +90,7 @@ public class HealthCheckExecutorServletT
 
     @Before
     public void setup() throws IOException {
-
-        healthCheckExecutorServlet = new HealthCheckExecutorServlet();
-
-        MockitoAnnotations.initMocks(this);
-        healthCheckExecutorServlet.healthCheckExecutor = healthCheckExecutor;
-        healthCheckExecutorServlet.htmlSerializer = htmlSerializer;
-        healthCheckExecutorServlet.jsonSerializer = jsonSerializer;
-        healthCheckExecutorServlet.txtSerializer = txtSerializer;
+        initMocks(this);
 
         doReturn(500L).when(hcServiceRef).getProperty(Constants.SERVICE_ID);
         doReturn(writer).when(response).getWriter();
@@ -108,6 +109,7 @@ public class HealthCheckExecutorServletT
 
         verifyZeroInteractions(jsonSerializer);
         verifyZeroInteractions(txtSerializer);
+        verifyZeroInteractions(verboseTxtSerializer);
         verify(htmlSerializer)
                 .serialize(resultEquals(new Result(Result.Status.CRITICAL, "Overall Status CRITICAL")), eq(executionResults), contains("Supported URL parameters"), eq(false));
     }
@@ -130,6 +132,7 @@ public class HealthCheckExecutorServletT
 
         verifyZeroInteractions(htmlSerializer);
         verifyZeroInteractions(txtSerializer);
+        verifyZeroInteractions(verboseTxtSerializer);
         verify(jsonSerializer).serialize(resultEquals(new Result(Result.Status.WARN, "Overall Status WARN")), eq(executionResults), anyString(),
                 eq(false));
 
@@ -140,7 +143,7 @@ public class HealthCheckExecutorServletT
 
         String testTag = "testTag";
         doReturn(testTag).when(request).getParameter(HealthCheckExecutorServlet.PARAM_TAGS.name);
-        doReturn("txt").when(request).getParameter(HealthCheckExecutorServlet.PARAM_FORMAT.name);
+        doReturn(HealthCheckExecutorServlet.FORMAT_TXT).when(request).getParameter(HealthCheckExecutorServlet.PARAM_FORMAT.name);
         doReturn("true").when(request).getParameter(HealthCheckExecutorServlet.PARAM_COMBINE_TAGS_WITH_OR.name);
         int timeout = 5000;
         doReturn(timeout + "").when(request).getParameter(HealthCheckExecutorServlet.PARAM_OVERRIDE_GLOBAL_TIMEOUT.name);
@@ -154,10 +157,30 @@ public class HealthCheckExecutorServletT
 
         verifyZeroInteractions(htmlSerializer);
         verifyZeroInteractions(jsonSerializer);
+        verifyZeroInteractions(verboseTxtSerializer);
         verify(txtSerializer).serialize(resultEquals(new Result(Result.Status.WARN, "Overall Status WARN")));
 
     }
 
+    @Test
+    public void testDoGetVerboseTxt() throws ServletException, IOException {
+
+        String testTag = "testTag";
+        doReturn(testTag).when(request).getParameter(HealthCheckExecutorServlet.PARAM_TAGS.name);
+        doReturn(HealthCheckExecutorServlet.FORMAT_VERBOSE_TXT).when(request).getParameter(HealthCheckExecutorServlet.PARAM_FORMAT.name);
+
+        List<HealthCheckExecutionResult> executionResults = getExecutionResults(Result.Status.WARN);
+        doReturn(executionResults).when(healthCheckExecutor).execute(any(HealthCheckExecutionOptions.class), eq(testTag));
+
+        healthCheckExecutorServlet.doGet(request, response);
+
+        verifyZeroInteractions(htmlSerializer);
+        verifyZeroInteractions(jsonSerializer);
+        verifyZeroInteractions(txtSerializer);
+        verify(verboseTxtSerializer).serialize(resultEquals(new Result(Result.Status.WARN, "Overall Status WARN")), eq(executionResults), eq(false));
+
+    }
+
     private List<HealthCheckExecutionResult> getExecutionResults(Result.Status worstStatus) {
         List<HealthCheckExecutionResult> results = new ArrayList<HealthCheckExecutionResult>();
         results.add(new ExecutionResult(new HealthCheckMetadata(hcServiceRef), new Result(worstStatus, worstStatus.name()), 100));