Skip to content

Commit

Permalink
Emit a 500 status code when rendering health checks if any are unheal…
Browse files Browse the repository at this point in the history
…thy.

Closes ratpack#912.
  • Loading branch information
ldaley committed Mar 22, 2016
1 parent 8b45d34 commit 21bc2c6
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,29 +16,59 @@

package ratpack.health.internal;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.ByteBufOutputStream;
import ratpack.handling.Context;
import ratpack.health.HealthCheck;
import ratpack.health.HealthCheckResults;
import ratpack.render.RendererSupport;

import java.io.BufferedOutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.Map;

public class HealthCheckResultsRenderer extends RendererSupport<HealthCheckResults> {

private final ByteBufAllocator byteBufAllocator;

public HealthCheckResultsRenderer(ByteBufAllocator byteBufAllocator) {
this.byteBufAllocator = byteBufAllocator;
}

@SuppressWarnings("ThrowableResultOfMethodCallIgnored")
@Override
public void render(Context context, HealthCheckResults healthCheckResults) throws Exception {
StringBuilder builder = new StringBuilder();
healthCheckResults.getResults().forEach((name, result) -> {
if (builder.length() > 0) {
builder.append("\n");
}
builder.append(name).append(" : ").append(result.isHealthy() ? "HEALTHY" : "UNHEALTHY");
if (!result.isHealthy()) {
builder.append(" [").append(result.getMessage()).append("]");
if (result.getError() != null) {
builder.append(" [").append(result.getError().toString()).append("]");
ByteBuf buffer = byteBufAllocator.buffer();
boolean first = true;
boolean unhealthy = false;

try {
Writer writer = new OutputStreamWriter(new BufferedOutputStream(new ByteBufOutputStream(buffer)));
for (Map.Entry<String, HealthCheck.Result> entry : healthCheckResults.getResults().entrySet()) {
if (first) {
first = false;
} else {
writer.write("\n");
}
String name = entry.getKey();
HealthCheck.Result result = entry.getValue();
writer.append(name).append(" : ").append(result.isHealthy() ? "HEALTHY" : "UNHEALTHY");
if (!result.isHealthy()) {
unhealthy = true;
writer.append(" [").append(result.getMessage()).append("]");
if (result.getError() != null) {
writer.append(" [").append(result.getError().toString()).append("]");
}
}
}
});
writer.close();
} catch (Exception e) {
buffer.release();
throw e;
}

context.getResponse().send(builder.toString());
context.getResponse().status(unhealthy ? 500 : 200).send(buffer);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ public static Registry buildBaseRegistry(RatpackServer ratpackServer, Imposition
}))
.add(HttpClient.class, HttpClient.httpClient(PooledByteBufAllocator.DEFAULT, serverConfig.getMaxContentLength()))
.add(ServerSentEventStreamClient.class, ServerSentEventStreamClient.sseStreamClient(PooledByteBufAllocator.DEFAULT))
.add(HealthCheckResultsRenderer.class, new HealthCheckResultsRenderer())
.add(HealthCheckResultsRenderer.class, new HealthCheckResultsRenderer(PooledByteBufAllocator.DEFAULT))
.add(RequestId.Generator.class, new UuidBasedRequestIdGenerator());

addConfigObjects(serverConfig, baseRegistryBuilder);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,10 @@ class HealthCheckHandlerSpec extends RatpackGroovyDslSpec {
}

then:
def result = getText("health-checks")
assert result.startsWith("foo")
assert result.contains("HEALTHY")
def result = get("health-checks")
result.body.text.startsWith("foo")
result.body.text.contains("HEALTHY")
result.statusCode == 200
}

def "render unhealthy check"() {
Expand All @@ -125,10 +126,11 @@ class HealthCheckHandlerSpec extends RatpackGroovyDslSpec {
}

then:
def result = getText("health-checks")
assert result.startsWith("foo")
assert result.contains("UNHEALTHY")
assert result.contains("EXECUTION TIMEOUT")
def result = get("health-checks")
result.body.text.startsWith("foo")
result.body.text.contains("UNHEALTHY")
result.body.text.contains("EXECUTION TIMEOUT")
result.statusCode == 500
}

def "render unhealthy check with exception stack trace"() {
Expand Down Expand Up @@ -227,7 +229,10 @@ class HealthCheckHandlerSpec extends RatpackGroovyDslSpec {
}

then:
assert getText("health-checks").isEmpty()
with(get("health-checks")) {
body.text.empty
statusCode == 200
}
}

def "render healthy check results for more health checks"() {
Expand Down Expand Up @@ -257,16 +262,16 @@ class HealthCheckHandlerSpec extends RatpackGroovyDslSpec {

then:
def result = getText("health-checks")
String[] results = result.split("\n")
assert results.length == 4
assert results[0].startsWith("bar")
assert results[0].contains("HEALTHY")
assert results[1].startsWith("baz")
assert results[1].contains("HEALTHY")
assert results[2].startsWith("foo")
assert results[2].contains("HEALTHY")
assert results[3].startsWith("quux")
assert results[3].contains("HEALTHY")
def results = result.split("\n")
results.length == 4
results[0].startsWith("bar")
results[0].contains("HEALTHY")
results[1].startsWith("baz")
results[1].contains("HEALTHY")
results[2].startsWith("foo")
results[2].contains("HEALTHY")
results[3].startsWith("quux")
results[3].contains("HEALTHY")
}

def "health checks run in parallel"() {
Expand Down Expand Up @@ -295,10 +300,10 @@ class HealthCheckHandlerSpec extends RatpackGroovyDslSpec {
then:
def result = getText("health-checks")
String[] results = result.split("\n")
assert results[0].startsWith("baz")
assert results[0].contains("HEALTHY")
assert results[1].startsWith("quux")
assert results[1].contains("HEALTHY")
results[0].startsWith("baz")
results[0].contains("HEALTHY")
results[1].startsWith("quux")
results[1].contains("HEALTHY")
}

def "duplicated health checks renders only once"() {
Expand All @@ -321,9 +326,9 @@ class HealthCheckHandlerSpec extends RatpackGroovyDslSpec {
then:
def result = getText("health-checks")
String[] results = result.split("\n")
assert results.size() == 1
assert results[0].startsWith("foo")
assert results[0].contains("HEALTHY")
results.size() == 1
results[0].startsWith("foo")
results[0].contains("HEALTHY")
}

def "render health check by token if more health checks in registry"() {
Expand Down Expand Up @@ -351,16 +356,16 @@ class HealthCheckHandlerSpec extends RatpackGroovyDslSpec {
then:
def result = getText("health-checks/foo")
String[] results = result.split("\n")
assert results.length == 1
assert results[0].startsWith("foo")
assert results[0].contains("HEALTHY")
results.length == 1
results[0].startsWith("foo")
results[0].contains("HEALTHY")

then:
def result2 = getText("health-checks/baz")
String[] results2 = result2.split("\n")
assert results.length == 1
assert results2[0].startsWith("baz")
assert results2[0].contains("UNHEALTHY")
results.length == 1
results2[0].startsWith("baz")
results2[0].contains("UNHEALTHY")
}

def "render json health check results for custom renderer"() {
Expand Down Expand Up @@ -395,12 +400,12 @@ class HealthCheckHandlerSpec extends RatpackGroovyDslSpec {
spec.headers.add("Accept", "application/json")
}
def result = get("health-checks")
assert result.body.contentType.toString() == MediaType.APPLICATION_JSON
def results = json.parse(result.body.inputStream)
assert results.foo.healthy == true
assert results.bar.healthy == true
assert results.baz.healthy == false
assert results.baz.message == "Unhealthy"
result.body.contentType.toString() == MediaType.APPLICATION_JSON
Map<String, Map<String, ?>> results = json.parse(result.body.inputStream)
results.foo.healthy == true
results.bar.healthy == true
results.baz.healthy == false
results.baz.message == "Unhealthy"
}

}
2 changes: 2 additions & 0 deletions release-notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@
This file contains the in progress release notes during the cycle.
It should not be considered the final announcement for any release at any time.
-->

-- Need to mention breaking change of https://github.com/ratpack/ratpack/issues/912

0 comments on commit 21bc2c6

Please sign in to comment.