Skip to content

Commit c27253c

Browse files
authored
Fix custom metric on Function Consumption (#2946)
Disable profiler and heartbeat when connection string is null
1 parent 916b445 commit c27253c

File tree

12 files changed

+178
-50
lines changed

12 files changed

+178
-50
lines changed

agent/agent-bootstrap/src/main/java/com/microsoft/applicationinsights/agent/bootstrap/diagnostics/status/StatusFile.java

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,19 @@ public class StatusFile {
5555
static final String HOME_ENV_VAR = "HOME";
5656

5757
// visible for testing
58-
static final String DEFAULT_LOGDIR = "/LogFiles";
58+
static final String DEFAULT_LOGDIR = "LogFiles";
5959

6060
// visible for testing
61-
static final String DEFAULT_APPLICATIONINSIGHTS_LOGDIR = "/ApplicationInsights";
61+
static final String DEFAULT_APPLICATIONINSIGHTS_LOGDIR = "ApplicationInsights";
6262

6363
// visible for testing
6464
static final String WINDOWS_DEFAULT_HOME_DIR =
65-
"/home" + DEFAULT_LOGDIR + DEFAULT_APPLICATIONINSIGHTS_LOGDIR;
65+
File.separator
66+
+ "home"
67+
+ File.separator
68+
+ DEFAULT_LOGDIR
69+
+ File.separator
70+
+ DEFAULT_APPLICATIONINSIGHTS_LOGDIR;
6671

6772
// visible for testing
6873
static String logDir;
@@ -110,11 +115,15 @@ static String initLogDir() {
110115
if (DiagnosticsHelper.isOsWindows()) {
111116
String siteLogDir = System.getProperty(SITE_LOGDIR_PROPERTY);
112117
if (siteLogDir != null && !siteLogDir.isEmpty()) {
113-
return siteLogDir + DEFAULT_APPLICATIONINSIGHTS_LOGDIR;
118+
return siteLogDir + File.separator + DEFAULT_APPLICATIONINSIGHTS_LOGDIR;
114119
}
115120
String homeDir = System.getenv(HOME_ENV_VAR);
116121
if (homeDir != null && !homeDir.isEmpty()) {
117-
return homeDir + DEFAULT_LOGDIR + DEFAULT_APPLICATIONINSIGHTS_LOGDIR;
122+
return homeDir
123+
+ File.separator
124+
+ DEFAULT_LOGDIR
125+
+ File.separator
126+
+ DEFAULT_APPLICATIONINSIGHTS_LOGDIR;
118127
}
119128
return WINDOWS_DEFAULT_HOME_DIR;
120129
}

agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/configuration/Configuration.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -615,7 +615,7 @@ private static String getDefaultPath() {
615615
}
616616
if (DiagnosticsHelper.useAppSvcRpIntegrationLogging()
617617
|| DiagnosticsHelper.useFunctionsRpIntegrationLogging()) {
618-
return StatusFile.getLogDir() + "/" + DEFAULT_NAME;
618+
return StatusFile.getLogDir() + File.separator + DEFAULT_NAME;
619619
}
620620
// azure spring cloud
621621
return DEFAULT_NAME;

agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/LoggingConfigurator.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,11 @@ private void configureFunctions() {
115115
Appender<ILoggingEvent> diagnosticAppender = configureConsoleAppender();
116116
diagnosticLogger.addAppender(diagnosticAppender);
117117

118+
ApplicationInsightsDiagnosticsLogFilter filter = new ApplicationInsightsDiagnosticsLogFilter();
119+
filter.setContext(loggerContext);
120+
filter.start();
121+
diagnosticAppender.addFilter(filter);
122+
118123
// errors reported by other loggers should also go to diagnostic log
119124
// (level filter for these is applied in ApplicationInsightsDiagnosticsLogFilter)
120125
rootLogger.addAppender(diagnosticAppender);

agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/RuntimeConfiguration.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,8 @@ public class RuntimeConfiguration {
2222
public String instrumentationLoggingLevel;
2323

2424
public String selfDiagnosticsLevel;
25+
26+
public boolean profilerEnabled;
27+
28+
public long heartbeatIntervalSeconds;
2529
}

agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/RuntimeConfigurator.java

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,26 @@
33

44
package com.microsoft.applicationinsights.agent.internal.init;
55

6+
import static java.util.concurrent.TimeUnit.MINUTES;
7+
68
import ch.qos.logback.classic.LoggerContext;
9+
import com.azure.monitor.opentelemetry.exporter.implementation.heartbeat.HeartbeatExporter;
10+
import com.azure.monitor.opentelemetry.exporter.implementation.models.TelemetryItem;
711
import com.azure.monitor.opentelemetry.exporter.implementation.utils.Strings;
812
import com.microsoft.applicationinsights.agent.internal.classicsdk.BytecodeUtilImpl;
913
import com.microsoft.applicationinsights.agent.internal.configuration.Configuration;
1014
import com.microsoft.applicationinsights.agent.internal.exporter.AgentLogExporter;
1115
import com.microsoft.applicationinsights.agent.internal.legacyheaders.DelegatingPropagator;
16+
import com.microsoft.applicationinsights.agent.internal.profiler.ProfilingInitializer;
1217
import com.microsoft.applicationinsights.agent.internal.sampling.DelegatingSampler;
1318
import com.microsoft.applicationinsights.agent.internal.sampling.Samplers;
1419
import com.microsoft.applicationinsights.agent.internal.telemetry.TelemetryClient;
20+
import java.io.File;
1521
import java.util.ArrayList;
1622
import java.util.List;
1723
import java.util.Objects;
24+
import java.util.concurrent.atomic.AtomicBoolean;
25+
import java.util.function.Consumer;
1826
import java.util.function.Supplier;
1927
import javax.annotation.Nullable;
2028
import org.slf4j.Logger;
@@ -26,15 +34,26 @@ public class RuntimeConfigurator {
2634

2735
private final TelemetryClient telemetryClient;
2836
private final Supplier<AgentLogExporter> agentLogExporter;
37+
private final Configuration initialConfig;
2938
private volatile RuntimeConfiguration currentConfig;
39+
private final Consumer<List<TelemetryItem>> heartbeatTelemetryItemsConsumer;
40+
private final File tempDir;
41+
42+
private final AtomicBoolean profilerStarted = new AtomicBoolean();
43+
private final AtomicBoolean heartbeatStarted = new AtomicBoolean();
3044

3145
RuntimeConfigurator(
3246
TelemetryClient telemetryClient,
3347
Supplier<AgentLogExporter> agentLogExporter,
34-
Configuration initialConfig) {
48+
Configuration initialConfig,
49+
Consumer<List<TelemetryItem>> heartbeatTelemetryItemConsumer,
50+
File tempDir) {
3551
this.telemetryClient = telemetryClient;
3652
this.agentLogExporter = agentLogExporter;
53+
this.initialConfig = initialConfig;
3754
currentConfig = captureInitialConfig(initialConfig);
55+
this.heartbeatTelemetryItemsConsumer = heartbeatTelemetryItemConsumer;
56+
this.tempDir = tempDir;
3857
}
3958

4059
private static RuntimeConfiguration captureInitialConfig(Configuration initialConfig) {
@@ -58,6 +77,9 @@ private static RuntimeConfiguration captureInitialConfig(Configuration initialCo
5877

5978
runtimeConfig.instrumentationLoggingLevel = initialConfig.instrumentation.logging.level;
6079
runtimeConfig.selfDiagnosticsLevel = initialConfig.selfDiagnostics.level;
80+
81+
runtimeConfig.profilerEnabled = initialConfig.preview.profiler.enabled;
82+
runtimeConfig.heartbeatIntervalSeconds = initialConfig.heartbeat.intervalSeconds;
6183
return runtimeConfig;
6284
}
6385

@@ -79,6 +101,9 @@ private static RuntimeConfiguration copy(RuntimeConfiguration config) {
79101

80102
copy.instrumentationLoggingLevel = config.instrumentationLoggingLevel;
81103
copy.selfDiagnosticsLevel = config.selfDiagnosticsLevel;
104+
105+
copy.profilerEnabled = config.profilerEnabled;
106+
copy.heartbeatIntervalSeconds = config.heartbeatIntervalSeconds;
82107
return copy;
83108
}
84109

@@ -112,6 +137,42 @@ public void apply(RuntimeConfiguration runtimeConfig) {
112137
updateSampling(enabled, runtimeConfig.sampling, runtimeConfig.samplingPreview);
113138
}
114139

140+
// initialize Profiler
141+
if (runtimeConfig.profilerEnabled && telemetryClient.getConnectionString() != null) {
142+
// this prevents profiler being initialized more than once in Azure Spring App
143+
if (!profilerStarted.getAndSet(true)) {
144+
try {
145+
ProfilingInitializer.initialize(
146+
tempDir,
147+
initialConfig.preview.profiler,
148+
initialConfig.preview.gcEvents.reportingLevel,
149+
runtimeConfig.role.name,
150+
runtimeConfig.role.instance,
151+
telemetryClient);
152+
} catch (RuntimeException e) {
153+
logger.warn("Failed to initialize profiler", e);
154+
}
155+
} else {
156+
logger.debug("Profiler has already been initialized.");
157+
}
158+
}
159+
160+
// enable Heartbeat
161+
if (telemetryClient.getConnectionString() != null) {
162+
// this prevents heartbeat being started more than once in Azure Spring App
163+
if (!heartbeatStarted.getAndSet(true)) {
164+
// interval longer than 15 minutes is not allowed since we use this data for usage telemetry
165+
long intervalSeconds =
166+
Math.min(runtimeConfig.heartbeatIntervalSeconds, MINUTES.toSeconds(15));
167+
HeartbeatExporter.start(
168+
intervalSeconds, telemetryClient::populateDefaults, heartbeatTelemetryItemsConsumer);
169+
} else {
170+
logger.debug("Heartbeat has already started.");
171+
}
172+
}
173+
174+
// TODO (heya) enable Statsbeat and need to refactor RuntimeConfiguration
175+
115176
updateInstrumentationLoggingLevel(runtimeConfig.instrumentationLoggingLevel);
116177
updateSelfDiagnosticsLevel(runtimeConfig.selfDiagnosticsLevel);
117178

agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/SecondEntryPoint.java

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -135,9 +135,7 @@ public void customize(AutoConfigurationCustomizer autoConfiguration) {
135135
.setDiskPersistenceMaxSizeMb(configuration.preview.diskPersistenceMaxSizeMb)
136136
.build();
137137

138-
// interval longer than 15 minutes is not allowed since we use this data for usage telemetry
139-
long intervalSeconds = Math.min(configuration.heartbeat.intervalSeconds, MINUTES.toSeconds(15));
140-
Consumer<List<TelemetryItem>> telemetryItemsConsumer =
138+
Consumer<List<TelemetryItem>> heartbeatTelemetryItemConsumer =
141139
telemetryItems -> {
142140
for (TelemetryItem telemetryItem : telemetryItems) {
143141
TelemetryObservers.INSTANCE
@@ -146,13 +144,40 @@ public void customize(AutoConfigurationCustomizer autoConfiguration) {
146144
telemetryClient.getMetricsBatchItemProcessor().trackAsync(telemetryItem);
147145
}
148146
};
149-
HeartbeatExporter.start(
150-
intervalSeconds, telemetryClient::populateDefaults, telemetryItemsConsumer);
147+
148+
if (telemetryClient.getConnectionString() != null) {
149+
startupLogger.verbose("connection string is not null, start HeartbeatExporter");
150+
// interval longer than 15 minutes is not allowed since we use this data for usage telemetry
151+
long intervalSeconds =
152+
Math.min(configuration.heartbeat.intervalSeconds, MINUTES.toSeconds(15));
153+
HeartbeatExporter.start(
154+
intervalSeconds, telemetryClient::populateDefaults, heartbeatTelemetryItemConsumer);
155+
}
151156

152157
TelemetryClient.setActive(telemetryClient);
153158

159+
if (configuration.preview.profiler.enabled && telemetryClient.getConnectionString() != null) {
160+
try {
161+
ProfilingInitializer.initialize(
162+
tempDir,
163+
configuration.preview.profiler,
164+
configuration.preview.gcEvents.reportingLevel,
165+
configuration.role.name,
166+
configuration.role.instance,
167+
telemetryClient);
168+
} catch (RuntimeException e) {
169+
startupLogger.warning("Failed to initialize profiler", e);
170+
}
171+
}
172+
173+
// TODO (heya) remove duplicate code in both RuntimeConfigurator and SecondEntryPoint
154174
RuntimeConfigurator runtimeConfigurator =
155-
new RuntimeConfigurator(telemetryClient, () -> agentLogExporter, configuration);
175+
new RuntimeConfigurator(
176+
telemetryClient,
177+
() -> agentLogExporter,
178+
configuration,
179+
heartbeatTelemetryItemConsumer,
180+
tempDir);
156181

157182
if (configuration.sampling.percentage != null) {
158183
BytecodeUtilImpl.samplingPercentage = configuration.sampling.percentage.floatValue();
@@ -164,14 +189,6 @@ public void customize(AutoConfigurationCustomizer autoConfiguration) {
164189
BytecodeUtilImpl.connectionStringConfiguredAtRuntime =
165190
configuration.connectionStringConfiguredAtRuntime;
166191

167-
if (configuration.preview.profiler.enabled) {
168-
try {
169-
ProfilingInitializer.initialize(tempDir, configuration, telemetryClient);
170-
} catch (RuntimeException e) {
171-
startupLogger.warning("Failed to initialize profiler", e);
172-
}
173-
}
174-
175192
if (ConfigurationBuilder.inAzureFunctionsConsumptionWorker()) {
176193
AzureFunctions.setup(
177194
() -> telemetryClient.getConnectionString() != null,

agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/profiler/PerformanceMonitoringService.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import com.azure.monitor.opentelemetry.exporter.implementation.utils.ThreadPoolUtils;
77
import com.microsoft.applicationinsights.agent.internal.configuration.Configuration;
8+
import com.microsoft.applicationinsights.agent.internal.configuration.GcReportingLevel;
89
import com.microsoft.applicationinsights.agent.internal.profiler.service.ServiceProfilerClient;
910
import com.microsoft.applicationinsights.agent.internal.profiler.triggers.AlertingSubsystemInit;
1011
import com.microsoft.applicationinsights.agent.internal.profiler.upload.UploadService;
@@ -38,7 +39,8 @@ public class PerformanceMonitoringService {
3839
private final String machineName;
3940
private final String roleName;
4041
private final TelemetryClient telemetryClient;
41-
private final Configuration configuration;
42+
private final Configuration.ProfilerConfiguration configuration;
43+
private final GcReportingLevel reportingLevel;
4244
private final File tempDir;
4345

4446
private boolean currentlyEnabled = false;
@@ -58,13 +60,15 @@ public PerformanceMonitoringService(
5860
String machineName,
5961
String roleName,
6062
TelemetryClient telemetryClient,
61-
Configuration configuration,
63+
Configuration.ProfilerConfiguration configuration,
64+
GcReportingLevel reportingLevel,
6265
File tempDir) {
6366
this.processId = processId;
6467
this.machineName = machineName;
6568
this.roleName = roleName;
6669
this.telemetryClient = telemetryClient;
6770
this.configuration = configuration;
71+
this.reportingLevel = reportingLevel;
6872
this.tempDir = tempDir;
6973
}
7074

@@ -80,7 +84,7 @@ synchronized void enableProfiler(
8084
logger.warn("INITIALISING JFR PROFILING SUBSYSTEM THIS FEATURE IS IN BETA");
8185

8286
diagnosticEngine = null;
83-
if (configuration.preview.profiler.enableDiagnostics) {
87+
if (configuration.enabled) {
8488
// Initialise diagnostic service
8589
diagnosticEngine = startDiagnosticEngine();
8690
}
@@ -91,11 +95,12 @@ synchronized void enableProfiler(
9195
ThreadPoolUtils.createDaemonThreadFactory(
9296
ProfilingInitializer.class, "ServiceProfilerAlertingService"));
9397

94-
profiler = new Profiler(configuration.preview.profiler, tempDir);
98+
profiler = new Profiler(configuration, tempDir);
9599

96100
alerting =
97101
AlertingSubsystemInit.create(
98102
configuration,
103+
reportingLevel,
99104
TelemetryObservers.INSTANCE,
100105
profiler,
101106
telemetryClient,

0 commit comments

Comments
 (0)