diff --git a/.buildkite/README.md b/.buildkite/README.md new file mode 100644 index 0000000000..cac080f834 --- /dev/null +++ b/.buildkite/README.md @@ -0,0 +1,21 @@ +# Buildkite + +This README provides an overview of the Buildkite pipeline used to automate the build and publishing process. + +## Release pipeline + +This is the Buildkite pipeline for releasing the APM Agent Java. + +### Pipeline Configuration + +To view the pipeline and its configuration, click [here](https://buildkite.com/elastic/apm-agent-java-release) or +go to the definition in the `elastic/ci` repository. + +## Snapshot pipeline + +This is the Buildkite pipeline for the APM Agent java in charge of the snaposhots. + +### Pipeline Configuration + +To view the pipeline and its configuration, click [here](https://buildkite.com/elastic/apm-agent-java-snapshot) or +go to the definition in the `elastic/ci` repository. diff --git a/.buildkite/load-testing.yml b/.buildkite/load-testing.yml new file mode 100644 index 0000000000..dc9f232059 --- /dev/null +++ b/.buildkite/load-testing.yml @@ -0,0 +1,4 @@ +# @reakaleek: This is a place holder to create the pipeline in Buildkite. I will work on it, in a follow-up. +steps: + - label: ":wave: Greetings" # Label (with rich emojis https://ela.st/bk-emoji). + command: "echo 'My first pipeline!'" # Command to run (evaluated by Bash). diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 1e4c5b1748..65525c4e40 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -33,8 +33,6 @@ updates: - dependency-name: "com.datastax.oss:java-driver-core" - dependency-name: "io.micrometer:*" - dependency-name: "redis.clients:*" - - dependency-name: "org.elasticsearch.client:*" - - dependency-name: "co.elastic.clients:*" - dependency-name: "io.vertx:*" - dependency-name: "org.apache.logging.log4j:*" - dependency-name: "org.springframework.boot:*" diff --git a/.github/workflows/README.md b/.github/workflows/README.md new file mode 100644 index 0000000000..d2d093d024 --- /dev/null +++ b/.github/workflows/README.md @@ -0,0 +1,50 @@ +## CI/CD + +There are 4 main stages that run on GitHub actions: + +* Build +* Unit Test +* Integration Test +* Release + +There are some other stages that run for every push on the main branches: + +* [Microbenchmark](./microbenchmark.yml) +* [Snapshoty](./snapshoty.yml) +* [Sync-branches](./sync-branches.yml) + +### Scenarios + +* Tests should be triggered on branch, tag and PR basis. +* Commits that are only affecting the docs files should not trigger any test or similar stages that are not required. +* Automated release in the CI gets triggered through a GitHub workflow. +* **This is not the case yet**, but if Github secrets are required then Pull Requests from forked repositories won't run any build accessing those secrets. If needed, then create a feature branch (opened directly on the upstream project). + +### How to interact with the CI? + +#### On a PR basis + +Once a PR has been opened then there are two different ways you can trigger builds in the CI: + +1. Git commit based +1. UI based, any Elasticians can force a build through the GitHub UI + +#### Branches + +Every time there is a merge to main or any branches the whole workflow will compile and test on Linux and Windows. + +### Release process + +This process has been fully automated and it gets triggered manually when running the [release](https://github.com/elastic/apm-agent-java/actions/workflows/release.yml) workflow. It runs then a Buildkite pipeline in charge of generating and publishing the artifacts, +for further details please go to [the buildkite folder](../../.buildkite/README.md). + +The tag release follows the naming convention: `v...`, where ``, `` and ``. + +### OpenTelemetry + +There is a GitHub workflow in charge to populate what the workflow run in terms of jobs and steps. Those details can be seen in [here](https://ela.st/oblt-ci-cd-stats) (**NOTE**: only available for Elasticians). + +## Bump automation + +[updatecli](https://www.updatecli.io/) is the tool we use to automatically update the specs +the [APM agents](./updatecli.yml) use. diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 04410dc9bf..6842516d9f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -176,6 +176,18 @@ jobs: with: name: build path: ${{ github.workspace }} + # As long as there are some space issues with the CI runners. + - name: Free Disk Space + continue-on-error: true + uses: jlumbroso/free-disk-space@f68fdb76e2ea636224182cfb7377ff9a1708f9b8 + with: + android: true + dotnet: true + haskell: true + large-packages: true + docker-images: true + swap-storage: true + tool-cache: false - uses: ./.github/workflows/maven-goal with: command: ./mvnw -q -P ci-non-application-server-integration-tests verify @@ -205,7 +217,8 @@ jobs: path: ${{ github.workspace }} # As long as there are some space issues with the CI runners. - name: Free Disk Space - uses: jlumbroso/free-disk-space@0add001504c51b93b35ac8e81d252bdd47e4ef07 + continue-on-error: true + uses: jlumbroso/free-disk-space@f68fdb76e2ea636224182cfb7377ff9a1708f9b8 with: android: true dotnet: true @@ -283,7 +296,7 @@ jobs: distribution: 'temurin' - version: 20 distribution: 'temurin' - - version: 21-ea + - version: 21 distribution: 'zulu' steps: - uses: actions/checkout@v3 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1ac29a6d1a..34967dc27b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -86,7 +86,7 @@ jobs: maven_central_deploy: name: "Deploy to Maven Central (Buildkite)" - if: ${{ ! inputs.skip_maven_deploy }} + if: ${{ ! inputs.skip_maven_deploy && ( inputs.skip_preparation || success() ) }} runs-on: ubuntu-latest needs: - prepare_release diff --git a/.mergify.yml b/.mergify.yml new file mode 100644 index 0000000000..95facf62c5 --- /dev/null +++ b/.mergify.yml @@ -0,0 +1,14 @@ +queue_rules: + - name: default + # merge method needs to be set to 'squash' to match the repository config + merge_method: squash + # branch protection rules are automatically included, no extra rule needed for now + +pull_request_rules: + - name: Automatic squash and merge on approval with success checks and ready-to-merge label + conditions: + - label=ready-to-merge + - base=main + actions: + queue: + name: default diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index cb9f2eb182..80f5025331 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -33,18 +33,35 @@ Use subheadings with the "=====" level for adding notes for unreleased changes: [float] ===== Bug fixes -* Prevent bad serialization in edge cases for span compression - {pull}3293[#3293] -* Allow overriding of transaction type for Servlet-API transactions - {pull}3226[#3226] -* Fix micrometer histogram serialization - {pull}3290[#3290], {pull}3304[#3304] -* Fix transactions not being correctly handled in certain edge cases - {pull}3294[#3294] +* Fixed too many spans being created for `HTTPUrlConnection` requests with method `HEAD` - {pull}3353[#3353] + +===== Features +* Support for micronaut 4.x + +[[release-notes-1.x]] +=== Java Agent version 1.x + +[[release-notes-1.43.0]] +==== 1.43.0 - 2023/09/26 [float] ===== Features * Add support for Elasticsearch client 8.9 - {pull}3283[#3283] * Added `baggage_to_attach` config option to allow automatic lifting of baggage into transaction, span and error attributes - {pull}3288[#3288], {pull}3289[#3289] +* Exclude elasticsearch 8.10 and newer clients from instrumentation because they natively support OpenTelemetry - {pull}3303[#3303] +* Switched to OpenTelemetry compatible context propagation for Kafka - {pull}3300[#3300] +* Changed `cloud.project.id` collected in Google Cloud (GCP) to be the `project-id` - {issues}3311[#3311] +* Allow running the IntelliJ debug agent in parallel - {pull}3315[#3315] +* Capture `span.sync` = `false` for ES restclient async spans plugins -[[release-notes-1.x]] -=== Java Agent version 1.x +[float] +===== Bug fixes +* Prevent bad serialization in edge cases for span compression - {pull}3293[#3293] +* Allow overriding of transaction type for Servlet-API transactions - {pull}3226[#3226] +* Fix micrometer histogram serialization - {pull}3290[#3290], {pull}3304[#3304] +* Fix transactions not being correctly handled in certain edge cases - {pull}3294[#3294] +* Fixed JDBC instrumentation for DB2 - {pull}3313[#3313] +* Fixed OpenTelemetry metrics export breaking when `instrument=false` is configured - {pull}3326[#3326] [[release-notes-1.42.0]] ==== 1.42.0 - 2023/08/11 diff --git a/apm-agent-api/pom.xml b/apm-agent-api/pom.xml index 539319686f..c8769a1c6b 100644 --- a/apm-agent-api/pom.xml +++ b/apm-agent-api/pom.xml @@ -5,7 +5,7 @@ apm-agent-parent co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-agent-api diff --git a/apm-agent-attach-cli/pom.xml b/apm-agent-attach-cli/pom.xml index 1585b0077c..2e5be17e8f 100644 --- a/apm-agent-attach-cli/pom.xml +++ b/apm-agent-attach-cli/pom.xml @@ -3,7 +3,7 @@ apm-agent-parent co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 @@ -56,6 +56,13 @@ ${version.bouncy-castle.bc-fips} provided + + + net.bytebuddy + byte-buddy-dep + ${version.byte-buddy} + test + diff --git a/apm-agent-attach/pom.xml b/apm-agent-attach/pom.xml index c8adff4c8e..fb5148532e 100644 --- a/apm-agent-attach/pom.xml +++ b/apm-agent-attach/pom.xml @@ -5,7 +5,7 @@ apm-agent-parent co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-agent-attach diff --git a/apm-agent-benchmarks/pom.xml b/apm-agent-benchmarks/pom.xml index 9342eae3e2..98b2703ce4 100644 --- a/apm-agent-benchmarks/pom.xml +++ b/apm-agent-benchmarks/pom.xml @@ -5,7 +5,7 @@ apm-agent-parent co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-agent-benchmarks diff --git a/apm-agent-bootstrap/pom.xml b/apm-agent-bootstrap/pom.xml index 50972790cb..e4b04c1073 100644 --- a/apm-agent-bootstrap/pom.xml +++ b/apm-agent-bootstrap/pom.xml @@ -5,7 +5,7 @@ apm-agent-parent co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-agent-bootstrap diff --git a/apm-agent-builds/apm-agent-java8/pom.xml b/apm-agent-builds/apm-agent-java8/pom.xml index 18c05be3d6..205971dcc1 100644 --- a/apm-agent-builds/apm-agent-java8/pom.xml +++ b/apm-agent-builds/apm-agent-java8/pom.xml @@ -5,7 +5,7 @@ co.elastic.apm apm-agent-builds - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-agent-java8 diff --git a/apm-agent-builds/apm-agent/pom.xml b/apm-agent-builds/apm-agent/pom.xml index 8e4d5ae775..650cfc1bc8 100644 --- a/apm-agent-builds/apm-agent/pom.xml +++ b/apm-agent-builds/apm-agent/pom.xml @@ -5,7 +5,7 @@ co.elastic.apm apm-agent-builds - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-agent diff --git a/apm-agent-builds/pom.xml b/apm-agent-builds/pom.xml index 4475d921f3..06b74c4e4c 100644 --- a/apm-agent-builds/pom.xml +++ b/apm-agent-builds/pom.xml @@ -3,7 +3,7 @@ apm-agent-parent co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 @@ -262,6 +262,11 @@ apm-micrometer-plugin ${project.version} + + ${project.groupId} + apm-micronaut-plugin + ${project.version} + ${project.groupId} apm-mongodb3-plugin diff --git a/apm-agent-cached-lookup-key/pom.xml b/apm-agent-cached-lookup-key/pom.xml index d827f49bfd..97ac7e9b84 100644 --- a/apm-agent-cached-lookup-key/pom.xml +++ b/apm-agent-cached-lookup-key/pom.xml @@ -3,7 +3,7 @@ apm-agent-parent co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/apm-agent-common/pom.xml b/apm-agent-common/pom.xml index 81e5618ea0..000e85e6e0 100644 --- a/apm-agent-common/pom.xml +++ b/apm-agent-common/pom.xml @@ -3,7 +3,7 @@ apm-agent-parent co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/apm-agent-core/pom.xml b/apm-agent-core/pom.xml index 21625b19ef..8126e46ae2 100644 --- a/apm-agent-core/pom.xml +++ b/apm-agent-core/pom.xml @@ -5,7 +5,7 @@ apm-agent-parent co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-agent-core diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/configuration/AutoDetectedServiceInfo.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/configuration/AutoDetectedServiceInfo.java new file mode 100644 index 0000000000..6129715193 --- /dev/null +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/configuration/AutoDetectedServiceInfo.java @@ -0,0 +1,130 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package co.elastic.apm.agent.configuration; + +import co.elastic.apm.agent.sdk.internal.util.PrivilegedActionUtils; +import co.elastic.apm.agent.tracer.service.ServiceInfo; + +import javax.annotation.Nullable; +import java.util.Map; +import java.util.Properties; +import java.util.jar.JarFile; + +public class AutoDetectedServiceInfo { + + private static final String JAR_VERSION_SUFFIX = "-(\\d+\\.)+(\\d+)(.*)?$"; + + private static final ServiceInfo AUTO_DETECTED = AutoDetectedServiceInfo.autoDetect(System.getProperties(), PrivilegedActionUtils.getEnv()); + + private AutoDetectedServiceInfo() { + } + + public static ServiceInfo autoDetected() { + return AUTO_DETECTED; + } + + public static ServiceInfo autoDetect(Properties sysProperties, Map sysEnv) { + String lambdaFunctionName = sysEnv.get("AWS_LAMBDA_FUNCTION_NAME"); + if (lambdaFunctionName != null) { + return ServiceInfo.of(lambdaFunctionName, sysEnv.get("AWS_LAMBDA_FUNCTION_VERSION")); + } else { + ServiceInfo serviceInfo = createFromSunJavaCommand(sysProperties.getProperty("sun.java.command")); + if (serviceInfo != null) { + return serviceInfo; + } + return ServiceInfo.empty(); + } + } + + @Nullable + private static ServiceInfo createFromSunJavaCommand(@Nullable String command) { + if (command == null) { + return null; + } + command = command.trim(); + String serviceName = getContainerServiceName(command); + if (serviceName != null) { + return ServiceInfo.ofMultiServiceContainer(serviceName); + } + if (command.contains(".jar")) { + return fromJarCommand(command); + } else { + return fromMainClassCommand(command); + } + } + + @Nullable + private static String getContainerServiceName(String command) { + if (command.startsWith("org.apache.catalina.startup.Bootstrap")) { + return "tomcat-application"; + } else if (command.startsWith("org.eclipse.jetty")) { + return "jetty-application"; + } else if (command.startsWith("com.sun.enterprise.glassfish")) { + return "glassfish-application"; + } else if (command.contains("ws-server.jar")) { + return "websphere-application"; + } else if (command.contains("jboss-modules.jar")) { + return "jboss-application"; + } else if (command.contains("weblogic")) { + return "weblogic-application"; + } + return null; + } + + private static ServiceInfo fromJarCommand(String command) { + final String[] commandParts = command.split(" "); + ServiceInfo serviceInfoFromManifest = ServiceInfo.empty(); + ServiceInfo serviceInfoFromJarName = ServiceInfo.empty(); + for (String commandPart : commandParts) { + if (commandPart.endsWith(".jar")) { + try (JarFile jarFile = new JarFile(commandPart)) { + serviceInfoFromManifest = ServiceInfo.fromManifest(jarFile.getManifest()); + } catch (Exception ignored) { + } + + serviceInfoFromJarName = ServiceInfo.of(removeVersionFromJar(removePath(removeJarExtension(commandPart)))); + break; + } + } + return serviceInfoFromManifest.withFallback(serviceInfoFromJarName); + } + + private static String removeJarExtension(String commandPart) { + return commandPart.substring(0, commandPart.indexOf(".jar")); + } + + private static String removePath(String path) { + return path.substring(path.lastIndexOf("/") + 1).substring(path.lastIndexOf("\\") + 1); + } + + private static String removeVersionFromJar(String jarFileName) { + return jarFileName.replaceFirst(JAR_VERSION_SUFFIX, ""); + } + + private static ServiceInfo fromMainClassCommand(String command) { + final String mainClassName; + int indexOfSpace = command.indexOf(' '); + if (indexOfSpace != -1) { + mainClassName = command.substring(0, indexOfSpace); + } else { + mainClassName = command; + } + return ServiceInfo.of(mainClassName.substring(mainClassName.lastIndexOf('.') + 1)); + } +} diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/configuration/CoreConfiguration.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/configuration/CoreConfiguration.java index fafde04a92..7200f1ab4f 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/configuration/CoreConfiguration.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/configuration/CoreConfiguration.java @@ -163,7 +163,7 @@ public class CoreConfiguration extends ConfigurationOptionProvider implements co "NOTE: Service name auto discovery mechanisms require APM Server 7.0+.") .addValidator(RegexValidator.of("^[a-zA-Z0-9 _-]+$", "Your service name \"{0}\" must only contain characters " + "from the ASCII alphabet, numbers, dashes, underscores and spaces")) - .buildWithDefault(ServiceInfo.autoDetected().getServiceName()); + .buildWithDefault(AutoDetectedServiceInfo.autoDetected().getServiceName()); private final ConfigurationOption serviceNodeName = ConfigurationOption.stringOption() .key(SERVICE_NODE_NAME) @@ -203,7 +203,7 @@ public class CoreConfiguration extends ConfigurationOptionProvider implements co "the agent can auto-detect the service version based on the `Implementation-Title` attribute in `META-INF/MANIFEST.MF`.\n" + "See <> on how to set this attribute.\n" + "\n") - .defaultValue(ServiceInfo.autoDetected().getServiceVersion()) + .defaultValue(AutoDetectedServiceInfo.autoDetected().getServiceVersion()) .build(); private final ConfigurationOption hostname = ConfigurationOption.stringOption() diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/ElasticApmTracer.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/ElasticApmTracer.java index 254bd3a42d..586511857e 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/ElasticApmTracer.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/ElasticApmTracer.java @@ -22,14 +22,16 @@ import co.elastic.apm.agent.collections.WeakReferenceCountedMap; import co.elastic.apm.agent.common.JvmRuntimeInfo; import co.elastic.apm.agent.common.util.WildcardMatcher; +import co.elastic.apm.agent.configuration.AutoDetectedServiceInfo; import co.elastic.apm.agent.configuration.CoreConfiguration; import co.elastic.apm.agent.configuration.MetricsConfiguration; import co.elastic.apm.agent.configuration.ServerlessConfiguration; -import co.elastic.apm.agent.configuration.ServiceInfo; +import co.elastic.apm.agent.tracer.service.ServiceInfo; import co.elastic.apm.agent.configuration.SpanConfiguration; import co.elastic.apm.agent.context.ClosableLifecycleListenerAdapter; import co.elastic.apm.agent.context.LifecycleListener; import co.elastic.apm.agent.impl.baggage.Baggage; +import co.elastic.apm.agent.impl.baggage.W3CBaggagePropagation; import co.elastic.apm.agent.impl.error.ErrorCapture; import co.elastic.apm.agent.impl.metadata.MetaDataFuture; import co.elastic.apm.agent.impl.sampling.ProbabilitySampler; @@ -55,8 +57,7 @@ import co.elastic.apm.agent.sdk.weakconcurrent.WeakMap; import co.elastic.apm.agent.tracer.GlobalTracer; import co.elastic.apm.agent.tracer.Scope; -import co.elastic.apm.agent.tracer.dispatch.BinaryHeaderGetter; -import co.elastic.apm.agent.tracer.dispatch.TextHeaderGetter; +import co.elastic.apm.agent.tracer.dispatch.HeaderGetter; import co.elastic.apm.agent.tracer.reference.ReferenceCounted; import co.elastic.apm.agent.tracer.reference.ReferenceCountedMap; import co.elastic.apm.agent.util.DependencyInjectingServiceLoader; @@ -69,7 +70,9 @@ import java.io.Closeable; import java.io.File; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -92,6 +95,15 @@ public class ElasticApmTracer implements Tracer { private static final Map, Class> configs = new HashMap<>(); + public static final Set TRACE_HEADER_NAMES; + + static { + Set headerNames = new HashSet<>(); + headerNames.addAll(TraceContext.TRACE_TEXTUAL_HEADERS); + headerNames.add(W3CBaggagePropagation.BAGGAGE_HEADER_NAME); + TRACE_HEADER_NAMES = Collections.unmodifiableSet(headerNames); + } + private static volatile boolean classloaderCheckOk = false; private final ConfigurationRegistry configurationRegistry; @@ -277,49 +289,29 @@ public Transaction startRootTransaction(Sampler sampler, long epochMicros, Bagga @Override @Nullable - public Transaction startChildTransaction(@Nullable C headerCarrier, TextHeaderGetter textHeadersGetter, @Nullable ClassLoader initiatingClassLoader) { - return startChildTransaction(headerCarrier, textHeadersGetter, sampler, -1, initiatingClassLoader); - } - - @Override - @Nullable - public Transaction startChildTransaction(@Nullable C headerCarrier, TextHeaderGetter textHeadersGetter, @Nullable ClassLoader initiatingClassLoader, Baggage baseBaggage, long epochMicros) { - return startChildTransaction(headerCarrier, textHeadersGetter, sampler, epochMicros, initiatingClassLoader); + public Transaction startChildTransaction(@Nullable C headerCarrier, HeaderGetter headersGetter, @Nullable ClassLoader initiatingClassLoader) { + return startChildTransaction(headerCarrier, headersGetter, sampler, -1, initiatingClassLoader); } @Override @Nullable - public Transaction startChildTransaction(@Nullable C headerCarrier, TextHeaderGetter textHeadersGetter, Sampler sampler, - long epochMicros, @Nullable ClassLoader initiatingClassLoader) { - return startChildTransaction(headerCarrier, textHeadersGetter, sampler, epochMicros, currentContext().getBaggage(), initiatingClassLoader); - } - - private Transaction startChildTransaction(@Nullable C headerCarrier, TextHeaderGetter textHeadersGetter, Sampler sampler, - long epochMicros, Baggage baseBaggage, @Nullable ClassLoader initiatingClassLoader) { - Transaction transaction = null; - if (isRunning()) { - transaction = createTransaction().start(TraceContext.getFromTraceContextTextHeaders(), headerCarrier, - textHeadersGetter, epochMicros, sampler, baseBaggage); - afterTransactionStart(initiatingClassLoader, transaction); - } - return transaction; + public Transaction startChildTransaction(@Nullable C headerCarrier, HeaderGetter headersGetter, @Nullable ClassLoader initiatingClassLoader, Baggage baseBaggage, long epochMicros) { + return startChildTransaction(headerCarrier, headersGetter, sampler, epochMicros, initiatingClassLoader); } @Override @Nullable - public Transaction startChildTransaction(@Nullable C headerCarrier, BinaryHeaderGetter binaryHeadersGetter, @Nullable ClassLoader initiatingClassLoader) { - return startChildTransaction(headerCarrier, binaryHeadersGetter, sampler, -1, initiatingClassLoader); + public Transaction startChildTransaction(@Nullable C headerCarrier, HeaderGetter headersGetter, Sampler sampler, + long epochMicros, @Nullable ClassLoader initiatingClassLoader) { + return startChildTransaction(headerCarrier, headersGetter, sampler, epochMicros, currentContext().getBaggage(), initiatingClassLoader); } - @Override - @Nullable - public Transaction startChildTransaction(@Nullable C headerCarrier, BinaryHeaderGetter binaryHeadersGetter, - Sampler sampler, long epochMicros, @Nullable ClassLoader initiatingClassLoader) { + private Transaction startChildTransaction(@Nullable C headerCarrier, HeaderGetter headersGetter, Sampler sampler, + long epochMicros, Baggage baseBaggage, @Nullable ClassLoader initiatingClassLoader) { Transaction transaction = null; if (isRunning()) { - Baggage baseBaggage = currentContext().getBaggage(); - transaction = createTransaction().start(TraceContext.getFromTraceContextBinaryHeaders(), headerCarrier, - binaryHeadersGetter, epochMicros, sampler, baseBaggage); + transaction = createTransaction().start(headerCarrier, + headersGetter, epochMicros, sampler, baseBaggage); afterTransactionStart(initiatingClassLoader, transaction); } return transaction; @@ -358,6 +350,12 @@ public Transaction currentTransaction() { return currentContext().getTransaction(); } + @Nullable + @Override + public ErrorCapture getActiveError() { + return ErrorCapture.getActive(); + } + /** * Starts a span with a given parent context. *

@@ -431,6 +429,12 @@ public ErrorCapture captureException(@Nullable Throwable e, ElasticContext pa return captureException(System.currentTimeMillis() * 1000, e, parentContext, initiatingClassLoader); } + @Nullable + @Override + public ErrorCapture captureException(@Nullable Throwable e, @Nullable ClassLoader initiatingClassLoader) { + return captureException(System.currentTimeMillis() * 1000, e, currentContext(), initiatingClassLoader); + } + @Nullable private ErrorCapture captureException(long epochMicros, @Nullable Throwable e, ElasticContext parentContext, @Nullable ClassLoader initiatingClassLoader) { if (!isRunning() || e == null) { @@ -969,6 +973,11 @@ public T require(Class type) { @Override public Set getTraceHeaderNames() { - return TraceContext.TRACE_TEXTUAL_HEADERS; + return TRACE_HEADER_NAMES; + } + + @Override + public ServiceInfo autoDetectedServiceInfo() { + return AutoDetectedServiceInfo.autoDetected(); } } diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/Tracer.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/Tracer.java index 9b3629b799..f645420cd9 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/Tracer.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/Tracer.java @@ -18,7 +18,7 @@ */ package co.elastic.apm.agent.impl; -import co.elastic.apm.agent.configuration.ServiceInfo; +import co.elastic.apm.agent.tracer.service.ServiceInfo; import co.elastic.apm.agent.impl.baggage.Baggage; import co.elastic.apm.agent.impl.error.ErrorCapture; import co.elastic.apm.agent.impl.sampling.Sampler; @@ -26,13 +26,11 @@ import co.elastic.apm.agent.impl.transaction.ElasticContext; import co.elastic.apm.agent.impl.transaction.Span; import co.elastic.apm.agent.impl.transaction.Transaction; -import co.elastic.apm.agent.tracer.dispatch.BinaryHeaderGetter; import co.elastic.apm.agent.tracer.dispatch.HeaderGetter; -import co.elastic.apm.agent.tracer.dispatch.TextHeaderGetter; import javax.annotation.Nullable; -public interface Tracer extends co.elastic.apm.agent.tracer.Tracer { +public interface Tracer extends co.elastic.apm.agent.tracer.service.ServiceAwareTracer, co.elastic.apm.agent.tracer.Tracer { @Nullable @Override @@ -59,10 +57,10 @@ public interface Tracer extends co.elastic.apm.agent.tracer.Tracer { @Override @Nullable - Transaction startChildTransaction(@Nullable C headerCarrier, TextHeaderGetter textHeadersGetter, @Nullable ClassLoader initiatingClassLoader); + Transaction startChildTransaction(@Nullable C headerCarrier, HeaderGetter headersGetter, @Nullable ClassLoader initiatingClassLoader); @Nullable - Transaction startChildTransaction(@Nullable C headerCarrier, TextHeaderGetter textHeadersGetter, @Nullable ClassLoader initiatingClassLoader, Baggage baseBaggage, long epochMicros); + Transaction startChildTransaction(@Nullable C headerCarrier, HeaderGetter headersGetter, @Nullable ClassLoader initiatingClassLoader, Baggage baseBaggage, long epochMicros); /** * Starts a transaction as a child of the context headers obtained through the provided {@link HeaderGetter}. @@ -70,7 +68,7 @@ public interface Tracer extends co.elastic.apm.agent.tracer.Tracer { * available), then it will be started as the root transaction of the trace. * * @param headerCarrier the Object from which context headers can be obtained, typically a request or a message - * @param textHeadersGetter provides the trace context headers required in order to create a child transaction + * @param headersGetter provides the trace context headers required in order to create a child transaction * @param sampler the {@link Sampler} instance which is responsible for determining the sampling decision if this is a root transaction * @param epochMicros the start timestamp * @param initiatingClassLoader the class loader corresponding to the service which initiated the creation of the transaction. @@ -79,30 +77,9 @@ public interface Tracer extends co.elastic.apm.agent.tracer.Tracer { * @return a transaction which is a child of the provided parent if the agent is currently RUNNING; null otherwise */ @Nullable - Transaction startChildTransaction(@Nullable C headerCarrier, TextHeaderGetter textHeadersGetter, Sampler sampler, - long epochMicros, @Nullable ClassLoader initiatingClassLoader); + Transaction startChildTransaction(@Nullable C headerCarrier, HeaderGetter headersGetter, Sampler sampler, + long epochMicros, @Nullable ClassLoader initiatingClassLoader); - @Override - @Nullable - Transaction startChildTransaction(@Nullable C headerCarrier, BinaryHeaderGetter binaryHeadersGetter, @Nullable ClassLoader initiatingClassLoader); - - /** - * Starts a transaction as a child of the context headers obtained through the provided {@link HeaderGetter}. - * If the created transaction cannot be started as a child transaction (for example - if no parent context header is - * available), then it will be started as the root transaction of the trace. - * - * @param headerCarrier the Object from which context headers can be obtained, typically a request or a message - * @param binaryHeadersGetter provides the trace context headers required in order to create a child transaction - * @param sampler the {@link Sampler} instance which is responsible for determining the sampling decision if this is a root transaction - * @param epochMicros the start timestamp - * @param initiatingClassLoader the class loader corresponding to the service which initiated the creation of the transaction. - * Used to determine the service name and to load application-scoped classes like the {@link org.slf4j.MDC}, - * for log correlation. - * @return a transaction which is a child of the provided parent if the agent is currently RUNNING; null otherwise - */ - @Nullable - Transaction startChildTransaction(@Nullable C headerCarrier, BinaryHeaderGetter binaryHeadersGetter, - Sampler sampler, long epochMicros, @Nullable ClassLoader initiatingClassLoader); @Override ElasticContext currentContext(); diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/baggage/Baggage.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/baggage/Baggage.java index cafe963e08..cecfe45f9e 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/baggage/Baggage.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/baggage/Baggage.java @@ -23,6 +23,7 @@ import co.elastic.apm.agent.impl.transaction.AbstractSpan; import javax.annotation.Nullable; +import java.nio.charset.StandardCharsets; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; @@ -61,6 +62,11 @@ public class Baggage implements co.elastic.apm.agent.tracer.Baggage { */ private volatile String cachedSerializedW3CHeader = null; + /** + * Cached UTF8-representation of {@link #cachedSerializedW3CHeader}. + */ + byte[] cachedSerializedW3CHeaderUtf8 = null; + private Baggage(Map baggage, Map baggageMetadata) { this.baggage = baggage; this.baggageMetadata = baggageMetadata; @@ -102,6 +108,20 @@ String getCachedSerializedW3CHeader() { return this.cachedSerializedW3CHeader; } + + byte[] getCachedSerializedW3CHeaderUtf8() { + if (cachedSerializedW3CHeader == null) { + throw new IllegalStateException("cached string header must be set first"); + } + if (cachedSerializedW3CHeader.isEmpty()) { + return null; + } + if (cachedSerializedW3CHeaderUtf8 == null) { + cachedSerializedW3CHeaderUtf8 = cachedSerializedW3CHeader.getBytes(StandardCharsets.UTF_8); + } + return this.cachedSerializedW3CHeaderUtf8; + } + public void storeBaggageInAttributes(AbstractSpan span, List keyFilter) { if (baggage.isEmpty() || keyFilter.isEmpty()) { // early out to prevent unnecessarily allocating an iterator @@ -143,6 +163,24 @@ private String getKeyWithAttributePrefix(String key) { return keyWithPrefix; } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Baggage baggage1 = (Baggage) o; + + if (!baggage.equals(baggage1.baggage)) return false; + return baggageMetadata.equals(baggage1.baggageMetadata); + } + + @Override + public int hashCode() { + int result = baggage.hashCode(); + result = 31 * result + baggageMetadata.hashCode(); + return result; + } + public static class Builder { public Builder(Baggage parent) { diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/baggage/W3CBaggagePropagation.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/baggage/W3CBaggagePropagation.java index fadac3a08e..6a52a1712d 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/baggage/W3CBaggagePropagation.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/baggage/W3CBaggagePropagation.java @@ -21,12 +21,16 @@ import co.elastic.apm.agent.impl.baggage.otel.Parser; import co.elastic.apm.agent.impl.baggage.otel.PercentEscaper; import co.elastic.apm.agent.tracer.dispatch.HeaderGetter; +import co.elastic.apm.agent.tracer.dispatch.HeaderSetter; import co.elastic.apm.agent.tracer.dispatch.TextHeaderGetter; import co.elastic.apm.agent.tracer.dispatch.TextHeaderSetter; +import co.elastic.apm.agent.tracer.dispatch.UTF8ByteHeaderGetter; +import co.elastic.apm.agent.tracer.dispatch.UTF8ByteHeaderSetter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.annotation.Nullable; +import java.nio.charset.StandardCharsets; public class W3CBaggagePropagation { @@ -36,7 +40,7 @@ public class W3CBaggagePropagation { public static final String BAGGAGE_HEADER_NAME = "baggage"; - private static final HeaderGetter.HeaderConsumer PARSING_CONSUMER = new HeaderGetter.HeaderConsumer() { + private static final HeaderGetter.HeaderConsumer STRING_PARSING_CONSUMER = new HeaderGetter.HeaderConsumer() { @Override public void accept(@Nullable String headerValue, Baggage.Builder state) { if (headerValue != null) { @@ -49,22 +53,71 @@ public void accept(@Nullable String headerValue, Baggage.Builder state) { } }; - public static void parse(C carrier, TextHeaderGetter headerGetter, Baggage.Builder into) { - headerGetter.forEach(BAGGAGE_HEADER_NAME, carrier, into, PARSING_CONSUMER); + + private static final HeaderGetter.HeaderConsumer UTF8_BYTES_PARSING_CONSUMER = new HeaderGetter.HeaderConsumer() { + @Override + public void accept(@Nullable byte[] headerValue, Baggage.Builder state) { + if (headerValue != null) { + try { + STRING_PARSING_CONSUMER.accept(new String(headerValue, StandardCharsets.UTF_8), state); + } catch (Exception e) { + logger.error("Failed to decode baggage header bytes as UTF8", e); + } + } + } + }; + + @SuppressWarnings("unchecked") + public static void parse(C carrier, HeaderGetter headerGetter, Baggage.Builder into) { + HeaderGetter.HeaderConsumer consumer; + if (headerGetter instanceof TextHeaderGetter) { + consumer = (HeaderGetter.HeaderConsumer) STRING_PARSING_CONSUMER; + } else if (headerGetter instanceof UTF8ByteHeaderGetter) { + consumer = (HeaderGetter.HeaderConsumer) UTF8_BYTES_PARSING_CONSUMER; + } else { + throw new IllegalArgumentException("HeaderGetter must be either a TextHeaderGetter or UTF8ByteHeaderGetter: " + headerGetter.getClass().getName()); + } + headerGetter.forEach(BAGGAGE_HEADER_NAME, carrier, into, consumer); } - public static void propagate(Baggage baggage, C carrier, TextHeaderSetter setter) { + public static void propagate(Baggage baggage, C carrier, HeaderSetter setter) { if (baggage.isEmpty()) { return; } + T header = getTextHeader(baggage, setter); + if (header != null) { + setter.setHeader(BAGGAGE_HEADER_NAME, header, carrier); + } + } + + @SuppressWarnings("unchecked") + private static T getTextHeader(Baggage baggage, HeaderSetter setter) { + if (setter instanceof TextHeaderSetter) { + return (T) getTextHeaderString(baggage); + } else if (setter instanceof UTF8ByteHeaderSetter) { + return (T) getTextHeaderUtf8Bytes(baggage); + } else { + throw new IllegalArgumentException("HeaderSetter must be either a TextHeaderSetter or UTF8ByteHeaderSetter: " + setter.getClass().getName()); + } + } + + @Nullable + private static byte[] getTextHeaderUtf8Bytes(Baggage baggage) { + getTextHeaderString(baggage); //ensures that the string-header is computed and cached + return baggage.getCachedSerializedW3CHeaderUtf8(); + } + + @Nullable + private static String getTextHeaderString(Baggage baggage) { String header = baggage.getCachedSerializedW3CHeader(); if (header == null) { header = encodeToHeader(baggage); baggage.setCachedSerializedW3CHeader(header); } - if (!header.isEmpty()) { - setter.setHeader(BAGGAGE_HEADER_NAME, encodeToHeader(baggage), carrier); + if (header.isEmpty()) { + return null; } + return header; } diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/error/ErrorCapture.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/error/ErrorCapture.java index 5f63869587..5be5431390 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/error/ErrorCapture.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/error/ErrorCapture.java @@ -37,7 +37,7 @@ /** * Data captured by an agent representing an event occurring in a monitored service */ -public class ErrorCapture implements Recyclable { +public class ErrorCapture implements Recyclable, co.elastic.apm.agent.tracer.ErrorCapture { private static final Logger logger = LoggerFactory.getLogger(ErrorCapture.class); @@ -147,6 +147,7 @@ public ErrorCapture asChildOf(AbstractSpan parent) { return this; } + @Override public TraceContext getTraceContext() { return traceContext; } @@ -199,11 +200,13 @@ private void setCulprit(StackTraceElement stackTraceElement) { culprit.append(')'); } + @Override public ErrorCapture activate() { activeError.set(this); return this; } + @Override public ErrorCapture deactivate() { activeError.remove(); return this; @@ -267,6 +270,7 @@ public void setTransactionType(@Nullable String type) { transactionInfo.type = type; } + @Override public void end() { tracer.endError(this); } diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/metadata/CloudMetadataProvider.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/metadata/CloudMetadataProvider.java index cf2f39cab8..caa060f0b7 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/metadata/CloudMetadataProvider.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/metadata/CloudMetadataProvider.java @@ -343,8 +343,7 @@ static CloudProviderInfo deserializeGcpMetadata(@Nullable String rawMetadata) th if (projectData instanceof Map) { @SuppressWarnings("unchecked") Map projectMap = (Map) projectData; String projectId = projectMap.get("projectId") instanceof String ? (String) projectMap.get("projectId") : null; - Long numericProjectId = projectMap.get("numericProjectId") instanceof Long ? (Long) projectMap.get("numericProjectId") : null; - cloudProviderInfo.setProject(new NameAndIdField(projectId, numericProjectId)); + cloudProviderInfo.setProject(new NameAndIdField(null, projectId)); } else { logger.warn("Error while parsing GCP metadata - expecting the value of the 'project' entry to be a map but it is not"); } diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/AbstractSpan.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/AbstractSpan.java index 173507cc47..96de90c4c0 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/AbstractSpan.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/AbstractSpan.java @@ -29,9 +29,7 @@ import co.elastic.apm.agent.sdk.logging.Logger; import co.elastic.apm.agent.sdk.logging.LoggerFactory; import co.elastic.apm.agent.tracer.Outcome; -import co.elastic.apm.agent.tracer.dispatch.BinaryHeaderGetter; import co.elastic.apm.agent.tracer.dispatch.HeaderGetter; -import co.elastic.apm.agent.tracer.dispatch.TextHeaderGetter; import co.elastic.apm.agent.tracer.pooling.Recyclable; import javax.annotation.Nullable; @@ -367,7 +365,6 @@ private boolean canAddSpanLink() { * Adds a span link based on the tracecontext header retrieved from the provided {@code carrier} through the provided {@code * headerGetter}. * - * @param childContextCreator the proper tracecontext inference implementation, corresponding on the header and types * @param headerGetter the proper header extractor, corresponding the header and carrier types * @param carrier the object from which the tracecontext header is to be retrieved * @param the tracecontext header type - either binary ({@code byte[]}) or textual ({@code String}) @@ -375,7 +372,6 @@ private boolean canAddSpanLink() { * @return {@code true} if added, {@code false} otherwise */ public boolean addSpanLink( - TraceContext.HeaderChildContextCreator childContextCreator, HeaderGetter headerGetter, @Nullable C carrier ) { @@ -385,7 +381,7 @@ public boolean addSpanLink( boolean added = false; try { TraceContext childTraceContext = tracer.createSpanLink(); - if (childContextCreator.asChildOf(childTraceContext, carrier, headerGetter)) { + if (childTraceContext.asChildOf(carrier, headerGetter, false)) { added = spanLinks.add(childTraceContext); } if (!added) { @@ -793,16 +789,7 @@ private String normalizeType(@Nullable String type) { } @Override - public boolean addLink(BinaryHeaderGetter headerGetter, @Nullable C carrier) { - return addSpanLink(TraceContext.getFromTraceContextBinaryHeaders(), - headerGetter, - carrier); - } - - @Override - public boolean addLink(TextHeaderGetter headerGetter, @Nullable C carrier) { - return addSpanLink(TraceContext.getFromTraceContextTextHeaders(), - headerGetter, - carrier); + public boolean addLink(HeaderGetter headerGetter, @Nullable C carrier) { + return addSpanLink(headerGetter, carrier); } } diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/CharAccessor.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/CharAccessor.java new file mode 100644 index 0000000000..3c90853b22 --- /dev/null +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/CharAccessor.java @@ -0,0 +1,142 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package co.elastic.apm.agent.impl.transaction; + +import co.elastic.apm.agent.tracer.util.HexUtils; + +import java.nio.charset.StandardCharsets; + +abstract class CharAccessor { + + abstract int length(T text); + + abstract char charAt(T text, int index); + + abstract void readHex(T text, int offset, byte[] into); + + abstract byte readHexByte(T text, int offset); + + abstract String asString(T text); + + int getLeadingWhitespaceCount(T text) { + int count = 0; + int len = length(text); + while (count < len && Character.isWhitespace(charAt(text, count))) { + count++; + } + return count; + } + + int getTrailingWhitespaceCount(T text) { + int count = 0; + int len = length(text); + while (count < len && Character.isWhitespace(charAt(text, len - 1 - count))) { + count++; + } + return count; + } + + public boolean containsAtOffset(T text, int offset, CharSequence substringToCheck) { + int len = length(text); + if (offset < 0 || offset > len) { + throw new IllegalArgumentException("Bad offset: " + offset); + } + int subStrLen = substringToCheck.length(); + if (offset + subStrLen > len) { + return false; + } + + for (int i = 0; i < subStrLen; i++) { + if (charAt(text, i + offset) != substringToCheck.charAt(i)) { + return false; + } + } + return true; + } + + public static CharAccessor forCharSequence() { + return CharSeq.INSTANCE; + } + + public static CharAccessor forAsciiBytes() { + return AsciiBytes.INSTANCE; + } + + + private static class CharSeq extends CharAccessor { + + static final CharSeq INSTANCE = new CharSeq(); + + @Override + int length(CharSequence text) { + return text.length(); + } + + @Override + char charAt(CharSequence text, int index) { + return text.charAt(index); + } + + @Override + void readHex(CharSequence text, int offset, byte[] into) { + HexUtils.nextBytes(text, offset, into); + } + + @Override + byte readHexByte(CharSequence text, int offset) { + return HexUtils.getNextByte(text, offset); + } + + @Override + String asString(CharSequence text) { + return text.toString(); + } + } + + private static class AsciiBytes extends CharAccessor { + + static final AsciiBytes INSTANCE = new AsciiBytes(); + + @Override + int length(byte[] text) { + return text.length; + } + + @Override + char charAt(byte[] text, int index) { + return (char) text[index]; + } + + @Override + void readHex(byte[] text, int offset, byte[] into) { + HexUtils.nextBytesAscii(text, offset, into); + } + + @Override + byte readHexByte(byte[] text, int offset) { + return HexUtils.getNextByteAscii(text, offset); + } + + @Override + String asString(byte[] text) { + return new String(text, StandardCharsets.UTF_8); + } + } + +} diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/ElasticContext.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/ElasticContext.java index 6545b24513..a59d74dfcc 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/ElasticContext.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/ElasticContext.java @@ -23,10 +23,9 @@ import co.elastic.apm.agent.impl.baggage.BaggageContext; import co.elastic.apm.agent.impl.baggage.W3CBaggagePropagation; import co.elastic.apm.agent.tracer.Scope; -import co.elastic.apm.agent.tracer.dispatch.BinaryHeaderSetter; +import co.elastic.apm.agent.tracer.dispatch.HeaderGetter; +import co.elastic.apm.agent.tracer.dispatch.HeaderSetter; import co.elastic.apm.agent.tracer.dispatch.HeaderUtils; -import co.elastic.apm.agent.tracer.dispatch.TextHeaderGetter; -import co.elastic.apm.agent.tracer.dispatch.TextHeaderSetter; import javax.annotation.Nullable; @@ -103,24 +102,13 @@ public boolean isEmpty() { return getSpan() == null && getBaggage().isEmpty(); } - - @Override - public final boolean propagateContext(C carrier, BinaryHeaderSetter headerSetter) { - AbstractSpan contextSpan = getSpan(); - if (contextSpan != null) { - contextSpan.setNonDiscardable(); - return contextSpan.getTraceContext().propagateTraceContext(carrier, headerSetter); - } - return false; - } - @Override - public final void propagateContext(C carrier, TextHeaderSetter headerSetter, @Nullable TextHeaderGetter headerGetter) { + public final void propagateContext(C carrier, HeaderSetter headerSetter, @Nullable HeaderGetter headerGetter) { propagateContext(carrier, headerSetter, carrier, headerGetter); } @Override - public void propagateContext(C1 carrier, TextHeaderSetter headerSetter, @Nullable C2 carrier2, @Nullable TextHeaderGetter headerGetter) { + public void propagateContext(C1 carrier, HeaderSetter headerSetter, @Nullable C2 carrier2, @Nullable HeaderGetter headerGetter) { AbstractSpan contextSpan = getSpan(); if (contextSpan != null) { if (headerGetter == null || carrier2 == null || !HeaderUtils.containsAny(TraceContext.TRACE_TEXTUAL_HEADERS, carrier2, headerGetter)) { @@ -137,7 +125,7 @@ public void propagateContext(C1 carrier, TextHeaderSetter headerSet } @Override - public boolean isPropagationRequired(C carrier, TextHeaderGetter headerGetter) { + public boolean isPropagationRequired(C carrier, HeaderGetter headerGetter) { AbstractSpan contextSpan = getSpan(); boolean traceContextPropagationRequired = contextSpan != null && !HeaderUtils.containsAny(TraceContext.TRACE_TEXTUAL_HEADERS, carrier, headerGetter); boolean baggagePropagationRequired = !getBaggage().isEmpty() && headerGetter.getFirstHeader(W3CBaggagePropagation.BAGGAGE_HEADER_NAME, carrier) == null; diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/Id.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/Id.java index e76ab5513d..27aa8289b7 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/Id.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/Id.java @@ -18,8 +18,9 @@ */ package co.elastic.apm.agent.impl.transaction; -import co.elastic.apm.agent.util.HexUtils; +import co.elastic.apm.agent.report.serialize.HexSerializationUtils; import co.elastic.apm.agent.tracer.pooling.Recyclable; +import co.elastic.apm.agent.tracer.util.HexUtils; import com.dslplatform.json.JsonWriter; import javax.annotation.Nullable; @@ -65,10 +66,15 @@ public void fromHexString(String hexEncodedString, int offset) { onMutation(); } + public void fromHexString(T hexEncodedString, int offset, CharAccessor accessor) { + accessor.readHex(hexEncodedString, offset, data); + onMutation(); + } + /** * Sets the id based on a byte array * - * @param bytes the byte array used to fill this id's {@link #data} + * @param bytes the byte array used to fill this id's {@link #data} * @param offset the offset in the byte array * @return the number of read bytes which is equivalent to {@link #getLength()} */ @@ -162,7 +168,7 @@ private static boolean isAllZeros(byte[] bytes) { } public void writeAsHex(JsonWriter jw) { - HexUtils.writeBytesAsHex(data, jw); + HexSerializationUtils.writeBytesAsHex(data, jw); } public void writeAsHex(StringBuilder sb) { diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/TraceContext.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/TraceContext.java index 7252a29737..f8854468f0 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/TraceContext.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/TraceContext.java @@ -24,14 +24,16 @@ import co.elastic.apm.agent.impl.sampling.Sampler; import co.elastic.apm.agent.sdk.logging.Logger; import co.elastic.apm.agent.sdk.logging.LoggerFactory; -import co.elastic.apm.agent.tracer.dispatch.BinaryHeaderSetter; import co.elastic.apm.agent.tracer.dispatch.HeaderGetter; import co.elastic.apm.agent.tracer.dispatch.HeaderRemover; +import co.elastic.apm.agent.tracer.dispatch.HeaderSetter; import co.elastic.apm.agent.tracer.dispatch.TextHeaderGetter; import co.elastic.apm.agent.tracer.dispatch.TextHeaderSetter; +import co.elastic.apm.agent.tracer.dispatch.UTF8ByteHeaderGetter; +import co.elastic.apm.agent.tracer.dispatch.UTF8ByteHeaderSetter; import co.elastic.apm.agent.tracer.pooling.Recyclable; +import co.elastic.apm.agent.tracer.util.HexUtils; import co.elastic.apm.agent.util.ByteUtils; -import co.elastic.apm.agent.util.HexUtils; import javax.annotation.Nullable; import java.nio.charset.StandardCharsets; @@ -56,23 +58,6 @@ * Header name Version Trace-Id Span-Id Flags * *

- * Binary representation (e.g. 0.11.0.0+ Kafka record header), based on - * https://github.com/elastic/apm/blob/main/docs/agent-development.md#binary-fields: - *

- *      traceparent     = version version_format
- *      version         = 1BYTE                   ; version is 0 in the current spec
- *      version_format  = "{ 0x0 }" trace-id "{ 0x1 }" parent-id "{ 0x2 }" trace-flags
- *      trace-id        = 16BYTES
- *      parent-id       = 8BYTES
- *      trace-flags     = 1BYTE  ; only the least significant bit is used
- * 
- * For example: - *
- * elasticapmparent:   [0,
- *                      0, 75, 249, 47, 53, 119, 179, 77, 166, 163, 206, 146, 157, 0, 14, 71, 54,
- *                      1, 52, 240, 103, 170, 11, 169, 2, 183,
- *                      2, 1]
- * 
*/ public class TraceContext implements Recyclable, co.elastic.apm.agent.tracer.TraceContext { @@ -84,18 +69,6 @@ public class TraceContext implements Recyclable, co.elastic.apm.agent.tracer.Tra private static final int TEXT_HEADER_TRACE_ID_OFFSET = 3; private static final int TEXT_HEADER_PARENT_ID_OFFSET = 36; private static final int TEXT_HEADER_FLAGS_OFFSET = 53; - - public static final int BINARY_FORMAT_EXPECTED_LENGTH = 29; - private static final byte BINARY_FORMAT_CURRENT_VERSION = (byte) 0b0000_0000; - // one byte for the trace-id field id (0x00), followed by 16 bytes of the actual ID - private static final int BINARY_FORMAT_TRACE_ID_OFFSET = 1; - private static final byte BINARY_FORMAT_TRACE_ID_FIELD_ID = (byte) 0b0000_0000; - // one byte for the parent-id field id (0x01), followed by 8 bytes of the actual ID - private static final int BINARY_FORMAT_PARENT_ID_OFFSET = 18; - private static final byte BINARY_FORMAT_PARENT_ID_FIELD_ID = (byte) 0b0000_0001; - // one byte for the flags field id (0x02), followed by two bytes of flags contents - private static final int BINARY_FORMAT_FLAGS_OFFSET = 27; - private static final byte BINARY_FORMAT_FLAGS_FIELD_ID = (byte) 0b0000_0010; private static final Logger logger = LoggerFactory.getLogger(TraceContext.class); private static final Double SAMPLE_RATE_ZERO = 0d; @@ -124,66 +97,66 @@ public boolean asChildOf(TraceContext child, AbstractSpan parent) { return true; } }; - private static final HeaderGetter.HeaderConsumer TRACESTATE_HEADER_CONSUMER = new HeaderGetter.HeaderConsumer() { + + private static final HeaderGetter.HeaderConsumer STRING_TRACESTATE_HEADER_CONSUMER = new HeaderGetter.HeaderConsumer() { @Override public void accept(@Nullable String tracestateHeaderValue, TraceContext state) { - if (tracestateHeaderValue != null) { - state.traceState.addTextHeader(tracestateHeaderValue); - } + state.addTraceStateHeader(tracestateHeaderValue, CharAccessor.forCharSequence()); } }; - private static final HeaderChildContextCreator FROM_TRACE_CONTEXT_TEXT_HEADERS = - new HeaderChildContextCreator() { - @Override - public boolean asChildOf(TraceContext child, @Nullable Object carrier, HeaderGetter traceContextHeaderGetter) { - if (carrier == null) { - return false; - } - boolean isValid = false; - String traceparent = traceContextHeaderGetter.getFirstHeader(W3C_TRACE_PARENT_TEXTUAL_HEADER_NAME, carrier); - if (traceparent != null) { - isValid = child.asChildOf(traceparent); - } - - if (!isValid) { - // Look for the legacy Elastic traceparent header (in case this comes from an older agent) - traceparent = traceContextHeaderGetter.getFirstHeader(ELASTIC_TRACE_PARENT_TEXTUAL_HEADER_NAME, carrier); - if (traceparent != null) { - isValid = child.asChildOf(traceparent); - } - } + private static final HeaderGetter.HeaderConsumer UTF8_BYTES_TRACESTATE_HEADER_CONSUMER = new HeaderGetter.HeaderConsumer() { + @Override + public void accept(@Nullable byte[] tracestateHeaderValue, TraceContext state) { + state.addTraceStateHeader(tracestateHeaderValue, CharAccessor.forAsciiBytes()); + } + }; - if (isValid) { - // as per spec, the tracestate header can be multi-valued - traceContextHeaderGetter.forEach(TRACESTATE_HEADER_NAME, carrier, child, TRACESTATE_HEADER_CONSUMER); - } + public boolean asChildOf(@Nullable C carrier, HeaderGetter headerGetter) { + return asChildOf(carrier, headerGetter, true); + } - return isValid; - } - }; - private static final HeaderChildContextCreator FROM_TRACE_CONTEXT_BINARY_HEADERS = - new HeaderChildContextCreator() { - @Override - public boolean asChildOf(TraceContext child, @Nullable Object carrier, HeaderGetter traceContextHeaderGetter) { - if (carrier == null) { - return false; - } - byte[] traceparent = traceContextHeaderGetter.getFirstHeader(ELASTIC_TRACE_PARENT_TEXTUAL_HEADER_NAME, carrier); - if (traceparent != null) { - return child.asChildOf(traceparent); - } - return false; - } - }; + @SuppressWarnings("unchecked") + public boolean asChildOf(@Nullable C carrier, HeaderGetter headerGetter, boolean parseTraceState) { + CharAccessor headerValueAccessor; + HeaderGetter.HeaderConsumer traceStateConsumer; + if (headerGetter instanceof TextHeaderGetter) { + headerValueAccessor = (CharAccessor) CharAccessor.forCharSequence(); + traceStateConsumer = (HeaderGetter.HeaderConsumer) STRING_TRACESTATE_HEADER_CONSUMER; + } else if (headerGetter instanceof UTF8ByteHeaderGetter) { + headerValueAccessor = (CharAccessor) CharAccessor.forAsciiBytes(); + traceStateConsumer = (HeaderGetter.HeaderConsumer) UTF8_BYTES_TRACESTATE_HEADER_CONSUMER; + } else { + throw new IllegalArgumentException("HeaderGetter must be either a TextHeaderGetter or UTF8ByteHeaderGetter: " + headerGetter.getClass().getName()); + } + boolean valid = extractTraceParentFromHeaders(carrier, headerGetter, headerValueAccessor); + if (valid && parseTraceState) { + headerGetter.forEach(TRACESTATE_HEADER_NAME, carrier, this, traceStateConsumer); + } + return valid; + } - private static final ChildContextCreator AS_ROOT = new ChildContextCreator() { - @Override - public boolean asChildOf(TraceContext child, Object ignore) { + private boolean extractTraceParentFromHeaders(@Nullable C carrier, HeaderGetter traceContextHeaderGetter, CharAccessor charAccessor) { + if (carrier == null) { return false; } - }; + boolean isValid = false; + T traceparent = traceContextHeaderGetter.getFirstHeader(W3C_TRACE_PARENT_TEXTUAL_HEADER_NAME, carrier); + if (traceparent != null) { + isValid = asChildOf(traceparent, charAccessor); + } + + if (!isValid) { + // Look for the legacy Elastic traceparent header (in case this comes from an older agent) + traceparent = traceContextHeaderGetter.getFirstHeader(ELASTIC_TRACE_PARENT_TEXTUAL_HEADER_NAME, carrier); + if (traceparent != null) { + isValid = asChildOf(traceparent, charAccessor); + } + } + + return isValid; + } public static boolean containsTraceContextTextHeaders(C carrier, TextHeaderGetter headerGetter) { // We assume that this header is always present if we found any of the other headers. @@ -271,16 +244,6 @@ public static TraceContext with128BitId(ElasticApmTracer tracer) { return new TraceContext(tracer, Id.new128BitId()); } - @SuppressWarnings("unchecked") - public static HeaderChildContextCreator getFromTraceContextTextHeaders() { - return (HeaderChildContextCreator) FROM_TRACE_CONTEXT_TEXT_HEADERS; - } - - @SuppressWarnings("unchecked") - public static HeaderChildContextCreator getFromTraceContextBinaryHeaders() { - return (HeaderChildContextCreator) FROM_TRACE_CONTEXT_BINARY_HEADERS; - } - public static ChildContextCreator fromParentContext() { return FROM_PARENT_CONTEXT; } @@ -289,8 +252,8 @@ public static ChildContextCreator> fromParent() { return FROM_PARENT; } - public static ChildContextCreator asRoot() { - return AS_ROOT; + boolean asChildOf(String traceParentHeader) { + return asChildOf(traceParentHeader, CharAccessor.forCharSequence()); } /** @@ -299,38 +262,50 @@ public static ChildContextCreator asRoot() { * @param traceParentHeader traceparent text header value * @return {@literal true} if header value is valid, {@literal false} otherwise */ - boolean asChildOf(String traceParentHeader) { - traceParentHeader = traceParentHeader.trim(); + boolean asChildOf(T traceParentHeader, CharAccessor charAccessor) { + + int leadingWs = charAccessor.getLeadingWhitespaceCount(traceParentHeader); + int trailingWs = charAccessor.getTrailingWhitespaceCount(traceParentHeader); + try { - if (traceParentHeader.length() < TEXT_HEADER_EXPECTED_LENGTH) { - logger.warn("The traceparent header has to be at least 55 chars long, but was '{}'", traceParentHeader); + int trimmedLen = Math.max(0, charAccessor.length(traceParentHeader) - leadingWs - trailingWs); + if (trimmedLen < TEXT_HEADER_EXPECTED_LENGTH) { + logger.warn("The traceparent header has to be at least 55 chars long, but was '{}'", trimmedLen); return false; } - if (noDashAtPosition(traceParentHeader, TEXT_HEADER_TRACE_ID_OFFSET - 1) - || noDashAtPosition(traceParentHeader, TEXT_HEADER_PARENT_ID_OFFSET - 1) - || noDashAtPosition(traceParentHeader, TEXT_HEADER_FLAGS_OFFSET - 1)) { - logger.warn("The traceparent header has an invalid format: '{}'", traceParentHeader); + if (noDashAtPosition(traceParentHeader, leadingWs + TEXT_HEADER_TRACE_ID_OFFSET - 1, charAccessor) + || noDashAtPosition(traceParentHeader, leadingWs + TEXT_HEADER_PARENT_ID_OFFSET - 1, charAccessor) + || noDashAtPosition(traceParentHeader, leadingWs + TEXT_HEADER_FLAGS_OFFSET - 1, charAccessor)) { + if (logger.isWarnEnabled()) { + logger.warn("The traceparent header has an invalid format: '{}'", charAccessor.asString(traceParentHeader)); + } return false; } - if (traceParentHeader.length() > TEXT_HEADER_EXPECTED_LENGTH - && noDashAtPosition(traceParentHeader, TEXT_HEADER_EXPECTED_LENGTH)) { - logger.warn("The traceparent header has an invalid format: '{}'", traceParentHeader); + if (trimmedLen > TEXT_HEADER_EXPECTED_LENGTH + && noDashAtPosition(traceParentHeader, leadingWs + TEXT_HEADER_EXPECTED_LENGTH, charAccessor)) { + if (logger.isWarnEnabled()) { + logger.warn("The traceparent header has an invalid format: '{}'", charAccessor.asString(traceParentHeader)); + } return false; } - if (traceParentHeader.startsWith("ff")) { - logger.warn("Version ff is not supported"); + if (charAccessor.containsAtOffset(traceParentHeader, leadingWs, "ff")) { + if (logger.isWarnEnabled()) { + logger.warn("Version ff is not supported"); + } return false; } - byte version = HexUtils.getNextByte(traceParentHeader, 0); - if (version == 0 && traceParentHeader.length() > TEXT_HEADER_EXPECTED_LENGTH) { - logger.warn("The traceparent header has to be exactly 55 chars long for version 00, but was '{}'", traceParentHeader); + byte version = charAccessor.readHexByte(traceParentHeader, leadingWs); + if (version == 0 && trimmedLen > TEXT_HEADER_EXPECTED_LENGTH) { + if (logger.isWarnEnabled()) { + logger.warn("The traceparent header has to be exactly 55 chars long for version 00, but was '{}'", charAccessor.asString(traceParentHeader)); + } return false; } - traceId.fromHexString(traceParentHeader, TEXT_HEADER_TRACE_ID_OFFSET); + traceId.fromHexString(traceParentHeader, leadingWs + TEXT_HEADER_TRACE_ID_OFFSET, charAccessor); if (traceId.isEmpty()) { return false; } - parentId.fromHexString(traceParentHeader, TEXT_HEADER_PARENT_ID_OFFSET); + parentId.fromHexString(traceParentHeader, leadingWs + TEXT_HEADER_PARENT_ID_OFFSET, charAccessor); if (parentId.isEmpty()) { return false; } @@ -339,7 +314,7 @@ && noDashAtPosition(traceParentHeader, TEXT_HEADER_EXPECTED_LENGTH)) { // TODO don't blindly trust the flags from the caller // consider implement rate limiting and/or having a list of trusted sources // trace the request if it's either requested or if the parent has recorded it - flags = HexUtils.getNextByte(traceParentHeader, TEXT_HEADER_FLAGS_OFFSET); + flags = charAccessor.readHexByte(traceParentHeader, TEXT_HEADER_FLAGS_OFFSET + leadingWs); clock.init(); return true; } catch (IllegalArgumentException e) { @@ -350,66 +325,14 @@ && noDashAtPosition(traceParentHeader, TEXT_HEADER_EXPECTED_LENGTH)) { } } - /** - * Tries to set trace context identifiers (Id, parent, ...) from traceparent binary header value - * - * @param traceParentHeader traceparent binary header value - * @return {@literal true} if header value is valid, {@literal false} otherwise - */ - boolean asChildOf(byte[] traceParentHeader) { - if (logger.isTraceEnabled()) { - logger.trace("Binary header content UTF-8-decoded: {}", new String(traceParentHeader, StandardCharsets.UTF_8)); - } - try { - if (traceParentHeader.length < BINARY_FORMAT_EXPECTED_LENGTH) { - logger.warn("The traceparent header has to be at least 29 bytes long, but is not"); - return false; - } - // Current spec says: "Note, that parsing should not treat any additional bytes in the end of the buffer - // as an invalid status. Those fields can be added for padding purposes.", which means there is no upper - // limit. In addition, no version is specified as erroneous, so version is non-informative. - - byte fieldId = traceParentHeader[BINARY_FORMAT_TRACE_ID_OFFSET]; - if (fieldId != BINARY_FORMAT_TRACE_ID_FIELD_ID) { - logger.warn("Wrong trace-id field identifier: {}", fieldId); - return false; - } - traceId.fromBytes(traceParentHeader, BINARY_FORMAT_TRACE_ID_OFFSET + 1); - if (traceId.isEmpty()) { - return false; - } - fieldId = traceParentHeader[BINARY_FORMAT_PARENT_ID_OFFSET]; - if (fieldId != BINARY_FORMAT_PARENT_ID_FIELD_ID) { - logger.warn("Wrong parent-id field identifier: {}", fieldId); - return false; - } - parentId.fromBytes(traceParentHeader, BINARY_FORMAT_PARENT_ID_OFFSET + 1); - if (parentId.isEmpty()) { - return false; - } - id.setToRandomValue(); - transactionId.copyFrom(id); - fieldId = traceParentHeader[BINARY_FORMAT_FLAGS_OFFSET]; - if (fieldId != BINARY_FORMAT_FLAGS_FIELD_ID) { - logger.warn("Wrong flags field identifier: {}", fieldId); - return false; - } - // TODO don't blindly trust the flags from the caller - // consider implement rate limiting and/or having a list of trusted sources - // trace the request if it's either requested or if the parent has recorded it - flags = traceParentHeader[BINARY_FORMAT_FLAGS_OFFSET + 1]; - clock.init(); - return true; - } catch (IllegalArgumentException e) { - logger.warn(e.getMessage()); - return false; - } finally { - onMutation(); - } + private boolean noDashAtPosition(T traceParentHeader, int index, CharAccessor accessor) { + return accessor.charAt(traceParentHeader, index) != '-'; } - private boolean noDashAtPosition(String traceParentHeader, int index) { - return traceParentHeader.charAt(index) != '-'; + private void addTraceStateHeader(@Nullable T tracestateHeaderValue, CharAccessor charAccessor) { + if (tracestateHeaderValue != null) { + traceState.addTextHeader(charAccessor.asString(tracestateHeaderValue)); + } } public void asRootSpan(Sampler sampler) { @@ -541,54 +464,63 @@ String getIncomingTraceParentHeader() { * @param headerSetter a setter implementing the actual addition of headers to the headers carrier * @param the header carrier type, for example - an HTTP request */ - void propagateTraceContext(C carrier, TextHeaderSetter headerSetter) { + void propagateTraceContext(C carrier, HeaderSetter headerSetter) { if (coreConfiguration.isOutgoingTraceContextHeadersInjectionDisabled()) { logger.debug("Outgoing TraceContext header injection is disabled"); return; } - String outgoingTraceParent = getOutgoingTraceParentTextHeader().toString(); + T outgoingTraceParent = getOutgoingTraceParentTextHeader(headerSetter); headerSetter.setHeader(W3C_TRACE_PARENT_TEXTUAL_HEADER_NAME, outgoingTraceParent, carrier); if (coreConfiguration.isElasticTraceparentHeaderEnabled()) { headerSetter.setHeader(ELASTIC_TRACE_PARENT_TEXTUAL_HEADER_NAME, outgoingTraceParent, carrier); } - String outgoingTraceState = traceState.toTextHeader(); + T outgoingTraceState = getOutgoingTraceStateHeader(headerSetter); if (outgoingTraceState != null) { headerSetter.setHeader(TRACESTATE_HEADER_NAME, outgoingTraceState, carrier); } logger.trace("Trace context headers added to {}", carrier); } - /** - * Sets Trace context binary headers, using this context as parent, on the provided carrier using the provided setter - * - * @param carrier the binary headers carrier - * @param headerSetter a setter implementing the actual addition of headers to the headers carrier - * @param the header carrier type, for example - a Kafka record - * @return true if Trace Context headers were set; false otherwise - */ - boolean propagateTraceContext(C carrier, BinaryHeaderSetter headerSetter) { - if (coreConfiguration.isOutgoingTraceContextHeadersInjectionDisabled()) { - logger.debug("Outgoing TraceContext header injection is disabled"); - return false; + T getOutgoingTraceParentTextHeader(HeaderSetter headerSetter) { + StringBuilder outgoingTraceParentTextHeader = getOutgoingTraceParentTextHeader(); + if (headerSetter instanceof TextHeaderSetter) { + return (T) outgoingTraceParentTextHeader.toString(); + } else if (headerSetter instanceof UTF8ByteHeaderSetter) { + int length = outgoingTraceParentTextHeader.length(); + byte[] result = new byte[length]; + for (int i = 0; i < length; i++) { + char c = outgoingTraceParentTextHeader.charAt(i); + if (c > 127) { + throw new IllegalStateException("Expected traceparent header to be ascii only"); + } + result[i] = (byte) c; + } + return (T) result; + } else { + throw new IllegalArgumentException("HeaderSetter must be either a TextHeaderSetter or UTF8ByteHeaderSetter: " + headerSetter.getClass().getName()); } - byte[] buffer = headerSetter.getFixedLengthByteArray(ELASTIC_TRACE_PARENT_TEXTUAL_HEADER_NAME, BINARY_FORMAT_EXPECTED_LENGTH); - if (buffer == null || buffer.length != BINARY_FORMAT_EXPECTED_LENGTH) { - logger.warn("Header setter {} failed to provide a byte buffer with the proper length. Allocating a buffer for each header.", - headerSetter.getClass().getName()); - buffer = new byte[BINARY_FORMAT_EXPECTED_LENGTH]; + } + + @Nullable + T getOutgoingTraceStateHeader(HeaderSetter headerSetter) { + String outgoingTraceState = traceState.toTextHeader(); + if (outgoingTraceState == null) { + return null; } - boolean headerBufferFilled = fillOutgoingTraceParentBinaryHeader(buffer); - if (headerBufferFilled) { - headerSetter.setHeader(ELASTIC_TRACE_PARENT_TEXTUAL_HEADER_NAME, buffer, carrier); + if (headerSetter instanceof TextHeaderSetter) { + return (T) outgoingTraceState; + } else if (headerSetter instanceof UTF8ByteHeaderSetter) { + return (T) outgoingTraceState.getBytes(StandardCharsets.UTF_8); + } else { + throw new IllegalArgumentException("HeaderSetter must be either a TextHeaderSetter or UTF8ByteHeaderSetter: " + headerSetter.getClass().getName()); } - return headerBufferFilled; } /** - * @return the value of the {@code traceparent} header for downstream services. + * @return the value of the {@code traceparent} header for downstream services. */ StringBuilder getOutgoingTraceParentTextHeader() { if (outgoingTextHeader.length() == 0) { @@ -613,31 +545,6 @@ private void fillTraceParentHeader(StringBuilder sb, Id spanId) { HexUtils.writeByteAsHex(flags, sb); } - /** - * Fills the given byte array with a binary representation of the {@code traceparent} header for downstream services. - * - * @param buffer buffer to fill - * @return true if buffer was filled, false otherwise - */ - private boolean fillOutgoingTraceParentBinaryHeader(byte[] buffer) { - if (buffer.length < BINARY_FORMAT_EXPECTED_LENGTH) { - logger.warn("Given byte array does not have the minimal required length - {}", BINARY_FORMAT_EXPECTED_LENGTH); - return false; - } - buffer[0] = BINARY_FORMAT_CURRENT_VERSION; - buffer[BINARY_FORMAT_TRACE_ID_OFFSET] = BINARY_FORMAT_TRACE_ID_FIELD_ID; - traceId.toBytes(buffer, BINARY_FORMAT_TRACE_ID_OFFSET + 1); - buffer[BINARY_FORMAT_PARENT_ID_OFFSET] = BINARY_FORMAT_PARENT_ID_FIELD_ID; - // for unsampled traces, propagate the ID of the transaction in calls to downstream services - // such that the parentID of those transactions point to a transaction that exists - // remember that we do report unsampled transactions - Id parentId = isSampled() ? id : transactionId; - parentId.toBytes(buffer, BINARY_FORMAT_PARENT_ID_OFFSET + 1); - buffer[BINARY_FORMAT_FLAGS_OFFSET] = BINARY_FORMAT_FLAGS_FIELD_ID; - buffer[BINARY_FORMAT_FLAGS_OFFSET + 1] = flags; - return true; - } - public boolean isChildOf(TraceContext other) { return other.getTraceId().equals(traceId) && other.getId().equals(parentId); } @@ -748,20 +655,6 @@ public void serialize(byte[] buffer) { ByteUtils.putLong(buffer, offset, clock.getOffset()); } - private void asChildOf(byte[] buffer, @Nullable String serviceName, @Nullable String serviceVersion) { - int offset = 0; - offset += traceId.fromBytes(buffer, offset); - offset += parentId.fromBytes(buffer, offset); - offset += transactionId.fromBytes(buffer, offset); - id.setToRandomValue(); - flags = buffer[offset++]; - discardable = buffer[offset++] == (byte) 1; - clock.init(ByteUtils.getLong(buffer, offset)); - this.serviceName = serviceName; - this.serviceVersion = serviceVersion; - onMutation(); - } - public void deserialize(byte[] buffer, @Nullable String serviceName, @Nullable String serviceVersion) { int offset = 0; offset += traceId.fromBytes(buffer, offset); @@ -775,10 +668,6 @@ public void deserialize(byte[] buffer, @Nullable String serviceName, @Nullable S onMutation(); } - public static void deserializeSpanId(Id id, byte[] buffer) { - id.fromBytes(buffer, 16); - } - public static long getSpanId(byte[] serializedTraceContext) { return ByteUtils.getLong(serializedTraceContext, 16); } @@ -795,10 +684,6 @@ public interface ChildContextCreator { boolean asChildOf(TraceContext child, T parent); } - public interface HeaderChildContextCreator { - boolean asChildOf(TraceContext child, @Nullable C carrier, HeaderGetter headerGetter); - } - public TraceContext copy() { final TraceContext copy; final int idLength = id.getLength(); diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/Transaction.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/Transaction.java index b907f26b9d..aabac69aed 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/Transaction.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/Transaction.java @@ -32,7 +32,6 @@ import co.elastic.apm.agent.metrics.Timer; import co.elastic.apm.agent.tracer.Outcome; import co.elastic.apm.agent.tracer.dispatch.HeaderGetter; -import co.elastic.apm.agent.tracer.dispatch.TextHeaderGetter; import co.elastic.apm.agent.tracer.util.ResultUtil; import co.elastic.apm.agent.util.KeyListConcurrentHashMap; import org.HdrHistogram.WriterReaderPhaser; @@ -133,7 +132,6 @@ public Transaction startRoot(long epochMicros, Sampler sampler, Baggage bagg } public Transaction start( - TraceContext.HeaderChildContextCreator childContextCreator, @Nullable C parent, HeaderGetter headerGetter, long epochMicros, @@ -143,13 +141,9 @@ public Transaction start( if (parent == null) { return startRoot(epochMicros, sampler, baseBaggage); } - if (headerGetter instanceof TextHeaderGetter) { - Baggage.Builder baggageBuilder = baseBaggage.toBuilder(); - W3CBaggagePropagation.parse(parent, (TextHeaderGetter) headerGetter, baggageBuilder); - this.baggage = baggageBuilder.build(); - } else { - this.baggage = baseBaggage; - } + Baggage.Builder baggageBuilder = baseBaggage.toBuilder(); + W3CBaggagePropagation.parse(parent, headerGetter, baggageBuilder); + this.baggage = baggageBuilder.build(); CoreConfiguration.TraceContinuationStrategy traceContinuationStrategy = coreConfig.getTraceContinuationStrategy(); boolean restartTrace = false; if (traceContinuationStrategy.equals(RESTART)) { @@ -159,10 +153,10 @@ public Transaction start( } if (restartTrace) { // need to add a span link - addSpanLink(childContextCreator, headerGetter, parent); + addSpanLink(headerGetter, parent); traceContext.asRootSpan(sampler); } else { - boolean valid = childContextCreator.asChildOf(traceContext, parent, headerGetter); + boolean valid = traceContext.asChildOf(parent, headerGetter); if (!valid) { traceContext.asRootSpan(sampler); } diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/logging/Log4j2ConfigurationFactory.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/logging/Log4j2ConfigurationFactory.java index 0bb8d6e634..e5da6fe806 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/logging/Log4j2ConfigurationFactory.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/logging/Log4j2ConfigurationFactory.java @@ -21,7 +21,7 @@ import co.elastic.apm.agent.bci.ElasticApmAgent; import co.elastic.apm.agent.common.util.SystemStandardOutputLogger; import co.elastic.apm.agent.configuration.CoreConfiguration; -import co.elastic.apm.agent.configuration.ServiceInfo; +import co.elastic.apm.agent.configuration.AutoDetectedServiceInfo; import co.elastic.apm.agent.tracer.configuration.ByteValue; import co.elastic.apm.agent.report.ApmServerReporter; import org.apache.logging.log4j.Level; @@ -186,7 +186,7 @@ private LayoutComponentBuilder createLayout(ConfigurationBuilder>> 4]); + jw.writeByte((byte) HexUtils.HEX_CHARS[v & 0x0F]); + } + + public static void writeAsHex(long l, JsonWriter jw) { + writeHexByte(jw, (byte) (l >> 56)); + writeHexByte(jw, (byte) (l >> 48)); + writeHexByte(jw, (byte) (l >> 40)); + writeHexByte(jw, (byte) (l >> 32)); + writeHexByte(jw, (byte) (l >> 24)); + writeHexByte(jw, (byte) (l >> 16)); + writeHexByte(jw, (byte) (l >> 8)); + writeHexByte(jw, (byte) l); + } +} diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/report/serialize/MetricRegistryReporter.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/report/serialize/MetricRegistryReporter.java index c281ade581..aa1a9347a9 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/report/serialize/MetricRegistryReporter.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/report/serialize/MetricRegistryReporter.java @@ -18,7 +18,7 @@ */ package co.elastic.apm.agent.report.serialize; -import co.elastic.apm.agent.configuration.ServiceInfo; +import co.elastic.apm.agent.tracer.service.ServiceInfo; import co.elastic.apm.agent.context.AbstractLifecycleListener; import co.elastic.apm.agent.impl.ElasticApmTracer; import co.elastic.apm.agent.metrics.Labels; diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/report/serialize/MetricRegistrySerializer.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/report/serialize/MetricRegistrySerializer.java index 2eb7b7bd20..e5b3700f39 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/report/serialize/MetricRegistrySerializer.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/report/serialize/MetricRegistrySerializer.java @@ -18,7 +18,7 @@ */ package co.elastic.apm.agent.report.serialize; -import co.elastic.apm.agent.configuration.ServiceInfo; +import co.elastic.apm.agent.tracer.service.ServiceInfo; import co.elastic.apm.agent.metrics.DoubleSupplier; import co.elastic.apm.agent.metrics.MetricSet; import co.elastic.apm.agent.metrics.Timer; diff --git a/apm-agent-core/src/test/java/co/elastic/apm/agent/configuration/ServiceInfoTest.java b/apm-agent-core/src/test/java/co/elastic/apm/agent/configuration/AutoDetectedServiceInfoTest.java similarity index 96% rename from apm-agent-core/src/test/java/co/elastic/apm/agent/configuration/ServiceInfoTest.java rename to apm-agent-core/src/test/java/co/elastic/apm/agent/configuration/AutoDetectedServiceInfoTest.java index 57aa889639..e900e81256 100644 --- a/apm-agent-core/src/test/java/co/elastic/apm/agent/configuration/ServiceInfoTest.java +++ b/apm-agent-core/src/test/java/co/elastic/apm/agent/configuration/AutoDetectedServiceInfoTest.java @@ -18,6 +18,7 @@ */ package co.elastic.apm.agent.configuration; +import co.elastic.apm.agent.tracer.service.ServiceInfo; import co.elastic.apm.agent.util.CustomEnvVariables; import org.junit.jupiter.api.Test; @@ -31,7 +32,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.SoftAssertions.assertSoftly; -class ServiceInfoTest extends CustomEnvVariables { +class AutoDetectedServiceInfoTest extends CustomEnvVariables { private static String getDefaultServiceName(@Nullable String sunJavaCommand) { Properties properties = new Properties(); @@ -39,7 +40,7 @@ private static String getDefaultServiceName(@Nullable String sunJavaCommand) { properties.setProperty("sun.java.command", sunJavaCommand); } - return ServiceInfo.autoDetect(properties, Map.of()).getServiceName(); + return AutoDetectedServiceInfo.autoDetect(properties, Map.of()).getServiceName(); } @Test @@ -81,7 +82,7 @@ void testDefaultsWithLambda() throws Exception { final Map awsLambdaEnvVariables = new HashMap<>(); awsLambdaEnvVariables.put("AWS_LAMBDA_FUNCTION_NAME", "my-lambda-function"); awsLambdaEnvVariables.put("AWS_LAMBDA_FUNCTION_VERSION", "24"); - ServiceInfo serviceInfo = callWithCustomEnvVariables(awsLambdaEnvVariables, () -> ServiceInfo.autoDetect(System.getProperties(), System.getenv())); + ServiceInfo serviceInfo = callWithCustomEnvVariables(awsLambdaEnvVariables, () -> AutoDetectedServiceInfo.autoDetect(System.getProperties(), System.getenv())); assertSoftly(softly -> { softly.assertThat(serviceInfo.getServiceName()).isEqualTo("my-lambda-function"); softly.assertThat(serviceInfo.getServiceVersion()).isEqualTo("24"); diff --git a/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/BinaryHeaderMapAccessor.java b/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/BinaryHeaderMapAccessor.java deleted file mode 100644 index 29c6a5fb5e..0000000000 --- a/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/BinaryHeaderMapAccessor.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package co.elastic.apm.agent.impl; - -import co.elastic.apm.agent.impl.transaction.TraceContext; -import co.elastic.apm.agent.tracer.dispatch.BinaryHeaderGetter; -import co.elastic.apm.agent.tracer.dispatch.BinaryHeaderSetter; -import co.elastic.apm.agent.tracer.dispatch.HeaderRemover; - -import javax.annotation.Nullable; -import java.util.HashMap; -import java.util.Map; - -public class BinaryHeaderMapAccessor implements BinaryHeaderGetter>, - BinaryHeaderSetter>, HeaderRemover> { - - public static final BinaryHeaderMapAccessor INSTANCE = new BinaryHeaderMapAccessor(); - - private final Map headerCache = new HashMap<>(); - - private BinaryHeaderMapAccessor() { - } - - @Nullable - @Override - public byte[] getFirstHeader(String headerName, Map headerMap) { - return headerMap.get(headerName); - } - - @Override - public void forEach(String headerName, Map carrier, S state, HeaderConsumer consumer) { - byte[] headerValue = carrier.get(headerName); - if (headerValue != null) { - consumer.accept(headerValue, state); - } - } - - @Nullable - @Override - public byte[] getFixedLengthByteArray(String headerName, int length) { - headerCache.computeIfAbsent(headerName, k -> new byte[TraceContext.BINARY_FORMAT_EXPECTED_LENGTH]); - return headerCache.get(headerName); - } - - @Override - public void setHeader(String headerName, byte[] headerValue, Map headerMap) { - headerMap.put(headerName, headerValue); - } - - @Override - public void remove(String headerName, Map headerMap) { - headerMap.remove(headerName); - } -} diff --git a/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/ElasticApmTracerTest.java b/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/ElasticApmTracerTest.java index baaf63d903..5283795cf5 100644 --- a/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/ElasticApmTracerTest.java +++ b/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/ElasticApmTracerTest.java @@ -20,8 +20,9 @@ import co.elastic.apm.agent.MockReporter; import co.elastic.apm.agent.common.util.WildcardMatcher; +import co.elastic.apm.agent.configuration.AutoDetectedServiceInfo; import co.elastic.apm.agent.configuration.CoreConfiguration; -import co.elastic.apm.agent.configuration.ServiceInfo; +import co.elastic.apm.agent.tracer.service.ServiceInfo; import co.elastic.apm.agent.configuration.SpyConfiguration; import co.elastic.apm.agent.configuration.source.ConfigSources; import co.elastic.apm.agent.impl.baggage.Baggage; @@ -619,7 +620,7 @@ void testNotOverrideServiceNameWhenDefaultServiceNameConfigured() { CoreConfiguration coreConfig = localConfig.getConfig(CoreConfiguration.class); - assertThat(ServiceInfo.autoDetect(System.getProperties(), System.getenv())) + assertThat(AutoDetectedServiceInfo.autoDetect(System.getProperties(), System.getenv())) .isEqualTo(ServiceInfo.of(coreConfig.getServiceName())); assertThat(reporter.getFirstTransaction().getTraceContext().getServiceName()).isNull(); diff --git a/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/Utf8HeaderMapAccessor.java b/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/Utf8HeaderMapAccessor.java new file mode 100644 index 0000000000..1c8bbd09d6 --- /dev/null +++ b/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/Utf8HeaderMapAccessor.java @@ -0,0 +1,54 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package co.elastic.apm.agent.impl; + +import co.elastic.apm.agent.tracer.dispatch.AbstractHeaderGetter; +import co.elastic.apm.agent.tracer.dispatch.HeaderRemover; +import co.elastic.apm.agent.tracer.dispatch.UTF8ByteHeaderGetter; +import co.elastic.apm.agent.tracer.dispatch.UTF8ByteHeaderSetter; + +import javax.annotation.Nullable; +import java.nio.charset.StandardCharsets; +import java.util.Map; + +public class Utf8HeaderMapAccessor extends AbstractHeaderGetter> implements + UTF8ByteHeaderGetter>, UTF8ByteHeaderSetter>, HeaderRemover> { + + public static final Utf8HeaderMapAccessor INSTANCE = new Utf8HeaderMapAccessor(); + + private Utf8HeaderMapAccessor() { + } + + @Nullable + @Override + public byte[] getFirstHeader(String headerName, Map headerMap) { + String result = headerMap.get(headerName); + return result == null ? null : result.getBytes(StandardCharsets.UTF_8); + } + + @Override + public void setHeader(String headerName, byte[] headerValue, Map headerMap) { + headerMap.put(headerName, new String(headerValue, StandardCharsets.UTF_8)); + } + + @Override + public void remove(String headerName, Map carrier) { + carrier.remove(headerName); + } +} diff --git a/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/baggage/W3CBaggagePropagationTest.java b/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/baggage/W3CBaggagePropagationTest.java index ddac6ba382..13490f3c5b 100644 --- a/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/baggage/W3CBaggagePropagationTest.java +++ b/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/baggage/W3CBaggagePropagationTest.java @@ -19,11 +19,15 @@ package co.elastic.apm.agent.impl.baggage; import co.elastic.apm.agent.impl.TextHeaderMapAccessor; +import co.elastic.apm.agent.impl.Utf8HeaderMapAccessor; import co.elastic.apm.agent.tracer.dispatch.TextHeaderGetter; +import co.elastic.apm.agent.tracer.dispatch.UTF8ByteHeaderGetter; +import org.jetbrains.annotations.NotNull; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import javax.annotation.Nullable; +import java.nio.charset.StandardCharsets; import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -43,20 +47,30 @@ public void testComplexValue() { .put("my_key!", "hello, world!?%ä=", "metadata=blub") .build(); - Map resultHeaders = new HashMap<>(); - W3CBaggagePropagation.propagate(baggage, resultHeaders, TextHeaderMapAccessor.INSTANCE); + Map resultHeaders = doPropagate(baggage); assertThat(resultHeaders) .hasSize(1) .containsEntry("baggage", "foo=bar,my_key!=hello%2C%20world!%3F%25%C3%A4%3D;metadata=blub"); } + @NotNull + private Map doPropagate(Baggage baggage) { + Map resultHeaders = new HashMap<>(); + W3CBaggagePropagation.propagate(baggage, resultHeaders, TextHeaderMapAccessor.INSTANCE); + + Map utf8Headers = new HashMap<>(); + W3CBaggagePropagation.propagate(baggage, utf8Headers, Utf8HeaderMapAccessor.INSTANCE); + assertThat(resultHeaders).isEqualTo(utf8Headers); + + return resultHeaders; + } + @Test public void testEmptyBaggage() { Baggage baggage = Baggage.builder().build(); - Map resultHeaders = new HashMap<>(); - W3CBaggagePropagation.propagate(baggage, resultHeaders, TextHeaderMapAccessor.INSTANCE); + Map resultHeaders = doPropagate(baggage); assertThat(resultHeaders).hasSize(0); } @@ -68,8 +82,7 @@ public void testInvalidKeysIgnored() { .put("bad,key", "42") .build(); - Map resultHeaders = new HashMap<>(); - W3CBaggagePropagation.propagate(baggage, resultHeaders, TextHeaderMapAccessor.INSTANCE); + Map resultHeaders = doPropagate(baggage); assertThat(resultHeaders) .hasSize(1) @@ -83,8 +96,7 @@ public void testOnlyInvalidKeys() { .put("bad,key", "42") .build(); - Map resultHeaders = new HashMap<>(); - W3CBaggagePropagation.propagate(baggage, resultHeaders, TextHeaderMapAccessor.INSTANCE); + Map resultHeaders = doPropagate(baggage); assertThat(resultHeaders).hasSize(0); } @@ -95,49 +107,79 @@ public void testOnlyInvalidKeys() { public class Parsing { @Test - public void testComplexValue() { + public void testComplexValueString() { String[] baggageHeaders = { "foo=bar,my_key!=hello%2C%20world!%3F%25%C3%A4%3D;metadata=blub,,bar=baz;override=me,foo=bar2;overridden=meta", "bar=baz2" }; - TextHeaderGetter headerGetter = new TextHeaderGetter() { - @Nullable - @Override - public String getFirstHeader(String headerName, String[] baggageHeaders) { - if (headerName.equals("baggage")) { - return baggageHeaders[0]; - } - return null; - } - - @Override - public void forEach(String headerName, String[] baggageHeaders, S state, HeaderConsumer consumer) { - if (headerName.equals("baggage")) { - for (String val : baggageHeaders) { - consumer.accept(val, state); - } - } - } - }; Baggage.Builder resultBuilder = Baggage.builder(); - W3CBaggagePropagation.parse(baggageHeaders, headerGetter, resultBuilder); + W3CBaggagePropagation.parse(baggageHeaders, new TextBaggageheaderGetter(), resultBuilder); assertThat(resultBuilder.build()) .hasSize(3) .containsEntry("my_key!", "hello, world!?%ä=", "metadata=blub") .containsEntry("bar", "baz2", null) .containsEntry("foo", "bar2", "overridden=meta"); + + Baggage.Builder utf8ResultBuilder = Baggage.builder(); + W3CBaggagePropagation.parse(baggageHeaders, new UTF8BaggageheaderGetter(), utf8ResultBuilder); + assertThat(utf8ResultBuilder.build()).isEqualTo(resultBuilder.build()); } + @Test public void testNoValue() { - Baggage.Builder resultBuilder = Baggage.builder(); - W3CBaggagePropagation.parse(Collections.emptyMap(), TextHeaderMapAccessor.INSTANCE, resultBuilder); + Baggage.Builder textResultBuilder = Baggage.builder(); + W3CBaggagePropagation.parse(Collections.emptyMap(), TextHeaderMapAccessor.INSTANCE, textResultBuilder); + assertThat(textResultBuilder.build()).hasSize(0); - assertThat(resultBuilder.build()).hasSize(0); + Baggage.Builder utf8ResultBuilder = Baggage.builder(); + W3CBaggagePropagation.parse(Collections.emptyMap(), Utf8HeaderMapAccessor.INSTANCE, utf8ResultBuilder); + assertThat(textResultBuilder.build()).hasSize(0); } } + private static class TextBaggageheaderGetter implements TextHeaderGetter { + @Nullable + @Override + public String getFirstHeader(String headerName, String[] baggageHeaders) { + if (headerName.equals("baggage")) { + return baggageHeaders[0]; + } + return null; + } + + @Override + public void forEach(String headerName, String[] baggageHeaders, S state, HeaderConsumer consumer) { + if (headerName.equals("baggage")) { + for (String val : baggageHeaders) { + consumer.accept(val, state); + } + } + } + } + + + private static class UTF8BaggageheaderGetter implements UTF8ByteHeaderGetter { + @Nullable + @Override + public byte[] getFirstHeader(String headerName, String[] baggageHeaders) { + if (headerName.equals("baggage")) { + return baggageHeaders[0].getBytes(StandardCharsets.UTF_8); + } + return null; + } + + @Override + public void forEach(String headerName, String[] baggageHeaders, S state, HeaderConsumer consumer) { + if (headerName.equals("baggage")) { + for (String val : baggageHeaders) { + consumer.accept(val.getBytes(StandardCharsets.UTF_8), state); + } + } + } + } + } diff --git a/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/metadata/CloudMetadataProviderTest.java b/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/metadata/CloudMetadataProviderTest.java index b2cd9c2399..90894e2fca 100644 --- a/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/metadata/CloudMetadataProviderTest.java +++ b/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/metadata/CloudMetadataProviderTest.java @@ -41,8 +41,8 @@ void gcpMetadataDeserializeTest() throws IOException { assertThat(gcpMetadata.getInstance().getId()).isEqualTo("4306570268266786072"); assertThat(gcpMetadata.getInstance().getName()).isEqualTo("basepi-test"); assertThat(gcpMetadata.getAccount()).isNull(); - assertThat(gcpMetadata.getProject().getId()).isEqualTo("513326162531"); - assertThat(gcpMetadata.getProject().getName()).isEqualTo("elastic-apm"); + assertThat(gcpMetadata.getProject().getId()).isEqualTo("elastic-apm"); + assertThat(gcpMetadata.getProject().getName()).isNull(); assertThat(gcpMetadata.getMachine().getType()).isEqualTo("n1-standard-1"); } diff --git a/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/transaction/AbstractCompressionStrategyTest.java b/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/transaction/AbstractCompressionStrategyTest.java index b37021c739..99c576f68b 100644 --- a/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/transaction/AbstractCompressionStrategyTest.java +++ b/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/transaction/AbstractCompressionStrategyTest.java @@ -25,12 +25,14 @@ import co.elastic.apm.agent.impl.context.ServiceTarget; import co.elastic.apm.agent.tracer.Outcome; import co.elastic.apm.agent.tracer.configuration.TimeDuration; +import co.elastic.apm.agent.tracer.dispatch.TextHeaderSetter; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.function.Consumer; import static co.elastic.apm.agent.testutils.assertions.Assertions.assertThat; @@ -195,7 +197,7 @@ void testContextPropagationStopsRegularCompression() { runInTransactionScope(t -> { startExitSpan(t).end(); Span span = startExitSpan(t); - span.propagateContext(new HashMap(), (h, v, c) -> { + span.propagateContext(new HashMap(), (TextHeaderSetter>) (h, v, c) -> { c.put(h, v); }, null); span.end(); @@ -217,7 +219,7 @@ void testContextPropagationStopsCompositeCompression() { startExitSpan(t).end(); startExitSpan(t).end(); Span span = startExitSpan(t); - span.propagateContext(new HashMap(), (h, v, c) -> { + span.propagateContext(new HashMap(), (TextHeaderSetter>) (h, v, c) -> { c.put(h, v); }, null); span.end(); diff --git a/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/transaction/CharAccessorTest.java b/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/transaction/CharAccessorTest.java new file mode 100644 index 0000000000..2cb886a729 --- /dev/null +++ b/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/transaction/CharAccessorTest.java @@ -0,0 +1,137 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package co.elastic.apm.agent.impl.transaction; + +import org.junit.jupiter.api.Named; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.nio.charset.StandardCharsets; +import java.util.function.Function; +import java.util.stream.Stream; + +import static co.elastic.apm.agent.testutils.assertions.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +public class CharAccessorTest { + + @Retention(RetentionPolicy.RUNTIME) + @ParameterizedTest(name = "{index} {0}") + @MethodSource("testArguments") + @interface TestForAllAccessors { + } + + private static Stream testArguments() { + return Stream.of( + Arguments.of(Named.of("CharSequence", CharAccessor.forCharSequence()), (Function) (input) -> input), + Arguments.of(Named.of("ascii byte[]", CharAccessor.forAsciiBytes()), (Function) (input) -> input.getBytes(StandardCharsets.US_ASCII)) + ); + } + + @TestForAllAccessors + void testLength(CharAccessor accessor, Function inputConverter) { + assertThat(accessor.length(inputConverter.apply(""))).isEqualTo(0); + assertThat(accessor.length(inputConverter.apply("abc"))).isEqualTo(3); + } + + @TestForAllAccessors + void testCharAt(CharAccessor accessor, Function inputConverter) { + T input = inputConverter.apply("abcde"); + assertThat(accessor.charAt(input, 0)).isEqualTo('a'); + assertThat(accessor.charAt(input, 2)).isEqualTo('c'); + assertThat(accessor.charAt(input, 4)).isEqualTo('e'); + assertThatThrownBy(() -> accessor.charAt(input, -1)); + assertThatThrownBy(() -> accessor.charAt(input, 5)); + } + + @TestForAllAccessors + void testAsString(CharAccessor accessor, Function inputConverter) { + assertThat(accessor.asString(inputConverter.apply(""))).isEqualTo(""); + assertThat(accessor.asString(inputConverter.apply("abc"))).isEqualTo("abc"); + } + + @TestForAllAccessors + void testHexByteDecode(CharAccessor accessor, Function inputConverter) { + assertThat(accessor.readHexByte(inputConverter.apply("0a"), 0)).isEqualTo((byte) 0x0a); + assertThat(accessor.readHexByte(inputConverter.apply("ff"), 0)).isEqualTo((byte) 0xFF); + assertThat(accessor.readHexByte(inputConverter.apply("zz23"), 2)).isEqualTo((byte) 0x23); + + assertThatThrownBy(() -> accessor.readHexByte(inputConverter.apply("ab"), -1)); + assertThatThrownBy(() -> accessor.readHexByte(inputConverter.apply("a"), 0)); + assertThatThrownBy(() -> accessor.readHexByte(inputConverter.apply("ab"), 1)); + assertThatThrownBy(() -> accessor.readHexByte(inputConverter.apply("1g"), 0)); + } + + @TestForAllAccessors + void testHexByteArrayDecode(CharAccessor accessor, Function inputConverter) { + + T input = inputConverter.apply("0123456789abcdef"); + + byte[] readFull = new byte[8]; + accessor.readHex(input, 0, readFull); + assertThat(readFull).containsExactly(0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF); + + byte[] readPartial = new byte[2]; + accessor.readHex(input, 3, readPartial); + assertThat(readPartial).containsExactly(0x34, 0x56); + + assertThatThrownBy(() -> accessor.readHex(input, 1, new byte[8])); + assertThatThrownBy(() -> accessor.readHex(input, -1, new byte[8])); + } + + @TestForAllAccessors + void testLeadingWhitespaceCounting(CharAccessor accessor, Function inputConverter) { + assertThat(accessor.getLeadingWhitespaceCount(inputConverter.apply(""))).isEqualTo(0); + assertThat(accessor.getLeadingWhitespaceCount(inputConverter.apply(" \t\r\nabcd"))).isEqualTo(4); + assertThat(accessor.getLeadingWhitespaceCount(inputConverter.apply(" a\t\r\n"))).isEqualTo(1); + assertThat(accessor.getLeadingWhitespaceCount(inputConverter.apply("a\t\r\n"))).isEqualTo(0); + } + + @TestForAllAccessors + void testTrailingWhitespaceCounting(CharAccessor accessor, Function inputConverter) { + assertThat(accessor.getTrailingWhitespaceCount(inputConverter.apply(""))).isEqualTo(0); + assertThat(accessor.getTrailingWhitespaceCount(inputConverter.apply("abcd \t\r\n"))).isEqualTo(4); + assertThat(accessor.getTrailingWhitespaceCount(inputConverter.apply("\t\r\na "))).isEqualTo(1); + assertThat(accessor.getTrailingWhitespaceCount(inputConverter.apply("\t\r\na"))).isEqualTo(0); + } + + @TestForAllAccessors + void testContainsAtOffset(CharAccessor accessor, Function inputConverter) { + + assertThat(accessor.containsAtOffset(inputConverter.apply(""), 0, "")).isTrue(); + + T abc = inputConverter.apply("abc"); + assertThat(accessor.containsAtOffset(abc, 0, "abc")).isTrue(); + assertThat(accessor.containsAtOffset(abc, 1, "bc")).isTrue(); + assertThat(accessor.containsAtOffset(abc, 0, "ab")).isTrue(); + assertThat(accessor.containsAtOffset(abc, 1, "b")).isTrue(); + + assertThat(accessor.containsAtOffset(abc, 1, "a")).isFalse(); + assertThat(accessor.containsAtOffset(abc, 1, "bcd")).isFalse(); + assertThat(accessor.containsAtOffset(abc, 0, "A")).isFalse(); + assertThat(accessor.containsAtOffset(abc, 0, "abcd")).isFalse(); + + assertThatThrownBy(() -> accessor.containsAtOffset(inputConverter.apply("a"), 2, "")); + assertThatThrownBy(() -> accessor.containsAtOffset(inputConverter.apply("a"), -1, "")); + } + +} diff --git a/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/transaction/SpanTest.java b/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/transaction/SpanTest.java index 3fea10b4c3..7b7bbae19b 100644 --- a/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/transaction/SpanTest.java +++ b/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/transaction/SpanTest.java @@ -19,9 +19,9 @@ package co.elastic.apm.agent.impl.transaction; import co.elastic.apm.agent.MockTracer; -import co.elastic.apm.agent.impl.BinaryHeaderMapAccessor; import co.elastic.apm.agent.impl.ElasticApmTracer; import co.elastic.apm.agent.impl.TextHeaderMapAccessor; +import co.elastic.apm.agent.impl.Utf8HeaderMapAccessor; import co.elastic.apm.agent.impl.baggage.Baggage; import co.elastic.apm.agent.impl.sampling.ConstantSampler; import co.elastic.apm.agent.objectpool.TestObjectPoolFactory; @@ -138,7 +138,6 @@ void testSpanLinks() { Map textTraceContextCarrier = new HashMap<>(); parent1.propagateContext(textTraceContextCarrier, TextHeaderMapAccessor.INSTANCE, null); assertThat(testSpan.addSpanLink( - TraceContext.getFromTraceContextTextHeaders(), TextHeaderMapAccessor.INSTANCE, textTraceContextCarrier) ).isTrue(); @@ -146,12 +145,11 @@ void testSpanLinks() { assertThat(objectPoolFactory.getSpanLinksPool().getRequestedObjectCount()).isEqualTo(1); assertThat(testSpan.getSpanLinks()).hasSize(1); Span parent2 = transaction.createSpan(); - Map binaryTraceContextCarrier = new HashMap<>(); - parent2.propagateContext(binaryTraceContextCarrier, BinaryHeaderMapAccessor.INSTANCE); + Map utfTraceContextCarrier = new HashMap<>(); + parent2.propagateContext(utfTraceContextCarrier, Utf8HeaderMapAccessor.INSTANCE, null); assertThat(testSpan.addSpanLink( - TraceContext.getFromTraceContextBinaryHeaders(), - BinaryHeaderMapAccessor.INSTANCE, - binaryTraceContextCarrier) + TextHeaderMapAccessor.INSTANCE, + utfTraceContextCarrier) ).isTrue(); assertThat(objectPoolFactory.getSpanLinksPool().getObjectsInPool()).isEqualTo(0); assertThat(objectPoolFactory.getSpanLinksPool().getRequestedObjectCount()).isEqualTo(2); @@ -175,13 +173,11 @@ void testSpanLinksUniqueness() { Map textTraceContextCarrier = new HashMap<>(); parent1.propagateContext(textTraceContextCarrier, TextHeaderMapAccessor.INSTANCE, null); assertThat(testSpan.addSpanLink( - TraceContext.getFromTraceContextTextHeaders(), TextHeaderMapAccessor.INSTANCE, textTraceContextCarrier) ).isTrue(); assertThat(testSpan.getSpanLinks()).hasSize(1); assertThat(testSpan.addSpanLink( - TraceContext.getFromTraceContextTextHeaders(), TextHeaderMapAccessor.INSTANCE, textTraceContextCarrier) ).isFalse(); @@ -192,7 +188,6 @@ void testSpanLinksUniqueness() { // verifying that uniqueness cache is cleared properly as well assertThat(testSpan.addSpanLink( - TraceContext.getFromTraceContextTextHeaders(), TextHeaderMapAccessor.INSTANCE, textTraceContextCarrier) ).isTrue(); diff --git a/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/transaction/TraceContextTest.java b/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/transaction/TraceContextTest.java index 2c75ccc6bc..e1f5c0a1d1 100644 --- a/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/transaction/TraceContextTest.java +++ b/apm-agent-core/src/test/java/co/elastic/apm/agent/impl/transaction/TraceContextTest.java @@ -22,16 +22,16 @@ import co.elastic.apm.agent.MockTracer; import co.elastic.apm.agent.configuration.CoreConfiguration; import co.elastic.apm.agent.configuration.SpyConfiguration; -import co.elastic.apm.agent.impl.BinaryHeaderMapAccessor; import co.elastic.apm.agent.impl.ElasticApmTracer; import co.elastic.apm.agent.impl.ElasticApmTracerBuilder; import co.elastic.apm.agent.impl.TextHeaderMapAccessor; +import co.elastic.apm.agent.impl.Utf8HeaderMapAccessor; import co.elastic.apm.agent.impl.sampling.ConstantSampler; import co.elastic.apm.agent.impl.sampling.Sampler; import co.elastic.apm.agent.objectpool.TestObjectPoolFactory; +import co.elastic.apm.agent.tracer.dispatch.HeaderGetter; +import co.elastic.apm.agent.tracer.dispatch.HeaderSetter; import co.elastic.apm.agent.tracer.metadata.PotentiallyMultiValuedMap; -import co.elastic.apm.agent.util.HexUtils; -import co.elastic.apm.agent.tracer.dispatch.BinaryHeaderSetter; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -39,9 +39,9 @@ import org.stagemonitor.configuration.ConfigurationRegistry; import javax.annotation.Nullable; +import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; -import java.util.Random; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; @@ -67,8 +67,8 @@ public void setup() { * Test flow: * 1. create a parent context from a fixed string * 2. create a child based on the string header - test {@link TraceContext#asChildOf(String)} - * 3. create a grandchild based on binary header - test {@link TraceContext#propagateTraceContext(Object, BinaryHeaderSetter)} - * and {@link TraceContext#asChildOf(byte[])} + * 3. create a grandchild based on byte[] utf8 header - test {@link TraceContext#propagateTraceContext(Object, HeaderSetter)} + * and {@link TraceContext#asChildOf(Object, HeaderGetter, boolean)} with utf8 encoded byte[]s * 4. create a second grandchild based on text header - test both {@link TraceContext#getOutgoingTraceParentTextHeader()} * and {@link TraceContext#asChildOf(String)} * @@ -78,7 +78,7 @@ public void setup() { private void mixTextAndBinaryParsingAndContextPropagation(String flagsValue, boolean isSampled) { Map textHeaderMap = Map.of(TraceContext.W3C_TRACE_PARENT_TEXTUAL_HEADER_NAME, "00-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-" + flagsValue); final TraceContext child = TraceContext.with64BitId(tracer); - assertThat(TraceContext.>getFromTraceContextTextHeaders().asChildOf(child, textHeaderMap, TextHeaderMapAccessor.INSTANCE)).isTrue(); + assertThat(child.asChildOf(textHeaderMap, TextHeaderMapAccessor.INSTANCE)).isTrue(); assertThat(child.getTraceId().toString()).isEqualTo("0af7651916cd43dd8448eb211c80319c"); assertThat(child.getParentId().toString()).isEqualTo("b9c7c989f97918e1"); assertThat(child.getId()).isNotEqualTo(child.getParentId()); @@ -86,9 +86,9 @@ private void mixTextAndBinaryParsingAndContextPropagation(String flagsValue, boo // create a grandchild to ensure proper regenerated trace context final TraceContext grandchild1 = TraceContext.with64BitId(tracer); - final Map binaryHeaderMap = new HashMap<>(); - assertThat(child.propagateTraceContext(binaryHeaderMap, BinaryHeaderMapAccessor.INSTANCE)).isTrue(); - assertThat(TraceContext.>getFromTraceContextBinaryHeaders().asChildOf(grandchild1, binaryHeaderMap, BinaryHeaderMapAccessor.INSTANCE)).isTrue(); + final Map binaryHeaderMap = new HashMap<>(); + child.propagateTraceContext(binaryHeaderMap, Utf8HeaderMapAccessor.INSTANCE); + assertThat(grandchild1.asChildOf(binaryHeaderMap, Utf8HeaderMapAccessor.INSTANCE)).isTrue(); assertThat(grandchild1.getTraceId().toString()).isEqualTo("0af7651916cd43dd8448eb211c80319c"); assertThat(grandchild1.getParentId().toString()).isEqualTo(child.getId().toString()); assertThat(grandchild1.getId()).isNotEqualTo(child.getId()); @@ -123,7 +123,7 @@ void parseFromTraceParentHeaderUnsupportedFlag() { void testChildOfElasticTraceparentHeader() { Map textHeaderMap = Map.of(TraceContext.ELASTIC_TRACE_PARENT_TEXTUAL_HEADER_NAME, "00-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01"); final TraceContext child = TraceContext.with64BitId(tracer); - assertThat(TraceContext.>getFromTraceContextTextHeaders().asChildOf(child, textHeaderMap, TextHeaderMapAccessor.INSTANCE)).isTrue(); + assertThat(child.asChildOf(textHeaderMap, TextHeaderMapAccessor.INSTANCE)).isTrue(); assertThat(child.getTraceId().toString()).isEqualTo("0af7651916cd43dd8448eb211c80319c"); assertThat(child.getParentId().toString()).isEqualTo("b9c7c989f97918e1"); assertThat(child.getId()).isNotEqualTo(child.getParentId()); @@ -137,7 +137,7 @@ void testW3CTraceparentHeaderPrecedence() { TraceContext.ELASTIC_TRACE_PARENT_TEXTUAL_HEADER_NAME, "00-dd8448eb211c80319c0af7651916cd43-f97918e1b9c7c989-01" ); final TraceContext child = TraceContext.with64BitId(tracer); - assertThat(TraceContext.>getFromTraceContextTextHeaders().asChildOf(child, textHeaderMap, TextHeaderMapAccessor.INSTANCE)).isTrue(); + assertThat(child.asChildOf(textHeaderMap, TextHeaderMapAccessor.INSTANCE)).isTrue(); assertThat(child.getTraceId().toString()).isEqualTo("0af7651916cd43dd8448eb211c80319c"); assertThat(child.getParentId().toString()).isEqualTo("b9c7c989f97918e1"); assertThat(child.getId()).isNotEqualTo(child.getParentId()); @@ -152,7 +152,7 @@ void testInvalidElasticTraceparentHeader() { TraceContext.ELASTIC_TRACE_PARENT_TEXTUAL_HEADER_NAME, "00-d8448eb211c80319c0af7651916cd43-f97918e1b9c7c989-00" ); final TraceContext child = TraceContext.with64BitId(tracer); - assertThat(TraceContext.>getFromTraceContextTextHeaders().asChildOf(child, textHeaderMap, TextHeaderMapAccessor.INSTANCE)).isTrue(); + assertThat(child.asChildOf(textHeaderMap, TextHeaderMapAccessor.INSTANCE)).isTrue(); // we should fallback to try the W3C header assertThat(child.getTraceId().toString()).isEqualTo("0af7651916cd43dd8448eb211c80319c"); assertThat(child.getParentId().toString()).isEqualTo("b9c7c989f97918e1"); @@ -164,7 +164,7 @@ void testInvalidElasticTraceparentHeader() { void testElasticTraceparentHeaderDisabled() { Map textHeaderMap = Map.of(TraceContext.W3C_TRACE_PARENT_TEXTUAL_HEADER_NAME, "00-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01"); final TraceContext child = TraceContext.with64BitId(tracer); - assertThat(TraceContext.>getFromTraceContextTextHeaders().asChildOf(child, textHeaderMap, TextHeaderMapAccessor.INSTANCE)).isTrue(); + assertThat(child.asChildOf(textHeaderMap, TextHeaderMapAccessor.INSTANCE)).isTrue(); Map outgoingHeaders = new HashMap<>(); doReturn(false).when(config.getConfig(CoreConfiguration.class)).isElasticTraceparentHeaderEnabled(); child.propagateTraceContext(outgoingHeaders, TextHeaderMapAccessor.INSTANCE); @@ -204,7 +204,7 @@ void testTracestateHeader() { incomingHeaders.add("tracestate", "foo=bar"); incomingHeaders.add("tracestate", "baz=qux,quux=quuz"); final TraceContext child = TraceContext.with64BitId(tracer); - assertThat(TraceContext.getFromTraceContextTextHeaders().asChildOf(child, incomingHeaders, MultiValueMapAccessor.INSTANCE)).isTrue(); + assertThat(child.asChildOf(incomingHeaders, MultiValueMapAccessor.INSTANCE)).isTrue(); assertThat(child.getTraceId().toString()).isEqualTo("0af7651916cd43dd8448eb211c80319c"); assertThat(child.getParentId().toString()).isEqualTo("b9c7c989f97918e1"); assertThat(child.getId()).isNotEqualTo(child.getParentId()); @@ -225,7 +225,7 @@ void testTracestateHeaderSizeLimit() { incomingHeaders.add("tracestate", "foo=bar"); incomingHeaders.add("tracestate", "baz=qux,quux=quuz"); final TraceContext child = TraceContext.with64BitId(tracer); - assertThat(TraceContext.getFromTraceContextTextHeaders().asChildOf(child, incomingHeaders, MultiValueMapAccessor.INSTANCE)).isTrue(); + assertThat(child.asChildOf(incomingHeaders, MultiValueMapAccessor.INSTANCE)).isTrue(); PotentiallyMultiValuedMap outgoingHeaders = new PotentiallyMultiValuedMap(); child.propagateTraceContext(outgoingHeaders, MultiValueMapAccessor.INSTANCE); assertThat(outgoingHeaders.size()).isEqualTo(3); @@ -242,7 +242,7 @@ void testNoTracestateWhenInvalidTraceparentHeader() { TraceContext.TRACESTATE_HEADER_NAME, "foo=bar,baz=qux" ); final TraceContext child = TraceContext.with64BitId(tracer); - assertThat(TraceContext.>getFromTraceContextTextHeaders().asChildOf(child, textHeaderMap, TextHeaderMapAccessor.INSTANCE)).isFalse(); + assertThat(child.asChildOf(textHeaderMap, TextHeaderMapAccessor.INSTANCE)).isFalse(); assertThat(child.isRecorded()).isFalse(); @@ -251,61 +251,6 @@ void testNoTracestateWhenInvalidTraceparentHeader() { assertThat(outgoingHeaders.get(TraceContext.TRACESTATE_HEADER_NAME)).isNull(); } - @Test - void testBinaryHeaderSizeEnforcement() { - final Map headerMap = Map.of(TraceContext.W3C_TRACE_PARENT_TEXTUAL_HEADER_NAME, "00-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01"); - final TraceContext child = TraceContext.with64BitId(tracer); - assertThat(TraceContext.>getFromTraceContextTextHeaders().asChildOf(child, headerMap, TextHeaderMapAccessor.INSTANCE)).isTrue(); - final byte[] outgoingBinaryHeader = new byte[TraceContext.BINARY_FORMAT_EXPECTED_LENGTH - 1]; - assertThat(child.propagateTraceContext(new HashMap<>(), new BinaryHeaderSetter>() { - @Override - public byte[] getFixedLengthByteArray(String headerName, int length) { - return outgoingBinaryHeader; - } - - @Override - public void setHeader(String headerName, byte[] headerValue, Map headerMap) { - // assert that the original byte array was not used due to its size limitation - assertThat(headerValue).isNotEqualTo(outgoingBinaryHeader); - } - })).isTrue(); - } - - @Test - void testBinaryHeaderCaching() { - final Map headerMap = Map.of(TraceContext.W3C_TRACE_PARENT_TEXTUAL_HEADER_NAME, "00-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01"); - final TraceContext child = TraceContext.with64BitId(tracer); - assertThat(TraceContext.>getFromTraceContextTextHeaders().asChildOf(child, headerMap, TextHeaderMapAccessor.INSTANCE)).isTrue(); - HashMap binaryHeaderMap = new HashMap<>(); - assertThat(child.propagateTraceContext(binaryHeaderMap, BinaryHeaderMapAccessor.INSTANCE)).isTrue(); - byte[] outgoingHeader = binaryHeaderMap.get(TraceContext.ELASTIC_TRACE_PARENT_TEXTUAL_HEADER_NAME); - assertThat(child.propagateTraceContext(binaryHeaderMap, BinaryHeaderMapAccessor.INSTANCE)).isTrue(); - assertThat(binaryHeaderMap.get(TraceContext.ELASTIC_TRACE_PARENT_TEXTUAL_HEADER_NAME)).isSameAs(outgoingHeader); - } - - @Test - void testBinaryHeader_CachingDisabled() { - final Map headerMap = Map.of(TraceContext.W3C_TRACE_PARENT_TEXTUAL_HEADER_NAME, "00-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01"); - final TraceContext child = TraceContext.with64BitId(tracer); - assertThat(TraceContext.>getFromTraceContextTextHeaders().asChildOf(child, headerMap, TextHeaderMapAccessor.INSTANCE)).isTrue(); - BinaryHeaderSetter> headerSetter = new BinaryHeaderSetter<>() { - @Override - public byte[] getFixedLengthByteArray(String headerName, int length) { - return null; - } - - @Override - public void setHeader(String headerName, byte[] headerValue, Map headerMap) { - headerMap.put(headerName, headerValue); - } - }; - HashMap binaryHeaderMap = new HashMap<>(); - assertThat(child.propagateTraceContext(binaryHeaderMap, headerSetter)).isTrue(); - byte[] outgoingHeader = binaryHeaderMap.get(TraceContext.ELASTIC_TRACE_PARENT_TEXTUAL_HEADER_NAME); - assertThat(child.propagateTraceContext(binaryHeaderMap, headerSetter)).isTrue(); - assertThat(binaryHeaderMap.get(TraceContext.ELASTIC_TRACE_PARENT_TEXTUAL_HEADER_NAME)).isNotSameAs(outgoingHeader); - } - private void verifyTraceContextContents(String traceContext, String expectedTraceId, String expectedParentId, String expectedVersion, String expectedFlags) { String[] parts = traceContext.split("-"); @@ -315,21 +260,6 @@ private void verifyTraceContextContents(String traceContext, String expectedTrac assertThat(parts[3]).isEqualTo(expectedFlags); } - private void verifyTraceContextContents(byte[] traceContext, String expectedTraceId, String expectedParentId, - byte expectedVersion, byte expectedFlags) { - assertThat(traceContext[0]).isEqualTo(expectedVersion); - assertThat(traceContext[1]).isEqualTo((byte) 0b0000_0000); - StringBuilder sb = new StringBuilder(); - HexUtils.writeBytesAsHex(traceContext, 2, 16, sb); - assertThat(sb.toString()).isEqualTo(expectedTraceId); - assertThat(traceContext[18]).isEqualTo((byte) 0b0000_0001); - sb.setLength(0); - HexUtils.writeBytesAsHex(traceContext, 19, 8, sb); - assertThat(sb.toString()).isEqualTo(expectedParentId); - assertThat(traceContext[27]).isEqualTo((byte) 0b0000_0010); - assertThat(traceContext[28]).isEqualTo(expectedFlags); - } - @Test void outgoingHeader() { final TraceContext traceContext = TraceContext.with64BitId(tracer); @@ -338,10 +268,10 @@ void outgoingHeader() { String parentId = traceContext.getId().toString(); verifyTraceContextContents(traceContext.getOutgoingTraceParentTextHeader().toString(), "0af7651916cd43dd8448eb211c80319c", parentId, "00", "03"); - Map headerMap = new HashMap<>(); - assertThat(traceContext.propagateTraceContext(headerMap, BinaryHeaderMapAccessor.INSTANCE)).isTrue(); + Map headerMap = new HashMap<>(); + traceContext.propagateTraceContext(headerMap, Utf8HeaderMapAccessor.INSTANCE); verifyTraceContextContents(headerMap.get(TraceContext.ELASTIC_TRACE_PARENT_TEXTUAL_HEADER_NAME), - "0af7651916cd43dd8448eb211c80319c", parentId, (byte) 0x00, (byte) 0x03); + "0af7651916cd43dd8448eb211c80319c", parentId, "00", "03"); } @Test @@ -353,10 +283,10 @@ void outgoingHeaderRootSpan() { assertThat(outgoingStringHeader).hasSize(55); verifyTraceContextContents(outgoingStringHeader, traceContext.getTraceId().toString(), traceContext.getId().toString(), "00", "01"); - Map headerMap = new HashMap<>(); - assertThat(traceContext.propagateTraceContext(headerMap, BinaryHeaderMapAccessor.INSTANCE)).isTrue(); + Map headerMap = new HashMap<>(); + traceContext.propagateTraceContext(headerMap, Utf8HeaderMapAccessor.INSTANCE); verifyTraceContextContents(headerMap.get(TraceContext.ELASTIC_TRACE_PARENT_TEXTUAL_HEADER_NAME), traceContext.getTraceId().toString(), - traceContext.getId().toString(), (byte) 0x00, (byte) 0x01); + traceContext.getId().toString(), "00", "01"); } @Test @@ -384,23 +314,6 @@ void testResetOutgoingTextHeader() { assertThat(traceContext.getOutgoingTraceParentTextHeader().toString()).isNotEqualTo(traceParentHeader); } - @Test - void testResetOutgoingBinaryHeader() { - final TraceContext traceContext = TraceContext.with64BitId(tracer); - Map headerMap = new HashMap<>(); - assertThat(traceContext.propagateTraceContext(headerMap, BinaryHeaderMapAccessor.INSTANCE)).isTrue(); - byte[] outgoingByteHeader = headerMap.get(TraceContext.ELASTIC_TRACE_PARENT_TEXTUAL_HEADER_NAME); - byte[] tmp = new byte[outgoingByteHeader.length]; - System.arraycopy(outgoingByteHeader, 0, tmp, 0, outgoingByteHeader.length); - traceContext.asChildOf("00-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-00"); - assertThat(traceContext.propagateTraceContext(headerMap, BinaryHeaderMapAccessor.INSTANCE)).isTrue(); - // relies on the byte array caching in BinaryHeaderMapAccessor - assertThat(outgoingByteHeader).isNotEqualTo(tmp); - traceContext.resetState(); - assertThat(traceContext.propagateTraceContext(headerMap, BinaryHeaderMapAccessor.INSTANCE)).isTrue(); - assertThat(outgoingByteHeader).isEqualTo(tmp); - } - @Test void testCopyFrom() { Map textHeaderMap = Map.of( @@ -408,23 +321,20 @@ void testCopyFrom() { TraceContext.TRACESTATE_HEADER_NAME, "foo=bar,baz=qux" ); final TraceContext first = TraceContext.with64BitId(tracer); - assertThat(TraceContext.>getFromTraceContextTextHeaders().asChildOf(first, textHeaderMap, TextHeaderMapAccessor.INSTANCE)).isTrue(); + assertThat(first.asChildOf(textHeaderMap, TextHeaderMapAccessor.INSTANCE)).isTrue(); textHeaderMap = Map.of(TraceContext.ELASTIC_TRACE_PARENT_TEXTUAL_HEADER_NAME, "00-8448ebb9c7c989f97918e11916cd43dd-211c80319c0af765-00"); final TraceContext second = TraceContext.with64BitId(tracer); - assertThat(TraceContext.>getFromTraceContextTextHeaders().asChildOf(second, textHeaderMap, TextHeaderMapAccessor.INSTANCE)).isTrue(); + assertThat(second.asChildOf(textHeaderMap, TextHeaderMapAccessor.INSTANCE)).isTrue(); assertThat(first.getTraceId()).isNotEqualTo(second.getTraceId()); assertThat(first.getParentId()).isNotEqualTo(second.getParentId()); assertThat(first.isSampled()).isNotEqualTo(second.isSampled()); assertThat(first.getOutgoingTraceParentTextHeader()).isNotEqualTo(second.getOutgoingTraceParentTextHeader()); - Map binaryHeaderMap = new HashMap<>(); - first.propagateTraceContext(binaryHeaderMap, BinaryHeaderMapAccessor.INSTANCE); - byte[] outgoingHeader = binaryHeaderMap.get(TraceContext.ELASTIC_TRACE_PARENT_TEXTUAL_HEADER_NAME); - // We must copy because of the byte array caching in BinaryHeaderMapAccessor - byte[] firstOutgoingHeader = new byte[outgoingHeader.length]; - System.arraycopy(outgoingHeader, 0, firstOutgoingHeader, 0, outgoingHeader.length); - second.propagateTraceContext(binaryHeaderMap, BinaryHeaderMapAccessor.INSTANCE); + Map binaryHeaderMap = new HashMap<>(); + first.propagateTraceContext(binaryHeaderMap, Utf8HeaderMapAccessor.INSTANCE); + String firstOutgoingHeader = binaryHeaderMap.get(TraceContext.ELASTIC_TRACE_PARENT_TEXTUAL_HEADER_NAME); + second.propagateTraceContext(binaryHeaderMap, Utf8HeaderMapAccessor.INSTANCE); assertThat(binaryHeaderMap.get(TraceContext.ELASTIC_TRACE_PARENT_TEXTUAL_HEADER_NAME)).isNotEqualTo(firstOutgoingHeader); second.copyFrom(first); @@ -432,7 +342,7 @@ void testCopyFrom() { assertThat(first.getParentId()).isEqualTo(second.getParentId()); assertThat(first.isSampled()).isEqualTo(second.isSampled()); assertThat(first.getOutgoingTraceParentTextHeader().toString()).isEqualTo(second.getOutgoingTraceParentTextHeader().toString()); - second.propagateTraceContext(binaryHeaderMap, BinaryHeaderMapAccessor.INSTANCE); + second.propagateTraceContext(binaryHeaderMap, Utf8HeaderMapAccessor.INSTANCE); assertThat(binaryHeaderMap.get(TraceContext.ELASTIC_TRACE_PARENT_TEXTUAL_HEADER_NAME)).isEqualTo(firstOutgoingHeader); } @@ -443,7 +353,7 @@ void testAsChildOfHeaders() { TraceContext.TRACESTATE_HEADER_NAME, "foo=bar,baz=qux" ); final TraceContext first = TraceContext.with64BitId(tracer); - assertThat(TraceContext.>getFromTraceContextTextHeaders().asChildOf(first, textHeaderMap, TextHeaderMapAccessor.INSTANCE)).isTrue(); + assertThat(first.asChildOf(textHeaderMap, TextHeaderMapAccessor.INSTANCE)).isTrue(); final TraceContext second = TraceContext.with64BitId(tracer); second.asChildOf(first); @@ -452,6 +362,15 @@ void testAsChildOfHeaders() { second.propagateTraceContext(textHeaders, TextHeaderMapAccessor.INSTANCE); assertThat(textHeaders.get(TraceContext.TRACESTATE_HEADER_NAME)).isEqualTo("foo=bar,baz=qux"); assertThat(textHeaders.get(TraceContext.W3C_TRACE_PARENT_TEXTUAL_HEADER_NAME)).startsWith("00-0af7651916cd43dd8448eb211c80319c-"); + + + final TraceContext firstUtf8 = TraceContext.with64BitId(tracer); + assertThat(firstUtf8.asChildOf(textHeaderMap, Utf8HeaderMapAccessor.INSTANCE)).isTrue(); + + HashMap utf8Headers = new HashMap<>(); + firstUtf8.propagateTraceContext(utf8Headers, Utf8HeaderMapAccessor.INSTANCE); + assertThat(utf8Headers.get(TraceContext.TRACESTATE_HEADER_NAME)).isEqualTo("foo=bar,baz=qux"); + assertThat(utf8Headers.get(TraceContext.W3C_TRACE_PARENT_TEXTUAL_HEADER_NAME)).startsWith("00-0af7651916cd43dd8448eb211c80319c-"); } @Test @@ -568,7 +487,7 @@ void checkExpectedSampleRate(@Nullable String traceState, double expectedRate, @ private TraceContext createChildSpanFromHeaders(Map inHeaders) { TraceContext child = TraceContext.with64BitId(tracer); - assertThat(TraceContext.>getFromTraceContextTextHeaders().asChildOf(child, inHeaders, TextHeaderMapAccessor.INSTANCE)).isTrue(); + assertThat(child.asChildOf(inHeaders, TextHeaderMapAccessor.INSTANCE)).isTrue(); return child; } @@ -582,10 +501,10 @@ void testPropagateTransactionIdForUnsampledSpan() { verifyTraceContextContents(childContext.getOutgoingTraceParentTextHeader().toString(), childContext.getTraceId().toString(), rootContext.getId().toString(), "00", "00"); - Map binaryHeaderMap = new HashMap<>(); - childContext.propagateTraceContext(binaryHeaderMap, BinaryHeaderMapAccessor.INSTANCE); + Map binaryHeaderMap = new HashMap<>(); + childContext.propagateTraceContext(binaryHeaderMap, Utf8HeaderMapAccessor.INSTANCE); verifyTraceContextContents(binaryHeaderMap.get(TraceContext.ELASTIC_TRACE_PARENT_TEXTUAL_HEADER_NAME), - childContext.getTraceId().toString(), rootContext.getId().toString(), (byte) 0x00, (byte) 0x00); + childContext.getTraceId().toString(), rootContext.getId().toString(), "00", "00"); } @Test @@ -598,10 +517,10 @@ void testPropagateSpanIdForSampledSpan() { verifyTraceContextContents(childContext.getOutgoingTraceParentTextHeader().toString(), childContext.getTraceId().toString(), childContext.getId().toString(), "00", "01"); - Map binaryHeaderMap = new HashMap<>(); - childContext.propagateTraceContext(binaryHeaderMap, BinaryHeaderMapAccessor.INSTANCE); + Map binaryHeaderMap = new HashMap<>(); + childContext.propagateTraceContext(binaryHeaderMap, Utf8HeaderMapAccessor.INSTANCE); verifyTraceContextContents(binaryHeaderMap.get(TraceContext.ELASTIC_TRACE_PARENT_TEXTUAL_HEADER_NAME), - childContext.getTraceId().toString(), childContext.getId().toString(), (byte) 0x00, (byte) 0x01); + childContext.getTraceId().toString(), childContext.getId().toString(), "00", "01"); } @Test @@ -621,21 +540,12 @@ void testRootContextSampleRateFromSampler() { void testUnknownVersion() { String testTextHeader = "42-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01"; assertValid(testTextHeader); - assertValid(convertToBinary(testTextHeader)); } @Test void testUnknownExtraStuff() { String testTextHeader = "42-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01-unknown-extra-stuff"; assertValid(testTextHeader); - - byte[] header = convertToBinary(testTextHeader); - byte[] withExtra = new byte[40]; - for (int i = header.length; i < withExtra.length; i++) { - new Random().nextBytes(withExtra); - } - System.arraycopy(header, 0, withExtra, 0, header.length); - assertValid(withExtra); } // If a traceparent header is invalid, ignore it and create a new root context @@ -644,14 +554,12 @@ void testUnknownExtraStuff() { void testInvalidHeader_traceIdAllZeroes() { String testTextHeader = "00-00000000000000000000000000000000-b9c7c989f97918e1-00"; assertInvalid(testTextHeader); - assertInvalid(convertToBinary(testTextHeader)); } @Test void testInvalidHeader_spanIdAllZeroes() { String testTextHeader = "00-0af7651916cd43dd8448eb211c80319c-0000000000000000-00"; assertInvalid(testTextHeader); - assertInvalid(convertToBinary(testTextHeader)); } @Test @@ -677,39 +585,19 @@ void testInvalidHeader_invalidTotalLength() { private void assertInvalid(String s) { final TraceContext traceContext = TraceContext.with64BitId(tracer); assertThat(traceContext.asChildOf(s)).isFalse(); - } - - private void assertInvalid(byte[] binaryHeader) { - final TraceContext traceContext = TraceContext.with64BitId(tracer); - assertThat(traceContext.asChildOf(binaryHeader)).isFalse(); + assertThat(traceContext.asChildOf(s.getBytes(StandardCharsets.UTF_8), CharAccessor.forAsciiBytes())).isFalse(); } private void assertValid(String s) { - final TraceContext traceContext = TraceContext.with64BitId(tracer); - assertThat(traceContext.asChildOf(s)).isTrue(); - verifyTraceContextContents(traceContext.getOutgoingTraceParentTextHeader().toString(), - traceContext.getTraceId().toString(), traceContext.getId().toString(), "00", s.substring(53, 55)); - } - - private void assertValid(byte[] binaryHeader) { - final TraceContext traceContext = TraceContext.with64BitId(tracer); - assertThat(traceContext.asChildOf(binaryHeader)).isTrue(); - Map binaryHeaderMap = new HashMap<>(); - traceContext.propagateTraceContext(binaryHeaderMap, BinaryHeaderMapAccessor.INSTANCE); - verifyTraceContextContents(binaryHeaderMap.get(TraceContext.ELASTIC_TRACE_PARENT_TEXTUAL_HEADER_NAME), - traceContext.getTraceId().toString(), traceContext.getId().toString(), (byte) 0x00, binaryHeader[28]); - } - - private byte[] convertToBinary(String textHeader) { - final TraceContext traceContext = TraceContext.with64BitId(tracer); - traceContext.asChildOf(textHeader); - Map binaryHeaderMap = new HashMap<>(); - traceContext.propagateTraceContext(binaryHeaderMap, BinaryHeaderMapAccessor.INSTANCE); - byte[] binaryHeader = binaryHeaderMap.get(TraceContext.ELASTIC_TRACE_PARENT_TEXTUAL_HEADER_NAME); - // replace the version and parent ID - HexUtils.decode(textHeader, 0, 2, binaryHeader, 0); - HexUtils.decode(textHeader, 36, 16, binaryHeader, 19); - return binaryHeader; + TraceContext textTraceContext = TraceContext.with64BitId(tracer); + assertThat(textTraceContext.asChildOf(s)).isTrue(); + verifyTraceContextContents(textTraceContext.getOutgoingTraceParentTextHeader().toString(), + textTraceContext.getTraceId().toString(), textTraceContext.getId().toString(), "00", s.substring(53, 55)); + + TraceContext utf8TraceContext = TraceContext.with64BitId(tracer); + assertThat(utf8TraceContext.asChildOf(s.getBytes(StandardCharsets.UTF_8), CharAccessor.forAsciiBytes())).isTrue(); + verifyTraceContextContents(utf8TraceContext.getOutgoingTraceParentTextHeader().toString(), + utf8TraceContext.getTraceId().toString(), utf8TraceContext.getId().toString(), "00", s.substring(53, 55)); } @Test diff --git a/apm-agent-core/src/test/java/co/elastic/apm/agent/report/serialize/DslJsonSerializerTest.java b/apm-agent-core/src/test/java/co/elastic/apm/agent/report/serialize/DslJsonSerializerTest.java index c5608ec0dd..86def7f803 100644 --- a/apm-agent-core/src/test/java/co/elastic/apm/agent/report/serialize/DslJsonSerializerTest.java +++ b/apm-agent-core/src/test/java/co/elastic/apm/agent/report/serialize/DslJsonSerializerTest.java @@ -23,7 +23,6 @@ import co.elastic.apm.agent.configuration.CoreConfiguration; import co.elastic.apm.agent.configuration.ServerlessConfiguration; import co.elastic.apm.agent.configuration.SpyConfiguration; -import co.elastic.apm.agent.impl.BinaryHeaderMapAccessor; import co.elastic.apm.agent.impl.ElasticApmTracer; import co.elastic.apm.agent.impl.TextHeaderMapAccessor; import co.elastic.apm.agent.impl.Tracer; @@ -1565,11 +1564,11 @@ void testSpanLinksSerialization() { Span parent1 = Objects.requireNonNull(transaction).createSpan(); Map textTraceContextCarrier = new HashMap<>(); parent1.propagateContext(textTraceContextCarrier, TextHeaderMapAccessor.INSTANCE, null); - transaction.addSpanLink(TraceContext.getFromTraceContextTextHeaders(), TextHeaderMapAccessor.INSTANCE, textTraceContextCarrier); + transaction.addSpanLink(TextHeaderMapAccessor.INSTANCE, textTraceContextCarrier); Span parent2 = transaction.createSpan(); - Map binaryTraceContextCarrier = new HashMap<>(); - parent2.propagateContext(binaryTraceContextCarrier, BinaryHeaderMapAccessor.INSTANCE); - transaction.addSpanLink(TraceContext.getFromTraceContextBinaryHeaders(), BinaryHeaderMapAccessor.INSTANCE, binaryTraceContextCarrier); + Map binaryTraceContextCarrier = new HashMap<>(); + parent2.propagateContext(binaryTraceContextCarrier, TextHeaderMapAccessor.INSTANCE, null); + transaction.addSpanLink(TextHeaderMapAccessor.INSTANCE, binaryTraceContextCarrier); JsonNode transactionJson = readJsonString(writer.toJsonString(transaction)); JsonNode spanLinks = transactionJson.get("links"); assertThat(spanLinks).isNotNull(); diff --git a/apm-agent-core/src/test/java/co/elastic/apm/agent/report/serialize/HexSerializationUtilsTest.java b/apm-agent-core/src/test/java/co/elastic/apm/agent/report/serialize/HexSerializationUtilsTest.java new file mode 100644 index 0000000000..f32fed39c4 --- /dev/null +++ b/apm-agent-core/src/test/java/co/elastic/apm/agent/report/serialize/HexSerializationUtilsTest.java @@ -0,0 +1,40 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package co.elastic.apm.agent.report.serialize; + +import co.elastic.apm.agent.tracer.util.HexUtils; +import co.elastic.apm.agent.util.ByteUtils; +import com.dslplatform.json.DslJson; +import com.dslplatform.json.JsonWriter; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class HexSerializationUtilsTest { + + @Test + void testLongToHex() { + byte[] bytes = new byte[8]; + HexUtils.nextBytes("09c2572177fdae24", 0, bytes); + long l = ByteUtils.getLong(bytes, 0); + JsonWriter jw = new DslJson<>().newWriter(); + HexSerializationUtils.writeAsHex(l, jw); + assertThat(jw.toString()).isEqualTo("09c2572177fdae24"); + } +} diff --git a/apm-agent-core/src/test/java/co/elastic/apm/agent/report/serialize/MetricRegistryReporterTest.java b/apm-agent-core/src/test/java/co/elastic/apm/agent/report/serialize/MetricRegistryReporterTest.java index 6f646b0bc5..2ae1bd60f4 100644 --- a/apm-agent-core/src/test/java/co/elastic/apm/agent/report/serialize/MetricRegistryReporterTest.java +++ b/apm-agent-core/src/test/java/co/elastic/apm/agent/report/serialize/MetricRegistryReporterTest.java @@ -19,7 +19,7 @@ package co.elastic.apm.agent.report.serialize; import co.elastic.apm.agent.MockReporter; -import co.elastic.apm.agent.configuration.ServiceInfo; +import co.elastic.apm.agent.tracer.service.ServiceInfo; import co.elastic.apm.agent.configuration.SpyConfiguration; import co.elastic.apm.agent.impl.ElasticApmTracer; import co.elastic.apm.agent.impl.ElasticApmTracerBuilder; diff --git a/apm-agent-core/src/test/java/co/elastic/apm/agent/report/serialize/MetricSetSerializationTest.java b/apm-agent-core/src/test/java/co/elastic/apm/agent/report/serialize/MetricSetSerializationTest.java index 0f56c650da..7f696af5f1 100644 --- a/apm-agent-core/src/test/java/co/elastic/apm/agent/report/serialize/MetricSetSerializationTest.java +++ b/apm-agent-core/src/test/java/co/elastic/apm/agent/report/serialize/MetricSetSerializationTest.java @@ -19,7 +19,7 @@ package co.elastic.apm.agent.report.serialize; import co.elastic.apm.agent.configuration.MetricsConfiguration; -import co.elastic.apm.agent.configuration.ServiceInfo; +import co.elastic.apm.agent.tracer.service.ServiceInfo; import co.elastic.apm.agent.metrics.Labels; import co.elastic.apm.agent.metrics.MetricCollector; import co.elastic.apm.agent.metrics.MetricRegistry; diff --git a/apm-agent-core/src/test/java/co/elastic/apm/agent/tracemethods/TraceMethodInstrumentationTest.java b/apm-agent-core/src/test/java/co/elastic/apm/agent/tracemethods/TraceMethodInstrumentationTest.java index 4b7a49168e..393e2cce56 100644 --- a/apm-agent-core/src/test/java/co/elastic/apm/agent/tracemethods/TraceMethodInstrumentationTest.java +++ b/apm-agent-core/src/test/java/co/elastic/apm/agent/tracemethods/TraceMethodInstrumentationTest.java @@ -30,6 +30,7 @@ import co.elastic.apm.agent.matcher.MethodMatcher; import co.elastic.apm.agent.objectpool.TestObjectPoolFactory; import co.elastic.apm.agent.tracer.configuration.TimeDuration; +import co.elastic.apm.agent.tracer.dispatch.TextHeaderSetter; import net.bytebuddy.agent.ByteBuddyAgent; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -352,7 +353,7 @@ private void manuallyTraced() { AbstractSpan active = tracer.getActive(); if (active != null) { Span span = active.createSpan(); - span.propagateContext(new HashMap<>(), (k, v, m) -> m.put(k, v), null); + span.propagateContext(new HashMap<>(), (TextHeaderSetter>) (k, v, m) -> m.put(k, v), null); span.end(); } } diff --git a/apm-agent-lambda-layer/pom.xml b/apm-agent-lambda-layer/pom.xml index 0a5d2240e3..5df205d539 100644 --- a/apm-agent-lambda-layer/pom.xml +++ b/apm-agent-lambda-layer/pom.xml @@ -3,7 +3,7 @@ apm-agent-parent co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/apm-agent-plugin-sdk/pom.xml b/apm-agent-plugin-sdk/pom.xml index cb728ea3c4..efce6e9469 100644 --- a/apm-agent-plugin-sdk/pom.xml +++ b/apm-agent-plugin-sdk/pom.xml @@ -3,7 +3,7 @@ apm-agent-parent co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/apm-agent-plugins/apm-apache-httpclient/apm-apache-httpclient3-plugin/pom.xml b/apm-agent-plugins/apm-apache-httpclient/apm-apache-httpclient3-plugin/pom.xml index 0903cc77c5..1446d2a56a 100644 --- a/apm-agent-plugins/apm-apache-httpclient/apm-apache-httpclient3-plugin/pom.xml +++ b/apm-agent-plugins/apm-apache-httpclient/apm-apache-httpclient3-plugin/pom.xml @@ -5,7 +5,7 @@ apm-apache-httpclient co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-apache-httpclient3-plugin diff --git a/apm-agent-plugins/apm-apache-httpclient/apm-apache-httpclient4-plugin/pom.xml b/apm-agent-plugins/apm-apache-httpclient/apm-apache-httpclient4-plugin/pom.xml index 9ccecb0af0..929950cde3 100644 --- a/apm-agent-plugins/apm-apache-httpclient/apm-apache-httpclient4-plugin/pom.xml +++ b/apm-agent-plugins/apm-apache-httpclient/apm-apache-httpclient4-plugin/pom.xml @@ -5,7 +5,7 @@ apm-apache-httpclient co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-apache-httpclient4-plugin diff --git a/apm-agent-plugins/apm-apache-httpclient/pom.xml b/apm-agent-plugins/apm-apache-httpclient/pom.xml index cbd2ee8746..2cc33d4868 100644 --- a/apm-agent-plugins/apm-apache-httpclient/pom.xml +++ b/apm-agent-plugins/apm-apache-httpclient/pom.xml @@ -5,7 +5,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-apache-httpclient diff --git a/apm-agent-plugins/apm-api-plugin/README.md b/apm-agent-plugins/apm-api-plugin/README.md index 1670d7f4d3..199c7c45ee 100644 --- a/apm-agent-plugins/apm-api-plugin/README.md +++ b/apm-agent-plugins/apm-api-plugin/README.md @@ -19,7 +19,7 @@ as the API could end up twice on the classpath. The consequence is that neither the API nor the agent can access each other's classes. -That's why yhe API module (`apm-agent-api`) users declare a dependency on is implemented as a noop. +That's why the API module (`apm-agent-api`) users declare a dependency on is implemented as a noop. If the agent is active (`-javaagent` JVM flag set), diff --git a/apm-agent-plugins/apm-api-plugin/pom.xml b/apm-agent-plugins/apm-api-plugin/pom.xml index e620175ce4..8d4ad6f605 100644 --- a/apm-agent-plugins/apm-api-plugin/pom.xml +++ b/apm-agent-plugins/apm-api-plugin/pom.xml @@ -5,7 +5,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT diff --git a/apm-agent-plugins/apm-api-plugin/src/main/java/co/elastic/apm/agent/pluginapi/CaptureExceptionInstrumentation.java b/apm-agent-plugins/apm-api-plugin/src/main/java/co/elastic/apm/agent/pluginapi/CaptureExceptionInstrumentation.java index 7d7f1f179d..4afe5ef561 100644 --- a/apm-agent-plugins/apm-api-plugin/src/main/java/co/elastic/apm/agent/pluginapi/CaptureExceptionInstrumentation.java +++ b/apm-agent-plugins/apm-api-plugin/src/main/java/co/elastic/apm/agent/pluginapi/CaptureExceptionInstrumentation.java @@ -18,8 +18,8 @@ */ package co.elastic.apm.agent.pluginapi; -import co.elastic.apm.agent.impl.Tracer; import co.elastic.apm.agent.sdk.internal.util.PrivilegedActionUtils; +import co.elastic.apm.agent.tracer.ErrorCapture; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.type.TypeDescription; @@ -33,7 +33,10 @@ public class CaptureExceptionInstrumentation extends ApiInstrumentation { public static class AdviceClass { @Advice.OnMethodEnter(suppress = Throwable.class, inline = false) public static void captureException(@Advice.Origin Class clazz, @Advice.Argument(0) Throwable t) { - tracer.require(Tracer.class).captureAndReportException(t, PrivilegedActionUtils.getClassLoader(clazz)); + ErrorCapture errorCapture = tracer.captureException(t, PrivilegedActionUtils.getClassLoader(clazz)); + if (errorCapture != null) { + errorCapture.end(); + } } } diff --git a/apm-agent-plugins/apm-api-plugin/src/main/java/co/elastic/apm/agent/pluginapi/ElasticApmApiInstrumentation.java b/apm-agent-plugins/apm-api-plugin/src/main/java/co/elastic/apm/agent/pluginapi/ElasticApmApiInstrumentation.java index 105d55a0c7..7723217d1c 100644 --- a/apm-agent-plugins/apm-api-plugin/src/main/java/co/elastic/apm/agent/pluginapi/ElasticApmApiInstrumentation.java +++ b/apm-agent-plugins/apm-api-plugin/src/main/java/co/elastic/apm/agent/pluginapi/ElasticApmApiInstrumentation.java @@ -18,9 +18,11 @@ */ package co.elastic.apm.agent.pluginapi; -import co.elastic.apm.agent.configuration.ServiceInfo; +import co.elastic.apm.agent.tracer.service.ServiceAwareTracer; +import co.elastic.apm.agent.tracer.service.ServiceInfo; import co.elastic.apm.agent.impl.ElasticApmTracer; import co.elastic.apm.agent.impl.Tracer; +import co.elastic.apm.agent.tracer.ErrorCapture; import co.elastic.apm.agent.tracer.GlobalTracer; import co.elastic.apm.agent.tracer.Transaction; import co.elastic.apm.agent.sdk.internal.util.PrivilegedActionUtils; @@ -149,7 +151,10 @@ public CaptureExceptionInstrumentation() { public static class AdviceClass { @Advice.OnMethodEnter(suppress = Throwable.class, inline = false) public static void captureException(@Advice.Origin Class clazz, @Advice.Argument(0) @Nullable Throwable e) { - tracer.require(Tracer.class).captureAndReportException(e, PrivilegedActionUtils.getClassLoader(clazz)); + ErrorCapture errorCapture = tracer.captureException(e, PrivilegedActionUtils.getClassLoader(clazz)); + if (errorCapture != null) { + errorCapture.end(); + } } } } @@ -162,7 +167,7 @@ public SetServiceInfoForClassLoaderInstrumentation() { public static class AdviceClass { @Advice.OnMethodExit(suppress = Throwable.class, inline = false) public static void setServiceInfoForClassLoader(@Advice.Argument(0) @Nullable ClassLoader classLoader, @Advice.Argument(1) String serviceName, @Advice.Argument(2) @Nullable String serviceVersion) { - tracer.require(Tracer.class).setServiceInfoForClassLoader(classLoader, ServiceInfo.of(serviceName, serviceVersion)); + tracer.require(ServiceAwareTracer.class).setServiceInfoForClassLoader(classLoader, ServiceInfo.of(serviceName, serviceVersion)); } } } diff --git a/apm-agent-plugins/apm-api-plugin/src/main/java/co/elastic/apm/agent/pluginapi/TransactionInstrumentation.java b/apm-agent-plugins/apm-api-plugin/src/main/java/co/elastic/apm/agent/pluginapi/TransactionInstrumentation.java index b74dfc1582..e6ce5c97a8 100644 --- a/apm-agent-plugins/apm-api-plugin/src/main/java/co/elastic/apm/agent/pluginapi/TransactionInstrumentation.java +++ b/apm-agent-plugins/apm-api-plugin/src/main/java/co/elastic/apm/agent/pluginapi/TransactionInstrumentation.java @@ -18,7 +18,8 @@ */ package co.elastic.apm.agent.pluginapi; -import co.elastic.apm.agent.configuration.ServiceInfo; +import co.elastic.apm.agent.tracer.service.ServiceAwareTracer; +import co.elastic.apm.agent.tracer.service.ServiceInfo; import co.elastic.apm.agent.impl.Tracer; import co.elastic.apm.agent.impl.transaction.Id; import co.elastic.apm.agent.impl.transaction.TraceContext; @@ -176,7 +177,7 @@ public static class AdviceClass { public static void useServiceInfoForClassLoader(@Advice.FieldValue(value = "span", typing = Assigner.Typing.DYNAMIC) Object transaction, @Advice.Argument(0) ClassLoader classLoader) { if (transaction instanceof Transaction) { - ServiceInfo serviceInfo = tracer.require(Tracer.class).getServiceInfoForClassLoader(classLoader); + ServiceInfo serviceInfo = tracer.require(ServiceAwareTracer.class).getServiceInfoForClassLoader(classLoader); if (serviceInfo != null) { ((Transaction) transaction).getTraceContext().setServiceInfo(serviceInfo.getServiceName(), serviceInfo.getServiceVersion()); } diff --git a/apm-agent-plugins/apm-api-plugin/src/test/java/co/elastic/apm/agent/pluginapi/TransactionInstrumentationTest.java b/apm-agent-plugins/apm-api-plugin/src/test/java/co/elastic/apm/agent/pluginapi/TransactionInstrumentationTest.java index cabb1fd282..50333280b9 100644 --- a/apm-agent-plugins/apm-api-plugin/src/test/java/co/elastic/apm/agent/pluginapi/TransactionInstrumentationTest.java +++ b/apm-agent-plugins/apm-api-plugin/src/test/java/co/elastic/apm/agent/pluginapi/TransactionInstrumentationTest.java @@ -19,7 +19,7 @@ package co.elastic.apm.agent.pluginapi; import co.elastic.apm.AbstractApiTest; -import co.elastic.apm.agent.configuration.ServiceInfo; +import co.elastic.apm.agent.tracer.service.ServiceInfo; import co.elastic.apm.agent.impl.TracerInternalApiUtils; import co.elastic.apm.api.AbstractSpanImplAccessor; import co.elastic.apm.api.ElasticApm; diff --git a/apm-agent-plugins/apm-api-plugin/src/test/java/co/elastic/apm/api/ElasticApmApiInstrumentationTest.java b/apm-agent-plugins/apm-api-plugin/src/test/java/co/elastic/apm/api/ElasticApmApiInstrumentationTest.java index 5b3b4af45f..b5a728eca6 100644 --- a/apm-agent-plugins/apm-api-plugin/src/test/java/co/elastic/apm/api/ElasticApmApiInstrumentationTest.java +++ b/apm-agent-plugins/apm-api-plugin/src/test/java/co/elastic/apm/api/ElasticApmApiInstrumentationTest.java @@ -19,7 +19,7 @@ package co.elastic.apm.api; import co.elastic.apm.AbstractApiTest; -import co.elastic.apm.agent.configuration.ServiceInfo; +import co.elastic.apm.agent.tracer.service.ServiceInfo; import co.elastic.apm.agent.impl.TextHeaderMapAccessor; import co.elastic.apm.agent.impl.TracerInternalApiUtils; import co.elastic.apm.agent.impl.transaction.AbstractSpan; diff --git a/apm-agent-plugins/apm-asynchttpclient-plugin/pom.xml b/apm-agent-plugins/apm-asynchttpclient-plugin/pom.xml index 80a2627e72..f817f65238 100644 --- a/apm-agent-plugins/apm-asynchttpclient-plugin/pom.xml +++ b/apm-agent-plugins/apm-asynchttpclient-plugin/pom.xml @@ -5,7 +5,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-asynchttpclient-plugin diff --git a/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-1-plugin/pom.xml b/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-1-plugin/pom.xml index eb3215612e..141f6d3512 100644 --- a/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-1-plugin/pom.xml +++ b/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-1-plugin/pom.xml @@ -3,7 +3,7 @@ apm-aws-sdk co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-2-plugin/pom.xml b/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-2-plugin/pom.xml index a36099fe83..531467cc31 100644 --- a/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-2-plugin/pom.xml +++ b/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-2-plugin/pom.xml @@ -3,7 +3,7 @@ apm-aws-sdk co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 @@ -13,7 +13,7 @@ ${project.basedir}/../../.. - 2.20.122 + 2.20.157 2.0.0 8 diff --git a/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-common/pom.xml b/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-common/pom.xml index 220c5bacf5..669b6d6a71 100644 --- a/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-common/pom.xml +++ b/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-common/pom.xml @@ -3,7 +3,7 @@ apm-aws-sdk co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/apm-agent-plugins/apm-aws-sdk/pom.xml b/apm-agent-plugins/apm-aws-sdk/pom.xml index dde9d2fb38..9b2adfbca3 100644 --- a/apm-agent-plugins/apm-aws-sdk/pom.xml +++ b/apm-agent-plugins/apm-aws-sdk/pom.xml @@ -3,7 +3,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/apm-agent-plugins/apm-awslambda-plugin/pom.xml b/apm-agent-plugins/apm-awslambda-plugin/pom.xml index 75c2886d7f..fef395007b 100644 --- a/apm-agent-plugins/apm-awslambda-plugin/pom.xml +++ b/apm-agent-plugins/apm-awslambda-plugin/pom.xml @@ -3,7 +3,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/apm-agent-plugins/apm-cassandra/apm-cassandra-core-plugin/pom.xml b/apm-agent-plugins/apm-cassandra/apm-cassandra-core-plugin/pom.xml index d0c971a619..7f534e20ff 100644 --- a/apm-agent-plugins/apm-cassandra/apm-cassandra-core-plugin/pom.xml +++ b/apm-agent-plugins/apm-cassandra/apm-cassandra-core-plugin/pom.xml @@ -3,7 +3,7 @@ apm-cassandra co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/apm-agent-plugins/apm-cassandra/apm-cassandra3-plugin/pom.xml b/apm-agent-plugins/apm-cassandra/apm-cassandra3-plugin/pom.xml index 6da4c7416b..32e3871dd3 100644 --- a/apm-agent-plugins/apm-cassandra/apm-cassandra3-plugin/pom.xml +++ b/apm-agent-plugins/apm-cassandra/apm-cassandra3-plugin/pom.xml @@ -3,7 +3,7 @@ apm-cassandra co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 @@ -18,7 +18,7 @@ com.datastax.cassandra cassandra-driver-core - 3.11.4 + 3.11.5 provided diff --git a/apm-agent-plugins/apm-cassandra/apm-cassandra4-plugin/pom.xml b/apm-agent-plugins/apm-cassandra/apm-cassandra4-plugin/pom.xml index feefb2a78b..84b8db7114 100644 --- a/apm-agent-plugins/apm-cassandra/apm-cassandra4-plugin/pom.xml +++ b/apm-agent-plugins/apm-cassandra/apm-cassandra4-plugin/pom.xml @@ -3,7 +3,7 @@ apm-cassandra co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/apm-agent-plugins/apm-cassandra/pom.xml b/apm-agent-plugins/apm-cassandra/pom.xml index b3e7392089..bf63a56453 100644 --- a/apm-agent-plugins/apm-cassandra/pom.xml +++ b/apm-agent-plugins/apm-cassandra/pom.xml @@ -3,7 +3,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/apm-agent-plugins/apm-dubbo-plugin/pom.xml b/apm-agent-plugins/apm-dubbo-plugin/pom.xml index 1aad275956..b4db69d404 100644 --- a/apm-agent-plugins/apm-dubbo-plugin/pom.xml +++ b/apm-agent-plugins/apm-dubbo-plugin/pom.xml @@ -3,7 +3,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/apm-agent-plugins/apm-ecs-logging-plugin/pom.xml b/apm-agent-plugins/apm-ecs-logging-plugin/pom.xml index e42851bd73..e61eda6307 100644 --- a/apm-agent-plugins/apm-ecs-logging-plugin/pom.xml +++ b/apm-agent-plugins/apm-ecs-logging-plugin/pom.xml @@ -5,7 +5,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-ecs-logging-plugin diff --git a/apm-agent-plugins/apm-ecs-logging-plugin/src/main/java/co/elastic/apm/agent/ecs_logging/EcsLoggingUtils.java b/apm-agent-plugins/apm-ecs-logging-plugin/src/main/java/co/elastic/apm/agent/ecs_logging/EcsLoggingUtils.java index 6ce83e7bab..bfae79d419 100644 --- a/apm-agent-plugins/apm-ecs-logging-plugin/src/main/java/co/elastic/apm/agent/ecs_logging/EcsLoggingUtils.java +++ b/apm-agent-plugins/apm-ecs-logging-plugin/src/main/java/co/elastic/apm/agent/ecs_logging/EcsLoggingUtils.java @@ -18,8 +18,8 @@ */ package co.elastic.apm.agent.ecs_logging; -import co.elastic.apm.agent.configuration.ServiceInfo; -import co.elastic.apm.agent.impl.ElasticApmTracer; +import co.elastic.apm.agent.tracer.service.ServiceAwareTracer; +import co.elastic.apm.agent.tracer.service.ServiceInfo; import co.elastic.apm.agent.sdk.logging.Logger; import co.elastic.apm.agent.sdk.logging.LoggerFactory; import co.elastic.apm.agent.sdk.weakconcurrent.WeakConcurrent; @@ -38,7 +38,7 @@ public class EcsLoggingUtils { private static final WeakSet versionChecked = WeakConcurrent.buildSet(); private static final WeakSet environmentChecked = WeakConcurrent.buildSet(); - private static final ElasticApmTracer tracer = GlobalTracer.get().require(ElasticApmTracer.class); + private static final ServiceAwareTracer tracer = GlobalTracer.get().require(ServiceAwareTracer.class); @Nullable public static String getServiceName() { diff --git a/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-5_6/pom.xml b/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-5_6/pom.xml index 4e2aa64a08..116f75d38b 100644 --- a/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-5_6/pom.xml +++ b/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-5_6/pom.xml @@ -5,7 +5,7 @@ apm-es-restclient-plugin co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-es-restclient-plugin-5_6 diff --git a/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-5_6/src/main/java/co/elastic/apm/agent/esrestclient/v5_6/ElasticsearchClientAsyncInstrumentation.java b/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-5_6/src/main/java/co/elastic/apm/agent/esrestclient/v5_6/ElasticsearchClientAsyncInstrumentation.java index 50624129f2..4bc3fa6c8c 100644 --- a/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-5_6/src/main/java/co/elastic/apm/agent/esrestclient/v5_6/ElasticsearchClientAsyncInstrumentation.java +++ b/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-5_6/src/main/java/co/elastic/apm/agent/esrestclient/v5_6/ElasticsearchClientAsyncInstrumentation.java @@ -75,7 +75,7 @@ public static Object[] onBeforeExecute(@Advice.Argument(0) String method, @Advice.Argument(3) @Nullable HttpEntity entity, @Advice.Argument(5) ResponseListener responseListener) { - Span span = helper.createClientSpan(method, endpoint, entity); + Span span = helper.createClientSpan(method, endpoint, entity, false); if (span != null) { Object[] ret = new Object[2]; ret[0] = span; diff --git a/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-5_6/src/main/java/co/elastic/apm/agent/esrestclient/v5_6/ElasticsearchClientSyncInstrumentation.java b/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-5_6/src/main/java/co/elastic/apm/agent/esrestclient/v5_6/ElasticsearchClientSyncInstrumentation.java index 3c51025234..e8ce060e27 100644 --- a/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-5_6/src/main/java/co/elastic/apm/agent/esrestclient/v5_6/ElasticsearchClientSyncInstrumentation.java +++ b/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-5_6/src/main/java/co/elastic/apm/agent/esrestclient/v5_6/ElasticsearchClientSyncInstrumentation.java @@ -47,7 +47,7 @@ public static class ElasticsearchRestClientAdvice { public static Object onBeforeExecute(@Advice.Argument(0) String method, @Advice.Argument(1) String endpoint, @Advice.Argument(3) @Nullable HttpEntity entity) { - return helper.createClientSpan(method, endpoint, entity); + return helper.createClientSpan(method, endpoint, entity, true); } @Advice.OnMethodExit(suppress = Throwable.class, onThrowable = Throwable.class, inline = false) diff --git a/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-6_4/pom.xml b/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-6_4/pom.xml index 868571b3ae..06b1090540 100644 --- a/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-6_4/pom.xml +++ b/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-6_4/pom.xml @@ -5,7 +5,7 @@ apm-es-restclient-plugin co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-es-restclient-plugin-6_4 diff --git a/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-6_4/src/main/java/co/elastic/apm/agent/esrestclient/v6_4/ElasticsearchClientAsyncInstrumentation.java b/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-6_4/src/main/java/co/elastic/apm/agent/esrestclient/v6_4/ElasticsearchClientAsyncInstrumentation.java index e50edf0dc9..d8d737609e 100644 --- a/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-6_4/src/main/java/co/elastic/apm/agent/esrestclient/v6_4/ElasticsearchClientAsyncInstrumentation.java +++ b/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-6_4/src/main/java/co/elastic/apm/agent/esrestclient/v6_4/ElasticsearchClientAsyncInstrumentation.java @@ -66,7 +66,7 @@ public static class ElasticsearchRestClientAsyncAdvice { @Advice.OnMethodEnter(suppress = Throwable.class, inline = false) public static Object[] onBeforeExecute(@Advice.Argument(0) Request request, @Advice.Argument(1) ResponseListener responseListener) { - Span span = helper.createClientSpan(request.getMethod(), request.getEndpoint(), request.getEntity()); + Span span = helper.createClientSpan(request.getMethod(), request.getEndpoint(), request.getEntity(), false); if (span != null) { Object[] ret = new Object[2]; ret[0] = span; diff --git a/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-6_4/src/main/java/co/elastic/apm/agent/esrestclient/v6_4/ElasticsearchClientSyncInstrumentation.java b/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-6_4/src/main/java/co/elastic/apm/agent/esrestclient/v6_4/ElasticsearchClientSyncInstrumentation.java index 1186200f26..cb9913cdac 100644 --- a/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-6_4/src/main/java/co/elastic/apm/agent/esrestclient/v6_4/ElasticsearchClientSyncInstrumentation.java +++ b/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-6_4/src/main/java/co/elastic/apm/agent/esrestclient/v6_4/ElasticsearchClientSyncInstrumentation.java @@ -60,7 +60,7 @@ public static class ElasticsearchRestClientSyncAdvice { @Nullable @Advice.OnMethodEnter(suppress = Throwable.class, inline = false) public static Object onBeforeExecute(@Advice.Argument(0) Request request) { - return helper.createClientSpan(request.getMethod(), request.getEndpoint(), request.getEntity()); + return helper.createClientSpan(request.getMethod(), request.getEndpoint(), request.getEntity(), true); } @Advice.OnMethodExit(suppress = Throwable.class, onThrowable = Throwable.class, inline = false) diff --git a/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-7_x/pom.xml b/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-7_x/pom.xml index ef9654ce74..d26f389c7b 100644 --- a/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-7_x/pom.xml +++ b/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-7_x/pom.xml @@ -5,7 +5,7 @@ apm-es-restclient-plugin co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-es-restclient-plugin-7_x diff --git a/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-7_x/src/test/java/co/elastic/apm/agent/esrestclient/v7_x/ElasticsearchRestClientInstrumentationIT.java b/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-7_x/src/test/java/co/elastic/apm/agent/esrestclient/v7_x/ElasticsearchRestClientInstrumentationIT.java index cceba3d000..cafbb85d1a 100644 --- a/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-7_x/src/test/java/co/elastic/apm/agent/esrestclient/v7_x/ElasticsearchRestClientInstrumentationIT.java +++ b/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-7_x/src/test/java/co/elastic/apm/agent/esrestclient/v7_x/ElasticsearchRestClientInstrumentationIT.java @@ -143,6 +143,7 @@ public void onFailure(Exception e) { .statusCode(-1) .disableHttpUrlCheck() .expectAnyStatement() + .expectAsync(true) .check(); assertThat(searchSpan.getOutcome()) diff --git a/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-8_x/pom.xml b/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-8_x/pom.xml index a35bbbfb2a..d593134225 100644 --- a/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-8_x/pom.xml +++ b/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-8_x/pom.xml @@ -3,7 +3,7 @@ apm-es-restclient-plugin co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 @@ -11,7 +11,7 @@ ${project.groupId}:${project.artifactId} - 8.9.0 + 8.9.1 ${project.basedir}/../../.. diff --git a/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-8_x/src/test/java/co/elastic/apm/agent/esrestclient/v8_x/Elasticsearch8JavaIT.java b/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-8_x/src/test/java/co/elastic/apm/agent/esrestclient/v8_x/Elasticsearch8JavaIT.java index fbc1a7e392..0381d5eb6a 100644 --- a/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-8_x/src/test/java/co/elastic/apm/agent/esrestclient/v8_x/Elasticsearch8JavaIT.java +++ b/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-8_x/src/test/java/co/elastic/apm/agent/esrestclient/v8_x/Elasticsearch8JavaIT.java @@ -276,6 +276,7 @@ public void testDocumentScenario() throws Exception { .endpointName("delete") .expectPathPart("index", INDEX) .expectPathPart("id", DOC_ID) + .expectAsync(false) // delete is a sync operation .check(); } } diff --git a/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-common/pom.xml b/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-common/pom.xml index b2ec60a1ea..91f1eac166 100644 --- a/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-common/pom.xml +++ b/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-common/pom.xml @@ -5,7 +5,7 @@ apm-es-restclient-plugin co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-es-restclient-plugin-common diff --git a/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-common/src/main/java/co/elastic/apm/agent/esrestclient/ElasticsearchRestClientInstrumentation.java b/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-common/src/main/java/co/elastic/apm/agent/esrestclient/ElasticsearchRestClientInstrumentation.java index 4c54b64108..d32a0eca74 100644 --- a/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-common/src/main/java/co/elastic/apm/agent/esrestclient/ElasticsearchRestClientInstrumentation.java +++ b/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-common/src/main/java/co/elastic/apm/agent/esrestclient/ElasticsearchRestClientInstrumentation.java @@ -21,10 +21,14 @@ import co.elastic.apm.agent.sdk.ElasticApmInstrumentation; import co.elastic.apm.agent.tracer.GlobalTracer; import co.elastic.apm.agent.tracer.Tracer; +import net.bytebuddy.matcher.ElementMatcher; import java.util.Collection; import java.util.Collections; +import static co.elastic.apm.agent.sdk.bytebuddy.CustomElementMatchers.classLoaderCanLoadClass; +import static net.bytebuddy.matcher.ElementMatchers.not; + public abstract class ElasticsearchRestClientInstrumentation extends ElasticApmInstrumentation { @@ -35,4 +39,10 @@ public Collection getInstrumentationGroupNames() { return Collections.singleton("elasticsearch-restclient"); } + @Override + public ElementMatcher.Junction getClassLoaderMatcher() { + // ensure only ES client versions without native instrumentation are instrumented (8.9 and older) + return not(classLoaderCanLoadClass("co.elastic.clients.transport.instrumentation.Instrumentation")); + } + } diff --git a/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-common/src/main/java/co/elastic/apm/agent/esrestclient/ElasticsearchRestClientInstrumentationHelper.java b/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-common/src/main/java/co/elastic/apm/agent/esrestclient/ElasticsearchRestClientInstrumentationHelper.java index 352572d752..759cb061d0 100644 --- a/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-common/src/main/java/co/elastic/apm/agent/esrestclient/ElasticsearchRestClientInstrumentationHelper.java +++ b/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-common/src/main/java/co/elastic/apm/agent/esrestclient/ElasticsearchRestClientInstrumentationHelper.java @@ -86,7 +86,7 @@ public void clearCurrentEndpoint() { } @Nullable - public Span createClientSpan(String method, String httpPath, @Nullable HttpEntity httpEntity) { + public Span createClientSpan(String method, String httpPath, @Nullable HttpEntity httpEntity, boolean isSync) { ElasticsearchEndpointDefinition endpoint = currentRequestEndpoint.getAndRemove(); Span span = tracer.currentContext().createExitSpan(); @@ -98,7 +98,8 @@ public Span createClientSpan(String method, String httpPath, @Nullable HttpEn span.withType(SPAN_TYPE) .withSubtype(ELASTICSEARCH) - .withAction(SPAN_ACTION); + .withAction(SPAN_ACTION) + .withSync(isSync); StringBuilder name = span.getAndOverrideName(AbstractSpan.PRIORITY_HIGH_LEVEL_FRAMEWORK); if (endpoint != null) { diff --git a/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-common/src/test/java/co/elastic/apm/agent/esrestclient/AbstractEsClientInstrumentationTest.java b/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-common/src/test/java/co/elastic/apm/agent/esrestclient/AbstractEsClientInstrumentationTest.java index ae641992d6..0c967a1a44 100644 --- a/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-common/src/test/java/co/elastic/apm/agent/esrestclient/AbstractEsClientInstrumentationTest.java +++ b/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-common/src/test/java/co/elastic/apm/agent/esrestclient/AbstractEsClientInstrumentationTest.java @@ -101,7 +101,7 @@ public void assertThatErrorsExistWhenDeleteNonExistingIndex() { } protected EsSpanValidationBuilder validateSpan(Span spanToValidate) { - return new EsSpanValidationBuilder(spanToValidate); + return new EsSpanValidationBuilder(spanToValidate, async); } protected EsSpanValidationBuilder validateSpan() { @@ -138,8 +138,11 @@ protected static class EsSpanValidationBuilder { @Nullable private String expectedHttpUrl = "http://" + container.getHttpHostAddress(); - public EsSpanValidationBuilder(Span spanToValidate) { + private boolean isAsyncRequest; + + public EsSpanValidationBuilder(Span spanToValidate, boolean isAsyncRequest) { this.span = spanToValidate; + this.isAsyncRequest = isAsyncRequest; } public EsSpanValidationBuilder expectNoStatement() { @@ -154,6 +157,11 @@ public EsSpanValidationBuilder expectAnyStatement() { return this; } + public EsSpanValidationBuilder expectAsync(boolean async) { + isAsyncRequest = async; + return this; + } + public EsSpanValidationBuilder expectStatement(String statement) { try { this.expectedStatement = jackson.readTree(statement); @@ -221,6 +229,11 @@ public void check() { checkDbContext(); checkPathPartAttributes(); checkDestinationContext(); + if (isAsyncRequest) { + assertThat(span).isAsync(); + } else { + assertThat(span).isSync(); + } } diff --git a/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-common/src/test/java/co/elastic/apm/agent/esrestclient/ElasticsearchRestClientInstrumentationHelperTest.java b/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-common/src/test/java/co/elastic/apm/agent/esrestclient/ElasticsearchRestClientInstrumentationHelperTest.java index a8605bb880..5fbce1c02e 100644 --- a/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-common/src/test/java/co/elastic/apm/agent/esrestclient/ElasticsearchRestClientInstrumentationHelperTest.java +++ b/apm-agent-plugins/apm-es-restclient-plugin/apm-es-restclient-plugin-common/src/test/java/co/elastic/apm/agent/esrestclient/ElasticsearchRestClientInstrumentationHelperTest.java @@ -24,6 +24,7 @@ import co.elastic.apm.agent.impl.transaction.Span; import co.elastic.apm.agent.impl.transaction.Transaction; import co.elastic.apm.agent.impl.transaction.TransactionTest; +import co.elastic.apm.agent.testutils.assertions.SpanAssert; import org.apache.http.HttpHost; import org.apache.http.HttpVersion; import org.apache.http.entity.ByteArrayEntity; @@ -36,6 +37,9 @@ import java.util.List; import java.util.Map; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; import static co.elastic.apm.agent.esrestclient.ElasticsearchRestClientInstrumentationHelper.ELASTICSEARCH; import static co.elastic.apm.agent.testutils.assertions.Assertions.assertThat; @@ -62,7 +66,7 @@ void after(){ @Test void testCreateSpan() { - Span span = (Span) helper.createClientSpan("GET", "/_test", null); + Span span = (Span) helper.createClientSpan("GET", "/_test", null, true); assertThat(span).isNotNull(); assertThat(tracer.getActive()).isEqualTo(span); @@ -87,7 +91,7 @@ void testCreateSpan() { @Test void testCreateSpanWithClusterName() { - Span span = (Span) helper.createClientSpan("GET", "/_test", null); + Span span = (Span) helper.createClientSpan("GET", "/_test", null, true); assertThat(span).isNotNull(); assertThat(tracer.getActive()).isEqualTo(span); @@ -127,7 +131,7 @@ private static Response mockResponse(Map headers) { @Test void testNonSampledSpan() { TransactionTest.setRecorded(false, transaction); - Span esSpan = (Span) helper.createClientSpan("SEARCH", "/test", null); + Span esSpan = (Span) helper.createClientSpan("SEARCH", "/test", null, true); assertThat(esSpan).isNotNull(); try { assertThat(esSpan.isSampled()).isFalse(); @@ -157,7 +161,7 @@ public void testCaptureBodyUrls(boolean captureEverything) throws Exception { } Span span = (Span) helper.createClientSpan("GET", "/_test", - new ByteArrayEntity(new byte[0])); + new ByteArrayEntity(new byte[0]), true); assertThat(span).isNotNull(); assertThat(tracer.getActive()).isEqualTo(span); @@ -179,4 +183,26 @@ public void testCaptureBodyUrls(boolean captureEverything) throws Exception { assertThat((CharSequence) db.getStatementBuffer()).isNull(); } } + + @Test + public void testSpanIsAsync() { + testSpanSyncAttribute(false, (span -> assertThat(span).isAsync())); + } + + @Test + public void testSpanIsSync() { + testSpanSyncAttribute(true, (span -> assertThat(span).isSync())); + } + + private void testSpanSyncAttribute(boolean isSync, Function checkSyncAttribute) { + Span span = (Span) helper.createClientSpan("GET", "/_test", null, isSync); + assertThat(span).isNotNull(); + + assertThat(tracer.getActive()).isEqualTo(span); + checkSyncAttribute.apply(span); + + Response response = mockResponse(Map.of()); + helper.finishClientSpan(response, span, null); + span.deactivate(); + } } diff --git a/apm-agent-plugins/apm-es-restclient-plugin/pom.xml b/apm-agent-plugins/apm-es-restclient-plugin/pom.xml index 7ab6d4b012..67af36117d 100644 --- a/apm-agent-plugins/apm-es-restclient-plugin/pom.xml +++ b/apm-agent-plugins/apm-es-restclient-plugin/pom.xml @@ -5,7 +5,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-es-restclient-plugin diff --git a/apm-agent-plugins/apm-finagle-httpclient-plugin/pom.xml b/apm-agent-plugins/apm-finagle-httpclient-plugin/pom.xml index 4af850d9ef..6c51ca5212 100644 --- a/apm-agent-plugins/apm-finagle-httpclient-plugin/pom.xml +++ b/apm-agent-plugins/apm-finagle-httpclient-plugin/pom.xml @@ -5,7 +5,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-finagle-httpclient-plugin diff --git a/apm-agent-plugins/apm-grails-plugin/pom.xml b/apm-agent-plugins/apm-grails-plugin/pom.xml index 0796fd953f..c651a28821 100644 --- a/apm-agent-plugins/apm-grails-plugin/pom.xml +++ b/apm-agent-plugins/apm-grails-plugin/pom.xml @@ -5,7 +5,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-grails-plugin diff --git a/apm-agent-plugins/apm-grpc/apm-grpc-plugin/pom.xml b/apm-agent-plugins/apm-grpc/apm-grpc-plugin/pom.xml index a3defb4e39..82c3ba2e58 100644 --- a/apm-agent-plugins/apm-grpc/apm-grpc-plugin/pom.xml +++ b/apm-agent-plugins/apm-grpc/apm-grpc-plugin/pom.xml @@ -5,7 +5,7 @@ co.elastic.apm apm-grpc - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-grpc-plugin diff --git a/apm-agent-plugins/apm-grpc/apm-grpc-test-1.6.1/pom.xml b/apm-agent-plugins/apm-grpc/apm-grpc-test-1.6.1/pom.xml index eed07b9026..c61b41c74f 100644 --- a/apm-agent-plugins/apm-grpc/apm-grpc-test-1.6.1/pom.xml +++ b/apm-agent-plugins/apm-grpc/apm-grpc-test-1.6.1/pom.xml @@ -5,7 +5,7 @@ co.elastic.apm apm-grpc - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-grpc-test-1.6.1 diff --git a/apm-agent-plugins/apm-grpc/apm-grpc-test-latest/pom.xml b/apm-agent-plugins/apm-grpc/apm-grpc-test-latest/pom.xml index 1b31bf42ee..4916e269b2 100644 --- a/apm-agent-plugins/apm-grpc/apm-grpc-test-latest/pom.xml +++ b/apm-agent-plugins/apm-grpc/apm-grpc-test-latest/pom.xml @@ -5,7 +5,7 @@ co.elastic.apm apm-grpc - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-grpc-test-latest diff --git a/apm-agent-plugins/apm-grpc/pom.xml b/apm-agent-plugins/apm-grpc/pom.xml index eaa7794441..4e601f51a5 100644 --- a/apm-agent-plugins/apm-grpc/pom.xml +++ b/apm-agent-plugins/apm-grpc/pom.xml @@ -5,7 +5,7 @@ co.elastic.apm apm-agent-plugins - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-grpc diff --git a/apm-agent-plugins/apm-hibernate-search-plugin/apm-hibernate-search-plugin-5_x/pom.xml b/apm-agent-plugins/apm-hibernate-search-plugin/apm-hibernate-search-plugin-5_x/pom.xml index 9f3c555397..2beb773baf 100644 --- a/apm-agent-plugins/apm-hibernate-search-plugin/apm-hibernate-search-plugin-5_x/pom.xml +++ b/apm-agent-plugins/apm-hibernate-search-plugin/apm-hibernate-search-plugin-5_x/pom.xml @@ -5,7 +5,7 @@ apm-hibernate-search-plugin co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-hibernate-search-plugin-5_x @@ -26,6 +26,12 @@ hibernate-search-orm 5.11.1.Final provided + + + net.bytebuddy + byte-buddy + + diff --git a/apm-agent-plugins/apm-hibernate-search-plugin/apm-hibernate-search-plugin-6_x/pom.xml b/apm-agent-plugins/apm-hibernate-search-plugin/apm-hibernate-search-plugin-6_x/pom.xml index 5af7282348..dd356070bd 100644 --- a/apm-agent-plugins/apm-hibernate-search-plugin/apm-hibernate-search-plugin-6_x/pom.xml +++ b/apm-agent-plugins/apm-hibernate-search-plugin/apm-hibernate-search-plugin-6_x/pom.xml @@ -5,7 +5,7 @@ apm-hibernate-search-plugin co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-hibernate-search-plugin-6_x @@ -28,6 +28,12 @@ hibernate-search-mapper-orm ${version.hibernate.search} provided + + + net.bytebuddy + byte-buddy + + diff --git a/apm-agent-plugins/apm-hibernate-search-plugin/apm-hibernate-search-plugin-common/pom.xml b/apm-agent-plugins/apm-hibernate-search-plugin/apm-hibernate-search-plugin-common/pom.xml index 4b2ee4a7e8..c356d24777 100644 --- a/apm-agent-plugins/apm-hibernate-search-plugin/apm-hibernate-search-plugin-common/pom.xml +++ b/apm-agent-plugins/apm-hibernate-search-plugin/apm-hibernate-search-plugin-common/pom.xml @@ -5,7 +5,7 @@ apm-hibernate-search-plugin co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-hibernate-search-plugin-common diff --git a/apm-agent-plugins/apm-hibernate-search-plugin/pom.xml b/apm-agent-plugins/apm-hibernate-search-plugin/pom.xml index 844d9080d1..fd6f64e0b0 100644 --- a/apm-agent-plugins/apm-hibernate-search-plugin/pom.xml +++ b/apm-agent-plugins/apm-hibernate-search-plugin/pom.xml @@ -5,7 +5,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-hibernate-search-plugin diff --git a/apm-agent-plugins/apm-httpclient-core/pom.xml b/apm-agent-plugins/apm-httpclient-core/pom.xml index 36c09fea0e..b99a13b823 100644 --- a/apm-agent-plugins/apm-httpclient-core/pom.xml +++ b/apm-agent-plugins/apm-httpclient-core/pom.xml @@ -5,7 +5,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-httpclient-core diff --git a/apm-agent-plugins/apm-httpserver-core/pom.xml b/apm-agent-plugins/apm-httpserver-core/pom.xml index b9ae47da32..5d5b698325 100644 --- a/apm-agent-plugins/apm-httpserver-core/pom.xml +++ b/apm-agent-plugins/apm-httpserver-core/pom.xml @@ -5,7 +5,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-httpserver-core diff --git a/apm-agent-plugins/apm-jakarta-websocket-plugin/pom.xml b/apm-agent-plugins/apm-jakarta-websocket-plugin/pom.xml index 99ff70a4ae..557346c7ac 100644 --- a/apm-agent-plugins/apm-jakarta-websocket-plugin/pom.xml +++ b/apm-agent-plugins/apm-jakarta-websocket-plugin/pom.xml @@ -5,7 +5,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-jakarta-websocket-plugin diff --git a/apm-agent-plugins/apm-java-concurrent-plugin/pom.xml b/apm-agent-plugins/apm-java-concurrent-plugin/pom.xml index 69d65328dc..5c271ad9c6 100644 --- a/apm-agent-plugins/apm-java-concurrent-plugin/pom.xml +++ b/apm-agent-plugins/apm-java-concurrent-plugin/pom.xml @@ -5,7 +5,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-java-concurrent-plugin diff --git a/apm-agent-plugins/apm-java-concurrent-plugin/src/main/java/co/elastic/apm/agent/concurrent/ForkJoinTaskInstrumentation.java b/apm-agent-plugins/apm-java-concurrent-plugin/src/main/java/co/elastic/apm/agent/concurrent/ForkJoinTaskInstrumentation.java index a2648cece9..1c5a0ee0f1 100644 --- a/apm-agent-plugins/apm-java-concurrent-plugin/src/main/java/co/elastic/apm/agent/concurrent/ForkJoinTaskInstrumentation.java +++ b/apm-agent-plugins/apm-java-concurrent-plugin/src/main/java/co/elastic/apm/agent/concurrent/ForkJoinTaskInstrumentation.java @@ -42,17 +42,6 @@ public class ForkJoinTaskInstrumentation extends ElasticApmInstrumentation { private static final Tracer tracer = GlobalTracer.get(); - static { - if (Boolean.parseBoolean(System.getProperty("intellij.debug.agent"))) { - // IntelliJ debugger also instrument some java.util.concurrent classes and changes the class structure. - // However, the changes are not re-applied when re-transforming already loaded classes, which makes our - // agent unable to see those structural changes and try to load classes with their original bytecode - // - // Go to the following to enable/disable: File | Settings | Build, Execution, Deployment | Debugger | Async Stack Traces - throw new IllegalStateException("IntelliJ debug agent detected, disable it to prevent unexpected instrumentation errors. See https://github.com/elastic/apm-agent-java/issues/1673"); - } - } - @Override public ElementMatcher getTypeMatcher() { return is(ForkJoinTask.class); diff --git a/apm-agent-plugins/apm-java-ldap-plugin/pom.xml b/apm-agent-plugins/apm-java-ldap-plugin/pom.xml index 64ed8675fc..edcb8cffeb 100644 --- a/apm-agent-plugins/apm-java-ldap-plugin/pom.xml +++ b/apm-agent-plugins/apm-java-ldap-plugin/pom.xml @@ -5,7 +5,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-java-ldap-plugin diff --git a/apm-agent-plugins/apm-javalin-plugin/pom.xml b/apm-agent-plugins/apm-javalin-plugin/pom.xml index 846c2afdd7..21f7184750 100644 --- a/apm-agent-plugins/apm-javalin-plugin/pom.xml +++ b/apm-agent-plugins/apm-javalin-plugin/pom.xml @@ -5,7 +5,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-javalin-plugin diff --git a/apm-agent-plugins/apm-jaxrs-plugin-jakartaee-test/pom.xml b/apm-agent-plugins/apm-jaxrs-plugin-jakartaee-test/pom.xml index b31afc2371..0b022ecc7e 100644 --- a/apm-agent-plugins/apm-jaxrs-plugin-jakartaee-test/pom.xml +++ b/apm-agent-plugins/apm-jaxrs-plugin-jakartaee-test/pom.xml @@ -3,7 +3,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/apm-agent-plugins/apm-jaxrs-plugin/pom.xml b/apm-agent-plugins/apm-jaxrs-plugin/pom.xml index 9ede98227c..1101ff7087 100644 --- a/apm-agent-plugins/apm-jaxrs-plugin/pom.xml +++ b/apm-agent-plugins/apm-jaxrs-plugin/pom.xml @@ -5,7 +5,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-jaxrs-plugin diff --git a/apm-agent-plugins/apm-jaxws-plugin-jakartaee-test/pom.xml b/apm-agent-plugins/apm-jaxws-plugin-jakartaee-test/pom.xml index 4cd3bd9376..07941caef7 100644 --- a/apm-agent-plugins/apm-jaxws-plugin-jakartaee-test/pom.xml +++ b/apm-agent-plugins/apm-jaxws-plugin-jakartaee-test/pom.xml @@ -3,7 +3,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/apm-agent-plugins/apm-jaxws-plugin/pom.xml b/apm-agent-plugins/apm-jaxws-plugin/pom.xml index 771c4b320c..b313a945e7 100644 --- a/apm-agent-plugins/apm-jaxws-plugin/pom.xml +++ b/apm-agent-plugins/apm-jaxws-plugin/pom.xml @@ -5,7 +5,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-jaxws-plugin diff --git a/apm-agent-plugins/apm-jdbc-plugin/pom.xml b/apm-agent-plugins/apm-jdbc-plugin/pom.xml index fc0034ab59..24d5210e61 100644 --- a/apm-agent-plugins/apm-jdbc-plugin/pom.xml +++ b/apm-agent-plugins/apm-jdbc-plugin/pom.xml @@ -5,7 +5,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-jdbc-plugin diff --git a/apm-agent-plugins/apm-jdbc-plugin/src/main/java/co/elastic/apm/agent/jdbc/ConnectionInstrumentation.java b/apm-agent-plugins/apm-jdbc-plugin/src/main/java/co/elastic/apm/agent/jdbc/ConnectionInstrumentation.java index b313c4f8dc..da79e09d49 100644 --- a/apm-agent-plugins/apm-jdbc-plugin/src/main/java/co/elastic/apm/agent/jdbc/ConnectionInstrumentation.java +++ b/apm-agent-plugins/apm-jdbc-plugin/src/main/java/co/elastic/apm/agent/jdbc/ConnectionInstrumentation.java @@ -57,7 +57,7 @@ public static void storeSql(@Advice.Return @Nullable PreparedStatement statement @Override public ElementMatcher getTypeMatcherPreFilter() { - return nameContains("Connection"); + return nameContains("Connection").or(nameStartsWith("com.ibm.db2.jcc")); //db2 doesn't have Connection in the name } @Override diff --git a/apm-agent-plugins/apm-jdk-httpclient-plugin/pom.xml b/apm-agent-plugins/apm-jdk-httpclient-plugin/pom.xml index f29adb0a57..80027ad88f 100644 --- a/apm-agent-plugins/apm-jdk-httpclient-plugin/pom.xml +++ b/apm-agent-plugins/apm-jdk-httpclient-plugin/pom.xml @@ -5,7 +5,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-jdk-httpclient-plugin diff --git a/apm-agent-plugins/apm-jdk-httpserver-plugin/pom.xml b/apm-agent-plugins/apm-jdk-httpserver-plugin/pom.xml index 04a0591ff7..e4dad276b9 100644 --- a/apm-agent-plugins/apm-jdk-httpserver-plugin/pom.xml +++ b/apm-agent-plugins/apm-jdk-httpserver-plugin/pom.xml @@ -5,7 +5,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-jdk-httpserver-plugin diff --git a/apm-agent-plugins/apm-jms-plugin/apm-jms-jakarta/pom.xml b/apm-agent-plugins/apm-jms-plugin/apm-jms-jakarta/pom.xml index 83dda13c63..4096bbf90b 100644 --- a/apm-agent-plugins/apm-jms-plugin/apm-jms-jakarta/pom.xml +++ b/apm-agent-plugins/apm-jms-plugin/apm-jms-jakarta/pom.xml @@ -3,7 +3,7 @@ apm-jms-plugin co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/apm-agent-plugins/apm-jms-plugin/apm-jms-javax/pom.xml b/apm-agent-plugins/apm-jms-plugin/apm-jms-javax/pom.xml index bc3732e6b9..583eb6835a 100644 --- a/apm-agent-plugins/apm-jms-plugin/apm-jms-javax/pom.xml +++ b/apm-agent-plugins/apm-jms-plugin/apm-jms-javax/pom.xml @@ -3,7 +3,7 @@ apm-jms-plugin co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/apm-agent-plugins/apm-jms-plugin/apm-jms-plugin-base/pom.xml b/apm-agent-plugins/apm-jms-plugin/apm-jms-plugin-base/pom.xml index 0b30a8828d..6be8864490 100644 --- a/apm-agent-plugins/apm-jms-plugin/apm-jms-plugin-base/pom.xml +++ b/apm-agent-plugins/apm-jms-plugin/apm-jms-plugin-base/pom.xml @@ -5,7 +5,7 @@ apm-jms-plugin co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-jms-plugin-base diff --git a/apm-agent-plugins/apm-jms-plugin/apm-jms-spring-plugin/pom.xml b/apm-agent-plugins/apm-jms-plugin/apm-jms-spring-plugin/pom.xml index a2e2d5f25c..5dc859dafa 100644 --- a/apm-agent-plugins/apm-jms-plugin/apm-jms-spring-plugin/pom.xml +++ b/apm-agent-plugins/apm-jms-plugin/apm-jms-spring-plugin/pom.xml @@ -5,7 +5,7 @@ apm-jms-plugin co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-jms-spring-plugin diff --git a/apm-agent-plugins/apm-jms-plugin/pom.xml b/apm-agent-plugins/apm-jms-plugin/pom.xml index ac7042607e..e9556f0a86 100644 --- a/apm-agent-plugins/apm-jms-plugin/pom.xml +++ b/apm-agent-plugins/apm-jms-plugin/pom.xml @@ -5,7 +5,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-jms-plugin diff --git a/apm-agent-plugins/apm-jmx-plugin/pom.xml b/apm-agent-plugins/apm-jmx-plugin/pom.xml index a8a83b1333..db560509a5 100644 --- a/apm-agent-plugins/apm-jmx-plugin/pom.xml +++ b/apm-agent-plugins/apm-jmx-plugin/pom.xml @@ -5,7 +5,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-jmx-plugin diff --git a/apm-agent-plugins/apm-jsf-plugin/pom.xml b/apm-agent-plugins/apm-jsf-plugin/pom.xml index 38b96c8f50..60013f9149 100644 --- a/apm-agent-plugins/apm-jsf-plugin/pom.xml +++ b/apm-agent-plugins/apm-jsf-plugin/pom.xml @@ -5,7 +5,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-jsf-plugin diff --git a/apm-agent-plugins/apm-kafka-plugin/apm-kafka-base-plugin/pom.xml b/apm-agent-plugins/apm-kafka-plugin/apm-kafka-base-plugin/pom.xml index 480860227e..32420b5739 100644 --- a/apm-agent-plugins/apm-kafka-plugin/apm-kafka-base-plugin/pom.xml +++ b/apm-agent-plugins/apm-kafka-plugin/apm-kafka-base-plugin/pom.xml @@ -3,7 +3,7 @@ apm-kafka-plugin co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/apm-agent-plugins/apm-kafka-plugin/apm-kafka-headers-plugin/pom.xml b/apm-agent-plugins/apm-kafka-plugin/apm-kafka-headers-plugin/pom.xml index 6ba598c203..d287904a66 100644 --- a/apm-agent-plugins/apm-kafka-plugin/apm-kafka-headers-plugin/pom.xml +++ b/apm-agent-plugins/apm-kafka-plugin/apm-kafka-headers-plugin/pom.xml @@ -4,7 +4,7 @@ apm-kafka-plugin co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/apm-agent-plugins/apm-kafka-plugin/apm-kafka-headers-plugin/src/main/java/co/elastic/apm/agent/kafka/helper/ConsumerRecordsIterableWrapper.java b/apm-agent-plugins/apm-kafka-plugin/apm-kafka-headers-plugin/src/main/java/co/elastic/apm/agent/kafka/helper/ConsumerRecordsIterableWrapper.java index 4666d79f64..aa5521676b 100644 --- a/apm-agent-plugins/apm-kafka-plugin/apm-kafka-headers-plugin/src/main/java/co/elastic/apm/agent/kafka/helper/ConsumerRecordsIterableWrapper.java +++ b/apm-agent-plugins/apm-kafka-plugin/apm-kafka-headers-plugin/src/main/java/co/elastic/apm/agent/kafka/helper/ConsumerRecordsIterableWrapper.java @@ -22,22 +22,19 @@ import org.apache.kafka.clients.consumer.ConsumerRecord; import java.util.Iterator; -import java.util.Set; class ConsumerRecordsIterableWrapper implements Iterable> { private final Iterable> delegate; private final Tracer tracer; - private final Set binaryTraceHeaders; - public ConsumerRecordsIterableWrapper(Iterable> delegate, Tracer tracer, Set binaryTraceHeaders) { + public ConsumerRecordsIterableWrapper(Iterable> delegate, Tracer tracer) { this.delegate = delegate; this.tracer = tracer; - this.binaryTraceHeaders = binaryTraceHeaders; } @Override public Iterator> iterator() { - return new ConsumerRecordsIteratorWrapper(delegate.iterator(), tracer, binaryTraceHeaders); + return new ConsumerRecordsIteratorWrapper(delegate.iterator(), tracer); } } diff --git a/apm-agent-plugins/apm-kafka-plugin/apm-kafka-headers-plugin/src/main/java/co/elastic/apm/agent/kafka/helper/ConsumerRecordsIteratorWrapper.java b/apm-agent-plugins/apm-kafka-plugin/apm-kafka-headers-plugin/src/main/java/co/elastic/apm/agent/kafka/helper/ConsumerRecordsIteratorWrapper.java index 7ecf0452e4..e577b61626 100644 --- a/apm-agent-plugins/apm-kafka-plugin/apm-kafka-headers-plugin/src/main/java/co/elastic/apm/agent/kafka/helper/ConsumerRecordsIteratorWrapper.java +++ b/apm-agent-plugins/apm-kafka-plugin/apm-kafka-headers-plugin/src/main/java/co/elastic/apm/agent/kafka/helper/ConsumerRecordsIteratorWrapper.java @@ -18,21 +18,20 @@ */ package co.elastic.apm.agent.kafka.helper; -import co.elastic.apm.agent.tracer.configuration.CoreConfiguration; -import co.elastic.apm.agent.tracer.configuration.MessagingConfiguration; +import co.elastic.apm.agent.common.util.WildcardMatcher; +import co.elastic.apm.agent.sdk.internal.util.PrivilegedActionUtils; +import co.elastic.apm.agent.sdk.logging.Logger; +import co.elastic.apm.agent.sdk.logging.LoggerFactory; import co.elastic.apm.agent.tracer.Tracer; import co.elastic.apm.agent.tracer.Transaction; -import co.elastic.apm.agent.common.util.WildcardMatcher; +import co.elastic.apm.agent.tracer.configuration.CoreConfiguration; +import co.elastic.apm.agent.tracer.configuration.MessagingConfiguration; import co.elastic.apm.agent.tracer.metadata.Message; -import co.elastic.apm.agent.sdk.internal.util.PrivilegedActionUtils; import org.apache.kafka.clients.consumer.ConsumerRecord; import org.apache.kafka.common.header.Header; import org.apache.kafka.common.record.TimestampType; -import co.elastic.apm.agent.sdk.logging.Logger; -import co.elastic.apm.agent.sdk.logging.LoggerFactory; import java.util.Iterator; -import java.util.Set; class ConsumerRecordsIteratorWrapper implements Iterator> { @@ -41,14 +40,12 @@ class ConsumerRecordsIteratorWrapper implements Iterator> { private final Iterator> delegate; private final Tracer tracer; - private final Set binaryTraceHeaders; private final CoreConfiguration coreConfiguration; private final MessagingConfiguration messagingConfiguration; - public ConsumerRecordsIteratorWrapper(Iterator> delegate, Tracer tracer, Set binaryTraceHeaders) { + public ConsumerRecordsIteratorWrapper(Iterator> delegate, Tracer tracer) { this.delegate = delegate; this.tracer = tracer; - this.binaryTraceHeaders = binaryTraceHeaders; coreConfiguration = tracer.getConfig(CoreConfiguration.class); messagingConfiguration = tracer.getConfig(MessagingConfiguration.class); } @@ -91,7 +88,7 @@ public void endCurrentTransaction() { if (transaction.isSampled() && coreConfiguration.isCaptureHeaders()) { for (Header header : record.headers()) { String key = header.key(); - if (!binaryTraceHeaders.contains(key) && + if (!tracer.getTraceHeaderNames().contains(key) && WildcardMatcher.anyMatch(coreConfiguration.getSanitizeFieldNames(), key) == null) { message.addHeader(key, header.value()); } diff --git a/apm-agent-plugins/apm-kafka-plugin/apm-kafka-headers-plugin/src/main/java/co/elastic/apm/agent/kafka/helper/ConsumerRecordsListWrapper.java b/apm-agent-plugins/apm-kafka-plugin/apm-kafka-headers-plugin/src/main/java/co/elastic/apm/agent/kafka/helper/ConsumerRecordsListWrapper.java index 9723e40c4d..357de0f3da 100644 --- a/apm-agent-plugins/apm-kafka-plugin/apm-kafka-headers-plugin/src/main/java/co/elastic/apm/agent/kafka/helper/ConsumerRecordsListWrapper.java +++ b/apm-agent-plugins/apm-kafka-plugin/apm-kafka-headers-plugin/src/main/java/co/elastic/apm/agent/kafka/helper/ConsumerRecordsListWrapper.java @@ -25,18 +25,15 @@ import java.util.Iterator; import java.util.List; import java.util.ListIterator; -import java.util.Set; class ConsumerRecordsListWrapper implements List> { private final List> delegate; private final Tracer tracer; - private final Set binaryTraceHeaders; - public ConsumerRecordsListWrapper(List> delegate, Tracer tracer, Set binaryTraceHeaders) { + public ConsumerRecordsListWrapper(List> delegate, Tracer tracer) { this.delegate = delegate; this.tracer = tracer; - this.binaryTraceHeaders = binaryTraceHeaders; } @Override @@ -56,7 +53,7 @@ public boolean contains(Object o) { @Override public Iterator> iterator() { - return new ConsumerRecordsIteratorWrapper(delegate.iterator(), tracer, binaryTraceHeaders); + return new ConsumerRecordsIteratorWrapper(delegate.iterator(), tracer); } @Override @@ -161,6 +158,6 @@ public int lastIndexOf(Object o) { @Override public List> subList(int fromIndex, int toIndex) { - return new ConsumerRecordsListWrapper(delegate.subList(fromIndex, toIndex), tracer, binaryTraceHeaders); + return new ConsumerRecordsListWrapper(delegate.subList(fromIndex, toIndex), tracer); } } diff --git a/apm-agent-plugins/apm-kafka-plugin/apm-kafka-headers-plugin/src/main/java/co/elastic/apm/agent/kafka/helper/ElasticHeaderImpl.java b/apm-agent-plugins/apm-kafka-plugin/apm-kafka-headers-plugin/src/main/java/co/elastic/apm/agent/kafka/helper/ElasticHeaderImpl.java deleted file mode 100644 index 171c40f2c1..0000000000 --- a/apm-agent-plugins/apm-kafka-plugin/apm-kafka-headers-plugin/src/main/java/co/elastic/apm/agent/kafka/helper/ElasticHeaderImpl.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package co.elastic.apm.agent.kafka.helper; - -import org.apache.kafka.common.header.Header; -import co.elastic.apm.agent.sdk.logging.Logger; -import co.elastic.apm.agent.sdk.logging.LoggerFactory; - -import javax.annotation.Nullable; - -/** - * An implementation of the Kafka record {@link Header} interface, meant for reducing memory allocations by reusing. - * This implementation assumes that the thread asking for the {@link ElasticHeaderImpl#value()} is the same one setting - * it. If that's not the case, distributed tracing through Kafka may be impaired, therefore a warning is logged and - * the returned value is null. - */ -class ElasticHeaderImpl implements Header { - - public static final Logger logger = LoggerFactory.getLogger(ElasticHeaderImpl.class); - - private final String key; - @Nullable - byte[] value; - - private long settingThreadId; - - public ElasticHeaderImpl(String key, int headerLength) { - this.key = key; - value = new byte[headerLength]; - } - - @Override - public String key() { - return key; - } - - /** - * Used when the value is required in order to be set - * - * @return the byte array representing the value - */ - @Nullable - public byte[] valueForSetting() { - settingThreadId = Thread.currentThread().getId(); - return value; - } - - /** - * The actual {@link Header#value()} implementation - typically used by producers during serialization - * - * @return the set value if same thread set it; null otherwise - */ - @Override - @Nullable - public byte[] value() { - if (Thread.currentThread().getId() != settingThreadId && value != null) { - // Our assumption that the same thread setting the value is the one serializing the header is invalid. - // We log this once and set the value of this header to null. Distributed tracing will still work but will - // allocate a byte array for every record - logger.warn("The assumption of same thread setting and serializing the header is invalid."); - value = null; - } - return value; - } -} diff --git a/apm-agent-plugins/apm-kafka-plugin/apm-kafka-headers-plugin/src/main/java/co/elastic/apm/agent/kafka/helper/KafkaInstrumentationHeadersHelper.java b/apm-agent-plugins/apm-kafka-plugin/apm-kafka-headers-plugin/src/main/java/co/elastic/apm/agent/kafka/helper/KafkaInstrumentationHeadersHelper.java index 0019bc2e9f..14cc72b372 100644 --- a/apm-agent-plugins/apm-kafka-plugin/apm-kafka-headers-plugin/src/main/java/co/elastic/apm/agent/kafka/helper/KafkaInstrumentationHeadersHelper.java +++ b/apm-agent-plugins/apm-kafka-plugin/apm-kafka-headers-plugin/src/main/java/co/elastic/apm/agent/kafka/helper/KafkaInstrumentationHeadersHelper.java @@ -30,13 +30,8 @@ import org.apache.kafka.clients.producer.ProducerRecord; import javax.annotation.Nullable; -import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.regex.Pattern; public class KafkaInstrumentationHeadersHelper { @@ -51,8 +46,6 @@ protected Boolean initialValue() { }; private final Tracer tracer; - private final Set binaryTraceHeaders = new HashSet<>(); - private final Map translatedTraceHeaders = new HashMap<>(); public static KafkaInstrumentationHeadersHelper get() { return INSTANCE; @@ -60,25 +53,11 @@ public static KafkaInstrumentationHeadersHelper get() { public KafkaInstrumentationHeadersHelper(Tracer tracer) { this.tracer = tracer; - Pattern pattern = Pattern.compile("[^a-zA-Z0-9]"); - Set traceHeaders = tracer.getTraceHeaderNames(); - for (String traceHeader : traceHeaders) { - String binaryTraceHeader = pattern.matcher(traceHeader).replaceAll(""); - if (!binaryTraceHeaders.add(binaryTraceHeader)) { - throw new IllegalStateException("Ambiguous translation of trace headers into binary format: " + traceHeaders); - } - translatedTraceHeaders.put(traceHeader, binaryTraceHeader); - } - } - - public String resolvePossibleTraceHeader(String header) { - String translation = translatedTraceHeaders.get(header); - return translation == null ? header : translation; } public Iterator> wrapConsumerRecordIterator(Iterator> consumerRecordIterator) { try { - return new ConsumerRecordsIteratorWrapper(consumerRecordIterator, tracer, binaryTraceHeaders); + return new ConsumerRecordsIteratorWrapper(consumerRecordIterator, tracer); } catch (Throwable throwable) { logger.debug("Failed to wrap Kafka ConsumerRecords iterator", throwable); return consumerRecordIterator; @@ -87,7 +66,7 @@ public String resolvePossibleTraceHeader(String header) { public Iterable> wrapConsumerRecordIterable(Iterable> consumerRecordIterable) { try { - return new ConsumerRecordsIterableWrapper(consumerRecordIterable, tracer, binaryTraceHeaders); + return new ConsumerRecordsIterableWrapper(consumerRecordIterable, tracer); } catch (Throwable throwable) { logger.debug("Failed to wrap Kafka ConsumerRecords", throwable); return consumerRecordIterable; @@ -96,7 +75,7 @@ public String resolvePossibleTraceHeader(String header) { public List> wrapConsumerRecordList(List> consumerRecordList) { try { - return new ConsumerRecordsListWrapper(consumerRecordList, tracer, binaryTraceHeaders); + return new ConsumerRecordsListWrapper(consumerRecordList, tracer); } catch (Throwable throwable) { logger.debug("Failed to wrap Kafka ConsumerRecords list", throwable); return consumerRecordList; @@ -138,10 +117,10 @@ public void addSpanLinks(@Nullable ConsumerRecords records, AbstractSpan toPropagate, ProducerRecord producerRecord) { - toPropagate.propagateContext(producerRecord, KafkaRecordHeaderAccessor.instance()); + toPropagate.propagateContext(producerRecord, KafkaRecordHeaderAccessor.instance(), null); } public void removeTraceContextHeader(ProducerRecord producerRecord) { - HeaderUtils.remove(binaryTraceHeaders, producerRecord, KafkaRecordHeaderAccessor.instance()); + HeaderUtils.remove(tracer.getTraceHeaderNames(), producerRecord, KafkaRecordHeaderAccessor.instance()); } } diff --git a/apm-agent-plugins/apm-kafka-plugin/apm-kafka-headers-plugin/src/main/java/co/elastic/apm/agent/kafka/helper/KafkaRecordHeaderAccessor.java b/apm-agent-plugins/apm-kafka-plugin/apm-kafka-headers-plugin/src/main/java/co/elastic/apm/agent/kafka/helper/KafkaRecordHeaderAccessor.java index 4ea45c0fc2..44085f2547 100644 --- a/apm-agent-plugins/apm-kafka-plugin/apm-kafka-headers-plugin/src/main/java/co/elastic/apm/agent/kafka/helper/KafkaRecordHeaderAccessor.java +++ b/apm-agent-plugins/apm-kafka-plugin/apm-kafka-headers-plugin/src/main/java/co/elastic/apm/agent/kafka/helper/KafkaRecordHeaderAccessor.java @@ -18,92 +18,148 @@ */ package co.elastic.apm.agent.kafka.helper; -import co.elastic.apm.agent.tracer.dispatch.BinaryHeaderGetter; -import co.elastic.apm.agent.tracer.dispatch.BinaryHeaderSetter; +import co.elastic.apm.agent.sdk.logging.Logger; +import co.elastic.apm.agent.sdk.logging.LoggerFactory; import co.elastic.apm.agent.tracer.dispatch.HeaderRemover; +import co.elastic.apm.agent.tracer.dispatch.UTF8ByteHeaderGetter; +import co.elastic.apm.agent.tracer.dispatch.UTF8ByteHeaderSetter; +import co.elastic.apm.agent.tracer.util.HexUtils; import org.apache.kafka.clients.consumer.ConsumerRecord; import org.apache.kafka.clients.producer.ProducerRecord; import org.apache.kafka.common.header.Header; -import co.elastic.apm.agent.sdk.logging.Logger; -import co.elastic.apm.agent.sdk.logging.LoggerFactory; import javax.annotation.Nullable; -import java.util.HashMap; -import java.util.Map; +/** + * This header accessor implements backwards compatibility for the legacy binary "elasticapmtraceparent" header. + * This is done by translating the textual "elastic-apm-traceparent" representation on the fly to the legacy binary representation. + * The legacy binary header format is as follows: + *
+ *      traceparent     = version version_format
+ *      version         = 1BYTE                   ; version is 0 in the current spec
+ *      version_format  = "{ 0x0 }" trace-id "{ 0x1 }" parent-id "{ 0x2 }" trace-flags
+ *      trace-id        = 16BYTES
+ *      parent-id       = 8BYTES
+ *      trace-flags     = 1BYTE  ; only the least significant bit is used
+ * 
+ * For example: + *
+ * elasticapmtraceparent:   [0,
+ *                           0, 75, 249, 47, 53, 119, 179, 77, 166, 163, 206, 146, 157, 0, 14, 71, 54,
+ *                           1, 52, 240, 103, 170, 11, 169, 2, 183,
+ *                           2, 1]
+ * 
+ */ @SuppressWarnings("rawtypes") -public class KafkaRecordHeaderAccessor implements BinaryHeaderGetter, BinaryHeaderSetter, +public class KafkaRecordHeaderAccessor implements UTF8ByteHeaderGetter, UTF8ByteHeaderSetter, HeaderRemover { public static final Logger logger = LoggerFactory.getLogger(KafkaRecordHeaderAccessor.class); private static final KafkaRecordHeaderAccessor INSTANCE = new KafkaRecordHeaderAccessor(); - - private static final ThreadLocal> threadLocalHeaderMap = new ThreadLocal<>(); + public static final String ELASTIC_TRACE_PARENT_TEXTUAL_HEADER_NAME = "elastic-apm-traceparent"; + public static final String LEGACY_BINARY_TRACEPARENT = "elasticapmtraceparent"; public static KafkaRecordHeaderAccessor instance() { return INSTANCE; } - private final KafkaInstrumentationHeadersHelper helper = KafkaInstrumentationHeadersHelper.get(); - @Nullable @Override public byte[] getFirstHeader(String headerName, ConsumerRecord record) { - headerName = helper.resolvePossibleTraceHeader(headerName); - Header traceParentHeader = record.headers().lastHeader(headerName); - if (traceParentHeader != null) { - return traceParentHeader.value(); + if (headerName.equals(ELASTIC_TRACE_PARENT_TEXTUAL_HEADER_NAME)) { + Header header = record.headers().lastHeader(LEGACY_BINARY_TRACEPARENT); + if (header != null) { + return convertLegacyBinaryTraceparentToTextHeader(header.value()); + } + } else { + Header header = record.headers().lastHeader(headerName); + if (header != null) { + return header.value(); + } } return null; } + @Override public void forEach(String headerName, ConsumerRecord carrier, S state, HeaderConsumer consumer) { - headerName = helper.resolvePossibleTraceHeader(headerName); - for (Header header : carrier.headers().headers(headerName)) { - consumer.accept(header.value(), state); + if (headerName.equals(ELASTIC_TRACE_PARENT_TEXTUAL_HEADER_NAME)) { + for (Header header : carrier.headers().headers(LEGACY_BINARY_TRACEPARENT)) { + byte[] convertedHeader = convertLegacyBinaryTraceparentToTextHeader(header.value()); + if (convertedHeader != null) { + consumer.accept(convertedHeader, state); + } + } + } else { + for (Header header : carrier.headers().headers(headerName)) { + consumer.accept(header.value(), state); + } } } - @Override - @Nullable - public byte[] getFixedLengthByteArray(String headerName, int length) { - headerName = helper.resolvePossibleTraceHeader(headerName); - Map headerMap = threadLocalHeaderMap.get(); - if (headerMap == null) { - headerMap = new HashMap<>(); - threadLocalHeaderMap.set(headerMap); - } - ElasticHeaderImpl header = headerMap.get(headerName); - if (header == null) { - header = new ElasticHeaderImpl(headerName, length); - headerMap.put(headerName, header); - } - return header.valueForSetting(); - } @Override public void setHeader(String headerName, byte[] headerValue, ProducerRecord record) { - headerName = helper.resolvePossibleTraceHeader(headerName); - ElasticHeaderImpl header = null; - Map headerMap = threadLocalHeaderMap.get(); - if (headerMap != null) { - header = headerMap.get(headerName); - } - // Not accessing the value through the method, as it checks the thread - if (header == null || header.value == null) { - logger.warn("No header cached for {}, allocating byte array for each record", headerName); - record.headers().add(headerName, headerValue); + // TODO: this currently allocates! Prior to the removal of binary propagation, + // custom thread-local cached headers instances with cached byte arrays were used. + // we can't use ThreadLocals due to loom, but we could use a bounded LRU cache instead + remove(headerName, record); + if (headerName.equals(ELASTIC_TRACE_PARENT_TEXTUAL_HEADER_NAME)) { + record.headers().add(LEGACY_BINARY_TRACEPARENT, convertTextHeaderToLegacyBinaryTraceparent(headerValue)); } else { - record.headers().add(header); + record.headers().add(headerName, headerValue); } } @Override public void remove(String headerName, ProducerRecord carrier) { - headerName = helper.resolvePossibleTraceHeader(headerName); - carrier.headers().remove(headerName); + if (headerName.equals(ELASTIC_TRACE_PARENT_TEXTUAL_HEADER_NAME)) { + carrier.headers().remove(LEGACY_BINARY_TRACEPARENT); + } else { + carrier.headers().remove(headerName); + } + } + + + private byte[] convertTextHeaderToLegacyBinaryTraceparent(byte[] asciiTextHeaderValue) { + //input is guaranteed to be a valid w3c header, no need to validate + byte[] buffer = new byte[29]; + buffer[0] = 0; //version + buffer[1] = 0; //trace-id field-id + HexUtils.decodeAscii(asciiTextHeaderValue, 3, 32, buffer, 2); //read 16 byte traceid + buffer[18] = 1; //parent-id field-id + HexUtils.decodeAscii(asciiTextHeaderValue, 36, 16, buffer, 19); //read 8 byte parentid + buffer[27] = 2; //flags field-id + buffer[28] = HexUtils.getNextByteAscii(asciiTextHeaderValue, 53); //flags + return buffer; } + @Nullable + private byte[] convertLegacyBinaryTraceparentToTextHeader(byte[] binaryHeader) { + if (binaryHeader.length < 29) { + logger.warn("The elasticapmtraceparent header has to be at least 29 bytes long, but is not"); + return null; + } + try { + byte[] asciiTextHeader = { + '0', '0', '-', + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //traceId + '-', + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //parentId + '-', + '0', '0' //flags + }; + HexUtils.writeBytesAsHexAscii(binaryHeader, 2, 16, asciiTextHeader, 3); + HexUtils.writeBytesAsHexAscii(binaryHeader, 19, 8, asciiTextHeader, 36); + byte flags = binaryHeader[28]; + HexUtils.writeBytesAsHexAscii(flags, asciiTextHeader, 53); + return asciiTextHeader; + } catch (Exception e) { + logger.warn("Failed to parse legacy elasticapmtraceparent header", e); + } + return null; + } + + } diff --git a/apm-agent-plugins/apm-kafka-plugin/apm-kafka-headers-plugin/src/test/java/co/elastic/apm/agent/kafka/KafkaIT.java b/apm-agent-plugins/apm-kafka-plugin/apm-kafka-headers-plugin/src/test/java/co/elastic/apm/agent/kafka/KafkaIT.java index 5d530111b8..48508ca34c 100644 --- a/apm-agent-plugins/apm-kafka-plugin/apm-kafka-headers-plugin/src/test/java/co/elastic/apm/agent/kafka/KafkaIT.java +++ b/apm-agent-plugins/apm-kafka-plugin/apm-kafka-headers-plugin/src/test/java/co/elastic/apm/agent/kafka/KafkaIT.java @@ -19,9 +19,10 @@ package co.elastic.apm.agent.kafka; import co.elastic.apm.agent.AbstractInstrumentationTest; +import co.elastic.apm.agent.common.util.WildcardMatcher; import co.elastic.apm.agent.configuration.CoreConfiguration; -import co.elastic.apm.agent.tracer.configuration.MessagingConfiguration; import co.elastic.apm.agent.impl.TracerInternalApiUtils; +import co.elastic.apm.agent.impl.baggage.BaggageContext; import co.elastic.apm.agent.impl.context.Destination; import co.elastic.apm.agent.impl.context.Headers; import co.elastic.apm.agent.impl.context.Message; @@ -29,12 +30,12 @@ import co.elastic.apm.agent.impl.context.TransactionContext; import co.elastic.apm.agent.impl.sampling.ConstantSampler; import co.elastic.apm.agent.impl.sampling.Sampler; -import co.elastic.apm.agent.tracer.Outcome; import co.elastic.apm.agent.impl.transaction.Span; import co.elastic.apm.agent.impl.transaction.TraceContext; import co.elastic.apm.agent.impl.transaction.Transaction; -import co.elastic.apm.agent.common.util.WildcardMatcher; import co.elastic.apm.agent.testutils.TestContainersUtils; +import co.elastic.apm.agent.tracer.Outcome; +import co.elastic.apm.agent.tracer.configuration.MessagingConfiguration; import org.apache.kafka.clients.consumer.ConsumerConfig; import org.apache.kafka.clients.consumer.ConsumerRecord; import org.apache.kafka.clients.consumer.ConsumerRecords; @@ -297,14 +298,19 @@ public void testIgnoreTopic() { @Test public void testTransactionCreationWithoutContext() { - testScenario = TestScenario.NO_CONTEXT_PROPAGATION; + testScenario = TestScenario.NO_TRACE_CONTEXT_PROPAGATION; consumerThread.setIterationMode(RecordIterationMode.ITERABLE_FOR); //noinspection ConstantConditions tracer.currentTransaction().deactivate().end(); reporter.reset(); - // Send without context + // Send without trace context, but verify baggage is still propagated + BaggageContext baggageContext = tracer.currentContext().withUpdatedBaggage() + .put("test_baggage", "baggage_val") + .buildContext() + .activate(); sendTwoRecordsAndConsumeReplies(); + baggageContext.deactivate(); // We expect two transactions from records read from the request topic, each creating a send span as well. // In addition, we expect two transactions from the main test thread, iterating over reply messages. @@ -320,6 +326,10 @@ public void testTransactionCreationWithoutContext() { verifyKafkaTransactionContents(transactions.get(1), null, null, REQUEST_TOPIC); verifyKafkaTransactionContents(transactions.get(2), sendSpan1, null, REPLY_TOPIC); verifyKafkaTransactionContents(transactions.get(3), sendSpan2, null, REPLY_TOPIC); + assertThat(transactions).allSatisfy(tx -> assertThat(tx.getBaggage()) + .hasSize(1) + .containsEntry("test_baggage", "baggage_val") + ); } @Test @@ -355,7 +365,7 @@ private void sendTwoRecordsAndConsumeReplies() { if (testScenario != TestScenario.IGNORE_REQUEST_TOPIC && testScenario != TestScenario.AGENT_PAUSED && testScenario != TestScenario.BATCH_PROCESSING) { await().atMost(2000, MILLISECONDS).until(() -> reporter.getTransactions().size() == 2); if (testScenario != TestScenario.NON_SAMPLED_TRANSACTION) { - int expectedSpans = (testScenario == TestScenario.NO_CONTEXT_PROPAGATION) ? 2 : 4; + int expectedSpans = (testScenario == TestScenario.NO_TRACE_CONTEXT_PROPAGATION) ? 2 : 4; await().atMost(500, MILLISECONDS).until(() -> reporter.getSpans().size() == expectedSpans); } } @@ -610,7 +620,7 @@ enum TestScenario { SANITIZED_HEADER, IGNORE_REQUEST_TOPIC, AGENT_PAUSED, - NO_CONTEXT_PROPAGATION, + NO_TRACE_CONTEXT_PROPAGATION, TOPIC_ADDRESS_COLLECTION_DISABLED, NON_SAMPLED_TRANSACTION, BATCH_PROCESSING diff --git a/apm-agent-plugins/apm-kafka-plugin/apm-kafka-headers-plugin/src/test/java/co/elastic/apm/agent/kafka/KafkaRecordHeaderAccessorTest.java b/apm-agent-plugins/apm-kafka-plugin/apm-kafka-headers-plugin/src/test/java/co/elastic/apm/agent/kafka/KafkaRecordHeaderAccessorTest.java new file mode 100644 index 0000000000..91deb8a387 --- /dev/null +++ b/apm-agent-plugins/apm-kafka-plugin/apm-kafka-headers-plugin/src/test/java/co/elastic/apm/agent/kafka/KafkaRecordHeaderAccessorTest.java @@ -0,0 +1,141 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package co.elastic.apm.agent.kafka; + +import co.elastic.apm.agent.kafka.helper.KafkaRecordHeaderAccessor; +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.apache.kafka.clients.producer.ProducerRecord; +import org.apache.kafka.common.header.Headers; +import org.apache.kafka.common.header.internals.RecordHeaders; +import org.apache.kafka.common.record.TimestampType; +import org.junit.jupiter.api.Test; + +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; + +public class KafkaRecordHeaderAccessorTest { + + @Test + public void testLegacyHeaderSetterTranslation() { + String W3C_HEADER = "00-0af7651916cd43dd8448eb211c80319c-00f067aa0ba902b7-01"; + byte[] W3C_HEADER_BYTES = W3C_HEADER.getBytes(StandardCharsets.UTF_8); + byte[] binary_header = { + 0, //version + 0, //trace-id field-id + 0x0a, (byte) 0xf7, 0x65, 0x19, 0x16, (byte) 0xcd, 0x43, (byte) 0xdd, + (byte) 0x84, 0x48, (byte) 0xeb, 0x21, 0x1c, (byte) 0x80, 0x31, (byte) 0x9c, + 1, //parent-id field-id + 0x00, (byte) 0xf0, 0x67, (byte) 0xaa, 0x0b, (byte) 0xa9, 0x02, (byte) 0xb7, + 2, //flags field-id + 0x01, + }; + ProducerRecord dummyRecord = new ProducerRecord("", 0, "", ""); + //set twice to ensure it is not added twice + KafkaRecordHeaderAccessor.instance().setHeader("elastic-apm-traceparent", W3C_HEADER_BYTES, dummyRecord); + KafkaRecordHeaderAccessor.instance().setHeader("elastic-apm-traceparent", W3C_HEADER_BYTES, dummyRecord); + + assertThat(dummyRecord.headers()).hasSize(1); + assertThat(dummyRecord.headers().lastHeader("elasticapmtraceparent").value()) + .isEqualTo(binary_header); + + KafkaRecordHeaderAccessor.instance().remove("elastic-apm-traceparent", dummyRecord); + assertThat(dummyRecord.headers()).hasSize(0); + } + + + @Test + public void testLegacyHeaderGetterTranslation() { + String W3C_HEADER = "00-0af7651916cd43dd8448eb211c80319c-00f067aa0ba902b7-01"; + byte[] binary_header = { + 0, //version + 0, //trace-id field-id + 0x0a, (byte) 0xf7, 0x65, 0x19, 0x16, (byte) 0xcd, 0x43, (byte) 0xdd, + (byte) 0x84, 0x48, (byte) 0xeb, 0x21, 0x1c, (byte) 0x80, 0x31, (byte) 0x9c, + 1, //parent-id field-id + 0x00, (byte) 0xf0, 0x67, (byte) 0xaa, 0x0b, (byte) 0xa9, 0x02, (byte) 0xb7, + 2, //flags field-id + 0x01, + }; + Headers headers = new RecordHeaders().add("elasticapmtraceparent", binary_header); + ConsumerRecord dummyRecord = new ConsumerRecord("", 0, 0, -1L, TimestampType.NO_TIMESTAMP_TYPE, -1, -1, "", "", headers, Optional.empty()); + + byte[] headerText = KafkaRecordHeaderAccessor.instance().getFirstHeader("elastic-apm-traceparent", dummyRecord); + assertThat(new String(headerText, StandardCharsets.UTF_8)).isEqualTo(W3C_HEADER); + + List allHeaders = new ArrayList<>(); + KafkaRecordHeaderAccessor.instance().forEach("elastic-apm-traceparent", dummyRecord, null, + (val, state) -> allHeaders.add(new String(val, StandardCharsets.UTF_8))); + assertThat(allHeaders).containsExactly(W3C_HEADER); + } + + + @Test + public void testInvalidLegacyHeaderGetterTranslation() { + byte[] binary_header = {42}; + Headers headers = new RecordHeaders().add("elasticapmtraceparent", binary_header); + ConsumerRecord dummyRecord = new ConsumerRecord("", 0, 0, -1L, TimestampType.NO_TIMESTAMP_TYPE, -1, -1, "", "", headers, Optional.empty()); + + byte[] headerText = KafkaRecordHeaderAccessor.instance().getFirstHeader("elastic-apm-traceparent", dummyRecord); + assertThat(headerText).isNull(); + + List allHeaders = new ArrayList<>(); + KafkaRecordHeaderAccessor.instance().forEach("elastic-apm-traceparent", dummyRecord, null, + (val, state) -> allHeaders.add(new String(val, StandardCharsets.UTF_8))); + assertThat(allHeaders).isEmpty(); + } + + + @Test + public void testW3cHeaderSetter() { + String W3C_HEADER = "00-0af7651916cd43dd8448eb211c80319c-00f067aa0ba902b7-01"; + byte[] W3C_HEADER_BYTES = W3C_HEADER.getBytes(StandardCharsets.UTF_8); + ProducerRecord dummyRecord = new ProducerRecord("", 0, "", ""); + //set twice to ensure it is not added twice + KafkaRecordHeaderAccessor.instance().setHeader("traceparent", W3C_HEADER_BYTES, dummyRecord); + KafkaRecordHeaderAccessor.instance().setHeader("traceparent", W3C_HEADER_BYTES, dummyRecord); + + assertThat(dummyRecord.headers()).hasSize(1); + assertThat(dummyRecord.headers().lastHeader("traceparent").value()) + .isEqualTo(W3C_HEADER.getBytes(StandardCharsets.UTF_8)); + + KafkaRecordHeaderAccessor.instance().remove("traceparent", dummyRecord); + assertThat(dummyRecord.headers()).hasSize(0); + } + + + @Test + public void testW3CHeaderGetter() { + String W3C_HEADER = "00-0af7651916cd43dd8448eb211c80319c-00f067aa0ba902b7-01"; + Headers headers = new RecordHeaders().add("traceparent", W3C_HEADER.getBytes(StandardCharsets.UTF_8)); + ConsumerRecord dummyRecord = new ConsumerRecord("", 0, 0, -1L, TimestampType.NO_TIMESTAMP_TYPE, -1, -1, "", "", headers, Optional.empty()); + + byte[] headerText = KafkaRecordHeaderAccessor.instance().getFirstHeader("traceparent", dummyRecord); + assertThat(new String(headerText, StandardCharsets.UTF_8)).isEqualTo(W3C_HEADER); + + List allHeaders = new ArrayList<>(); + KafkaRecordHeaderAccessor.instance().forEach("traceparent", dummyRecord, null, + (val, state) -> allHeaders.add(new String(val, StandardCharsets.UTF_8))); + assertThat(allHeaders).containsExactly(W3C_HEADER); + } + +} diff --git a/apm-agent-plugins/apm-kafka-plugin/apm-kafka-spring-plugin/pom.xml b/apm-agent-plugins/apm-kafka-plugin/apm-kafka-spring-plugin/pom.xml index 9bd8648a17..e75b6f5629 100644 --- a/apm-agent-plugins/apm-kafka-plugin/apm-kafka-spring-plugin/pom.xml +++ b/apm-agent-plugins/apm-kafka-plugin/apm-kafka-spring-plugin/pom.xml @@ -4,7 +4,7 @@ apm-kafka-plugin co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/apm-agent-plugins/apm-kafka-plugin/pom.xml b/apm-agent-plugins/apm-kafka-plugin/pom.xml index 53a903f07b..7569fb57f2 100644 --- a/apm-agent-plugins/apm-kafka-plugin/pom.xml +++ b/apm-agent-plugins/apm-kafka-plugin/pom.xml @@ -3,7 +3,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/apm-agent-plugins/apm-logging-plugin/apm-jboss-logging-plugin/pom.xml b/apm-agent-plugins/apm-logging-plugin/apm-jboss-logging-plugin/pom.xml index b3c636400f..36b506a115 100644 --- a/apm-agent-plugins/apm-logging-plugin/apm-jboss-logging-plugin/pom.xml +++ b/apm-agent-plugins/apm-logging-plugin/apm-jboss-logging-plugin/pom.xml @@ -5,7 +5,7 @@ apm-logging-plugin co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-jboss-logging-plugin diff --git a/apm-agent-plugins/apm-logging-plugin/apm-jboss-logging-plugin/src/test/java/co/elastic/apm/agent/jbosslogging/correlation/JBossLogManagerCorrelationInstrumentationTest.java b/apm-agent-plugins/apm-logging-plugin/apm-jboss-logging-plugin/src/test/java/co/elastic/apm/agent/jbosslogging/correlation/JBossLogManagerCorrelationInstrumentationTest.java index 61357f37f0..081905a8de 100644 --- a/apm-agent-plugins/apm-logging-plugin/apm-jboss-logging-plugin/src/test/java/co/elastic/apm/agent/jbosslogging/correlation/JBossLogManagerCorrelationInstrumentationTest.java +++ b/apm-agent-plugins/apm-logging-plugin/apm-jboss-logging-plugin/src/test/java/co/elastic/apm/agent/jbosslogging/correlation/JBossLogManagerCorrelationInstrumentationTest.java @@ -116,7 +116,7 @@ protected void doPublish(ExtLogRecord record) { assertThat(traceParent).isNotNull(); Map textHeaderMap = Map.of(W3C_TRACE_PARENT_TEXTUAL_HEADER_NAME, traceParent); TraceContext childTraceContext = TraceContext.with64BitId(tracer); - TraceContext.>getFromTraceContextTextHeaders().asChildOf(childTraceContext, textHeaderMap, TextHeaderMapAccessor.INSTANCE); + childTraceContext.asChildOf(textHeaderMap, TextHeaderMapAccessor.INSTANCE); System.out.println("childTraceContext = " + childTraceContext); assertThat(childTraceContext.getTraceId().toString()).isEqualTo(traceId.toString()); assertThat(childTraceContext.getParentId().toString()).isEqualTo(transactionId.toString()); diff --git a/apm-agent-plugins/apm-logging-plugin/apm-jboss-logging-plugin/src/test/java/co/elastic/apm/agent/jbosslogging/correlation/JBossLoggingCorrelationInstrumentationTest.java b/apm-agent-plugins/apm-logging-plugin/apm-jboss-logging-plugin/src/test/java/co/elastic/apm/agent/jbosslogging/correlation/JBossLoggingCorrelationInstrumentationTest.java index 97407028de..af869e005f 100644 --- a/apm-agent-plugins/apm-logging-plugin/apm-jboss-logging-plugin/src/test/java/co/elastic/apm/agent/jbosslogging/correlation/JBossLoggingCorrelationInstrumentationTest.java +++ b/apm-agent-plugins/apm-logging-plugin/apm-jboss-logging-plugin/src/test/java/co/elastic/apm/agent/jbosslogging/correlation/JBossLoggingCorrelationInstrumentationTest.java @@ -120,7 +120,7 @@ public void publish(LogRecord record) { assertThat(traceParent).isNotNull(); Map textHeaderMap = Map.of(W3C_TRACE_PARENT_TEXTUAL_HEADER_NAME, traceParent); TraceContext childTraceContext = TraceContext.with64BitId(tracer); - TraceContext.>getFromTraceContextTextHeaders().asChildOf(childTraceContext, textHeaderMap, TextHeaderMapAccessor.INSTANCE); + childTraceContext.asChildOf(textHeaderMap, TextHeaderMapAccessor.INSTANCE); System.out.println("childTraceContext = " + childTraceContext); assertThat(childTraceContext.getTraceId().toString()).isEqualTo(traceId.toString()); assertThat(childTraceContext.getParentId().toString()).isEqualTo(transactionId.toString()); diff --git a/apm-agent-plugins/apm-logging-plugin/apm-jul-plugin/pom.xml b/apm-agent-plugins/apm-logging-plugin/apm-jul-plugin/pom.xml index 54f1a3eb72..49589b05f3 100644 --- a/apm-agent-plugins/apm-logging-plugin/apm-jul-plugin/pom.xml +++ b/apm-agent-plugins/apm-logging-plugin/apm-jul-plugin/pom.xml @@ -5,7 +5,7 @@ apm-logging-plugin co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-jul-plugin diff --git a/apm-agent-plugins/apm-logging-plugin/apm-log4j1-plugin/pom.xml b/apm-agent-plugins/apm-logging-plugin/apm-log4j1-plugin/pom.xml index 864526edfd..7db2429557 100644 --- a/apm-agent-plugins/apm-logging-plugin/apm-log4j1-plugin/pom.xml +++ b/apm-agent-plugins/apm-logging-plugin/apm-log4j1-plugin/pom.xml @@ -5,7 +5,7 @@ apm-logging-plugin co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-log4j1-plugin diff --git a/apm-agent-plugins/apm-logging-plugin/apm-log4j2-plugin/pom.xml b/apm-agent-plugins/apm-logging-plugin/apm-log4j2-plugin/pom.xml index e210bc8b0e..2947ec3339 100644 --- a/apm-agent-plugins/apm-logging-plugin/apm-log4j2-plugin/pom.xml +++ b/apm-agent-plugins/apm-logging-plugin/apm-log4j2-plugin/pom.xml @@ -5,7 +5,7 @@ apm-logging-plugin co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-log4j2-plugin diff --git a/apm-agent-plugins/apm-logging-plugin/apm-log4j2-plugin/src/main/java/co/elastic/apm/agent/log4j2/correlation/Log4j2_7PlusLogCorrelationHelper.java b/apm-agent-plugins/apm-logging-plugin/apm-log4j2-plugin/src/main/java/co/elastic/apm/agent/log4j2/correlation/Log4j2_7PlusLogCorrelationHelper.java index 65e4971f0c..0551af209a 100644 --- a/apm-agent-plugins/apm-logging-plugin/apm-log4j2-plugin/src/main/java/co/elastic/apm/agent/log4j2/correlation/Log4j2_7PlusLogCorrelationHelper.java +++ b/apm-agent-plugins/apm-logging-plugin/apm-log4j2-plugin/src/main/java/co/elastic/apm/agent/log4j2/correlation/Log4j2_7PlusLogCorrelationHelper.java @@ -36,7 +36,7 @@ public class Log4j2_7PlusLogCorrelationHelper extends AbstractLogCorrelationHelp @Override protected boolean addToMdc() { - if (tracer.currentTransaction() == null && ErrorCapture.getActive() == null) { + if (tracer.currentTransaction() == null && tracer.getActiveError() == null) { return false; } ThreadContext.putAll(CorrelationIdMapAdapter.get()); diff --git a/apm-agent-plugins/apm-logging-plugin/apm-logback-plugin/apm-logback-plugin-impl/pom.xml b/apm-agent-plugins/apm-logging-plugin/apm-logback-plugin/apm-logback-plugin-impl/pom.xml index ff69f00789..e9ddd64e3f 100644 --- a/apm-agent-plugins/apm-logging-plugin/apm-logback-plugin/apm-logback-plugin-impl/pom.xml +++ b/apm-agent-plugins/apm-logging-plugin/apm-logback-plugin/apm-logback-plugin-impl/pom.xml @@ -5,7 +5,7 @@ apm-logback-plugin co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-logback-plugin-impl diff --git a/apm-agent-plugins/apm-logging-plugin/apm-logback-plugin/apm-logback-plugin-legacy-tests/pom.xml b/apm-agent-plugins/apm-logging-plugin/apm-logback-plugin/apm-logback-plugin-legacy-tests/pom.xml index 494240a9cf..91b549a12d 100644 --- a/apm-agent-plugins/apm-logging-plugin/apm-logback-plugin/apm-logback-plugin-legacy-tests/pom.xml +++ b/apm-agent-plugins/apm-logging-plugin/apm-logback-plugin/apm-logback-plugin-legacy-tests/pom.xml @@ -5,7 +5,7 @@ apm-logback-plugin co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-logback-plugin-legacy-tests diff --git a/apm-agent-plugins/apm-logging-plugin/apm-logback-plugin/pom.xml b/apm-agent-plugins/apm-logging-plugin/apm-logback-plugin/pom.xml index d689c771a0..c1539fa01d 100644 --- a/apm-agent-plugins/apm-logging-plugin/apm-logback-plugin/pom.xml +++ b/apm-agent-plugins/apm-logging-plugin/apm-logback-plugin/pom.xml @@ -5,7 +5,7 @@ apm-logging-plugin co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-logback-plugin diff --git a/apm-agent-plugins/apm-logging-plugin/apm-logging-plugin-common/pom.xml b/apm-agent-plugins/apm-logging-plugin/apm-logging-plugin-common/pom.xml index b15abe36aa..d064729da2 100644 --- a/apm-agent-plugins/apm-logging-plugin/apm-logging-plugin-common/pom.xml +++ b/apm-agent-plugins/apm-logging-plugin/apm-logging-plugin-common/pom.xml @@ -5,7 +5,7 @@ apm-logging-plugin co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-logging-plugin-common diff --git a/apm-agent-plugins/apm-logging-plugin/apm-logging-plugin-common/src/main/java/co/elastic/apm/agent/loginstr/correlation/AbstractLogCorrelationHelper.java b/apm-agent-plugins/apm-logging-plugin/apm-logging-plugin-common/src/main/java/co/elastic/apm/agent/loginstr/correlation/AbstractLogCorrelationHelper.java index a939ca184f..09828a84d0 100644 --- a/apm-agent-plugins/apm-logging-plugin/apm-logging-plugin-common/src/main/java/co/elastic/apm/agent/loginstr/correlation/AbstractLogCorrelationHelper.java +++ b/apm-agent-plugins/apm-logging-plugin/apm-logging-plugin-common/src/main/java/co/elastic/apm/agent/loginstr/correlation/AbstractLogCorrelationHelper.java @@ -19,8 +19,8 @@ package co.elastic.apm.agent.loginstr.correlation; import co.elastic.apm.agent.tracer.AbstractSpan; +import co.elastic.apm.agent.tracer.ErrorCapture; import co.elastic.apm.agent.tracer.GlobalTracer; -import co.elastic.apm.agent.impl.error.ErrorCapture; import co.elastic.apm.agent.sdk.state.CallDepth; import co.elastic.apm.agent.sdk.state.GlobalState; import co.elastic.apm.agent.tracer.Tracer; @@ -80,7 +80,7 @@ protected boolean addToMdc() { addToMdc(TRANSACTION_ID_MDC_KEY, activeSpan.getTraceContext().getTransactionId().toString()); addedToMdc = true; } - ErrorCapture activeError = ErrorCapture.getActive(); + ErrorCapture activeError = tracer.getActiveError(); if (activeError != null) { addToMdc(ERROR_ID_MDC_KEY, activeError.getTraceContext().getId().toString()); addedToMdc = true; diff --git a/apm-agent-plugins/apm-logging-plugin/apm-logging-plugin-common/src/main/java/co/elastic/apm/agent/loginstr/correlation/CorrelationIdMapAdapter.java b/apm-agent-plugins/apm-logging-plugin/apm-logging-plugin-common/src/main/java/co/elastic/apm/agent/loginstr/correlation/CorrelationIdMapAdapter.java index 7262590c8e..7548453060 100644 --- a/apm-agent-plugins/apm-logging-plugin/apm-logging-plugin-common/src/main/java/co/elastic/apm/agent/loginstr/correlation/CorrelationIdMapAdapter.java +++ b/apm-agent-plugins/apm-logging-plugin/apm-logging-plugin-common/src/main/java/co/elastic/apm/agent/loginstr/correlation/CorrelationIdMapAdapter.java @@ -19,8 +19,8 @@ package co.elastic.apm.agent.loginstr.correlation; import co.elastic.apm.agent.tracer.AbstractSpan; +import co.elastic.apm.agent.tracer.ErrorCapture; import co.elastic.apm.agent.tracer.GlobalTracer; -import co.elastic.apm.agent.impl.error.ErrorCapture; import co.elastic.apm.agent.tracer.Tracer; import javax.annotation.Nullable; @@ -71,7 +71,7 @@ public String call() { @Override @Nullable public String call() { - ErrorCapture error = ErrorCapture.getActive(); + ErrorCapture error = tracer.getActiveError(); if (error == null) { return null; } diff --git a/apm-agent-plugins/apm-logging-plugin/apm-logging-plugin-common/src/main/java/co/elastic/apm/agent/loginstr/error/LoggerErrorHelper.java b/apm-agent-plugins/apm-logging-plugin/apm-logging-plugin-common/src/main/java/co/elastic/apm/agent/loginstr/error/LoggerErrorHelper.java index a534c19548..ce88c8b356 100644 --- a/apm-agent-plugins/apm-logging-plugin/apm-logging-plugin-common/src/main/java/co/elastic/apm/agent/loginstr/error/LoggerErrorHelper.java +++ b/apm-agent-plugins/apm-logging-plugin/apm-logging-plugin-common/src/main/java/co/elastic/apm/agent/loginstr/error/LoggerErrorHelper.java @@ -18,7 +18,7 @@ */ package co.elastic.apm.agent.loginstr.error; -import co.elastic.apm.agent.impl.error.ErrorCapture; +import co.elastic.apm.agent.tracer.ErrorCapture; import co.elastic.apm.agent.sdk.internal.util.PrivilegedActionUtils; import co.elastic.apm.agent.sdk.state.CallDepth; import co.elastic.apm.agent.tracer.Tracer; @@ -46,8 +46,7 @@ public LoggerErrorHelper(Class adviceClass, Tracer tracer) { public Object enter(@Nullable Throwable exception, Class originClass) { if (!callDepth.isNestedCallAndIncrement()) { if (exception != null) { - co.elastic.apm.agent.impl.Tracer required = tracer.require(co.elastic.apm.agent.impl.Tracer.class); - ErrorCapture error = required.captureException(exception, required.currentContext(), PrivilegedActionUtils.getClassLoader(originClass)); + ErrorCapture error = tracer.captureException(exception, PrivilegedActionUtils.getClassLoader(originClass)); if (error != null) { error.activate(); } diff --git a/apm-agent-plugins/apm-logging-plugin/apm-slf4j-plugin/pom.xml b/apm-agent-plugins/apm-logging-plugin/apm-slf4j-plugin/pom.xml index c91e7a940a..58975cda11 100644 --- a/apm-agent-plugins/apm-logging-plugin/apm-slf4j-plugin/pom.xml +++ b/apm-agent-plugins/apm-logging-plugin/apm-slf4j-plugin/pom.xml @@ -5,7 +5,7 @@ apm-logging-plugin co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-slf4j-plugin diff --git a/apm-agent-plugins/apm-logging-plugin/apm-tomcat-logging-plugin/pom.xml b/apm-agent-plugins/apm-logging-plugin/apm-tomcat-logging-plugin/pom.xml index 0ba943c4bd..3c3bcb2ee9 100644 --- a/apm-agent-plugins/apm-logging-plugin/apm-tomcat-logging-plugin/pom.xml +++ b/apm-agent-plugins/apm-logging-plugin/apm-tomcat-logging-plugin/pom.xml @@ -5,7 +5,7 @@ apm-logging-plugin co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-tomcat-logging-plugin diff --git a/apm-agent-plugins/apm-logging-plugin/pom.xml b/apm-agent-plugins/apm-logging-plugin/pom.xml index 67328e4065..760825e2e5 100644 --- a/apm-agent-plugins/apm-logging-plugin/pom.xml +++ b/apm-agent-plugins/apm-logging-plugin/pom.xml @@ -5,7 +5,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-logging-plugin diff --git a/apm-agent-plugins/apm-micrometer-plugin/pom.xml b/apm-agent-plugins/apm-micrometer-plugin/pom.xml index be49483f23..1939b8ca2f 100644 --- a/apm-agent-plugins/apm-micrometer-plugin/pom.xml +++ b/apm-agent-plugins/apm-micrometer-plugin/pom.xml @@ -3,7 +3,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 @@ -29,7 +29,7 @@ io.micrometer micrometer-core - 1.11.2 + 1.11.4 provided diff --git a/apm-agent-plugins/apm-micronaut-plugin/README.md b/apm-agent-plugins/apm-micronaut-plugin/README.md new file mode 100644 index 0000000000..543ac325ad --- /dev/null +++ b/apm-agent-plugins/apm-micronaut-plugin/README.md @@ -0,0 +1,4 @@ +1. wrap propagate for all PropagatedContext: return code that: + - propagate() : find an elastic context in a current context; if found - activate transaction + - return scope that de-activate transaction on scope close +2. intercept the runWithFilters creation to try-use with a PropagatedContext containing elastic transaction diff --git a/apm-agent-plugins/apm-micronaut-plugin/pom.xml b/apm-agent-plugins/apm-micronaut-plugin/pom.xml new file mode 100644 index 0000000000..9ca35e220a --- /dev/null +++ b/apm-agent-plugins/apm-micronaut-plugin/pom.xml @@ -0,0 +1,46 @@ + + + 4.0.0 + + + apm-agent-plugins + co.elastic.apm + 1.42.1-SNAPSHOT + + + apm-micronaut-plugin + ${project.groupId}:${project.artifactId} + + + 8 + ${project.basedir}/../.. + true + + + + + ${project.groupId} + apm-httpserver-core + ${project.version} + + + io.micronaut + micronaut-core + 4.0.2 + provided + + + io.micronaut + micronaut-router + 4.0.2 + provided + + + io.micronaut + micronaut-http + 4.0.2 + provided + + + + diff --git a/apm-agent-plugins/apm-micronaut-plugin/src/main/java/co/elastic/apm/agent/micronaut/MicronautInstrumentation.java b/apm-agent-plugins/apm-micronaut-plugin/src/main/java/co/elastic/apm/agent/micronaut/MicronautInstrumentation.java new file mode 100644 index 0000000000..76b29897e6 --- /dev/null +++ b/apm-agent-plugins/apm-micronaut-plugin/src/main/java/co/elastic/apm/agent/micronaut/MicronautInstrumentation.java @@ -0,0 +1,32 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package co.elastic.apm.agent.micronaut; + +import co.elastic.apm.agent.sdk.ElasticApmInstrumentation; + +import java.util.Collection; +import java.util.Collections; + +public abstract class MicronautInstrumentation extends ElasticApmInstrumentation { + + @Override + public Collection getInstrumentationGroupNames() { + return Collections.singleton("micronaut"); + } +} diff --git a/apm-agent-plugins/apm-micronaut-plugin/src/main/java/co/elastic/apm/agent/micronaut/PropagatedContextElement.java b/apm-agent-plugins/apm-micronaut-plugin/src/main/java/co/elastic/apm/agent/micronaut/PropagatedContextElement.java new file mode 100644 index 0000000000..e31989d869 --- /dev/null +++ b/apm-agent-plugins/apm-micronaut-plugin/src/main/java/co/elastic/apm/agent/micronaut/PropagatedContextElement.java @@ -0,0 +1,49 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package co.elastic.apm.agent.micronaut; + +import co.elastic.apm.agent.tracer.Transaction; +import io.micronaut.core.annotation.Nullable; +import io.micronaut.core.propagation.ThreadPropagatedContextElement; + +public class PropagatedContextElement implements ThreadPropagatedContextElement> { + private Transaction transaction; + + public PropagatedContextElement(Transaction transaction) { + this.transaction = transaction; + } + + public Transaction getTransaction() { + return transaction; + } + + public void setTransaction(Transaction transaction) { + this.transaction = transaction; + } + + @Override + public @Nullable Transaction updateThreadContext() { + return transaction.activate(); + } + + @Override + public void restoreThreadContext(@Nullable Transaction oldState) { + oldState.deactivate(); + } +} diff --git a/apm-agent-plugins/apm-micronaut-plugin/src/main/java/co/elastic/apm/agent/micronaut/RequestLifecycleAdvice.java b/apm-agent-plugins/apm-micronaut-plugin/src/main/java/co/elastic/apm/agent/micronaut/RequestLifecycleAdvice.java new file mode 100644 index 0000000000..53c0f1e660 --- /dev/null +++ b/apm-agent-plugins/apm-micronaut-plugin/src/main/java/co/elastic/apm/agent/micronaut/RequestLifecycleAdvice.java @@ -0,0 +1,168 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package co.elastic.apm.agent.micronaut; + +import co.elastic.apm.agent.tracer.AbstractSpan; +import co.elastic.apm.agent.tracer.GlobalTracer; +import co.elastic.apm.agent.tracer.Transaction; +import co.elastic.apm.agent.tracer.dispatch.AbstractHeaderGetter; +import co.elastic.apm.agent.tracer.dispatch.TextHeaderGetter; +import co.elastic.apm.agent.tracer.metadata.Request; +import co.elastic.apm.agent.tracer.metadata.Response; +import co.elastic.apm.agent.tracer.util.ResultUtil; +import io.micronaut.core.execution.ExecutionFlow; +import io.micronaut.core.propagation.PropagatedContext; +import io.micronaut.http.HttpHeaders; +import io.micronaut.http.HttpRequest; +import io.micronaut.http.MutableHttpResponse; +import net.bytebuddy.asm.Advice; + +import javax.annotation.Nullable; + +@SuppressWarnings("unused") +public class RequestLifecycleAdvice { + private static class ScopeWrapper { + private final PropagatedContext.Scope propagatedScope; + private final Transaction transaction; + + public ScopeWrapper(PropagatedContext.Scope propagatedScope, Transaction transaction) { + this.propagatedScope = propagatedScope; + this.transaction = transaction; + } + + public PropagatedContext.Scope getPropagatedScope() { + return propagatedScope; + } + + public Transaction getTransaction() { + return transaction; + } + } + + public static class HeaderGetter extends AbstractHeaderGetter implements TextHeaderGetter { + + @Nullable + @Override + public String getFirstHeader(String headerName, HttpHeaders carrier) { + return carrier.get(headerName); + } + } + + @Nullable + @Advice.OnMethodEnter(suppress = Throwable.class, inline = false) + public static Object onEnter( + @Advice.FieldValue("request") @Nullable Object requestUntyped + ) { + if(requestUntyped == null) { + return null; + } + + HttpRequest typedRequest = (HttpRequest) requestUntyped; + + Transaction trx = GlobalTracer.get().startChildTransaction(typedRequest.getHeaders(), new HeaderGetter(), Thread.currentThread().getContextClassLoader()); + + if(trx == null) { + return null; + } + + trx.setFrameworkName("micronaut"); + + StringBuilder nameBuilder = trx.getAndOverrideName(AbstractSpan.PRIORITY_LOW_LEVEL_FRAMEWORK); + + if(nameBuilder == null) { + trx.end(); + return null; + } + + nameBuilder.append(typedRequest.getMethodName()); + nameBuilder.append(" "); + nameBuilder.append(typedRequest.getUri().getPath()); + + Request request = trx.getContext().getRequest(); + + request.getSocket() + .withRemoteAddress(typedRequest.getRemoteAddress().getAddress().getHostAddress()); + + request.withHttpVersion(typedRequest.getHttpVersion().name()) + .withMethod(typedRequest.getMethodName()); + + request.getUrl() + .withProtocol("http") + .withHostname(typedRequest.getRemoteAddress().getAddress().getHostAddress()) + .withPort(typedRequest.getServerAddress().getPort()) + .withPathname(typedRequest.getUri().getPath()) + .withSearch(typedRequest.getUri().getQuery()); + + PropagatedContextElement elasticContextElement = new PropagatedContextElement(trx); + + PropagatedContext ctx = PropagatedContext.getOrEmpty().plus(elasticContextElement); + + return new ScopeWrapper(ctx.propagate(), trx); + } + + @Advice.OnMethodExit(suppress = Throwable.class, onThrowable = Throwable.class, inline = false) + public static void onExit( + @Advice.Enter @Nullable Object scopeUntyped, + @Advice.Return @Nullable ExecutionFlow> returnFlow, + @Advice.Thrown @Nullable Throwable t) { + + if(scopeUntyped == null) { + return; + } + + ScopeWrapper wrapper = (ScopeWrapper) scopeUntyped; + + PropagatedContext.Scope scope = wrapper.propagatedScope; + + scope.close(); + + Transaction trx = wrapper.getTransaction(); + + if(t != null) { + finishTransaction(trx, null, t); + return; + } + + if (returnFlow == null) { + return; + } + + returnFlow.onComplete((res, ex) -> finishTransaction(trx, res, ex)); + } + + private static void finishTransaction( + Transaction trx, + @Nullable MutableHttpResponse response, + @Nullable Throwable exception) + { + if(response != null) { + trx + .withResultIfUnset(ResultUtil.getResultByHttpStatus(response.code())) + .captureException(exception); + + Response trxResponse = trx.getContext().getResponse(); + + trxResponse + .withFinished(true) + .withStatusCode(response.code()); + } + + trx.end(); + } +} diff --git a/apm-agent-plugins/apm-micronaut-plugin/src/main/java/co/elastic/apm/agent/micronaut/RequestLifecycleInstrumentation.java b/apm-agent-plugins/apm-micronaut-plugin/src/main/java/co/elastic/apm/agent/micronaut/RequestLifecycleInstrumentation.java new file mode 100644 index 0000000000..9fdda4815d --- /dev/null +++ b/apm-agent-plugins/apm-micronaut-plugin/src/main/java/co/elastic/apm/agent/micronaut/RequestLifecycleInstrumentation.java @@ -0,0 +1,48 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package co.elastic.apm.agent.micronaut; + +import net.bytebuddy.description.NamedElement; +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.matcher.ElementMatcher; + +import static net.bytebuddy.matcher.ElementMatchers.*; + +public class RequestLifecycleInstrumentation extends MicronautInstrumentation { + @Override + public ElementMatcher getTypeMatcherPreFilter() { + return nameStartsWith("io.micronaut.http.server"); + } + + @Override + public ElementMatcher getTypeMatcher() { + return hasSuperType(named("io.micronaut.http.server.RequestLifecycle")); + } + + @Override + public ElementMatcher getMethodMatcher() { + return named("normalFlow"); + } + + @Override + public String getAdviceClassName() { + return "co.elastic.apm.agent.micronaut.RequestLifecycleAdvice"; + } +} diff --git a/apm-agent-plugins/apm-micronaut-plugin/src/main/java/co/elastic/apm/agent/micronaut/RouteExecutorAdvice.java b/apm-agent-plugins/apm-micronaut-plugin/src/main/java/co/elastic/apm/agent/micronaut/RouteExecutorAdvice.java new file mode 100644 index 0000000000..d1558b81ec --- /dev/null +++ b/apm-agent-plugins/apm-micronaut-plugin/src/main/java/co/elastic/apm/agent/micronaut/RouteExecutorAdvice.java @@ -0,0 +1,69 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package co.elastic.apm.agent.micronaut; + +import co.elastic.apm.agent.tracer.AbstractSpan; +import co.elastic.apm.agent.tracer.Transaction; +import io.micronaut.core.propagation.PropagatedContext; +import io.micronaut.web.router.MethodBasedRouteInfo; +import io.micronaut.web.router.RouteInfo; +import io.micronaut.web.router.RouteMatch; +import net.bytebuddy.asm.Advice; +import java.util.Optional; + +public class RouteExecutorAdvice { + @Advice.OnMethodEnter(suppress = Throwable.class, inline = false) + public static void onEnter(@Advice.Argument(1) RouteMatch match) { + Optional ctxOpt = PropagatedContext.find(); + + if(ctxOpt.isEmpty()) { + return; + } + + PropagatedContext ctx = ctxOpt.get(); + + PropagatedContextElement ctxElement = ctx.get(PropagatedContextElement.class); + + if(ctxElement == null) { + return; + } + + Transaction trx = ctxElement.getTransaction(); + + RouteInfo routeInfo = match.getRouteInfo(); + + if(routeInfo instanceof MethodBasedRouteInfo) { + MethodBasedRouteInfo methodBasedRouteInfo = (MethodBasedRouteInfo) routeInfo; + + String controllerName = methodBasedRouteInfo.getTargetMethod().getDeclaringType().getSimpleName(); + String methodName = methodBasedRouteInfo.getTargetMethod().getName(); + + StringBuilder nameBuilder = trx.getAndOverrideName(AbstractSpan.PRIORITY_LOW_LEVEL_FRAMEWORK); + + if(nameBuilder == null) { + return; + } + + nameBuilder.append(controllerName); + nameBuilder.append("#"); + nameBuilder.append(methodName); + + } + } +} diff --git a/apm-agent-plugins/apm-micronaut-plugin/src/main/java/co/elastic/apm/agent/micronaut/RouteExecutorInstrumentation.java b/apm-agent-plugins/apm-micronaut-plugin/src/main/java/co/elastic/apm/agent/micronaut/RouteExecutorInstrumentation.java new file mode 100644 index 0000000000..0c43f81522 --- /dev/null +++ b/apm-agent-plugins/apm-micronaut-plugin/src/main/java/co/elastic/apm/agent/micronaut/RouteExecutorInstrumentation.java @@ -0,0 +1,49 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package co.elastic.apm.agent.micronaut; + +import net.bytebuddy.description.NamedElement; +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.matcher.ElementMatcher; + +import static net.bytebuddy.matcher.ElementMatchers.*; +import static net.bytebuddy.matcher.ElementMatchers.named; + +public class RouteExecutorInstrumentation extends MicronautInstrumentation { + @Override + public ElementMatcher getTypeMatcherPreFilter() { + return nameStartsWith("io.micronaut.http.server"); + } + + @Override + public ElementMatcher getTypeMatcher() { + return hasSuperType(named("io.micronaut.http.server.RouteExecutor")); + } + + @Override + public ElementMatcher getMethodMatcher() { + return named("callRoute"); + } + + @Override + public String getAdviceClassName() { + return "co.elastic.apm.agent.micronaut.RouteExecutorAdvice"; + } +} diff --git a/apm-agent-plugins/apm-micronaut-plugin/src/main/java/co/elastic/apm/agent/micronaut/package-info.java b/apm-agent-plugins/apm-micronaut-plugin/src/main/java/co/elastic/apm/agent/micronaut/package-info.java new file mode 100644 index 0000000000..bf7147f365 --- /dev/null +++ b/apm-agent-plugins/apm-micronaut-plugin/src/main/java/co/elastic/apm/agent/micronaut/package-info.java @@ -0,0 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +@NonnullApi +package co.elastic.apm.agent.micronaut; + +import co.elastic.apm.agent.sdk.NonnullApi; diff --git a/apm-agent-plugins/apm-micronaut-plugin/src/main/resources/META-INF/services/co.elastic.apm.agent.sdk.ElasticApmInstrumentation b/apm-agent-plugins/apm-micronaut-plugin/src/main/resources/META-INF/services/co.elastic.apm.agent.sdk.ElasticApmInstrumentation new file mode 100644 index 0000000000..3cfd997d19 --- /dev/null +++ b/apm-agent-plugins/apm-micronaut-plugin/src/main/resources/META-INF/services/co.elastic.apm.agent.sdk.ElasticApmInstrumentation @@ -0,0 +1,2 @@ +co.elastic.apm.agent.micronaut.RequestLifecycleInstrumentation +co.elastic.apm.agent.micronaut.RouteExecutorInstrumentation diff --git a/apm-agent-plugins/apm-mongodb/apm-mongodb-common/pom.xml b/apm-agent-plugins/apm-mongodb/apm-mongodb-common/pom.xml index eff76d8806..b333b21416 100644 --- a/apm-agent-plugins/apm-mongodb/apm-mongodb-common/pom.xml +++ b/apm-agent-plugins/apm-mongodb/apm-mongodb-common/pom.xml @@ -4,7 +4,7 @@ apm-mongodb co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT diff --git a/apm-agent-plugins/apm-mongodb/apm-mongodb3-plugin/pom.xml b/apm-agent-plugins/apm-mongodb/apm-mongodb3-plugin/pom.xml index 97827fe72a..d660f23ae0 100644 --- a/apm-agent-plugins/apm-mongodb/apm-mongodb3-plugin/pom.xml +++ b/apm-agent-plugins/apm-mongodb/apm-mongodb3-plugin/pom.xml @@ -3,7 +3,7 @@ apm-mongodb co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/apm-agent-plugins/apm-mongodb/apm-mongodb4-plugin/pom.xml b/apm-agent-plugins/apm-mongodb/apm-mongodb4-plugin/pom.xml index 1e1e605de4..a0497dbf51 100644 --- a/apm-agent-plugins/apm-mongodb/apm-mongodb4-plugin/pom.xml +++ b/apm-agent-plugins/apm-mongodb/apm-mongodb4-plugin/pom.xml @@ -5,7 +5,7 @@ apm-mongodb co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-mongodb4-plugin diff --git a/apm-agent-plugins/apm-mongodb/pom.xml b/apm-agent-plugins/apm-mongodb/pom.xml index 231183edad..162420a9ad 100644 --- a/apm-agent-plugins/apm-mongodb/pom.xml +++ b/apm-agent-plugins/apm-mongodb/pom.xml @@ -5,7 +5,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-mongodb diff --git a/apm-agent-plugins/apm-okhttp-plugin/pom.xml b/apm-agent-plugins/apm-okhttp-plugin/pom.xml index ce44520ec1..68de0acce1 100644 --- a/apm-agent-plugins/apm-okhttp-plugin/pom.xml +++ b/apm-agent-plugins/apm-okhttp-plugin/pom.xml @@ -5,7 +5,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-okhttp-plugin diff --git a/apm-agent-plugins/apm-okhttp-test/pom.xml b/apm-agent-plugins/apm-okhttp-test/pom.xml index b71a965e96..b389091b19 100644 --- a/apm-agent-plugins/apm-okhttp-test/pom.xml +++ b/apm-agent-plugins/apm-okhttp-test/pom.xml @@ -3,7 +3,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-embedded-metrics-sdk/pom.xml b/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-embedded-metrics-sdk/pom.xml index 6890b6ffce..70be4e1d1f 100644 --- a/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-embedded-metrics-sdk/pom.xml +++ b/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-embedded-metrics-sdk/pom.xml @@ -4,7 +4,7 @@ co.elastic.apm apm-opentelemetry - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-opentelemetry-embedded-metrics-sdk diff --git a/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-metrics-bridge-parent/apm-opentelemetry-metrics-bridge-common/pom.xml b/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-metrics-bridge-parent/apm-opentelemetry-metrics-bridge-common/pom.xml index 2707f64a30..f1bca23a98 100644 --- a/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-metrics-bridge-parent/apm-opentelemetry-metrics-bridge-common/pom.xml +++ b/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-metrics-bridge-parent/apm-opentelemetry-metrics-bridge-common/pom.xml @@ -3,7 +3,7 @@ apm-opentelemetry-metrics-bridge-parent co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-metrics-bridge-parent/apm-opentelemetry-metrics-bridge-latest/pom.xml b/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-metrics-bridge-parent/apm-opentelemetry-metrics-bridge-latest/pom.xml index f5baf84ad8..eccd85af30 100644 --- a/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-metrics-bridge-parent/apm-opentelemetry-metrics-bridge-latest/pom.xml +++ b/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-metrics-bridge-parent/apm-opentelemetry-metrics-bridge-latest/pom.xml @@ -3,7 +3,7 @@ apm-opentelemetry-metrics-bridge-parent co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-metrics-bridge-parent/apm-opentelemetry-metrics-bridge-v1_14/pom.xml b/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-metrics-bridge-parent/apm-opentelemetry-metrics-bridge-v1_14/pom.xml index 1430872728..0e3fe8069f 100644 --- a/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-metrics-bridge-parent/apm-opentelemetry-metrics-bridge-v1_14/pom.xml +++ b/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-metrics-bridge-parent/apm-opentelemetry-metrics-bridge-v1_14/pom.xml @@ -3,7 +3,7 @@ apm-opentelemetry-metrics-bridge-parent co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-metrics-bridge-parent/pom.xml b/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-metrics-bridge-parent/pom.xml index 4d2ef5b48c..8cb7d23851 100644 --- a/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-metrics-bridge-parent/pom.xml +++ b/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-metrics-bridge-parent/pom.xml @@ -3,7 +3,7 @@ apm-opentelemetry co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-metricsdk-plugin/pom.xml b/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-metricsdk-plugin/pom.xml index 366b73536c..d8bf8f0345 100644 --- a/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-metricsdk-plugin/pom.xml +++ b/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-metricsdk-plugin/pom.xml @@ -4,7 +4,7 @@ co.elastic.apm apm-opentelemetry - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-opentelemetry-metricsdk-plugin diff --git a/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-metricsdk-plugin/src/main/java/co/elastic/apm/agent/otelmetricsdk/SdkMeterProviderBuilderInstrumentation.java b/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-metricsdk-plugin/src/main/java/co/elastic/apm/agent/otelmetricsdk/SdkMeterProviderBuilderInstrumentation.java index 91b982a349..2cc64c554c 100644 --- a/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-metricsdk-plugin/src/main/java/co/elastic/apm/agent/otelmetricsdk/SdkMeterProviderBuilderInstrumentation.java +++ b/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-metricsdk-plugin/src/main/java/co/elastic/apm/agent/otelmetricsdk/SdkMeterProviderBuilderInstrumentation.java @@ -19,13 +19,13 @@ package co.elastic.apm.agent.otelmetricsdk; import co.elastic.apm.agent.impl.ElasticApmTracer; -import co.elastic.apm.agent.tracer.GlobalTracer; import co.elastic.apm.agent.sdk.ElasticApmInstrumentation; +import co.elastic.apm.agent.sdk.internal.util.LoggerUtils; import co.elastic.apm.agent.sdk.logging.Logger; import co.elastic.apm.agent.sdk.logging.LoggerFactory; import co.elastic.apm.agent.sdk.weakconcurrent.WeakConcurrent; import co.elastic.apm.agent.sdk.weakconcurrent.WeakSet; -import co.elastic.apm.agent.sdk.internal.util.LoggerUtils; +import co.elastic.apm.agent.tracer.GlobalTracer; import io.opentelemetry.sdk.metrics.SdkMeterProviderBuilder; import io.opentelemetry.sdk.metrics.export.MetricExporter; import net.bytebuddy.asm.Advice; @@ -55,6 +55,11 @@ public Collection getInstrumentationGroupNames() { return Arrays.asList("opentelemetry", "opentelemetry-metrics", "experimental"); } + @Override + public final boolean includeWhenInstrumentationIsDisabled() { + return true; + } + @Override public String getAdviceClassName() { return getClass().getName() + "$SdkMeterProviderBuilderAdvice"; diff --git a/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-metricsdk-plugin/src/test/java/co/elastic/apm/agent/otelmetricsdk/AbstractOtelMetricsTest.java b/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-metricsdk-plugin/src/test/java/co/elastic/apm/agent/otelmetricsdk/AbstractOtelMetricsTest.java index ef93c11b3b..53c3b29819 100644 --- a/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-metricsdk-plugin/src/test/java/co/elastic/apm/agent/otelmetricsdk/AbstractOtelMetricsTest.java +++ b/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-metricsdk-plugin/src/test/java/co/elastic/apm/agent/otelmetricsdk/AbstractOtelMetricsTest.java @@ -18,9 +18,14 @@ */ package co.elastic.apm.agent.otelmetricsdk; -import co.elastic.apm.agent.AbstractInstrumentationTest; +import co.elastic.apm.agent.MockReporter; +import co.elastic.apm.agent.MockTracer; +import co.elastic.apm.agent.bci.ElasticApmAgent; import co.elastic.apm.agent.common.util.WildcardMatcher; +import co.elastic.apm.agent.configuration.CoreConfiguration; import co.elastic.apm.agent.configuration.MetricsConfiguration; +import co.elastic.apm.agent.configuration.SpyConfiguration; +import co.elastic.apm.agent.impl.ElasticApmTracer; import co.elastic.apm.agent.report.ReporterConfiguration; import co.elastic.apm.agent.util.AtomicDouble; import io.opentelemetry.api.common.Attributes; @@ -41,8 +46,13 @@ import io.opentelemetry.api.metrics.ObservableLongGauge; import io.opentelemetry.api.metrics.ObservableLongMeasurement; import io.opentelemetry.api.metrics.ObservableLongUpDownCounter; +import net.bytebuddy.agent.ByteBuddyAgent; +import org.junit.AfterClass; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.stagemonitor.configuration.ConfigurationRegistry; import javax.annotation.Nullable; import java.time.Instant; @@ -63,7 +73,12 @@ import static io.opentelemetry.api.common.AttributeKey.stringKey; import static org.mockito.Mockito.doReturn; -public abstract class AbstractOtelMetricsTest extends AbstractInstrumentationTest { +public abstract class AbstractOtelMetricsTest { + + protected static ElasticApmTracer tracer; + protected static MockReporter reporter; + protected static ConfigurationRegistry config; + private ReporterConfiguration reporterConfig; @@ -74,9 +89,32 @@ public abstract class AbstractOtelMetricsTest extends AbstractInstrumentationTes @Nullable private MeterProvider meterProvider; + + @BeforeAll + public static synchronized void beforeAll() { + MockTracer.MockInstrumentationSetup mockInstrumentationSetup = MockTracer.createMockInstrumentationSetup(); + config = mockInstrumentationSetup.getConfig(); + tracer = mockInstrumentationSetup.getTracer(); + reporter = mockInstrumentationSetup.getReporter(); + + //Metrics export should work even with instrument=false + CoreConfiguration coreConfig = config.getConfig(CoreConfiguration.class); + doReturn(false).when(coreConfig).isInstrument(); + + assertThat(tracer.isRunning()).isTrue(); + ElasticApmAgent.initInstrumentation(tracer, ByteBuddyAgent.install()); + } + + @AfterAll + @AfterClass + public static synchronized void afterAll() { + ElasticApmAgent.reset(); + } + @BeforeEach public void setup() { - reporterConfig = tracer.getConfig(ReporterConfiguration.class); + SpyConfiguration.reset(config); + reporterConfig = config.getConfig(ReporterConfiguration.class); // we use explicit flush in tests instead of periodic reporting to prevent flakyness doReturn(1_000_000L).when(reporterConfig).getMetricsIntervalMs(); meterProvider = null; diff --git a/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-plugin/pom.xml b/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-plugin/pom.xml index 6daefaa193..8f890f3f34 100644 --- a/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-plugin/pom.xml +++ b/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-plugin/pom.xml @@ -4,7 +4,7 @@ co.elastic.apm apm-opentelemetry - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-opentelemetry-plugin diff --git a/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-plugin/src/test/java/co/elastic/apm/agent/opentelemetry/tracing/ElasticOpenTelemetryTest.java b/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-plugin/src/test/java/co/elastic/apm/agent/opentelemetry/tracing/ElasticOpenTelemetryTest.java index c5a4a35608..aa2084f246 100644 --- a/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-plugin/src/test/java/co/elastic/apm/agent/opentelemetry/tracing/ElasticOpenTelemetryTest.java +++ b/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-plugin/src/test/java/co/elastic/apm/agent/opentelemetry/tracing/ElasticOpenTelemetryTest.java @@ -23,6 +23,7 @@ import co.elastic.apm.agent.impl.transaction.OTelSpanKind; import co.elastic.apm.agent.impl.transaction.Transaction; import co.elastic.apm.agent.tracer.Outcome; +import co.elastic.apm.agent.tracer.dispatch.TextHeaderSetter; import io.opentelemetry.api.baggage.Baggage; import io.opentelemetry.api.baggage.BaggageEntryMetadata; import io.opentelemetry.api.trace.Span; @@ -231,7 +232,7 @@ public void testTransactionInject() { HashMap elasticApmHeaders = new HashMap<>(); try (Scope scope = transaction.makeCurrent()) { openTelemetry.getPropagators().getTextMapPropagator().inject(Context.current(), otelHeaders, HashMap::put); - tracer.currentContext().propagateContext(elasticApmHeaders, (k, v, m) -> m.put(k, v), null); + tracer.currentContext().propagateContext(elasticApmHeaders, (TextHeaderSetter>) (k, v, m) -> m.put(k, v), null); } finally { transaction.end(); } diff --git a/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-test/pom.xml b/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-test/pom.xml index 23a2c522b2..648ddb3c12 100644 --- a/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-test/pom.xml +++ b/apm-agent-plugins/apm-opentelemetry/apm-opentelemetry-test/pom.xml @@ -4,7 +4,7 @@ co.elastic.apm apm-opentelemetry - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT ${project.groupId}:${project.artifactId} diff --git a/apm-agent-plugins/apm-opentelemetry/pom.xml b/apm-agent-plugins/apm-opentelemetry/pom.xml index e6c2cb63f4..cd5a609d10 100644 --- a/apm-agent-plugins/apm-opentelemetry/pom.xml +++ b/apm-agent-plugins/apm-opentelemetry/pom.xml @@ -5,7 +5,7 @@ co.elastic.apm apm-agent-plugins - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-opentelemetry diff --git a/apm-agent-plugins/apm-opentracing-plugin/pom.xml b/apm-agent-plugins/apm-opentracing-plugin/pom.xml index ef8e2d9c77..83d1f96d9c 100644 --- a/apm-agent-plugins/apm-opentracing-plugin/pom.xml +++ b/apm-agent-plugins/apm-opentracing-plugin/pom.xml @@ -5,7 +5,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-opentracing-plugin diff --git a/apm-agent-plugins/apm-opentracing-plugin/src/main/java/co/elastic/apm/agent/opentracingimpl/ExternalSpanContextInstrumentation.java b/apm-agent-plugins/apm-opentracing-plugin/src/main/java/co/elastic/apm/agent/opentracingimpl/ExternalSpanContextInstrumentation.java index 9e08b58e94..30a05603d6 100644 --- a/apm-agent-plugins/apm-opentracing-plugin/src/main/java/co/elastic/apm/agent/opentracingimpl/ExternalSpanContextInstrumentation.java +++ b/apm-agent-plugins/apm-opentracing-plugin/src/main/java/co/elastic/apm/agent/opentracingimpl/ExternalSpanContextInstrumentation.java @@ -119,7 +119,7 @@ public static TraceContext parseTextMap(Iterable> text ElasticApmTracer tracer = OpenTracingBridgeInstrumentation.tracer.require(ElasticApmTracer.class); if (tracer != null) { TraceContext childTraceContext = TraceContext.with64BitId(tracer); - if (TraceContext.>>getFromTraceContextTextHeaders().asChildOf(childTraceContext, textMap, OpenTracingTextMapBridge.instance())) { + if (childTraceContext.asChildOf(textMap, OpenTracingTextMapBridge.instance())) { return childTraceContext; } } diff --git a/apm-agent-plugins/apm-process-plugin/pom.xml b/apm-agent-plugins/apm-process-plugin/pom.xml index f0db8d70f4..78997931af 100644 --- a/apm-agent-plugins/apm-process-plugin/pom.xml +++ b/apm-agent-plugins/apm-process-plugin/pom.xml @@ -3,7 +3,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/apm-agent-plugins/apm-profiling-plugin/pom.xml b/apm-agent-plugins/apm-profiling-plugin/pom.xml index b5224e3481..daf8abd825 100644 --- a/apm-agent-plugins/apm-profiling-plugin/pom.xml +++ b/apm-agent-plugins/apm-profiling-plugin/pom.xml @@ -5,7 +5,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-profiling-plugin diff --git a/apm-agent-plugins/apm-quartz/apm-quartz-common/pom.xml b/apm-agent-plugins/apm-quartz/apm-quartz-common/pom.xml index 4ba899b144..f609ff0612 100644 --- a/apm-agent-plugins/apm-quartz/apm-quartz-common/pom.xml +++ b/apm-agent-plugins/apm-quartz/apm-quartz-common/pom.xml @@ -3,7 +3,7 @@ apm-quartz co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/apm-agent-plugins/apm-quartz/apm-quartz-plugin-1/pom.xml b/apm-agent-plugins/apm-quartz/apm-quartz-plugin-1/pom.xml index a71764c89c..3b4188f705 100644 --- a/apm-agent-plugins/apm-quartz/apm-quartz-plugin-1/pom.xml +++ b/apm-agent-plugins/apm-quartz/apm-quartz-plugin-1/pom.xml @@ -3,7 +3,7 @@ apm-quartz co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/apm-agent-plugins/apm-quartz/apm-quartz-plugin-2/pom.xml b/apm-agent-plugins/apm-quartz/apm-quartz-plugin-2/pom.xml index 09a28a3a31..b241858276 100644 --- a/apm-agent-plugins/apm-quartz/apm-quartz-plugin-2/pom.xml +++ b/apm-agent-plugins/apm-quartz/apm-quartz-plugin-2/pom.xml @@ -3,7 +3,7 @@ apm-quartz co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/apm-agent-plugins/apm-quartz/pom.xml b/apm-agent-plugins/apm-quartz/pom.xml index 8ef34f4e50..211aa54e0f 100644 --- a/apm-agent-plugins/apm-quartz/pom.xml +++ b/apm-agent-plugins/apm-quartz/pom.xml @@ -5,7 +5,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-quartz diff --git a/apm-agent-plugins/apm-rabbitmq/apm-rabbitmq-plugin/pom.xml b/apm-agent-plugins/apm-rabbitmq/apm-rabbitmq-plugin/pom.xml index da1e07e871..64ae45e6b8 100644 --- a/apm-agent-plugins/apm-rabbitmq/apm-rabbitmq-plugin/pom.xml +++ b/apm-agent-plugins/apm-rabbitmq/apm-rabbitmq-plugin/pom.xml @@ -5,7 +5,7 @@ apm-rabbitmq co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-rabbitmq-plugin diff --git a/apm-agent-plugins/apm-rabbitmq/apm-rabbitmq-spring/pom.xml b/apm-agent-plugins/apm-rabbitmq/apm-rabbitmq-spring/pom.xml index 2ff1aa3655..320579513a 100644 --- a/apm-agent-plugins/apm-rabbitmq/apm-rabbitmq-spring/pom.xml +++ b/apm-agent-plugins/apm-rabbitmq/apm-rabbitmq-spring/pom.xml @@ -5,7 +5,7 @@ apm-rabbitmq co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-rabbitmq-spring diff --git a/apm-agent-plugins/apm-rabbitmq/apm-rabbitmq-test-3/pom.xml b/apm-agent-plugins/apm-rabbitmq/apm-rabbitmq-test-3/pom.xml index 9f7e94c214..1ccf1deebe 100644 --- a/apm-agent-plugins/apm-rabbitmq/apm-rabbitmq-test-3/pom.xml +++ b/apm-agent-plugins/apm-rabbitmq/apm-rabbitmq-test-3/pom.xml @@ -5,7 +5,7 @@ apm-rabbitmq co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-rabbitmq-test-3 diff --git a/apm-agent-plugins/apm-rabbitmq/apm-rabbitmq-test-4/pom.xml b/apm-agent-plugins/apm-rabbitmq/apm-rabbitmq-test-4/pom.xml index b54394e5cb..219cb90dd4 100644 --- a/apm-agent-plugins/apm-rabbitmq/apm-rabbitmq-test-4/pom.xml +++ b/apm-agent-plugins/apm-rabbitmq/apm-rabbitmq-test-4/pom.xml @@ -5,7 +5,7 @@ apm-rabbitmq co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-rabbitmq-test-4 diff --git a/apm-agent-plugins/apm-rabbitmq/pom.xml b/apm-agent-plugins/apm-rabbitmq/pom.xml index e7249f623f..70aaaa10ee 100644 --- a/apm-agent-plugins/apm-rabbitmq/pom.xml +++ b/apm-agent-plugins/apm-rabbitmq/pom.xml @@ -5,7 +5,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-rabbitmq diff --git a/apm-agent-plugins/apm-reactor-plugin/pom.xml b/apm-agent-plugins/apm-reactor-plugin/pom.xml index 6907fd382e..bb6004bd68 100644 --- a/apm-agent-plugins/apm-reactor-plugin/pom.xml +++ b/apm-agent-plugins/apm-reactor-plugin/pom.xml @@ -5,7 +5,7 @@ co.elastic.apm apm-agent-plugins - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-reactor-plugin diff --git a/apm-agent-plugins/apm-redis-plugin/apm-jedis-2-tests/pom.xml b/apm-agent-plugins/apm-redis-plugin/apm-jedis-2-tests/pom.xml index 5e905301ca..50b826232c 100644 --- a/apm-agent-plugins/apm-redis-plugin/apm-jedis-2-tests/pom.xml +++ b/apm-agent-plugins/apm-redis-plugin/apm-jedis-2-tests/pom.xml @@ -5,7 +5,7 @@ apm-redis-plugin co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-jedis-2-tests diff --git a/apm-agent-plugins/apm-redis-plugin/apm-jedis-3-tests/pom.xml b/apm-agent-plugins/apm-redis-plugin/apm-jedis-3-tests/pom.xml index 888bd285d3..7278df0ac8 100644 --- a/apm-agent-plugins/apm-redis-plugin/apm-jedis-3-tests/pom.xml +++ b/apm-agent-plugins/apm-redis-plugin/apm-jedis-3-tests/pom.xml @@ -5,7 +5,7 @@ apm-redis-plugin co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-jedis-3-tests diff --git a/apm-agent-plugins/apm-redis-plugin/apm-jedis-4-plugin/pom.xml b/apm-agent-plugins/apm-redis-plugin/apm-jedis-4-plugin/pom.xml index 8ec4c836fe..b079d966ed 100644 --- a/apm-agent-plugins/apm-redis-plugin/apm-jedis-4-plugin/pom.xml +++ b/apm-agent-plugins/apm-redis-plugin/apm-jedis-4-plugin/pom.xml @@ -5,7 +5,7 @@ apm-redis-plugin co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-jedis-4-plugin diff --git a/apm-agent-plugins/apm-redis-plugin/apm-jedis-plugin/pom.xml b/apm-agent-plugins/apm-redis-plugin/apm-jedis-plugin/pom.xml index 11b7b59743..6f7b0be854 100644 --- a/apm-agent-plugins/apm-redis-plugin/apm-jedis-plugin/pom.xml +++ b/apm-agent-plugins/apm-redis-plugin/apm-jedis-plugin/pom.xml @@ -5,7 +5,7 @@ apm-redis-plugin co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-jedis-plugin diff --git a/apm-agent-plugins/apm-redis-plugin/apm-lettuce-3-tests/pom.xml b/apm-agent-plugins/apm-redis-plugin/apm-lettuce-3-tests/pom.xml index 8d647c66ff..9f058e88b7 100644 --- a/apm-agent-plugins/apm-redis-plugin/apm-lettuce-3-tests/pom.xml +++ b/apm-agent-plugins/apm-redis-plugin/apm-lettuce-3-tests/pom.xml @@ -3,7 +3,7 @@ apm-redis-plugin co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/apm-agent-plugins/apm-redis-plugin/apm-lettuce-plugin/pom.xml b/apm-agent-plugins/apm-redis-plugin/apm-lettuce-plugin/pom.xml index 998d2b4f91..23b9e3bbdc 100644 --- a/apm-agent-plugins/apm-redis-plugin/apm-lettuce-plugin/pom.xml +++ b/apm-agent-plugins/apm-redis-plugin/apm-lettuce-plugin/pom.xml @@ -3,7 +3,7 @@ apm-redis-plugin co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/apm-agent-plugins/apm-redis-plugin/apm-redis-common/pom.xml b/apm-agent-plugins/apm-redis-plugin/apm-redis-common/pom.xml index 05cd327223..5f51c53505 100644 --- a/apm-agent-plugins/apm-redis-plugin/apm-redis-common/pom.xml +++ b/apm-agent-plugins/apm-redis-plugin/apm-redis-common/pom.xml @@ -5,7 +5,7 @@ apm-redis-plugin co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-redis-common diff --git a/apm-agent-plugins/apm-redis-plugin/apm-redisson-plugin/pom.xml b/apm-agent-plugins/apm-redis-plugin/apm-redisson-plugin/pom.xml index e1d18404cf..918bebe898 100644 --- a/apm-agent-plugins/apm-redis-plugin/apm-redisson-plugin/pom.xml +++ b/apm-agent-plugins/apm-redis-plugin/apm-redisson-plugin/pom.xml @@ -5,7 +5,7 @@ apm-redis-plugin co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-redisson-plugin diff --git a/apm-agent-plugins/apm-redis-plugin/pom.xml b/apm-agent-plugins/apm-redis-plugin/pom.xml index 16217ad15c..cda530e82c 100644 --- a/apm-agent-plugins/apm-redis-plugin/pom.xml +++ b/apm-agent-plugins/apm-redis-plugin/pom.xml @@ -5,7 +5,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-redis-plugin diff --git a/apm-agent-plugins/apm-scala-concurrent-plugin/pom.xml b/apm-agent-plugins/apm-scala-concurrent-plugin/pom.xml index ca8933f698..99ba7f1645 100644 --- a/apm-agent-plugins/apm-scala-concurrent-plugin/pom.xml +++ b/apm-agent-plugins/apm-scala-concurrent-plugin/pom.xml @@ -5,7 +5,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-scala-concurrent-plugin diff --git a/apm-agent-plugins/apm-scheduled-annotation-plugin-jakartaee-test/pom.xml b/apm-agent-plugins/apm-scheduled-annotation-plugin-jakartaee-test/pom.xml index 7a651a640c..7283e11884 100644 --- a/apm-agent-plugins/apm-scheduled-annotation-plugin-jakartaee-test/pom.xml +++ b/apm-agent-plugins/apm-scheduled-annotation-plugin-jakartaee-test/pom.xml @@ -3,7 +3,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/apm-agent-plugins/apm-scheduled-annotation-plugin/pom.xml b/apm-agent-plugins/apm-scheduled-annotation-plugin/pom.xml index 59e1600b10..f2e9690510 100644 --- a/apm-agent-plugins/apm-scheduled-annotation-plugin/pom.xml +++ b/apm-agent-plugins/apm-scheduled-annotation-plugin/pom.xml @@ -5,7 +5,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-scheduled-annotation-plugin diff --git a/apm-agent-plugins/apm-servlet-jakarta-test/pom.xml b/apm-agent-plugins/apm-servlet-jakarta-test/pom.xml index 5e3b23d66e..6a5cdb13a5 100644 --- a/apm-agent-plugins/apm-servlet-jakarta-test/pom.xml +++ b/apm-agent-plugins/apm-servlet-jakarta-test/pom.xml @@ -5,7 +5,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-servlet-jakarta-test diff --git a/apm-agent-plugins/apm-servlet-plugin/pom.xml b/apm-agent-plugins/apm-servlet-plugin/pom.xml index b42be23d57..4dc94472f6 100644 --- a/apm-agent-plugins/apm-servlet-plugin/pom.xml +++ b/apm-agent-plugins/apm-servlet-plugin/pom.xml @@ -5,7 +5,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-servlet-plugin diff --git a/apm-agent-plugins/apm-servlet-plugin/src/main/java/co/elastic/apm/agent/servlet/ServletServiceNameHelper.java b/apm-agent-plugins/apm-servlet-plugin/src/main/java/co/elastic/apm/agent/servlet/ServletServiceNameHelper.java index b507bb5aa9..e58bdf02dc 100644 --- a/apm-agent-plugins/apm-servlet-plugin/src/main/java/co/elastic/apm/agent/servlet/ServletServiceNameHelper.java +++ b/apm-agent-plugins/apm-servlet-plugin/src/main/java/co/elastic/apm/agent/servlet/ServletServiceNameHelper.java @@ -18,8 +18,8 @@ */ package co.elastic.apm.agent.servlet; -import co.elastic.apm.agent.configuration.ServiceInfo; -import co.elastic.apm.agent.impl.ElasticApmTracer; +import co.elastic.apm.agent.tracer.service.ServiceAwareTracer; +import co.elastic.apm.agent.tracer.service.ServiceInfo; import co.elastic.apm.agent.sdk.logging.Logger; import co.elastic.apm.agent.sdk.logging.LoggerFactory; import co.elastic.apm.agent.sdk.state.GlobalState; @@ -44,8 +44,8 @@ public static void determineServiceName(ServletContextAdapter void determineServiceName(ServletContextAdapter ServiceInfo detectServiceInfo(ServletContextAdapter adapter, ServletContext servletContext, ClassLoader servletContextClassLoader) { diff --git a/apm-agent-plugins/apm-sparkjava-plugin/pom.xml b/apm-agent-plugins/apm-sparkjava-plugin/pom.xml index a932d241c4..7da4283830 100644 --- a/apm-agent-plugins/apm-sparkjava-plugin/pom.xml +++ b/apm-agent-plugins/apm-sparkjava-plugin/pom.xml @@ -3,7 +3,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/apm-agent-plugins/apm-spring-resttemplate/apm-spring-resttemplate-plugin/pom.xml b/apm-agent-plugins/apm-spring-resttemplate/apm-spring-resttemplate-plugin/pom.xml index 0a810c0304..32685642e9 100644 --- a/apm-agent-plugins/apm-spring-resttemplate/apm-spring-resttemplate-plugin/pom.xml +++ b/apm-agent-plugins/apm-spring-resttemplate/apm-spring-resttemplate-plugin/pom.xml @@ -5,7 +5,7 @@ co.elastic.apm apm-spring-resttemplate - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-spring-resttemplate-plugin @@ -22,7 +22,7 @@ org.springframework.boot spring-boot-dependencies - 3.1.2 + 3.1.4 pom import diff --git a/apm-agent-plugins/apm-spring-resttemplate/apm-spring-resttemplate-test/pom.xml b/apm-agent-plugins/apm-spring-resttemplate/apm-spring-resttemplate-test/pom.xml index d807832431..72015e90ce 100644 --- a/apm-agent-plugins/apm-spring-resttemplate/apm-spring-resttemplate-test/pom.xml +++ b/apm-agent-plugins/apm-spring-resttemplate/apm-spring-resttemplate-test/pom.xml @@ -5,7 +5,7 @@ co.elastic.apm apm-spring-resttemplate - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-spring-resttemplate-test diff --git a/apm-agent-plugins/apm-spring-resttemplate/pom.xml b/apm-agent-plugins/apm-spring-resttemplate/pom.xml index ee4bc70ea9..c94f72c299 100644 --- a/apm-agent-plugins/apm-spring-resttemplate/pom.xml +++ b/apm-agent-plugins/apm-spring-resttemplate/pom.xml @@ -5,7 +5,7 @@ co.elastic.apm apm-agent-plugins - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-spring-resttemplate diff --git a/apm-agent-plugins/apm-spring-webflux/apm-spring-webclient-plugin/pom.xml b/apm-agent-plugins/apm-spring-webflux/apm-spring-webclient-plugin/pom.xml index 7189928852..4ffcbe4a82 100755 --- a/apm-agent-plugins/apm-spring-webflux/apm-spring-webclient-plugin/pom.xml +++ b/apm-agent-plugins/apm-spring-webflux/apm-spring-webclient-plugin/pom.xml @@ -5,7 +5,7 @@ co.elastic.apm apm-spring-webflux - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-spring-webclient-plugin diff --git a/apm-agent-plugins/apm-spring-webflux/apm-spring-webflux-plugin/pom.xml b/apm-agent-plugins/apm-spring-webflux/apm-spring-webflux-plugin/pom.xml index 3298590bbd..4a49a9535f 100644 --- a/apm-agent-plugins/apm-spring-webflux/apm-spring-webflux-plugin/pom.xml +++ b/apm-agent-plugins/apm-spring-webflux/apm-spring-webflux-plugin/pom.xml @@ -5,7 +5,7 @@ co.elastic.apm apm-spring-webflux - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-spring-webflux-plugin diff --git a/apm-agent-plugins/apm-spring-webflux/apm-spring-webflux-spring5/pom.xml b/apm-agent-plugins/apm-spring-webflux/apm-spring-webflux-spring5/pom.xml index 6c06f8cc09..13a17c7aea 100644 --- a/apm-agent-plugins/apm-spring-webflux/apm-spring-webflux-spring5/pom.xml +++ b/apm-agent-plugins/apm-spring-webflux/apm-spring-webflux-spring5/pom.xml @@ -5,7 +5,7 @@ co.elastic.apm apm-spring-webflux - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-spring-webflux-spring5 diff --git a/apm-agent-plugins/apm-spring-webflux/apm-spring-webflux-testapp/pom.xml b/apm-agent-plugins/apm-spring-webflux/apm-spring-webflux-testapp/pom.xml index 1398d6999c..6d7c9f86bb 100644 --- a/apm-agent-plugins/apm-spring-webflux/apm-spring-webflux-testapp/pom.xml +++ b/apm-agent-plugins/apm-spring-webflux/apm-spring-webflux-testapp/pom.xml @@ -5,7 +5,7 @@ co.elastic.apm apm-spring-webflux - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-spring-webflux-testapp diff --git a/apm-agent-plugins/apm-spring-webflux/pom.xml b/apm-agent-plugins/apm-spring-webflux/pom.xml index 386e97a0f6..4cb515c007 100644 --- a/apm-agent-plugins/apm-spring-webflux/pom.xml +++ b/apm-agent-plugins/apm-spring-webflux/pom.xml @@ -5,7 +5,7 @@ co.elastic.apm apm-agent-plugins - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-spring-webflux @@ -17,8 +17,8 @@ ${project.basedir}/../.. - 2.7.10 - 3.1.2 + 2.7.16 + 3.1.4 diff --git a/apm-agent-plugins/apm-spring-webmvc/apm-spring-webmvc-plugin/pom.xml b/apm-agent-plugins/apm-spring-webmvc/apm-spring-webmvc-plugin/pom.xml index 409a3149eb..e725b18695 100644 --- a/apm-agent-plugins/apm-spring-webmvc/apm-spring-webmvc-plugin/pom.xml +++ b/apm-agent-plugins/apm-spring-webmvc/apm-spring-webmvc-plugin/pom.xml @@ -5,7 +5,7 @@ apm-spring-webmvc co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-spring-webmvc-plugin @@ -22,7 +22,7 @@ org.springframework.boot spring-boot-dependencies - 3.1.2 + 3.1.4 pom import
diff --git a/apm-agent-plugins/apm-spring-webmvc/apm-spring-webmvc-spring5/pom.xml b/apm-agent-plugins/apm-spring-webmvc/apm-spring-webmvc-spring5/pom.xml index f7c45d6d34..ffbcbd6397 100644 --- a/apm-agent-plugins/apm-spring-webmvc/apm-spring-webmvc-spring5/pom.xml +++ b/apm-agent-plugins/apm-spring-webmvc/apm-spring-webmvc-spring5/pom.xml @@ -5,7 +5,7 @@ apm-spring-webmvc co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-spring-webmvc-spring5 @@ -24,7 +24,7 @@ org.springframework.boot spring-boot-dependencies - 2.7.10 + 2.7.16 pom import diff --git a/apm-agent-plugins/apm-spring-webmvc/apm-spring-webmvc-spring5/src/main/java/co/elastic/apm/agent/springwebmvc/AbstractSpringServiceNameInstrumentation.java b/apm-agent-plugins/apm-spring-webmvc/apm-spring-webmvc-spring5/src/main/java/co/elastic/apm/agent/springwebmvc/AbstractSpringServiceNameInstrumentation.java index 68a4d8f199..e38a5491f1 100644 --- a/apm-agent-plugins/apm-spring-webmvc/apm-spring-webmvc-spring5/src/main/java/co/elastic/apm/agent/springwebmvc/AbstractSpringServiceNameInstrumentation.java +++ b/apm-agent-plugins/apm-spring-webmvc/apm-spring-webmvc-spring5/src/main/java/co/elastic/apm/agent/springwebmvc/AbstractSpringServiceNameInstrumentation.java @@ -18,8 +18,8 @@ */ package co.elastic.apm.agent.springwebmvc; -import co.elastic.apm.agent.configuration.ServiceInfo; -import co.elastic.apm.agent.impl.ElasticApmTracer; +import co.elastic.apm.agent.tracer.service.ServiceAwareTracer; +import co.elastic.apm.agent.tracer.service.ServiceInfo; import co.elastic.apm.agent.sdk.ElasticApmInstrumentation; import co.elastic.apm.agent.servlet.Constants; import co.elastic.apm.agent.servlet.ServletServiceNameHelper; @@ -76,14 +76,14 @@ public static class Helper { public static void detectSpringServiceName(ServletContextAdapter adapter, WebApplicationContext applicationContext, @Nullable ServletContext servletContext) { - ElasticApmTracer elasticApmTracer = tracer.probe(ElasticApmTracer.class); - if (elasticApmTracer == null) { + ServiceAwareTracer serviceAwareTracer = tracer.probe(ServiceAwareTracer.class); + if (serviceAwareTracer == null) { return; } // avoid having two service names for a standalone jar // one based on Implementation-Title and one based on spring.application.name - if (!ServiceInfo.autoDetected().isMultiServiceContainer()) { + if (!serviceAwareTracer.autoDetectedServiceInfo().isMultiServiceContainer()) { return; } @@ -105,7 +105,7 @@ public static void detectSpringServiceName(ServletContextAdapte ServiceInfo fromSpringApplicationNameProperty = ServiceInfo.of(applicationContext.getEnvironment().getProperty("spring.application.name", "")); ServiceInfo fromApplicationContextApplicationName = ServiceInfo.of(removeLeadingSlash(applicationContext.getApplicationName())); - elasticApmTracer.setServiceInfoForClassLoader(classLoader, fromSpringApplicationNameProperty + serviceAwareTracer.setServiceInfoForClassLoader(classLoader, fromSpringApplicationNameProperty .withFallback(fromServletContext) .withFallback(fromApplicationContextApplicationName)); } diff --git a/apm-agent-plugins/apm-spring-webmvc/pom.xml b/apm-agent-plugins/apm-spring-webmvc/pom.xml index 1a63d925d6..723e855b08 100644 --- a/apm-agent-plugins/apm-spring-webmvc/pom.xml +++ b/apm-agent-plugins/apm-spring-webmvc/pom.xml @@ -3,7 +3,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 @@ -29,7 +29,7 @@ org.springframework.boot spring-boot-dependencies - 3.1.2 + 3.1.4 pom import diff --git a/apm-agent-plugins/apm-struts-plugin/pom.xml b/apm-agent-plugins/apm-struts-plugin/pom.xml index 25a48afa9b..b2564bba4d 100644 --- a/apm-agent-plugins/apm-struts-plugin/pom.xml +++ b/apm-agent-plugins/apm-struts-plugin/pom.xml @@ -3,7 +3,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/apm-agent-plugins/apm-urlconnection-plugin/pom.xml b/apm-agent-plugins/apm-urlconnection-plugin/pom.xml index 5cbc70d56f..ae2be90d08 100644 --- a/apm-agent-plugins/apm-urlconnection-plugin/pom.xml +++ b/apm-agent-plugins/apm-urlconnection-plugin/pom.xml @@ -5,7 +5,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-urlconnection-plugin diff --git a/apm-agent-plugins/apm-urlconnection-plugin/src/main/java/co/elastic/apm/agent/urlconnection/HttpUrlConnectionInstrumentation.java b/apm-agent-plugins/apm-urlconnection-plugin/src/main/java/co/elastic/apm/agent/urlconnection/HttpUrlConnectionInstrumentation.java index 6101e4225f..85155b989f 100644 --- a/apm-agent-plugins/apm-urlconnection-plugin/src/main/java/co/elastic/apm/agent/urlconnection/HttpUrlConnectionInstrumentation.java +++ b/apm-agent-plugins/apm-urlconnection-plugin/src/main/java/co/elastic/apm/agent/urlconnection/HttpUrlConnectionInstrumentation.java @@ -79,15 +79,19 @@ public static class AdviceClass { @Advice.OnMethodEnter(suppress = Throwable.class, inline = false) public static Object enter(@Advice.This HttpURLConnection thiz, @Advice.FieldValue("connected") boolean connected, + @Advice.FieldValue("responseCode") int responseCode, @Advice.Origin String signature) { + //With HEAD requests the connected stays false + boolean actuallyConnected = connected || responseCode != -1; + boolean isNestedCall = callDepth.isNestedCallAndIncrement(); ElasticContext activeContext = tracer.currentContext(); AbstractSpan parentSpan = activeContext.getSpan(); Span span = null; if (parentSpan != null) { span = inFlightSpans.get(thiz); - if (span == null && !connected) { + if (span == null && !actuallyConnected) { final URL url = thiz.getURL(); span = HttpClientHelper.startHttpClientSpan(activeContext, thiz.getRequestMethod(), url.toString(), url.getProtocol(), url.getHost(), url.getPort()); } @@ -98,7 +102,7 @@ public static Object enter(@Advice.This HttpURLConnection thiz, } } - if (!isNestedCall && !connected) { + if (!isNestedCall && !actuallyConnected) { tracer.currentContext().propagateContext(thiz, UrlConnectionPropertyAccessor.instance(), UrlConnectionPropertyAccessor.instance()); } diff --git a/apm-agent-plugins/apm-urlconnection-plugin/src/test/java/co/elastic/apm/agent/urlconnection/HttpUrlConnectionInstrumentationTest.java b/apm-agent-plugins/apm-urlconnection-plugin/src/test/java/co/elastic/apm/agent/urlconnection/HttpUrlConnectionInstrumentationTest.java index e091d49251..1200f0ad9a 100644 --- a/apm-agent-plugins/apm-urlconnection-plugin/src/test/java/co/elastic/apm/agent/urlconnection/HttpUrlConnectionInstrumentationTest.java +++ b/apm-agent-plugins/apm-urlconnection-plugin/src/test/java/co/elastic/apm/agent/urlconnection/HttpUrlConnectionInstrumentationTest.java @@ -81,6 +81,16 @@ public void testMultipleConnect() throws Exception { expectSpan("/").verify(); } + @Test + public void testMultipleGetResponseCodeWithHead() throws Exception { + final HttpURLConnection urlConnection = (HttpURLConnection) new URL(getBaseUrl() + "/").openConnection(); + urlConnection.setRequestMethod("HEAD"); + //Call twice to make sure we don't create two spans + urlConnection.getResponseCode(); + urlConnection.getResponseCode(); + expectSpan("/").verify(); + } + @Test public void testGetOutputStream() throws Exception { final HttpURLConnection urlConnection = (HttpURLConnection) new URL(getBaseUrl() + "/").openConnection(); diff --git a/apm-agent-plugins/apm-vertx/apm-vertx-common/pom.xml b/apm-agent-plugins/apm-vertx/apm-vertx-common/pom.xml index be9decb1c7..ca4181fcad 100644 --- a/apm-agent-plugins/apm-vertx/apm-vertx-common/pom.xml +++ b/apm-agent-plugins/apm-vertx/apm-vertx-common/pom.xml @@ -5,7 +5,7 @@ apm-vertx co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-vertx-common diff --git a/apm-agent-plugins/apm-vertx/apm-vertx3-plugin/pom.xml b/apm-agent-plugins/apm-vertx/apm-vertx3-plugin/pom.xml index a0a1c4d415..691536fbaa 100644 --- a/apm-agent-plugins/apm-vertx/apm-vertx3-plugin/pom.xml +++ b/apm-agent-plugins/apm-vertx/apm-vertx3-plugin/pom.xml @@ -5,7 +5,7 @@ apm-vertx co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-vertx3-plugin diff --git a/apm-agent-plugins/apm-vertx/apm-vertx3-test-latest/pom.xml b/apm-agent-plugins/apm-vertx/apm-vertx3-test-latest/pom.xml index 6cc81ff8d3..c7aab8ae11 100644 --- a/apm-agent-plugins/apm-vertx/apm-vertx3-test-latest/pom.xml +++ b/apm-agent-plugins/apm-vertx/apm-vertx3-test-latest/pom.xml @@ -5,7 +5,7 @@ apm-vertx co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-vertx3-test-latest diff --git a/apm-agent-plugins/apm-vertx/apm-vertx4-plugin/pom.xml b/apm-agent-plugins/apm-vertx/apm-vertx4-plugin/pom.xml index 79079aabf1..86541e3beb 100644 --- a/apm-agent-plugins/apm-vertx/apm-vertx4-plugin/pom.xml +++ b/apm-agent-plugins/apm-vertx/apm-vertx4-plugin/pom.xml @@ -5,7 +5,7 @@ apm-vertx co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-vertx4-plugin diff --git a/apm-agent-plugins/apm-vertx/pom.xml b/apm-agent-plugins/apm-vertx/pom.xml index d75cb4746d..6d82ec6f54 100644 --- a/apm-agent-plugins/apm-vertx/pom.xml +++ b/apm-agent-plugins/apm-vertx/pom.xml @@ -5,7 +5,7 @@ apm-agent-plugins co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-vertx diff --git a/apm-agent-plugins/pom.xml b/apm-agent-plugins/pom.xml index f0f4a8d745..686abf1efa 100644 --- a/apm-agent-plugins/pom.xml +++ b/apm-agent-plugins/pom.xml @@ -5,7 +5,7 @@ apm-agent-parent co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-agent-plugins @@ -73,6 +73,7 @@ apm-aws-sdk apm-finagle-httpclient-plugin apm-java-ldap-plugin + apm-micronaut-plugin diff --git a/apm-agent-tracer/pom.xml b/apm-agent-tracer/pom.xml index 88745af8bc..6e476cdd80 100644 --- a/apm-agent-tracer/pom.xml +++ b/apm-agent-tracer/pom.xml @@ -4,7 +4,7 @@ co.elastic.apm apm-agent-parent - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-agent-tracer @@ -24,6 +24,13 @@ apm-agent-common ${project.version} + + + net.bytebuddy + byte-buddy-dep + ${version.byte-buddy} + test + diff --git a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/AbstractSpan.java b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/AbstractSpan.java index 481ac69c1e..e164291c4d 100644 --- a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/AbstractSpan.java +++ b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/AbstractSpan.java @@ -18,13 +18,12 @@ */ package co.elastic.apm.agent.tracer; -import co.elastic.apm.agent.tracer.dispatch.BinaryHeaderGetter; -import co.elastic.apm.agent.tracer.dispatch.TextHeaderGetter; +import co.elastic.apm.agent.tracer.dispatch.HeaderGetter; import co.elastic.apm.agent.tracer.reference.ReferenceCounted; import javax.annotation.Nullable; -public interface AbstractSpan> extends Activateable, ReferenceCounted { +public interface AbstractSpan> extends ActivateableInScope, ReferenceCounted { int PRIORITY_DEFAULT = 0; int PRIORITY_LOW_LEVEL_FRAMEWORK = 10; @@ -76,9 +75,7 @@ public interface AbstractSpan> extends Activateable boolean isSampled(); - boolean addLink(BinaryHeaderGetter headerGetter, @Nullable C carrier); - - boolean addLink(TextHeaderGetter headerGetter, @Nullable C carrier); + boolean addLink(HeaderGetter headerGetter, @Nullable C carrier); /** * Appends a string to the name. diff --git a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/Activateable.java b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/Activateable.java index 737d5276b0..196a393a05 100644 --- a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/Activateable.java +++ b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/Activateable.java @@ -33,11 +33,4 @@ public interface Activateable> { * @return this */ T deactivate(); - - /** - * Activates context in a scope - * - * @return active scope that will deactivate context when closed - */ - Scope activateInScope(); } diff --git a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/ActivateableInScope.java b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/ActivateableInScope.java new file mode 100644 index 0000000000..4b9b4eeec8 --- /dev/null +++ b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/ActivateableInScope.java @@ -0,0 +1,29 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package co.elastic.apm.agent.tracer; + +public interface ActivateableInScope> extends Activateable { + + /** + * Activates context in a scope + * + * @return active scope that will deactivate context when closed + */ + Scope activateInScope(); +} diff --git a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/ElasticContext.java b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/ElasticContext.java index a36a74ec7b..4f86c8bd6a 100644 --- a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/ElasticContext.java +++ b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/ElasticContext.java @@ -18,14 +18,13 @@ */ package co.elastic.apm.agent.tracer; -import co.elastic.apm.agent.tracer.dispatch.BinaryHeaderSetter; -import co.elastic.apm.agent.tracer.dispatch.TextHeaderGetter; -import co.elastic.apm.agent.tracer.dispatch.TextHeaderSetter; +import co.elastic.apm.agent.tracer.dispatch.HeaderGetter; +import co.elastic.apm.agent.tracer.dispatch.HeaderSetter; import co.elastic.apm.agent.tracer.reference.ReferenceCounted; import javax.annotation.Nullable; -public interface ElasticContext> extends ReferenceCounted, Activateable { +public interface ElasticContext> extends ActivateableInScope, ReferenceCounted { /** * @return the span/transaction that is associated to this context, {@literal null} if there is none @@ -71,16 +70,6 @@ public interface ElasticContext> extends ReferenceCo */ boolean isEmpty(); - /** - * Propagates this context onto the given carrier. This includes both trace context and baggage. - * - * @param carrier the binary headers carrier - * @param headerSetter a setter implementing the actual addition of headers to the headers carrier - * @param the header carrier type, for example - a Kafka record - * @return true if Trace Context headers were set; false otherwise - */ - boolean propagateContext(C carrier, BinaryHeaderSetter headerSetter); - /** * Propagates this context onto the given carrier. This includes both trace context and baggage. * This method ensures that if trace-context headers are already present, they will not be overridden. @@ -91,10 +80,10 @@ public interface ElasticContext> extends ReferenceCo * If not provided, no such check will be performed. * @param the header carrier type, for example - an HTTP request */ - void propagateContext(C carrier, TextHeaderSetter headerSetter, @Nullable TextHeaderGetter headerGetter); + void propagateContext(C carrier, HeaderSetter headerSetter, @Nullable HeaderGetter headerGetter); /** - * Same as {@link #propagateContext(Object, TextHeaderSetter, TextHeaderGetter)}, except that different types can be used + * Same as {@link #propagateContext(Object, HeaderSetter, HeaderGetter)}, except that different types can be used * for the getter and setter carriers (e.g. builder vs request). * * @param carrier the text headers carrier for setting header @@ -105,10 +94,10 @@ public interface ElasticContext> extends ReferenceCo * @param the header carrier type for writing headers * @param the header carrier type for reading headers */ - void propagateContext(C1 carrier, TextHeaderSetter headerSetter, @Nullable C2 carrier2, @Nullable TextHeaderGetter headerGetter); + void propagateContext(C1 carrier, HeaderSetter headerSetter, @Nullable C2 carrier2, @Nullable HeaderGetter headerGetter); /** - * Checks if a call to {@link #propagateContext(Object, TextHeaderSetter, TextHeaderGetter)} would modify the headers of this carrier. + * Checks if a call to {@link #propagateContext(Object, HeaderSetter, HeaderGetter)} would modify the headers of this carrier. * In other words, this method can be used as a precheck to see whether a propagation is required. *

* This allows the delay and avoidance of creating costly resources, e.g. builder. @@ -118,7 +107,7 @@ public interface ElasticContext> extends ReferenceCo * @param the carrier type * @return true, if a call to propagateContext would modify the headers of the carrier */ - boolean isPropagationRequired(C carrier, TextHeaderGetter headerGetter); + boolean isPropagationRequired(C carrier, HeaderGetter headerGetter); /** * @return {@literal true} when span limit is reached and the caller can optimize and not create a span. The caller diff --git a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/ErrorCapture.java b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/ErrorCapture.java new file mode 100644 index 0000000000..2441b0e825 --- /dev/null +++ b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/ErrorCapture.java @@ -0,0 +1,26 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package co.elastic.apm.agent.tracer; + +public interface ErrorCapture extends Activateable { + + TraceContext getTraceContext(); + + void end(); +} diff --git a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/GlobalTracer.java b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/GlobalTracer.java index 7dbb91ab95..031f927381 100644 --- a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/GlobalTracer.java +++ b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/GlobalTracer.java @@ -18,8 +18,7 @@ */ package co.elastic.apm.agent.tracer; -import co.elastic.apm.agent.tracer.dispatch.BinaryHeaderGetter; -import co.elastic.apm.agent.tracer.dispatch.TextHeaderGetter; +import co.elastic.apm.agent.tracer.dispatch.HeaderGetter; import co.elastic.apm.agent.tracer.pooling.ObjectPoolFactory; import co.elastic.apm.agent.tracer.reference.ReferenceCounted; import co.elastic.apm.agent.tracer.reference.ReferenceCountedMap; @@ -111,6 +110,12 @@ public Transaction currentTransaction() { return tracer.currentTransaction(); } + @Nullable + @Override + public ErrorCapture getActiveError() { + return tracer.getActiveError(); + } + @Nullable @Override public Transaction startRootTransaction(@Nullable ClassLoader initiatingClassLoader) { @@ -119,13 +124,13 @@ public Transaction startRootTransaction(@Nullable ClassLoader initiatingClass @Nullable @Override - public Transaction startChildTransaction(@Nullable C headerCarrier, TextHeaderGetter textHeadersGetter, @Nullable ClassLoader initiatingClassLoader) { + public Transaction startChildTransaction(@Nullable C headerCarrier, HeaderGetter textHeadersGetter, @Nullable ClassLoader initiatingClassLoader) { return tracer.startChildTransaction(headerCarrier, textHeadersGetter, initiatingClassLoader); } @Nullable @Override - public Transaction startChildTransaction(@Nullable C headerCarrier, BinaryHeaderGetter binaryHeadersGetter, @Nullable ClassLoader initiatingClassLoader) { - return tracer.startChildTransaction(headerCarrier, binaryHeadersGetter, initiatingClassLoader); + public ErrorCapture captureException(@Nullable Throwable e, @Nullable ClassLoader initiatingClassLoader) { + return tracer.captureException(e, initiatingClassLoader); } } diff --git a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/NoopElasticContext.java b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/NoopElasticContext.java index 563f40dcf2..1f662c7328 100644 --- a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/NoopElasticContext.java +++ b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/NoopElasticContext.java @@ -18,9 +18,8 @@ */ package co.elastic.apm.agent.tracer; -import co.elastic.apm.agent.tracer.dispatch.BinaryHeaderSetter; -import co.elastic.apm.agent.tracer.dispatch.TextHeaderGetter; -import co.elastic.apm.agent.tracer.dispatch.TextHeaderSetter; +import co.elastic.apm.agent.tracer.dispatch.HeaderGetter; +import co.elastic.apm.agent.tracer.dispatch.HeaderSetter; import javax.annotation.Nullable; @@ -87,22 +86,17 @@ public boolean isEmpty() { } @Override - public boolean propagateContext(C carrier, BinaryHeaderSetter headerSetter) { - return false; - } - - @Override - public void propagateContext(C carrier, TextHeaderSetter headerSetter, TextHeaderGetter headerGetter) { + public void propagateContext(C carrier, HeaderSetter headerSetter, HeaderGetter headerGetter) { } @Override - public void propagateContext(C1 carrier, TextHeaderSetter headerSetter, @Nullable C2 carrier2, @Nullable TextHeaderGetter headerGetter) { + public void propagateContext(C1 carrier, HeaderSetter headerSetter, @Nullable C2 carrier2, @Nullable HeaderGetter headerGetter) { } @Override - public boolean isPropagationRequired(C carrier, TextHeaderGetter headerGetter) { + public boolean isPropagationRequired(C carrier, HeaderGetter headerGetter) { return false; } diff --git a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/NoopTracer.java b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/NoopTracer.java index 6b8490cbe4..6088e75683 100644 --- a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/NoopTracer.java +++ b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/NoopTracer.java @@ -18,8 +18,7 @@ */ package co.elastic.apm.agent.tracer; -import co.elastic.apm.agent.tracer.dispatch.BinaryHeaderGetter; -import co.elastic.apm.agent.tracer.dispatch.TextHeaderGetter; +import co.elastic.apm.agent.tracer.dispatch.HeaderGetter; import co.elastic.apm.agent.tracer.pooling.ObjectPoolFactory; import co.elastic.apm.agent.tracer.reference.ReferenceCounted; import co.elastic.apm.agent.tracer.reference.ReferenceCountedMap; @@ -88,6 +87,12 @@ public Transaction currentTransaction() { return null; } + @Nullable + @Override + public ErrorCapture getActiveError() { + return null; + } + @Nullable @Override public Transaction startRootTransaction(@Nullable ClassLoader initiatingClassLoader) { @@ -96,13 +101,13 @@ public Transaction startRootTransaction(@Nullable ClassLoader initiatingClass @Nullable @Override - public Transaction startChildTransaction(@Nullable C headerCarrier, TextHeaderGetter textHeadersGetter, @Nullable ClassLoader initiatingClassLoader) { + public Transaction startChildTransaction(@Nullable C headerCarrier, HeaderGetter textHeadersGetter, @Nullable ClassLoader initiatingClassLoader) { return null; } @Nullable @Override - public Transaction startChildTransaction(@Nullable C headerCarrier, BinaryHeaderGetter binaryHeadersGetter, @Nullable ClassLoader initiatingClassLoader) { + public ErrorCapture captureException(@Nullable Throwable e, @Nullable ClassLoader initiatingClassLoader) { return null; } } diff --git a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/Tracer.java b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/Tracer.java index 36fe7a695c..97f8e8bb87 100644 --- a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/Tracer.java +++ b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/Tracer.java @@ -18,9 +18,7 @@ */ package co.elastic.apm.agent.tracer; -import co.elastic.apm.agent.tracer.dispatch.BinaryHeaderGetter; import co.elastic.apm.agent.tracer.dispatch.HeaderGetter; -import co.elastic.apm.agent.tracer.dispatch.TextHeaderGetter; import co.elastic.apm.agent.tracer.pooling.ObjectPoolFactory; import co.elastic.apm.agent.tracer.reference.ReferenceCounted; import co.elastic.apm.agent.tracer.reference.ReferenceCountedMap; @@ -45,7 +43,6 @@ public interface Tracer { Set getTraceHeaderNames(); - ElasticContext currentContext(); @Nullable @@ -54,6 +51,9 @@ public interface Tracer { @Nullable Transaction currentTransaction(); + @Nullable + ErrorCapture getActiveError(); + /** * Starts a trace-root transaction * @@ -76,19 +76,8 @@ public interface Tracer { * @return a transaction which is a child of the provided parent if the agent is currently RUNNING; null otherwise */ @Nullable - Transaction startChildTransaction(@Nullable C headerCarrier, TextHeaderGetter textHeadersGetter, @Nullable ClassLoader initiatingClassLoader); + Transaction startChildTransaction(@Nullable C headerCarrier, HeaderGetter textHeadersGetter, @Nullable ClassLoader initiatingClassLoader); - /** - * Starts a transaction as a child of the context headers obtained through the provided {@link HeaderGetter}. - * If the created transaction cannot be started as a child transaction (for example - if no parent context header is - * available), then it will be started as the root transaction of the trace. - * - * @param headerCarrier the Object from which context headers can be obtained, typically a request or a message - * @param binaryHeadersGetter provides the trace context headers required in order to create a child transaction - * @param initiatingClassLoader the class loader corresponding to the service which initiated the creation of the transaction. - * Used to determine the service name. - * @return a transaction which is a child of the provided parent if the agent is currently RUNNING; null otherwise - */ @Nullable - Transaction startChildTransaction(@Nullable C headerCarrier, BinaryHeaderGetter binaryHeadersGetter, @Nullable ClassLoader initiatingClassLoader); + ErrorCapture captureException(@Nullable Throwable e, @Nullable ClassLoader initiatingClassLoader); } diff --git a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/dispatch/HeaderUtils.java b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/dispatch/HeaderUtils.java index 051cae999b..cc0f4e305b 100644 --- a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/dispatch/HeaderUtils.java +++ b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/dispatch/HeaderUtils.java @@ -25,7 +25,7 @@ public class HeaderUtils { private HeaderUtils() { } - public static boolean containsAny(Set headerNames, C carrier, TextHeaderGetter headerGetter) { + public static boolean containsAny(Set headerNames, C carrier, HeaderGetter headerGetter) { for (String headerName : headerNames) { if (headerGetter.getFirstHeader(headerName, carrier) != null) { return true; diff --git a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/dispatch/BinaryHeaderGetter.java b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/dispatch/UTF8ByteHeaderGetter.java similarity index 91% rename from apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/dispatch/BinaryHeaderGetter.java rename to apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/dispatch/UTF8ByteHeaderGetter.java index f0ce2b3392..c5631626c6 100644 --- a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/dispatch/BinaryHeaderGetter.java +++ b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/dispatch/UTF8ByteHeaderGetter.java @@ -18,5 +18,5 @@ */ package co.elastic.apm.agent.tracer.dispatch; -public interface BinaryHeaderGetter extends HeaderGetter { +public interface UTF8ByteHeaderGetter extends HeaderGetter { } diff --git a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/dispatch/BinaryHeaderSetter.java b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/dispatch/UTF8ByteHeaderSetter.java similarity index 81% rename from apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/dispatch/BinaryHeaderSetter.java rename to apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/dispatch/UTF8ByteHeaderSetter.java index d98ba2841c..de6251e2c4 100644 --- a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/dispatch/BinaryHeaderSetter.java +++ b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/dispatch/UTF8ByteHeaderSetter.java @@ -18,10 +18,5 @@ */ package co.elastic.apm.agent.tracer.dispatch; -import javax.annotation.Nullable; - -public interface BinaryHeaderSetter extends HeaderSetter { - - @Nullable - byte[] getFixedLengthByteArray(String headerName, int length); +public interface UTF8ByteHeaderSetter extends HeaderSetter { } diff --git a/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/service/ServiceAwareTracer.java b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/service/ServiceAwareTracer.java new file mode 100644 index 0000000000..30634926fe --- /dev/null +++ b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/service/ServiceAwareTracer.java @@ -0,0 +1,33 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package co.elastic.apm.agent.tracer.service; + +import co.elastic.apm.agent.tracer.Tracer; + +import javax.annotation.Nullable; + +public interface ServiceAwareTracer extends Tracer { + + @Nullable + ServiceInfo getServiceInfoForClassLoader(@Nullable ClassLoader initiatingClassLoader); + + void setServiceInfoForClassLoader(@Nullable ClassLoader classLoader, ServiceInfo serviceInfo); + + ServiceInfo autoDetectedServiceInfo(); +} diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/configuration/ServiceInfo.java b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/service/ServiceInfo.java similarity index 53% rename from apm-agent-core/src/main/java/co/elastic/apm/agent/configuration/ServiceInfo.java rename to apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/service/ServiceInfo.java index b003a2256f..83d4b7eb79 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/configuration/ServiceInfo.java +++ b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/service/ServiceInfo.java @@ -16,34 +16,22 @@ * specific language governing permissions and limitations * under the License. */ -package co.elastic.apm.agent.configuration; - -import co.elastic.apm.agent.sdk.internal.util.PrivilegedActionUtils; +package co.elastic.apm.agent.tracer.service; import javax.annotation.Nullable; -import java.util.Map; import java.util.Objects; -import java.util.Properties; import java.util.jar.Attributes; -import java.util.jar.JarFile; import java.util.jar.Manifest; public class ServiceInfo { - - private static final String JAR_VERSION_SUFFIX = "-(\\d+\\.)+(\\d+)(.*)?$"; private static final String DEFAULT_SERVICE_NAME = "unknown-java-service"; private static final ServiceInfo EMPTY = new ServiceInfo(null, null); - private static final ServiceInfo AUTO_DETECTED = autoDetect(System.getProperties(), PrivilegedActionUtils.getEnv()); private final String serviceName; @Nullable private final String serviceVersion; private final boolean multiServiceContainer; - public ServiceInfo(@Nullable String serviceName) { - this(serviceName, null); - } - private ServiceInfo(@Nullable String serviceName, @Nullable String serviceVersion) { this(serviceName, serviceVersion, false); } @@ -82,76 +70,6 @@ private static String replaceDisallowedServiceNameChars(String serviceName) { return serviceName.replaceAll("[^a-zA-Z0-9 _-]", "-"); } - public static ServiceInfo autoDetected() { - return AUTO_DETECTED; - } - - public static ServiceInfo autoDetect(Properties sysProperties, Map sysEnv) { - String lambdaFunctionName = sysEnv.get("AWS_LAMBDA_FUNCTION_NAME"); - if (lambdaFunctionName != null) { - return new ServiceInfo(lambdaFunctionName, sysEnv.get("AWS_LAMBDA_FUNCTION_VERSION")); - } else { - ServiceInfo serviceInfo = createFromSunJavaCommand(sysProperties.getProperty("sun.java.command")); - if (serviceInfo != null) { - return serviceInfo; - } - return ServiceInfo.empty(); - } - } - - @Nullable - private static ServiceInfo createFromSunJavaCommand(@Nullable String command) { - if (command == null) { - return null; - } - command = command.trim(); - String serviceName = getContainerServiceName(command); - if (serviceName != null) { - return ServiceInfo.ofMultiServiceContainer(serviceName); - } - if (command.contains(".jar")) { - return fromJarCommand(command); - } else { - return fromMainClassCommand(command); - } - } - - @Nullable - private static String getContainerServiceName(String command) { - if (command.startsWith("org.apache.catalina.startup.Bootstrap")) { - return "tomcat-application"; - } else if (command.startsWith("org.eclipse.jetty")) { - return "jetty-application"; - } else if (command.startsWith("com.sun.enterprise.glassfish")) { - return "glassfish-application"; - } else if (command.contains("ws-server.jar")) { - return "websphere-application"; - } else if (command.contains("jboss-modules.jar")) { - return "jboss-application"; - } else if (command.contains("weblogic")) { - return "weblogic-application"; - } - return null; - } - - private static ServiceInfo fromJarCommand(String command) { - final String[] commandParts = command.split(" "); - ServiceInfo serviceInfoFromManifest = ServiceInfo.empty(); - ServiceInfo serviceInfoFromJarName = ServiceInfo.empty(); - for (String commandPart : commandParts) { - if (commandPart.endsWith(".jar")) { - try (JarFile jarFile = new JarFile(commandPart)) { - serviceInfoFromManifest = fromManifest(jarFile.getManifest()); - } catch (Exception ignored) { - } - - serviceInfoFromJarName = ServiceInfo.of(removeVersionFromJar(removePath(removeJarExtension(commandPart)))); - break; - } - } - return serviceInfoFromManifest.withFallback(serviceInfoFromJarName); - } - public static ServiceInfo fromManifest(@Nullable Manifest manifest) { if (manifest == null) { return ServiceInfo.empty(); @@ -162,29 +80,6 @@ public static ServiceInfo fromManifest(@Nullable Manifest manifest) { mainAttributes.getValue(Attributes.Name.IMPLEMENTATION_VERSION)); } - private static String removeJarExtension(String commandPart) { - return commandPart.substring(0, commandPart.indexOf(".jar")); - } - - private static String removePath(String path) { - return path.substring(path.lastIndexOf("/") + 1).substring(path.lastIndexOf("\\") + 1); - } - - private static String removeVersionFromJar(String jarFileName) { - return jarFileName.replaceFirst(JAR_VERSION_SUFFIX, ""); - } - - private static ServiceInfo fromMainClassCommand(String command) { - final String mainClassName; - int indexOfSpace = command.indexOf(' '); - if (indexOfSpace != -1) { - mainClassName = command.substring(0, indexOfSpace); - } else { - mainClassName = command; - } - return new ServiceInfo(mainClassName.substring(mainClassName.lastIndexOf('.') + 1)); - } - public String getServiceName() { return serviceName; } diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/util/HexUtils.java b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/util/HexUtils.java similarity index 57% rename from apm-agent-core/src/main/java/co/elastic/apm/agent/util/HexUtils.java rename to apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/util/HexUtils.java index 29e05d5c22..4bf5a507cc 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/util/HexUtils.java +++ b/apm-agent-tracer/src/main/java/co/elastic/apm/agent/tracer/util/HexUtils.java @@ -16,13 +16,13 @@ * specific language governing permissions and limitations * under the License. */ -package co.elastic.apm.agent.util; +package co.elastic.apm.agent.tracer.util; -import com.dslplatform.json.JsonWriter; +import java.nio.charset.StandardCharsets; public class HexUtils { - private final static char[] hexArray = "0123456789abcdef".toCharArray(); + public static final char[] HEX_CHARS = "0123456789abcdef".toCharArray(); private HexUtils() { // only static utility methods, don't instantiate @@ -43,18 +43,6 @@ public static String bytesToHex(byte[] bytes) { return sb.toString(); } - public static void writeBytesAsHex(byte[] bytes, JsonWriter jw) { - for (int i = 0; i < bytes.length; i++) { - writeHexByte(jw, bytes[i]); - } - } - - private static void writeHexByte(JsonWriter jw, byte b) { - int v = b & 0xFF; - jw.writeByte((byte) hexArray[v >>> 4]); - jw.writeByte((byte) hexArray[v & 0x0F]); - } - public static void writeBytesAsHex(byte[] bytes, StringBuilder sb) { writeBytesAsHex(bytes, 0, bytes.length, sb); } @@ -65,13 +53,29 @@ public static void writeBytesAsHex(byte[] bytes, int offset, int length, StringB } } + + public static void writeBytesAsHexAscii(byte[] input, int inputOffset, int inputLength, byte[] outputAscii, int outputOffset) { + if (outputAscii.length - outputOffset < inputLength * 2) { + throw new IllegalArgumentException("Output buffer is not big enough!"); + } + for (int i = 0; i < inputLength; i++) { + writeBytesAsHexAscii(input[inputOffset + i], outputAscii, outputOffset + i * 2); + } + } + + public static void writeBytesAsHexAscii(byte input, byte[] outputAscii, int outputOffset) { + int v = input & 0xFF; + outputAscii[outputOffset] = (byte) HEX_CHARS[v >>> 4]; + outputAscii[outputOffset + 1] = (byte) HEX_CHARS[v & 0x0F]; + } + public static void writeByteAsHex(byte b, StringBuilder sb) { int v = b & 0xFF; - sb.append(hexArray[v >>> 4]); - sb.append(hexArray[v & 0x0F]); + sb.append(HEX_CHARS[v >>> 4]); + sb.append(HEX_CHARS[v & 0x0F]); } - public static byte getNextByte(String hexEncodedString, int offset) { + public static byte getNextByte(CharSequence hexEncodedString, int offset) { final int hi = hexCharToBinary(hexEncodedString.charAt(offset)); final int lo = hexCharToBinary(hexEncodedString.charAt(offset + 1)); if (hi == -1 || lo == -1) { @@ -80,6 +84,15 @@ public static byte getNextByte(String hexEncodedString, int offset) { return (byte) ((hi << 4) + lo); } + public static byte getNextByteAscii(byte[] asciiText, int offset) { + final int hi = hexCharToBinary((char) asciiText[offset]); + final int lo = hexCharToBinary((char) asciiText[offset + 1]); + if (hi == -1 || lo == -1) { + throw new IllegalArgumentException("Not a hex encoded string"); + } + return (byte) ((hi << 4) + lo); + } + private static int hexCharToBinary(char ch) { if ('0' <= ch && ch <= '9') { return ch - '0'; @@ -93,7 +106,7 @@ private static int hexCharToBinary(char ch) { return -1; } - public static void nextBytes(String hexEncodedString, int offset, byte[] bytes) { + public static void nextBytes(CharSequence hexEncodedString, int offset, byte[] bytes) { final int charsToRead = bytes.length * 2; if (hexEncodedString.length() < offset + charsToRead) { throw new IllegalArgumentException(String.format("Can't read %d bytes from string %s with offset %d", bytes.length, hexEncodedString, offset)); @@ -103,6 +116,25 @@ public static void nextBytes(String hexEncodedString, int offset, byte[] bytes) } } + public static void nextBytesAscii(byte[] asciiText, int offset, byte[] bytes) { + final int charsToRead = bytes.length * 2; + if (asciiText.length < offset + charsToRead) { + throw new IllegalArgumentException(String.format("Can't read %d bytes from byte array with length %d with offset %d", bytes.length, asciiText.length, offset)); + } + for (int i = 0; i < charsToRead; i += 2) { + bytes[i / 2] = getNextByteAscii(asciiText, offset + i); + } + } + + public static void decodeAscii(byte[] asciiHexEncodedString, int srcOffset, int srcLength, byte[] bytes, int destOffset) { + if (asciiHexEncodedString.length < srcOffset + srcLength) { + throw new IllegalArgumentException(String.format("Can't read %d chars from string %s with offset %d", srcLength, new String(asciiHexEncodedString, StandardCharsets.UTF_8), srcOffset)); + } + for (int i = 0; i < srcLength; i += 2) { + bytes[destOffset + (i / 2)] = getNextByteAscii(asciiHexEncodedString, srcOffset + i); + } + } + public static void decode(String hexEncodedString, int srcOffset, int srcLength, byte[] bytes, int destOffset) { if (hexEncodedString.length() < srcOffset + srcLength) { throw new IllegalArgumentException(String.format("Can't read %d chars from string %s with offset %d", srcLength, hexEncodedString, srcOffset)); @@ -112,14 +144,4 @@ public static void decode(String hexEncodedString, int srcOffset, int srcLength, } } - public static void writeAsHex(long l, JsonWriter jw) { - writeHexByte(jw, (byte) (l >> 56)); - writeHexByte(jw, (byte) (l >> 48)); - writeHexByte(jw, (byte) (l >> 40)); - writeHexByte(jw, (byte) (l >> 32)); - writeHexByte(jw, (byte) (l >> 24)); - writeHexByte(jw, (byte) (l >> 16)); - writeHexByte(jw, (byte) (l >> 8)); - writeHexByte(jw, (byte) l); - } } diff --git a/apm-agent-tracer/src/test/java/co/elastic/apm/agent/tracer/service/ServiceInfoTest.java b/apm-agent-tracer/src/test/java/co/elastic/apm/agent/tracer/service/ServiceInfoTest.java new file mode 100644 index 0000000000..68a3323321 --- /dev/null +++ b/apm-agent-tracer/src/test/java/co/elastic/apm/agent/tracer/service/ServiceInfoTest.java @@ -0,0 +1,125 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package co.elastic.apm.agent.tracer.service; + +import org.junit.jupiter.api.Test; + +import javax.annotation.Nullable; +import java.util.Map; +import java.util.jar.Attributes; +import java.util.jar.Manifest; + +import static org.assertj.core.api.Assertions.assertThat; + +class ServiceInfoTest { + + @Test + void testNormalizedName() { + checkServiceInfoEmpty(ServiceInfo.of("")); + checkServiceInfoEmpty(ServiceInfo.of(" ")); + + assertThat(ServiceInfo.of(" a")).isEqualTo(ServiceInfo.of("a")); + assertThat(ServiceInfo.of(" !web# ")).isEqualTo(ServiceInfo.of("-web-")); + } + + @Test + void createEmpty() { + checkServiceInfoEmpty(ServiceInfo.empty()); + assertThat(ServiceInfo.empty()) + .isEqualTo(ServiceInfo.empty()); + + } + + @Test + void of() { + checkServiceInfoEmpty(ServiceInfo.of(null)); + checkServiceInfoEmpty(ServiceInfo.of(null, null)); + + checkServiceInfo(ServiceInfo.of("service"), "service", null); + checkServiceInfo(ServiceInfo.of("service", null), "service", null); + checkServiceInfo(ServiceInfo.of("service", "1.2.3"), "service", "1.2.3"); + + } + + @Test + void checkEquality() { + checkEquality(ServiceInfo.of(null), ServiceInfo.empty()); + checkEquality(ServiceInfo.of(""), ServiceInfo.empty()); + checkEquality(ServiceInfo.of(null, null), ServiceInfo.empty()); + checkEquality(ServiceInfo.of("", ""), ServiceInfo.empty()); + } + + private static void checkEquality(ServiceInfo first, ServiceInfo second){ + assertThat(first) + .isEqualTo(second); + + assertThat(first.hashCode()) + .isEqualTo(second.hashCode()); + } + + @Test + void fromManifest() { + checkServiceInfoEmpty(ServiceInfo.fromManifest(null)); + checkServiceInfoEmpty(ServiceInfo.fromManifest(null)); + checkServiceInfoEmpty(ServiceInfo.fromManifest(new Manifest())); + + ServiceInfo serviceInfo = ServiceInfo.fromManifest(manifest(Map.of( + Attributes.Name.IMPLEMENTATION_TITLE.toString(), "service-name" + ))); + checkServiceInfo(serviceInfo, "service-name", null); + + serviceInfo = ServiceInfo.fromManifest(manifest(Map.of( + Attributes.Name.IMPLEMENTATION_TITLE.toString(), "my-service", + Attributes.Name.IMPLEMENTATION_VERSION.toString(), "v42" + ))); + checkServiceInfo(serviceInfo, "my-service", "v42"); + } + + private static Manifest manifest(Map entries) { + Manifest manifest = new Manifest(); + + Attributes attributes = manifest.getMainAttributes(); + entries.forEach(attributes::putValue); + + return manifest; + } + + private static void checkServiceInfoEmpty(ServiceInfo serviceInfo) { + assertThat(serviceInfo.isEmpty()).isTrue(); + assertThat(serviceInfo.getServiceName()).isEqualTo("unknown-java-service"); + assertThat(serviceInfo.hasServiceName()).isFalse(); + assertThat(serviceInfo.getServiceVersion()).isNull(); + + assertThat(serviceInfo).isEqualTo(ServiceInfo.empty()); + } + + private static void checkServiceInfo(ServiceInfo serviceInfo, String expectedServiceName, @Nullable String expectedServiceVersion) { + assertThat(serviceInfo.isEmpty()).isFalse(); + assertThat(serviceInfo.getServiceName()).isEqualTo(expectedServiceName); + assertThat(serviceInfo.hasServiceName()).isTrue(); + if (expectedServiceVersion == null) { + assertThat(serviceInfo.getServiceVersion()).isNull(); + } else { + assertThat(serviceInfo.getServiceVersion()).isEqualTo(expectedServiceVersion); + } + + assertThat(serviceInfo).isEqualTo(ServiceInfo.of(expectedServiceName, expectedServiceVersion)); + } + +} diff --git a/apm-agent-core/src/test/java/co/elastic/apm/agent/util/HexUtilsTest.java b/apm-agent-tracer/src/test/java/co/elastic/apm/agent/tracer/util/HexUtilsTest.java similarity index 60% rename from apm-agent-core/src/test/java/co/elastic/apm/agent/util/HexUtilsTest.java rename to apm-agent-tracer/src/test/java/co/elastic/apm/agent/tracer/util/HexUtilsTest.java index 82a467e250..ca6a7f1d35 100644 --- a/apm-agent-core/src/test/java/co/elastic/apm/agent/util/HexUtilsTest.java +++ b/apm-agent-tracer/src/test/java/co/elastic/apm/agent/tracer/util/HexUtilsTest.java @@ -16,13 +16,12 @@ * specific language governing permissions and limitations * under the License. */ -package co.elastic.apm.agent.util; +package co.elastic.apm.agent.tracer.util; -import com.dslplatform.json.DslJson; -import com.dslplatform.json.JsonWriter; import org.junit.jupiter.api.Test; import java.io.IOException; +import java.nio.charset.StandardCharsets; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -32,8 +31,15 @@ class HexUtilsTest { @Test void hexConversionRoundTrip() throws IOException { byte[] bytes = new byte[8]; - HexUtils.nextBytes("09c2572177fdae24", 0, bytes); - assertThat(HexUtils.bytesToHex(bytes)).isEqualTo("09c2572177fdae24"); + String hexEncodedString = "09c2572177fdae24"; + HexUtils.nextBytes(hexEncodedString, 0, bytes); + assertThat(HexUtils.bytesToHex(bytes)).isEqualTo(hexEncodedString); + + bytes = new byte[8]; + HexUtils.nextBytesAscii(hexEncodedString.getBytes(StandardCharsets.US_ASCII), 0, bytes); + byte[] outputAscii = new byte[16]; + HexUtils.writeBytesAsHexAscii(bytes, 0, 8, outputAscii, 0); + assertThat(new String(outputAscii, StandardCharsets.US_ASCII)).isEqualTo(hexEncodedString); } @Test @@ -41,6 +47,10 @@ void testInvalidHex() { assertThatThrownBy(() -> HexUtils.getNextByte("0$", 0)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("Not a hex encoded string: 0$ at offset 0"); + + assertThatThrownBy(() -> HexUtils.getNextByteAscii("0$".getBytes(StandardCharsets.US_ASCII), 0)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Not a hex encoded string"); } @Test @@ -48,23 +58,21 @@ void testStringTooSmall() { assertThatThrownBy(() -> HexUtils.nextBytes("00", 0, new byte[2])) .isInstanceOf(IllegalArgumentException.class) .hasMessage("Can't read 2 bytes from string 00 with offset 0"); + + assertThatThrownBy(() -> HexUtils.nextBytesAscii("00".getBytes(StandardCharsets.US_ASCII), 0, new byte[2])) + .isInstanceOf(IllegalArgumentException.class); } @Test void testUnevenLength() { - final byte[] bytes = new byte[1]; + byte[] bytes = new byte[1]; // reads the first two chars and converts "0a" to (byte) 10 HexUtils.nextBytes("0a0", 0, bytes); assertThat(bytes).isEqualTo(new byte[]{10}); - } - @Test - void testLongToHex() { - byte[] bytes = new byte[8]; - HexUtils.nextBytes("09c2572177fdae24", 0, bytes); - long l = ByteUtils.getLong(bytes, 0); - JsonWriter jw = new DslJson<>().newWriter(); - HexUtils.writeAsHex(l, jw); - assertThat(jw.toString()).isEqualTo("09c2572177fdae24"); + bytes = new byte[1]; + HexUtils.nextBytesAscii("0a0".getBytes(StandardCharsets.US_ASCII), 0, bytes); + assertThat(bytes).isEqualTo(new byte[]{10}); } + } diff --git a/apm-opentracing/pom.xml b/apm-opentracing/pom.xml index 8823ac2215..dd19c4819b 100644 --- a/apm-opentracing/pom.xml +++ b/apm-opentracing/pom.xml @@ -5,7 +5,7 @@ apm-agent-parent co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT apm-opentracing diff --git a/apm-opentracing/src/test/java/co/elastic/apm/opentracing/OpenTracingBridgeTest.java b/apm-opentracing/src/test/java/co/elastic/apm/opentracing/OpenTracingBridgeTest.java index b72cb09194..23d5831870 100644 --- a/apm-opentracing/src/test/java/co/elastic/apm/opentracing/OpenTracingBridgeTest.java +++ b/apm-opentracing/src/test/java/co/elastic/apm/opentracing/OpenTracingBridgeTest.java @@ -22,11 +22,11 @@ import co.elastic.apm.agent.impl.TextHeaderMapAccessor; import co.elastic.apm.agent.impl.TracerInternalApiUtils; import co.elastic.apm.agent.impl.context.Http; -import co.elastic.apm.agent.tracer.util.ResultUtil; import co.elastic.apm.agent.impl.transaction.Id; import co.elastic.apm.agent.impl.transaction.TraceContext; import co.elastic.apm.agent.impl.transaction.Transaction; import co.elastic.apm.agent.tracer.Outcome; +import co.elastic.apm.agent.tracer.util.ResultUtil; import io.opentracing.Scope; import io.opentracing.Span; import io.opentracing.SpanContext; @@ -576,7 +576,7 @@ void testInjectExtract() { final HashMap map = new HashMap<>(); apmTracer.inject(otSpan.context(), Format.Builtin.TEXT_MAP, new TextMapAdapter(map)); final TraceContext injectedContext = TraceContext.with64BitId(tracer); - assertThat(TraceContext.>getFromTraceContextTextHeaders().asChildOf(injectedContext, map, TextHeaderMapAccessor.INSTANCE)).isTrue(); + assertThat(injectedContext.asChildOf(map, TextHeaderMapAccessor.INSTANCE)).isTrue(); assertThat(injectedContext.getTraceId().toString()).isEqualTo(traceId); assertThat(injectedContext.getParentId()).isEqualTo(transaction.getTraceContext().getId()); assertThat(injectedContext.isSampled()).isTrue(); diff --git a/catalog-info.yaml b/catalog-info.yaml new file mode 100644 index 0000000000..17564e5920 --- /dev/null +++ b/catalog-info.yaml @@ -0,0 +1,93 @@ +--- +# yaml-language-server: $schema=https://gist.githubusercontent.com/elasticmachine/988b80dae436cafea07d9a4a460a011d/raw/rre.schema.json +apiVersion: backstage.io/v1alpha1 +kind: Resource +metadata: + name: buildkite-pipeline-apm-agent-java-release + description: Buildkite Release pipeline for apm-agent-java + links: + - title: Pipeline + url: https://buildkite.com/elastic/apm-agent-java-release +spec: + type: buildkite-pipeline + owner: group:apm-agent-java + system: buildkite + implementation: + apiVersion: buildkite.elastic.dev/v1 + kind: Pipeline + metadata: + name: apm-agent-java-release + spec: + repository: elastic/apm-agent-java + pipeline_file: ".buildkite/release.yml" + provider_settings: + trigger_mode: none + teams: + apm-agent-java: + access_level: MANAGE_BUILD_AND_READ + observablt-robots: + access_level: MANAGE_BUILD_AND_READ + everyone: + access_level: READ_ONLY + +--- +# yaml-language-server: $schema=https://gist.githubusercontent.com/elasticmachine/988b80dae436cafea07d9a4a460a011d/raw/rre.schema.json +apiVersion: backstage.io/v1alpha1 +kind: Resource +metadata: + name: buildkite-pipeline-apm-agent-java-snapshot + description: Buildkite Snapshot pipeline for apm-agent-java + links: + - title: Pipeline + url: https://buildkite.com/elastic/apm-agent-java-snapshot +spec: + type: buildkite-pipeline + owner: group:apm-agent-java + system: buildkite + implementation: + apiVersion: buildkite.elastic.dev/v1 + kind: Pipeline + metadata: + name: apm-agent-java-snapshot + spec: + repository: elastic/apm-agent-java + pipeline_file: ".buildkite/snapshot.yml" + provider_settings: + trigger_mode: none + teams: + apm-agent-java: + access_level: MANAGE_BUILD_AND_READ + observablt-robots: + access_level: MANAGE_BUILD_AND_READ + everyone: + access_level: READ_ONLY + +--- +# yaml-language-server: $schema=https://gist.githubusercontent.com/elasticmachine/988b80dae436cafea07d9a4a460a011d/raw/rre.schema.json +apiVersion: backstage.io/v1alpha1 +kind: Resource +metadata: + name: buildkite-pipeline-apm-agent-java-load-testing + description: Buildkite Load Testing Pipeline for apm-agent-java + links: + - title: Pipeline + url: https://buildkite.com/elastic/apm-agent-java-load-testing +spec: + type: buildkite-pipeline + owner: group:apm-agent-java + system: buildkite + implementation: + apiVersion: buildkite.elastic.dev/v1 + kind: Pipeline + metadata: + name: apm-agent-java-load-testing + spec: + repository: elastic/apm-agent-java + pipeline_file: ".buildkite/load-testing.yml" + teams: + apm-agent-java: + access_level: MANAGE_BUILD_AND_READ + observablt-robots: + access_level: MANAGE_BUILD_AND_READ + everyone: + access_level: READ_ONLY diff --git a/cloudfoundry/index.yml b/cloudfoundry/index.yml index 201827b85a..1dd8993587 100644 --- a/cloudfoundry/index.yml +++ b/cloudfoundry/index.yml @@ -53,3 +53,4 @@ 1.41.0: https://repo1.maven.org/maven2/co/elastic/apm/elastic-apm-agent/1.41.0/elastic-apm-agent-1.41.0.jar 1.41.1: https://repo1.maven.org/maven2/co/elastic/apm/elastic-apm-agent/1.41.1/elastic-apm-agent-1.41.1.jar 1.42.0: https://repo1.maven.org/maven2/co/elastic/apm/elastic-apm-agent/1.42.0/elastic-apm-agent-1.42.0.jar +1.43.0: https://repo1.maven.org/maven2/co/elastic/apm/elastic-apm-agent/1.43.0/elastic-apm-agent-1.43.0.jar diff --git a/docs/community-plugins.asciidoc b/docs/community-plugins.asciidoc index 4d75f1bd63..47d565bffc 100644 --- a/docs/community-plugins.asciidoc +++ b/docs/community-plugins.asciidoc @@ -14,3 +14,4 @@ NOTE: Elastic provides no warranty or support for community-sourced plugins. [horizontal] https://github.com/elastic/apm-agent-java-plugin-example[example repo]:: an example plugin for a custom webserver +https://github.com/videnkz/apm-jetty-httpclient-plugin[apm-jetty-httpclient-plugin]:: Jetty HttpClient plugin diff --git a/docs/metrics.asciidoc b/docs/metrics.asciidoc index 7d26ab705b..09d43629d7 100644 --- a/docs/metrics.asciidoc +++ b/docs/metrics.asciidoc @@ -580,6 +580,10 @@ Although there is no upper limit, note that a high number of distinct values per higher index sizes, and slower queries. Also, make sure the number of distinct tag keys is limited to avoid {ref}/mapping.html#mapping-limit-settings[mapping explosions]. +Depending on the meter type, some meters might be exported as multiple metrics to elasticsearch. The resulting fields are shown below for each meter type. +Note that the <> option operates on the original name of the metric, not on the generated fields. +For that reason it is only possible to disable all fields of a given metric, not individual ones. + *`Timer`*:: + -- diff --git a/docs/supported-technologies.asciidoc b/docs/supported-technologies.asciidoc index fe223cfc0e..58d3388c1f 100644 --- a/docs/supported-technologies.asciidoc +++ b/docs/supported-technologies.asciidoc @@ -183,6 +183,11 @@ rendering |Captures methods annotated with `@OnOpen`, `@OnMessage`, `@OnError`, or `@OnClose` as transactions for classes that are annotated with `@ServerEndpoint`. |1.29.0 +|Micronaut +|4.x +|Creates transactions for inbound HTTP requests, injects into PropagatedContext (introduced in 4.x), names transaction according to the controller (Controller#method) +|1.43.0 + |=== diff --git a/elastic-apm-agent-java8/pom.xml b/elastic-apm-agent-java8/pom.xml index ba12bb3481..9ad016f79c 100644 --- a/elastic-apm-agent-java8/pom.xml +++ b/elastic-apm-agent-java8/pom.xml @@ -5,7 +5,7 @@ co.elastic.apm apm-agent-parent - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT elastic-apm-agent-java8 diff --git a/elastic-apm-agent-premain/pom.xml b/elastic-apm-agent-premain/pom.xml index 9e6a043a54..7ea122c299 100644 --- a/elastic-apm-agent-premain/pom.xml +++ b/elastic-apm-agent-premain/pom.xml @@ -3,7 +3,7 @@ apm-agent-parent co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 @@ -21,6 +21,13 @@ apm-agent-common ${project.version} + + + net.bytebuddy + byte-buddy-dep + ${version.byte-buddy} + test + diff --git a/elastic-apm-agent/pom.xml b/elastic-apm-agent/pom.xml index 4147cc2fad..5282d74044 100644 --- a/elastic-apm-agent/pom.xml +++ b/elastic-apm-agent/pom.xml @@ -5,7 +5,7 @@ co.elastic.apm apm-agent-parent - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT elastic-apm-agent diff --git a/integration-tests/application-server-integration-tests/pom.xml b/integration-tests/application-server-integration-tests/pom.xml index 1daf2b433f..1c0473065d 100644 --- a/integration-tests/application-server-integration-tests/pom.xml +++ b/integration-tests/application-server-integration-tests/pom.xml @@ -5,7 +5,7 @@ integration-tests co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT application-server-integration-tests diff --git a/integration-tests/application-server-integration-tests/src/test/java/co/elastic/apm/servlet/tests/ExternalPluginTestApp.java b/integration-tests/application-server-integration-tests/src/test/java/co/elastic/apm/servlet/tests/ExternalPluginTestApp.java index 1886148281..d6c895d66e 100644 --- a/integration-tests/application-server-integration-tests/src/test/java/co/elastic/apm/servlet/tests/ExternalPluginTestApp.java +++ b/integration-tests/application-server-integration-tests/src/test/java/co/elastic/apm/servlet/tests/ExternalPluginTestApp.java @@ -18,7 +18,7 @@ */ package co.elastic.apm.servlet.tests; -import co.elastic.apm.agent.configuration.ServiceInfo; +import co.elastic.apm.agent.tracer.service.ServiceInfo; import co.elastic.apm.agent.impl.Tracer; import co.elastic.apm.agent.tracer.Outcome; import co.elastic.apm.servlet.AbstractServletContainerIntegrationTest; diff --git a/integration-tests/aws-lambda-test/pom.xml b/integration-tests/aws-lambda-test/pom.xml index 6035455471..fa1ec52f58 100644 --- a/integration-tests/aws-lambda-test/pom.xml +++ b/integration-tests/aws-lambda-test/pom.xml @@ -3,7 +3,7 @@ integration-tests co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/integration-tests/cdi-app/cdi-app-dependent/pom.xml b/integration-tests/cdi-app/cdi-app-dependent/pom.xml index 1be657db2f..6437e47d4b 100644 --- a/integration-tests/cdi-app/cdi-app-dependent/pom.xml +++ b/integration-tests/cdi-app/cdi-app-dependent/pom.xml @@ -4,7 +4,7 @@ cdi-app co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/integration-tests/cdi-app/cdi-app-standalone/pom.xml b/integration-tests/cdi-app/cdi-app-standalone/pom.xml index 2b5b58429f..10efb42d1b 100644 --- a/integration-tests/cdi-app/cdi-app-standalone/pom.xml +++ b/integration-tests/cdi-app/cdi-app-standalone/pom.xml @@ -4,7 +4,7 @@ cdi-app co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/integration-tests/cdi-app/pom.xml b/integration-tests/cdi-app/pom.xml index ff8ce5a087..67e40b0eae 100644 --- a/integration-tests/cdi-app/pom.xml +++ b/integration-tests/cdi-app/pom.xml @@ -4,7 +4,7 @@ integration-tests co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/integration-tests/cdi-jakartaee-app/cdi-jakartaee-app-dependent/pom.xml b/integration-tests/cdi-jakartaee-app/cdi-jakartaee-app-dependent/pom.xml index 5349261f67..1118abe120 100644 --- a/integration-tests/cdi-jakartaee-app/cdi-jakartaee-app-dependent/pom.xml +++ b/integration-tests/cdi-jakartaee-app/cdi-jakartaee-app-dependent/pom.xml @@ -4,7 +4,7 @@ cdi-jakartaee-app co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/integration-tests/cdi-jakartaee-app/cdi-jakartaee-app-standalone/pom.xml b/integration-tests/cdi-jakartaee-app/cdi-jakartaee-app-standalone/pom.xml index 15e5ddff15..0896294585 100644 --- a/integration-tests/cdi-jakartaee-app/cdi-jakartaee-app-standalone/pom.xml +++ b/integration-tests/cdi-jakartaee-app/cdi-jakartaee-app-standalone/pom.xml @@ -4,7 +4,7 @@ cdi-jakartaee-app co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/integration-tests/cdi-jakartaee-app/pom.xml b/integration-tests/cdi-jakartaee-app/pom.xml index 670aa38eec..bc59cbd19c 100644 --- a/integration-tests/cdi-jakartaee-app/pom.xml +++ b/integration-tests/cdi-jakartaee-app/pom.xml @@ -4,7 +4,7 @@ integration-tests co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/integration-tests/external-plugin-otel-test/external-plugin-otel-test-app/pom.xml b/integration-tests/external-plugin-otel-test/external-plugin-otel-test-app/pom.xml index c5d81ea388..51b3a5b711 100644 --- a/integration-tests/external-plugin-otel-test/external-plugin-otel-test-app/pom.xml +++ b/integration-tests/external-plugin-otel-test/external-plugin-otel-test-app/pom.xml @@ -4,7 +4,7 @@ co.elastic.apm external-plugin-otel-test - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT external-plugin-otel-test-app diff --git a/integration-tests/external-plugin-otel-test/external-plugin-otel-test-plugin1/pom.xml b/integration-tests/external-plugin-otel-test/external-plugin-otel-test-plugin1/pom.xml index db47710ecf..ad6843db77 100644 --- a/integration-tests/external-plugin-otel-test/external-plugin-otel-test-plugin1/pom.xml +++ b/integration-tests/external-plugin-otel-test/external-plugin-otel-test-plugin1/pom.xml @@ -4,7 +4,7 @@ co.elastic.apm external-plugin-otel-test - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT external-plugin-otel-test-plugin1 diff --git a/integration-tests/external-plugin-otel-test/external-plugin-otel-test-plugin2/pom.xml b/integration-tests/external-plugin-otel-test/external-plugin-otel-test-plugin2/pom.xml index a9df8d6652..11ab07f4a0 100644 --- a/integration-tests/external-plugin-otel-test/external-plugin-otel-test-plugin2/pom.xml +++ b/integration-tests/external-plugin-otel-test/external-plugin-otel-test-plugin2/pom.xml @@ -4,7 +4,7 @@ co.elastic.apm external-plugin-otel-test - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT external-plugin-otel-test-plugin2 diff --git a/integration-tests/external-plugin-otel-test/pom.xml b/integration-tests/external-plugin-otel-test/pom.xml index 734f100e5e..a4e51cd926 100644 --- a/integration-tests/external-plugin-otel-test/pom.xml +++ b/integration-tests/external-plugin-otel-test/pom.xml @@ -4,7 +4,7 @@ co.elastic.apm integration-tests - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT external-plugin-otel-test diff --git a/integration-tests/external-plugin-test/external-plugin-app/pom.xml b/integration-tests/external-plugin-test/external-plugin-app/pom.xml index 8e67da6075..ab182f00a5 100644 --- a/integration-tests/external-plugin-test/external-plugin-app/pom.xml +++ b/integration-tests/external-plugin-test/external-plugin-app/pom.xml @@ -6,7 +6,7 @@ external-plugin-test co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT external-plugin-app diff --git a/integration-tests/external-plugin-test/external-plugin-jakarta-app/pom.xml b/integration-tests/external-plugin-test/external-plugin-jakarta-app/pom.xml index c88fddc341..30c1e88c0a 100644 --- a/integration-tests/external-plugin-test/external-plugin-jakarta-app/pom.xml +++ b/integration-tests/external-plugin-test/external-plugin-jakarta-app/pom.xml @@ -6,7 +6,7 @@ external-plugin-test co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT external-plugin-jakarta-app diff --git a/integration-tests/external-plugin-test/external-plugin/pom.xml b/integration-tests/external-plugin-test/external-plugin/pom.xml index b3f96ab1e2..20ac865078 100644 --- a/integration-tests/external-plugin-test/external-plugin/pom.xml +++ b/integration-tests/external-plugin-test/external-plugin/pom.xml @@ -6,7 +6,7 @@ external-plugin-test co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT external-plugin diff --git a/integration-tests/external-plugin-test/plugin-instrumentation-target/pom.xml b/integration-tests/external-plugin-test/plugin-instrumentation-target/pom.xml index 750b128eb1..69303d7c7c 100644 --- a/integration-tests/external-plugin-test/plugin-instrumentation-target/pom.xml +++ b/integration-tests/external-plugin-test/plugin-instrumentation-target/pom.xml @@ -6,7 +6,7 @@ external-plugin-test co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT plugin-instrumentation-target diff --git a/integration-tests/external-plugin-test/pom.xml b/integration-tests/external-plugin-test/pom.xml index d10c779d1a..336ddb04a2 100644 --- a/integration-tests/external-plugin-test/pom.xml +++ b/integration-tests/external-plugin-test/pom.xml @@ -3,7 +3,7 @@ integration-tests co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/integration-tests/jakartaee-jsf-app/jakartaee-jsf-app-dependent/pom.xml b/integration-tests/jakartaee-jsf-app/jakartaee-jsf-app-dependent/pom.xml index 256e3d6abc..c36116e0fd 100644 --- a/integration-tests/jakartaee-jsf-app/jakartaee-jsf-app-dependent/pom.xml +++ b/integration-tests/jakartaee-jsf-app/jakartaee-jsf-app-dependent/pom.xml @@ -3,7 +3,7 @@ jakartaee-jsf-app co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/integration-tests/jakartaee-jsf-app/jakartaee-jsf-app-standalone/pom.xml b/integration-tests/jakartaee-jsf-app/jakartaee-jsf-app-standalone/pom.xml index 37b31f65b6..651ea6f509 100644 --- a/integration-tests/jakartaee-jsf-app/jakartaee-jsf-app-standalone/pom.xml +++ b/integration-tests/jakartaee-jsf-app/jakartaee-jsf-app-standalone/pom.xml @@ -3,7 +3,7 @@ jakartaee-jsf-app co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/integration-tests/jakartaee-jsf-app/pom.xml b/integration-tests/jakartaee-jsf-app/pom.xml index 02e2a11b53..c28df5b385 100644 --- a/integration-tests/jakartaee-jsf-app/pom.xml +++ b/integration-tests/jakartaee-jsf-app/pom.xml @@ -3,7 +3,7 @@ integration-tests co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 pom diff --git a/integration-tests/jakartaee-simple-webapp/pom.xml b/integration-tests/jakartaee-simple-webapp/pom.xml index 96b46ad404..b6db62bcf0 100644 --- a/integration-tests/jakartaee-simple-webapp/pom.xml +++ b/integration-tests/jakartaee-simple-webapp/pom.xml @@ -5,7 +5,7 @@ integration-tests co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT jakartaee-simple-webapp diff --git a/integration-tests/jsf-app/jsf-app-dependent/pom.xml b/integration-tests/jsf-app/jsf-app-dependent/pom.xml index 1556472340..cd754a3c55 100644 --- a/integration-tests/jsf-app/jsf-app-dependent/pom.xml +++ b/integration-tests/jsf-app/jsf-app-dependent/pom.xml @@ -4,7 +4,7 @@ jsf-app co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/integration-tests/jsf-app/jsf-app-standalone/pom.xml b/integration-tests/jsf-app/jsf-app-standalone/pom.xml index 9a00eb42a6..ae96ac7c5b 100644 --- a/integration-tests/jsf-app/jsf-app-standalone/pom.xml +++ b/integration-tests/jsf-app/jsf-app-standalone/pom.xml @@ -6,7 +6,7 @@ jsf-app co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT jsf-app-standalone diff --git a/integration-tests/jsf-app/pom.xml b/integration-tests/jsf-app/pom.xml index 1b73417583..76a843d966 100644 --- a/integration-tests/jsf-app/pom.xml +++ b/integration-tests/jsf-app/pom.xml @@ -6,7 +6,7 @@ integration-tests co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT jsf-app diff --git a/integration-tests/main-app-test/pom.xml b/integration-tests/main-app-test/pom.xml index 4d42335ad5..523d4e1e03 100644 --- a/integration-tests/main-app-test/pom.xml +++ b/integration-tests/main-app-test/pom.xml @@ -5,7 +5,7 @@ integration-tests co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT main-app-test diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml index 0c239cd61e..61abc23576 100644 --- a/integration-tests/pom.xml +++ b/integration-tests/pom.xml @@ -5,7 +5,7 @@ apm-agent-parent co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT integration-tests diff --git a/integration-tests/quarkus/pom.xml b/integration-tests/quarkus/pom.xml index 078172a8b5..79163692e5 100644 --- a/integration-tests/quarkus/pom.xml +++ b/integration-tests/quarkus/pom.xml @@ -5,7 +5,7 @@ integration-tests co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT quarkus diff --git a/integration-tests/quarkus/quarkus-jaxrs-base/pom.xml b/integration-tests/quarkus/quarkus-jaxrs-base/pom.xml index b35a4e3ffe..51e3557853 100644 --- a/integration-tests/quarkus/quarkus-jaxrs-base/pom.xml +++ b/integration-tests/quarkus/quarkus-jaxrs-base/pom.xml @@ -5,7 +5,7 @@ quarkus co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT quarkus-jaxrs-base diff --git a/integration-tests/quarkus/quarkus-jaxrs-undertow/pom.xml b/integration-tests/quarkus/quarkus-jaxrs-undertow/pom.xml index f5feb10e3c..265fb6785f 100644 --- a/integration-tests/quarkus/quarkus-jaxrs-undertow/pom.xml +++ b/integration-tests/quarkus/quarkus-jaxrs-undertow/pom.xml @@ -5,7 +5,7 @@ quarkus co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT quarkus-jaxrs-undertow diff --git a/integration-tests/quarkus/quarkus-jaxrs-vertx/pom.xml b/integration-tests/quarkus/quarkus-jaxrs-vertx/pom.xml index ec7f0719c2..c05df59398 100644 --- a/integration-tests/quarkus/quarkus-jaxrs-vertx/pom.xml +++ b/integration-tests/quarkus/quarkus-jaxrs-vertx/pom.xml @@ -5,7 +5,7 @@ quarkus co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT quarkus-jaxrs-vertx diff --git a/integration-tests/runtime-attach/pom.xml b/integration-tests/runtime-attach/pom.xml index 2b85660629..e1b50ff4dc 100644 --- a/integration-tests/runtime-attach/pom.xml +++ b/integration-tests/runtime-attach/pom.xml @@ -6,7 +6,7 @@ integration-tests co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT runtime-attach diff --git a/integration-tests/runtime-attach/runtime-attach-app/pom.xml b/integration-tests/runtime-attach/runtime-attach-app/pom.xml index 6a88d23984..70d1ed6688 100644 --- a/integration-tests/runtime-attach/runtime-attach-app/pom.xml +++ b/integration-tests/runtime-attach/runtime-attach-app/pom.xml @@ -3,7 +3,7 @@ runtime-attach co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/integration-tests/runtime-attach/runtime-attach-test/pom.xml b/integration-tests/runtime-attach/runtime-attach-test/pom.xml index 8b9357d9f9..38811b36ec 100644 --- a/integration-tests/runtime-attach/runtime-attach-test/pom.xml +++ b/integration-tests/runtime-attach/runtime-attach-test/pom.xml @@ -3,7 +3,7 @@ runtime-attach co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/integration-tests/simple-webapp/pom.xml b/integration-tests/simple-webapp/pom.xml index be585011ba..7298051bf5 100644 --- a/integration-tests/simple-webapp/pom.xml +++ b/integration-tests/simple-webapp/pom.xml @@ -6,7 +6,7 @@ integration-tests co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT simple-webapp diff --git a/integration-tests/soap-test/pom.xml b/integration-tests/soap-test/pom.xml index 6df030145d..4788ea99e7 100644 --- a/integration-tests/soap-test/pom.xml +++ b/integration-tests/soap-test/pom.xml @@ -5,7 +5,7 @@ integration-tests co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT soap-test diff --git a/integration-tests/spring-boot-1-5/pom.xml b/integration-tests/spring-boot-1-5/pom.xml index fc7bd94d42..5b22443a05 100644 --- a/integration-tests/spring-boot-1-5/pom.xml +++ b/integration-tests/spring-boot-1-5/pom.xml @@ -5,7 +5,7 @@ integration-tests co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT spring-boot-1-5 diff --git a/integration-tests/spring-boot-2/pom.xml b/integration-tests/spring-boot-2/pom.xml index 52c44cbff6..dcfe25524a 100644 --- a/integration-tests/spring-boot-2/pom.xml +++ b/integration-tests/spring-boot-2/pom.xml @@ -5,7 +5,7 @@ integration-tests co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT spring-boot-2 @@ -31,7 +31,7 @@ org.springframework.boot spring-boot-dependencies - 2.7.10 + 2.7.16 pom import diff --git a/integration-tests/spring-boot-2/spring-boot-2-base/pom.xml b/integration-tests/spring-boot-2/spring-boot-2-base/pom.xml index 20422b170b..b3cc302ad5 100644 --- a/integration-tests/spring-boot-2/spring-boot-2-base/pom.xml +++ b/integration-tests/spring-boot-2/spring-boot-2-base/pom.xml @@ -5,7 +5,7 @@ spring-boot-2 co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT spring-boot-2-base diff --git a/integration-tests/spring-boot-2/spring-boot-2-jetty/pom.xml b/integration-tests/spring-boot-2/spring-boot-2-jetty/pom.xml index 97fe47f0a2..6ab4947f34 100644 --- a/integration-tests/spring-boot-2/spring-boot-2-jetty/pom.xml +++ b/integration-tests/spring-boot-2/spring-boot-2-jetty/pom.xml @@ -5,7 +5,7 @@ spring-boot-2 co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT spring-boot-2-jetty diff --git a/integration-tests/spring-boot-2/spring-boot-2-tomcat/pom.xml b/integration-tests/spring-boot-2/spring-boot-2-tomcat/pom.xml index 1b00032cfb..e08fbf0ac5 100644 --- a/integration-tests/spring-boot-2/spring-boot-2-tomcat/pom.xml +++ b/integration-tests/spring-boot-2/spring-boot-2-tomcat/pom.xml @@ -5,7 +5,7 @@ spring-boot-2 co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT spring-boot-2-tomcat diff --git a/integration-tests/spring-boot-2/spring-boot-2-undertow/pom.xml b/integration-tests/spring-boot-2/spring-boot-2-undertow/pom.xml index b27978ba83..5acbb8ace9 100644 --- a/integration-tests/spring-boot-2/spring-boot-2-undertow/pom.xml +++ b/integration-tests/spring-boot-2/spring-boot-2-undertow/pom.xml @@ -5,7 +5,7 @@ spring-boot-2 co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT spring-boot-2-undertow diff --git a/integration-tests/spring-boot-3/pom.xml b/integration-tests/spring-boot-3/pom.xml index f28a72895f..23f0defbc5 100644 --- a/integration-tests/spring-boot-3/pom.xml +++ b/integration-tests/spring-boot-3/pom.xml @@ -5,7 +5,7 @@ integration-tests co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT spring-boot-3 @@ -30,7 +30,7 @@ org.springframework.boot spring-boot-dependencies - 3.1.2 + 3.1.4 pom import diff --git a/integration-tests/spring-boot-3/spring-boot-3-jetty/pom.xml b/integration-tests/spring-boot-3/spring-boot-3-jetty/pom.xml index 3945b9c621..31efac4148 100644 --- a/integration-tests/spring-boot-3/spring-boot-3-jetty/pom.xml +++ b/integration-tests/spring-boot-3/spring-boot-3-jetty/pom.xml @@ -3,7 +3,7 @@ spring-boot-3 co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/integration-tests/spring-boot-3/spring-boot-3-tomcat/pom.xml b/integration-tests/spring-boot-3/spring-boot-3-tomcat/pom.xml index 8a3cc40db1..6787975ae7 100644 --- a/integration-tests/spring-boot-3/spring-boot-3-tomcat/pom.xml +++ b/integration-tests/spring-boot-3/spring-boot-3-tomcat/pom.xml @@ -3,7 +3,7 @@ spring-boot-3 co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/integration-tests/spring-boot-3/spring-boot-3-undertow/pom.xml b/integration-tests/spring-boot-3/spring-boot-3-undertow/pom.xml index 74bbbde93e..01df3715b6 100644 --- a/integration-tests/spring-boot-3/spring-boot-3-undertow/pom.xml +++ b/integration-tests/spring-boot-3/spring-boot-3-undertow/pom.xml @@ -3,7 +3,7 @@ spring-boot-3 co.elastic.apm - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT 4.0.0 diff --git a/pom.xml b/pom.xml index eadb44e249..a152bbb355 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ co.elastic.apm apm-agent-parent - 1.42.1-SNAPSHOT + 1.43.1-SNAPSHOT pom ${project.groupId}:${project.artifactId} @@ -131,8 +131,8 @@ 9.4.11.v20180605 1.0.86 - 1.14.7 - 9.5 + 1.14.8 + 9.6 5.4.0 5.1.1 @@ -142,6 +142,9 @@ 1.16.3 + + 2.38.0 + UTF-8 UTF-8 @@ -386,29 +389,29 @@ - - org.codehaus.mojo - animal-sniffer-maven-plugin - - - signature-check - verify - - check - - - - - ${animal.sniffer.skip} - - org.codehaus.mojo.signature - java17 - 1.0 - - - java.lang.invoke.MethodHandle - - + + + + + + + + + + + + + + + + + + + + + + + maven-enforcer-plugin @@ -721,12 +724,24 @@ assertj-core 3.24.2 test + + + net.bytebuddy + byte-buddy + + org.mockito mockito-core ${version.mockito} test + + + net.bytebuddy + byte-buddy + + @@ -756,7 +771,7 @@ net.javacrumbs.json-unit json-unit-assertj - 2.37.0 + ${version.jsonunit} test