From 8c1b94743eb80e3dd95399a07f8236a5b722ecd0 Mon Sep 17 00:00:00 2001 From: John Oliver <1615532+johnoliver@users.noreply.github.com> Date: Fri, 18 Jul 2025 17:30:47 +0100 Subject: [PATCH] Add timeout on profiler settings pull --- .../internal/configuration/Configuration.java | 1 + .../profiler/ProfilingInitializer.java | 8 +++++-- .../service/ServiceProfilerClient.java | 24 +++++++++++++++---- .../profiler/config/ConfigServiceTest.java | 6 +++-- .../upload/UploadServiceSimpleTest.java | 6 +++-- .../profiler/upload/UploadServiceTest.java | 3 ++- 6 files changed, 37 insertions(+), 11 deletions(-) diff --git a/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/configuration/Configuration.java b/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/configuration/Configuration.java index a39a66b454c..efab9297921 100644 --- a/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/configuration/Configuration.java +++ b/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/configuration/Configuration.java @@ -1530,6 +1530,7 @@ public static class ProfilerConfiguration { public boolean enableDiagnostics = false; public boolean enableRequestTriggering = false; public List requestTriggerEndpoints = new ArrayList<>(); + public int serviceProfilerHttpTimeoutSeconds = 30; } public static class GcEventConfiguration { diff --git a/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/profiler/ProfilingInitializer.java b/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/profiler/ProfilingInitializer.java index b6fac1be160..1c3a0d1634f 100644 --- a/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/profiler/ProfilingInitializer.java +++ b/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/profiler/ProfilingInitializer.java @@ -7,6 +7,7 @@ import com.azure.core.http.HttpPipeline; import com.azure.core.http.policy.DefaultRedirectStrategy; import com.azure.core.http.policy.RedirectPolicy; +import com.azure.core.http.policy.TimeoutPolicy; import com.azure.monitor.opentelemetry.autoconfigure.implementation.utils.SystemInformation; import com.azure.monitor.opentelemetry.autoconfigure.implementation.utils.ThreadPoolUtils; import com.microsoft.applicationinsights.agent.internal.common.FriendlyException; @@ -23,6 +24,7 @@ import java.io.File; import java.net.MalformedURLException; import java.net.URL; +import java.time.Duration; import java.util.Arrays; import java.util.HashSet; import java.util.concurrent.Executors; @@ -127,7 +129,8 @@ private synchronized void performInit() { 3, "Location", new HashSet<>( - Arrays.asList(HttpMethod.GET, HttpMethod.HEAD, HttpMethod.POST))))); + Arrays.asList(HttpMethod.GET, HttpMethod.HEAD, HttpMethod.POST)))), + new TimeoutPolicy(Duration.ofSeconds(configuration.serviceProfilerHttpTimeoutSeconds))); serviceProfilerExecutorService = Executors.newScheduledThreadPool( @@ -140,7 +143,8 @@ private synchronized void performInit() { getServiceProfilerFrontEndPoint(configuration), telemetryClient.getInstrumentationKey(), httpPipeline, - userAgent); + userAgent, + configuration.serviceProfilerHttpTimeoutSeconds); // Monitor service remains alive permanently due to scheduling an periodic config pull startPollingForConfigUpdates(); diff --git a/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/profiler/service/ServiceProfilerClient.java b/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/profiler/service/ServiceProfilerClient.java index 02c79790a9f..631fb049279 100644 --- a/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/profiler/service/ServiceProfilerClient.java +++ b/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/profiler/service/ServiceProfilerClient.java @@ -15,6 +15,7 @@ import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; +import java.time.Duration; import java.util.Date; import java.util.UUID; import javax.annotation.Nullable; @@ -40,21 +41,25 @@ public class ServiceProfilerClient { private final URL hostUrl; private final String instrumentationKey; private final HttpPipeline httpPipeline; + private final int httpTimeoutSeconds; @Nullable private final String userAgent; public ServiceProfilerClient( URL hostUrl, String instrumentationKey, HttpPipeline httpPipeline, - @Nullable String userAgent) { + @Nullable String userAgent, + int httpTimeoutSeconds) { this.hostUrl = hostUrl; this.instrumentationKey = instrumentationKey; this.httpPipeline = httpPipeline; this.userAgent = userAgent; + this.httpTimeoutSeconds = httpTimeoutSeconds; } - public ServiceProfilerClient(URL hostUrl, String instrumentationKey, HttpPipeline httpPipeline) { - this(hostUrl, instrumentationKey, httpPipeline, null); + public ServiceProfilerClient( + URL hostUrl, String instrumentationKey, HttpPipeline httpPipeline, int httpTimeoutSeconds) { + this(hostUrl, instrumentationKey, httpPipeline, null, httpTimeoutSeconds); } /** Obtain permission to upload a profile to service profiler. */ @@ -144,7 +149,18 @@ public Mono getSettings(Date oldTimeStamp) { HttpRequest request = new HttpRequest(HttpMethod.GET, requestUrl); - return httpPipeline.send(request).flatMap(response -> handle(response, requestUrl)); + return httpPipeline + .send(request) + .timeout( + Duration.ofSeconds(httpTimeoutSeconds), + Mono.error( + new HttpResponseException( + "Timed out after " + + httpTimeoutSeconds + + " seconds while waiting for response from " + + requestUrl, + null))) + .flatMap(response -> handle(response, requestUrl)); } private static Mono handle(HttpResponse response, URL requestUrl) { diff --git a/agent/agent-tooling/src/test/java/com/microsoft/applicationinsights/agent/internal/profiler/config/ConfigServiceTest.java b/agent/agent-tooling/src/test/java/com/microsoft/applicationinsights/agent/internal/profiler/config/ConfigServiceTest.java index b02b0672cdc..961ff221aaf 100644 --- a/agent/agent-tooling/src/test/java/com/microsoft/applicationinsights/agent/internal/profiler/config/ConfigServiceTest.java +++ b/agent/agent-tooling/src/test/java/com/microsoft/applicationinsights/agent/internal/profiler/config/ConfigServiceTest.java @@ -27,7 +27,8 @@ void pullSettings() throws IOException, InterruptedException { new ServiceProfilerClient( new URL("https://agent.azureserviceprofiler.net/"), "00000000-0000-0000-0000-000000000000", - getHttpPipeline()); + getHttpPipeline(), + 30); ConfigService configService = new ConfigService(serviceProfilerClient); @@ -56,7 +57,8 @@ void badServiceResponseDoesNotProvideReturn() throws MalformedURLException { new ServiceProfilerClient( new URL("https://agent.azureserviceprofiler.net/"), "00000000-0000-0000-0000-000000000000", - getHttpPipeline()); + getHttpPipeline(), + 30); ConfigService configService = new ConfigService(serviceProfilerClient); Mono result = configService.pullSettings(); diff --git a/agent/agent-tooling/src/test/java/com/microsoft/applicationinsights/agent/internal/profiler/upload/UploadServiceSimpleTest.java b/agent/agent-tooling/src/test/java/com/microsoft/applicationinsights/agent/internal/profiler/upload/UploadServiceSimpleTest.java index b2116d95eb9..02aca886b64 100644 --- a/agent/agent-tooling/src/test/java/com/microsoft/applicationinsights/agent/internal/profiler/upload/UploadServiceSimpleTest.java +++ b/agent/agent-tooling/src/test/java/com/microsoft/applicationinsights/agent/internal/profiler/upload/UploadServiceSimpleTest.java @@ -32,7 +32,8 @@ void roleNameIsCorrectlyAddedToMetaData() throws IOException { new ServiceProfilerClient( new URL("https://agent.azureserviceprofiler.net/"), "00000000-0000-0000-0000-000000000000", - httpPipeline); + httpPipeline, + 30); File tmpFile = createFakeJfrFile(); UUID appId = UUID.randomUUID(); @@ -93,7 +94,8 @@ void uploadWithoutFileThrows() throws MalformedURLException { new ServiceProfilerClient( new URL("https://agent.azureserviceprofiler.net/"), "00000000-0000-0000-0000-000000000000", - httpPipeline); + httpPipeline, + 30); UUID appId = UUID.randomUUID(); UUID profileId = UUID.randomUUID(); diff --git a/agent/agent-tooling/src/test/java/com/microsoft/applicationinsights/agent/internal/profiler/upload/UploadServiceTest.java b/agent/agent-tooling/src/test/java/com/microsoft/applicationinsights/agent/internal/profiler/upload/UploadServiceTest.java index 2f8dd7873a5..3b2f967415c 100644 --- a/agent/agent-tooling/src/test/java/com/microsoft/applicationinsights/agent/internal/profiler/upload/UploadServiceTest.java +++ b/agent/agent-tooling/src/test/java/com/microsoft/applicationinsights/agent/internal/profiler/upload/UploadServiceTest.java @@ -30,7 +30,8 @@ void uploadFileGoodPathReturnsExpectedResponse() throws IOException { new ServiceProfilerClient( new URL("https://agent.azureserviceprofiler.net/"), "00000000-0000-0000-0000-000000000000", - httpPipeline); + httpPipeline, + 30); File tmpFile = createFakeJfrFile(); UUID appId = UUID.randomUUID();