Skip to content
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 S3 Downstream Span Pointers #587

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

nhulston
Copy link
Contributor

@nhulston nhulston commented Nov 14, 2024

What does this PR do?

Tests will fail until my changes in DataDog/dd-trace-js#4875 are out.

Adds span pointers to spans for Lambdas triggered by putObject, copyObject, and completeMultipartUpload events.

Span pointers are similar to Span Links, but for cases when it is impossible to pass the Trace ID and Span ID between the spans that need to be linked.

When the calculated hashes for the upstream and downstream lambdas match, the Datadog backend will automatically link the two traces together.

Screenshot 2024-11-11 at 1 29 11 PM When clicking on the linked span, a new tab opens linking to the downstream Lambda function that was triggered by this S3 object update.

Motivation

This feature already exists in Python, and I'm working on adding it to all other runtimes (Node, .NET, Java, Golang).

Testing Guidelines

Run this Lambda function with the event payload

{
  "shouldPutObject": false,
  "shouldCopyObject": false,
  "shouldMultipartUpload": false,
  "useV2": true
}

and change one of the bools to true. Also, try both with AWS SDK v2 and v3. Enable the span pointers feature flag, and check Datadog to ensure that the spans are properly linked.

Additional Notes

  • This handles the 'downstream' case, for Lambdas that make S3 requests. This PR adds span pointers on the upstream case.
  • S3 and Dynamo are supported in Python. I will soon open another PR to add support for Dynamo.

Types of Changes

  • Bug fix
  • New feature
  • Breaking change
  • Misc (docs, refactoring, dependency upgrade, etc.)

Check all that apply

  • This PR's description is comprehensive
  • This PR contains breaking changes that are documented in the description
  • This PR introduces new APIs or parameters that are documented and unlikely to change in the foreseeable future
  • This PR impacts documentation, and it has been updated (or a ticket has been logged)
  • This PR's changes are covered by the automated tests
  • This PR collects user input/sensitive content into Datadog
  • This PR passes the integration tests (ask a Datadog member to run the tests)

* @param {any} event - The event object containing source-specific data.
* @returns {SpanPointerAttributes[] | undefined} An array of span pointer attribute objects, or undefined if none could be computed.
*/
export function getSpanPointerAttributes(eventSource: eventTypes | undefined, event: any): SpanPointerAttributes[] | undefined {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Quality Violation

Unexpected any. Specify a different type. (...read more)

Do not use the any type, as it is too broad and can lead to unexpected behavior.

View in Datadog  Leave us feedback  Documentation

}
}

function processS3Event(event: any): SpanPointerAttributes[] {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Quality Violation

Unexpected any. Specify a different type. (...read more)

Do not use the any type, as it is too broad and can lead to unexpected behavior.

View in Datadog  Leave us feedback  Documentation

@@ -323,9 +323,8 @@ function extractHTTPTags(event: APIGatewayEvent | APIGatewayProxyEventV2 | ALBEv
/**
* extractTriggerTags parses the trigger event object for tags to be added to the span metadata
*/
export function extractTriggerTags(event: any, context: Context) {
export function extractTriggerTags(event: any, context: Context, eventSource: eventTypes | undefined) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Quality Violation

Unexpected any. Specify a different type. (...read more)

Do not use the any type, as it is too broad and can lead to unexpected behavior.

View in Datadog  Leave us feedback  Documentation

@nhulston nhulston force-pushed the nicholas.hulston/s3-span-pointers branch from d0a666e to c8aa5a8 Compare November 14, 2024 17:45
*/
export function getSpanPointerAttributes(
eventSource: eventTypes | undefined,
event: any,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Quality Violation

Unexpected any. Specify a different type. (...read more)

Do not use the any type, as it is too broad and can lead to unexpected behavior.

View in Datadog  Leave us feedback  Documentation

@nhulston nhulston force-pushed the nicholas.hulston/s3-span-pointers branch from c8aa5a8 to a3b587b Compare November 14, 2024 17:55
@nhulston nhulston marked this pull request as ready for review November 14, 2024 18:46
@nhulston nhulston requested a review from a team as a code owner November 14, 2024 18:46
Copy link
Contributor

@apiarian-datadog apiarian-datadog left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the span pointer stuff looks fine, though some aspects of the api are a little strange. we may want someone with more js experience to take a look as well.


for (const record of records) {
const eventName = record.eventName;
if (!["ObjectCreated:Put", "ObjectCreated:Copy", "ObjectCreated:CompleteMultipartUpload"].includes(eventName)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why restrict us to only these particular object created types instead of ObjectCreated:*?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We only support creating span pointers for these three operations on the upstream case. I guess it doesn't hurt to create span pointers downstream in other cases; we could change the check to

if (!eventName.startsWith("ObjectCreated"))

src/utils/span-pointers.ts Outdated Show resolved Hide resolved
eventSource: eventTypes | undefined,
event: any,
): SpanPointerAttributes[] | undefined {
console.log('[LIBRARY] getSpanPointerAttributes(): ', eventSource)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 Code Quality Violation

Unexpected console statement. (...read more)

Debugging with console is not considered a bad practice, but it's easy to forget about console statements and leave them in production code. There is no need to pollute production builds with debugging statements.

View in Datadog  Leave us feedback  Documentation

this.stepFunctionContext = StepFunctionContextService.instance().context;

console.log('[LIBRARY] Getting span pointer attributes')

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 Code Quality Violation

Unexpected console statement. (...read more)

Debugging with console is not considered a bad practice, but it's easy to forget about console statements and leave them in production code. There is no need to pollute production builds with debugging statements.

View in Datadog  Leave us feedback  Documentation


if (this.wrappedCurrentSpan) {
for (const attributes of this.spanPointerAttributesList) {
console.log('[LIBRARY] Adding attributes:', attributes)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 Code Quality Violation

Unexpected console statement. (...read more)

Debugging with console is not considered a bad practice, but it's easy to forget about console statements and leave them in production code. There is no need to pollute production builds with debugging statements.

View in Datadog  Leave us feedback  Documentation


console.log('[LIBRARY] Getting span pointer attributes')
const result = getSpanPointerAttributes(eventSource, event);
console.log('[LIBRARY] result:', result)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 Code Quality Violation

Unexpected console statement. (...read more)

Debugging with console is not considered a bad practice, but it's easy to forget about console statements and leave them in production code. There is no need to pollute production builds with debugging statements.

View in Datadog  Leave us feedback  Documentation

@nhulston nhulston force-pushed the nicholas.hulston/s3-span-pointers branch from c9e623b to ea5594b Compare November 15, 2024 16:23
@nhulston nhulston marked this pull request as draft November 15, 2024 21:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants