Skip to content

Commit d072864

Browse files
feat(tracing): ability to override object mapper (#698)
* feat(tracing): ability to override object mapper used for serialization * chore(tracing): fix static code warnings * docs(tracing): ability to override object mapper used for serialization
1 parent 760b663 commit d072864

File tree

6 files changed

+225
-9
lines changed

6 files changed

+225
-9
lines changed

docs/core/tracing.md

+32
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,38 @@ context for an operation using any native object.
164164
}
165165
```
166166

167+
## Override default object mapper
168+
169+
You can optionally choose to override default object mapper which is used to serialize method response and exceptions when enabled. You might
170+
want to supply custom object mapper in order to control how serialisation is done, for example, when you want to log only
171+
specific fields from received event due to security.
172+
173+
=== "App.java"
174+
175+
```java hl_lines="10-14"
176+
import software.amazon.lambda.powertools.tracing.Tracing;
177+
import software.amazon.lambda.powertools.tracing.TracingUtils;
178+
import static software.amazon.lambda.powertools.tracing.CaptureMode.RESPONSE;
179+
180+
/**
181+
* Handler for requests to Lambda function.
182+
*/
183+
public class App implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
184+
static {
185+
ObjectMapper objectMapper = new ObjectMapper();
186+
SimpleModule simpleModule = new SimpleModule();
187+
objectMapper.registerModule(simpleModule);
188+
189+
TracingUtils.defaultObjectMapper(objectMapper);
190+
}
191+
192+
@Tracing(captureMode = RESPONSE)
193+
public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) {
194+
...
195+
}
196+
}
197+
```
198+
167199
## Utilities
168200

169201
Tracing modules comes with certain utility method when you don't want to use annotation for capturing a code block

powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/TracingUtils.java

+17-2
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@
1313
*/
1414
package software.amazon.lambda.powertools.tracing;
1515

16+
import java.util.function.Consumer;
1617
import com.amazonaws.xray.AWSXRay;
1718
import com.amazonaws.xray.entities.Entity;
1819
import com.amazonaws.xray.entities.Subsegment;
19-
20-
import java.util.function.Consumer;
20+
import com.fasterxml.jackson.databind.ObjectMapper;
2121

2222
import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.serviceName;
2323

@@ -27,6 +27,7 @@
2727
*
2828
*/
2929
public final class TracingUtils {
30+
private static ObjectMapper objectMapper;
3031

3132
/**
3233
* Put an annotation to the current subsegment with a String value.
@@ -155,4 +156,18 @@ public static void withSubsegment(String namespace, String name, Consumer<Subseg
155156
AWSXRay.endSubsegment();
156157
}
157158
}
159+
160+
/**
161+
* Sets the instance of ObjectMapper object which is used for serialising object response when
162+
* {@code @Tracing(captureMode=CaptureMode.RESPONSE)}.
163+
*
164+
* @param objectMapper Custom implementation of object mapper to be used for serializing response
165+
*/
166+
public static void defaultObjectMapper(ObjectMapper objectMapper) {
167+
TracingUtils.objectMapper = objectMapper;
168+
}
169+
170+
public static ObjectMapper objectMapper() {
171+
return objectMapper;
172+
}
158173
}

powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/internal/LambdaTracingAspect.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
package software.amazon.lambda.powertools.tracing.internal;
1515

1616
import java.util.function.Supplier;
17-
1817
import com.amazonaws.xray.AWSXRay;
1918
import com.amazonaws.xray.entities.Subsegment;
2019
import org.aspectj.lang.ProceedingJoinPoint;
@@ -30,6 +29,7 @@
3029
import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.placedOnRequestHandler;
3130
import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.placedOnStreamHandler;
3231
import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.serviceName;
32+
import static software.amazon.lambda.powertools.tracing.TracingUtils.objectMapper;
3333

3434
@Aspect
3535
public final class LambdaTracingAspect {
@@ -59,7 +59,7 @@ public Object around(ProceedingJoinPoint pjp,
5959
try {
6060
Object methodReturn = pjp.proceed(proceedArgs);
6161
if (captureResponse) {
62-
segment.putMetadata(namespace(tracing), pjp.getSignature().getName() + " response", methodReturn);
62+
segment.putMetadata(namespace(tracing), pjp.getSignature().getName() + " response", null != objectMapper() ? objectMapper().writeValueAsString(methodReturn): methodReturn);
6363
}
6464

6565
if (placedOnHandlerMethod(pjp)) {
@@ -69,7 +69,7 @@ public Object around(ProceedingJoinPoint pjp,
6969
return methodReturn;
7070
} catch (Exception e) {
7171
if (captureError) {
72-
segment.putMetadata(namespace(tracing), pjp.getSignature().getName() + " error", e);
72+
segment.putMetadata(namespace(tracing), pjp.getSignature().getName() + " error", null != objectMapper() ? objectMapper().writeValueAsString(e) : e);
7373
}
7474
throw e;
7575
} finally {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
* Copyright 2020 Amazon.com, Inc. or its affiliates.
3+
* Licensed under the Apache License, Version 2.0 (the
4+
* "License"); you may not use this file except in compliance
5+
* with the License. You may obtain a copy of the License at
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
* Unless required by applicable law or agreed to in writing, software
8+
* distributed under the License is distributed on an "AS IS" BASIS,
9+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
* See the License for the specific language governing permissions and
11+
* limitations under the License.
12+
*
13+
*/
14+
package software.amazon.lambda.powertools.tracing.handlers;
15+
16+
import java.io.IOException;
17+
import com.amazonaws.services.lambda.runtime.Context;
18+
import com.amazonaws.services.lambda.runtime.RequestHandler;
19+
import com.fasterxml.jackson.core.JsonGenerator;
20+
import com.fasterxml.jackson.databind.ObjectMapper;
21+
import com.fasterxml.jackson.databind.SerializerProvider;
22+
import com.fasterxml.jackson.databind.module.SimpleModule;
23+
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
24+
import software.amazon.lambda.powertools.tracing.Tracing;
25+
import software.amazon.lambda.powertools.tracing.TracingUtils;
26+
27+
import static software.amazon.lambda.powertools.tracing.CaptureMode.RESPONSE;
28+
29+
public class PowerTracerToolEnabledForResponseWithCustomMapper implements RequestHandler<Object, Object> {
30+
static {
31+
ObjectMapper objectMapper = new ObjectMapper();
32+
SimpleModule simpleModule = new SimpleModule();
33+
simpleModule.addSerializer(ChildClass.class, new ChildSerializer());
34+
objectMapper.registerModule(simpleModule);
35+
36+
TracingUtils.defaultObjectMapper(objectMapper);
37+
}
38+
@Override
39+
@Tracing(namespace = "lambdaHandler", captureMode = RESPONSE)
40+
public Object handleRequest(Object input, Context context) {
41+
ParentClass parentClass = new ParentClass("parent");
42+
ChildClass childClass = new ChildClass("child", parentClass);
43+
parentClass.setC(childClass);
44+
return parentClass;
45+
}
46+
47+
public class ParentClass {
48+
public String name;
49+
public ChildClass c;
50+
51+
public ParentClass(String name) {
52+
this.name = name;
53+
}
54+
55+
public void setC(ChildClass c) {
56+
this.c = c;
57+
}
58+
}
59+
60+
public class ChildClass {
61+
public String name;
62+
public ParentClass p;
63+
64+
public ChildClass(String name, ParentClass p) {
65+
this.name = name;
66+
this.p = p;
67+
}
68+
}
69+
70+
public static class ChildSerializer extends StdSerializer<ChildClass> {
71+
72+
public ChildSerializer() {
73+
this(null);
74+
}
75+
76+
public ChildSerializer(Class<ChildClass> t) {
77+
super(t);
78+
}
79+
80+
@Override
81+
public void serialize(ChildClass value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
82+
jgen.writeStartObject();
83+
jgen.writeStringField("name", value.name);
84+
jgen.writeStringField("p", value.p.name);
85+
jgen.writeEndObject();
86+
}
87+
}
88+
}

0 commit comments

Comments
 (0)