diff --git a/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/profiler/triggers/AlertingSubsystemInit.java b/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/profiler/triggers/AlertingSubsystemInit.java index b7c5b3a5b85..d8e2d633694 100644 --- a/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/profiler/triggers/AlertingSubsystemInit.java +++ b/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/profiler/triggers/AlertingSubsystemInit.java @@ -16,6 +16,7 @@ import com.microsoft.applicationinsights.agent.internal.profiler.Profiler; import com.microsoft.applicationinsights.agent.internal.profiler.ProfilerControl; import com.microsoft.applicationinsights.agent.internal.profiler.upload.ServiceProfilerIndex; +import com.microsoft.applicationinsights.agent.internal.sampling.SamplerUtil; import com.microsoft.applicationinsights.agent.internal.telemetry.TelemetryClient; import com.microsoft.applicationinsights.agent.internal.telemetry.TelemetryObservers; import com.microsoft.applicationinsights.alerting.AlertingSubsystem; @@ -149,6 +150,7 @@ private static void sendServiceProfilerIndex( EventTelemetryBuilder telemetryBuilder = telemetryClient.newEventTelemetryBuilder(); telemetryBuilder.setName("ServiceProfilerIndex"); + telemetryBuilder.setSampleRate((float) SamplerUtil.SAMPLE_RATE_TO_DISABLE_INGESTION_SAMPLING); for (Map.Entry entry : serviceProfilerIndex.getProperties().entrySet()) { telemetryBuilder.addProperty(entry.getKey(), entry.getValue()); @@ -170,6 +172,7 @@ private static void sendMessageTelemetry(TelemetryClient telemetryClient, String MessageTelemetryBuilder telemetryBuilder = telemetryClient.newMessageTelemetryBuilder(); telemetryBuilder.setMessage(message); + telemetryBuilder.setSampleRate((float) SamplerUtil.SAMPLE_RATE_TO_DISABLE_INGESTION_SAMPLING); telemetryBuilder.setTime(FormattedTime.offSetDateTimeFromNow()); telemetryClient.trackAsync(telemetryBuilder.build()); diff --git a/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/profiler/triggers/GcEventInit.java b/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/profiler/triggers/GcEventInit.java index 8f58ccfa30d..71cac16643a 100644 --- a/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/profiler/triggers/GcEventInit.java +++ b/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/profiler/triggers/GcEventInit.java @@ -7,6 +7,7 @@ import com.azure.monitor.opentelemetry.autoconfigure.implementation.utils.FormattedTime; import com.microsoft.applicationinsights.agent.internal.configuration.GcReportingLevel; import com.microsoft.applicationinsights.agent.internal.profiler.util.ServiceLoaderUtil; +import com.microsoft.applicationinsights.agent.internal.sampling.SamplerUtil; import com.microsoft.applicationinsights.agent.internal.telemetry.TelemetryClient; import com.microsoft.applicationinsights.alerting.AlertingSubsystem; import com.microsoft.applicationinsights.alerting.config.AlertMetricType; @@ -125,6 +126,7 @@ private static void emitGcEvent( EventTelemetryBuilder telemetryBuilder = telemetryClient.newEventTelemetryBuilder(); telemetryBuilder.setName("GcEvent"); + telemetryBuilder.setSampleRate((float) SamplerUtil.SAMPLE_RATE_TO_DISABLE_INGESTION_SAMPLING); telemetryBuilder.addProperty("collector", event.getCollector().getName()); telemetryBuilder.addProperty("type", event.getGcCause()); diff --git a/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/sampling/SamplerUtil.java b/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/sampling/SamplerUtil.java index fd810248a09..ad16cae0ec1 100644 --- a/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/sampling/SamplerUtil.java +++ b/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/sampling/SamplerUtil.java @@ -12,7 +12,7 @@ public class SamplerUtil { - private static final double SAMPLE_RATE_TO_DISABLE_INGESTION_SAMPLING = 99.99; + public static final double SAMPLE_RATE_TO_DISABLE_INGESTION_SAMPLING = 99.99; private static final Cache recordAndSampleWithSampleRateMap = Cache.bounded(100); diff --git a/agent/agent-tooling/src/test/java/com/microsoft/applicationinsights/agent/internal/profiler/triggers/GcEventInitTest.java b/agent/agent-tooling/src/test/java/com/microsoft/applicationinsights/agent/internal/profiler/triggers/GcEventInitTest.java index 5b1257d5f16..872ac0ed2c4 100644 --- a/agent/agent-tooling/src/test/java/com/microsoft/applicationinsights/agent/internal/profiler/triggers/GcEventInitTest.java +++ b/agent/agent-tooling/src/test/java/com/microsoft/applicationinsights/agent/internal/profiler/triggers/GcEventInitTest.java @@ -5,8 +5,11 @@ import static org.assertj.core.api.Assertions.assertThat; +import com.azure.monitor.opentelemetry.autoconfigure.implementation.builders.EventTelemetryBuilder; +import com.azure.monitor.opentelemetry.autoconfigure.implementation.models.TelemetryItem; import com.microsoft.applicationinsights.agent.internal.configuration.GcReportingLevel; import com.microsoft.applicationinsights.agent.internal.profiler.testutil.TestTimeSource; +import com.microsoft.applicationinsights.agent.internal.sampling.SamplerUtil; import com.microsoft.applicationinsights.agent.internal.telemetry.TelemetryClient; import com.microsoft.applicationinsights.alerting.AlertingSubsystem; import com.microsoft.applicationinsights.alerting.alert.AlertBreach; @@ -29,10 +32,59 @@ import java.util.concurrent.TimeoutException; import javax.management.MBeanServerConnection; import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; import org.mockito.Mockito; class GcEventInitTest { + @Test + void gcEventIsEmittedWithSampleRateThatBypassesIngestionSampling() { + + TelemetryClient telemetryClient = Mockito.mock(TelemetryClient.class); + Mockito.when(telemetryClient.newEventTelemetryBuilder()) + .thenReturn(EventTelemetryBuilder.create()); + + CompletableFuture alertFuture = new CompletableFuture<>(); + TestTimeSource timeSource = new TestTimeSource(); + AlertingSubsystem alertingSubsystem = getAlertingSubsystem(alertFuture, timeSource); + + GcMonitorFactory factory = + new GcMonitorFactory() { + @Override + public MemoryManagement monitorSelf( + ExecutorService executorService, GcEventConsumer consumer) { + consumer.accept(fullyMockedGcEvent()); + return null; + } + + @Override + public MemoryManagement monitor( + MBeanServerConnection connection, + ExecutorService executorService, + GcEventConsumer consumer) { + return null; + } + }; + + ExecutorService executorService = Executors.newSingleThreadExecutor(); + try { + GcEventInit.init( + alertingSubsystem, + telemetryClient, + executorService, + new GcEventInit.GcEventMonitorConfiguration(GcReportingLevel.ALL), + factory); + + ArgumentCaptor captor = ArgumentCaptor.forClass(TelemetryItem.class); + Mockito.verify(telemetryClient).trackAsync(captor.capture()); + + assertThat(captor.getValue().getSampleRate()) + .isEqualTo((float) SamplerUtil.SAMPLE_RATE_TO_DISABLE_INGESTION_SAMPLING); + } finally { + executorService.shutdownNow(); + } + } + @Test void endToEndAlertIsTriggered() throws ExecutionException, InterruptedException, TimeoutException { @@ -102,4 +154,25 @@ private static GcCollectionEvent mockGcEvent() { .thenReturn(new MemoryUsage(1, 9, 10, 10)); return event; } + + private static GcCollectionEvent fullyMockedGcEvent() { + GcCollectionEvent event = Mockito.mock(GcCollectionEvent.class); + GarbageCollector collector = Mockito.mock(GarbageCollector.class); + MemoryPool tenuredPool = Mockito.mock(MemoryPool.class); + MemoryUsage memoryUsage = new MemoryUsage(1, 9, 10, 10); + + Mockito.when(collector.isTenuredCollector()).thenReturn(true); + Mockito.when(collector.getName()).thenReturn("test-collector"); + Mockito.when(event.getCollector()).thenReturn(collector); + Mockito.when(event.getGcCause()).thenReturn("test-cause"); + Mockito.when(event.getGcAction()).thenReturn("test-action"); + Mockito.when(event.getTenuredPool()).thenReturn(Optional.of(tenuredPool)); + Mockito.when(event.getMemoryUsageBeforeGc(Mockito.any(MemoryPool.class))) + .thenReturn(memoryUsage); + Mockito.when(event.getMemoryUsageAfterGc(Mockito.any(MemoryPool.class))) + .thenReturn(memoryUsage); + Mockito.when(event.getMemoryUsageBeforeGc(Mockito.anyList())).thenReturn(memoryUsage); + Mockito.when(event.getMemoryUsageAfterGc(Mockito.anyList())).thenReturn(memoryUsage); + return event; + } }