-
Notifications
You must be signed in to change notification settings - Fork 293
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Data Streams support in AWS SQS without raw message delivery #8071
Changes from 3 commits
60d9bf8
fa94628
6f658fe
21c7767
e8d3d4e
af87d96
bde98d2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,8 +2,14 @@ | |
|
||
import com.amazonaws.services.sqs.model.Message; | ||
import com.amazonaws.services.sqs.model.MessageAttributeValue; | ||
import com.fasterxml.jackson.databind.JsonNode; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import datadog.trace.api.Config; | ||
import datadog.trace.bootstrap.instrumentation.api.AgentPropagation; | ||
import datadog.trace.bootstrap.instrumentation.messaging.DatadogAttributeParser; | ||
import java.io.IOException; | ||
import java.nio.ByteBuffer; | ||
import java.util.Base64; | ||
import java.util.Map; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
@@ -12,6 +18,8 @@ public final class MessageExtractAdapter implements AgentPropagation.ContextVisi | |
private static final Logger log = LoggerFactory.getLogger(MessageExtractAdapter.class); | ||
|
||
public static final MessageExtractAdapter GETTER = new MessageExtractAdapter(); | ||
public static final boolean SHOULD_EXTRACT_CONTEXT_FROM_BODY = | ||
Config.get().isSqsBodyPropagationEnabled(); | ||
|
||
@Override | ||
public void forEachKey(Message carrier, AgentPropagation.KeyClassifier classifier) { | ||
|
@@ -28,6 +36,33 @@ public void forEachKey(Message carrier, AgentPropagation.KeyClassifier classifie | |
} else if ("Binary".equals(datadog.getDataType())) { | ||
DatadogAttributeParser.forEachProperty(classifier, datadog.getBinaryValue()); | ||
} | ||
} else if (SHOULD_EXTRACT_CONTEXT_FROM_BODY) { | ||
try { | ||
this.forEachKeyInBody(carrier.getBody(), classifier); | ||
} catch (IOException e) { | ||
log.warn("Error extracting Datadog context from SQS message body", e); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is maybe too noisy in warn if it fails since it's for each message |
||
} | ||
} | ||
} | ||
|
||
public void forEachKeyInBody(String body, AgentPropagation.KeyClassifier classifier) | ||
throws IOException { | ||
ObjectMapper objectMapper = new ObjectMapper(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this should be statically created since it can be reused. Recently @PerfectSlayer also added (or he's adding) a json parser api you can access from the tracer instead using jackson even it should be fine for aws sdk There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Scratch that, the above PR was for producing JSON - the parsing piece isn't available yet There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, parsing is yet another topic... I haven’t seen a loot usage yet to justify implementing it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh cool, it would be useful here, since for SQS v2 doesn't have Jackson, so I'm not sure how to add the same support for v2. |
||
|
||
// Parse the JSON string into a JsonNode | ||
JsonNode rootNode = objectMapper.readTree(body); | ||
|
||
// Navigate to MessageAttributes._datadog | ||
JsonNode messageAttributes = rootNode.path("MessageAttributes").path("_datadog"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what if There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It returns an empty Note that if the message is not in a Json format, it throws an IOException that is caught by the caller of this method. So it also works. |
||
|
||
// Extract Value and Type | ||
String value = messageAttributes.path("Value").asText(); | ||
String type = messageAttributes.path("Type").asText(); | ||
if ("String".equals(type)) { | ||
DatadogAttributeParser.forEachProperty(classifier, value); | ||
} else if ("Binary".equals(type)) { | ||
ByteBuffer decodedValue = ByteBuffer.wrap(Base64.getDecoder().decode(value)); | ||
DatadogAttributeParser.forEachProperty(classifier, decodedValue); | ||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -159,5 +159,7 @@ public final class TraceInstrumentationConfig { | |
/** If set, the instrumentation will set its resource name on the local root too. */ | ||
public static final String AXIS_PROMOTE_RESOURCE_NAME = "trace.axis.promote.resource-name"; | ||
|
||
public static final String SQS_BODY_PROPAGATION_ENABLED = "sqs.body.propagation.enabled"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would have prefixed by |
||
|
||
private TraceInstrumentationConfig() {} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would have widen to
Throwable
just in case