diff --git a/eng/versioning/version_client.txt b/eng/versioning/version_client.txt
index 138e39751965..afd95058f9fb 100644
--- a/eng/versioning/version_client.txt
+++ b/eng/versioning/version_client.txt
@@ -441,8 +441,8 @@ com.azure.tools:azure-sdk-build-tool;1.0.0;1.1.0-beta.1
# note: The unreleased dependencies will not be manipulated with the automatic PR creation code.
# In the pom, the version update tag after the version should name the unreleased package and the dependency version:
#
-unreleased_com.azure:azure-core-test;1.22.0-beta.1
unreleased_com.azure:azure-messaging-eventgrid;4.19.0-beta.1
+unreleased_com.azure:azure-core-test;1.22.0-beta.1
# Released Beta dependencies: Copy the entry from above, prepend "beta_", remove the current
# version and set the version to the released beta. Released beta dependencies are only valid
diff --git a/sdk/monitor/azure-monitor-opentelemetry-exporter/assets.json b/sdk/monitor/azure-monitor-opentelemetry-exporter/assets.json
index 3e558946941e..5d5f20b9dab7 100644
--- a/sdk/monitor/azure-monitor-opentelemetry-exporter/assets.json
+++ b/sdk/monitor/azure-monitor-opentelemetry-exporter/assets.json
@@ -2,5 +2,5 @@
"AssetsRepo": "Azure/azure-sdk-assets",
"AssetsRepoPrefixPath": "java",
"TagPrefix": "java/monitor/azure-monitor-opentelemetry-exporter",
- "Tag": "java/monitor/azure-monitor-opentelemetry-exporter_4051462e7c"
+ "Tag": "java/monitor/azure-monitor-opentelemetry-exporter_28d6ecbf1a"
}
diff --git a/sdk/monitor/azure-monitor-opentelemetry-exporter/pom.xml b/sdk/monitor/azure-monitor-opentelemetry-exporter/pom.xml
index 37a345553c54..d3a5fe1e7b71 100644
--- a/sdk/monitor/azure-monitor-opentelemetry-exporter/pom.xml
+++ b/sdk/monitor/azure-monitor-opentelemetry-exporter/pom.xml
@@ -151,7 +151,7 @@
com.azure
azure-core-test
- 1.21.0
+ 1.22.0-beta.1
test
diff --git a/sdk/monitor/azure-monitor-opentelemetry-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/AzureMonitorExporterBuilder.java b/sdk/monitor/azure-monitor-opentelemetry-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/AzureMonitorExporterBuilder.java
index 0dabb769b6d8..6c778151592b 100644
--- a/sdk/monitor/azure-monitor-opentelemetry-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/AzureMonitorExporterBuilder.java
+++ b/sdk/monitor/azure-monitor-opentelemetry-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/AzureMonitorExporterBuilder.java
@@ -27,6 +27,7 @@
import com.azure.monitor.opentelemetry.exporter.implementation.SpanDataMapper;
import com.azure.monitor.opentelemetry.exporter.implementation.builders.AbstractTelemetryBuilder;
import com.azure.monitor.opentelemetry.exporter.implementation.configuration.ConnectionString;
+import com.azure.monitor.opentelemetry.exporter.implementation.configuration.StatsbeatConnectionString;
import com.azure.monitor.opentelemetry.exporter.implementation.heartbeat.HeartbeatExporter;
import com.azure.monitor.opentelemetry.exporter.implementation.localstorage.LocalStorageStats;
import com.azure.monitor.opentelemetry.exporter.implementation.localstorage.LocalStorageTelemetryPipelineListener;
@@ -34,6 +35,9 @@
import com.azure.monitor.opentelemetry.exporter.implementation.pipeline.TelemetryItemExporter;
import com.azure.monitor.opentelemetry.exporter.implementation.pipeline.TelemetryPipeline;
import com.azure.monitor.opentelemetry.exporter.implementation.pipeline.TelemetryPipelineListener;
+import com.azure.monitor.opentelemetry.exporter.implementation.statsbeat.Feature;
+import com.azure.monitor.opentelemetry.exporter.implementation.statsbeat.StatsbeatModule;
+import com.azure.monitor.opentelemetry.exporter.implementation.utils.PropertyHelper;
import com.azure.monitor.opentelemetry.exporter.implementation.utils.ResourceParser;
import com.azure.monitor.opentelemetry.exporter.implementation.utils.TempDirs;
import com.azure.monitor.opentelemetry.exporter.implementation.utils.VersionGenerator;
@@ -55,9 +59,12 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.Set;
import java.util.function.BiConsumer;
+import static java.util.concurrent.TimeUnit.DAYS;
import static java.util.concurrent.TimeUnit.MINUTES;
+import static java.util.concurrent.TimeUnit.SECONDS;
/**
* This class provides a fluent builder API to configure the OpenTelemetry SDK with Azure Monitor Exporters.
@@ -71,6 +78,9 @@ public final class AzureMonitorExporterBuilder {
private static final String APPLICATIONINSIGHTS_AUTHENTICATION_SCOPE =
"https://monitor.azure.com//.default";
+ private static final String STATSBEAT_LONG_INTERVAL_SECONDS = "STATSBEAT_LONG_INTERVAL_SECONDS";
+ private static final String STATSBEAT_SHORT_INTERVAL_SECONDS = "STATSBEAT_SHORT_INTERVAL_SECONDS";
+
private static final Map PROPERTIES =
CoreUtils.getProperties("azure-monitor-opentelemetry-exporter.properties");
@@ -257,7 +267,7 @@ public SpanExporter buildTraceExporter() {
public MetricExporter buildMetricExporter() {
internalBuildAndFreeze();
// TODO (trask) how to pass along configuration properties?
- return buildMetricExporter(DefaultConfigProperties.createForTest(Collections.emptyMap()));
+ return buildMetricExporter(DefaultConfigProperties.create(Collections.emptyMap()));
}
/**
@@ -271,7 +281,7 @@ public MetricExporter buildMetricExporter() {
public LogRecordExporter buildLogRecordExporter() {
internalBuildAndFreeze();
// TODO (trask) how to pass along configuration properties?
- return buildLogRecordExporter(DefaultConfigProperties.createForTest(Collections.emptyMap()));
+ return buildLogRecordExporter(DefaultConfigProperties.create(Collections.emptyMap()));
}
/**
@@ -351,10 +361,45 @@ private SpanExporter buildTraceExporter(ConfigProperties configProperties) {
private MetricExporter buildMetricExporter(ConfigProperties configProperties) {
HeartbeatExporter.start(
MINUTES.toSeconds(15), createDefaultsPopulator(configProperties), builtTelemetryItemExporter::send);
+ if (connectionString != null) {
+ StatsbeatModule statsbeatModule = new StatsbeatModule(PropertyHelper::lazyUpdateVmRpIntegration);
+ statsbeatModule.start(
+ builtTelemetryItemExporter,
+ this::getStatsbeatConnectionString,
+ connectionString::getInstrumentationKey,
+ false,
+ getStatsbeaLongInterval(configProperties.getInt(STATSBEAT_LONG_INTERVAL_SECONDS)),
+ getStatsbeatShortInterval(configProperties.getInt(STATSBEAT_SHORT_INTERVAL_SECONDS)),
+ false,
+ initStatsbeatFeatures());
+ }
return new AzureMonitorMetricExporter(
new MetricDataMapper(createDefaultsPopulator(configProperties), true), builtTelemetryItemExporter);
}
+ private long getStatsbeaLongInterval(Integer intervalFromConfig) {
+ if (intervalFromConfig == null) {
+ return DAYS.toSeconds(1); // default to every 24 hours
+ }
+ return SECONDS.toSeconds(intervalFromConfig);
+ }
+
+ private long getStatsbeatShortInterval(Integer intervalFromConfig) {
+ if (intervalFromConfig == null) {
+ return MINUTES.toSeconds(15); // default to every 15 mins
+ }
+ return SECONDS.toSeconds(intervalFromConfig);
+ }
+
+ private Set initStatsbeatFeatures() {
+ // TODO (jean): start tracking native image usage based on a system property or env var to indicate it's from the native image path
+ return Collections.emptySet();
+ }
+
+ private StatsbeatConnectionString getStatsbeatConnectionString() {
+ return StatsbeatConnectionString.create(connectionString, null, null);
+ }
+
private LogRecordExporter buildLogRecordExporter(ConfigProperties configProperties) {
return new AzureMonitorLogRecordExporter(
new LogDataMapper(true, false, createDefaultsPopulator(configProperties)), builtTelemetryItemExporter);
diff --git a/sdk/monitor/azure-monitor-opentelemetry-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/configuration/StatsbeatConnectionString.java b/sdk/monitor/azure-monitor-opentelemetry-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/configuration/StatsbeatConnectionString.java
index db5c5b56021d..e79289dbfb1e 100644
--- a/sdk/monitor/azure-monitor-opentelemetry-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/configuration/StatsbeatConnectionString.java
+++ b/sdk/monitor/azure-monitor-opentelemetry-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/configuration/StatsbeatConnectionString.java
@@ -91,7 +91,7 @@ public final class StatsbeatConnectionString {
public static StatsbeatConnectionString create(
ConnectionString connectionString,
@Nullable String instrumentationKey,
- String ingestionEndpoint) {
+ @Nullable String ingestionEndpoint) {
if (instrumentationKey == null || instrumentationKey.isEmpty()) {
InstrumentationKeyEndpointPair pair =
diff --git a/sdk/monitor/azure-monitor-opentelemetry-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/pipeline/TelemetryItemExporter.java b/sdk/monitor/azure-monitor-opentelemetry-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/pipeline/TelemetryItemExporter.java
index 558b03553606..8705ca7ffe9c 100644
--- a/sdk/monitor/azure-monitor-opentelemetry-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/pipeline/TelemetryItemExporter.java
+++ b/sdk/monitor/azure-monitor-opentelemetry-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/pipeline/TelemetryItemExporter.java
@@ -137,7 +137,6 @@ public CompletableResultCode shutdown() {
CompletableResultCode internalSendByBatch(TelemetryItemBatchKey telemetryItemBatchKey,
List telemetryItems) {
List byteBuffers;
-
// Don't send _OTELRESOURCE_ custom metric when OTEL_RESOURCE_ATTRIBUTES env var is empty
// Don't send _OTELRESOURCE_ custom metric to Statsbeat yet
// insert _OTELRESOURCE_ at the beginning of each batch
diff --git a/sdk/monitor/azure-monitor-opentelemetry-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/statsbeat/AzureMetadataService.java b/sdk/monitor/azure-monitor-opentelemetry-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/statsbeat/AzureMetadataService.java
index f2e5dfa9fc1f..1e0077f4131e 100644
--- a/sdk/monitor/azure-monitor-opentelemetry-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/statsbeat/AzureMetadataService.java
+++ b/sdk/monitor/azure-monitor-opentelemetry-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/statsbeat/AzureMetadataService.java
@@ -8,9 +8,6 @@
import com.azure.core.http.HttpPipelineBuilder;
import com.azure.core.http.HttpRequest;
import com.azure.core.http.HttpResponse;
-import com.azure.core.http.policy.CookiePolicy;
-import com.azure.core.http.policy.RetryPolicy;
-import com.azure.core.http.policy.UserAgentPolicy;
import com.azure.monitor.opentelemetry.exporter.implementation.NoopTracer;
import com.azure.monitor.opentelemetry.exporter.implementation.utils.ThreadPoolUtils;
import com.fasterxml.jackson.databind.DeserializationFeature;
@@ -81,7 +78,7 @@ void updateMetadata(String response) throws IOException {
private void updateMetadata(MetadataInstanceResponse metadataInstanceResponse) {
vmMetadataServiceCallback.accept(metadataInstanceResponse);
attachStatsbeat.updateMetadataInstance(metadataInstanceResponse);
- customDimensions.setResourceProvider(ResourceProvider.RP_VM);
+ customDimensions.setResourceProviderVm();
// osType from the Azure Metadata Service has a higher precedence over the running app’s
// operating system.
diff --git a/sdk/monitor/azure-monitor-opentelemetry-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/statsbeat/CustomDimensions.java b/sdk/monitor/azure-monitor-opentelemetry-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/statsbeat/CustomDimensions.java
index e3c54fc67427..94e0691bd21f 100644
--- a/sdk/monitor/azure-monitor-opentelemetry-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/statsbeat/CustomDimensions.java
+++ b/sdk/monitor/azure-monitor-opentelemetry-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/statsbeat/CustomDimensions.java
@@ -6,6 +6,7 @@
import com.azure.monitor.opentelemetry.exporter.implementation.builders.StatsbeatTelemetryBuilder;
import com.azure.monitor.opentelemetry.exporter.implementation.utils.PropertyHelper;
import com.azure.monitor.opentelemetry.exporter.implementation.utils.SystemInformation;
+import com.azure.monitor.opentelemetry.exporter.implementation.utils.VersionGenerator;
public class CustomDimensions {
@@ -19,51 +20,28 @@ public class CustomDimensions {
// visible for testing
CustomDimensions() {
- String qualifiedSdkVersion = PropertyHelper.getQualifiedSdkVersionString();
-
- if (qualifiedSdkVersion.startsWith("aw")) {
- resourceProvider = ResourceProvider.RP_APPSVC;
- operatingSystem = OperatingSystem.OS_WINDOWS;
- } else if (qualifiedSdkVersion.startsWith("al")) {
- resourceProvider = ResourceProvider.RP_APPSVC;
- operatingSystem = OperatingSystem.OS_LINUX;
- } else if (qualifiedSdkVersion.startsWith("kw")) {
- resourceProvider = ResourceProvider.RP_AKS;
- operatingSystem = OperatingSystem.OS_WINDOWS;
- } else if (qualifiedSdkVersion.startsWith("kl")) {
- resourceProvider = ResourceProvider.RP_AKS;
- operatingSystem = OperatingSystem.OS_LINUX;
- } else if (qualifiedSdkVersion.startsWith("fw")) {
- resourceProvider = ResourceProvider.RP_FUNCTIONS;
- operatingSystem = OperatingSystem.OS_WINDOWS;
- } else if (qualifiedSdkVersion.startsWith("fl")) {
- resourceProvider = ResourceProvider.RP_FUNCTIONS;
- operatingSystem = OperatingSystem.OS_LINUX;
- } else {
- resourceProvider = ResourceProvider.UNKNOWN;
- operatingSystem = initOperatingSystem();
- }
-
- sdkVersion = qualifiedSdkVersion.substring(qualifiedSdkVersion.lastIndexOf(':') + 1);
+ resourceProvider = ResourceProvider.initResourceProvider();
+ operatingSystem = initOperatingSystem();
+ sdkVersion = initSdkVersion();
runtimeVersion = System.getProperty("java.version");
- attachType = RpAttachType.getRpAttachType();
+ attachType = RpAttachType.getRpAttachTypeString();
language = "java";
}
- public ResourceProvider getResourceProvider() {
+ ResourceProvider getResourceProvider() {
return resourceProvider;
}
- public OperatingSystem getOperatingSystem() {
+ OperatingSystem getOperatingSystem() {
return operatingSystem;
}
- public void setResourceProvider(ResourceProvider resourceProvider) {
- this.resourceProvider = resourceProvider;
+ void setResourceProviderVm() {
+ this.resourceProvider = ResourceProvider.RP_VM;
}
- public void setOperatingSystem(OperatingSystem operatingSystem) {
+ void setOperatingSystem(OperatingSystem operatingSystem) {
this.operatingSystem = operatingSystem;
}
@@ -86,4 +64,12 @@ private static OperatingSystem initOperatingSystem() {
return OperatingSystem.OS_UNKNOWN;
}
}
+
+ private static String initSdkVersion() {
+ if (RpAttachType.getRpAttachType() == RpAttachType.MANUAL) {
+ return VersionGenerator.getSdkVersion();
+ }
+ String qualifiedSdkVersionString = PropertyHelper.getQualifiedSdkVersionString();
+ return qualifiedSdkVersionString.substring(qualifiedSdkVersionString.lastIndexOf(':')+1);
+ }
}
diff --git a/sdk/monitor/azure-monitor-opentelemetry-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/statsbeat/FeatureStatsbeat.java b/sdk/monitor/azure-monitor-opentelemetry-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/statsbeat/FeatureStatsbeat.java
index 5da37359c1da..b29b25e70ab4 100644
--- a/sdk/monitor/azure-monitor-opentelemetry-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/statsbeat/FeatureStatsbeat.java
+++ b/sdk/monitor/azure-monitor-opentelemetry-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/statsbeat/FeatureStatsbeat.java
@@ -69,11 +69,14 @@ protected void send(TelemetryItemExporter telemetryItemExporter) {
featureType = "1";
}
- StatsbeatTelemetryBuilder telemetryBuilder = createStatsbeatTelemetry(FEATURE_METRIC_NAME, 0);
- telemetryBuilder.addProperty("feature", featureValue);
- telemetryBuilder.addProperty("type", featureType);
+ // don't send feature/instrumentation statsbeat when it's empty
+ if (!featureValue.isEmpty()) {
+ StatsbeatTelemetryBuilder telemetryBuilder = createStatsbeatTelemetry(FEATURE_METRIC_NAME, 0);
+ telemetryBuilder.addProperty("feature", featureValue);
+ telemetryBuilder.addProperty("type", featureType);
- telemetryItemExporter.send(Collections.singletonList(telemetryBuilder.build()));
+ telemetryItemExporter.send(Collections.singletonList(telemetryBuilder.build()));
+ }
}
void trackConfigurationOptions(Set featureSet) {
diff --git a/sdk/monitor/azure-monitor-opentelemetry-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/statsbeat/ResourceProvider.java b/sdk/monitor/azure-monitor-opentelemetry-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/statsbeat/ResourceProvider.java
index 3a6fee228665..37b7c2cce6e6 100644
--- a/sdk/monitor/azure-monitor-opentelemetry-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/statsbeat/ResourceProvider.java
+++ b/sdk/monitor/azure-monitor-opentelemetry-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/statsbeat/ResourceProvider.java
@@ -3,11 +3,14 @@
package com.azure.monitor.opentelemetry.exporter.implementation.statsbeat;
+import com.azure.monitor.opentelemetry.exporter.implementation.utils.Strings;
+
enum ResourceProvider {
RP_FUNCTIONS("functions"),
RP_APPSVC("appsvc"),
RP_VM("vm"),
RP_AKS("aks"),
+ RP_SPRING_CLOUD("springcloud"),
UNKNOWN("unknown");
private final String value;
@@ -19,4 +22,18 @@ enum ResourceProvider {
String getValue() {
return value;
}
+
+ static ResourceProvider initResourceProvider() {
+ if ("java".equals(System.getenv("FUNCTIONS_WORKER_RUNTIME"))) {
+ return ResourceProvider.RP_FUNCTIONS;
+ } else if (!Strings.isNullOrEmpty(System.getenv("WEBSITE_SITE_NAME"))) {
+ return ResourceProvider.RP_APPSVC;
+ } else if (!Strings.isNullOrEmpty(System.getenv("KUBERNETES_SERVICE_HOST"))) {
+ return ResourceProvider.RP_AKS;
+ } else if (!Strings.isNullOrEmpty(System.getenv("APPLICATIONINSIGHTS_SPRINGCLOUD_SERVICE_ID"))) {
+ return ResourceProvider.RP_SPRING_CLOUD;
+ } else {
+ return ResourceProvider.UNKNOWN;
+ }
+ }
}
diff --git a/sdk/monitor/azure-monitor-opentelemetry-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/statsbeat/RpAttachType.java b/sdk/monitor/azure-monitor-opentelemetry-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/statsbeat/RpAttachType.java
index 4e3340dfa9c7..fd1d7498efcb 100644
--- a/sdk/monitor/azure-monitor-opentelemetry-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/statsbeat/RpAttachType.java
+++ b/sdk/monitor/azure-monitor-opentelemetry-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/statsbeat/RpAttachType.java
@@ -9,7 +9,7 @@ public enum RpAttachType {
STANDALONE_AUTO("StandaloneAuto"), // RP attach is enabled via a custom JAVA_OPTS or on premise resources
INTEGRATED_AUTO("IntegratedAuto"); // RP attach is on by default
- private static volatile RpAttachType attachType;
+ private static volatile RpAttachType attachType = MANUAL;
private final String label;
private RpAttachType(String label) {
@@ -20,7 +20,11 @@ public static void setRpAttachType(RpAttachType type) {
attachType = type;
}
- public static String getRpAttachType() {
+ public static RpAttachType getRpAttachType() {
+ return attachType;
+ }
+
+ public static String getRpAttachTypeString() {
return attachType != null ? attachType.label : null;
}
}
diff --git a/sdk/monitor/azure-monitor-opentelemetry-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/statsbeat/StatsbeatModule.java b/sdk/monitor/azure-monitor-opentelemetry-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/statsbeat/StatsbeatModule.java
index a1f12e706c4c..e78c93e7aaf3 100644
--- a/sdk/monitor/azure-monitor-opentelemetry-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/statsbeat/StatsbeatModule.java
+++ b/sdk/monitor/azure-monitor-opentelemetry-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/statsbeat/StatsbeatModule.java
@@ -11,13 +11,11 @@
import org.slf4j.MDC;
import java.util.Set;
-import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
-import java.util.function.Function;
import java.util.function.Supplier;
import static com.azure.monitor.opentelemetry.exporter.implementation.utils.AzureMonitorMsgId.FAIL_TO_SEND_STATSBEAT_ERROR;
@@ -37,19 +35,23 @@ public class StatsbeatModule {
private final FeatureStatsbeat instrumentationStatsbeat;
private final NonessentialStatsbeat nonessentialStatsbeat;
private final AzureMetadataService azureMetadataService;
-
private final AtomicBoolean started = new AtomicBoolean();
private final AtomicBoolean shutdown = new AtomicBoolean();
public StatsbeatModule(Consumer vmMetadataServiceCallback) {
customDimensions = new CustomDimensions();
- networkStatsbeat = new NetworkStatsbeat(customDimensions);
attachStatsbeat = new AttachStatsbeat(customDimensions);
featureStatsbeat = new FeatureStatsbeat(customDimensions, FeatureType.FEATURE);
instrumentationStatsbeat = new FeatureStatsbeat(customDimensions, FeatureType.INSTRUMENTATION);
- nonessentialStatsbeat = new NonessentialStatsbeat(customDimensions);
azureMetadataService = new AzureMetadataService(attachStatsbeat, customDimensions, vmMetadataServiceCallback);
+ if (RpAttachType.getRpAttachType() == RpAttachType.MANUAL) {
+ networkStatsbeat = new NetworkStatsbeat(customDimensions);
+ nonessentialStatsbeat = new NonessentialStatsbeat(customDimensions);
+ } else {
+ networkStatsbeat = null;
+ nonessentialStatsbeat = null;
+ }
}
public void start(
@@ -80,11 +82,13 @@ public void start(
updateConnectionString(connectionString.get());
updateInstrumentationKey(instrumentationKey.get());
- scheduledExecutor.scheduleWithFixedDelay(
- new StatsbeatSender(networkStatsbeat, telemetryItemExporter),
- shortIntervalSeconds,
- shortIntervalSeconds,
- TimeUnit.SECONDS);
+ if (RpAttachType.getRpAttachType() != RpAttachType.MANUAL) {
+ scheduledExecutor.scheduleWithFixedDelay(
+ new StatsbeatSender(networkStatsbeat, telemetryItemExporter),
+ shortIntervalSeconds,
+ shortIntervalSeconds,
+ TimeUnit.SECONDS);
+ }
scheduledExecutor.scheduleWithFixedDelay(
new StatsbeatSender(attachStatsbeat, telemetryItemExporter),
Math.min(60, longIntervalSeconds),
@@ -110,7 +114,7 @@ public void start(
featureStatsbeat.trackConfigurationOptions(featureSet);
- if (!disabled) {
+ if (!disabled && RpAttachType.getRpAttachType() != RpAttachType.MANUAL) {
nonessentialStatsbeat.setConnectionString(connectionString.get());
nonessentialStatsbeat.setInstrumentationKey(instrumentationKey.get());
scheduledExecutor.scheduleWithFixedDelay(
@@ -151,7 +155,9 @@ public NonessentialStatsbeat getNonessentialStatsbeat() {
private void updateConnectionString(StatsbeatConnectionString connectionString) {
if (connectionString != null) {
- networkStatsbeat.setConnectionString(connectionString);
+ if (RpAttachType.getRpAttachType() != RpAttachType.MANUAL) {
+ networkStatsbeat.setConnectionString(connectionString);
+ }
attachStatsbeat.setConnectionString(connectionString);
featureStatsbeat.setConnectionString(connectionString);
instrumentationStatsbeat.setConnectionString(connectionString);
@@ -160,7 +166,9 @@ private void updateConnectionString(StatsbeatConnectionString connectionString)
private void updateInstrumentationKey(String instrumentationKey) {
if (instrumentationKey != null && !instrumentationKey.isEmpty()) {
- networkStatsbeat.setInstrumentationKey(instrumentationKey);
+ if (RpAttachType.getRpAttachType() != RpAttachType.MANUAL) {
+ networkStatsbeat.setInstrumentationKey(instrumentationKey);
+ }
attachStatsbeat.setInstrumentationKey(instrumentationKey);
featureStatsbeat.setInstrumentationKey(instrumentationKey);
instrumentationStatsbeat.setInstrumentationKey(instrumentationKey);
diff --git a/sdk/monitor/azure-monitor-opentelemetry-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/utils/PropertyHelper.java b/sdk/monitor/azure-monitor-opentelemetry-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/utils/PropertyHelper.java
index 2908b8b4c4a8..74de0ce2f84d 100644
--- a/sdk/monitor/azure-monitor-opentelemetry-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/utils/PropertyHelper.java
+++ b/sdk/monitor/azure-monitor-opentelemetry-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/utils/PropertyHelper.java
@@ -3,6 +3,8 @@
package com.azure.monitor.opentelemetry.exporter.implementation.utils;
+import com.azure.monitor.opentelemetry.exporter.implementation.statsbeat.MetadataInstanceResponse;
+import com.azure.monitor.opentelemetry.exporter.implementation.statsbeat.RpAttachType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -24,6 +26,8 @@ public final class PropertyHelper {
public static final String UNKNOWN_VERSION_VALUE = "unknown";
+ private static volatile char rpIntegrationChar;
+
/**
* Reads the properties from a properties file.
*
@@ -86,6 +90,36 @@ public static String getSdkVersionNumber() {
return SdkPropertyValues.SDK_VERSION_NUMBER;
}
+ /** Is resource provider (Azure Spring Cloud, AppService, Azure Functions, AKS, VM...). */
+ public static boolean isRpIntegration() {
+ return rpIntegrationChar != 0;
+ }
+
+ public static void setRpIntegrationChar(char ch) {
+ rpIntegrationChar = ch;
+ }
+
+ public static void lazyUpdateVmRpIntegration(MetadataInstanceResponse response) {
+ rpIntegrationChar = 'v';
+ PropertyHelper.setSdkNamePrefix(getRpIntegrationSdkNamePrefix());
+ RpAttachType.setRpAttachType(RpAttachType.STANDALONE_AUTO);
+ }
+
+ public static String getRpIntegrationSdkNamePrefix() {
+ StringBuilder sdkNamePrefix = new StringBuilder(3);
+ sdkNamePrefix.append(rpIntegrationChar);
+ if (SystemInformation.isWindows()) {
+ sdkNamePrefix.append("w");
+ } else if (SystemInformation.isLinux()) {
+ sdkNamePrefix.append("l");
+ } else {
+ logger.warn("could not detect os: {}", System.getProperty("os.name"));
+ sdkNamePrefix.append("u");
+ }
+ sdkNamePrefix.append("_");
+ return sdkNamePrefix.toString();
+ }
+
private static class SdkPropertyValues {
private static final String SDK_VERSION_NUMBER;
private static volatile String sdkVersionString;
diff --git a/sdk/monitor/azure-monitor-opentelemetry-exporter/src/test/java/com/azure/monitor/opentelemetry/exporter/AzureMonitorExportersEndToEndTest.java b/sdk/monitor/azure-monitor-opentelemetry-exporter/src/test/java/com/azure/monitor/opentelemetry/exporter/AzureMonitorExportersEndToEndTest.java
index 64d736ee23f5..eca84c55e426 100644
--- a/sdk/monitor/azure-monitor-opentelemetry-exporter/src/test/java/com/azure/monitor/opentelemetry/exporter/AzureMonitorExportersEndToEndTest.java
+++ b/sdk/monitor/azure-monitor-opentelemetry-exporter/src/test/java/com/azure/monitor/opentelemetry/exporter/AzureMonitorExportersEndToEndTest.java
@@ -34,9 +34,7 @@
import java.io.ByteArrayOutputStream;
import java.net.URL;
import java.nio.charset.StandardCharsets;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.zip.GZIPInputStream;
@@ -51,6 +49,11 @@ public class AzureMonitorExportersEndToEndTest extends MonitorExporterClientTest
"InstrumentationKey=00000000-0000-0000-0000-0FEEDDADBEEF;"
+ "IngestionEndpoint=https://test.in.applicationinsights.azure.com/;"
+ "LiveEndpoint=https://test.livediagnostics.monitor.azure.com/";
+
+ private static final String STATSBEAT_CONNECTION_STRING =
+ "InstrumentationKey=00000000-0000-0000-0000-000000000000;"
+ + "IngestionEndpoint=https://westus-0.in.applicationinsights.azure.com/;"
+ + "LiveEndpoint=https://westus.livediagnostics.monitor.azure.com/";
private static final String INSTRUMENTATION_KEY = "00000000-0000-0000-0000-000000000000";
@Test
@@ -192,10 +195,65 @@ public void testBuildTraceMetricLogExportersConsecutively() throws Exception {
// TODO (trask) also export and validate logs in this test
}
+ @Test
+ public void testStatsbeat() throws Exception {
+ // create the OpenTelemetry SDK
+ CountDownLatch countDownLatch = new CountDownLatch(1);
+ CustomValidationPolicy customValidationPolicy = new CustomValidationPolicy(countDownLatch);
+ OpenTelemetrySdk openTelemetry =
+ TestUtils.createOpenTelemetrySdk(
+ getHttpPipeline(customValidationPolicy), getStatsbeatConfiguration(), STATSBEAT_CONNECTION_STRING);
+
+ // generate a metric
+ generateMetric(openTelemetry);
+
+ // close to flush
+ openTelemetry.close();
+
+ Thread.sleep(1000);
+
+ // wait for export
+ countDownLatch.await(10, SECONDS);
+ assertThat(customValidationPolicy.url)
+ .isEqualTo(new URL("https://westus-0.in.applicationinsights.azure.com/v2.1/track"));
+ assertThat(customValidationPolicy.actualTelemetryItems.size()).isEqualTo(4);
+
+ TelemetryItem attachStatsbeat =
+ customValidationPolicy.actualTelemetryItems.stream()
+ .filter(item -> item.getName().equals("Statsbeat"))
+ .filter(item -> {
+ MetricsData metricsData = (MetricsData) item.getData().getBaseData();
+ return metricsData.getMetrics().stream().allMatch(metricDataPoint -> metricDataPoint.getName().equals("Attach"));
+ })
+ .findFirst()
+ .get();
+ validateAttachStatsbeat(attachStatsbeat);
+
+ TelemetryItem featureStatsbeat =
+ customValidationPolicy.actualTelemetryItems.stream()
+ .filter(item -> item.getName().equals("Statsbeat"))
+ .filter(item -> {
+ MetricsData metricsData = (MetricsData) item.getData().getBaseData();
+ return metricsData.getMetrics().stream().allMatch(metricDataPoint -> metricDataPoint.getName().equals("Feature"));
+ })
+ .findFirst()
+ .get();
+ validateFeatureStatsbeat(featureStatsbeat);
+ }
+
private static Map getConfiguration() {
return Collections.singletonMap("APPLICATIONINSIGHTS_CONNECTION_STRING", CONNECTION_STRING_ENV);
}
+ private static Map getStatsbeatConfiguration() {
+ Map map = new HashMap<>(3);
+ map.put("APPLICATIONINSIGHTS_CONNECTION_STRING", CONNECTION_STRING_ENV);
+ map.put("STATSBEAT_LONG_INTERVAL_SECONDS", "1");
+ map.put("STATSBEAT_SHORT_INTERVAL_SECONDS", "1");
+ return map;
+ }
+
+
@SuppressWarnings("try")
private static void generateSpan(OpenTelemetry openTelemetry) {
Tracer tracer = openTelemetry.getTracer("Sample");
@@ -240,8 +298,23 @@ private static void validateSpan(TelemetryItem telemetryItem) {
.containsExactly(entry("color", "red"), entry("name", "apple"));
}
+ private static void validateAttachStatsbeat(TelemetryItem telemetryItem) {
+ assertThat(telemetryItem.getData().getBaseType()).isEqualTo("MetricData");
+ MetricsData actualMetricsData = (MetricsData) telemetryItem.getData().getBaseData();
+ assertThat(actualMetricsData.getMetrics().get(0).getName()).isEqualTo("Attach");
+ assertThat(actualMetricsData.getProperties()).contains(entry("rp", "unknown"), entry("attach", "Manual"), entry("language", "java"));
+ assertThat(actualMetricsData.getProperties()).containsKeys("attach", "cikey", "language", "os", "rp", "runtimeVersion", "version");
+ }
+
+ private static void validateFeatureStatsbeat(TelemetryItem telemetryItem) {
+ assertThat(telemetryItem.getData().getBaseType()).isEqualTo("MetricData");
+ MetricsData actualMetricsData = (MetricsData) telemetryItem.getData().getBaseData();
+ assertThat(actualMetricsData.getMetrics().get(0).getName()).isEqualTo("Feature");
+ assertThat(actualMetricsData.getProperties()).contains(entry("type", "0"), entry("language", "java"));
+ assertThat(actualMetricsData.getProperties()).containsKeys("feature", "cikey", "language", "os", "rp", "runtimeVersion", "version");
+ }
+
private static void validateMetric(TelemetryItem telemetryItem) {
- assertThat(telemetryItem.getName()).isEqualTo("Metric");
assertThat(telemetryItem.getInstrumentationKey()).isEqualTo(INSTRUMENTATION_KEY);
assertThat(telemetryItem.getTags()).containsEntry("ai.cloud.role", "unknown_service:java");
assertThat(telemetryItem.getTags())
diff --git a/sdk/monitor/azure-monitor-opentelemetry-exporter/src/test/java/com/azure/monitor/opentelemetry/exporter/implementation/statsbeat/CustomDimensionsTest.java b/sdk/monitor/azure-monitor-opentelemetry-exporter/src/test/java/com/azure/monitor/opentelemetry/exporter/implementation/statsbeat/CustomDimensionsTest.java
index e8a4d5a43871..b35e52f3cfe8 100644
--- a/sdk/monitor/azure-monitor-opentelemetry-exporter/src/test/java/com/azure/monitor/opentelemetry/exporter/implementation/statsbeat/CustomDimensionsTest.java
+++ b/sdk/monitor/azure-monitor-opentelemetry-exporter/src/test/java/com/azure/monitor/opentelemetry/exporter/implementation/statsbeat/CustomDimensionsTest.java
@@ -50,11 +50,8 @@ public void testVersion() {
StatsbeatTelemetryBuilder telemetryBuilder = StatsbeatTelemetryBuilder.create("test", 1);
customDimensions.populateProperties(telemetryBuilder, null);
- String sdkVersion = PropertyHelper.getQualifiedSdkVersionString();
- String version = sdkVersion.substring(sdkVersion.lastIndexOf(':') + 1);
-
MetricsData data = (MetricsData) telemetryBuilder.build().getData().getBaseData();
- assertThat(data.getProperties()).containsEntry("version", version);
+ assertThat(data.getProperties()).containsKeys("version");
}
@Test
diff --git a/sdk/monitor/azure-monitor-opentelemetry-exporter/src/test/java/com/azure/monitor/opentelemetry/exporter/implementation/utils/TestUtils.java b/sdk/monitor/azure-monitor-opentelemetry-exporter/src/test/java/com/azure/monitor/opentelemetry/exporter/implementation/utils/TestUtils.java
index 0456124699d6..411046135bb4 100644
--- a/sdk/monitor/azure-monitor-opentelemetry-exporter/src/test/java/com/azure/monitor/opentelemetry/exporter/implementation/utils/TestUtils.java
+++ b/sdk/monitor/azure-monitor-opentelemetry-exporter/src/test/java/com/azure/monitor/opentelemetry/exporter/implementation/utils/TestUtils.java
@@ -70,17 +70,22 @@ public static OpenTelemetrySdk createOpenTelemetrySdk(HttpPipeline httpPipeline)
public static OpenTelemetrySdk createOpenTelemetrySdk(
HttpPipeline httpPipeline, Map configuration) {
+ return createOpenTelemetrySdk(httpPipeline, configuration, TRACE_CONNECTION_STRING);
+ }
+
+ public static OpenTelemetrySdk createOpenTelemetrySdk(HttpPipeline httpPipeline, Map configuration, String connectionString) {
AutoConfiguredOpenTelemetrySdkBuilder sdkBuilder = AutoConfiguredOpenTelemetrySdk.builder();
new AzureMonitorExporterBuilder()
- .connectionString(TRACE_CONNECTION_STRING)
+ .connectionString(connectionString)
.httpPipeline(httpPipeline)
.build(sdkBuilder);
return sdkBuilder.addPropertiesSupplier(() -> configuration).build().getOpenTelemetrySdk();
}
+
private TestUtils() {
}
}