Skip to content

Commit b1bb421

Browse files
Polish redacting Dynatrace token in error logs
1 parent 2580480 commit b1bb421

File tree

2 files changed

+35
-32
lines changed

2 files changed

+35
-32
lines changed

implementations/micrometer-registry-dynatrace/src/main/java/io/micrometer/dynatrace/v1/DynatraceExporterV1.java

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@
5353
*/
5454
public class DynatraceExporterV1 extends AbstractDynatraceExporter {
5555

56-
private static final int MAX_MESSAGE_SIZE = 15360; // max message size in bytes that
57-
// Dynatrace will accept
56+
// max message size in bytes that Dynatrace will accept
57+
private static final int MAX_MESSAGE_SIZE = 15360;
5858

5959
private final InternalLogger logger = InternalLoggerFactory.getInstance(DynatraceExporterV1.class);
6060

@@ -194,12 +194,10 @@ void putCustomMetric(final DynatraceMetricDefinition customMetric) {
194194
.withJsonContent(customMetric.asJson());
195195
}
196196
catch (Exception ex) {
197-
// log only the error message without the token
198197
if (logger.isErrorEnabled()) {
199198
logger.error("failed to build request: {}", redactToken(ex.getMessage()));
200199
}
201-
// do not attempt to export if the creation of the request already failed
202-
return;
200+
return; // don't try to export data points, the request can't be built
203201
}
204202

205203
HttpSender.Response httpResponse = trySendHttpRequest(requestBuilder);
@@ -225,9 +223,8 @@ private void postCustomMetricValues(String type, String group, List<DynatraceTim
225223
if (logger.isErrorEnabled()) {
226224
logger.error("failed to build request: {}", redactToken(ex.getMessage()));
227225
}
228-
// don't export the other data points, since the endpoint will always be
229-
// invalid.
230-
return;
226+
227+
return; // don't try to export data points, the request can't be built
231228
}
232229

233230
HttpSender.Response httpResponse = trySendHttpRequest(requestBuilder);
@@ -249,17 +246,15 @@ private void postCustomMetricValues(String type, String group, List<DynatraceTim
249246

250247
// VisibleForTesting
251248
HttpSender.Response trySendHttpRequest(HttpSender.Request.Builder requestBuilder) {
252-
HttpSender.Response httpResponse;
253249
try {
254-
httpResponse = requestBuilder.send();
250+
return requestBuilder.send();
255251
}
256252
catch (Throwable e) {
257253
if (logger.isErrorEnabled()) {
258254
logger.error("failed to send metrics to Dynatrace: {}", redactToken(e.getMessage()));
259255
}
260256
return null;
261257
}
262-
return httpResponse;
263258
}
264259

265260
// VisibleForTesting
@@ -314,8 +309,8 @@ private Meter.Id idWithSuffix(Meter.Id id, String suffix) {
314309
return id.withName(id.getName() + "." + suffix);
315310
}
316311

317-
private String redactToken(String s) {
318-
return s.replace(config.apiToken(), "<redacted>");
312+
private String redactToken(String message) {
313+
return message.replace(config.apiToken(), "<redacted>");
319314
}
320315

321316
}

implementations/micrometer-registry-dynatrace/src/test/java/io/micrometer/dynatrace/v1/DynatraceExporterV1Test.java

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -266,16 +266,21 @@ void whenAllTsTooLargeEmptyMessageListReturned() {
266266

267267
@Test
268268
void splitsWhenExactlyExceedingMaxByComma() {
269+
// @formatter:off
269270
// comma needs to be considered when there is more than one time series
270-
List<DynatraceBatchedPayload> messages = exporter.createPostMessages("my.type", "my.group",
271+
List<DynatraceBatchedPayload> messages = exporter.createPostMessages(
272+
"my.type",
273+
"my.group",
271274
// Max bytes: 15330 (excluding header/footer, 15360 with header/footer)
272-
Arrays.asList(createTimeSeriesWithDimensions(750), // 14861 bytes
273-
createTimeSeriesWithDimensions(23, "asdfg"), // 469 bytes
274-
// (overflows due to
275-
// comma)
275+
Arrays.asList(
276+
createTimeSeriesWithDimensions(750), // 14861 bytes
277+
// 469 bytes (overflows due to comma)
278+
createTimeSeriesWithDimensions(23, "asdfg"),
276279
createTimeSeriesWithDimensions(750), // 14861 bytes
277280
createTimeSeriesWithDimensions(22, "asd") // 468 bytes + comma
278-
));
281+
)
282+
);
283+
// @formatter:on
279284
assertThat(messages).hasSize(3);
280285
assertThat(messages.get(0).metricCount).isEqualTo(1);
281286
assertThat(messages.get(1).metricCount).isEqualTo(1);
@@ -286,14 +291,19 @@ void splitsWhenExactlyExceedingMaxByComma() {
286291

287292
@Test
288293
void countsPreviousAndNextComma() {
289-
List<DynatraceBatchedPayload> messages = exporter.createPostMessages("my.type", null,
294+
// @formatter:off
295+
List<DynatraceBatchedPayload> messages = exporter.createPostMessages(
296+
"my.type",
297+
null,
290298
// Max bytes: 15330 (excluding header/footer, 15360 with header/footer)
291-
Arrays.asList(createTimeSeriesWithDimensions(750), // 14861 bytes
299+
Arrays.asList(
300+
createTimeSeriesWithDimensions(750), // 14861 bytes
292301
createTimeSeriesWithDimensions(10, "asdf"), // 234 bytes + comma
293-
createTimeSeriesWithDimensions(10, "asdf") // 234 bytes + comma =
294-
// 15331 bytes
295-
// (overflow)
296-
));
302+
// 234 bytes + comma = 15331 bytes (overflow)
303+
createTimeSeriesWithDimensions(10, "asdf")
304+
)
305+
);
306+
// @formatter:on
297307
assertThat(messages).hasSize(2);
298308
assertThat(messages.get(0).metricCount).isEqualTo(2);
299309
assertThat(messages.get(1).metricCount).isEqualTo(1);
@@ -416,7 +426,7 @@ void testTokenShouldBeRedactedInPostFailure() throws Throwable {
416426
String apiToken = "this.is.a.fake.apiToken";
417427

418428
HttpSender.Request.Builder builder = HttpSender.Request.build("http://localhost", httpClient);
419-
// mock the PUT call, so we can even run the post call.
429+
// mock the PUT call, so we can even run the post call
420430
doReturn(builder).when(httpClient).put(anyString());
421431
doReturn(new HttpSender.Response(200, "")).when(httpClient).send(any(HttpSender.Request.class));
422432

@@ -432,7 +442,7 @@ void testTokenShouldBeRedactedInPostFailure() throws Throwable {
432442
.extracting(LogEvent::getMessage).containsExactly(
433443
// the custom metric was created, meaning the PUT call succeeded
434444
"created custom:my.gauge as custom metric in Dynatrace",
435-
// the POST call now threw, and the token is redacted.
445+
// the POST call throws an exception and the token is redacted
436446
String.format(
437447
"failed to build request: Illegal character in fragment at index 17: %s/api/v1/entity/infrastructure/custom/?api-token=<redacted>",
438448
invalidUrl));
@@ -459,8 +469,7 @@ void trySendHttpRequestErrorCode() throws Throwable {
459469
DynatraceExporterV1 exporter = FACTORY.injectLogger(() -> createExporter(httpClient));
460470
HttpSender.Request.Builder reqBuilder = mock(HttpSender.Request.Builder.class);
461471

462-
// simulate a failure response. This should be accepted, it will be handled
463-
// elsewhere
472+
// simulate a failure response, errors are handled elsewhere
464473
when(reqBuilder.send()).thenReturn(new HttpSender.Response(400, ""));
465474

466475
// test that everything works and no error is logged
@@ -477,9 +486,8 @@ void trySendHttpRequestThrowsAndRedacts() throws Throwable {
477486

478487
HttpSender.Request.Builder reqBuilder = mock(HttpSender.Request.Builder.class);
479488

480-
// simulate that the request builder throws. This should not happen if the
481-
// endpoint is invalid,
482-
// as the URI is validated elsewhere.
489+
// Simulate that the request builder throws an exception.
490+
// Should not happen if the endpoint is invalid, the URI is validated elsewhere.
483491
String exceptionMessageTemplate = "Exception with the token: %s";
484492
when(reqBuilder.send()).thenThrow(new Throwable(String.format(exceptionMessageTemplate, apiToken)));
485493

0 commit comments

Comments
 (0)