Skip to content

Commit

Permalink
aws-lambda: add stable semconv (#9355)
Browse files Browse the repository at this point in the history
  • Loading branch information
laurit authored Aug 31, 2023
1 parent 30cd005 commit 103224c
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
import io.opentelemetry.instrumentation.awslambdaevents.v2_2.internal.AwsLambdaEventsInstrumenterFactory;
import io.opentelemetry.instrumentation.awslambdaevents.v2_2.internal.AwsLambdaSqsInstrumenterFactory;
import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig;

public final class AwsLambdaInstrumentationHelper {

private static final io.opentelemetry.instrumentation.awslambdacore.v1_0.internal
.AwsLambdaFunctionInstrumenter
FUNCTION_INSTRUMENTER =
AwsLambdaEventsInstrumenterFactory.createInstrumenter(GlobalOpenTelemetry.get());
AwsLambdaEventsInstrumenterFactory.createInstrumenter(
GlobalOpenTelemetry.get(), CommonConfig.get().getKnownHttpRequestMethods());

public static io.opentelemetry.instrumentation.awslambdacore.v1_0.internal
.AwsLambdaFunctionInstrumenter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.opentelemetry.instrumentation.api.internal.HttpConstants;
import io.opentelemetry.instrumentation.awslambdacore.v1_0.TracingRequestHandler;
import io.opentelemetry.instrumentation.awslambdacore.v1_0.internal.MapUtils;
import io.opentelemetry.instrumentation.awslambdacore.v1_0.internal.WrappedLambda;
Expand Down Expand Up @@ -51,7 +52,8 @@ protected TracingRequestWrapperBase(BiFunction<I, Class<?>, Object> parameterMap
super(
openTelemetrySdk,
WrapperConfiguration.flushTimeout(),
AwsLambdaEventsInstrumenterFactory.createInstrumenter(openTelemetrySdk));
AwsLambdaEventsInstrumenterFactory.createInstrumenter(
openTelemetrySdk, HttpConstants.KNOWN_METHODS));
this.wrappedLambda = wrappedLambda;
this.targetMethod = wrappedLambda.getRequestTargetMethod();
this.parameterMapper = parameterMapper;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,40 @@

package io.opentelemetry.instrumentation.awslambdaevents.v2_2.internal;

import static io.opentelemetry.instrumentation.api.internal.AttributesExtractorUtil.internalSet;
import static io.opentelemetry.instrumentation.api.internal.HttpConstants._OTHER;
import static io.opentelemetry.instrumentation.awslambdacore.v1_0.internal.MapUtils.emptyIfNull;
import static io.opentelemetry.instrumentation.awslambdacore.v1_0.internal.MapUtils.lowercaseMap;
import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.FAAS_TRIGGER;
import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.HTTP_METHOD;
import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.HTTP_STATUS_CODE;
import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.HTTP_URL;
import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.USER_AGENT_ORIGINAL;

import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
import io.opentelemetry.api.common.AttributesBuilder;
import io.opentelemetry.context.Context;
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
import io.opentelemetry.instrumentation.api.instrumenter.http.internal.HttpAttributes;
import io.opentelemetry.instrumentation.api.instrumenter.url.internal.UrlAttributes;
import io.opentelemetry.instrumentation.api.internal.SemconvStability;
import io.opentelemetry.instrumentation.awslambdacore.v1_0.AwsLambdaRequest;
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;

final class ApiGatewayProxyAttributesExtractor
implements AttributesExtractor<AwsLambdaRequest, Object> {

private final Set<String> knownMethods;

ApiGatewayProxyAttributesExtractor(Set<String> knownMethods) {
this.knownMethods = knownMethods;
}

@Override
public void onStart(
AttributesBuilder attributes, Context parentContext, AwsLambdaRequest request) {
Expand All @@ -38,16 +49,34 @@ public void onStart(
}

void onRequest(AttributesBuilder attributes, APIGatewayProxyRequestEvent request) {
attributes.put(HTTP_METHOD, request.getHttpMethod());
String method = request.getHttpMethod();
if (SemconvStability.emitStableHttpSemconv()) {
if (method == null || knownMethods.contains(method)) {
internalSet(attributes, HttpAttributes.HTTP_REQUEST_METHOD, method);
} else {
internalSet(attributes, HttpAttributes.HTTP_REQUEST_METHOD, _OTHER);
internalSet(attributes, HttpAttributes.HTTP_REQUEST_METHOD_ORIGINAL, method);
}
}
if (SemconvStability.emitOldHttpSemconv()) {
internalSet(attributes, SemanticAttributes.HTTP_METHOD, method);
}

Map<String, String> headers = lowercaseMap(request.getHeaders());
String userAgent = headers.get("user-agent");
if (userAgent != null) {
attributes.put(USER_AGENT_ORIGINAL, userAgent);
}

String httpUrl = getHttpUrl(request, headers);
if (httpUrl != null) {
attributes.put(HTTP_URL, httpUrl);
if (SemconvStability.emitStableHttpSemconv()) {
internalSet(attributes, UrlAttributes.URL_FULL, httpUrl);
}

if (SemconvStability.emitOldHttpSemconv()) {
internalSet(attributes, SemanticAttributes.HTTP_URL, httpUrl);
}
}
}

Expand Down Expand Up @@ -97,6 +126,4 @@ public void onEnd(
}
}
}

ApiGatewayProxyAttributesExtractor() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,24 @@
import io.opentelemetry.instrumentation.awslambdacore.v1_0.AwsLambdaRequest;
import io.opentelemetry.instrumentation.awslambdacore.v1_0.internal.AwsLambdaFunctionAttributesExtractor;
import io.opentelemetry.instrumentation.awslambdacore.v1_0.internal.AwsLambdaFunctionInstrumenter;
import java.util.Set;

/**
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
* any time.
*/
public final class AwsLambdaEventsInstrumenterFactory {

public static AwsLambdaFunctionInstrumenter createInstrumenter(OpenTelemetry openTelemetry) {
public static AwsLambdaFunctionInstrumenter createInstrumenter(
OpenTelemetry openTelemetry, Set<String> knownMethods) {
return new AwsLambdaFunctionInstrumenter(
openTelemetry,
Instrumenter.builder(
openTelemetry,
"io.opentelemetry.aws-lambda-events-2.2",
AwsLambdaEventsInstrumenterFactory::spanName)
.addAttributesExtractor(new AwsLambdaFunctionAttributesExtractor())
.addAttributesExtractor(new ApiGatewayProxyAttributesExtractor())
.addAttributesExtractor(new ApiGatewayProxyAttributesExtractor(knownMethods))
.buildInstrumenter(SpanKindExtractor.alwaysServer()));
}

Expand Down

0 comments on commit 103224c

Please sign in to comment.