Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<String, String> entry : serviceProfilerIndex.getProperties().entrySet()) {
telemetryBuilder.addProperty(entry.getKey(), entry.getValue());
Expand All @@ -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());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<Double, SamplingResult> recordAndSampleWithSampleRateMap =
Cache.bounded(100);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,14 @@

import static org.assertj.core.api.Assertions.assertThat;

import com.azure.monitor.opentelemetry.autoconfigure.implementation.models.TelemetryEventData;
import com.azure.monitor.opentelemetry.autoconfigure.implementation.models.TelemetryItem;
import com.azure.monitor.opentelemetry.autoconfigure.implementation.statsbeat.StatsbeatModule;
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.agent.internal.telemetry.TelemetryObservers;
import com.microsoft.applicationinsights.alerting.AlertingSubsystem;
import com.microsoft.applicationinsights.alerting.alert.AlertBreach;
import com.microsoft.applicationinsights.alerting.analysis.TimeSource;
Expand All @@ -19,20 +24,93 @@
import com.microsoft.gcmonitor.MemoryManagement;
import com.microsoft.gcmonitor.garbagecollectors.GarbageCollector;
import com.microsoft.gcmonitor.memorypools.MemoryPool;
import io.opentelemetry.sdk.resources.Resource;
import java.lang.management.MemoryUsage;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Consumer;
import javax.management.MBeanServerConnection;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;

class GcEventInitTest {

@Test
void gcEventIsEmittedWithSampleRateThatBypassesIngestionSampling()
throws ExecutionException, InterruptedException, TimeoutException {

CompletableFuture<TelemetryItem> gcEventFuture = new CompletableFuture<>();
Consumer<TelemetryItem> observer =
telemetryItem -> {
if (telemetryItem.getData().getBaseData() instanceof TelemetryEventData
&& "GcEvent"
.equals(((TelemetryEventData) telemetryItem.getData().getBaseData()).getName())) {
gcEventFuture.complete(telemetryItem);
}
};
TelemetryObservers.INSTANCE.getObservers().add(observer);

try {
CompletableFuture<AlertBreach> 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;
}
};

TelemetryClient telemetryClient =
TelemetryClient.builder()
.setCustomDimensions(new HashMap<>())
.setMetricFilters(new ArrayList<>())
.setStatsbeatModule(new StatsbeatModule(response -> {}))
.setConnectionStrings(
"InstrumentationKey=00000000-0000-0000-0000-000000000000;IngestionEndpoint=https://test.in.applicationinsights.azure.com/")
.build();
telemetryClient.setOtelResource(Resource.empty());

ExecutorService executorService = Executors.newSingleThreadExecutor();
try {
GcEventInit.init(
alertingSubsystem,
telemetryClient,
executorService,
new GcEventInit.GcEventMonitorConfiguration(GcReportingLevel.ALL),
factory);

TelemetryItem gcEvent = gcEventFuture.get(30, TimeUnit.SECONDS);

assertThat(gcEvent.getSampleRate())
.isEqualTo((float) SamplerUtil.SAMPLE_RATE_TO_DISABLE_INGESTION_SAMPLING);
} finally {
executorService.shutdownNow();
}
} finally {
TelemetryObservers.INSTANCE.getObservers().remove(observer);
}
}

@Test
void endToEndAlertIsTriggered()
throws ExecutionException, InterruptedException, TimeoutException {
Expand Down Expand Up @@ -102,4 +180,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;
}
}