in aws-xray-recorder-sdk-core/src/main/java/com/amazonaws/xray/contexts/LambdaSegmentContext.java [52:114]
public Subsegment beginSubsegment(AWSXRayRecorder recorder, String name) {
if (logger.isDebugEnabled()) {
logger.debug("Beginning subsegment named: " + name);
}
TraceHeader traceHeader = LambdaSegmentContext.getTraceHeaderFromEnvironment();
Entity entity = getTraceEntity();
if (entity == null) { // First subsegment of a subsegment branch
Segment parentSegment;
// Trace header either takes the structure `Root=...;<extra-data>` or
// `Root=...;Parent=...;Sampled=...;<extra-data>`
if (traceHeader.getRootTraceId() != null && traceHeader.getParentId() != null && traceHeader.getSampled() != null) {
parentSegment = new FacadeSegment(
recorder,
traceHeader.getRootTraceId(),
traceHeader.getParentId(),
traceHeader.getSampled());
} else {
if (logger.isDebugEnabled()) {
logger.debug("Creating No-Op parent segment");
}
TraceID t = traceHeader.getRootTraceId() != null ? traceHeader.getRootTraceId() : TraceID.create(recorder);
parentSegment = Segment.noOp(t, recorder);
}
boolean isRecording = parentSegment.isRecording();
Subsegment subsegment = isRecording
? new SubsegmentImpl(recorder, name, parentSegment)
: Subsegment.noOp(parentSegment, recorder);
subsegment.setParent(parentSegment);
// Enable FacadeSegment to keep track of its subsegments for subtree streaming
parentSegment.addSubsegment(subsegment);
setTraceEntity(subsegment);
return subsegment;
} else { // Continuation of a subsegment branch.
Subsegment parentSubsegment = (Subsegment) entity;
// Ensure customers have not leaked subsegments across invocations
TraceID environmentRootTraceId = LambdaSegmentContext.getTraceHeaderFromEnvironment().getRootTraceId();
if (environmentRootTraceId != null &&
!environmentRootTraceId.equals(parentSubsegment.getParentSegment().getTraceId())) {
clearTraceEntity();
return beginSubsegment(recorder, name);
}
Segment parentSegment = parentSubsegment.getParentSegment();
boolean isRecording = parentSubsegment.isRecording();
Subsegment subsegment = isRecording
? new SubsegmentImpl(recorder, name, parentSegment)
: Subsegment.noOp(parentSegment, recorder, name);
subsegment.setParent(parentSubsegment);
parentSubsegment.addSubsegment(subsegment);
setTraceEntity(subsegment);
List<SegmentListener> segmentListeners = recorder.getSegmentListeners();
segmentListeners.stream()
.filter(Objects::nonNull)
.forEach(listener -> listener.onBeginSubsegment(subsegment));
return subsegment;
}
}