Skip to content

Commit

Permalink
Set role name lazily for Linux consumption plan (#1537)
Browse files Browse the repository at this point in the history
  • Loading branch information
heyams authored Mar 11, 2021
1 parent 0f2612c commit cc8b707
Show file tree
Hide file tree
Showing 8 changed files with 250 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
import com.microsoft.applicationinsights.internal.config.TelemetryModulesXmlElement;
import com.microsoft.applicationinsights.internal.system.SystemInformation;
import com.microsoft.applicationinsights.internal.util.PropertyHelper;
import io.opentelemetry.instrumentation.api.aiconnectionstring.AiConnectionString;
import io.opentelemetry.instrumentation.api.aisdk.AiLazyConfiguration;
import io.opentelemetry.javaagent.spi.ComponentInstaller;
import org.apache.http.HttpHost;
import org.checkerframework.checker.nullness.qual.Nullable;
Expand Down Expand Up @@ -158,7 +158,7 @@ private static void start(Instrumentation instrumentation) {

// this is for Azure Function Linux consumption plan support.
if ("java".equals(System.getenv("FUNCTIONS_WORKER_RUNTIME"))) {
AiConnectionString.setAccessor(new ConnectionStringAccessor());
AiLazyConfiguration.setAccessor(new LazyConfigurationAccessor());
}

// this is currently used by Micrometer instrumentation in addition to 2.x SDK
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
import com.microsoft.applicationinsights.internal.channel.common.LazyHttpClient;
import com.microsoft.applicationinsights.internal.util.ExceptionStats;
import com.microsoft.applicationinsights.internal.util.ThreadPoolUtils;
import io.opentelemetry.instrumentation.api.aiappid.AiAppId;
import io.opentelemetry.instrumentation.api.aisdk.AiAppId;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.util.EntityUtils;
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
* ApplicationInsights-Java
* Copyright (c) Microsoft Corporation
* All rights reserved.
*
* MIT License
* Permission is hereby granted, free of charge, to any person obtaining a copy of this
* software and associated documentation files (the ""Software""), to deal in the Software
* without restriction, including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the following conditions:
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
* THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/

package com.microsoft.applicationinsights.agent.internal;

import com.google.common.base.Strings;
import com.microsoft.applicationinsights.TelemetryConfiguration;
import com.microsoft.applicationinsights.agent.internal.propagator.DelegatingPropagator;
import com.microsoft.applicationinsights.agent.internal.sampling.DelegatingSampler;
import io.opentelemetry.instrumentation.api.aisdk.AiLazyConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LazyConfigurationAccessor implements AiLazyConfiguration.Accessor {

private static final Logger logger = LoggerFactory.getLogger(LazyConfigurationAccessor.class);

@Override
public void lazyLoad() {
lazySetEnvVars();
}

private void lazySetEnvVars() {
String instrumentationKey = TelemetryConfiguration.getActive().getInstrumentationKey();
String roleName = TelemetryConfiguration.getActive().getRoleName();
if (instrumentationKey != null && !instrumentationKey.isEmpty() && roleName != null && !roleName.isEmpty()) {
return;
}

boolean lazySetOptIn = Boolean.parseBoolean(System.getProperty("LazySetOptIn"));
String enableAgent = System.getenv("APPLICATIONINSIGHTS_ENABLE_AGENT");
logger.debug("lazySetOptIn: {}", lazySetOptIn);
logger.debug("APPLICATIONINSIGHTS_ENABLE_AGENT: {}", enableAgent);
if (!shouldSetConnectionString(lazySetOptIn, enableAgent)) {
return;
}

setConnectionString(System.getenv("APPLICATIONINSIGHTS_CONNECTION_STRING"), System.getenv("APPINSIGHTS_INSTRUMENTATIONKEY"));
setWebsiteSiteName(System.getenv("WEBSITE_SITE_NAME"));
}

static void setConnectionString(String connectionString, String instrumentationKey) {
if (connectionString != null && !connectionString.isEmpty()) {
setValue(connectionString);
} else {
// if the instrumentation key is neither null nor empty , we will create a default
// connection string based on the instrumentation key.
// this is to support Azure Functions that were created prior to the introduction of
// connection strings
if (instrumentationKey != null && !instrumentationKey.isEmpty()) {
setValue("InstrumentationKey=" + instrumentationKey);
}
}
}

private static void setValue(String value) {
if (!Strings.isNullOrEmpty(value)) {
TelemetryConfiguration.getActive().setConnectionString(value);
// now that we know the user has opted in to tracing, we need to init the propagator and sampler
DelegatingPropagator.getInstance().setUpStandardDelegate();
// TODO handle APPLICATIONINSIGHTS_SAMPLING_PERCENTAGE
DelegatingSampler.getInstance().setAlwaysOnDelegate();
logger.info("Set connection string {} lazily for the Azure Function Consumption Plan.", value);
}
}

static void setWebsiteSiteName(String websiteSiteName) {
if (websiteSiteName != null && !websiteSiteName.isEmpty()) {
TelemetryConfiguration.getActive().setRoleName(websiteSiteName);
logger.info("Set WEBSITE_SITE_NAME: {} lazily for the Azure Function Consumption Plan.", websiteSiteName);
}
}

static boolean shouldSetConnectionString(boolean lazySetOptIn, String enableAgent) {
if (lazySetOptIn) {
// when LazySetOptIn is on, enable agent if APPLICATIONINSIGHTS_ENABLE_AGENT is null or true
if (enableAgent == null || Boolean.parseBoolean(enableAgent)) {
return true;
}
} else {
// when LazySetOptIn is off, enable agent if APPLICATIONINSIGHTS_ENABLE_AGENT is true
if (Boolean.parseBoolean(enableAgent)) {
return true;
}
}
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
import io.opentelemetry.context.propagation.TextMapGetter;
import io.opentelemetry.context.propagation.TextMapPropagator;
import io.opentelemetry.context.propagation.TextMapSetter;
import io.opentelemetry.instrumentation.api.aiappid.AiAppId;
import io.opentelemetry.instrumentation.api.aisdk.AiAppId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
/*
* ApplicationInsights-Java
* Copyright (c) Microsoft Corporation
* All rights reserved.
*
* MIT License
* Permission is hereby granted, free of charge, to any person obtaining a copy of this
* software and associated documentation files (the ""Software""), to deal in the Software
* without restriction, including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the following conditions:
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
* THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/

package com.microsoft.applicationinsights.agent.internal;

import com.microsoft.applicationinsights.TelemetryConfiguration;
import org.junit.*;

import static org.junit.Assert.*;

public class LazyConfigurationAccessorTest {

/*
* Lazily Set Connection String For Linux Consumption Plan:
*
* Term LazySetOptIn ConnectionString EnableAgent LazySet
* Preview FALSE VALID TRUE Enabled
* VALID FALSE Disabled
* VALID NULL Disabled
* NULL TRUE/FALSE/NULL Disabled
* GA TRUE VALID TRUE Enabled
* VALID FALSE Disabled
* VALID NULL Enabled
* NULL TRUE/FALSE/NULL Disabled
*/
private static final String CONNECTION_STRING =
"InstrumentationKey=00000000-0000-0000-0000-0FEEDDADBEEF;IngestionEndpoint=http://fakeingestion:60606/";

private static final String INSTRUMENTATION_KEY = "00000000-0000-0000-0000-0FEEDDADBEEF";
private static final String WEBSITE_SITE_NAME = "fake_site_name";

@Test
//"LazySetOptIn is FALSE, ConnectionString is valid and EnableAgent is TRUE"
public void enableLazySetWithLazySetOptInOffEnableAgentOn() {
assertTrue(LazyConfigurationAccessor.shouldSetConnectionString(false, "true"));
}

@Test
//"LazySetOptIn is FALSE, ConnectionString is valid and EnableAgent is FALSE"
public void disableLazySetWithLazySetOptInOffEnableAgentOff() {
assertFalse(LazyConfigurationAccessor.shouldSetConnectionString(false, "false"));
}

@Test
//"LazySetOptIn is FALSE, ConnectionString is valid and EnableAgent is NULL"
public void disableLazySetWithLazySetOptInOffEnableAgentNull() {
assertFalse(LazyConfigurationAccessor.shouldSetConnectionString(false, null));
}

@Test
//"LazySetOptIn is FALSE, ConnectionString is NULL, InstrumentationKey is NULL, and EnableAgent is TRUE"
public void disableLazySetWithLazySetOptInOffConnectionStringNullInstrumentationKeyNull() {
String oldConnectionString = TelemetryConfiguration.getActive().getConnectionString();
assertTrue(LazyConfigurationAccessor.shouldSetConnectionString(false, "true"));
LazyConfigurationAccessor.setConnectionString(null, null);
assertEquals(TelemetryConfiguration.getActive().getConnectionString(), oldConnectionString);
}

@Test
//"LazySetOptIn is FALSE, ConnectionString is valid, InstrumentationKey is NULL, and EnableAgent is TRUE"
public void disableLazySetWithLazySetOptInOffConnectionStringNotNullInstrumentationKeyNull() {
assertTrue(LazyConfigurationAccessor.shouldSetConnectionString(false, "true"));
LazyConfigurationAccessor.setConnectionString(CONNECTION_STRING, null);
assertEquals(TelemetryConfiguration.getActive().getConnectionString(), CONNECTION_STRING);

LazyConfigurationAccessor.setWebsiteSiteName(WEBSITE_SITE_NAME);
assertEquals(TelemetryConfiguration.getActive().getRoleName(), WEBSITE_SITE_NAME);
}

@Test
//"LazySetOptIn is FALSE, ConnectionString is NULL, InstrumentationKey is valid, and EnableAgent is TRUE")
public void enableLazySetWithLazySetOptInOffConnectionStringNullInstrumentationKeyNotNull() {
assertTrue(LazyConfigurationAccessor.shouldSetConnectionString(false, "true"));
LazyConfigurationAccessor.setConnectionString(null, INSTRUMENTATION_KEY);
assertEquals(TelemetryConfiguration.getActive().getConnectionString(), "InstrumentationKey=" + INSTRUMENTATION_KEY);
}

@Test
//"LazySetOptIn is TRUE, ConnectionString is valid and EnableAgent is TRUE"
public void enableLazySetWithLazySetOptInOnEnableAgentOn() {
assertTrue(LazyConfigurationAccessor.shouldSetConnectionString(true, "true"));
}

@Test
//"LazySetOptIn is TRUE, ConnectionString is valid and EnableAgent is FALSE"
public void disableLazySetWithLazySetOptInOnEnableAgentOff() {
assertFalse(LazyConfigurationAccessor.shouldSetConnectionString(true, "false"));
}

@Test
//"LazySetOptIn is TRUE, ConnectionString is valid and EnableAgent is NULL"
public void enableLazySetWithLazySetOptInOnEnableAgentNull() {
assertTrue(LazyConfigurationAccessor.shouldSetConnectionString(true, null));
}

@Test
//"LazySetOptIn is TRUE, ConnectionString is NULL, InstrumentationKey is NULL, and EnableAgent is TRUE"
public void disableLazySetWithLazySetOptInOnConnectionStringNullAndInstrumentationKeyNull() {
String oldConnectionString = TelemetryConfiguration.getActive().getConnectionString();
assertTrue(LazyConfigurationAccessor.shouldSetConnectionString(true, "true"));
LazyConfigurationAccessor.setConnectionString(null, null);
assertEquals(TelemetryConfiguration.getActive().getConnectionString(), oldConnectionString);
}

@Test
//"LazySetOptIn is TRUE, ConnectionString is valid, InstrumentationKey is NULL, and EnableAgent is TRUE"
public void enableLazySetWithLazySetOptInOnConnectionStringNotNullInstrumentationKeyNull() {
assertTrue(LazyConfigurationAccessor.shouldSetConnectionString(false, "true"));
LazyConfigurationAccessor.setConnectionString(CONNECTION_STRING, null);
assertEquals(TelemetryConfiguration.getActive().getConnectionString(), CONNECTION_STRING);
}

@Test
//"LazySetOptIn is TRUE, ConnectionString is NULL, InstrumentationKey is valid, and EnableAgent is TRUE"
public void enableLazySetWithLazySetOptInOnConnectionStringNullInstrumentationKeyNotNull() {
assertTrue(LazyConfigurationAccessor.shouldSetConnectionString(false, "true"));
LazyConfigurationAccessor.setConnectionString(null, INSTRUMENTATION_KEY);
assertEquals(TelemetryConfiguration.getActive().getConnectionString(), "InstrumentationKey=" + INSTRUMENTATION_KEY);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.api.trace.SpanId;
import io.opentelemetry.api.trace.StatusCode;
import io.opentelemetry.instrumentation.api.aiappid.AiAppId;
import io.opentelemetry.instrumentation.api.aisdk.AiAppId;
import io.opentelemetry.sdk.common.CompletableResultCode;
import io.opentelemetry.sdk.trace.data.EventData;
import io.opentelemetry.sdk.trace.data.LinkData;
Expand Down

0 comments on commit cc8b707

Please sign in to comment.