From 442a9e0367a833a0b3849b354661b6e67dd6abef Mon Sep 17 00:00:00 2001 From: oliver zhang Date: Mon, 23 Sep 2024 15:51:48 +0800 Subject: [PATCH 01/16] Create sync.yml --- .github/workflows/sync.yml | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 .github/workflows/sync.yml diff --git a/.github/workflows/sync.yml b/.github/workflows/sync.yml new file mode 100644 index 000000000000..c16605ebb215 --- /dev/null +++ b/.github/workflows/sync.yml @@ -0,0 +1,34 @@ +name: Upstream Sync + +permissions: + contents: write + +on: + schedule: + - cron: "0 0 * * *" + workflow_dispatch: + +jobs: + sync_with_upstream: + name: Sync with Upstream + runs-on: ubuntu-latest + if: ${{ github.event.repository.fork }} + + steps: + - name: Checkout target repo + uses: actions/checkout@v3 + + - name: Sync Upstream + uses: aormsby/Fork-Sync-With-Upstream-action@v3.4 + with: + target_repo_token: ${{ secrets.GITHUB_TOKEN }} + upstream_sync_repo: open-telemetry/opentelemetry-java-instrumentation + upstream_sync_branch: main + target_sync_branch: main + test_mode: false + + - name: Check for Failure + if: failure() + run: | + echo "[Error] Due to a change in the workflow file of the upstream repository, GitHub has automatically suspended the scheduled automatic update. You need to manually sync your fork." + exit 1 From 9dc2d2f7420bd1feab82c864b3763013f33715ef Mon Sep 17 00:00:00 2001 From: oliver zhang Date: Mon, 23 Sep 2024 16:16:30 +0800 Subject: [PATCH 02/16] Delete .github/workflows/sync.yml --- .github/workflows/sync.yml | 34 ---------------------------------- 1 file changed, 34 deletions(-) delete mode 100644 .github/workflows/sync.yml diff --git a/.github/workflows/sync.yml b/.github/workflows/sync.yml deleted file mode 100644 index c16605ebb215..000000000000 --- a/.github/workflows/sync.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: Upstream Sync - -permissions: - contents: write - -on: - schedule: - - cron: "0 0 * * *" - workflow_dispatch: - -jobs: - sync_with_upstream: - name: Sync with Upstream - runs-on: ubuntu-latest - if: ${{ github.event.repository.fork }} - - steps: - - name: Checkout target repo - uses: actions/checkout@v3 - - - name: Sync Upstream - uses: aormsby/Fork-Sync-With-Upstream-action@v3.4 - with: - target_repo_token: ${{ secrets.GITHUB_TOKEN }} - upstream_sync_repo: open-telemetry/opentelemetry-java-instrumentation - upstream_sync_branch: main - target_sync_branch: main - test_mode: false - - - name: Check for Failure - if: failure() - run: | - echo "[Error] Due to a change in the workflow file of the upstream repository, GitHub has automatically suspended the scheduled automatic update. You need to manually sync your fork." - exit 1 From 1f7de02822ae32b5b97b69d7bedf36cdee6bc472 Mon Sep 17 00:00:00 2001 From: oliver zhang Date: Tue, 24 Sep 2024 11:20:13 +0800 Subject: [PATCH 03/16] Create sync.yml --- .github/workflows/sync.yml | 58 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 .github/workflows/sync.yml diff --git a/.github/workflows/sync.yml b/.github/workflows/sync.yml new file mode 100644 index 000000000000..34644c4dc18f --- /dev/null +++ b/.github/workflows/sync.yml @@ -0,0 +1,58 @@ +name: 'Upstream Sync' + +on: + schedule: + - cron: '0 7 * * 1,4' + # scheduled at 07:00 every Monday and Thursday + + workflow_dispatch: # click the button on Github repo! + inputs: + sync_test_mode: # Adds a boolean option that appears during manual workflow run for easy test mode config + description: 'Fork Sync Test Mode' + type: boolean + default: false + +jobs: + sync_latest_from_upstream: + runs-on: ubuntu-latest + name: Sync latest commits from upstream repo + + steps: + # REQUIRED step + # Step 1: run a standard checkout action, provided by github + - name: Checkout target repo + uses: actions/checkout@v3 + with: + # optional: set the branch to checkout, + # sync action checks out your 'target_sync_branch' anyway + ref: main + # REQUIRED if your upstream repo is private (see wiki) + persist-credentials: false + + # REQUIRED step + # Step 2: run the sync action + - name: Sync upstream changes + id: sync + uses: aormsby/Fork-Sync-With-Upstream-action@v3.4.1 + with: + target_sync_branch: main + # REQUIRED 'target_repo_token' exactly like this! + target_repo_token: ${{ secrets.GITHUB_TOKEN }} + upstream_sync_branch: main + upstream_sync_repo: open-telemetry/opentelemetry-java-instrumentation + upstream_repo_access_token: ${{ secrets.UPSTREAM_REPO_SECRET }} + + # Set test_mode true during manual dispatch to run tests instead of the true action!! + test_mode: false + + # Step 3: Display a sample message based on the sync output var 'has_new_commits' + - name: New commits found + if: steps.sync.outputs.has_new_commits == 'true' + run: echo "New commits were found to sync." + + - name: No new commits + if: steps.sync.outputs.has_new_commits == 'false' + run: echo "There were no new commits." + + - name: Show value of 'has_new_commits' + run: echo ${{ steps.sync.outputs.has_new_commits }} From 8c704f81c06642a278bb3705b38a2aad73696d9f Mon Sep 17 00:00:00 2001 From: oliver zhang Date: Tue, 24 Sep 2024 16:06:24 +0800 Subject: [PATCH 04/16] Update sync.yml --- .github/workflows/sync.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/sync.yml b/.github/workflows/sync.yml index 34644c4dc18f..f7e20099341b 100644 --- a/.github/workflows/sync.yml +++ b/.github/workflows/sync.yml @@ -37,7 +37,7 @@ jobs: with: target_sync_branch: main # REQUIRED 'target_repo_token' exactly like this! - target_repo_token: ${{ secrets.GITHUB_TOKEN }} + target_repo_token: ${{ secrets.MY_SECRET }} upstream_sync_branch: main upstream_sync_repo: open-telemetry/opentelemetry-java-instrumentation upstream_repo_access_token: ${{ secrets.UPSTREAM_REPO_SECRET }} From 356f36bd07c6c35a958b4ce0e272d836c791b5f2 Mon Sep 17 00:00:00 2001 From: oliver zhang Date: Tue, 24 Sep 2024 18:07:36 +0800 Subject: [PATCH 05/16] Update sync.yml --- .github/workflows/sync.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/sync.yml b/.github/workflows/sync.yml index f7e20099341b..40b4b05a69c6 100644 --- a/.github/workflows/sync.yml +++ b/.github/workflows/sync.yml @@ -36,6 +36,8 @@ jobs: uses: aormsby/Fork-Sync-With-Upstream-action@v3.4.1 with: target_sync_branch: main + git_config_user: oliver zhang + git_config_email: oliver_zhangjian@163.com # REQUIRED 'target_repo_token' exactly like this! target_repo_token: ${{ secrets.MY_SECRET }} upstream_sync_branch: main From e56fd190b39e97e319bd348f72e81ed2488dc6da Mon Sep 17 00:00:00 2001 From: oliver Date: Thu, 29 May 2025 15:05:50 +0800 Subject: [PATCH 06/16] capture code attributes --- .../v1_2/Log4jAppenderInstrumentation.java | 3 +- .../log4j/appender/v1_2/LogEventMapper.java | 28 ++++++++++++++++++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/Log4jAppenderInstrumentation.java b/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/Log4jAppenderInstrumentation.java index 1ec27c84bff7..009d07bf983f 100644 --- a/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/Log4jAppenderInstrumentation.java +++ b/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/Log4jAppenderInstrumentation.java @@ -48,6 +48,7 @@ public static class ForcedLogAdvice { @Advice.OnMethodEnter(suppress = Throwable.class) public static void methodEnter( @Advice.This Category logger, + @Advice.Argument(0) String fqcn, @Advice.Argument(1) Priority level, @Advice.Argument(2) Object message, @Advice.Argument(3) Throwable t, @@ -56,7 +57,7 @@ public static void methodEnter( // framework delegates to another callDepth = CallDepth.forClass(LoggerProvider.class); if (callDepth.getAndIncrement() == 0) { - LogEventMapper.INSTANCE.capture(logger, level, message, t); + LogEventMapper.INSTANCE.capture(fqcn, logger, level, message, t); } } diff --git a/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/LogEventMapper.java b/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/LogEventMapper.java index 522ef4ad9fb2..1632dfa58829 100644 --- a/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/LogEventMapper.java +++ b/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/LogEventMapper.java @@ -28,6 +28,7 @@ import org.apache.log4j.Category; import org.apache.log4j.MDC; import org.apache.log4j.Priority; +import org.apache.log4j.spi.LocationInfo; public final class LogEventMapper { @@ -35,6 +36,11 @@ public final class LogEventMapper { public static final LogEventMapper INSTANCE = new LogEventMapper(); + private static final AttributeKey CODE_FILEPATH = AttributeKey.stringKey("code.filepath"); + private static final AttributeKey CODE_FUNCTION = AttributeKey.stringKey("code.function"); + private static final AttributeKey CODE_LINENO = AttributeKey.stringKey("code.lineno"); + private static final AttributeKey CODE_NAMESPACE = + AttributeKey.stringKey("code.namespace"); // copied from org.apache.log4j.Level because it was only introduced in 1.2.12 private static final int TRACE_INT = 5000; @@ -60,7 +66,13 @@ private LogEventMapper() { captureMdcAttributes.size() == 1 && captureMdcAttributes.get(0).equals("*"); } - public void capture(Category logger, Priority level, Object message, Throwable throwable) { + boolean captureCodeAttributes = + AgentInstrumentationConfig.get() + .getBoolean( + "otel.instrumentation.log4j-appender.experimental.capture-code-attributes", false); + + public void capture( + String fqcn, Category logger, Priority level, Object message, Throwable throwable) { String instrumentationName = logger.getName(); if (instrumentationName == null || instrumentationName.isEmpty()) { instrumentationName = "ROOT"; @@ -104,6 +116,20 @@ public void capture(Category logger, Priority level, Object message, Throwable t attributes.put(ThreadIncubatingAttributes.THREAD_ID, currentThread.getId()); } + if (captureCodeAttributes) { + LocationInfo locationInfo = new LocationInfo(new Throwable(), fqcn); + String fileName = locationInfo.getFileName(); + if (fileName != null) { + attributes.put(CODE_FILEPATH, fileName); + } + attributes.put(CODE_NAMESPACE, locationInfo.getClassName()); + attributes.put(CODE_FUNCTION, locationInfo.getMethodName()); + String lineNumber = locationInfo.getLineNumber(); + if (lineNumber != null) { + attributes.put(CODE_LINENO, lineNumber); + } + } + builder.setAllAttributes(attributes.build()); // span context From 41f3d84662967086cfcaf615341ba2492d8cc760 Mon Sep 17 00:00:00 2001 From: oliver Date: Thu, 29 May 2025 15:12:50 +0800 Subject: [PATCH 07/16] delete sync.yml --- .github/workflows/sync.yml | 60 -------------------------------------- 1 file changed, 60 deletions(-) delete mode 100644 .github/workflows/sync.yml diff --git a/.github/workflows/sync.yml b/.github/workflows/sync.yml deleted file mode 100644 index 40b4b05a69c6..000000000000 --- a/.github/workflows/sync.yml +++ /dev/null @@ -1,60 +0,0 @@ -name: 'Upstream Sync' - -on: - schedule: - - cron: '0 7 * * 1,4' - # scheduled at 07:00 every Monday and Thursday - - workflow_dispatch: # click the button on Github repo! - inputs: - sync_test_mode: # Adds a boolean option that appears during manual workflow run for easy test mode config - description: 'Fork Sync Test Mode' - type: boolean - default: false - -jobs: - sync_latest_from_upstream: - runs-on: ubuntu-latest - name: Sync latest commits from upstream repo - - steps: - # REQUIRED step - # Step 1: run a standard checkout action, provided by github - - name: Checkout target repo - uses: actions/checkout@v3 - with: - # optional: set the branch to checkout, - # sync action checks out your 'target_sync_branch' anyway - ref: main - # REQUIRED if your upstream repo is private (see wiki) - persist-credentials: false - - # REQUIRED step - # Step 2: run the sync action - - name: Sync upstream changes - id: sync - uses: aormsby/Fork-Sync-With-Upstream-action@v3.4.1 - with: - target_sync_branch: main - git_config_user: oliver zhang - git_config_email: oliver_zhangjian@163.com - # REQUIRED 'target_repo_token' exactly like this! - target_repo_token: ${{ secrets.MY_SECRET }} - upstream_sync_branch: main - upstream_sync_repo: open-telemetry/opentelemetry-java-instrumentation - upstream_repo_access_token: ${{ secrets.UPSTREAM_REPO_SECRET }} - - # Set test_mode true during manual dispatch to run tests instead of the true action!! - test_mode: false - - # Step 3: Display a sample message based on the sync output var 'has_new_commits' - - name: New commits found - if: steps.sync.outputs.has_new_commits == 'true' - run: echo "New commits were found to sync." - - - name: No new commits - if: steps.sync.outputs.has_new_commits == 'false' - run: echo "There were no new commits." - - - name: Show value of 'has_new_commits' - run: echo ${{ steps.sync.outputs.has_new_commits }} From 1b9194fc6df965fd94aa12088f7614949dad7c4e Mon Sep 17 00:00:00 2001 From: oliver zhang Date: Fri, 30 May 2025 11:28:01 +0800 Subject: [PATCH 08/16] add unit test --- .../javaagent/build.gradle.kts | 1 + .../log4j/appender/v1_2/LogEventMapper.java | 12 ++++++-- .../log4j/appender/v1_2/Log4j1Test.java | 28 ++++++++++++++++++- 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/instrumentation/log4j/log4j-appender-1.2/javaagent/build.gradle.kts b/instrumentation/log4j/log4j-appender-1.2/javaagent/build.gradle.kts index bc336ded66ca..f31453561e78 100644 --- a/instrumentation/log4j/log4j-appender-1.2/javaagent/build.gradle.kts +++ b/instrumentation/log4j/log4j-appender-1.2/javaagent/build.gradle.kts @@ -34,6 +34,7 @@ configurations { tasks.withType().configureEach { // TODO run tests both with and without experimental log attributes jvmArgs("-Dotel.instrumentation.log4j-appender.experimental.capture-mdc-attributes=*") + jvmArgs("-Dotel.instrumentation.log4j-appender.experimental.capture-code-attributes=true") jvmArgs("-Dotel.instrumentation.log4j-appender.experimental-log-attributes=true") jvmArgs("-Dotel.instrumentation.log4j-appender.experimental-log-attributes=true") jvmArgs("-Dotel.instrumentation.common.experimental.controller-telemetry.enabled=true") diff --git a/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/LogEventMapper.java b/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/LogEventMapper.java index 1632dfa58829..b514730540c6 100644 --- a/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/LogEventMapper.java +++ b/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/LogEventMapper.java @@ -38,7 +38,7 @@ public final class LogEventMapper { private static final AttributeKey CODE_FILEPATH = AttributeKey.stringKey("code.filepath"); private static final AttributeKey CODE_FUNCTION = AttributeKey.stringKey("code.function"); - private static final AttributeKey CODE_LINENO = AttributeKey.stringKey("code.lineno"); + private static final AttributeKey CODE_LINENO = AttributeKey.longKey("code.lineno"); private static final AttributeKey CODE_NAMESPACE = AttributeKey.stringKey("code.namespace"); // copied from org.apache.log4j.Level because it was only introduced in 1.2.12 @@ -125,9 +125,15 @@ public void capture( attributes.put(CODE_NAMESPACE, locationInfo.getClassName()); attributes.put(CODE_FUNCTION, locationInfo.getMethodName()); String lineNumber = locationInfo.getLineNumber(); - if (lineNumber != null) { - attributes.put(CODE_LINENO, lineNumber); + int codeLineNo = 0; + if (!lineNumber.equals("?")) { + try { + codeLineNo = Integer.parseInt(lineNumber); + }catch (NumberFormatException e) { + // ignore + } } + attributes.put(CODE_LINENO, codeLineNo); } builder.setAllAttributes(attributes.build()); diff --git a/instrumentation/log4j/log4j-appender-1.2/javaagent/src/test/java/io/opentelemetry/instrumentation/log4j/appender/v1_2/Log4j1Test.java b/instrumentation/log4j/log4j-appender-1.2/javaagent/src/test/java/io/opentelemetry/instrumentation/log4j/appender/v1_2/Log4j1Test.java index 669dbb5053a5..4f50f0d2b036 100644 --- a/instrumentation/log4j/log4j-appender-1.2/javaagent/src/test/java/io/opentelemetry/instrumentation/log4j/appender/v1_2/Log4j1Test.java +++ b/instrumentation/log4j/log4j-appender-1.2/javaagent/src/test/java/io/opentelemetry/instrumentation/log4j/appender/v1_2/Log4j1Test.java @@ -11,6 +11,12 @@ import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_MESSAGE; import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_STACKTRACE; import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_TYPE; +import static io.opentelemetry.semconv.incubating.CodeIncubatingAttributes.CODE_FILEPATH; +import static io.opentelemetry.semconv.incubating.CodeIncubatingAttributes.CODE_FUNCTION; +import static io.opentelemetry.semconv.incubating.CodeIncubatingAttributes.CODE_LINENO; +import static io.opentelemetry.semconv.incubating.CodeIncubatingAttributes.CODE_NAMESPACE; +import static io.opentelemetry.semconv.incubating.ThreadIncubatingAttributes.THREAD_ID; +import static io.opentelemetry.semconv.incubating.ThreadIncubatingAttributes.THREAD_NAME; import static java.util.concurrent.TimeUnit.MILLISECONDS; import io.opentelemetry.api.common.AttributeKey; @@ -31,6 +37,7 @@ import org.apache.log4j.Logger; import org.apache.log4j.MDC; import org.apache.log4j.helpers.Loader; +import org.assertj.core.api.AbstractLongAssert; import org.assertj.core.api.AssertAccess; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -38,6 +45,7 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +@SuppressWarnings("deprecation") // using deprecated semconv class Log4j1Test { static { @@ -67,6 +75,25 @@ private static Stream provideParameters() { Arguments.of(true, true)); } + @Test + public void testCodeAttributes() { + logger.info("this is test message"); + testing.waitAndAssertLogRecords( + logRecord -> + logRecord + .hasBody("this is test message") + .hasInstrumentationScope(InstrumentationScopeInfo.builder("abc").build()) + .hasSeverity(Severity.INFO) + .hasSeverityText("INFO") + .hasAttributesSatisfyingExactly( + equalTo(THREAD_NAME, Thread.currentThread().getName()), + equalTo(THREAD_ID, Thread.currentThread().getId()), + equalTo(CODE_NAMESPACE, Log4j1Test.class.getName()), + equalTo(CODE_FUNCTION, "testCodeAttributes"), + satisfies(CODE_LINENO, AbstractLongAssert::isPositive), + equalTo(CODE_FILEPATH, "Log4j1Test.java"))); + } + @ParameterizedTest @MethodSource("provideParameters") public void test(boolean logException, boolean withParent) throws InterruptedException { @@ -79,7 +106,6 @@ public void test(boolean logException, boolean withParent) throws InterruptedExc test(Logger::error, Logger::error, logException, withParent, "abc", Severity.ERROR, "ERROR"); testing.clearData(); } - private static void test( LoggerMethod loggerMethod, ExceptionLoggerMethod exceptionLoggerMethod, From 857cc029f6df4307e13761b0359303c0cd65eb74 Mon Sep 17 00:00:00 2001 From: oliver zhang Date: Fri, 30 May 2025 11:29:28 +0800 Subject: [PATCH 09/16] add unit test --- .../instrumentation/log4j/appender/v1_2/LogEventMapper.java | 2 +- .../instrumentation/log4j/appender/v1_2/Log4j1Test.java | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/LogEventMapper.java b/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/LogEventMapper.java index b514730540c6..84dcdd581845 100644 --- a/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/LogEventMapper.java +++ b/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/LogEventMapper.java @@ -129,7 +129,7 @@ public void capture( if (!lineNumber.equals("?")) { try { codeLineNo = Integer.parseInt(lineNumber); - }catch (NumberFormatException e) { + } catch (NumberFormatException e) { // ignore } } diff --git a/instrumentation/log4j/log4j-appender-1.2/javaagent/src/test/java/io/opentelemetry/instrumentation/log4j/appender/v1_2/Log4j1Test.java b/instrumentation/log4j/log4j-appender-1.2/javaagent/src/test/java/io/opentelemetry/instrumentation/log4j/appender/v1_2/Log4j1Test.java index 4f50f0d2b036..c40111fcd746 100644 --- a/instrumentation/log4j/log4j-appender-1.2/javaagent/src/test/java/io/opentelemetry/instrumentation/log4j/appender/v1_2/Log4j1Test.java +++ b/instrumentation/log4j/log4j-appender-1.2/javaagent/src/test/java/io/opentelemetry/instrumentation/log4j/appender/v1_2/Log4j1Test.java @@ -106,6 +106,7 @@ public void test(boolean logException, boolean withParent) throws InterruptedExc test(Logger::error, Logger::error, logException, withParent, "abc", Severity.ERROR, "ERROR"); testing.clearData(); } + private static void test( LoggerMethod loggerMethod, ExceptionLoggerMethod exceptionLoggerMethod, From fdc97a747e81672ec043f2224914e11a889be27a Mon Sep 17 00:00:00 2001 From: oliver Date: Thu, 29 May 2025 15:05:50 +0800 Subject: [PATCH 10/16] capture code attributes --- .../v1_2/Log4jAppenderInstrumentation.java | 3 +- .../log4j/appender/v1_2/LogEventMapper.java | 28 ++++++++++++++++++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/Log4jAppenderInstrumentation.java b/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/Log4jAppenderInstrumentation.java index 1ec27c84bff7..009d07bf983f 100644 --- a/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/Log4jAppenderInstrumentation.java +++ b/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/Log4jAppenderInstrumentation.java @@ -48,6 +48,7 @@ public static class ForcedLogAdvice { @Advice.OnMethodEnter(suppress = Throwable.class) public static void methodEnter( @Advice.This Category logger, + @Advice.Argument(0) String fqcn, @Advice.Argument(1) Priority level, @Advice.Argument(2) Object message, @Advice.Argument(3) Throwable t, @@ -56,7 +57,7 @@ public static void methodEnter( // framework delegates to another callDepth = CallDepth.forClass(LoggerProvider.class); if (callDepth.getAndIncrement() == 0) { - LogEventMapper.INSTANCE.capture(logger, level, message, t); + LogEventMapper.INSTANCE.capture(fqcn, logger, level, message, t); } } diff --git a/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/LogEventMapper.java b/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/LogEventMapper.java index 522ef4ad9fb2..1632dfa58829 100644 --- a/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/LogEventMapper.java +++ b/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/LogEventMapper.java @@ -28,6 +28,7 @@ import org.apache.log4j.Category; import org.apache.log4j.MDC; import org.apache.log4j.Priority; +import org.apache.log4j.spi.LocationInfo; public final class LogEventMapper { @@ -35,6 +36,11 @@ public final class LogEventMapper { public static final LogEventMapper INSTANCE = new LogEventMapper(); + private static final AttributeKey CODE_FILEPATH = AttributeKey.stringKey("code.filepath"); + private static final AttributeKey CODE_FUNCTION = AttributeKey.stringKey("code.function"); + private static final AttributeKey CODE_LINENO = AttributeKey.stringKey("code.lineno"); + private static final AttributeKey CODE_NAMESPACE = + AttributeKey.stringKey("code.namespace"); // copied from org.apache.log4j.Level because it was only introduced in 1.2.12 private static final int TRACE_INT = 5000; @@ -60,7 +66,13 @@ private LogEventMapper() { captureMdcAttributes.size() == 1 && captureMdcAttributes.get(0).equals("*"); } - public void capture(Category logger, Priority level, Object message, Throwable throwable) { + boolean captureCodeAttributes = + AgentInstrumentationConfig.get() + .getBoolean( + "otel.instrumentation.log4j-appender.experimental.capture-code-attributes", false); + + public void capture( + String fqcn, Category logger, Priority level, Object message, Throwable throwable) { String instrumentationName = logger.getName(); if (instrumentationName == null || instrumentationName.isEmpty()) { instrumentationName = "ROOT"; @@ -104,6 +116,20 @@ public void capture(Category logger, Priority level, Object message, Throwable t attributes.put(ThreadIncubatingAttributes.THREAD_ID, currentThread.getId()); } + if (captureCodeAttributes) { + LocationInfo locationInfo = new LocationInfo(new Throwable(), fqcn); + String fileName = locationInfo.getFileName(); + if (fileName != null) { + attributes.put(CODE_FILEPATH, fileName); + } + attributes.put(CODE_NAMESPACE, locationInfo.getClassName()); + attributes.put(CODE_FUNCTION, locationInfo.getMethodName()); + String lineNumber = locationInfo.getLineNumber(); + if (lineNumber != null) { + attributes.put(CODE_LINENO, lineNumber); + } + } + builder.setAllAttributes(attributes.build()); // span context From 51494f9ea192ee2de0add9c15574f96dedfb1def Mon Sep 17 00:00:00 2001 From: oliver Date: Thu, 29 May 2025 15:12:50 +0800 Subject: [PATCH 11/16] delete sync.yml --- .github/workflows/sync.yml | 60 -------------------------------------- 1 file changed, 60 deletions(-) delete mode 100644 .github/workflows/sync.yml diff --git a/.github/workflows/sync.yml b/.github/workflows/sync.yml deleted file mode 100644 index 40b4b05a69c6..000000000000 --- a/.github/workflows/sync.yml +++ /dev/null @@ -1,60 +0,0 @@ -name: 'Upstream Sync' - -on: - schedule: - - cron: '0 7 * * 1,4' - # scheduled at 07:00 every Monday and Thursday - - workflow_dispatch: # click the button on Github repo! - inputs: - sync_test_mode: # Adds a boolean option that appears during manual workflow run for easy test mode config - description: 'Fork Sync Test Mode' - type: boolean - default: false - -jobs: - sync_latest_from_upstream: - runs-on: ubuntu-latest - name: Sync latest commits from upstream repo - - steps: - # REQUIRED step - # Step 1: run a standard checkout action, provided by github - - name: Checkout target repo - uses: actions/checkout@v3 - with: - # optional: set the branch to checkout, - # sync action checks out your 'target_sync_branch' anyway - ref: main - # REQUIRED if your upstream repo is private (see wiki) - persist-credentials: false - - # REQUIRED step - # Step 2: run the sync action - - name: Sync upstream changes - id: sync - uses: aormsby/Fork-Sync-With-Upstream-action@v3.4.1 - with: - target_sync_branch: main - git_config_user: oliver zhang - git_config_email: oliver_zhangjian@163.com - # REQUIRED 'target_repo_token' exactly like this! - target_repo_token: ${{ secrets.MY_SECRET }} - upstream_sync_branch: main - upstream_sync_repo: open-telemetry/opentelemetry-java-instrumentation - upstream_repo_access_token: ${{ secrets.UPSTREAM_REPO_SECRET }} - - # Set test_mode true during manual dispatch to run tests instead of the true action!! - test_mode: false - - # Step 3: Display a sample message based on the sync output var 'has_new_commits' - - name: New commits found - if: steps.sync.outputs.has_new_commits == 'true' - run: echo "New commits were found to sync." - - - name: No new commits - if: steps.sync.outputs.has_new_commits == 'false' - run: echo "There were no new commits." - - - name: Show value of 'has_new_commits' - run: echo ${{ steps.sync.outputs.has_new_commits }} From ba2fd50771b8559b9dba7f53afe8ccd530886631 Mon Sep 17 00:00:00 2001 From: oliver zhang Date: Fri, 30 May 2025 11:28:01 +0800 Subject: [PATCH 12/16] add unit test --- .../javaagent/build.gradle.kts | 1 + .../log4j/appender/v1_2/LogEventMapper.java | 12 ++++++-- .../log4j/appender/v1_2/Log4j1Test.java | 28 ++++++++++++++++++- 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/instrumentation/log4j/log4j-appender-1.2/javaagent/build.gradle.kts b/instrumentation/log4j/log4j-appender-1.2/javaagent/build.gradle.kts index bc336ded66ca..f31453561e78 100644 --- a/instrumentation/log4j/log4j-appender-1.2/javaagent/build.gradle.kts +++ b/instrumentation/log4j/log4j-appender-1.2/javaagent/build.gradle.kts @@ -34,6 +34,7 @@ configurations { tasks.withType().configureEach { // TODO run tests both with and without experimental log attributes jvmArgs("-Dotel.instrumentation.log4j-appender.experimental.capture-mdc-attributes=*") + jvmArgs("-Dotel.instrumentation.log4j-appender.experimental.capture-code-attributes=true") jvmArgs("-Dotel.instrumentation.log4j-appender.experimental-log-attributes=true") jvmArgs("-Dotel.instrumentation.log4j-appender.experimental-log-attributes=true") jvmArgs("-Dotel.instrumentation.common.experimental.controller-telemetry.enabled=true") diff --git a/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/LogEventMapper.java b/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/LogEventMapper.java index 1632dfa58829..b514730540c6 100644 --- a/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/LogEventMapper.java +++ b/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/LogEventMapper.java @@ -38,7 +38,7 @@ public final class LogEventMapper { private static final AttributeKey CODE_FILEPATH = AttributeKey.stringKey("code.filepath"); private static final AttributeKey CODE_FUNCTION = AttributeKey.stringKey("code.function"); - private static final AttributeKey CODE_LINENO = AttributeKey.stringKey("code.lineno"); + private static final AttributeKey CODE_LINENO = AttributeKey.longKey("code.lineno"); private static final AttributeKey CODE_NAMESPACE = AttributeKey.stringKey("code.namespace"); // copied from org.apache.log4j.Level because it was only introduced in 1.2.12 @@ -125,9 +125,15 @@ public void capture( attributes.put(CODE_NAMESPACE, locationInfo.getClassName()); attributes.put(CODE_FUNCTION, locationInfo.getMethodName()); String lineNumber = locationInfo.getLineNumber(); - if (lineNumber != null) { - attributes.put(CODE_LINENO, lineNumber); + int codeLineNo = 0; + if (!lineNumber.equals("?")) { + try { + codeLineNo = Integer.parseInt(lineNumber); + }catch (NumberFormatException e) { + // ignore + } } + attributes.put(CODE_LINENO, codeLineNo); } builder.setAllAttributes(attributes.build()); diff --git a/instrumentation/log4j/log4j-appender-1.2/javaagent/src/test/java/io/opentelemetry/instrumentation/log4j/appender/v1_2/Log4j1Test.java b/instrumentation/log4j/log4j-appender-1.2/javaagent/src/test/java/io/opentelemetry/instrumentation/log4j/appender/v1_2/Log4j1Test.java index 669dbb5053a5..4f50f0d2b036 100644 --- a/instrumentation/log4j/log4j-appender-1.2/javaagent/src/test/java/io/opentelemetry/instrumentation/log4j/appender/v1_2/Log4j1Test.java +++ b/instrumentation/log4j/log4j-appender-1.2/javaagent/src/test/java/io/opentelemetry/instrumentation/log4j/appender/v1_2/Log4j1Test.java @@ -11,6 +11,12 @@ import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_MESSAGE; import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_STACKTRACE; import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_TYPE; +import static io.opentelemetry.semconv.incubating.CodeIncubatingAttributes.CODE_FILEPATH; +import static io.opentelemetry.semconv.incubating.CodeIncubatingAttributes.CODE_FUNCTION; +import static io.opentelemetry.semconv.incubating.CodeIncubatingAttributes.CODE_LINENO; +import static io.opentelemetry.semconv.incubating.CodeIncubatingAttributes.CODE_NAMESPACE; +import static io.opentelemetry.semconv.incubating.ThreadIncubatingAttributes.THREAD_ID; +import static io.opentelemetry.semconv.incubating.ThreadIncubatingAttributes.THREAD_NAME; import static java.util.concurrent.TimeUnit.MILLISECONDS; import io.opentelemetry.api.common.AttributeKey; @@ -31,6 +37,7 @@ import org.apache.log4j.Logger; import org.apache.log4j.MDC; import org.apache.log4j.helpers.Loader; +import org.assertj.core.api.AbstractLongAssert; import org.assertj.core.api.AssertAccess; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -38,6 +45,7 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +@SuppressWarnings("deprecation") // using deprecated semconv class Log4j1Test { static { @@ -67,6 +75,25 @@ private static Stream provideParameters() { Arguments.of(true, true)); } + @Test + public void testCodeAttributes() { + logger.info("this is test message"); + testing.waitAndAssertLogRecords( + logRecord -> + logRecord + .hasBody("this is test message") + .hasInstrumentationScope(InstrumentationScopeInfo.builder("abc").build()) + .hasSeverity(Severity.INFO) + .hasSeverityText("INFO") + .hasAttributesSatisfyingExactly( + equalTo(THREAD_NAME, Thread.currentThread().getName()), + equalTo(THREAD_ID, Thread.currentThread().getId()), + equalTo(CODE_NAMESPACE, Log4j1Test.class.getName()), + equalTo(CODE_FUNCTION, "testCodeAttributes"), + satisfies(CODE_LINENO, AbstractLongAssert::isPositive), + equalTo(CODE_FILEPATH, "Log4j1Test.java"))); + } + @ParameterizedTest @MethodSource("provideParameters") public void test(boolean logException, boolean withParent) throws InterruptedException { @@ -79,7 +106,6 @@ public void test(boolean logException, boolean withParent) throws InterruptedExc test(Logger::error, Logger::error, logException, withParent, "abc", Severity.ERROR, "ERROR"); testing.clearData(); } - private static void test( LoggerMethod loggerMethod, ExceptionLoggerMethod exceptionLoggerMethod, From e865995db15ca53189e4af5dac5c4716fea022b1 Mon Sep 17 00:00:00 2001 From: oliver zhang Date: Fri, 30 May 2025 11:29:28 +0800 Subject: [PATCH 13/16] add unit test --- .../instrumentation/log4j/appender/v1_2/LogEventMapper.java | 2 +- .../instrumentation/log4j/appender/v1_2/Log4j1Test.java | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/LogEventMapper.java b/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/LogEventMapper.java index b514730540c6..84dcdd581845 100644 --- a/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/LogEventMapper.java +++ b/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/LogEventMapper.java @@ -129,7 +129,7 @@ public void capture( if (!lineNumber.equals("?")) { try { codeLineNo = Integer.parseInt(lineNumber); - }catch (NumberFormatException e) { + } catch (NumberFormatException e) { // ignore } } diff --git a/instrumentation/log4j/log4j-appender-1.2/javaagent/src/test/java/io/opentelemetry/instrumentation/log4j/appender/v1_2/Log4j1Test.java b/instrumentation/log4j/log4j-appender-1.2/javaagent/src/test/java/io/opentelemetry/instrumentation/log4j/appender/v1_2/Log4j1Test.java index 4f50f0d2b036..c40111fcd746 100644 --- a/instrumentation/log4j/log4j-appender-1.2/javaagent/src/test/java/io/opentelemetry/instrumentation/log4j/appender/v1_2/Log4j1Test.java +++ b/instrumentation/log4j/log4j-appender-1.2/javaagent/src/test/java/io/opentelemetry/instrumentation/log4j/appender/v1_2/Log4j1Test.java @@ -106,6 +106,7 @@ public void test(boolean logException, boolean withParent) throws InterruptedExc test(Logger::error, Logger::error, logException, withParent, "abc", Severity.ERROR, "ERROR"); testing.clearData(); } + private static void test( LoggerMethod loggerMethod, ExceptionLoggerMethod exceptionLoggerMethod, From 7560a5139e0a80cadcd165159daf4cd5bc95b975 Mon Sep 17 00:00:00 2001 From: oliver zhang Date: Thu, 26 Jun 2025 16:11:52 +0800 Subject: [PATCH 14/16] semconv stable code --- .../log4j/appender/v1_2/LogEventMapper.java | 31 ++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/LogEventMapper.java b/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/LogEventMapper.java index 84dcdd581845..ce0558fefd0c 100644 --- a/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/LogEventMapper.java +++ b/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/LogEventMapper.java @@ -14,8 +14,10 @@ import io.opentelemetry.api.logs.LogRecordBuilder; import io.opentelemetry.api.logs.Severity; import io.opentelemetry.context.Context; +import io.opentelemetry.instrumentation.api.internal.SemconvStability; import io.opentelemetry.instrumentation.api.internal.cache.Cache; import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; +import io.opentelemetry.semconv.CodeAttributes; import io.opentelemetry.semconv.ExceptionAttributes; import io.opentelemetry.semconv.incubating.ThreadIncubatingAttributes; import java.io.PrintWriter; @@ -120,10 +122,24 @@ public void capture( LocationInfo locationInfo = new LocationInfo(new Throwable(), fqcn); String fileName = locationInfo.getFileName(); if (fileName != null) { - attributes.put(CODE_FILEPATH, fileName); + if (SemconvStability.isEmitStableCodeSemconv()) { + attributes.put(CodeAttributes.CODE_FILE_PATH, fileName); + } + if (SemconvStability.isEmitOldCodeSemconv()) { + attributes.put(CODE_FILEPATH, fileName); + } + } + + if (SemconvStability.isEmitStableCodeSemconv()) { + attributes.put( + CodeAttributes.CODE_FUNCTION_NAME, + locationInfo.getClassName() + "." + locationInfo.getMethodName()); + } + if (SemconvStability.isEmitOldCodeSemconv()) { + attributes.put(CODE_NAMESPACE, locationInfo.getClassName()); + attributes.put(CODE_FUNCTION, locationInfo.getMethodName()); } - attributes.put(CODE_NAMESPACE, locationInfo.getClassName()); - attributes.put(CODE_FUNCTION, locationInfo.getMethodName()); + String lineNumber = locationInfo.getLineNumber(); int codeLineNo = 0; if (!lineNumber.equals("?")) { @@ -133,7 +149,14 @@ public void capture( // ignore } } - attributes.put(CODE_LINENO, codeLineNo); + if (codeLineNo > 0) { + if (SemconvStability.isEmitStableCodeSemconv()) { + attributes.put(CodeAttributes.CODE_LINE_NUMBER, codeLineNo); + } + if (SemconvStability.isEmitOldCodeSemconv()) { + attributes.put(CODE_LINENO, codeLineNo); + } + } } builder.setAllAttributes(attributes.build()); From e6aa3ef1fc922fbfa1bdf2769c530eb2deecde9d Mon Sep 17 00:00:00 2001 From: oliver zhang Date: Fri, 27 Jun 2025 09:43:00 +0800 Subject: [PATCH 15/16] code review --- .../log4j/appender/v1_2/LogEventMapper.java | 4 ++-- .../log4j/appender/v1_2/Log4j1Test.java | 21 ++++++++----------- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/LogEventMapper.java b/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/LogEventMapper.java index ce0558fefd0c..b2c3b6dea3ad 100644 --- a/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/LogEventMapper.java +++ b/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/LogEventMapper.java @@ -141,7 +141,7 @@ public void capture( } String lineNumber = locationInfo.getLineNumber(); - int codeLineNo = 0; + int codeLineNo = -1; if (!lineNumber.equals("?")) { try { codeLineNo = Integer.parseInt(lineNumber); @@ -149,7 +149,7 @@ public void capture( // ignore } } - if (codeLineNo > 0) { + if (codeLineNo >= 0) { if (SemconvStability.isEmitStableCodeSemconv()) { attributes.put(CodeAttributes.CODE_LINE_NUMBER, codeLineNo); } diff --git a/instrumentation/log4j/log4j-appender-1.2/javaagent/src/test/java/io/opentelemetry/instrumentation/log4j/appender/v1_2/Log4j1Test.java b/instrumentation/log4j/log4j-appender-1.2/javaagent/src/test/java/io/opentelemetry/instrumentation/log4j/appender/v1_2/Log4j1Test.java index c40111fcd746..c0b6d1f8e5f1 100644 --- a/instrumentation/log4j/log4j-appender-1.2/javaagent/src/test/java/io/opentelemetry/instrumentation/log4j/appender/v1_2/Log4j1Test.java +++ b/instrumentation/log4j/log4j-appender-1.2/javaagent/src/test/java/io/opentelemetry/instrumentation/log4j/appender/v1_2/Log4j1Test.java @@ -11,10 +11,6 @@ import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_MESSAGE; import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_STACKTRACE; import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_TYPE; -import static io.opentelemetry.semconv.incubating.CodeIncubatingAttributes.CODE_FILEPATH; -import static io.opentelemetry.semconv.incubating.CodeIncubatingAttributes.CODE_FUNCTION; -import static io.opentelemetry.semconv.incubating.CodeIncubatingAttributes.CODE_LINENO; -import static io.opentelemetry.semconv.incubating.CodeIncubatingAttributes.CODE_NAMESPACE; import static io.opentelemetry.semconv.incubating.ThreadIncubatingAttributes.THREAD_ID; import static io.opentelemetry.semconv.incubating.ThreadIncubatingAttributes.THREAD_NAME; import static java.util.concurrent.TimeUnit.MILLISECONDS; @@ -24,6 +20,7 @@ import io.opentelemetry.api.trace.SpanContext; import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.code.SemconvCodeStabilityUtil; import io.opentelemetry.sdk.common.InstrumentationScopeInfo; import io.opentelemetry.sdk.logs.data.LogRecordData; import io.opentelemetry.sdk.testing.assertj.AttributeAssertion; @@ -37,7 +34,6 @@ import org.apache.log4j.Logger; import org.apache.log4j.MDC; import org.apache.log4j.helpers.Loader; -import org.assertj.core.api.AbstractLongAssert; import org.assertj.core.api.AssertAccess; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -78,6 +74,13 @@ private static Stream provideParameters() { @Test public void testCodeAttributes() { logger.info("this is test message"); + List assertions = + SemconvCodeStabilityUtil.codeFileAndLineAssertions("Log4j1Test.java"); + assertions.addAll( + SemconvCodeStabilityUtil.codeFunctionAssertions(Log4j1Test.class, "testCodeAttributes")); + assertions.add(equalTo(THREAD_NAME, Thread.currentThread().getName())); + assertions.add(equalTo(THREAD_ID, Thread.currentThread().getId())); + testing.waitAndAssertLogRecords( logRecord -> logRecord @@ -85,13 +88,7 @@ public void testCodeAttributes() { .hasInstrumentationScope(InstrumentationScopeInfo.builder("abc").build()) .hasSeverity(Severity.INFO) .hasSeverityText("INFO") - .hasAttributesSatisfyingExactly( - equalTo(THREAD_NAME, Thread.currentThread().getName()), - equalTo(THREAD_ID, Thread.currentThread().getId()), - equalTo(CODE_NAMESPACE, Log4j1Test.class.getName()), - equalTo(CODE_FUNCTION, "testCodeAttributes"), - satisfies(CODE_LINENO, AbstractLongAssert::isPositive), - equalTo(CODE_FILEPATH, "Log4j1Test.java"))); + .hasAttributesSatisfyingExactly(assertions)); } @ParameterizedTest From 2c9c77e7249bc38b179ab0c054a081290761039c Mon Sep 17 00:00:00 2001 From: Sylvain Juge <763082+SylvainJuge@users.noreply.github.com> Date: Mon, 11 Aug 2025 14:08:51 +0200 Subject: [PATCH 16/16] fix tests --- .../log4j/appender/v1_2/Log4j1Test.java | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/instrumentation/log4j/log4j-appender-1.2/javaagent/src/test/java/io/opentelemetry/instrumentation/log4j/appender/v1_2/Log4j1Test.java b/instrumentation/log4j/log4j-appender-1.2/javaagent/src/test/java/io/opentelemetry/instrumentation/log4j/appender/v1_2/Log4j1Test.java index c0b6d1f8e5f1..b43d402e3c24 100644 --- a/instrumentation/log4j/log4j-appender-1.2/javaagent/src/test/java/io/opentelemetry/instrumentation/log4j/appender/v1_2/Log4j1Test.java +++ b/instrumentation/log4j/log4j-appender-1.2/javaagent/src/test/java/io/opentelemetry/instrumentation/log4j/appender/v1_2/Log4j1Test.java @@ -24,7 +24,6 @@ import io.opentelemetry.sdk.common.InstrumentationScopeInfo; import io.opentelemetry.sdk.logs.data.LogRecordData; import io.opentelemetry.sdk.testing.assertj.AttributeAssertion; -import io.opentelemetry.semconv.incubating.ThreadIncubatingAttributes; import java.lang.reflect.Field; import java.time.Instant; import java.util.ArrayList; @@ -41,7 +40,6 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -@SuppressWarnings("deprecation") // using deprecated semconv class Log4j1Test { static { @@ -146,11 +144,8 @@ private static void test( List attributeAsserts = new ArrayList<>( Arrays.asList( - equalTo( - ThreadIncubatingAttributes.THREAD_NAME, - Thread.currentThread().getName()), - equalTo( - ThreadIncubatingAttributes.THREAD_ID, Thread.currentThread().getId()))); + equalTo(THREAD_NAME, Thread.currentThread().getName()), + equalTo(THREAD_ID, Thread.currentThread().getId()))); if (logException) { attributeAsserts.addAll( Arrays.asList( @@ -159,6 +154,11 @@ private static void test( satisfies( EXCEPTION_STACKTRACE, v -> v.contains(Log4j1Test.class.getName())))); } + attributeAsserts.addAll( + SemconvCodeStabilityUtil.codeFunctionAssertions( + Log4j1Test.class, "performLogging")); + attributeAsserts.addAll( + SemconvCodeStabilityUtil.codeFileAndLineAssertions("Log4j1Test.java")); logRecord.hasAttributesSatisfyingExactly(attributeAsserts); LogRecordData logRecordData = AssertAccess.getActual(logRecord); @@ -183,6 +183,14 @@ void testMdc() { MDC.remove("key2"); } + List assertions = + SemconvCodeStabilityUtil.codeFileAndLineAssertions("Log4j1Test.java"); + assertions.addAll(SemconvCodeStabilityUtil.codeFunctionAssertions(Log4j1Test.class, "testMdc")); + assertions.add(equalTo(AttributeKey.stringKey("key1"), "val1")); + assertions.add(equalTo(AttributeKey.stringKey("key2"), "val2")); + assertions.add(equalTo(THREAD_NAME, Thread.currentThread().getName())); + assertions.add(equalTo(THREAD_ID, Thread.currentThread().getId())); + testing.waitAndAssertLogRecords( logRecord -> logRecord @@ -190,12 +198,7 @@ void testMdc() { .hasInstrumentationScope(InstrumentationScopeInfo.builder("abc").build()) .hasSeverity(Severity.INFO) .hasSeverityText("INFO") - .hasAttributesSatisfyingExactly( - equalTo(AttributeKey.stringKey("key1"), "val1"), - equalTo(AttributeKey.stringKey("key2"), "val2"), - equalTo( - ThreadIncubatingAttributes.THREAD_NAME, Thread.currentThread().getName()), - equalTo(ThreadIncubatingAttributes.THREAD_ID, Thread.currentThread().getId()))); + .hasAttributesSatisfyingExactly(assertions)); } private static void performLogging(