Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ignore accept header in requests to metrics service #1345

Merged
merged 4 commits into from
Aug 27, 2020
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

### Bug Fixes

* The metrics HTTP server no longer rejects requests containing `Accept` header that doesn't precisely match the prometheus text format [\#1345](https://github.com/hyperledger/besu/pull/1345)

#### Previously identified known issues

- [Logs queries missing results against chain head](KNOWN_ISSUES.md#Logs-queries-missing-results-against-chain-head)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,7 @@ public CompletableFuture<?> start() {
router.route("/").method(HttpMethod.GET).handler(this::handleEmptyRequest);

// Endpoint for Prometheus metrics monitoring.
router
.route("/metrics")
.method(HttpMethod.GET)
.produces(TextFormat.CONTENT_TYPE_004)
.handler(this::metricsRequest);
router.route("/metrics").method(HttpMethod.GET).handler(this::metricsRequest);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe just check for "text/plain" instead of completely dropping Prometheus' very specific version?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given we only have one representation to offer we shouldn't be doing any content negotiation (which is what the Accept header is for). If we had multiple representations, then yes filtering to a particular Accept makes sense but if there's a default version, it should just be returned even if it doesn't match Accept.

For example this works fine:

curl --fail -v -H 'Accept: foo/foo' https://www.google.com/

The caller can then decide if they want to process the response based on the Content-Type header.


final CompletableFuture<?> resultFuture = new CompletableFuture<>();
httpServer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,22 @@ public void metricsAreAbsentWhenFiltered() throws Exception {
}
}

@Test
// There is only one available representation so content negotiation should not be used
public void acceptHeaderIgnored() throws Exception {
final Request metricsRequest =
new Request.Builder().addHeader("Accept", "text/xml").url(baseUrl + "/metrics").build();
try (final Response resp = client.newCall(metricsRequest).execute()) {
assertThat(resp.code()).isEqualTo(200);
// Check general format of result, it maps to java.util.Properties
final Properties props = new Properties();
props.load(resp.body().byteStream());

// We should have JVM metrics already loaded, verify a simple key.
assertThat(props).containsKey("jvm_threads_deadlocked");
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
}
// Assert we still get the Content-Type Prometheus likes
assertThat(resp.header("Content-Type")).isEqualTo(TextFormat.CONTENT_TYPE_004);
}

You will also need import io.prometheus.client.exporter.common.TextFormat; but GitHub won't let me suggest that far our of the code diff.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added.

}

private Request buildGetRequest(final String path) {
return new Request.Builder().get().url(baseUrl + path).build();
}
Expand Down