From e404d80a26193a52690d8a0368edf4f016387565 Mon Sep 17 00:00:00 2001 From: Helen Yang Date: Fri, 30 Sep 2022 12:58:38 -0700 Subject: [PATCH 01/12] Update azure functions auto-instrumentation's custom dimensions --- .../AzureFunctionsCustomDimensions.java | 62 +++++++++++++++++++ .../init/AzureFunctionsLogProcessor.java | 36 +++++++++++ .../agent/internal/init/SecondEntryPoint.java | 5 ++ .../implementation/AiSemanticAttributes.java | 11 ++++ .../InvocationInstrumentation.java | 24 ++++++- .../InvocationRequestExtractAdapter.java | 8 +++ 6 files changed, 144 insertions(+), 2 deletions(-) create mode 100644 agent/agent-bootstrap/src/main/java/com/microsoft/applicationinsights/agent/bootstrap/AzureFunctionsCustomDimensions.java create mode 100644 agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/AzureFunctionsLogProcessor.java diff --git a/agent/agent-bootstrap/src/main/java/com/microsoft/applicationinsights/agent/bootstrap/AzureFunctionsCustomDimensions.java b/agent/agent-bootstrap/src/main/java/com/microsoft/applicationinsights/agent/bootstrap/AzureFunctionsCustomDimensions.java new file mode 100644 index 00000000000..72197f91576 --- /dev/null +++ b/agent/agent-bootstrap/src/main/java/com/microsoft/applicationinsights/agent/bootstrap/AzureFunctionsCustomDimensions.java @@ -0,0 +1,62 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.applicationinsights.agent.bootstrap; + +import io.opentelemetry.context.Context; +import io.opentelemetry.context.ContextKey; +import io.opentelemetry.context.ImplicitContextKeyed; + +public class AzureFunctionsCustomDimensions implements ImplicitContextKeyed { + + private static final ContextKey + AI_FUNCTION_CUSTOM_DIMENSIONS_KEY = ContextKey.named("ai-function-custom-dimensions"); + + public final String invocationId; + public final String processId; + public final String logLevel; + public final String category; + public final String hostInstanceId; + public final String azFunctionLiveLogsSessionId; + + public AzureFunctionsCustomDimensions( + String invocationId, + String processId, + String logLevel, + String category, + String hostInstanceId, + String azFunctionLiveLogsSessionId) { + this.invocationId = invocationId; + this.processId = processId; + this.logLevel = logLevel; + this.category = category; + this.hostInstanceId = hostInstanceId; + this.azFunctionLiveLogsSessionId = azFunctionLiveLogsSessionId; + } + + public static AzureFunctionsCustomDimensions fromContext(Context context) { + return context.get(AI_FUNCTION_CUSTOM_DIMENSIONS_KEY); + } + + @Override + public Context storeInContext(Context context) { + return context.with(AI_FUNCTION_CUSTOM_DIMENSIONS_KEY, this); + } + + // TODO to be removed and it's for debugging + public String toString() { + return "{invocationId:" + + invocationId + + ", processId:" + + processId + + ", logLevel:" + + logLevel + + ", category:" + + category + + ", hostInstanceId:" + + hostInstanceId + + ", azFunctionLiveLogSessionId:" + + azFunctionLiveLogsSessionId + + "}"; + } +} diff --git a/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/AzureFunctionsLogProcessor.java b/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/AzureFunctionsLogProcessor.java new file mode 100644 index 00000000000..e6a9672da2e --- /dev/null +++ b/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/AzureFunctionsLogProcessor.java @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.applicationinsights.agent.internal.init; + +import com.azure.core.util.logging.ClientLogger; +import com.azure.monitor.opentelemetry.exporter.implementation.AiSemanticAttributes; +import com.microsoft.applicationinsights.agent.bootstrap.AzureFunctionsCustomDimensions; +import io.opentelemetry.context.Context; +import io.opentelemetry.sdk.logs.LogProcessor; +import io.opentelemetry.sdk.logs.ReadWriteLogRecord; + +public class AzureFunctionsLogProcessor implements LogProcessor { + + private static final ClientLogger logger = new ClientLogger(AzureFunctionsLogProcessor.class); + + @Override + public void onEmit(ReadWriteLogRecord logRecord) { + AzureFunctionsCustomDimensions customDimensions = + AzureFunctionsCustomDimensions.fromContext(Context.current()); + logger.verbose( + "####### AzureFunctionsLogProcessor::onEmit:: \n CustomDimensions: {}", + customDimensions.toString()); + if (customDimensions != null) { + logRecord.setAttribute(AiSemanticAttributes.INVOCATION_ID, customDimensions.invocationId); + logRecord.setAttribute(AiSemanticAttributes.PROCESS_ID, customDimensions.processId); + logRecord.setAttribute(AiSemanticAttributes.LOG_LEVEL, customDimensions.logLevel); + logRecord.setAttribute(AiSemanticAttributes.CATEGORY, customDimensions.category); + logRecord.setAttribute( + AiSemanticAttributes.HOST_INSTANCE_ID, customDimensions.hostInstanceId); + logRecord.setAttribute( + AiSemanticAttributes.AZ_FUNC_LIVE_LOGS_SESSION_ID, + customDimensions.azFunctionLiveLogsSessionId); + } + } +} diff --git a/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/SecondEntryPoint.java b/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/SecondEntryPoint.java index 36f96061a42..0af334b84eb 100644 --- a/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/SecondEntryPoint.java +++ b/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/SecondEntryPoint.java @@ -432,6 +432,11 @@ private static SdkLogEmitterProviderBuilder configureLogging( Configuration configuration) { builder.addLogProcessor(new AzureMonitorLogProcessor()); + + if ("java".equals(System.getenv("FUNCTIONS_WORKER_RUNTIME"))) { + builder.addLogProcessor(new AzureFunctionsLogProcessor()); + } + if (!configuration.preview.inheritedAttributes.isEmpty()) { builder.addLogProcessor( new InheritedAttributesLogProcessor(configuration.preview.inheritedAttributes)); diff --git a/agent/azure-monitor-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/AiSemanticAttributes.java b/agent/azure-monitor-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/AiSemanticAttributes.java index 4dbfb4bc166..465b6861be6 100644 --- a/agent/azure-monitor-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/AiSemanticAttributes.java +++ b/agent/azure-monitor-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/AiSemanticAttributes.java @@ -106,5 +106,16 @@ public final class AiSemanticAttributes { public static final AttributeKey IS_PRE_AGGREGATED = AttributeKey.booleanKey("applicationinsights.internal.is_pre_aggregated"); + // Azure Function + + public static final AttributeKey INVOCATION_ID = AttributeKey.stringKey("InvocationId"); + public static final AttributeKey PROCESS_ID = AttributeKey.stringKey("ProcessId"); + public static final AttributeKey LOG_LEVEL = AttributeKey.stringKey("LogLevel"); + public static final AttributeKey CATEGORY = AttributeKey.stringKey("Category"); + public static final AttributeKey HOST_INSTANCE_ID = + AttributeKey.stringKey("HostInstanceId"); + public static final AttributeKey AZ_FUNC_LIVE_LOGS_SESSION_ID = + AttributeKey.stringKey("#AzFuncLiveLogsSessionId"); + private AiSemanticAttributes() {} } diff --git a/agent/instrumentation/azure-functions/src/main/java/io/opentelemetry/javaagent/instrumentation/azurefunctions/InvocationInstrumentation.java b/agent/instrumentation/azure-functions/src/main/java/io/opentelemetry/javaagent/instrumentation/azurefunctions/InvocationInstrumentation.java index 854ce7d5548..705fe6f8398 100644 --- a/agent/instrumentation/azure-functions/src/main/java/io/opentelemetry/javaagent/instrumentation/azurefunctions/InvocationInstrumentation.java +++ b/agent/instrumentation/azure-functions/src/main/java/io/opentelemetry/javaagent/instrumentation/azurefunctions/InvocationInstrumentation.java @@ -9,6 +9,7 @@ import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import com.microsoft.applicationinsights.agent.bootstrap.AzureFunctions; +import com.microsoft.applicationinsights.agent.bootstrap.AzureFunctionsCustomDimensions; import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.SpanContext; @@ -16,6 +17,7 @@ import io.opentelemetry.context.Scope; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; +import java.util.Map; import javax.annotation.Nullable; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.type.TypeDescription; @@ -39,7 +41,12 @@ public void transform(TypeTransformer transformer) { InvocationInstrumentation.class.getName() + "$ExecuteAdvice"); } - @SuppressWarnings({"unused", "PrivateConstructorForUtilityClass", "MustBeClosedChecker"}) + @SuppressWarnings({ + "unused", + "PrivateConstructorForUtilityClass", + "MustBeClosedChecker", + "unchecked" + }) public static class ExecuteAdvice { @Nullable @Advice.OnMethodEnter(suppress = Throwable.class) @@ -57,7 +64,20 @@ public static Scope methodEnter(@Advice.Argument(0) Object request) .extract(Context.root(), traceContext, GETTER); SpanContext spanContext = Span.fromContext(extractedContext).getSpanContext(); - return Context.current().with(Span.wrap(spanContext)).makeCurrent(); + String invocationId = + (String) InvocationRequestExtractAdapter.getInvocationId.invoke(request); + Map attributesMap = + (Map) + InvocationRequestExtractAdapter.getAttributesMap.invoke(traceContext); + AzureFunctionsCustomDimensions customDimensions = + new AzureFunctionsCustomDimensions( + invocationId, + attributesMap.get("ProcessId"), + attributesMap.get("LogLevel"), + attributesMap.get("Category"), + attributesMap.get("HostInstanceId"), + attributesMap.get("#AzFuncLiveLogsSessionId")); + return Context.current().with(Span.wrap(spanContext)).with(customDimensions).makeCurrent(); } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) diff --git a/agent/instrumentation/azure-functions/src/main/java/io/opentelemetry/javaagent/instrumentation/azurefunctions/InvocationRequestExtractAdapter.java b/agent/instrumentation/azure-functions/src/main/java/io/opentelemetry/javaagent/instrumentation/azurefunctions/InvocationRequestExtractAdapter.java index ca50444cb8c..d18477edf09 100644 --- a/agent/instrumentation/azure-functions/src/main/java/io/opentelemetry/javaagent/instrumentation/azurefunctions/InvocationRequestExtractAdapter.java +++ b/agent/instrumentation/azure-functions/src/main/java/io/opentelemetry/javaagent/instrumentation/azurefunctions/InvocationRequestExtractAdapter.java @@ -20,11 +20,15 @@ public class InvocationRequestExtractAdapter implements TextMapGetter { new InvocationRequestExtractAdapter(); public static final Method getTraceContextMethod; + public static final Method getInvocationId; + public static final Method getAttributesMap; private static final Method getTraceParentMethod; private static final Method getTraceStateMethod; static { Method getTraceContextMethodLocal = null; + Method getInvocationIdLocal = null; + Method getAttributesMapLocal = null; Method getTraceParentMethodLocal = null; Method getTraceStateMethodLocal = null; try { @@ -33,12 +37,16 @@ public class InvocationRequestExtractAdapter implements TextMapGetter { Class rpcTraceContextClass = Class.forName("com.microsoft.azure.functions.rpc.messages.RpcTraceContext"); getTraceContextMethodLocal = invocationRequestClass.getMethod("getTraceContext"); + getInvocationIdLocal = invocationRequestClass.getMethod("getInvocationId"); + getAttributesMapLocal = rpcTraceContextClass.getMethod("getAttributesMap"); getTraceParentMethodLocal = rpcTraceContextClass.getMethod("getTraceParent"); getTraceStateMethodLocal = rpcTraceContextClass.getMethod("getTraceState"); } catch (ReflectiveOperationException e) { logger.log(Level.SEVERE, e.getMessage(), e); } getTraceContextMethod = getTraceContextMethodLocal; + getInvocationId = getInvocationIdLocal; + getAttributesMap = getAttributesMapLocal; getTraceParentMethod = getTraceParentMethodLocal; getTraceStateMethod = getTraceStateMethodLocal; } From ad2e3baad45faa7eafd4742a5acdafe18f4e0823 Mon Sep 17 00:00:00 2001 From: Helen Yang Date: Fri, 30 Sep 2022 13:06:06 -0700 Subject: [PATCH 02/12] Rename --- .../agent/bootstrap/AzureFunctionsCustomDimensions.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/agent/agent-bootstrap/src/main/java/com/microsoft/applicationinsights/agent/bootstrap/AzureFunctionsCustomDimensions.java b/agent/agent-bootstrap/src/main/java/com/microsoft/applicationinsights/agent/bootstrap/AzureFunctionsCustomDimensions.java index 72197f91576..e22e5ab9dcc 100644 --- a/agent/agent-bootstrap/src/main/java/com/microsoft/applicationinsights/agent/bootstrap/AzureFunctionsCustomDimensions.java +++ b/agent/agent-bootstrap/src/main/java/com/microsoft/applicationinsights/agent/bootstrap/AzureFunctionsCustomDimensions.java @@ -10,7 +10,7 @@ public class AzureFunctionsCustomDimensions implements ImplicitContextKeyed { private static final ContextKey - AI_FUNCTION_CUSTOM_DIMENSIONS_KEY = ContextKey.named("ai-function-custom-dimensions"); + AI_FUNCTIONS_CUSTOM_DIMENSIONS_KEY = ContextKey.named("ai-functions-custom-dimensions"); public final String invocationId; public final String processId; @@ -35,12 +35,12 @@ public AzureFunctionsCustomDimensions( } public static AzureFunctionsCustomDimensions fromContext(Context context) { - return context.get(AI_FUNCTION_CUSTOM_DIMENSIONS_KEY); + return context.get(AI_FUNCTIONS_CUSTOM_DIMENSIONS_KEY); } @Override public Context storeInContext(Context context) { - return context.with(AI_FUNCTION_CUSTOM_DIMENSIONS_KEY, this); + return context.with(AI_FUNCTIONS_CUSTOM_DIMENSIONS_KEY, this); } // TODO to be removed and it's for debugging From c6f4fce28077e7acfa59c81fc0bf3ee5ded261d3 Mon Sep 17 00:00:00 2001 From: Helen Yang Date: Fri, 30 Sep 2022 13:42:09 -0700 Subject: [PATCH 03/12] Fix errorprone --- .../agent/bootstrap/AzureFunctionsCustomDimensions.java | 1 + 1 file changed, 1 insertion(+) diff --git a/agent/agent-bootstrap/src/main/java/com/microsoft/applicationinsights/agent/bootstrap/AzureFunctionsCustomDimensions.java b/agent/agent-bootstrap/src/main/java/com/microsoft/applicationinsights/agent/bootstrap/AzureFunctionsCustomDimensions.java index e22e5ab9dcc..24741c6e8a9 100644 --- a/agent/agent-bootstrap/src/main/java/com/microsoft/applicationinsights/agent/bootstrap/AzureFunctionsCustomDimensions.java +++ b/agent/agent-bootstrap/src/main/java/com/microsoft/applicationinsights/agent/bootstrap/AzureFunctionsCustomDimensions.java @@ -44,6 +44,7 @@ public Context storeInContext(Context context) { } // TODO to be removed and it's for debugging + @Override public String toString() { return "{invocationId:" + invocationId From b1a550c18d7e87b35b6da4899267e7bcb7bc6f16 Mon Sep 17 00:00:00 2001 From: Helen Yang Date: Fri, 30 Sep 2022 13:45:38 -0700 Subject: [PATCH 04/12] Fix spotless --- .../agent/bootstrap/AzureFunctionsCustomDimensions.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agent/agent-bootstrap/src/main/java/com/microsoft/applicationinsights/agent/bootstrap/AzureFunctionsCustomDimensions.java b/agent/agent-bootstrap/src/main/java/com/microsoft/applicationinsights/agent/bootstrap/AzureFunctionsCustomDimensions.java index 24741c6e8a9..eb0939c0783 100644 --- a/agent/agent-bootstrap/src/main/java/com/microsoft/applicationinsights/agent/bootstrap/AzureFunctionsCustomDimensions.java +++ b/agent/agent-bootstrap/src/main/java/com/microsoft/applicationinsights/agent/bootstrap/AzureFunctionsCustomDimensions.java @@ -10,7 +10,7 @@ public class AzureFunctionsCustomDimensions implements ImplicitContextKeyed { private static final ContextKey - AI_FUNCTIONS_CUSTOM_DIMENSIONS_KEY = ContextKey.named("ai-functions-custom-dimensions"); + AI_FUNCTIONS_CUSTOM_DIMENSIONS_KEY = ContextKey.named("ai-functions-custom-dimensions"); public final String invocationId; public final String processId; From 4605f87c9d5a81e43f9f5e06f4edfa1aa629dc68 Mon Sep 17 00:00:00 2001 From: Helen Yang Date: Fri, 30 Sep 2022 14:21:24 -0700 Subject: [PATCH 05/12] Fix lgtm --- .../init/AzureFunctionsLogProcessor.java | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/AzureFunctionsLogProcessor.java b/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/AzureFunctionsLogProcessor.java index e6a9672da2e..7a218cbe1f1 100644 --- a/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/AzureFunctionsLogProcessor.java +++ b/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/AzureFunctionsLogProcessor.java @@ -21,13 +21,23 @@ public void onEmit(ReadWriteLogRecord logRecord) { logger.verbose( "####### AzureFunctionsLogProcessor::onEmit:: \n CustomDimensions: {}", customDimensions.toString()); - if (customDimensions != null) { + if (customDimensions.invocationId != null) { logRecord.setAttribute(AiSemanticAttributes.INVOCATION_ID, customDimensions.invocationId); - logRecord.setAttribute(AiSemanticAttributes.PROCESS_ID, customDimensions.processId); - logRecord.setAttribute(AiSemanticAttributes.LOG_LEVEL, customDimensions.logLevel); + } + if (customDimensions.processId != null) { + logRecord.setAttribute(AiSemanticAttributes.PROCESS_ID, customDimensions.processId); + } + if (customDimensions.logLevel != null) { + logRecord.setAttribute(AiSemanticAttributes.LOG_LEVEL, customDimensions.logLevel); + } + if (customDimensions.category != null) { logRecord.setAttribute(AiSemanticAttributes.CATEGORY, customDimensions.category); + } + if (customDimensions.hostInstanceId != null) { logRecord.setAttribute( AiSemanticAttributes.HOST_INSTANCE_ID, customDimensions.hostInstanceId); + } + if (customDimensions.azFunctionLiveLogsSessionId != null) { logRecord.setAttribute( AiSemanticAttributes.AZ_FUNC_LIVE_LOGS_SESSION_ID, customDimensions.azFunctionLiveLogsSessionId); From a43df04bcaeacd9fa68824d63b1f7b3ce08a953b Mon Sep 17 00:00:00 2001 From: Helen Yang Date: Fri, 30 Sep 2022 14:35:04 -0700 Subject: [PATCH 06/12] Fix spotless --- .../agent/internal/init/AzureFunctionsLogProcessor.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/AzureFunctionsLogProcessor.java b/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/AzureFunctionsLogProcessor.java index 7a218cbe1f1..24a7804b241 100644 --- a/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/AzureFunctionsLogProcessor.java +++ b/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/AzureFunctionsLogProcessor.java @@ -25,10 +25,10 @@ public void onEmit(ReadWriteLogRecord logRecord) { logRecord.setAttribute(AiSemanticAttributes.INVOCATION_ID, customDimensions.invocationId); } if (customDimensions.processId != null) { - logRecord.setAttribute(AiSemanticAttributes.PROCESS_ID, customDimensions.processId); + logRecord.setAttribute(AiSemanticAttributes.PROCESS_ID, customDimensions.processId); } if (customDimensions.logLevel != null) { - logRecord.setAttribute(AiSemanticAttributes.LOG_LEVEL, customDimensions.logLevel); + logRecord.setAttribute(AiSemanticAttributes.LOG_LEVEL, customDimensions.logLevel); } if (customDimensions.category != null) { logRecord.setAttribute(AiSemanticAttributes.CATEGORY, customDimensions.category); From 82b5b6679459da57c1a9e6620a948a53386b4f1c Mon Sep 17 00:00:00 2001 From: Helen Yang Date: Mon, 3 Oct 2022 10:05:35 -0700 Subject: [PATCH 07/12] Address comments --- .../AzureFunctionsCustomDimensions.java | 2 +- .../init/AzureFunctionsLogProcessor.java | 19 ++++++---- .../implementation/AiSemanticAttributes.java | 13 +++---- .../InvocationInstrumentation.java | 35 +++++++++++-------- 4 files changed, 40 insertions(+), 29 deletions(-) diff --git a/agent/agent-bootstrap/src/main/java/com/microsoft/applicationinsights/agent/bootstrap/AzureFunctionsCustomDimensions.java b/agent/agent-bootstrap/src/main/java/com/microsoft/applicationinsights/agent/bootstrap/AzureFunctionsCustomDimensions.java index eb0939c0783..979871ecddd 100644 --- a/agent/agent-bootstrap/src/main/java/com/microsoft/applicationinsights/agent/bootstrap/AzureFunctionsCustomDimensions.java +++ b/agent/agent-bootstrap/src/main/java/com/microsoft/applicationinsights/agent/bootstrap/AzureFunctionsCustomDimensions.java @@ -7,7 +7,7 @@ import io.opentelemetry.context.ContextKey; import io.opentelemetry.context.ImplicitContextKeyed; -public class AzureFunctionsCustomDimensions implements ImplicitContextKeyed { +public final class AzureFunctionsCustomDimensions implements ImplicitContextKeyed { private static final ContextKey AI_FUNCTIONS_CUSTOM_DIMENSIONS_KEY = ContextKey.named("ai-functions-custom-dimensions"); diff --git a/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/AzureFunctionsLogProcessor.java b/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/AzureFunctionsLogProcessor.java index 24a7804b241..65448929424 100644 --- a/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/AzureFunctionsLogProcessor.java +++ b/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/AzureFunctionsLogProcessor.java @@ -10,7 +10,7 @@ import io.opentelemetry.sdk.logs.LogProcessor; import io.opentelemetry.sdk.logs.ReadWriteLogRecord; -public class AzureFunctionsLogProcessor implements LogProcessor { +public final class AzureFunctionsLogProcessor implements LogProcessor { private static final ClientLogger logger = new ClientLogger(AzureFunctionsLogProcessor.class); @@ -18,28 +18,33 @@ public class AzureFunctionsLogProcessor implements LogProcessor { public void onEmit(ReadWriteLogRecord logRecord) { AzureFunctionsCustomDimensions customDimensions = AzureFunctionsCustomDimensions.fromContext(Context.current()); + if (customDimensions == null) { + logger.warning("'ai-functions-custom-dimensions' is missing from the context"); + return; + } logger.verbose( "####### AzureFunctionsLogProcessor::onEmit:: \n CustomDimensions: {}", customDimensions.toString()); if (customDimensions.invocationId != null) { - logRecord.setAttribute(AiSemanticAttributes.INVOCATION_ID, customDimensions.invocationId); + logRecord.setAttribute( + AiSemanticAttributes.AZ_FN_INVOCATION_ID, customDimensions.invocationId); } if (customDimensions.processId != null) { - logRecord.setAttribute(AiSemanticAttributes.PROCESS_ID, customDimensions.processId); + logRecord.setAttribute(AiSemanticAttributes.AZ_FN_PROCESS_ID, customDimensions.processId); } if (customDimensions.logLevel != null) { - logRecord.setAttribute(AiSemanticAttributes.LOG_LEVEL, customDimensions.logLevel); + logRecord.setAttribute(AiSemanticAttributes.AZ_FN_LOG_LEVEL, customDimensions.logLevel); } if (customDimensions.category != null) { - logRecord.setAttribute(AiSemanticAttributes.CATEGORY, customDimensions.category); + logRecord.setAttribute(AiSemanticAttributes.AZ_FN_CATEGORY, customDimensions.category); } if (customDimensions.hostInstanceId != null) { logRecord.setAttribute( - AiSemanticAttributes.HOST_INSTANCE_ID, customDimensions.hostInstanceId); + AiSemanticAttributes.AZ_FN_HOST_INSTANCE_ID, customDimensions.hostInstanceId); } if (customDimensions.azFunctionLiveLogsSessionId != null) { logRecord.setAttribute( - AiSemanticAttributes.AZ_FUNC_LIVE_LOGS_SESSION_ID, + AiSemanticAttributes.AZ_FN_LIVE_LOGS_SESSION_ID, customDimensions.azFunctionLiveLogsSessionId); } } diff --git a/agent/azure-monitor-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/AiSemanticAttributes.java b/agent/azure-monitor-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/AiSemanticAttributes.java index 465b6861be6..56be20f8efd 100644 --- a/agent/azure-monitor-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/AiSemanticAttributes.java +++ b/agent/azure-monitor-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/AiSemanticAttributes.java @@ -108,13 +108,14 @@ public final class AiSemanticAttributes { // Azure Function - public static final AttributeKey INVOCATION_ID = AttributeKey.stringKey("InvocationId"); - public static final AttributeKey PROCESS_ID = AttributeKey.stringKey("ProcessId"); - public static final AttributeKey LOG_LEVEL = AttributeKey.stringKey("LogLevel"); - public static final AttributeKey CATEGORY = AttributeKey.stringKey("Category"); - public static final AttributeKey HOST_INSTANCE_ID = + public static final AttributeKey AZ_FN_INVOCATION_ID = + AttributeKey.stringKey("InvocationId"); + public static final AttributeKey AZ_FN_PROCESS_ID = AttributeKey.stringKey("ProcessId"); + public static final AttributeKey AZ_FN_LOG_LEVEL = AttributeKey.stringKey("LogLevel"); + public static final AttributeKey AZ_FN_CATEGORY = AttributeKey.stringKey("Category"); + public static final AttributeKey AZ_FN_HOST_INSTANCE_ID = AttributeKey.stringKey("HostInstanceId"); - public static final AttributeKey AZ_FUNC_LIVE_LOGS_SESSION_ID = + public static final AttributeKey AZ_FN_LIVE_LOGS_SESSION_ID = AttributeKey.stringKey("#AzFuncLiveLogsSessionId"); private AiSemanticAttributes() {} diff --git a/agent/instrumentation/azure-functions/src/main/java/io/opentelemetry/javaagent/instrumentation/azurefunctions/InvocationInstrumentation.java b/agent/instrumentation/azure-functions/src/main/java/io/opentelemetry/javaagent/instrumentation/azurefunctions/InvocationInstrumentation.java index 705fe6f8398..0ffa3134cd6 100644 --- a/agent/instrumentation/azure-functions/src/main/java/io/opentelemetry/javaagent/instrumentation/azurefunctions/InvocationInstrumentation.java +++ b/agent/instrumentation/azure-functions/src/main/java/io/opentelemetry/javaagent/instrumentation/azurefunctions/InvocationInstrumentation.java @@ -63,21 +63,10 @@ public static Scope methodEnter(@Advice.Argument(0) Object request) .getTextMapPropagator() .extract(Context.root(), traceContext, GETTER); SpanContext spanContext = Span.fromContext(extractedContext).getSpanContext(); - - String invocationId = - (String) InvocationRequestExtractAdapter.getInvocationId.invoke(request); - Map attributesMap = - (Map) - InvocationRequestExtractAdapter.getAttributesMap.invoke(traceContext); - AzureFunctionsCustomDimensions customDimensions = - new AzureFunctionsCustomDimensions( - invocationId, - attributesMap.get("ProcessId"), - attributesMap.get("LogLevel"), - attributesMap.get("Category"), - attributesMap.get("HostInstanceId"), - attributesMap.get("#AzFuncLiveLogsSessionId")); - return Context.current().with(Span.wrap(spanContext)).with(customDimensions).makeCurrent(); + return Context.current() + .with(Span.wrap(spanContext)) + .with(generateCustomDimensions(request, traceContext)) + .makeCurrent(); } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) @@ -86,5 +75,21 @@ public static void methodExit(@Advice.Enter @Nullable Scope scope) { scope.close(); } } + + private static AzureFunctionsCustomDimensions generateCustomDimensions( + Object request, Object traceContext) throws ReflectiveOperationException { + String invocationId = + (String) InvocationRequestExtractAdapter.getInvocationId.invoke(request); + Map attributesMap = + (Map) + InvocationRequestExtractAdapter.getAttributesMap.invoke(traceContext); + return new AzureFunctionsCustomDimensions( + invocationId, + attributesMap.get("ProcessId"), + attributesMap.get("LogLevel"), + attributesMap.get("Category"), + attributesMap.get("HostInstanceId"), + attributesMap.get("#AzFuncLiveLogsSessionId")); + } } } From a6e7366f10f522fa1d00092276aca1d2f383572f Mon Sep 17 00:00:00 2001 From: Helen Yang Date: Tue, 4 Oct 2022 13:39:40 -0700 Subject: [PATCH 08/12] Remove debug log --- .../AzureFunctionsCustomDimensions.java | 18 ------------------ .../init/AzureFunctionsLogProcessor.java | 3 --- 2 files changed, 21 deletions(-) diff --git a/agent/agent-bootstrap/src/main/java/com/microsoft/applicationinsights/agent/bootstrap/AzureFunctionsCustomDimensions.java b/agent/agent-bootstrap/src/main/java/com/microsoft/applicationinsights/agent/bootstrap/AzureFunctionsCustomDimensions.java index 979871ecddd..a1242deb766 100644 --- a/agent/agent-bootstrap/src/main/java/com/microsoft/applicationinsights/agent/bootstrap/AzureFunctionsCustomDimensions.java +++ b/agent/agent-bootstrap/src/main/java/com/microsoft/applicationinsights/agent/bootstrap/AzureFunctionsCustomDimensions.java @@ -42,22 +42,4 @@ public static AzureFunctionsCustomDimensions fromContext(Context context) { public Context storeInContext(Context context) { return context.with(AI_FUNCTIONS_CUSTOM_DIMENSIONS_KEY, this); } - - // TODO to be removed and it's for debugging - @Override - public String toString() { - return "{invocationId:" - + invocationId - + ", processId:" - + processId - + ", logLevel:" - + logLevel - + ", category:" - + category - + ", hostInstanceId:" - + hostInstanceId - + ", azFunctionLiveLogSessionId:" - + azFunctionLiveLogsSessionId - + "}"; - } } diff --git a/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/AzureFunctionsLogProcessor.java b/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/AzureFunctionsLogProcessor.java index 65448929424..0515ddae00c 100644 --- a/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/AzureFunctionsLogProcessor.java +++ b/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/AzureFunctionsLogProcessor.java @@ -22,9 +22,6 @@ public void onEmit(ReadWriteLogRecord logRecord) { logger.warning("'ai-functions-custom-dimensions' is missing from the context"); return; } - logger.verbose( - "####### AzureFunctionsLogProcessor::onEmit:: \n CustomDimensions: {}", - customDimensions.toString()); if (customDimensions.invocationId != null) { logRecord.setAttribute( AiSemanticAttributes.AZ_FN_INVOCATION_ID, customDimensions.invocationId); From 1e57bf191061d838241ec215a17300592b2c3166 Mon Sep 17 00:00:00 2001 From: Helen Yang Date: Mon, 10 Oct 2022 11:23:26 -0700 Subject: [PATCH 09/12] Refactor --- .../implementation/AiSemanticAttributes.java | 15 +++++---- .../implementation/LogDataMapper.java | 32 +++++++++++++++++++ 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/agent/azure-monitor-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/AiSemanticAttributes.java b/agent/azure-monitor-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/AiSemanticAttributes.java index 56be20f8efd..47769d3f4c2 100644 --- a/agent/azure-monitor-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/AiSemanticAttributes.java +++ b/agent/azure-monitor-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/AiSemanticAttributes.java @@ -109,14 +109,17 @@ public final class AiSemanticAttributes { // Azure Function public static final AttributeKey AZ_FN_INVOCATION_ID = - AttributeKey.stringKey("InvocationId"); - public static final AttributeKey AZ_FN_PROCESS_ID = AttributeKey.stringKey("ProcessId"); - public static final AttributeKey AZ_FN_LOG_LEVEL = AttributeKey.stringKey("LogLevel"); - public static final AttributeKey AZ_FN_CATEGORY = AttributeKey.stringKey("Category"); + AttributeKey.stringKey("applicationinsights.internal.invocationId"); + public static final AttributeKey AZ_FN_PROCESS_ID = + AttributeKey.stringKey("applicationinsights.internal.processId"); + public static final AttributeKey AZ_FN_LOG_LEVEL = + AttributeKey.stringKey("applicationinsights.internal.logLevel"); + public static final AttributeKey AZ_FN_CATEGORY = + AttributeKey.stringKey("applicationinsights.internal.category"); public static final AttributeKey AZ_FN_HOST_INSTANCE_ID = - AttributeKey.stringKey("HostInstanceId"); + AttributeKey.stringKey("applicationinsights.internal.hostInstanceId"); public static final AttributeKey AZ_FN_LIVE_LOGS_SESSION_ID = - AttributeKey.stringKey("#AzFuncLiveLogsSessionId"); + AttributeKey.stringKey("applicationinsights.internal.azFuncLiveLogsSessionId"); private AiSemanticAttributes() {} } diff --git a/agent/azure-monitor-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/LogDataMapper.java b/agent/azure-monitor-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/LogDataMapper.java index 230bedafff6..2a25e0f7ed6 100644 --- a/agent/azure-monitor-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/LogDataMapper.java +++ b/agent/azure-monitor-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/LogDataMapper.java @@ -138,6 +138,9 @@ private static void setItemCount( private static void setExtraAttributes( AbstractTelemetryBuilder telemetryBuilder, Attributes attributes) { + if ("java".equals(System.getenv("FUNCTIONS_WORKER_RUNTIME"))) { + setFunctionExtraAttributes(telemetryBuilder, attributes); + } attributes.forEach( (attributeKey, value) -> { String key = attributeKey.getKey(); @@ -196,6 +199,35 @@ private static void setExtraAttributes( }); } + private static void setFunctionExtraAttributes( + AbstractTelemetryBuilder telemetryBuilder, Attributes attributes) { + String invocationId = attributes.get(AiSemanticAttributes.AZ_FN_INVOCATION_ID); + if (invocationId != null) { + telemetryBuilder.addProperty( + "InvocationId", attributes.get(AiSemanticAttributes.AZ_FN_INVOCATION_ID)); + } + String processId = attributes.get(AiSemanticAttributes.AZ_FN_PROCESS_ID); + if (processId != null) { + telemetryBuilder.addProperty("ProcessId", processId); + } + String logLevel = attributes.get(AiSemanticAttributes.AZ_FN_LOG_LEVEL); + if (logLevel != null) { + telemetryBuilder.addProperty("LogLevel", logLevel); + } + String category = attributes.get(AiSemanticAttributes.AZ_FN_CATEGORY); + if (category != null) { + telemetryBuilder.addProperty("Category", category); + } + String hostInstanceId = attributes.get(AiSemanticAttributes.AZ_FN_HOST_INSTANCE_ID); + if (hostInstanceId != null) { + telemetryBuilder.addProperty("HostInstanceId", hostInstanceId); + } + String liveLogsSessionId = attributes.get(AiSemanticAttributes.AZ_FN_LIVE_LOGS_SESSION_ID); + if (liveLogsSessionId != null) { + telemetryBuilder.addProperty("#AzFuncLiveLogsSessionId", liveLogsSessionId); + } + } + private void setLoggerProperties( AbstractTelemetryBuilder telemetryBuilder, @Nullable String loggerName, From 73cd4213bfc738f0e4dff398fc176a1474008cb3 Mon Sep 17 00:00:00 2001 From: Helen Yang Date: Wed, 12 Oct 2022 11:45:50 -0700 Subject: [PATCH 10/12] Explain why --- .../exporter/implementation/AiSemanticAttributes.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/agent/azure-monitor-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/AiSemanticAttributes.java b/agent/azure-monitor-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/AiSemanticAttributes.java index 47769d3f4c2..dea7949558f 100644 --- a/agent/azure-monitor-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/AiSemanticAttributes.java +++ b/agent/azure-monitor-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/AiSemanticAttributes.java @@ -106,8 +106,10 @@ public final class AiSemanticAttributes { public static final AttributeKey IS_PRE_AGGREGATED = AttributeKey.booleanKey("applicationinsights.internal.is_pre_aggregated"); - // Azure Function - + // These attributes are specific for Azure Function and are added to Application Insights traces' + // custom dimensions. + // When Azure Function host starts suppressing the same logs to Application Insights, these new + // attributes will provide backward compatibility for keeping the same behaviour. public static final AttributeKey AZ_FN_INVOCATION_ID = AttributeKey.stringKey("applicationinsights.internal.invocationId"); public static final AttributeKey AZ_FN_PROCESS_ID = From 4638ae04cdf6e435318f884b7a145f6a16518aa3 Mon Sep 17 00:00:00 2001 From: Helen Yang Date: Wed, 12 Oct 2022 11:46:48 -0700 Subject: [PATCH 11/12] Use verbose --- .../agent/internal/init/AzureFunctionsLogProcessor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/AzureFunctionsLogProcessor.java b/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/AzureFunctionsLogProcessor.java index 0515ddae00c..d29b7fc5e81 100644 --- a/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/AzureFunctionsLogProcessor.java +++ b/agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/init/AzureFunctionsLogProcessor.java @@ -19,7 +19,7 @@ public void onEmit(ReadWriteLogRecord logRecord) { AzureFunctionsCustomDimensions customDimensions = AzureFunctionsCustomDimensions.fromContext(Context.current()); if (customDimensions == null) { - logger.warning("'ai-functions-custom-dimensions' is missing from the context"); + logger.verbose("'ai-functions-custom-dimensions' is missing from the context"); return; } if (customDimensions.invocationId != null) { From d58a6ab55b5e46752a190d9721081de36a559bc9 Mon Sep 17 00:00:00 2001 From: Helen Yang Date: Wed, 12 Oct 2022 11:49:40 -0700 Subject: [PATCH 12/12] Reformat comment --- .../exporter/implementation/AiSemanticAttributes.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/agent/azure-monitor-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/AiSemanticAttributes.java b/agent/azure-monitor-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/AiSemanticAttributes.java index dea7949558f..fa7e1887510 100644 --- a/agent/azure-monitor-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/AiSemanticAttributes.java +++ b/agent/azure-monitor-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/AiSemanticAttributes.java @@ -107,9 +107,9 @@ public final class AiSemanticAttributes { AttributeKey.booleanKey("applicationinsights.internal.is_pre_aggregated"); // These attributes are specific for Azure Function and are added to Application Insights traces' - // custom dimensions. - // When Azure Function host starts suppressing the same logs to Application Insights, these new - // attributes will provide backward compatibility for keeping the same behaviour. + // custom dimensions. When Azure Function host starts suppressing the same logs to Application + // Insights, these new attributes will provide backward compatibility for keeping the same + // behaviour. public static final AttributeKey AZ_FN_INVOCATION_ID = AttributeKey.stringKey("applicationinsights.internal.invocationId"); public static final AttributeKey AZ_FN_PROCESS_ID =