Skip to content

Commit

Permalink
Merge remote-tracking branch 'elastic/main' into context-propagation-…
Browse files Browse the repository at this point in the history
…only

# Conflicts:
#	CHANGELOG.asciidoc
  • Loading branch information
JonasKunz committed Oct 24, 2023
2 parents 77d9d5b + 5fcba10 commit d74e2fc
Show file tree
Hide file tree
Showing 24 changed files with 251 additions and 62 deletions.
2 changes: 2 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ updates:
- dependency-name: "io.vertx:*"
- dependency-name: "org.apache.logging.log4j:*"
- dependency-name: "org.springframework.boot:*"
- dependency-name: "io.opentelemetry:*"
- dependency-name: "io.opentelemetry.semconv:*"
ignore:
- dependency-name: "net.bytebuddy:byte-buddy-agent"
# We deliberately want to keep this older version of Byte Buddy for our runtime attach test
Expand Down
28 changes: 0 additions & 28 deletions .github/workflows/triggerCI.yml

This file was deleted.

3 changes: 3 additions & 0 deletions CHANGELOG.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ Use subheadings with the "=====" level for adding notes for unreleased changes:
[float]
===== Features
* Added protection against invalid timestamps provided by manual instrumentation - {pull}3363[#3363]
* Added support for AWS SDK 2.21 - {pull}3373[#3373]
* Capture bucket and object key to Lambda transaction as OTel attributes - `aws.s3.bueckt`, `aws.s3.key` - {pull}3364[#3364]
* Added `context_propagation_only` configuration option - {pull}3358[#3358]
[float]
Expand Down
2 changes: 1 addition & 1 deletion apm-agent-builds/apm-agent-java8/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<!-- Upgrade log4j2 to non vulnerable version -->
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-bom</artifactId>
<version>2.20.0</version>
<version>2.21.0</version>
<scope>import</scope>
<type>pom</type>
</dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,13 @@ public void end() {

public final void end(long epochMicros) {
if (!finished) {

long startTime = timestamp.get();
if(epochMicros < startTime) {
logger.warn("End called on {} with a timestamp before start! Using start timestamp as end instead.", this);
epochMicros = startTime;
}

this.endTimestamp.set(epochMicros);
childDurations.onSpanEnd(epochMicros);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,20 @@ void testTimestamps() {
assertThat(span.getDuration()).isEqualTo(10);
}

@Test
void testTimestampSanitization() {
final Transaction transaction = tracerImpl.startChildTransaction(new HashMap<>(), TextHeaderMapAccessor.INSTANCE, ConstantSampler.of(true), 10, null);
final Span span = transaction.createSpan(20);
span.end(10);

transaction.end(5);

assertThat(transaction.getTimestamp()).isEqualTo(10);
assertThat(transaction.getDuration()).isEqualTo(0);
assertThat(span.getTimestamp()).isEqualTo(20);
assertThat(span.getDuration()).isEqualTo(0);
}

@Test
void testStartSpanAfterTransactionHasEnded() {
final Transaction transaction = startTestRootTransaction();
Expand Down
2 changes: 1 addition & 1 deletion apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-2-plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

<properties>
<apm-agent-parent.base.dir>${project.basedir}/../../..</apm-agent-parent.base.dir>
<version.aws.sdk>2.20.157</version.aws.sdk>
<version.aws.sdk>2.21.1</version.aws.sdk>
<version.aws.jms>2.0.0</version.aws.jms>
<!-- AWS SDK v2 is compiled for Java 8 -->
<maven.compiler.target>8</maven.compiler.target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
import co.elastic.apm.agent.awssdk.v2.helper.S3Helper;
import co.elastic.apm.agent.awssdk.v2.helper.SQSHelper;
import co.elastic.apm.agent.sdk.ElasticApmInstrumentation;
import co.elastic.apm.agent.sdk.logging.Logger;
import co.elastic.apm.agent.sdk.logging.LoggerFactory;
import co.elastic.apm.agent.tracer.GlobalTracer;
import co.elastic.apm.agent.tracer.Span;
import co.elastic.apm.agent.tracer.Tracer;
Expand All @@ -35,6 +37,7 @@
import software.amazon.awssdk.core.client.config.SdkClientOption;
import software.amazon.awssdk.core.client.handler.ClientExecutionParams;
import software.amazon.awssdk.core.http.ExecutionContext;
import software.amazon.awssdk.core.internal.handler.BaseAsyncClientHandler;
import software.amazon.awssdk.core.internal.http.TransformingAsyncResponseHandler;

import java.net.URI;
Expand Down Expand Up @@ -70,12 +73,21 @@ public Collection<String> getInstrumentationGroupNames() {
@SuppressWarnings({"unchecked", "rawtypes"})
public static class AdviceClass {

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

@Advice.OnMethodEnter(suppress = Throwable.class, inline = false)
@Advice.AssignReturned.ToArguments(@Advice.AssignReturned.ToArguments.ToArgument(value = 2))
public static TransformingAsyncResponseHandler<?> enterDoExecute(@Advice.Argument(value = 0) ClientExecutionParams clientExecutionParams,
@Advice.Argument(value = 1) ExecutionContext executionContext,
@Advice.Argument(value = 2) TransformingAsyncResponseHandler<?> responseHandler,
@Advice.FieldValue("clientConfiguration") SdkClientConfiguration clientConfiguration) {
@Advice.This BaseAsyncClientHandler handler) {

SdkClientConfiguration clientConfiguration = ClientHandlerConfigInstrumentation.AdviceClass.getConfig(handler);
if(clientConfiguration == null) {
logger.warn("Not tracing AWS request due to being unable to resolve the configuration");
return responseHandler;
}

String awsService = executionContext.executionAttributes().getAttribute(AwsSignerExecutionAttribute.SERVICE_NAME);
SdkRequest sdkRequest = clientExecutionParams.getInput();
URI uri = clientConfiguration.option(SdkClientOption.ENDPOINT);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
import co.elastic.apm.agent.awssdk.v2.helper.sqs.wrapper.MessageListWrapper;
import co.elastic.apm.agent.common.JvmRuntimeInfo;
import co.elastic.apm.agent.sdk.ElasticApmInstrumentation;
import co.elastic.apm.agent.sdk.logging.Logger;
import co.elastic.apm.agent.sdk.logging.LoggerFactory;
import co.elastic.apm.agent.tracer.GlobalTracer;
import co.elastic.apm.agent.tracer.Outcome;
import co.elastic.apm.agent.tracer.Span;
Expand All @@ -39,6 +41,8 @@
import software.amazon.awssdk.core.client.config.SdkClientOption;
import software.amazon.awssdk.core.client.handler.ClientExecutionParams;
import software.amazon.awssdk.core.http.ExecutionContext;
import software.amazon.awssdk.core.internal.handler.BaseAsyncClientHandler;
import software.amazon.awssdk.core.internal.handler.BaseSyncClientHandler;

import javax.annotation.Nullable;
import java.net.URI;
Expand Down Expand Up @@ -81,11 +85,20 @@ public Collection<String> getInstrumentationGroupNames() {
@SuppressWarnings("rawtypes")
public static class AdviceClass {

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

@Nullable
@Advice.OnMethodEnter(suppress = Throwable.class, inline = false)
public static Object enterDoExecute(@Advice.Argument(value = 0) ClientExecutionParams clientExecutionParams,
@Advice.Argument(value = 1) ExecutionContext executionContext,
@Advice.FieldValue("clientConfiguration") SdkClientConfiguration clientConfiguration) {
@Advice.This BaseSyncClientHandler handler) {

SdkClientConfiguration clientConfiguration = ClientHandlerConfigInstrumentation.AdviceClass.getConfig(handler);
if(clientConfiguration == null) {
logger.warn("Not tracing AWS request due to being unable to resolve the configuration");
return null;
}

String awsService = executionContext.executionAttributes().getAttribute(AwsSignerExecutionAttribute.SERVICE_NAME);
SdkRequest sdkRequest = clientExecutionParams.getInput();
URI uri = clientConfiguration.option(SdkClientOption.ENDPOINT);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* 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.awssdk.v2;

import co.elastic.apm.agent.awssdk.v2.helper.DynamoDbHelper;
import co.elastic.apm.agent.awssdk.v2.helper.S3Helper;
import co.elastic.apm.agent.awssdk.v2.helper.SQSHelper;
import co.elastic.apm.agent.awssdk.v2.helper.sqs.wrapper.MessageListWrapper;
import co.elastic.apm.agent.common.JvmRuntimeInfo;
import co.elastic.apm.agent.sdk.ElasticApmInstrumentation;
import co.elastic.apm.agent.sdk.weakconcurrent.WeakConcurrent;
import co.elastic.apm.agent.sdk.weakconcurrent.WeakMap;
import co.elastic.apm.agent.tracer.GlobalTracer;
import co.elastic.apm.agent.tracer.Outcome;
import co.elastic.apm.agent.tracer.Span;
import co.elastic.apm.agent.tracer.Tracer;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;
import software.amazon.awssdk.auth.signer.AwsSignerExecutionAttribute;
import software.amazon.awssdk.core.SdkRequest;
import software.amazon.awssdk.core.SdkResponse;
import software.amazon.awssdk.core.client.config.SdkClientConfiguration;
import software.amazon.awssdk.core.client.config.SdkClientOption;
import software.amazon.awssdk.core.client.handler.ClientExecutionParams;
import software.amazon.awssdk.core.http.ExecutionContext;

import javax.annotation.Nullable;
import java.net.URI;
import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import static net.bytebuddy.matcher.ElementMatchers.isConstructor;
import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;

public class ClientHandlerConfigInstrumentation extends ElasticApmInstrumentation {


@Override
public ElementMatcher<? super TypeDescription> getTypeMatcher() {
return named("software.amazon.awssdk.core.internal.handler.BaseSyncClientHandler")
.or(named("software.amazon.awssdk.core.internal.handler.BaseAsyncClientHandler"));
}

@Override
public ElementMatcher<? super MethodDescription> getMethodMatcher() {
return isConstructor()
.and(takesArgument(0, named("software.amazon.awssdk.core.client.config.SdkClientConfiguration")));
}

@Override
public Collection<String> getInstrumentationGroupNames() {
return Collections.singleton("aws-sdk");
}


@SuppressWarnings("rawtypes")
public static class AdviceClass {

private static final WeakMap<Object, SdkClientConfiguration> configMap = WeakConcurrent.buildMap();

@Nullable
public static SdkClientConfiguration getConfig(Object handler) {
return configMap.get(handler);
}


@Advice.OnMethodExit(suppress = Throwable.class, inline = false)
public static void exit(@Advice.This Object handler, @Advice.Argument(value = 0) SdkClientConfiguration config) {
configMap.put(handler, config);
}

}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
co.elastic.apm.agent.awssdk.v2.BaseSyncClientHandlerInstrumentation
co.elastic.apm.agent.awssdk.v2.BaseAsyncClientHandlerInstrumentation
co.elastic.apm.agent.awssdk.v2.ClientHandlerConfigInstrumentation
co.elastic.apm.agent.awssdk.v2.GetMessagesInstrumentation
co.elastic.apm.agent.awssdk.v2.AmazonSQSMessagingClientWrapperInstrumentation
co.elastic.apm.agent.awssdk.v2.AmazonSQSMessagingClientWrapperInstrumentation
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,20 @@ protected void setTransactionTriggerData(Transaction transaction, S3Event s3Even

cloudOrigin.withRegion(s3NotificationRecord.getAwsRegion());

if (null != s3NotificationRecord.getS3() && null != s3NotificationRecord.getS3().getBucket()) {
if (null != s3NotificationRecord.getS3()) {
S3EventNotification.S3BucketEntity bucket = s3NotificationRecord.getS3().getBucket();
ServiceOrigin serviceOrigin = transaction.getContext().getServiceOrigin();
serviceOrigin.withId(bucket.getArn());
serviceOrigin.withName(bucket.getName());
serviceOrigin.withVersion(s3NotificationRecord.getEventVersion());
if (null != bucket) {
ServiceOrigin serviceOrigin = transaction.getContext().getServiceOrigin();
serviceOrigin.withId(bucket.getArn());
serviceOrigin.withName(bucket.getName());
serviceOrigin.withVersion(s3NotificationRecord.getEventVersion());

transaction.withOtelAttribute("aws.s3.bucket", bucket.getName());
}
S3EventNotification.S3ObjectEntity object = s3NotificationRecord.getS3().getObject();
if (null != object) {
transaction.withOtelAttribute("aws.s3.key", object.getKey());
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ protected boolean supportsContextPropagation() {
private S3EventNotification.S3EventNotificationRecord createS3NotificationRecord() {
S3EventNotification.ResponseElementsEntity responseElements = new S3EventNotification.ResponseElementsEntity("xAmzId2", S3_REQUEST_ID);
S3EventNotification.S3BucketEntity bucket = new S3EventNotification.S3BucketEntity(S3_BUCKET_NAME, null, S3_BUCKET_ARN);
S3EventNotification.S3Entity s3 = new S3EventNotification.S3Entity("configId", bucket, null, "3.3");
S3EventNotification.S3ObjectEntity object = new S3EventNotification.S3ObjectEntity("b21b84d653bb07b05b1e6b33684dc11b", 1305107, "b21b84d653bb07b05b1e6b33684dc11b", "0C0F6F405D6ED209E1");
S3EventNotification.S3Entity s3 = new S3EventNotification.S3Entity("configId", bucket, object, "3.3");
return new S3EventNotification.S3EventNotificationRecord(EVENT_SOURCE_REGION, S3_EVENT_NAME, S3_EVENT_SOURCE, null,
S3_EVENT_VERSION, null, responseElements, s3, null);
}
Expand Down Expand Up @@ -102,6 +103,8 @@ public void testBasicCall() {
assertThat(faas.getId()).isEqualTo(TestContext.FUNCTION_ARN);
assertThat(faas.getTrigger().getType()).isEqualTo("datasource");
assertThat(faas.getTrigger().getRequestId()).isEqualTo(S3_REQUEST_ID);

verifyOtelAttributes(transaction);
}

@Test
Expand Down Expand Up @@ -174,4 +177,12 @@ private void validateResultsForUnspecifiedRecord() {
assertThat(faas.getTrigger().getType()).isEqualTo("datasource");
assertThat(faas.getTrigger().getRequestId()).isNull();
}

private void verifyOtelAttributes(Transaction transaction) {
Object s3keyAttribute = transaction.getOtelAttributes().get("aws.s3.key");
assertThat(s3keyAttribute).isInstanceOf(String.class).isEqualTo("b21b84d653bb07b05b1e6b33684dc11b");

Object s3bucketAttribute = transaction.getOtelAttributes().get("aws.s3.bucket");
assertThat(s3bucketAttribute).isInstanceOf(String.class).isEqualTo(S3_BUCKET_NAME);
}
}
2 changes: 1 addition & 1 deletion apm-agent-plugins/apm-ecs-logging-plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.20.0</version>
<version>2.21.0</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
Expand Down
2 changes: 1 addition & 1 deletion apm-agent-plugins/apm-micrometer-plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-core</artifactId>
<version>1.11.4</version>
<version>1.11.5</version>
<scope>provided</scope>
</dependency>
<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@
</dependency>

<dependency>
<groupId>io.opentelemetry</groupId>
<groupId>io.opentelemetry.semconv</groupId>
<artifactId>opentelemetry-semconv</artifactId>
<version>${version.opentelemetry}-alpha</version>
<version>${version.opentelemetry-semconv}</version>
<scope>test</scope>
</dependency>

Expand Down
Loading

0 comments on commit d74e2fc

Please sign in to comment.