Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,18 @@ public class MetricDataMapper {
private static final Set<String> OTEL_PRE_AGGREGATED_STANDARD_METRIC_NAMES = new HashSet<>(4);
public static final AttributeKey<String> APPLICATIONINSIGHTS_INTERNAL_METRIC_NAME
= AttributeKey.stringKey("applicationinsights.internal.metric_name");
public static final String MS_SENT_TO_AMW_ATTR = "_MS.SentToAMW";
private static final String METRICS_TO_LOG_ANALYTICS_ENABLED
= "APPLICATIONINSIGHTS_METRICS_TO_LOGANALYTICS_ENABLED";

private final BiConsumer<AbstractTelemetryBuilder, Resource> telemetryInitializer;
private final boolean captureHttpServer4xxAsError;

private final Boolean otlpExporterEnabled;
private final boolean metricsToLAEnabled;

static {
// HTTP unstable metrics to be excluded via Otel auto instrumentation
// HTTP unstable metrics to be excluded via OTel auto instrumentation
OTEL_UNSTABLE_METRICS_TO_EXCLUDE.add("rpc.client.duration");
OTEL_UNSTABLE_METRICS_TO_EXCLUDE.add("rpc.server.duration");

Expand All @@ -71,16 +77,25 @@ public class MetricDataMapper {

public MetricDataMapper(BiConsumer<AbstractTelemetryBuilder, Resource> telemetryInitializer,
boolean captureHttpServer4xxAsError) {
this(telemetryInitializer, captureHttpServer4xxAsError, null);
}

public MetricDataMapper(BiConsumer<AbstractTelemetryBuilder, Resource> telemetryInitializer,
boolean captureHttpServer4xxAsError, Boolean otlpExporterEnabled) {
this.telemetryInitializer = telemetryInitializer;
this.captureHttpServer4xxAsError = captureHttpServer4xxAsError;
this.otlpExporterEnabled = otlpExporterEnabled;

String metricsToLaEnvVar = System.getenv(METRICS_TO_LOG_ANALYTICS_ENABLED);
this.metricsToLAEnabled = metricsToLaEnvVar == null || "true".equalsIgnoreCase(metricsToLaEnvVar);
}

public void map(MetricData metricData, Consumer<TelemetryItem> consumer) {
MetricDataType type = metricData.getType();
if (type == DOUBLE_SUM || type == DOUBLE_GAUGE || type == LONG_SUM || type == LONG_GAUGE || type == HISTOGRAM) {
boolean isPreAggregatedStandardMetric
= OTEL_PRE_AGGREGATED_STANDARD_METRIC_NAMES.contains(metricData.getName());
if (isPreAggregatedStandardMetric) {
if (isPreAggregatedStandardMetric) { // we want standard metrics to always be sent to Breeze
List<TelemetryItem> preAggregatedStandardMetrics
= convertOtelMetricToAzureMonitorMetric(metricData, true);
preAggregatedStandardMetrics.forEach(consumer::accept);
Expand All @@ -92,8 +107,11 @@ public void map(MetricData metricData, Consumer<TelemetryItem> consumer) {
&& metricData.getInstrumentationScopeInfo().getName().startsWith(OTEL_INSTRUMENTATION_NAME_PREFIX)) {
return;
}
List<TelemetryItem> stableOtelMetrics = convertOtelMetricToAzureMonitorMetric(metricData, false);
stableOtelMetrics.forEach(consumer::accept);

if (metricsToLAEnabled && !isPreAggregatedStandardMetric) {
List<TelemetryItem> stableOtelMetrics = convertOtelMetricToAzureMonitorMetric(metricData, false);
stableOtelMetrics.forEach(consumer::accept);
}
} else {
logger.warning("metric data type {} is not supported yet.", metricData.getType());
}
Expand All @@ -109,7 +127,7 @@ private List<TelemetryItem> convertOtelMetricToAzureMonitorMetric(MetricData met

builder.setTime(FormattedTime.offSetDateTimeFromEpochNanos(pointData.getEpochNanos()));
updateMetricPointBuilder(builder, metricData, pointData, captureHttpServer4xxAsError,
isPreAggregatedStandardMetric);
isPreAggregatedStandardMetric, this.otlpExporterEnabled);

telemetryItems.add(builder.build());
}
Expand All @@ -118,7 +136,8 @@ private List<TelemetryItem> convertOtelMetricToAzureMonitorMetric(MetricData met

// visible for testing
public static void updateMetricPointBuilder(MetricTelemetryBuilder metricTelemetryBuilder, MetricData metricData,
PointData pointData, boolean captureHttpServer4xxAsError, boolean isPreAggregatedStandardMetric) {
PointData pointData, boolean captureHttpServer4xxAsError, boolean isPreAggregatedStandardMetric,
Boolean otlpExporterEnabled) {
checkArgument(metricData != null, "MetricData cannot be null.");

MetricPointBuilder pointBuilder = new MetricPointBuilder();
Expand Down Expand Up @@ -176,6 +195,9 @@ public static void updateMetricPointBuilder(MetricTelemetryBuilder metricTelemet
}

metricTelemetryBuilder.setMetricPoint(pointBuilder);
if (otlpExporterEnabled != null) {
metricTelemetryBuilder.addProperty(MS_SENT_TO_AMW_ATTR, otlpExporterEnabled ? "True" : "False");
}

Attributes attributes = pointData.getAttributes();
if (isPreAggregatedStandardMetric) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,16 @@
import io.opentelemetry.sdk.metrics.export.PeriodicMetricReader;
import io.opentelemetry.sdk.testing.exporter.InMemoryMetricExporter;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;

import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.azure.monitor.opentelemetry.autoconfigure.implementation.semconv.HttpAttributes.HTTP_RESPONSE_STATUS_CODE;
import static com.azure.monitor.opentelemetry.autoconfigure.implementation.semconv.ServerAttributes.SERVER_ADDRESS;
Expand All @@ -40,8 +43,13 @@

public class AzureMonitorMetricExporterTest {

@Test
public void testDoubleCounter() {
static Stream<Boolean> enablementOptions() {
return Stream.of(true, false, null);
}

@ParameterizedTest
@MethodSource("enablementOptions")
public void testDoubleCounter(Boolean otlpExporterEnabled) {
InMemoryMetricExporter inMemoryMetricExporter = InMemoryMetricExporter.create();
SdkMeterProvider meterProvider = SdkMeterProvider.builder()
.registerMetricReader(PeriodicMetricReader.builder(inMemoryMetricExporter).build())
Expand All @@ -59,18 +67,28 @@ public void testDoubleCounter() {
MetricData metricData = metricDataList.get(0);
for (PointData pointData : metricData.getData().getPoints()) {
MetricTelemetryBuilder builder = MetricTelemetryBuilder.create();
MetricDataMapper.updateMetricPointBuilder(builder, metricDataList.get(0), pointData, true, false);
MetricDataMapper.updateMetricPointBuilder(builder, metricDataList.get(0), pointData, true, false,
otlpExporterEnabled);
MetricsData metricsData = (MetricsData) builder.build().getData().getBaseData();
assertThat(metricsData.getMetrics().size()).isEqualTo(1);
assertThat(metricsData.getMetrics().get(0).getValue()).isEqualTo(3.1415);

if (otlpExporterEnabled != null) {
assertThat(metricsData.getProperties().size()).isEqualTo(1);
assertThat(metricsData.getProperties()).containsEntry("_MS.SentToAMW",
otlpExporterEnabled ? "True" : "False");
} else {
assertThat(metricsData.getProperties()).isNull();
}
}

assertThat(metricData.getType()).isEqualTo(DOUBLE_SUM);
assertThat(metricData.getName()).isEqualTo("testDoubleCounter");
}

@Test
public void testDoubleGauge() {
@ParameterizedTest
@MethodSource("enablementOptions")
public void testDoubleGauge(Boolean otlpExporterEnabled) {
InMemoryMetricExporter inMemoryMetricExporter = InMemoryMetricExporter.create();
SdkMeterProvider meterProvider = SdkMeterProvider.builder()
.registerMetricReader(PeriodicMetricReader.builder(inMemoryMetricExporter).build())
Expand All @@ -90,12 +108,16 @@ public void testDoubleGauge() {
MetricData metricData = metricDataList.get(0);
for (PointData pointData : metricData.getData().getPoints()) {
MetricTelemetryBuilder builder = MetricTelemetryBuilder.create();
MetricDataMapper.updateMetricPointBuilder(builder, metricData, pointData, true, false);
MetricDataMapper.updateMetricPointBuilder(builder, metricData, pointData, true, false, otlpExporterEnabled);
MetricsData metricsData = (MetricsData) builder.build().getData().getBaseData();
assertThat(metricsData.getMetrics().size()).isEqualTo(1);
assertThat(metricsData.getMetrics().get(0).getValue()).isEqualTo(20.0);
assertThat(metricsData.getProperties().size()).isEqualTo(1);
assertThat(metricsData.getProperties().size()).isEqualTo(otlpExporterEnabled == null ? 1 : 2);
assertThat(metricsData.getProperties()).containsEntry("thing", "engine");
if (otlpExporterEnabled != null) {
assertThat(metricsData.getProperties()).containsEntry("_MS.SentToAMW",
otlpExporterEnabled ? "True" : "False");
}
}

assertThat(metricData.getType()).isEqualTo(DOUBLE_GAUGE);
Expand Down Expand Up @@ -123,7 +145,7 @@ public void testAttributesOnCustomMetric() {
MetricData metric = metricDatas.get(0);
PointData pointData = metric.getData().getPoints().stream().findFirst().get();
MetricTelemetryBuilder builder = MetricTelemetryBuilder.create();
MetricDataMapper.updateMetricPointBuilder(builder, metric, pointData, true, false);
MetricDataMapper.updateMetricPointBuilder(builder, metric, pointData, true, false, null);

MetricsData metricsData = (MetricsData) builder.build().getData().getBaseData();
assertThat(metricsData.getMetrics().size()).isEqualTo(1);
Expand Down Expand Up @@ -157,7 +179,7 @@ public void testAttributesOnStandardMetric() {
MetricData metric = metricDatas.get(0);
PointData pointData = metric.getData().getPoints().stream().findFirst().get();
MetricTelemetryBuilder builder = MetricTelemetryBuilder.create();
MetricDataMapper.updateMetricPointBuilder(builder, metric, pointData, true, true);
MetricDataMapper.updateMetricPointBuilder(builder, metric, pointData, true, true, null);

MetricsData metricsData = (MetricsData) builder.build().getData().getBaseData();
assertThat(metricsData.getMetrics().size()).isEqualTo(1);
Expand Down Expand Up @@ -220,7 +242,7 @@ public void testLongCounter() {
assertThat(longPointData3.getAttributes().get(AttributeKey.stringKey("color"))).isEqualTo("yellow");

MetricTelemetryBuilder builder = MetricTelemetryBuilder.create();
MetricDataMapper.updateMetricPointBuilder(builder, metricData, longPointData1, true, false);
MetricDataMapper.updateMetricPointBuilder(builder, metricData, longPointData1, true, false, null);
MetricsData metricsData = (MetricsData) builder.build().getData().getBaseData();
assertThat(metricsData.getMetrics().size()).isEqualTo(1);
MetricDataPoint metricDataPoint = metricsData.getMetrics().get(0);
Expand All @@ -232,7 +254,7 @@ public void testLongCounter() {
assertThat(properties).containsEntry("color", "green");

builder = MetricTelemetryBuilder.create();
MetricDataMapper.updateMetricPointBuilder(builder, metricData, longPointData2, true, false);
MetricDataMapper.updateMetricPointBuilder(builder, metricData, longPointData2, true, false, null);
metricsData = (MetricsData) builder.build().getData().getBaseData();
assertThat(metricsData.getMetrics().size()).isEqualTo(1);
metricDataPoint = metricsData.getMetrics().get(0);
Expand All @@ -244,7 +266,7 @@ public void testLongCounter() {
assertThat(properties).containsEntry("color", "red");

builder = MetricTelemetryBuilder.create();
MetricDataMapper.updateMetricPointBuilder(builder, metricData, longPointData3, true, false);
MetricDataMapper.updateMetricPointBuilder(builder, metricData, longPointData3, true, false, null);
metricsData = (MetricsData) builder.build().getData().getBaseData();
assertThat(metricsData.getMetrics().size()).isEqualTo(1);
metricDataPoint = metricsData.getMetrics().get(0);
Expand Down Expand Up @@ -283,7 +305,7 @@ public void testLongGauge() {
MetricData metricData = metricDataList.get(0);
for (PointData pointData : metricData.getData().getPoints()) {
MetricTelemetryBuilder builder = MetricTelemetryBuilder.create();
MetricDataMapper.updateMetricPointBuilder(builder, metricData, pointData, true, false);
MetricDataMapper.updateMetricPointBuilder(builder, metricData, pointData, true, false, null);
MetricsData metricsData = (MetricsData) builder.build().getData().getBaseData();
assertThat(metricsData.getMetrics().size()).isEqualTo(1);
assertThat(metricsData.getMetrics().get(0).getValue()).isEqualTo(20);
Expand Down Expand Up @@ -319,7 +341,7 @@ public void testDoubleHistogram() {
assertThat(metricData.getData().getPoints().size()).isEqualTo(1);
PointData pointData = metricData.getData().getPoints().iterator().next();
MetricTelemetryBuilder builder = MetricTelemetryBuilder.create();
MetricDataMapper.updateMetricPointBuilder(builder, metricData, pointData, true, false);
MetricDataMapper.updateMetricPointBuilder(builder, metricData, pointData, true, false, null);
MetricsData metricsData = (MetricsData) builder.build().getData().getBaseData();
assertThat(metricsData.getMetrics().size()).isEqualTo(1);
assertThat(metricsData.getMetrics().get(0).getCount()).isEqualTo(1);
Expand Down Expand Up @@ -357,7 +379,7 @@ public void testNoAttributeWithPrefixApplicationInsightsInternal() {
assertThat(metricData.getData().getPoints().size()).isEqualTo(1);
PointData pointData = metricData.getData().getPoints().iterator().next();
MetricTelemetryBuilder builder = MetricTelemetryBuilder.create();
MetricDataMapper.updateMetricPointBuilder(builder, metricData, pointData, true, false);
MetricDataMapper.updateMetricPointBuilder(builder, metricData, pointData, true, false, null);
MetricsData metricsData = (MetricsData) builder.build().getData().getBaseData();
assertThat(metricsData.getMetrics().size()).isEqualTo(1);
assertThat(metricsData.getProperties()).isNotNull();
Expand Down
Loading