Skip to content

Commit df71eb9

Browse files
bbenner7635Brendan Benner
andauthored
Increment Office365 request failure metrics on retry (#6204)
Signed-off-by: Brendan Benner <bbenner@amazon.com> Co-authored-by: Brendan Benner <bbenner@amazon.com>
1 parent daeac45 commit df71eb9

3 files changed

Lines changed: 73 additions & 6 deletions

File tree

data-prepper-plugins/saas-source-plugins/microsoft-office365-source/src/main/java/org/opensearch/dataprepper/plugins/source/microsoft_office365/Office365RestClient.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -182,11 +182,11 @@ public AuditLogsResponse searchAuditLogs(final String contentType,
182182

183183
return new AuditLogsResponse(response.getBody(), nextPageUri);
184184
},
185-
authConfig::renewCredentials
185+
authConfig::renewCredentials,
186+
searchRequestsFailedCounter
186187
);
187188
} catch (Exception e) {
188189
log.error(NOISY, "Error while fetching audit logs for content type {}", contentType, e);
189-
searchRequestsFailedCounter.increment();
190190
throw new RuntimeException("Failed to fetch audit logs", e);
191191
}
192192
});
@@ -216,12 +216,11 @@ public String getAuditLog(String contentUri) {
216216
new HttpEntity<>(headers),
217217
String.class
218218
).getBody();
219-
}, authConfig::renewCredentials);
219+
}, authConfig::renewCredentials, auditLogRequestsFailedCounter);
220220
auditLogRequestsSuccessCounter.increment();
221221
return response;
222222
} catch (Exception e) {
223223
log.error(NOISY, "Error while fetching audit log content from URI: {}", contentUri, e);
224-
auditLogRequestsFailedCounter.increment();
225224
throw new RuntimeException("Failed to fetch audit log", e);
226225
}
227226
});

data-prepper-plugins/saas-source-plugins/microsoft-office365-source/src/main/java/org/opensearch/dataprepper/plugins/source/microsoft_office365/RetryHandler.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
package org.opensearch.dataprepper.plugins.source.microsoft_office365;
1111

12+
import io.micrometer.core.instrument.Counter;
1213
import lombok.extern.slf4j.Slf4j;
1314
import org.springframework.http.HttpStatus;
1415
import org.springframework.web.client.HttpClientErrorException;
@@ -26,10 +27,17 @@ public class RetryHandler {
2627
private static final int SLEEP_TIME_MULTIPLIER = 1000;
2728

2829
public static <T> T executeWithRetry(Supplier<T> operation, Runnable credentialRenewal) {
30+
return executeWithRetry(operation, credentialRenewal, null);
31+
}
32+
33+
public static <T> T executeWithRetry(Supplier<T> operation, Runnable credentialRenewal, Counter failureCounter) {
2934
int retryCount = 0;
3035
while (retryCount < MAX_RETRIES) {
36+
boolean operationSucceeded = false;
3137
try {
32-
return operation.get();
38+
T result = operation.get();
39+
operationSucceeded = true;
40+
return result;
3341
} catch (HttpClientErrorException | HttpServerErrorException ex) {
3442
HttpStatus statusCode = ex.getStatusCode();
3543
String statusMessage = ex.getMessage();
@@ -70,9 +78,13 @@ public static <T> T executeWithRetry(Supplier<T> operation, Runnable credentialR
7078
Thread.currentThread().interrupt();
7179
throw new RuntimeException("Retry interrupted", ie);
7280
}
81+
} finally {
82+
if (!operationSucceeded && failureCounter != null) {
83+
failureCounter.increment();
84+
}
7385
}
7486
retryCount++;
7587
}
7688
throw new RuntimeException("Exceeded max retry attempts");
7789
}
78-
}
90+
}

data-prepper-plugins/saas-source-plugins/microsoft-office365-source/src/test/java/org/opensearch/dataprepper/plugins/source/microsoft_office365/Office365RestClientTest.java

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import org.junit.jupiter.api.BeforeEach;
1313
import org.junit.jupiter.api.Test;
1414
import org.junit.jupiter.api.extension.ExtendWith;
15+
import io.micrometer.core.instrument.Counter;
1516
import org.mockito.ArgumentCaptor;
1617
import org.mockito.Mock;
1718
import org.mockito.junit.jupiter.MockitoExtension;
@@ -291,4 +292,59 @@ void testTokenRenewal() {
291292
assertEquals("Bearer token-0", requestTokens.get(0), "First request should use token-0");
292293
assertEquals("Bearer token-1", requestTokens.get(1), "Second request should use token-1");
293294
}
295+
296+
@Test
297+
void testSearchAuditLogsFailureCounterIncrementsOnEachRetry() throws Exception {
298+
Instant startTime = Instant.now().minus(1, ChronoUnit.HOURS);
299+
Instant endTime = Instant.now();
300+
301+
when(authConfig.getTenantId()).thenReturn("test-tenant-id");
302+
when(authConfig.getAccessToken()).thenReturn("test-access-token");
303+
304+
Counter mockCounter = org.mockito.Mockito.mock(Counter.class);
305+
ReflectivelySetField.setField(Office365RestClient.class, office365RestClient, "searchRequestsFailedCounter", mockCounter);
306+
307+
when(restTemplate.exchange(
308+
anyString(),
309+
eq(HttpMethod.GET),
310+
any(),
311+
any(ParameterizedTypeReference.class)
312+
)).thenThrow(new HttpClientErrorException(HttpStatus.TOO_MANY_REQUESTS));
313+
314+
assertThrows(RuntimeException.class, () ->
315+
office365RestClient.searchAuditLogs(
316+
"Audit.AzureActiveDirectory",
317+
startTime,
318+
endTime,
319+
null
320+
)
321+
);
322+
323+
// Verify counter.increment() was called exactly 6 times (once for each retry attempt)
324+
verify(mockCounter, times(6)).increment();
325+
}
326+
327+
@Test
328+
void testGetAuditLogFailureCounterIncrementsOnEachRetry() throws Exception {
329+
String contentUri = "https://manage.office.com/api/v1.0/test-tenant/activity/feed/audit/123";
330+
331+
when(authConfig.getAccessToken()).thenReturn("test-access-token");
332+
333+
Counter mockCounter = org.mockito.Mockito.mock(Counter.class);
334+
ReflectivelySetField.setField(Office365RestClient.class, office365RestClient, "auditLogRequestsFailedCounter", mockCounter);
335+
336+
when(restTemplate.exchange(
337+
eq(contentUri),
338+
eq(HttpMethod.GET),
339+
any(),
340+
eq(String.class)
341+
)).thenThrow(new HttpClientErrorException(HttpStatus.TOO_MANY_REQUESTS));
342+
343+
assertThrows(RuntimeException.class, () ->
344+
office365RestClient.getAuditLog(contentUri)
345+
);
346+
347+
// Verify counter.increment() was called exactly 6 times (once for each retry attempt)
348+
verify(mockCounter, times(6)).increment();
349+
}
294350
}

0 commit comments

Comments
 (0)