diff --git a/agent-bridge/src/main/java/com/newrelic/agent/bridge/logging/AppLoggingUtils.java b/agent-bridge/src/main/java/com/newrelic/agent/bridge/logging/AppLoggingUtils.java index 271f651134..d5cbf0f474 100644 --- a/agent-bridge/src/main/java/com/newrelic/agent/bridge/logging/AppLoggingUtils.java +++ b/agent-bridge/src/main/java/com/newrelic/agent/bridge/logging/AppLoggingUtils.java @@ -6,6 +6,8 @@ */ package com.newrelic.agent.bridge.logging; +import com.newrelic.agent.bridge.logging.LogAttributeKey; +import com.newrelic.agent.bridge.logging.LogAttributeType; import com.newrelic.api.agent.NewRelic; import java.io.UnsupportedEncodingException; @@ -52,32 +54,11 @@ public class AppLoggingUtils { * @return agent linking metadata string blob */ public static String getLinkingMetadataBlob() { - return constructLinkingMetadataBlob(NewRelic.getAgent().getLinkingMetadata()); - } - - /** - * Gets a String representing the agent linking metadata in blob format: - * NR-LINKING|entity.guid|hostname|trace.id|span.id|entity.name| - * - * @param agentLinkingMetadata map of linking metadata - * @return agent linking metadata string blob - */ - public static String getLinkingMetadataBlobFromMap(Map agentLinkingMetadata) { - return constructLinkingMetadataBlob(agentLinkingMetadata); - } - - /** - * Constructs a String representing the agent linking metadata in blob format: - * NR-LINKING|entity.guid|hostname|trace.id|span.id|entity.name| - * - * @param agentLinkingMetadata map of linking metadata - * @return agent linking metadata string blob - */ - private static String constructLinkingMetadataBlob(Map agentLinkingMetadata) { + Map agentLinkingMetadata = NewRelic.getAgent().getLinkingMetadata(); StringBuilder blob = new StringBuilder(); blob.append(" ").append(BLOB_PREFIX).append(BLOB_DELIMITER); - if (agentLinkingMetadata != null && !agentLinkingMetadata.isEmpty()) { + if (agentLinkingMetadata != null && agentLinkingMetadata.size() > 0) { appendAttributeToBlob(agentLinkingMetadata.get(ENTITY_GUID), blob); appendAttributeToBlob(agentLinkingMetadata.get(HOSTNAME), blob); appendAttributeToBlob(agentLinkingMetadata.get(TRACE_ID), blob); diff --git a/instrumentation/apache-log4j-2/build.gradle b/instrumentation/apache-log4j-2/build.gradle index 2083af1595..2042aee68b 100644 --- a/instrumentation/apache-log4j-2/build.gradle +++ b/instrumentation/apache-log4j-2/build.gradle @@ -4,11 +4,12 @@ jar { dependencies { implementation(project(":agent-bridge")) - implementation("org.apache.logging.log4j:log4j-core:2.20.0") + implementation("org.apache.logging.log4j:log4j-core:2.17.1") } verifyInstrumentation { - passesOnly("org.apache.logging.log4j:log4j-core:[2.6,3.0.0-alpha1)") + passesOnly("org.apache.logging.log4j:log4j-core:[2.6,)") + excludeRegex '.*(alpha|beta|rc).*' } site { diff --git a/instrumentation/apache-log4j-2/src/main/java/com/nr/agent/instrumentation/log4j2/AgentUtil.java b/instrumentation/apache-log4j-2/src/main/java/com/nr/agent/instrumentation/log4j2/AgentUtil.java index 8b8ffdcef3..df8761d0fc 100644 --- a/instrumentation/apache-log4j-2/src/main/java/com/nr/agent/instrumentation/log4j2/AgentUtil.java +++ b/instrumentation/apache-log4j-2/src/main/java/com/nr/agent/instrumentation/log4j2/AgentUtil.java @@ -14,6 +14,7 @@ import org.apache.logging.log4j.Level; import org.apache.logging.log4j.core.LogEvent; import org.apache.logging.log4j.message.Message; +import org.apache.logging.log4j.util.ReadOnlyStringMap; import java.util.HashMap; import java.util.Map; @@ -127,28 +128,4 @@ private static int calculateInitialMapSize(Map mdcPropertyMap) { ? mdcPropertyMap.size() + DEFAULT_NUM_OF_LOG_EVENT_ATTRIBUTES : DEFAULT_NUM_OF_LOG_EVENT_ATTRIBUTES; } - - /** - * Checks pretty or compact JSON layout strings for a series of characters and returns the index of - * the characters or -1 if they were not found. This is used to find the log "message" substring - * so that the NR-LINKING metadata blob can be inserted when using local decorating with JsonLayout. - * - * @param writerString String representing JSON formatted log event - * @return positive int if index was found, else -1 - */ - public static int getIndexToModifyJson(String writerString) { - return writerString.indexOf("\",", writerString.indexOf("message")); - } - - /** - * Check if a valid match was found when calling String.indexOf. - * If index value is -1 then no valid match was found, a positive integer represents a valid index. - * - * @param indexToModifyJson int representing index returned by indexOf - * @return true if a valid index was found, else false - */ - public static boolean foundIndexToInsertLinkingMetadata(int indexToModifyJson) { - return indexToModifyJson != -1; - } - } diff --git a/instrumentation/apache-log4j-2/src/main/java/org/apache/logging/log4j/core/LogEvent_Instrumentation.java b/instrumentation/apache-log4j-2/src/main/java/org/apache/logging/log4j/core/LogEvent_Instrumentation.java deleted file mode 100644 index 4c86c4b000..0000000000 --- a/instrumentation/apache-log4j-2/src/main/java/org/apache/logging/log4j/core/LogEvent_Instrumentation.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * - * * Copyright 2023 New Relic Corporation. All rights reserved. - * * SPDX-License-Identifier: Apache-2.0 - * - */ - -package org.apache.logging.log4j.core; - -import com.newrelic.api.agent.NewRelic; -import com.newrelic.api.agent.weaver.MatchType; -import com.newrelic.api.agent.weaver.NewField; -import com.newrelic.api.agent.weaver.Weave; -import org.apache.logging.log4j.Level; -import org.apache.logging.log4j.Marker; -import org.apache.logging.log4j.ThreadContext; -import org.apache.logging.log4j.core.impl.ThrowableProxy; -import org.apache.logging.log4j.core.time.Instant; -import org.apache.logging.log4j.message.Message; -import org.apache.logging.log4j.util.ReadOnlyStringMap; - -import java.util.Map; - -import static com.newrelic.agent.bridge.logging.AppLoggingUtils.isApplicationLoggingLocalDecoratingEnabled; - -@Weave(originalName = "org.apache.logging.log4j.core.LogEvent", type = MatchType.Interface) -public abstract class LogEvent_Instrumentation { - - /* - * In cases where the LogEvent is sent to an AsyncAppender, getLinkingMetadata would get called on a new thread and the trace.id and span.id - * would be missing. To work around this we save the linking metadata on the LogEvent on the thread where it was created and use it later. - */ - @NewField - public Map agentLinkingMetadata = isApplicationLoggingLocalDecoratingEnabled() ? NewRelic.getAgent().getLinkingMetadata() : null; - - public abstract LogEvent toImmutable(); - - @Deprecated - public abstract Map getContextMap(); - - public abstract ReadOnlyStringMap getContextData(); - - public abstract ThreadContext.ContextStack getContextStack(); - - public abstract String getLoggerFqcn(); - - public abstract Level getLevel(); - - public abstract String getLoggerName(); - - public abstract Marker getMarker(); - - public abstract Message getMessage(); - - public abstract long getTimeMillis(); - - public abstract Instant getInstant(); - - public abstract StackTraceElement getSource(); - - public abstract String getThreadName(); - - public abstract long getThreadId(); - - public abstract int getThreadPriority(); - - public abstract Throwable getThrown(); - - public abstract ThrowableProxy getThrownProxy(); - - public abstract boolean isEndOfBatch(); - - public abstract boolean isIncludeLocation(); - - public abstract void setEndOfBatch(boolean endOfBatch); - - public abstract void setIncludeLocation(boolean locationRequired); - - public abstract long getNanoTime(); -} diff --git a/instrumentation/apache-log4j-2/src/main/java/org/apache/logging/log4j/core/layout/AbstractJacksonLayout_Instrumentation.java b/instrumentation/apache-log4j-2/src/main/java/org/apache/logging/log4j/core/layout/AbstractJacksonLayout_Instrumentation.java deleted file mode 100644 index d24a77cb4a..0000000000 --- a/instrumentation/apache-log4j-2/src/main/java/org/apache/logging/log4j/core/layout/AbstractJacksonLayout_Instrumentation.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * - * * Copyright 2023 New Relic Corporation. All rights reserved. - * * SPDX-License-Identifier: Apache-2.0 - * - */ - -package org.apache.logging.log4j.core.layout; - -import com.newrelic.api.agent.weaver.MatchType; -import com.newrelic.api.agent.weaver.Weave; -import com.newrelic.api.agent.weaver.Weaver; -import org.apache.logging.log4j.core.LogEvent_Instrumentation; -import org.apache.logging.log4j.core.util.StringBuilderWriter; - -import java.io.IOException; -import java.io.Writer; - -import static com.newrelic.agent.bridge.logging.AppLoggingUtils.BLOB_PREFIX; -import static com.newrelic.agent.bridge.logging.AppLoggingUtils.getLinkingMetadataBlob; -import static com.newrelic.agent.bridge.logging.AppLoggingUtils.getLinkingMetadataBlobFromMap; -import static com.newrelic.agent.bridge.logging.AppLoggingUtils.isApplicationLoggingEnabled; -import static com.newrelic.agent.bridge.logging.AppLoggingUtils.isApplicationLoggingLocalDecoratingEnabled; -import static com.nr.agent.instrumentation.log4j2.AgentUtil.foundIndexToInsertLinkingMetadata; -import static com.nr.agent.instrumentation.log4j2.AgentUtil.getIndexToModifyJson; - -@Weave(originalName = "org.apache.logging.log4j.core.layout.AbstractJacksonLayout", type = MatchType.ExactClass) -abstract class AbstractJacksonLayout_Instrumentation { - - public abstract void toSerializable(final LogEvent_Instrumentation event, final Writer writer) throws IOException; - - public String toSerializable(final LogEvent_Instrumentation event) { - final StringBuilderWriter writer = new StringBuilderWriter(); - try { - toSerializable(event, writer); - String writerString = writer.toString(); - String modified = writerString; - - // Append linking metadata to the log message if local decorating is enabled - if (isApplicationLoggingEnabled() && isApplicationLoggingLocalDecoratingEnabled()) { - // It is possible that the log might already have NR-LINKING metadata from JUL instrumentation - if (!writerString.contains(BLOB_PREFIX)) { - int indexToModifyJson = getIndexToModifyJson(writerString); - if (foundIndexToInsertLinkingMetadata(indexToModifyJson)) { - // Replace the JSON string with modified version that includes NR-LINKING metadata - if (event != null && event.agentLinkingMetadata != null && (!event.agentLinkingMetadata.isEmpty())) { - // Get linking metadata stored on LogEvent if available. This ensures that - // the trace.id and span.id will be available when using an async appender. - modified = new StringBuilder(writerString).insert(indexToModifyJson, getLinkingMetadataBlobFromMap(event.agentLinkingMetadata)) - .toString(); - } else { - // Get linking metadata from current thread if it is not available on LogEvent. - modified = new StringBuilder(writerString).insert(indexToModifyJson, getLinkingMetadataBlob()).toString(); - } - } - } - return modified; - } - - return writerString; - } catch (final IOException e) { - return Weaver.callOriginal(); - } - } - -} diff --git a/instrumentation/apache-log4j-2/src/main/java/org/apache/logging/log4j/core/layout/StringBuilderEncoder_Instrumentation.java b/instrumentation/apache-log4j-2/src/main/java/org/apache/logging/log4j/core/layout/StringBuilderEncoder_Instrumentation.java index ef3469d0d7..e09c3e19a5 100644 --- a/instrumentation/apache-log4j-2/src/main/java/org/apache/logging/log4j/core/layout/StringBuilderEncoder_Instrumentation.java +++ b/instrumentation/apache-log4j-2/src/main/java/org/apache/logging/log4j/core/layout/StringBuilderEncoder_Instrumentation.java @@ -11,7 +11,6 @@ import com.newrelic.api.agent.weaver.Weave; import com.newrelic.api.agent.weaver.Weaver; -import static com.newrelic.agent.bridge.logging.AppLoggingUtils.BLOB_PREFIX; import static com.newrelic.agent.bridge.logging.AppLoggingUtils.getLinkingMetadataBlob; import static com.newrelic.agent.bridge.logging.AppLoggingUtils.isApplicationLoggingEnabled; import static com.newrelic.agent.bridge.logging.AppLoggingUtils.isApplicationLoggingLocalDecoratingEnabled; @@ -31,15 +30,11 @@ public void encode(final StringBuilder source, final ByteBufferDestination desti } private void appendAgentMetadata(StringBuilder source) { - String sourceString = source.toString(); - // It is possible that the log might already have NR-LINKING metadata from JUL instrumentation - if (!sourceString.contains(BLOB_PREFIX)) { - int breakLine = sourceString.lastIndexOf("\n"); - if (breakLine != -1) { - source.replace(breakLine, breakLine + 1, ""); - } - source.append(getLinkingMetadataBlob()).append("\n"); + int breakLine = source.toString().lastIndexOf("\n"); + if (breakLine != -1) { + source.replace(breakLine, breakLine + 1, ""); } + source.append(getLinkingMetadataBlob()).append("\n"); } -} +} \ No newline at end of file