-
Notifications
You must be signed in to change notification settings - Fork 48
Propagate trace context from SQS events #142
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
Changes from all commits
9487275
c1ebc7e
0571851
5208df0
e2fe7e3
fe1f2f0
c531b66
b5e9c50
e44935f
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 |
|---|---|---|
|
|
@@ -17,6 +17,7 @@ import ( | |
| "strconv" | ||
| "strings" | ||
|
|
||
| "github.com/DataDog/datadog-lambda-go/internal/extension" | ||
| "github.com/DataDog/datadog-lambda-go/internal/logger" | ||
| "github.com/aws/aws-xray-sdk-go/header" | ||
| "github.com/aws/aws-xray-sdk-go/xray" | ||
|
|
@@ -47,7 +48,7 @@ var DefaultTraceExtractor = getHeadersFromEventHeaders | |
| // contextWithRootTraceContext uses the incoming event and context object payloads to determine | ||
| // the root TraceContext and then adds that TraceContext to the context object. | ||
| func contextWithRootTraceContext(ctx context.Context, ev json.RawMessage, mergeXrayTraces bool, extractor ContextExtractor) (context.Context, error) { | ||
| datadogTraceContext, gotDatadogTraceContext := getTraceContext(extractor(ctx, ev)) | ||
| datadogTraceContext, gotDatadogTraceContext := getTraceContext(ctx, extractor(ctx, ev)) | ||
|
|
||
| xrayTraceContext, errGettingXrayContext := convertXrayTraceContextFromLambdaContext(ctx) | ||
| if errGettingXrayContext != nil { | ||
|
|
@@ -126,21 +127,36 @@ func createDummySubsegmentForXrayConverter(ctx context.Context, traceCtx TraceCo | |
| return nil | ||
| } | ||
|
|
||
| func getTraceContext(context map[string]string) (TraceContext, bool) { | ||
| func getTraceContext(ctx context.Context, headers map[string]string) (TraceContext, bool) { | ||
|
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. When the extension is in charge of parsing for trace context, it is included in the response from calling start invocation. It is then added to the context object. If present, it therefore should be read in case there is no trace context found in the event payload headers. 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. by event payload headers, you mean the actual event that triggered the go lambda right? and So to be sure we extract and attach context we do check both ways. 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. That is exactly correct. Reading the "event payload headers" is hold over from before we added universal instrumentation. We could potentially get rid of it completely and just rely on the extension to do this work for us. |
||
| tc := TraceContext{} | ||
|
|
||
| traceID, ok := context[traceIDHeader] | ||
| if !ok { | ||
| traceID := headers[traceIDHeader] | ||
| if traceID == "" { | ||
| if val, ok := ctx.Value(extension.DdTraceId).(string); ok { | ||
| traceID = val | ||
| } | ||
| } | ||
| if traceID == "" { | ||
| return tc, false | ||
| } | ||
|
|
||
| parentID, ok := context[parentIDHeader] | ||
| if !ok { | ||
| parentID := headers[parentIDHeader] | ||
| if parentID == "" { | ||
| if val, ok := ctx.Value(extension.DdParentId).(string); ok { | ||
| parentID = val | ||
| } | ||
| } | ||
| if parentID == "" { | ||
| return tc, false | ||
| } | ||
|
|
||
| samplingPriority, ok := context[samplingPriorityHeader] | ||
| if !ok { | ||
| samplingPriority := headers[samplingPriorityHeader] | ||
| if samplingPriority == "" { | ||
| if val, ok := ctx.Value(extension.DdSamplingPriority).(string); ok { | ||
| samplingPriority = val | ||
| } | ||
| } | ||
| if samplingPriority == "" { | ||
| samplingPriority = "1" //sampler-keep | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
|
|
@@ -64,6 +64,10 @@ func (l *Listener) HandlerStarted(ctx context.Context, msg json.RawMessage) cont | |||
| return ctx | ||||
| } | ||||
|
|
||||
| if l.universalInstrumentation && l.extensionManager.IsExtensionRunning() { | ||||
| ctx = l.extensionManager.SendStartInvocationRequest(ctx, msg) | ||||
|
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. Calling |
||||
| } | ||||
|
|
||||
| ctx, _ = contextWithRootTraceContext(ctx, msg, l.mergeXrayTraces, l.traceContextExtractor) | ||||
|
|
||||
| if !tracerInitialized { | ||||
|
|
@@ -77,15 +81,11 @@ func (l *Listener) HandlerStarted(ctx context.Context, msg json.RawMessage) cont | |||
| } | ||||
|
|
||||
| isDdServerlessSpan := l.universalInstrumentation && l.extensionManager.IsExtensionRunning() | ||||
| functionExecutionSpan = startFunctionExecutionSpan(ctx, l.mergeXrayTraces, isDdServerlessSpan) | ||||
| functionExecutionSpan, ctx = startFunctionExecutionSpan(ctx, l.mergeXrayTraces, isDdServerlessSpan) | ||||
|
|
||||
| // Add the span to the context so the user can create child spans | ||||
| ctx = tracer.ContextWithSpan(ctx, functionExecutionSpan) | ||||
|
|
||||
| if l.universalInstrumentation && l.extensionManager.IsExtensionRunning() { | ||||
| ctx = l.extensionManager.SendStartInvocationRequest(ctx, msg) | ||||
| } | ||||
|
|
||||
| return ctx | ||||
| } | ||||
|
|
||||
|
|
@@ -104,7 +104,7 @@ func (l *Listener) HandlerFinished(ctx context.Context, err error) { | |||
|
|
||||
| // startFunctionExecutionSpan starts a span that represents the current Lambda function execution | ||||
| // and returns the span so that it can be finished when the function execution is complete | ||||
| func startFunctionExecutionSpan(ctx context.Context, mergeXrayTraces bool, isDdServerlessSpan bool) tracer.Span { | ||||
| func startFunctionExecutionSpan(ctx context.Context, mergeXrayTraces bool, isDdServerlessSpan bool) (tracer.Span, context.Context) { | ||||
| // Extract information from context | ||||
| lambdaCtx, _ := lambdacontext.FromContext(ctx) | ||||
| rootTraceContext, ok := ctx.Value(traceContextKey).(TraceContext) | ||||
|
|
@@ -149,7 +149,9 @@ func startFunctionExecutionSpan(ctx context.Context, mergeXrayTraces bool, isDdS | |||
| span.SetTag("_dd.parent_source", "xray") | ||||
| } | ||||
|
|
||||
| return span | ||||
| ctx = context.WithValue(ctx, extension.DdSpanId, fmt.Sprint(span.Context().SpanID())) | ||||
|
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. Add the span id to the context for use later when calling end invocation on the extension. (see
The extension uses this span id to replace the span id of the 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. as a sanity check, that SpanID gets replaced here https://github.com/DataDog/datadog-agent/blob/570ed026d8dc3afc4324610db8f922027f8786ca/pkg/serverless/invocationlifecycle/trace.go#L110-L111? 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. Exactly right. You'll notice that the tracer and the extension are creating We do it this way because we want to make sure the tracer has access to the |
||||
|
|
||||
| return span, ctx | ||||
| } | ||||
|
|
||||
| func separateVersionFromFunctionArn(functionArn string) (arnWithoutVersion string, functionVersion string) { | ||||
|
|
||||
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.
If the parent id is not set, later on we will throw out the found trace context completely.