Here are the examples of the java api com.amazonaws.xray.AWSXRayRecorder taken from open source projects. By voting up you can indicate which examples are most useful and appropriate.
62 Examples
19
Source : AWSXRayTestParent.java
with Apache License 2.0
from opentracing-contrib
with Apache License 2.0
from opentracing-contrib
/**
* @author [email protected]
*/
abstract clreplaced AWSXRayTestParent {
final AWSXRayRecorder awsxRayRecorder = AWSXRayRecorderBuilder.defaultRecorder();
/**
* Make sure this reference stays as pure {@link Tracer} since we don't
* want to rely on implementation-specific details or return types.
*/
final Tracer tracer = new AWSXRayTracer(awsxRayRecorder);
/**
* A sample {@link com.amazonaws.xray.enreplacedies.TraceHeader} value to use
* for testing. NB we use all parts (root, parent, sampling decision) to
* ensure that they all get propagated correctly.
*/
final TraceHeader traceHeader = new TraceHeader(new TraceID(), "0f15eadda7879f1d", TraceHeader.SampleDecision.SAMPLED);
/**
* @param operationName the operation name
*/
AWSXRaySpan mockSpan(String operationName) {
return new AWSXRaySpan(new SegmentImpl(awsxRayRecorder, operationName), new AWSXRaySpanContext(Collections.emptyMap()));
}
}
19
Source : AWSXRaySpanBuilderTests.java
with Apache License 2.0
from opentracing-contrib
with Apache License 2.0
from opentracing-contrib
/**
* @author [email protected]
*/
clreplaced AWSXRaySpanBuilderTests extends AWSXRayTestParent {
private final AWSXRayRecorder recorder = AWSXRayRecorderBuilder.defaultRecorder();
private final AWSXRayTracer tracer = new AWSXRayTracer(recorder);
@Test
@DisplayName("set span name")
void setSpanName() {
final Span span = tracer.buildSpan("test-span-name").start();
replacedertEquals("test-span-name", ((AWSXRaySpan) span).getEnreplacedy().getName());
}
@Test
@DisplayName("set active span")
void setActiveSpan() {
final Scope activeScope = tracer.buildSpan("test-active-span").startActive(true);
replacedertEquals(activeScope.span(), tracer.activeSpan());
activeScope.close();
}
@Test
@DisplayName("set trace header in baggage")
void setTraceHeaderInBaggage() {
final Scope activeScope = tracer.buildSpan("test-trace-header").startActive(true);
final String activeTraceHeader = activeScope.span().getBaggageItem(TraceHeader.HEADER_KEY);
replacedertNotNull(activeTraceHeader);
replacedertTrue(activeTraceHeader.contains(((AWSXRaySpan) activeScope.span()).getEnreplacedy().getTraceId().toString()));
activeScope.close();
}
@Test
@DisplayName("set implicit active span as parent")
void setImplicitParentSpan() {
final Scope parentScope = tracer.buildSpan("parent-span").startActive(true);
final Scope childScope = tracer.buildSpan("child-span").startActive(true);
final Enreplacedy parentEnreplacedy = ((AWSXRayScope) parentScope).span().getEnreplacedy();
final Enreplacedy childEnreplacedy = ((AWSXRayScope) childScope).span().getEnreplacedy();
replacedertFalse(parentEnreplacedy.getSubsegments().isEmpty());
replacedertEquals(parentEnreplacedy, childEnreplacedy.getParent());
replacedertEquals(parentEnreplacedy.getTraceId(), childEnreplacedy.getParent().getTraceId());
// Check that trace header is correctly set in the child
final String childTraceHeader = childScope.span().getBaggageItem(TraceHeader.HEADER_KEY);
replacedertNotNull(childTraceHeader);
replacedertTrue(childTraceHeader.contains(parentEnreplacedy.getTraceId().toString()));
replacedertTrue(childTraceHeader.contains(parentEnreplacedy.getId()));
childScope.close();
parentScope.close();
}
@Test
@DisplayName("set explicit span as parent")
void setExplicitParentSpan() {
// NB we *don't* startActive here - replacedume this Span
// object came from somewhere else in the code
final AWSXRaySpan explicitParentSpan = mockSpan("explicit-parent-span");
// This implicit parent should be ignored by SpanBuilder
// when we set the explicit parent
final Scope implicitParentScope = tracer.buildSpan("implicit-parent-span").startActive(true);
final Scope childScope = tracer.buildSpan("child-span").asChildOf(explicitParentSpan).startActive(true);
final Enreplacedy explicitParentEnreplacedy = explicitParentSpan.getEnreplacedy();
final Enreplacedy implicitParentEnreplacedy = ((AWSXRayScope) implicitParentScope).span().getEnreplacedy();
final Enreplacedy childEnreplacedy = ((AWSXRayScope) childScope).span().getEnreplacedy();
replacedertFalse(explicitParentEnreplacedy.getSubsegments().isEmpty());
replacedertTrue(implicitParentEnreplacedy.getSubsegments().isEmpty());
replacedertEquals(explicitParentEnreplacedy, childEnreplacedy.getParent());
replacedertNotEquals(explicitParentEnreplacedy.getId(), childEnreplacedy.getId());
// Check that trace header is correctly set in the child
final String childTraceHeader = childScope.span().getBaggageItem(TraceHeader.HEADER_KEY);
replacedertNotNull(childTraceHeader);
replacedertTrue(childTraceHeader.contains(explicitParentEnreplacedy.getTraceId().toString()));
replacedertTrue(childTraceHeader.contains(explicitParentEnreplacedy.getId()));
childScope.close();
implicitParentScope.close();
}
@Test
@DisplayName("set explicit span as parent from remote server")
void setExplicitParentSpanFromRemote() {
// SpanContext can be preplaceded to remote servers using inject() and
// extract(), so replacedume we read this in from e.g. HTTP headers
final SpanContext remoteContext = new AWSXRaySpanContext(Collections.singletonMap(TraceHeader.HEADER_KEY, traceHeader.toString()));
final Scope childScope = tracer.buildSpan("child-span").asChildOf(remoteContext).startActive(true);
final Enreplacedy childEnreplacedy = ((AWSXRayScope) childScope).span().getEnreplacedy();
replacedertEquals(childEnreplacedy.getParentSegment().getTraceId(), traceHeader.getRootTraceId());
replacedertEquals(childEnreplacedy.getParentSegment().getId(), traceHeader.getParentId());
// Check that trace header is correctly set in the child
final String childTraceHeader = childScope.span().getBaggageItem(TraceHeader.HEADER_KEY);
replacedertNotNull(childTraceHeader);
childScope.close();
}
@Test
@DisplayName("ignore implicit active span on ignoreActiveSpan")
void ignoreImplicitParentSpan() {
final Scope parentScope = tracer.buildSpan("parent-span").startActive(true);
final Scope childScope = tracer.buildSpan("child-span").ignoreActiveSpan().startActive(true);
final Enreplacedy parentEnreplacedy = ((AWSXRayScope) parentScope).span().getEnreplacedy();
final Enreplacedy childEnreplacedy = ((AWSXRayScope) childScope).span().getEnreplacedy();
replacedertTrue(parentEnreplacedy.getSubsegments().isEmpty());
replacedertNull(childEnreplacedy.getParent());
replacedertNotEquals(parentEnreplacedy.getParentSegment().getTraceId(), childEnreplacedy.getParentSegment().getTraceId());
// Check that trace header is correctly set in the child
final String childTraceHeader = childScope.span().getBaggageItem(TraceHeader.HEADER_KEY);
replacedertNotNull(childTraceHeader);
replacedertTrue(childTraceHeader.contains(childEnreplacedy.getParentSegment().getTraceId().toString()));
replacedertFalse(childTraceHeader.contains(parentEnreplacedy.getParentSegment().getTraceId().toString()));
replacedertFalse(childTraceHeader.contains(parentEnreplacedy.getId()));
childScope.close();
parentScope.close();
}
/**
* In systems where the surrounding code is using X-Ray directly, but
* not the OpenTracing API, we should detect if a trace is already in
* progress. For example, in AWS Lambda functions, the lambda server
* creates a top-level trace segment for the whole function call
*
* @see <a href="https://docs.aws.amazon.com/xray/latest/devguide/xray-services-lambda.html">https://docs.aws.amazon.com/xray/latest/devguide/xray-services-lambda.html</a>
*/
@Test
@DisplayName("detect a pre-existing X-Ray trace")
void detectPreExisting() {
final Segment parentEnreplacedy = awsxRayRecorder.beginSegment("pre-existing-trace");
final Scope childScope = tracer.buildSpan("child-of-pre-existing-trace").startActive(true);
final Enreplacedy childEnreplacedy = ((AWSXRayScope) childScope).span().getEnreplacedy();
replacedertFalse(parentEnreplacedy.getSubsegments().isEmpty());
replacedertEquals(parentEnreplacedy, childEnreplacedy.getParent());
// Check that trace header is correctly set in the child
final String childTraceHeader = childScope.span().getBaggageItem(TraceHeader.HEADER_KEY);
replacedertNotNull(childTraceHeader);
replacedertTrue(childTraceHeader.contains(parentEnreplacedy.getTraceId().toString()));
replacedertTrue(childTraceHeader.contains(parentEnreplacedy.getId()));
childScope.close();
}
@Test
@DisplayName("set tags correctly")
@SuppressWarnings("unchecked")
void setTags() {
final Scope scope = tracer.buildSpan("test-set-tags").withTag("http.request.method", "POST").withTag("http.response.status_code", 503).withTag("fault", true).startActive(true);
final Enreplacedy enreplacedy = ((AWSXRayScope) scope).span().getEnreplacedy();
replacedertEquals("POST", ((Map<String, Object>) enreplacedy.getHttp().get("request")).get("method"));
replacedertEquals(503, ((Map<String, Object>) enreplacedy.getHttp().get("response")).get("status_code"));
replacedertTrue(enreplacedy.isFault());
scope.close();
}
@Test
@DisplayName("set start timestamp correctly")
void setStartTimestamp() {
final Scope scope = tracer.buildSpan("test-set-start-timestamp").withStartTimestamp(1551016321000000L).startActive(true);
final Enreplacedy enreplacedy = ((AWSXRayScope) scope).span().getEnreplacedy();
replacedertEquals(1551016321.0, enreplacedy.getStartTime());
scope.close();
}
}
19
Source : AWSXRayTracer.java
with Apache License 2.0
from opentracing-contrib
with Apache License 2.0
from opentracing-contrib
/**
* Top-level OpenTracing {@link Tracer} implementation which is backed
* by the AWS X-Ray client libraries.
*
* @see <a href="https://opentracing.io">https://opentracing.io</a>
* @see <a href="https://docs.aws.amazon.com/xray/latest/devguide/aws-xray.html">https://docs.aws.amazon.com/xray/latest/devguide/aws-xray.html</a>
* @author [email protected]
*/
@SuppressWarnings("WeakerAccess")
public clreplaced AWSXRayTracer implements Tracer {
private static final Logger log = LoggerFactory.getLogger(AWSXRayTracer.clreplaced);
private final AWSXRayRecorder xRayRecorder;
private final AWSXRayScopeManager scopeManager;
public AWSXRayTracer(AWSXRayRecorder xRayRecorder) {
this.xRayRecorder = xRayRecorder;
this.scopeManager = new AWSXRayScopeManager(xRayRecorder);
}
@Override
public ScopeManager scopeManager() {
return scopeManager;
}
@Override
public Span activeSpan() {
return scopeManager.activeSpan();
}
@Override
public SpanBuilder buildSpan(String operationName) {
return new AWSXRaySpanBuilderImpl(operationName);
}
@Override
public <C> void inject(SpanContext spanContext, Format<C> format, C carrier) {
if (format == Format.Builtin.TEXT_MAP || format == Format.Builtin.HTTP_HEADERS) {
final TextMap textMap = (TextMap) carrier;
spanContext.baggageItems().forEach(e -> textMap.put(e.getKey(), e.getValue()));
} else {
throw new UnsupportedOperationException("Format " + format.toString() + " is not currently supported");
}
}
@Override
public <C> SpanContext extract(Format<C> format, C carrier) {
if (format == Format.Builtin.TEXT_MAP || format == Format.Builtin.HTTP_HEADERS) {
final TextMap textMap = (TextMap) carrier;
final Map<String, String> baggage = new HashMap<>();
for (Map.Entry<String, String> e : textMap) {
baggage.put(e.getKey(), e.getValue());
}
return new AWSXRaySpanContext(baggage);
} else {
throw new UnsupportedOperationException("Format " + format.toString() + " is not currently supported");
}
}
/**
* AWS-specific {@link io.opentracing.Tracer.SpanBuilder} implementation
*/
private final clreplaced AWSXRaySpanBuilderImpl implements SpanBuilder {
private final String operationName;
private final Map<String, String> stringTags;
private final Map<String, Boolean> booleanTags;
private final Map<String, Number> numberTags;
/**
* AWS X-Ray timestamps are stored a number of seconds since
* the UNIX epoch, with the fractional part giving sub-second
* precision. Defaults to creation time of this builder.
*
* @see #withStartTimestamp(long)
* @see Enreplacedy#getStartTime()
*/
private final AtomicReference<Double> startTimestampEpochSeconds;
/**
* @see SpanBuilder#ignoreActiveSpan()
*/
private final AtomicReference<Boolean> ignoreActiveSpan;
/**
* Currently only support a single reference to the parent Span (if
* it exists). Other references are not supported.
*
* @see References
*/
private final Map<String, SpanContext> references;
private AWSXRaySpanBuilderImpl(String operationName) {
this.operationName = operationName;
this.stringTags = new HashMap<>();
this.booleanTags = new HashMap<>();
this.numberTags = new HashMap<>();
this.startTimestampEpochSeconds = new AtomicReference<>();
this.ignoreActiveSpan = new AtomicReference<>(false);
this.references = new ConcurrentHashMap<>();
}
@Override
public SpanBuilder asChildOf(SpanContext parent) {
return addReference(References.CHILD_OF, parent);
}
@Override
public SpanBuilder asChildOf(Span parent) {
if (parent == null) {
return this;
} else if (parent instanceof AWSXRaySpan) {
return addReference(References.CHILD_OF, new CapturingSpanContext((AWSXRaySpan) parent));
} else {
return addReference(References.CHILD_OF, parent.context());
}
}
@Override
public SpanBuilder addReference(String referenceType, SpanContext referencedContext) {
if (references.containsKey(referenceType)) {
log.warn("Replacing reference of type '" + referenceType + "': multiple references of the same type are not supported by X-Ray");
}
references.put(referenceType, referencedContext);
return this;
}
@Override
public SpanBuilder ignoreActiveSpan() {
ignoreActiveSpan.set(true);
return this;
}
@Override
public SpanBuilder withTag(String key, String value) {
stringTags.put(key, value);
return this;
}
@Override
public SpanBuilder withTag(String key, boolean value) {
booleanTags.put(key, value);
return this;
}
@Override
public SpanBuilder withTag(String key, Number value) {
numberTags.put(key, value);
return this;
}
@Override
public SpanBuilder withStartTimestamp(long microseconds) {
startTimestampEpochSeconds.set(microseconds / 1000.0 / 1000.0);
return this;
}
@Override
@Deprecated
public Span startManual() {
return start();
}
@Override
public Scope startActive(boolean finishSpanOnClose) {
final Span span = start();
return scopeManager.activate(span, finishSpanOnClose);
}
@Override
public Span start() {
// X-Ray only supports parent-child relationships between spans
// (OpenTracing allows for other references e.g. FOLLOWS_FROM)
references.forEach((key, value) -> {
if (!References.CHILD_OF.equals(key)) {
log.warn("Ignoring reference of type '" + key + "': references of this type are not supported by X-Ray");
}
});
// If an explicit CHILD_OF reference is set, this should override
// any (implicit) reference to the current trace enreplacedy
final Enreplacedy originalTraceEnreplacedy = xRayRecorder.getTraceEnreplacedy();
final SpanContext explicitParentContext = references.get(References.CHILD_OF);
final Enreplacedy parentEnreplacedy;
final Map<String, String> parentBaggage;
// Because X-Ray an OpenTracing maintain their references to the
// "current" trace separately, we can be in one of four possible states:
//
// 1. an explicit parent is set, and it has captured a full AWSXRaySpan
// i.e. this is an in-memory Span with a real X-Ray Enreplacedy
//
if (explicitParentContext instanceof CapturingSpanContext) {
parentEnreplacedy = ((CapturingSpanContext) explicitParentContext).span.getEnreplacedy();
parentBaggage = AWSXRayUtils.extract(explicitParentContext.baggageItems());
} else // 2. an explicit parent is set but it doesn't have an X-Ray Enreplacedy
// attached: we can present a FacadeSegment to X-Ray
//
if (explicitParentContext != null) {
// If the parent context has a valid AWS trace ID in its baggage
// (e.g. it came from some remote upstream server) then extract
// the trace and parent segment IDs here
TraceHeader traceHeader = null;
for (Map.Entry<String, String> e : explicitParentContext.baggageItems()) {
if (TraceHeader.HEADER_KEY.equals(e.getKey())) {
traceHeader = TraceHeader.fromString(e.getValue());
}
}
final TraceID traceId = null == traceHeader ? null : traceHeader.getRootTraceId();
final String parentId = null == traceHeader ? null : traceHeader.getParentId();
final TraceHeader.SampleDecision sampleDecision = traceHeader == null ? null : traceHeader.getSampled();
// NB the default FacadeSegment clreplaced throws exceptions but we want
// to allow subsegments to be added and removed (even though both
// of these are ultimately a no-op)
parentEnreplacedy = new FacadeSegment(xRayRecorder, traceId, parentId, sampleDecision) {
@Override
public void addSubsegment(Subsegment subsegment) {
}
@Override
public void removeSubsegment(Subsegment subsegment) {
}
};
parentBaggage = AWSXRayUtils.extract(explicitParentContext.baggageItems());
} else // 3. no explicit parent is set, but ignoreActiveSpan has been set so
// make sure the parent Enreplacedy is null (i.e. we'll create a new
// Segment in X-Ray terms)
//
if (ignoreActiveSpan.get()) {
parentEnreplacedy = null;
parentBaggage = Collections.emptyMap();
} else // 4. no explicit parent, and ignoreActiveSpan is not set so create an
// implicit reference to the current trace enreplacedy (if it exists:
// if it's null we'll instead end up creating a top-level Segment
// instead)
//
{
parentEnreplacedy = originalTraceEnreplacedy;
parentBaggage = Collections.emptyMap();
}
// X-Ray automatically maintains internal references between Segments and
// Subsegments - rather than trying to replicate that logic here, we cheat
// by (temporarily) overwriting the parent trace Enreplacedy, creating the new
// Enreplacedy, then setting it back once we're done
xRayRecorder.setTraceEnreplacedy(parentEnreplacedy);
// Special case when running in AWS Lambda: the Lambda infrastructure
// creates a top-level trace Segment to which we do not have access, so
// creating another Segment here would be an error. Instead, we need to
// forcibly create a Subsegment.
final boolean isAwsLambda = xRayRecorder.getSegmentContextResolverChain().resolve() instanceof LambdaSegmentContext;
final Enreplacedy childEnreplacedy = (xRayRecorder.getTraceEnreplacedy() == null && !isAwsLambda) ? xRayRecorder.beginSegment(operationName) : xRayRecorder.beginSubsegment(operationName);
// Set the original trace enreplacedy back on AWSXRayRecorder as soon as possible
xRayRecorder.setTraceEnreplacedy(originalTraceEnreplacedy);
// AWS X-Ray doesn't support the notion of "not-yet-started" segments
// so set the Enreplacedy to be "in progress"
childEnreplacedy.setInProgress(true);
// Default to "now" if an explicit start time wasn't set
startTimestampEpochSeconds.compareAndSet(null, Instant.now().toEpochMilli() / 1000.0);
childEnreplacedy.setStartTime(startTimestampEpochSeconds.get());
// Baggage items should mostly be carried over from the parent Span's
// context (if it exists) to the child Span; however, the TraceHeader
// should be replaced with the new value for the child span
final TraceHeader traceHeader = new TraceHeader(childEnreplacedy.getParentSegment().getTraceId(), null == parentEnreplacedy ? null : parentEnreplacedy.getId(), childEnreplacedy.getParentSegment().isSampled() ? TraceHeader.SampleDecision.SAMPLED : TraceHeader.SampleDecision.NOT_SAMPLED);
final Map<String, String> childBaggage = new HashMap<>(parentBaggage);
childBaggage.put(TraceHeader.HEADER_KEY, traceHeader.toString());
final AWSXRaySpanContext newSpanContext = new AWSXRaySpanContext(childBaggage);
// Defer to AWSXRaySpan to set tag values since this will handle
// converting to X-Ray's naming conventions and format
final AWSXRaySpan newSpan = new AWSXRaySpan(childEnreplacedy, newSpanContext);
stringTags.forEach(newSpan::setTag);
booleanTags.forEach(newSpan::setTag);
numberTags.forEach(newSpan::setTag);
return newSpan;
}
}
/**
* Parent-child relationships between Spans are typically only defined in
* terms of the SpanContext (i.e. we only need to know the parent span's
* trace and span ID). However, X-Ray also holds directly object references
* to the underlying Segment and Subsegment instances, so try to capture
* the full AWSXRaySpan instance here if we can.
*/
private static final clreplaced CapturingSpanContext implements SpanContext {
private final AWSXRaySpan span;
public CapturingSpanContext(AWSXRaySpan span) {
this.span = span;
}
@Override
public Iterable<Map.Entry<String, String>> baggageItems() {
return span.context().baggageItems();
}
}
}
19
Source : AWSXRayScopeManager.java
with Apache License 2.0
from opentracing-contrib
with Apache License 2.0
from opentracing-contrib
/**
* Implementation of {@link ScopeManager} when tracing with AWS X-Ray.
* The X-Ray libraries also have their own lifecycle management and
* reference counting for the underlying trace {@link Enreplacedy}s, so we
* need to hook in to these to keep OpenTracing and X-Ray in sync.
*
* @author [email protected]
*/
clreplaced AWSXRayScopeManager implements ScopeManager {
private static final Logger log = LoggerFactory.getLogger(AWSXRayScopeManager.clreplaced);
/**
* The {@link AWSXRayRecorder} clreplaced keeps track of the current trace
* {@link Enreplacedy} on this thread, and we need to keep its view and our
* view of the world in sync.
*/
private final AWSXRayRecorder xRayRecorder;
/**
* X-Ray already keeps track of the current active {@link Enreplacedy}, but
* additionally track here the whole {@link Scope} in order to be able
* to recover the previous state on this thread once the current span
* is finished / closed.
*/
private final ThreadLocal<AWSXRayScope> currentScope;
/**
* Set the current {@link Scope} back to the given value. All changes to
* the {@link #currentScope} value should preplaced through this method, since
* it also hooks into the underlying X-Ray clreplacedes.
*
* @param scope the new current scope
*/
void setCurrentScope(AWSXRayScope scope) {
currentScope.set(scope);
xRayRecorder.setTraceEnreplacedy(scope == null ? null : scope.span().getEnreplacedy());
}
AWSXRayScopeManager(AWSXRayRecorder xRayRecorder) {
this.xRayRecorder = xRayRecorder;
this.currentScope = new ThreadLocal<>();
}
@Override
public AWSXRayScope active() {
return this.currentScope.get();
}
AWSXRaySpan activeSpan() {
final AWSXRayScope activeScope = this.currentScope.get();
return activeScope == null ? null : activeScope.span();
}
@Override
public Scope activate(Span span, boolean finishSpanOnClose) {
if (span instanceof AWSXRaySpan) {
final AWSXRayScope oldScope = currentScope.get();
final AWSXRayScope newScope = new AWSXRayScope(this, oldScope, (AWSXRaySpan) span, finishSpanOnClose);
setCurrentScope(newScope);
return newScope;
} else {
if (span != null) {
log.warn("Cannot activate Span: expected AWSXRaySpan but got type " + span.getClreplaced().getSimpleName());
}
return currentScope.get();
}
}
}
19
Source : SqsListenerXrayConfigurationTest.java
with MIT License
from JaidenAshmore
with MIT License
from JaidenAshmore
@ExtendWith(MockitoExtension.clreplaced)
clreplaced SqsListenerXrayConfigurationTest {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner().withConfiguration(AutoConfigurations.of(QueueListenerConfiguration.clreplaced, SqsListenerXrayConfiguration.clreplaced));
@Mock
private AWSXRayRecorder mockGlobalRecorder;
private AWSXRayRecorder globalRecorder;
@BeforeEach
void setupMockRecorder() {
globalRecorder = AWSXRay.getGlobalRecorder();
AWSXRay.setGlobalRecorder(mockGlobalRecorder);
}
@AfterEach
void tearDown() {
AWSXRay.setGlobalRecorder(globalRecorder);
}
@Nested
clreplaced Decorator {
@Test
void shouldProvideDecoratorBean() {
contextRunner.withBean(SqsAsyncClient.clreplaced, () -> mock(SqsAsyncClient.clreplaced)).run(context -> replacedertThat(context).hreplacedingleBean(BasicXrayMessageProcessingDecorator.clreplaced));
}
@Test
void willSetSegmentAsDefaultNameWhenApplicationNameNotPresent() {
contextRunner.withBean(SqsAsyncClient.clreplaced, () -> mock(SqsAsyncClient.clreplaced)).run(context -> {
when(mockGlobalRecorder.beginSegment(anyString())).thenReturn(mock(Segment.clreplaced));
when(mockGlobalRecorder.beginSubsegment(anyString())).thenReturn(mock(Subsegment.clreplaced));
final BasicXrayMessageProcessingDecorator decorator = context.getBean(BasicXrayMessageProcessingDecorator.clreplaced);
decorator.onPreMessageProcessing(MessageProcessingContext.builder().attributes(new HashMap<>()).listenerIdentifier("identifier").queueProperties(QueueProperties.builder().queueUrl("url").build()).build(), Message.builder().build());
verify(mockGlobalRecorder).beginSegment("service");
});
}
@Test
void willSetSegmentreplacederviceNameWhenApplicationNameNotPresent() {
contextRunner.withPropertyValues("spring.application.name=my-service-name").withBean(SqsAsyncClient.clreplaced, () -> mock(SqsAsyncClient.clreplaced)).run(context -> {
when(mockGlobalRecorder.beginSegment(anyString())).thenReturn(mock(Segment.clreplaced));
when(mockGlobalRecorder.beginSubsegment(anyString())).thenReturn(mock(Subsegment.clreplaced));
final BasicXrayMessageProcessingDecorator decorator = context.getBean(BasicXrayMessageProcessingDecorator.clreplaced);
decorator.onPreMessageProcessing(MessageProcessingContext.builder().attributes(new HashMap<>()).listenerIdentifier("identifier").queueProperties(QueueProperties.builder().queueUrl("url").build()).build(), Message.builder().build());
verify(mockGlobalRecorder).beginSegment("my-service-name");
});
}
@Test
void willUseCustomRecorderIfExplicitlySet() {
final AWSXRayRecorder mockRecorder = mock(AWSXRayRecorder.clreplaced);
contextRunner.withBean(SqsAsyncClient.clreplaced, () -> mock(SqsAsyncClient.clreplaced)).withBean("sqsXrayRecorder", AWSXRayRecorder.clreplaced, () -> mockRecorder).run(context -> {
when(mockRecorder.beginSegment(anyString())).thenReturn(mock(Segment.clreplaced));
when(mockRecorder.beginSubsegment(anyString())).thenReturn(mock(Subsegment.clreplaced));
final BasicXrayMessageProcessingDecorator decorator = context.getBean(BasicXrayMessageProcessingDecorator.clreplaced);
decorator.onPreMessageProcessing(MessageProcessingContext.builder().attributes(new HashMap<>()).listenerIdentifier("identifier").queueProperties(QueueProperties.builder().queueUrl("url").build()).build(), Message.builder().build());
verify(mockRecorder).beginSegment("service");
});
}
}
@Nested
clreplaced ClientProvider {
@Test
void whenNoSqsAsyncClientProvidedDefaultWillBeCreated() {
contextRunner.withSystemProperties("aws.region:localstack").run(context -> context.getBean(SqsAsyncClientProvider.clreplaced));
}
@Test
void defaultProviderWrapsSqsClientWithXRayLogic() {
final SqsAsyncClient defaultClient = mock(SqsAsyncClient.clreplaced);
contextRunner.withBean(SqsAsyncClient.clreplaced, () -> defaultClient).run(context -> {
when(mockGlobalRecorder.beginSegment(anyString())).thenReturn(mock(Segment.clreplaced));
final SqsAsyncClientProvider provider = context.getBean(SqsAsyncClientProvider.clreplaced);
final SqsAsyncClient client = provider.getDefaultClient().orElseThrow(() -> new RuntimeException("Error"));
replacedertThat(client).isInstanceOf(XrayWrappedSqsAsyncClient.clreplaced);
client.sendMessage(SendMessageRequest.builder().build());
verify(defaultClient).sendMessage(any(SendMessageRequest.clreplaced));
});
}
@Test
void willPublishMetricsWithDefaultSegmentNameIfApplicationNameMissing() {
contextRunner.withBean(SqsAsyncClient.clreplaced, () -> mock(SqsAsyncClient.clreplaced)).run(context -> {
when(mockGlobalRecorder.beginSegment(anyString())).thenReturn(mock(Segment.clreplaced));
final SqsAsyncClient client = context.getBean(SqsAsyncClientProvider.clreplaced).getDefaultClient().orElseThrow(() -> new RuntimeException("Error"));
client.sendMessage(SendMessageRequest.builder().build());
verify(mockGlobalRecorder).beginSegment("service");
verify(mockGlobalRecorder).endSegment();
});
}
@Test
void willPublishMetricsWithApplicationNameWhenSet() {
contextRunner.withPropertyValues("spring.application.name=my-service-name").withBean(SqsAsyncClient.clreplaced, () -> mock(SqsAsyncClient.clreplaced)).run(context -> {
when(mockGlobalRecorder.beginSegment(anyString())).thenReturn(mock(Segment.clreplaced));
final SqsAsyncClient client = context.getBean(SqsAsyncClientProvider.clreplaced).getDefaultClient().orElseThrow(() -> new RuntimeException("Error"));
client.sendMessage(SendMessageRequest.builder().build());
verify(mockGlobalRecorder).beginSegment("my-service-name");
verify(mockGlobalRecorder).endSegment();
});
}
@Test
void shouldUseProvidedClientProviderIfOneSet() {
final SqsAsyncClientProvider clientProvider = mock(SqsAsyncClientProvider.clreplaced);
contextRunner.withBean(SqsAsyncClientProvider.clreplaced, () -> clientProvider).run(context -> replacedertThat(context.getBean(SqsAsyncClientProvider.clreplaced)).isSameAs(clientProvider));
}
@Test
void canIncludeCustomRecorderNotUsedByThisLibrary() {
contextRunner.withBean(SqsAsyncClient.clreplaced, () -> mock(SqsAsyncClient.clreplaced)).withBean("anotherXrayRecorder", AWSXRayRecorder.clreplaced, () -> mock(AWSXRayRecorder.clreplaced)).run(context -> {
replacedertThat(context).hasBean("anotherXrayRecorder");
replacedertThat(context).hasBean("sqsXrayRecorder");
context.getBean(SqsAsyncClientProvider.clreplaced);
});
}
@Test
void canOverrideSqsXrayRecorderUsingBeanName() {
final AWSXRayRecorder mockRecorder = mock(AWSXRayRecorder.clreplaced);
contextRunner.withBean(SqsAsyncClient.clreplaced, () -> mock(SqsAsyncClient.clreplaced)).withBean("sqsXrayRecorder", AWSXRayRecorder.clreplaced, () -> mockRecorder).run(context -> {
when(mockRecorder.beginSegment(anyString())).thenReturn(mock(Segment.clreplaced));
replacedertThat(context).hreplacedingleBean(AWSXRayRecorder.clreplaced);
replacedertThat(context.getBean("sqsXrayRecorder")).isSameAs(mockRecorder);
final SqsAsyncClient sqsAsyncClient = context.getBean(SqsAsyncClientProvider.clreplaced).getDefaultClient().orElseThrow(() -> new RuntimeException(""));
sqsAsyncClient.sendMessage(SendMessageRequest.builder().build());
verify(mockRecorder).beginSegment(anyString());
});
}
@Test
void willUseGlobalRecorderIfNoneExplicitlySet() {
contextRunner.withBean(SqsAsyncClient.clreplaced, () -> mock(SqsAsyncClient.clreplaced)).run(context -> {
when(mockGlobalRecorder.beginSegment(anyString())).thenReturn(mock(Segment.clreplaced));
replacedertThat(context).hreplacedingleBean(AWSXRayRecorder.clreplaced);
replacedertThat(context.getBean("sqsXrayRecorder")).isSameAs(mockGlobalRecorder);
final SqsAsyncClient sqsAsyncClient = context.getBean(SqsAsyncClientProvider.clreplaced).getDefaultClient().orElseThrow(() -> new RuntimeException(""));
sqsAsyncClient.sendMessage(SendMessageRequest.builder().build());
verify(mockGlobalRecorder).beginSegment(anyString());
});
}
}
}
19
Source : SqsListenerXrayConfiguration.java
with MIT License
from JaidenAshmore
with MIT License
from JaidenAshmore
@Bean
@ConditionalOnMissingBean
public BasicXrayMessageProcessingDecorator xrayMessageDecorator(@Qualifier("sqsXrayRecorder") final AWSXRayRecorder recorder, @Value("${spring.application.name:service}") final String applicationName) {
return new BasicXrayMessageProcessingDecorator(BasicXrayMessageProcessingDecorator.Options.builder().recorder(recorder).segmentNamingStrategy(new StaticDecoratorSegmentNamingStrategy(applicationName)).build());
}
19
Source : BasicXrayMessageProcessingDecoratorTest.java
with MIT License
from JaidenAshmore
with MIT License
from JaidenAshmore
@ExtendWith(MockitoExtension.clreplaced)
clreplaced BasicXrayMessageProcessingDecoratorTest {
@Mock
AWSXRayRecorder recorder;
@Nested
public clreplaced MessageListenerSegment {
@Test
void willBeginSegment() {
// arrange
final BasicXrayMessageProcessingDecorator decorator = new BasicXrayMessageProcessingDecorator(BasicXrayMessageProcessingDecorator.Options.builder().recorder(recorder).build());
final MessageProcessor processor = createMessageProcessor("message-listener", decorator);
// act
processor.processMessage(Message.builder().build(), () -> CompletableFuture.completedFuture(null));
// replacedert
verify(recorder).beginSegment(anyString());
}
@Test
void whenNoSegmentNamingStrategyProvidedTheNameIsADefaultValue() {
// arrange
final BasicXrayMessageProcessingDecorator decorator = new BasicXrayMessageProcessingDecorator(BasicXrayMessageProcessingDecorator.Options.builder().recorder(recorder).build());
final MessageProcessor processor = createMessageProcessor("message-listener-identifier", decorator);
// act
processor.processMessage(Message.builder().build(), () -> CompletableFuture.completedFuture(null));
// replacedert
verify(recorder).beginSegment("message-listener");
}
@Test
void whenNoRecorderGlobalRecorderIsUsed() {
// arrange
AWSXRay.setGlobalRecorder(recorder);
final BasicXrayMessageProcessingDecorator decorator = new BasicXrayMessageProcessingDecorator(BasicXrayMessageProcessingDecorator.Options.builder().build());
final MessageProcessor processor = createMessageProcessor("message-listener-identifier", decorator);
// act
processor.processMessage(Message.builder().build(), () -> CompletableFuture.completedFuture(null));
// replacedert
verify(recorder).beginSegment("message-listener");
}
@Test
void segmentNamingStrategyCanBeUsedToNameSegment() {
// arrange
final BasicXrayMessageProcessingDecorator decorator = new BasicXrayMessageProcessingDecorator(BasicXrayMessageProcessingDecorator.Options.builder().recorder(recorder).segmentNamingStrategy(new StaticDecoratorSegmentNamingStrategy("static-name")).build());
final MessageProcessor processor = createMessageProcessor("message-listener-identifier", decorator);
// act
processor.processMessage(Message.builder().build(), () -> CompletableFuture.completedFuture(null));
// replacedert
verify(recorder).beginSegment("static-name");
}
@Test
void segmentMutatorCanBeUsedToMutateTheSegmentAfterConstruction() {
// arrange
final BasicXrayMessageProcessingDecorator decorator = new BasicXrayMessageProcessingDecorator(BasicXrayMessageProcessingDecorator.Options.builder().recorder(recorder).segmentMutator((segment, context, message) -> segment.setSampled(false)).build());
final MessageProcessor processor = createMessageProcessor("message-listener-identifier", decorator);
final Segment mockSegment = mock(Segment.clreplaced);
when(recorder.beginSegment(anyString())).thenReturn(mockSegment);
// act
processor.processMessage(Message.builder().build(), () -> CompletableFuture.completedFuture(null));
// replacedert
verify(mockSegment).setSampled(false);
}
@Test
void messageProcessingThreadWillHaveSegmentAsContextWhenNoSubsegmentCreated() {
// arrange
final AtomicReference<Segment> messageListenerSegment = new AtomicReference<>();
final AtomicReference<Enreplacedy> messageProcessingEnreplacedy = new AtomicReference<>();
final AWSXRayRecorder globalRecorder = AWSXRayRecorderBuilder.defaultRecorder();
final BasicXrayMessageProcessingDecorator decorator = new BasicXrayMessageProcessingDecorator(BasicXrayMessageProcessingDecorator.Options.builder().recorder(globalRecorder).segmentMutator((segment, context, message) -> messageListenerSegment.set(segment)).generateSubsegment(false).build());
AWSXRay.setGlobalRecorder(globalRecorder);
final MessageProcessor processor = createMessageProcessor("message-listener-identifier", decorator, (message, resolver) -> {
messageProcessingEnreplacedy.set(AWSXRay.getCurrentSegment());
return CompletableFuture.completedFuture(null);
});
// act
processor.processMessage(Message.builder().build(), () -> CompletableFuture.completedFuture(null));
// replacedert
replacedertThat(messageProcessingEnreplacedy).hasValue(messageListenerSegment.get());
}
@Test
void willContinueTraceWhenHeaderPresentInMessage() {
// arrange
final Segment mockSegment = mock(Segment.clreplaced);
when(recorder.beginSegment(anyString())).thenReturn(mockSegment);
final BasicXrayMessageProcessingDecorator decorator = new BasicXrayMessageProcessingDecorator(BasicXrayMessageProcessingDecorator.Options.builder().recorder(recorder).build());
final MessageProcessor processor = createMessageProcessor("message-listener-identifier", decorator, (message, resolver) -> CompletableFuture.completedFuture(null));
// act
processor.processMessage(Message.builder().attributes(Collections.singletonMap(MessageSystemAttributeName.AWS_TRACE_HEADER, "Root=1-5f07980f-7e310a9e3becb5a6386ce0e6;Parent=3ee6c885d5b1663b;Sampled=1")).build(), () -> CompletableFuture.completedFuture(null));
// replacedert
verify(mockSegment).setTraceId(TraceID.fromString("1-5f07980f-7e310a9e3becb5a6386ce0e6"));
verify(mockSegment).setParentId("3ee6c885d5b1663b");
verify(mockSegment).setSampled(true);
}
@Test
void afterProcessingSegmentWillBeEnded() {
// arrange
final AtomicReference<Segment> messageListenerSegment = new AtomicReference<>();
final AWSXRayRecorder globalRecorder = AWSXRayRecorderBuilder.defaultRecorder();
final BasicXrayMessageProcessingDecorator decorator = new BasicXrayMessageProcessingDecorator(BasicXrayMessageProcessingDecorator.Options.builder().recorder(globalRecorder).segmentMutator((segment, context, message) -> messageListenerSegment.set(segment)).generateSubsegment(false).build());
AWSXRay.setGlobalRecorder(globalRecorder);
final MessageProcessor processor = createMessageProcessor("message-listener-identifier", decorator, (message, resolver) -> {
replacedertThat(messageListenerSegment.get().isEmitted()).isFalse();
return CompletableFuture.completedFuture(null);
});
// act
processor.processMessage(Message.builder().build(), () -> CompletableFuture.completedFuture(null));
// replacedert
replacedertThat(messageListenerSegment.get().isEmitted()).isTrue();
}
}
@Nested
clreplaced MessageListenerSubsegment {
@Test
void willNotCreateSubsegmentIfMarkedAsFalse() {
// arrange
final BasicXrayMessageProcessingDecorator decorator = new BasicXrayMessageProcessingDecorator(BasicXrayMessageProcessingDecorator.Options.builder().recorder(recorder).generateSubsegment(false).build());
final MessageProcessor processor = createMessageProcessor("message-listener", decorator);
// act
processor.processMessage(Message.builder().build(), () -> CompletableFuture.completedFuture(null));
// replacedert
verify(recorder, never()).beginSubsegment(anyString());
}
@Test
void willCreateSubsegmentIfGenerateSubsegmentIsNull() {
// arrange
final BasicXrayMessageProcessingDecorator decorator = new BasicXrayMessageProcessingDecorator(BasicXrayMessageProcessingDecorator.Options.builder().recorder(recorder).generateSubsegment(null).build());
final MessageProcessor processor = createMessageProcessor("message-listener-identifier", decorator);
// act
processor.processMessage(Message.builder().build(), () -> CompletableFuture.completedFuture(null));
// replacedert
verify(recorder).beginSubsegment("message-listener-identifier");
}
@Test
void whenNoSubsegmentNamingStrategySubsegmentNameWillBeMessageListenerIdentifier() {
// arrange
final BasicXrayMessageProcessingDecorator decorator = new BasicXrayMessageProcessingDecorator(BasicXrayMessageProcessingDecorator.Options.builder().recorder(recorder).subsegmentNamingStrategy(null).build());
final MessageProcessor processor = createMessageProcessor("message-listener-identifier", decorator);
// act
processor.processMessage(Message.builder().build(), () -> CompletableFuture.completedFuture(null));
// replacedert
verify(recorder).beginSubsegment("message-listener-identifier");
}
@Test
void subsegmentNamingStrategyCanBeUsedToNameSubsegment() {
// arrange
final BasicXrayMessageProcessingDecorator decorator = new BasicXrayMessageProcessingDecorator(BasicXrayMessageProcessingDecorator.Options.builder().recorder(recorder).subsegmentNamingStrategy((context, message) -> "static-name").build());
final MessageProcessor processor = createMessageProcessor("message-listener-identifier", decorator);
// act
processor.processMessage(Message.builder().build(), () -> CompletableFuture.completedFuture(null));
// replacedert
verify(recorder).beginSubsegment("static-name");
}
@Test
void subsegmentMutatorCanBeUsedToModifyTheSubsegment() {
// arrange
final AtomicReference<Subsegment> subsegmentFound = new AtomicReference<>();
final BasicXrayMessageProcessingDecorator decorator = new BasicXrayMessageProcessingDecorator(BasicXrayMessageProcessingDecorator.Options.builder().recorder(recorder).subsegmentMutator(((subsegment, context, message) -> subsegmentFound.set(subsegment))).build());
final MessageProcessor processor = createMessageProcessor("message-listener-identifier", decorator);
// act
processor.processMessage(Message.builder().build(), () -> CompletableFuture.completedFuture(null));
// replacedert
replacedertThat(subsegmentFound).isNotNull();
}
@Test
void messageProcessingThreadWillHaveSegmentAsContextWhenNoSubsegmentCreated() {
// arrange
final AtomicReference<Subsegment> messageListenerSubsegment = new AtomicReference<>();
final AtomicReference<Enreplacedy> messageProcessingEnreplacedy = new AtomicReference<>();
final AWSXRayRecorder globalRecorder = AWSXRayRecorderBuilder.defaultRecorder();
final BasicXrayMessageProcessingDecorator decorator = new BasicXrayMessageProcessingDecorator(BasicXrayMessageProcessingDecorator.Options.builder().recorder(globalRecorder).subsegmentMutator((segment, context, message) -> messageListenerSubsegment.set(segment)).build());
AWSXRay.setGlobalRecorder(globalRecorder);
final MessageProcessor processor = createMessageProcessor("message-listener-identifier", decorator, (message, resolver) -> {
messageProcessingEnreplacedy.set(AWSXRay.getTraceEnreplacedy());
return CompletableFuture.completedFuture(null);
});
// act
processor.processMessage(Message.builder().build(), () -> CompletableFuture.completedFuture(null));
// replacedert
replacedertThat(messageProcessingEnreplacedy).hasValue(messageListenerSubsegment.get());
}
@Test
void subsegmentWillBeClosedWhenFinishedProcessing() {
// arrange
final AtomicReference<Subsegment> messageListenerSubsegment = new AtomicReference<>();
final AtomicReference<Enreplacedy> messageProcessingEnreplacedy = new AtomicReference<>();
when(recorder.beginSegment(anyString())).thenReturn(mock(Segment.clreplaced));
final Subsegment mockSubsegment = mock(Subsegment.clreplaced);
when(recorder.beginSubsegment(anyString())).thenReturn(mockSubsegment);
final BasicXrayMessageProcessingDecorator decorator = new BasicXrayMessageProcessingDecorator(BasicXrayMessageProcessingDecorator.Options.builder().recorder(recorder).subsegmentMutator((segment, context, message) -> messageListenerSubsegment.set(segment)).build());
final MessageProcessor processor = createMessageProcessor("message-listener-identifier", decorator, (message, resolver) -> {
messageProcessingEnreplacedy.set(AWSXRay.getTraceEnreplacedy());
return CompletableFuture.completedFuture(null);
});
// act
processor.processMessage(Message.builder().build(), () -> CompletableFuture.completedFuture(null));
// replacedert
verify(recorder, times(2)).setTraceEnreplacedy(mockSubsegment);
verify(recorder).endSubsegment();
}
}
@Nested
clreplaced ProcessingErrorOutcome {
@Test
void onFailureToProcessMessageSegmentWillHaveExceptionAddedToSegment() {
// arrange
final BasicXrayMessageProcessingDecorator decorator = new BasicXrayMessageProcessingDecorator(BasicXrayMessageProcessingDecorator.Options.builder().recorder(recorder).build());
final ExpectedTestException expectedTestException = new ExpectedTestException();
final MessageProcessor processor = createMessageProcessor("message-listener", decorator, CompletableFutureUtils.completedExceptionally(expectedTestException));
final Segment mockSegment = mock(Segment.clreplaced);
when(recorder.beginSegment(anyString())).thenReturn(mockSegment);
// act
processor.processMessage(Message.builder().build(), () -> CompletableFuture.completedFuture(null));
// replacedert
verify(mockSegment).addException(expectedTestException);
}
@Test
void onFailureToProcessMessageSegmentWillHaveExceptionAddedToSubsegment() {
// arrange
final BasicXrayMessageProcessingDecorator decorator = new BasicXrayMessageProcessingDecorator(BasicXrayMessageProcessingDecorator.Options.builder().recorder(recorder).build());
final ExpectedTestException expectedTestException = new ExpectedTestException();
final MessageProcessor processor = createMessageProcessor("message-listener", decorator, CompletableFutureUtils.completedExceptionally(expectedTestException));
final Subsegment mockSubsegment = mock(Subsegment.clreplaced);
when(recorder.beginSubsegment(anyString())).thenReturn(mockSubsegment);
// act
processor.processMessage(Message.builder().build(), () -> CompletableFuture.completedFuture(null));
// replacedert
verify(mockSubsegment).addException(expectedTestException);
}
}
private MessageProcessor createMessageProcessor(final String messageListenerIdentifier, final BasicXrayMessageProcessingDecorator decorator) {
return createMessageProcessor(messageListenerIdentifier, decorator, CompletableFuture.completedFuture(null));
}
private MessageProcessor createMessageProcessor(final String messageListenerIdentifier, final BasicXrayMessageProcessingDecorator decorator, final CompletableFuture<?> returnValue) {
return createMessageProcessor(messageListenerIdentifier, decorator, (message, resolveMessageCallback) -> returnValue);
}
private MessageProcessor createMessageProcessor(final String messageListenerIdentifier, final BasicXrayMessageProcessingDecorator decorator, final MessageProcessor delegate) {
return new DecoratingMessageProcessor(messageListenerIdentifier, QueueProperties.builder().queueUrl("url").build(), Collections.singletonList(decorator), delegate);
}
}
19
Source : XrayWrappedSqsAsyncClientTest.java
with MIT License
from JaidenAshmore
with MIT License
from JaidenAshmore
@Slf4j
@ExtendWith(MockitoExtension.clreplaced)
clreplaced XrayWrappedSqsAsyncClientTest {
@Mock
SqsAsyncClient delegate;
@Mock
AWSXRayRecorder recorder;
ClientSegmentNamingStrategy segmentNamingStrategy = new StaticClientSegmentNamingStrategy("static-name");
@Nested
clreplaced SegmentWrapping {
@Test
void noSegmentNamingStrategyWillUseDefault() {
// arrange
when(recorder.getCurrentSegmentOptional()).thenReturn(Optional.empty());
final SqsAsyncClient client = new XrayWrappedSqsAsyncClient(XrayWrappedSqsAsyncClient.Options.builder().delegate(delegate).recorder(recorder).build());
// act
client.sendMessage(SendMessageRequest.builder().messageBody("body").build());
// replacedert
verify(recorder).beginSegment("message-listener");
verify(delegate).sendMessage(any(SendMessageRequest.clreplaced));
verify(recorder).endSegment();
}
@Test
void clientCallWillCreateSegmentIfNotAlreadyPresent() {
// arrange
when(recorder.getCurrentSegmentOptional()).thenReturn(Optional.empty());
final SqsAsyncClient client = new XrayWrappedSqsAsyncClient(XrayWrappedSqsAsyncClient.Options.builder().delegate(delegate).recorder(recorder).segmentNamingStrategy(segmentNamingStrategy).build());
// act
client.sendMessage(SendMessageRequest.builder().messageBody("body").build());
// replacedert
verify(recorder).beginSegment("static-name");
verify(delegate).sendMessage(any(SendMessageRequest.clreplaced));
verify(recorder).endSegment();
}
@Test
void clientCallWillNotCreateSegmentIfAlreadyPresent() {
// arrange
when(recorder.getCurrentSegmentOptional()).thenReturn(Optional.of(mock(Segment.clreplaced)));
final SqsAsyncClient client = new XrayWrappedSqsAsyncClient(XrayWrappedSqsAsyncClient.Options.builder().delegate(delegate).recorder(recorder).segmentNamingStrategy(segmentNamingStrategy).build());
// act
client.sendMessage(SendMessageRequest.builder().messageBody("body").build());
// replacedert
verify(recorder, never()).beginSegment("static-name");
verify(delegate).sendMessage(any(SendMessageRequest.clreplaced));
verify(recorder, never()).endSegment();
}
@Test
void whenNoRecorderSetGlobalIsUsed() {
// arrange
AWSXRay.setGlobalRecorder(recorder);
when(recorder.getCurrentSegmentOptional()).thenReturn(Optional.of(mock(Segment.clreplaced)));
final SqsAsyncClient client = new XrayWrappedSqsAsyncClient(XrayWrappedSqsAsyncClient.Options.builder().delegate(delegate).segmentNamingStrategy(segmentNamingStrategy).build());
// act
client.sendMessage(SendMessageRequest.builder().messageBody("body").build());
// replacedert
verify(recorder, never()).beginSegment("static-name");
verify(delegate).sendMessage(any(SendMessageRequest.clreplaced));
verify(recorder, never()).endSegment();
}
@Test
void allowsForMutatingOfSegmentCreated() {
// arrange
when(recorder.getCurrentSegmentOptional()).thenReturn(Optional.empty());
final Segment mockSegment = mock(Segment.clreplaced);
when(recorder.beginSegment(anyString())).thenReturn(mockSegment);
final ClientSegmentMutator clientSegmentMutator = mock(ClientSegmentMutator.clreplaced);
final SqsAsyncClient client = new XrayWrappedSqsAsyncClient(XrayWrappedSqsAsyncClient.Options.builder().delegate(delegate).recorder(recorder).segmentMutator(clientSegmentMutator).build());
// act
client.sendMessage(SendMessageRequest.builder().messageBody("body").build());
// replacedert
verify(clientSegmentMutator).mutateSegment(mockSegment);
}
@Test
void unsampledClientSegmentMutatorWillMarkSegmentAsNotSampled() {
// arrange
when(recorder.getCurrentSegmentOptional()).thenReturn(Optional.empty());
final Segment mockSegment = mock(Segment.clreplaced);
when(recorder.beginSegment(anyString())).thenReturn(mockSegment);
final SqsAsyncClient client = new XrayWrappedSqsAsyncClient(XrayWrappedSqsAsyncClient.Options.builder().delegate(delegate).recorder(recorder).segmentMutator(new UnsampledClientSegmentMutator()).build());
// act
client.sendMessage(SendMessageRequest.builder().messageBody("body").build());
// replacedert
verify(mockSegment).setSampled(false);
}
@Test
void allMethodsAreCorrectlyWrapped() throws InvocationTargetException, IllegalAccessException {
// arrange
when(recorder.getCurrentSegmentOptional()).thenReturn(Optional.empty());
final List<Method> declaredMethods = Arrays.stream(XrayWrappedSqsAsyncClient.clreplaced.getDeclaredMethods()).filter(method -> Modifier.isPublic(method.getModifiers()) && !Modifier.isStatic(method.getModifiers())).filter(method -> !method.getName().equals("serviceName") && !method.getName().equals("close")).collect(toList());
log.info("Methods: {}", declaredMethods.stream().map(Method::getName).collect(toList()));
final SqsAsyncClient client = new XrayWrappedSqsAsyncClient(XrayWrappedSqsAsyncClient.Options.builder().delegate(delegate).recorder(recorder).build());
// act
for (final Method method : declaredMethods) {
if (method.getParameterCount() == 1) {
method.invoke(client, (Object) null);
} else {
method.invoke(client);
}
}
// replacedert
verify(recorder, times(declaredMethods.size())).beginSegment(anyString());
verify(recorder, times(declaredMethods.size())).endSegment();
}
}
@Nested
clreplaced ServiceName {
@Test
void willCallDelegateServiceName() {
// arrange
final SqsAsyncClient client = new XrayWrappedSqsAsyncClient(XrayWrappedSqsAsyncClient.Options.builder().delegate(delegate).recorder(recorder).build());
// act
client.serviceName();
// arrange
verify(delegate).serviceName();
}
}
@Nested
clreplaced Close {
@Test
void willCallDelegateClose() {
// arrange
final SqsAsyncClient client = new XrayWrappedSqsAsyncClient(XrayWrappedSqsAsyncClient.Options.builder().delegate(delegate).recorder(recorder).build());
// act
client.close();
// arrange
verify(delegate).close();
}
}
}
19
Source : BasicXrayMessageProcessingDecorator.java
with MIT License
from JaidenAshmore
with MIT License
from JaidenAshmore
/**
* A very basic decorator that will start a new segment and link this to any existing Xray trace in the message.
*
* <p>See <a href="https://docs.aws.amazon.com/xray/latest/devguide/xray-services-sqs.html">Xray SQS Services</a>
*/
public clreplaced BasicXrayMessageProcessingDecorator implements MessageProcessingDecorator {
private static final String SEGMENT_CONTEXT_ATTRIBUTE_NAME = BasicXrayMessageProcessingDecorator.clreplaced.getSimpleName() + ":segment";
private static final String SUBSEGMENT_CONTEXT_ATTRIBUTE_NAME = BasicXrayMessageProcessingDecorator.clreplaced.getSimpleName() + ":subsegment";
private static final String DEFAULT_SEGMENT_NAME = "message-listener";
private final AWSXRayRecorder recorder;
private final DecoratorSegmentNamingStrategy segmentNamingStrategy;
private final DecoratorSegmentMutator segmentMutator;
private final DecoratorSubsegmentNamingStrategy subsegmentNamingStrategy;
private final DecoratorSubsegmentMutator subsegmentMutator;
private final boolean generateSubsegment;
public BasicXrayMessageProcessingDecorator(final Options options) {
this.recorder = options.recorder != null ? options.recorder : AWSXRay.getGlobalRecorder();
this.segmentNamingStrategy = options.segmentNamingStrategy != null ? options.segmentNamingStrategy : new StaticDecoratorSegmentNamingStrategy(DEFAULT_SEGMENT_NAME);
this.segmentMutator = options.segmentMutator;
this.subsegmentNamingStrategy = options.subsegmentNamingStrategy != null ? options.subsegmentNamingStrategy : (context, message) -> context.getListenerIdentifier();
this.subsegmentMutator = options.subsegmentMutator;
this.generateSubsegment = options.generateSubsegment != null ? options.generateSubsegment : true;
}
@Override
public void onPreMessageProcessing(final MessageProcessingContext context, final Message message) {
final Segment segment = recorder.beginSegment(segmentNamingStrategy.getSegmentName(context, message));
final String rawTraceHeader = message.attributes().get(MessageSystemAttributeName.AWS_TRACE_HEADER);
if (rawTraceHeader != null) {
final TraceHeader traceHeader = TraceHeader.fromString(rawTraceHeader);
segment.setTraceId(traceHeader.getRootTraceId());
segment.setParentId(traceHeader.getParentId());
segment.setSampled(traceHeader.getSampled().equals(TraceHeader.SampleDecision.SAMPLED));
}
if (segmentMutator != null) {
segmentMutator.mutateSegment(segment, context, message);
}
context.setAttribute(SEGMENT_CONTEXT_ATTRIBUTE_NAME, segment);
if (generateSubsegment) {
final Subsegment subsegment = recorder.beginSubsegment(subsegmentNamingStrategy.getSubsegmentName(context, message));
if (subsegmentMutator != null) {
subsegmentMutator.mutateSubsegment(subsegment, context, message);
}
context.setAttribute(SUBSEGMENT_CONTEXT_ATTRIBUTE_NAME, subsegment);
recorder.setTraceEnreplacedy(subsegment);
}
}
@Override
public void onMessageProcessingFailure(final MessageProcessingContext context, final Message message, final Throwable throwable) {
final Subsegment subsegment = context.getAttribute(SUBSEGMENT_CONTEXT_ATTRIBUTE_NAME);
if (subsegment != null) {
recorder.setTraceEnreplacedy(subsegment);
subsegment.addException(throwable);
recorder.endSubsegment();
}
final Segment segment = context.getAttribute(SEGMENT_CONTEXT_ATTRIBUTE_NAME);
if (segment != null) {
recorder.setTraceEnreplacedy(segment);
segment.addException(throwable);
recorder.endSegment();
}
recorder.clearTraceEnreplacedy();
}
@Override
public void onMessageProcessingSuccess(final MessageProcessingContext context, final Message message, @Nullable final Object object) {
final Subsegment subsegment = context.getAttribute(SUBSEGMENT_CONTEXT_ATTRIBUTE_NAME);
if (subsegment != null) {
recorder.setTraceEnreplacedy(subsegment);
recorder.endSubsegment();
}
final Segment segment = context.getAttribute(SEGMENT_CONTEXT_ATTRIBUTE_NAME);
if (segment != null) {
recorder.setTraceEnreplacedy(segment);
recorder.endSegment();
}
recorder.clearTraceEnreplacedy();
}
@Override
public void onMessageProcessingThreadComplete(final MessageProcessingContext context, final Message message) {
recorder.clearTraceEnreplacedy();
}
@Value
@Builder
public static clreplaced Options {
/**
* The Xray recorder that will be used to start the segments and subsegments for the message listeners.
*
* <p>If this is not set, the {@link AWSXRay#getGlobalRecorder()} will be used.
*/
AWSXRayRecorder recorder;
/**
* Strategy for naming the Segment that will be started when processing a message.
*
* <p>If this is not set, all segments will have the name {@link #DEFAULT_SEGMENT_NAME}.
*/
DecoratorSegmentNamingStrategy segmentNamingStrategy;
/**
* Optional mutator that can be used to add custom configuration for the segment started.
*/
DecoratorSegmentMutator segmentMutator;
/**
* Whether the message listener should generate a subsegment before executing.
*
* <p>If null, this will default to true.
*/
@Builder.Default
Boolean generateSubsegment = true;
/**
* Strategy for naming the Subsegment that will be started when processing a message.
*
* <p>If this is not set, all subsegments will have the same name as the message listener identifier.
*/
DecoratorSubsegmentNamingStrategy subsegmentNamingStrategy;
/**
* Optional mutator that can be used to add custom configuration for the subsegment started.
*/
DecoratorSubsegmentMutator subsegmentMutator;
}
}
19
Source : XrayWrappedSqsAsyncClient.java
with MIT License
from JaidenAshmore
with MIT License
from JaidenAshmore
/**
* The {@link SqsAsyncClient} that can be used when the Xray Instrumentor has been integrated into the service which will allow you to use the client even
* if it is being called when a segment has not begun.
*
* <p>This client is needed because when the <pre>TracingInterceptor</pre> from the Xray Instrumentor is automatically injected, whenever a call to a client
* is made without a segment being begun an exception will be thrown. This is because the interceptor will try and create a subsegment which is not possible
* if the overall segment hasn't been started. The way that this works with Http Requests is that each request will go through a filter that will start a
* segment for you. However, as the {@link SqsAsyncClient} is being used on separate threads orchestrated by this SQS Library, no segment will have
* automatically been set up for you. As the library does not and should not know about XRay, it would be easier to wrap all calls to the client with some
* safety code instead of littering this segment code in the core library.
*
* <p>This {@link SqsAsyncClient}, on every call, will check if there is a segment already started and if there hasn't been it will start one with the
* name defined by the {@link ClientSegmentNamingStrategy} provided to this.
*/
public clreplaced XrayWrappedSqsAsyncClient implements SqsAsyncClient {
private static final String DEFAULT_SEGMENT_NAME = "message-listener";
private final SqsAsyncClient delegate;
private final AWSXRayRecorder recorder;
private final ClientSegmentNamingStrategy segmentNamingStrategy;
private final ClientSegmentMutator segmentMutator;
public XrayWrappedSqsAsyncClient(final Options options) {
Preconditions.checkNotNull(options.delegate, "delegate must not be null");
this.delegate = options.delegate;
this.recorder = (options.recorder != null) ? options.recorder : AWSXRay.getGlobalRecorder();
this.segmentNamingStrategy = (options.segmentNamingStrategy != null) ? options.segmentNamingStrategy : new StaticClientSegmentNamingStrategy(DEFAULT_SEGMENT_NAME);
this.segmentMutator = options.segmentMutator;
}
@Override
public String serviceName() {
return delegate.serviceName();
}
@Override
public CompletableFuture<AddPermissionResponse> addPermission(final AddPermissionRequest addPermissionRequest) {
return wrapWithXray(delegate::addPermission, addPermissionRequest);
}
@Override
public CompletableFuture<AddPermissionResponse> addPermission(final Consumer<AddPermissionRequest.Builder> addPermissionRequest) {
return wrapWithXray(delegate::addPermission, addPermissionRequest);
}
@Override
public CompletableFuture<ChangeMessageVisibilityResponse> changeMessageVisibility(final ChangeMessageVisibilityRequest changeMessageVisibilityRequest) {
return wrapWithXray(delegate::changeMessageVisibility, changeMessageVisibilityRequest);
}
@Override
public CompletableFuture<ChangeMessageVisibilityResponse> changeMessageVisibility(final Consumer<ChangeMessageVisibilityRequest.Builder> changeMessageVisibilityRequest) {
return wrapWithXray(delegate::changeMessageVisibility, changeMessageVisibilityRequest);
}
@Override
public CompletableFuture<ChangeMessageVisibilityBatchResponse> changeMessageVisibilityBatch(final ChangeMessageVisibilityBatchRequest changeMessageVisibilityBatchRequest) {
return wrapWithXray(delegate::changeMessageVisibilityBatch, changeMessageVisibilityBatchRequest);
}
@Override
public CompletableFuture<ChangeMessageVisibilityBatchResponse> changeMessageVisibilityBatch(final Consumer<ChangeMessageVisibilityBatchRequest.Builder> changeMessageVisibilityBatchRequest) {
return wrapWithXray(delegate::changeMessageVisibilityBatch, changeMessageVisibilityBatchRequest);
}
@Override
public CompletableFuture<CreateQueueResponse> createQueue(final CreateQueueRequest createQueueRequest) {
return wrapWithXray(delegate::createQueue, createQueueRequest);
}
@Override
public CompletableFuture<CreateQueueResponse> createQueue(final Consumer<CreateQueueRequest.Builder> createQueueRequest) {
return wrapWithXray(delegate::createQueue, createQueueRequest);
}
@Override
public CompletableFuture<DeleteMessageResponse> deleteMessage(final DeleteMessageRequest deleteMessageRequest) {
return wrapWithXray(delegate::deleteMessage, deleteMessageRequest);
}
@Override
public CompletableFuture<DeleteMessageResponse> deleteMessage(final Consumer<DeleteMessageRequest.Builder> deleteMessageRequest) {
return wrapWithXray(delegate::deleteMessage, deleteMessageRequest);
}
@Override
public CompletableFuture<DeleteMessageBatchResponse> deleteMessageBatch(final DeleteMessageBatchRequest deleteMessageBatchRequest) {
return wrapWithXray(delegate::deleteMessageBatch, deleteMessageBatchRequest);
}
@Override
public CompletableFuture<DeleteMessageBatchResponse> deleteMessageBatch(final Consumer<DeleteMessageBatchRequest.Builder> deleteMessageBatchRequest) {
return wrapWithXray(delegate::deleteMessageBatch, deleteMessageBatchRequest);
}
@Override
public CompletableFuture<DeleteQueueResponse> deleteQueue(final DeleteQueueRequest deleteQueueRequest) {
return wrapWithXray(delegate::deleteQueue, deleteQueueRequest);
}
@Override
public CompletableFuture<DeleteQueueResponse> deleteQueue(final Consumer<DeleteQueueRequest.Builder> deleteQueueRequest) {
return wrapWithXray(delegate::deleteQueue, deleteQueueRequest);
}
@Override
public CompletableFuture<GetQueueAttributesResponse> getQueueAttributes(final GetQueueAttributesRequest getQueueAttributesRequest) {
return wrapWithXray(delegate::getQueueAttributes, getQueueAttributesRequest);
}
@Override
public CompletableFuture<GetQueueAttributesResponse> getQueueAttributes(final Consumer<GetQueueAttributesRequest.Builder> getQueueAttributesRequest) {
return wrapWithXray(delegate::getQueueAttributes, getQueueAttributesRequest);
}
@Override
public CompletableFuture<GetQueueUrlResponse> getQueueUrl(GetQueueUrlRequest getQueueUrlRequest) {
return wrapWithXray(delegate::getQueueUrl, getQueueUrlRequest);
}
@Override
public CompletableFuture<GetQueueUrlResponse> getQueueUrl(final Consumer<GetQueueUrlRequest.Builder> getQueueUrlRequest) {
return wrapWithXray(delegate::getQueueUrl, getQueueUrlRequest);
}
@Override
public CompletableFuture<ListDeadLetterSourceQueuesResponse> listDeadLetterSourceQueues(final ListDeadLetterSourceQueuesRequest listDeadLetterSourceQueuesRequest) {
return wrapWithXray(delegate::listDeadLetterSourceQueues, listDeadLetterSourceQueuesRequest);
}
@Override
public CompletableFuture<ListDeadLetterSourceQueuesResponse> listDeadLetterSourceQueues(final Consumer<ListDeadLetterSourceQueuesRequest.Builder> listDeadLetterSourceQueuesRequest) {
return wrapWithXray(delegate::listDeadLetterSourceQueues, listDeadLetterSourceQueuesRequest);
}
@Override
public CompletableFuture<ListQueueTagsResponse> listQueueTags(final ListQueueTagsRequest listQueueTagsRequest) {
return wrapWithXray(delegate::listQueueTags, listQueueTagsRequest);
}
@Override
public CompletableFuture<ListQueueTagsResponse> listQueueTags(final Consumer<ListQueueTagsRequest.Builder> listQueueTagsRequest) {
return wrapWithXray(delegate::listQueueTags, listQueueTagsRequest);
}
@Override
public CompletableFuture<ListQueuesResponse> listQueues(final ListQueuesRequest listQueuesRequest) {
return wrapWithXray(delegate::listQueues, listQueuesRequest);
}
@Override
public CompletableFuture<ListQueuesResponse> listQueues(final Consumer<ListQueuesRequest.Builder> listQueuesRequest) {
return wrapWithXray(delegate::listQueues, listQueuesRequest);
}
@Override
public CompletableFuture<ListQueuesResponse> listQueues() {
return wrapWithXray(delegate::listQueues);
}
@Override
public CompletableFuture<PurgeQueueResponse> purgeQueue(final PurgeQueueRequest purgeQueueRequest) {
return wrapWithXray(delegate::purgeQueue, purgeQueueRequest);
}
@Override
public CompletableFuture<PurgeQueueResponse> purgeQueue(final Consumer<PurgeQueueRequest.Builder> purgeQueueRequest) {
return wrapWithXray(delegate::purgeQueue, purgeQueueRequest);
}
@Override
public CompletableFuture<ReceiveMessageResponse> receiveMessage(final ReceiveMessageRequest receiveMessageRequest) {
return wrapWithXray(delegate::receiveMessage, receiveMessageRequest);
}
@Override
public CompletableFuture<ReceiveMessageResponse> receiveMessage(final Consumer<ReceiveMessageRequest.Builder> receiveMessageRequest) {
return wrapWithXray(delegate::receiveMessage, receiveMessageRequest);
}
@Override
public CompletableFuture<RemovePermissionResponse> removePermission(final RemovePermissionRequest removePermissionRequest) {
return wrapWithXray(delegate::removePermission, removePermissionRequest);
}
@Override
public CompletableFuture<RemovePermissionResponse> removePermission(final Consumer<RemovePermissionRequest.Builder> removePermissionRequest) {
return wrapWithXray(delegate::removePermission, removePermissionRequest);
}
@Override
public CompletableFuture<SendMessageResponse> sendMessage(final SendMessageRequest sendMessageRequest) {
return wrapWithXray(delegate::sendMessage, sendMessageRequest);
}
@Override
public CompletableFuture<SendMessageResponse> sendMessage(final Consumer<SendMessageRequest.Builder> sendMessageRequest) {
return wrapWithXray(delegate::sendMessage, sendMessageRequest);
}
@Override
public CompletableFuture<SendMessageBatchResponse> sendMessageBatch(final SendMessageBatchRequest sendMessageBatchRequest) {
return wrapWithXray(delegate::sendMessageBatch, sendMessageBatchRequest);
}
@Override
public CompletableFuture<SendMessageBatchResponse> sendMessageBatch(final Consumer<SendMessageBatchRequest.Builder> sendMessageBatchRequest) {
return wrapWithXray(delegate::sendMessageBatch, sendMessageBatchRequest);
}
@Override
public CompletableFuture<SetQueueAttributesResponse> setQueueAttributes(final SetQueueAttributesRequest setQueueAttributesRequest) {
return wrapWithXray(delegate::setQueueAttributes, setQueueAttributesRequest);
}
@Override
public CompletableFuture<SetQueueAttributesResponse> setQueueAttributes(final Consumer<SetQueueAttributesRequest.Builder> setQueueAttributesRequest) {
return wrapWithXray(delegate::setQueueAttributes, setQueueAttributesRequest);
}
@Override
public CompletableFuture<TagQueueResponse> tagQueue(final TagQueueRequest tagQueueRequest) {
return wrapWithXray(delegate::tagQueue, tagQueueRequest);
}
@Override
public CompletableFuture<TagQueueResponse> tagQueue(final Consumer<TagQueueRequest.Builder> tagQueueRequest) {
return wrapWithXray(delegate::tagQueue, tagQueueRequest);
}
@Override
public CompletableFuture<UntagQueueResponse> untagQueue(final UntagQueueRequest untagQueueRequest) {
return wrapWithXray(delegate::untagQueue, untagQueueRequest);
}
@Override
public CompletableFuture<UntagQueueResponse> untagQueue(final Consumer<UntagQueueRequest.Builder> untagQueueRequest) {
return wrapWithXray(delegate::untagQueue, untagQueueRequest);
}
/**
* Will wrap the underlying code with a segment if one has not already been started.
*
* @param function the code to wrap with an Xray segment
* @param <P> the type of argument being preplaceded to the function
* @param <M> the return type of the underlying code
* @return the value returned by the underling code
*/
private <P, M> M wrapWithXray(final Function<P, M> function, final P argument) {
return wrapWithXray(() -> function.apply(argument));
}
/**
* Will wrap the underlying code with a segment if one has not already been started.
*
* @param supplier the code to wrap with an Xray segment
* @return the value returned by the underling code
*/
private <M> M wrapWithXray(final Supplier<M> supplier) {
final Optional<Segment> optionalSegment = recorder.getCurrentSegmentOptional();
try {
if (!optionalSegment.isPresent()) {
final Segment segment = recorder.beginSegment(segmentNamingStrategy.getSegmentName());
if (segmentMutator != null) {
segmentMutator.mutateSegment(segment);
}
}
return supplier.get();
} finally {
if (!optionalSegment.isPresent()) {
recorder.endSegment();
}
}
}
@Override
public void close() {
delegate.close();
}
@Value
@Builder
public static clreplaced Options {
/**
* Delegate client that will make the underlying calls to the SQS queues.
*/
SqsAsyncClient delegate;
/**
* The Xray recorder that will be used to start the segments and subsegments for the message listeners.
*
* <p>If this is not set, the {@link AWSXRay#getGlobalRecorder()} will be used.
*/
AWSXRayRecorder recorder;
/**
* Strategy for naming the Segment that will be started when processing a message.
*
* <p>If this is not set, all segments will have the name {@link #DEFAULT_SEGMENT_NAME}.
*/
ClientSegmentNamingStrategy segmentNamingStrategy;
/**
* Optional mutator that can be used to add custom configuration for the segment started.
*/
ClientSegmentMutator segmentMutator;
}
}
19
Source : MainRunner.java
with The Unlicense
from diegopacheco
with The Unlicense
from diegopacheco
public clreplaced MainRunner {
private static SegmentNamingStrategy segmentNamingStrategy;
private static AWSXRayRecorder recorder = AWSXRay.getGlobalRecorder();
static {
AWSXRayRecorderBuilder builder = AWSXRayRecorderBuilder.standard().withPlugin(new EC2Plugin());
URL ruleFile = MainRunner.clreplaced.getResource("/sampling-rules.json");
builder.withSamplingStrategy(new LocalizedSamplingStrategy(ruleFile));
AWSXRay.setGlobalRecorder(builder.build());
segmentNamingStrategy = new FixedSegmentNamingStrategy("aws-xray-poc");
}
public static void approachA() throws Exception {
String segmentName = segmentNamingStrategy.nameForRequest(null);
Segment segment = recorder.beginSegment(segmentName, new TraceID(), null);
Thread.sleep(2000);
if (segment.end()) {
recorder.sendSegment(segment);
}
System.out.println("Approach A - DONE");
}
public static void approachB() throws Exception {
String segmentName = segmentNamingStrategy.nameForRequest(null) + "-b";
Segment segment = recorder.beginSegment(segmentName, new TraceID(), null);
Thread.sleep(2000);
CloseableHttpClient httpclient = HttpClientBuilder.create().build();
HttpGet httpGet = new HttpGet("http://google.com/");
CloseableHttpResponse response = httpclient.execute(httpGet);
try {
HttpEnreplacedy enreplacedy = response.getEnreplacedy();
System.out.println(enreplacedy);
} finally {
response.close();
}
if (segment.end()) {
recorder.sendSegment(segment);
}
System.out.println("Approach B - DONE");
}
public static void approachC() throws Exception {
String segmentName = segmentNamingStrategy.nameForRequest(null) + "-C";
Segment segment = recorder.beginSegment(segmentName, new TraceID(), null);
Thread.sleep(2000);
Subsegment subsegment = AWSXRay.beginSubsegment("Twitter");
subsegment.setNamespace("remote");
Thread.sleep(1000);
Subsegment subsegment2 = AWSXRay.beginSubsegment("Github");
subsegment2.setNamespace("remote");
Thread.sleep(1000);
AWSXRay.endSubsegment();
AWSXRay.endSubsegment();
if (segment.end()) {
recorder.sendSegment(segment);
}
System.out.println("Approach C - DONE");
}
public static void approachD() throws Exception {
Segment s = AWSXRay.beginSegment("Facebook");
s.setNamespace("remote");
Thread.sleep(1000);
AWSXRay.endSegment();
System.out.println("Approach D - DONE");
}
public static void main(String[] args) {
try {
approachA();
approachB();
approachC();
approachD();
} catch (Exception e) {
e.printStackTrace();
}
}
}
19
Source : EntitySpanTest.java
with Apache License 2.0
from awslabs
with Apache License 2.0
from awslabs
@ExtendWith(MockitoExtension.clreplaced)
public clreplaced EnreplacedySpanTest {
@Mock
AWSXRayRecorder recorder;
@Mock
Segment segment;
@Mock
Subsegment subsegment;
@Mock
Segment previousSegment;
@Test
public void when_aSegmentIsCreatedAndEnded_then_theCurrentEnreplacedyIsPreserved() {
when(recorder.beginSegment(anyString())).thenReturn(segment);
when(recorder.getTraceEnreplacedy()).thenReturn(previousSegment);
when(segment.getCreator()).thenReturn(recorder);
when(segment.isInProgress()).thenReturn(true);
Span testSpan = EnreplacedySpan.beginSegment(recorder, "Test Span", 0, Span.Kind.INTERNAL);
testSpan.end();
// Verify Order of Operations
InOrder inOrder = inOrder(recorder);
// Create new span
inOrder.verify(recorder).getTraceEnreplacedy();
inOrder.verify(recorder).beginSegment(anyString());
inOrder.verify(recorder).setTraceEnreplacedy(previousSegment);
// End span
inOrder.verify(recorder).getTraceEnreplacedy();
inOrder.verify(recorder).setTraceEnreplacedy(segment);
inOrder.verify(recorder).endSegment();
inOrder.verify(recorder).setTraceEnreplacedy(previousSegment);
inOrder.verifyNoMoreInteractions();
}
@Test
public void when_aSegmentExists_then_aSubsegemtnIsCreated() {
EnreplacedySpan parentSpan = mock(EnreplacedySpan.clreplaced);
when(parentSpan.getXrayEnreplacedy()).thenReturn(segment);
when(subsegment.getCreator()).thenReturn(recorder);
when(recorder.getTraceEnreplacedy()).thenReturn(previousSegment);
when(recorder.beginSubsegment(anyString())).thenReturn(subsegment);
when(subsegment.isInProgress()).thenReturn(true);
Span subsegmentSpan = EnreplacedySpan.beginSubsegment(recorder, "Test Child", parentSpan, 0, Span.Kind.INTERNAL);
subsegmentSpan.end();
// Verify Order of Operations
InOrder inOrder = inOrder(recorder);
// Create new subsegment
inOrder.verify(recorder).getTraceEnreplacedy();
inOrder.verify(recorder).setTraceEnreplacedy(segment);
inOrder.verify(recorder).beginSubsegment(anyString());
inOrder.verify(recorder).setTraceEnreplacedy(previousSegment);
// End span
inOrder.verify(recorder).getTraceEnreplacedy();
inOrder.verify(recorder).setTraceEnreplacedy(subsegment);
inOrder.verify(recorder).endSubsegment();
inOrder.verify(recorder).setTraceEnreplacedy(previousSegment);
inOrder.verifyNoMoreInteractions();
}
@Test
public void when_aSegmentHasHttpParams_then_segmentHasHttpBlock() {
when(recorder.beginSegment(anyString())).thenReturn(segment);
Span testSpan = EnreplacedySpan.beginSegment(recorder, "Test Span", 0, Span.Kind.INTERNAL);
testSpan.setAttribute("http.method", "GET");
testSpan.setAttribute("http.status_code", 200L);
testSpan.setAttribute("http.url", "http://test.com");
testSpan.end();
verify(segment, times(2)).putHttp(eq("request"), any(Map.clreplaced));
verify(segment).putHttp(eq("response"), any(Map.clreplaced));
}
@Test
public void when_isRecordingCalled_then_isInProgressCalled() {
when(recorder.beginSegment(anyString())).thenReturn(segment);
when(segment.isInProgress()).thenReturn(false);
Span testSpan = EnreplacedySpan.beginSegment(recorder, "Test Span", 0, Span.Kind.INTERNAL);
replacedertEquals(false, testSpan.isRecording());
}
}
19
Source : RecorderBackedTracerFactory.java
with Apache License 2.0
from awslabs
with Apache License 2.0
from awslabs
/**
* A factory for creating RecorderBackedTracers.
*
* @see io.opentelemetry.trace.Tracer
*/
public clreplaced RecorderBackedTracerFactory implements TracerFactory {
private final AWSXRayRecorder recorder;
private RecorderBackedTracer tracer = null;
private RecorderBackedTracerFactory(AWSXRayRecorder recorder) {
this.recorder = recorder;
}
/**
* Create a new tracer factory.
*
* @return the factory
*/
public static final RecorderBackedTracerFactory create() {
return new RecorderBackedTracerFactory(AWSXRay.getGlobalRecorder());
}
@Override
public Tracer get(final String instrumentationName) {
return get(instrumentationName, null);
}
@Override
public Tracer get(final String instrumentationName, final String instrumentationVersion) {
if (tracer == null) {
synchronized (this) {
if (tracer == null) {
tracer = RecorderBackedTracer.fromRecorder(recorder);
}
}
}
return tracer;
}
}
19
Source : RecorderBackedTracer.java
with Apache License 2.0
from awslabs
with Apache License 2.0
from awslabs
/**
* A tracer backed by an AWS X-Ray recorder.
*
* @see io.opentelemetry.trace.Tracer
*/
public clreplaced RecorderBackedTracer implements Tracer {
private static final HttpTraceContext HTTP_TRACE_CONTEXT = new HttpTraceContext();
private AWSXRayRecorder recorder;
private Span currentSpan = null;
private Enreplacedy currentEnreplacedy = null;
private RecorderBackedTracer(AWSXRayRecorder recorder) {
this.recorder = recorder;
}
/**
* Create a tracer using a given recorder.
*
* @param recorder the recorder
* @return a tracer
*/
public static RecorderBackedTracer fromRecorder(AWSXRayRecorder recorder) {
return new RecorderBackedTracer(recorder);
}
/**
* {@inheritDoc} This implementation will automatically update the active span based on changes to
* the X-Ray recorder but otherwise conforms to OpenTelemetry semantics when creating spans.
*/
@Override
public Span getCurrentSpan() {
if (currentSpan == null && recorder.getTraceEnreplacedy() == null) {
return DefaultSpan.getInvalid();
} else {
// Reflect the recorder's current enreplacedy changing in response to X-Ray calls
Enreplacedy recorderCurrentEnreplacedy = recorder.getTraceEnreplacedy();
if (recorderCurrentEnreplacedy != null && !recorderCurrentEnreplacedy.equals(currentEnreplacedy)) {
currentEnreplacedy = recorderCurrentEnreplacedy;
currentSpan = EnreplacedySpan.fromEnreplacedy(currentEnreplacedy);
}
}
return currentSpan;
}
@Override
public Scope withSpan(final Span span) {
if (span instanceof EnreplacedySpan) {
final EnreplacedySpan adapter = (EnreplacedySpan) span;
currentSpan = span;
recorder.setTraceEnreplacedy(adapter.getXrayEnreplacedy());
}
// Just a rough implementation. There's some talk of separating scope management from
// existing gRPC influenced deps. Need to better integrate this and X-Ray Recorder's
// scope management.
return new Scope() {
@Override
public void close() {
}
};
}
@Override
public Span.Builder spanBuilder(final String name) {
return EnreplacedySpanBuilder.create(name, recorder, getCurrentSpan());
}
@Override
public BinaryFormat<SpanContext> getBinaryFormat() {
return null;
}
@Override
public HttpTextFormat<SpanContext> getHttpTextFormat() {
return HTTP_TRACE_CONTEXT;
}
}
19
Source : RecorderBackedTracer.java
with Apache License 2.0
from awslabs
with Apache License 2.0
from awslabs
/**
* Create a tracer using a given recorder.
*
* @param recorder the recorder
* @return a tracer
*/
public static RecorderBackedTracer fromRecorder(AWSXRayRecorder recorder) {
return new RecorderBackedTracer(recorder);
}
19
Source : EntitySpanBuilder.java
with Apache License 2.0
from awslabs
with Apache License 2.0
from awslabs
/**
* A builder clreplaced which creates spans against a given X-Ray recorder.
*
* @see io.opentelemetry.trace.Span.Builder
*/
public clreplaced EnreplacedySpanBuilder implements Span.Builder {
private final AWSXRayRecorder recorder;
private final String name;
private SpanContext parentContext;
private Span parentSpan;
private Span.Kind kind = Span.Kind.INTERNAL;
private long startTimestamp;
private EnreplacedySpanBuilder(final String name, final AWSXRayRecorder recorder, final Span currentSpan) {
this.name = name;
this.recorder = recorder;
this.parentSpan = currentSpan;
}
/**
* Create a factory using the given recorder.
*
* @param name the name of the span to create
* @param recorder the recorder to use
* @param currentSpan the current span or null
* @return the builder
*/
public static EnreplacedySpanBuilder create(final String name, final AWSXRayRecorder recorder, final Span currentSpan) {
return new EnreplacedySpanBuilder(name, recorder, currentSpan);
}
@Override
public Span.Builder setParent(final Span span) {
this.parentSpan = span;
this.parentContext = null;
return this;
}
@Override
public Span.Builder setParent(final SpanContext spanContext) {
this.parentContext = spanContext;
this.parentSpan = null;
return this;
}
@Override
public Span.Builder setNoParent() {
parentContext = null;
parentSpan = null;
return this;
}
/*
* Segment linking is not supported by X-Ray
*/
@Override
public Span.Builder addLink(final SpanContext spanContext) {
return this;
}
@Override
public Span.Builder addLink(final SpanContext spanContext, final Map<String, AttributeValue> map) {
return this;
}
@Override
public Span.Builder addLink(final Link link) {
return this;
}
@Override
public Span.Builder setSpanKind(final Span.Kind kind) {
this.kind = kind;
return this;
}
@Override
public Span.Builder setStartTimestamp(final long startTimestamp) {
this.startTimestamp = startTimestamp;
return this;
}
@Override
public Span startSpan() {
if (startTimestamp == 0) {
startTimestamp = TimeUtils.getCurrentNanoTime();
}
if (parentContext != null || parentSpan == null) {
return EnreplacedySpan.beginSegment(recorder, name, startTimestamp, kind);
} else {
return EnreplacedySpan.beginSubsegment(recorder, name, (EnreplacedySpan) parentSpan, startTimestamp, kind);
}
}
}
19
Source : EntitySpanBuilder.java
with Apache License 2.0
from awslabs
with Apache License 2.0
from awslabs
/**
* Create a factory using the given recorder.
*
* @param name the name of the span to create
* @param recorder the recorder to use
* @param currentSpan the current span or null
* @return the builder
*/
public static EnreplacedySpanBuilder create(final String name, final AWSXRayRecorder recorder, final Span currentSpan) {
return new EnreplacedySpanBuilder(name, recorder, currentSpan);
}
19
Source : BaseAbstractXRayInterceptorTest.java
with Apache License 2.0
from aws
with Apache License 2.0
from aws
public clreplaced BaseAbstractXRayInterceptorTest {
@Rule
public MockitoRule mocks = MockitoJUnit.rule();
static clreplaced ImplementedXRayInterceptor extends BaseAbstractXRayInterceptor {
@Override
protected void xrayEnabledClreplacedes() {
}
}
private BaseAbstractXRayInterceptor xRayInterceptor = new ImplementedXRayInterceptor();
@Mock
private AWSXRayRecorder mockRecorder;
@Mock
private ProceedingJoinPoint mockPjp;
@Mock
private Signature mockSignature;
@Before
public void setup() {
AWSXRay.setGlobalRecorder(mockRecorder);
when(mockPjp.getArgs()).thenReturn(new Object[] {});
when(mockPjp.getSignature()).thenReturn(mockSignature);
when(mockSignature.getName()).thenReturn("testSpringName");
}
@Test
public void testNullSegmentOnProcessFailure() throws Throwable {
// Test to ensure that getCurrentSegment()/getCurrentSegmentOptional() don't throw NPEs when customers are using
// the Log context missing strategy during the processXRayTrace call.
Exception expectedException = new RuntimeException("An intended exception");
// Cause an intended exception to be thrown so that getCurrentSegmentOptional() is called.
when(mockRecorder.beginSubsegment(any())).thenThrow(expectedException);
when(mockRecorder.getCurrentSegmentOptional()).thenReturn(Optional.empty());
when(mockRecorder.getCurrentSegment()).thenReturn(null);
try {
xRayInterceptor.processXRayTrace(mockPjp);
} catch (Exception e) {
// A null pointer exception here could potentially indicate that a call to getCurrentSegment() is returning null.
// i.e. there is another exception other than our intended exception that is thrown that's not supposed to be thrown.
replacedertNotEquals(NullPointerException.clreplaced, e.getClreplaced());
replacedertEquals(expectedException.getMessage(), e.getMessage());
}
}
@Test
public void testSegmentOnProcessFailure() throws Throwable {
// Test to ensure that the exception is populated to the segment when an error occurs during the
// processXRayTrace call.
Exception expectedException = new RuntimeException("An intended exception");
// Cause an intended exception to be thrown so that getCurrentSegmentOptional() is called.
when(mockRecorder.beginSubsegment(any())).thenThrow(expectedException);
Segment mockSegment = mock(Segment.clreplaced);
when(mockRecorder.getCurrentSegmentOptional()).thenReturn(Optional.of(mockSegment));
when(mockRecorder.getCurrentSegment()).thenReturn(mockSegment);
try {
xRayInterceptor.processXRayTrace(mockPjp);
} catch (Exception e) {
verify(mockSegment).addException(expectedException);
}
}
}
19
Source : SegmentContextExecutorsTest.java
with Apache License 2.0
from aws
with Apache License 2.0
from aws
public clreplaced SegmentContextExecutorsTest {
private static ExecutorService backgroundExecutor;
@Rule
public MockitoRule mocks = MockitoJUnit.rule();
@Mock
private volatile AWSXRayRecorder recorder;
@Spy
private volatile Segment current;
@Spy
private volatile Segment manual;
@Spy
private volatile Segment previous;
@BeforeClreplaced
public static void startBackgroundExecutor() {
backgroundExecutor = Executors.newSingleThreadExecutor();
}
@AfterClreplaced
public static void stopBackgroundExecutor() {
backgroundExecutor.shutdown();
}
@Before
public void setUp() {
when(recorder.getTraceEnreplacedy()).thenAnswer(invocation -> ThreadLocalStorage.get());
when(recorder.getCurrentSegmentOptional()).thenAnswer(invocation -> Optional.of(ThreadLocalStorage.get()));
doAnswer(invocation -> {
ThreadLocalStorage.set(invocation.getArgument(0));
return null;
}).when(recorder).setTraceEnreplacedy(any());
recorder.setTraceEnreplacedy(current);
AWSXRay.setGlobalRecorder(recorder);
}
@After
public void tearDown() {
recorder.setTraceEnreplacedy(null);
}
@Test
public void currentSegmentExecutor() {
runSegmentExecutorTest(SegmentContextExecutors.newSegmentContextExecutor(), current);
}
@Test
public void segmentExecutor() {
runSegmentExecutorTest(SegmentContextExecutors.newSegmentContextExecutor(manual), manual);
}
@Test
public void segmentAndRecorderExecutor() {
runSegmentExecutorTest(SegmentContextExecutors.newSegmentContextExecutor(recorder, manual), manual);
}
private void runSegmentExecutorTest(Executor segmentExecutor, Segment mounted) {
replacedertThat(recorder.getTraceEnreplacedy()).isEqualTo(current);
CountDownLatch ready = new CountDownLatch(1);
AtomicReference<Thread> backgroundThread = new AtomicReference<>();
CompletableFuture<?> future = CompletableFuture.supplyAsync(() -> {
backgroundThread.set(Thread.currentThread());
recorder.setTraceEnreplacedy(previous);
try {
// We need to make sure callbacks are registered before we complete this future or else the callbacks will
// be called inline on the main thread (the one that registers them).
ready.await(10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
throw new IllegalStateException();
}
return null;
}, backgroundExecutor).thenAcceptAsync(unused -> {
// Sanity check our test is actually on a different thread.
replacedertThat(Thread.currentThread()).isEqualTo(backgroundThread.get());
replacedertThat(recorder.getTraceEnreplacedy()).isEqualTo(mounted);
}, segmentExecutor).thenAcceptAsync(unused -> {
replacedertThat(Thread.currentThread()).isEqualTo(backgroundThread.get());
replacedertThat(recorder.getTraceEnreplacedy()).isEqualTo(previous);
}, backgroundExecutor);
ready.countDown();
future.join();
replacedertThat(recorder.getTraceEnreplacedy()).isEqualTo(current);
}
}
19
Source : AWSXRayServletFilter.java
with Apache License 2.0
from aws
with Apache License 2.0
from aws
public clreplaced AWSXRayServletFilter implements javax.servlet.Filter {
private static final Log logger = LogFactory.getLog(AWSXRayServletFilter.clreplaced);
@Nullable
private String segmentOverrideName;
@Nullable
private String segmentDefaultName;
@MonotonicNonNull
private SegmentNamingStrategy segmentNamingStrategy;
@MonotonicNonNull
private AWSXRayRecorder recorder;
private final AWSXRayServletAsyncListener listener;
/**
* Warning: this no-args constructor should not be used directly. This constructor is made available for use from within
* {@code web.xml} and other declarative file-based instantiations.
*/
public AWSXRayServletFilter() {
this((SegmentNamingStrategy) null);
}
public AWSXRayServletFilter(String fixedSegmentName) {
this(new FixedSegmentNamingStrategy(fixedSegmentName));
}
public AWSXRayServletFilter(@Nullable SegmentNamingStrategy segmentNamingStrategy) {
this(segmentNamingStrategy, null);
}
// TODO(anuraaga): Better define lifecycle relationship between this listener and the filter.
@SuppressWarnings("nullness")
public AWSXRayServletFilter(@Nullable SegmentNamingStrategy segmentNamingStrategy, @Nullable AWSXRayRecorder recorder) {
// Will be configured by web.xml otherwise.
if (segmentNamingStrategy != null) {
this.segmentNamingStrategy = segmentNamingStrategy;
}
// Will be configured by web.xml otherwise.
if (recorder != null) {
this.recorder = recorder;
}
this.listener = new AWSXRayServletAsyncListener(this, recorder);
}
/**
* @return the segmentOverrideName
*/
@Nullable
public String getSegmentOverrideName() {
return segmentOverrideName;
}
/**
* @param segmentOverrideName
* the segmentOverrideName to set
*/
public void setSegmentOverrideName(String segmentOverrideName) {
this.segmentOverrideName = segmentOverrideName;
}
/**
* @return the segmentDefaultName
*/
@Nullable
public String getSegmentDefaultName() {
return segmentDefaultName;
}
/**
* @param segmentDefaultName
* the segmentDefaultName to set
*/
public void setSegmentDefaultName(String segmentDefaultName) {
this.segmentDefaultName = segmentDefaultName;
}
/**
* @param config
* the filter configuration. There are various init-params which may be preplaceded on initialization. The values in init-params
* will create segment naming strategies which override those preplaceded in constructors.
*
* <ul>
*
* <li>
* <b>fixedName</b> A String value used as the fixedName parameter for a created
* {@link com.amazonaws.xray.strategy.FixedSegmentNamingStrategy}. Used only if the {@code dynamicNamingFallbackName}
* init-param is not set.
* </li>
*
* <li>
* <b>dynamicNamingFallbackName</b> A String value used as the fallbackName parameter for a created
* {@link com.amazonaws.xray.strategy.DynamicSegmentNamingStrategy}.
* </li>
*
* <li>
* <b>dynamicNamingRecognizedHosts</b> A String value used as the recognizedHosts parameter for a created
* {@link com.amazonaws.xray.strategy.DynamicSegmentNamingStrategy}.
* </li>
*
* </ul>
*
* @throws ServletException
* when a segment naming strategy is not provided in constructor arguments nor in init-params.
*/
@Override
public void init(FilterConfig config) throws ServletException {
String fixedName = config.getInitParameter("fixedName");
String dynamicNamingFallbackName = config.getInitParameter("dynamicNamingFallbackName");
String dynamicNamingRecognizedHosts = config.getInitParameter("dynamicNamingRecognizedHosts");
if (StringValidator.isNotNullOrBlank(dynamicNamingFallbackName)) {
if (StringValidator.isNotNullOrBlank(dynamicNamingRecognizedHosts)) {
segmentNamingStrategy = new DynamicSegmentNamingStrategy(dynamicNamingFallbackName, dynamicNamingRecognizedHosts);
} else {
segmentNamingStrategy = new DynamicSegmentNamingStrategy(dynamicNamingFallbackName);
}
} else if (StringValidator.isNotNullOrBlank(fixedName)) {
segmentNamingStrategy = new FixedSegmentNamingStrategy(fixedName);
} else if (null == segmentNamingStrategy) {
throw new ServletException("The AWSXRayServletFilter requires either a fixedName init-param or an instance of SegmentNamingStrategy. " + "Add an init-param tag to the AWSXRayServletFilter's declaration in web.xml, using param-name: 'fixedName'. " + "Alternatively, preplaced an instance of SegmentNamingStrategy to the AWSXRayServletFilter constructor.");
}
}
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
if (logger.isDebugEnabled()) {
logger.debug("AWSXRayServletFilter is beginning to process request: " + request.toString());
}
Segment segment = preFilter(request, response);
try {
chain.doFilter(request, response);
} catch (Throwable e) {
segment.addException(e);
throw e;
} finally {
if (request.isAsyncStarted()) {
request.setAttribute(AWSXRayServletAsyncListener.ENreplacedY_ATTRIBUTE_KEY, segment);
try {
request.getAsyncContext().addListener(listener);
if (recorder != null) {
recorder.clearTraceEnreplacedy();
}
} catch (IllegalStateException ise) {
// race condition that occurs when async processing finishes before adding the listener
postFilter(request, response);
}
} else {
postFilter(request, response);
}
if (logger.isDebugEnabled()) {
logger.debug("AWSXRayServletFilter is finished processing request: " + request.toString());
}
}
}
@Nullable
private HttpServletRequest castServletRequest(ServletRequest request) {
try {
return (HttpServletRequest) request;
} catch (ClreplacedCastException cce) {
logger.warn("Unable to cast ServletRequest to HttpServletRequest.", cce);
}
return null;
}
@Nullable
private HttpServletResponse castServletResponse(ServletResponse response) {
try {
return (HttpServletResponse) response;
} catch (ClreplacedCastException cce) {
logger.warn("Unable to cast ServletResponse to HttpServletResponse.", cce);
}
return null;
}
private Optional<TraceHeader> getTraceHeader(HttpServletRequest request) {
String traceHeaderString = request.getHeader(TraceHeader.HEADER_KEY);
if (null != traceHeaderString) {
return Optional.of(TraceHeader.fromString(traceHeaderString));
}
return Optional.empty();
}
private Optional<String> getHost(HttpServletRequest request) {
return Optional.ofNullable(request.getHeader("Host"));
}
private Optional<String> getClientIp(HttpServletRequest request) {
return Optional.ofNullable(request.getRemoteAddr());
}
private Optional<String> getXForwardedFor(HttpServletRequest request) {
String forwarded = request.getHeader("X-Forwarded-For");
if (forwarded != null) {
return Optional.of(forwarded.split(",")[0].trim());
}
return Optional.empty();
}
private Optional<String> getUserAgent(HttpServletRequest request) {
String userAgentHeaderString = request.getHeader("User-Agent");
if (null != userAgentHeaderString) {
return Optional.of(userAgentHeaderString);
}
return Optional.empty();
}
private Optional<Integer> getContentLength(HttpServletResponse response) {
String contentLengthString = response.getHeader("Content-Length");
if (null != contentLengthString && !contentLengthString.isEmpty()) {
try {
return Optional.of(Integer.parseInt(contentLengthString));
} catch (NumberFormatException nfe) {
logger.debug("Unable to parse Content-Length header from HttpServletResponse.", nfe);
}
}
return Optional.empty();
}
private String getSegmentName(HttpServletRequest httpServletRequest) {
if (segmentNamingStrategy == null) {
throw new RuntimeException("The AWSXRayServletFilter requires either a fixedName init-param or an instance of SegmentNamingStrategy. " + "Add an init-param tag to the AWSXRayServletFilter's declaration in web.xml, using param-name: 'fixedName'. " + "Alternatively, preplaced an instance of SegmentNamingStrategy to the AWSXRayServletFilter constructor.");
}
return segmentNamingStrategy.nameForRequest(httpServletRequest);
}
private SamplingResponse fromSamplingStrategy(HttpServletRequest httpServletRequest) {
AWSXRayRecorder recorder = getRecorder();
SamplingRequest samplingRequest = new SamplingRequest(getSegmentName(httpServletRequest), getHost(httpServletRequest).orElse(null), httpServletRequest.getRequestURI(), httpServletRequest.getMethod(), recorder.getOrigin());
SamplingResponse sample = recorder.getSamplingStrategy().shouldTrace(samplingRequest);
return sample;
}
private SampleDecision getSampleDecision(SamplingResponse sample) {
if (sample.isSampled()) {
logger.debug("Sampling strategy decided SAMPLED.");
return SampleDecision.SAMPLED;
} else {
logger.debug("Sampling strategy decided NOT_SAMPLED.");
return SampleDecision.NOT_SAMPLED;
}
}
private AWSXRayRecorder getRecorder() {
if (recorder == null) {
recorder = AWSXRay.getGlobalRecorder();
}
return recorder;
}
public Segment preFilter(ServletRequest request, ServletResponse response) {
AWSXRayRecorder recorder = getRecorder();
HttpServletRequest httpServletRequest = castServletRequest(request);
if (httpServletRequest == null) {
logger.warn("Null value for incoming HttpServletRequest. Beginning NoOpSegment.");
return recorder.beginNoOpSegment();
}
Optional<TraceHeader> incomingHeader = getTraceHeader(httpServletRequest);
SamplingStrategy samplingStrategy = recorder.getSamplingStrategy();
if (logger.isDebugEnabled() && incomingHeader.isPresent()) {
logger.debug("Incoming trace header received: " + incomingHeader.get().toString());
}
SamplingResponse samplingResponse = fromSamplingStrategy(httpServletRequest);
SampleDecision sampleDecision = incomingHeader.isPresent() ? incomingHeader.get().getSampled() : getSampleDecision(samplingResponse);
if (SampleDecision.REQUESTED.equals(sampleDecision) || SampleDecision.UNKNOWN.equals(sampleDecision)) {
sampleDecision = getSampleDecision(samplingResponse);
}
TraceID traceId = null;
String parentId = null;
if (incomingHeader.isPresent()) {
TraceHeader header = incomingHeader.get();
traceId = header.getRootTraceId();
parentId = header.getParentId();
}
final Segment created;
if (SampleDecision.SAMPLED.equals(sampleDecision)) {
String segmentName = getSegmentName(httpServletRequest);
created = traceId != null ? recorder.beginSegment(segmentName, traceId, parentId) : recorder.beginSegment(segmentName);
if (samplingResponse.getRuleName().isPresent()) {
logger.debug("Sampling strategy decided to use rule named: " + samplingResponse.getRuleName().get() + ".");
created.setRuleName(samplingResponse.getRuleName().get());
}
} else {
// NOT_SAMPLED
String segmentName = getSegmentName(httpServletRequest);
if (samplingStrategy.isForcedSamplingSupported()) {
created = traceId != null ? recorder.beginSegment(segmentName, traceId, parentId) : recorder.beginSegment(segmentName);
created.setSampled(false);
} else {
logger.debug("Creating Dummy Segment");
created = traceId != null ? recorder.beginNoOpSegment(traceId) : recorder.beginNoOpSegment();
}
}
Map<String, Object> requestAttributes = new HashMap<String, Object>();
requestAttributes.put("url", httpServletRequest.getRequestURL().toString());
requestAttributes.put("method", httpServletRequest.getMethod());
Optional<String> userAgent = getUserAgent(httpServletRequest);
if (userAgent.isPresent()) {
requestAttributes.put("user_agent", userAgent.get());
}
Optional<String> xForwardedFor = getXForwardedFor(httpServletRequest);
if (xForwardedFor.isPresent()) {
requestAttributes.put("client_ip", xForwardedFor.get());
requestAttributes.put("x_forwarded_for", true);
} else {
Optional<String> clientIp = getClientIp(httpServletRequest);
if (clientIp.isPresent()) {
requestAttributes.put("client_ip", clientIp.get());
}
}
created.putHttp("request", requestAttributes);
HttpServletResponse httpServletResponse = castServletResponse(response);
if (httpServletResponse == null) {
return created;
}
final TraceHeader responseHeader;
if (incomingHeader.isPresent()) {
// create a new header, and use the incoming header so we know what to do in regards to sending back the sampling
// decision.
responseHeader = new TraceHeader(created.getTraceId());
if (SampleDecision.REQUESTED == incomingHeader.get().getSampled()) {
responseHeader.setSampled(created.isSampled() ? SampleDecision.SAMPLED : SampleDecision.NOT_SAMPLED);
}
} else {
// Create a new header, we're the tracing root. We wont return the sampling decision.
responseHeader = new TraceHeader(created.getTraceId());
}
httpServletResponse.addHeader(TraceHeader.HEADER_KEY, responseHeader.toString());
return created;
}
public void postFilter(ServletRequest request, ServletResponse response) {
AWSXRayRecorder recorder = getRecorder();
Segment segment = recorder.getCurrentSegment();
if (null != segment) {
HttpServletResponse httpServletResponse = castServletResponse(response);
if (null != httpServletResponse) {
Map<String, Object> responseAttributes = new HashMap<String, Object>();
int responseCode = httpServletResponse.getStatus();
switch(responseCode / 100) {
case 4:
segment.setError(true);
if (responseCode == 429) {
segment.setThrottle(true);
}
break;
case 5:
segment.setFault(true);
break;
default:
break;
}
responseAttributes.put("status", responseCode);
Optional<Integer> contentLength = getContentLength(httpServletResponse);
if (contentLength.isPresent()) {
responseAttributes.put("content_length", contentLength.get());
}
segment.putHttp("response", responseAttributes);
}
recorder.endSegment();
}
}
}
19
Source : AWSXRayServletAsyncListener.java
with Apache License 2.0
from aws
with Apache License 2.0
from aws
clreplaced AWSXRayServletAsyncListener implements AsyncListener {
public static final String ENreplacedY_ATTRIBUTE_KEY = "com.amazonaws.xray.enreplacedies.Enreplacedy";
@Nullable
private AWSXRayRecorder recorder;
private final AWSXRayServletFilter filter;
// TODO(anuraaga): Better define lifecycle relationship between this listener and the filter.
@SuppressWarnings("nullness")
AWSXRayServletAsyncListener(@UnderInitialization AWSXRayServletFilter filter, @Nullable AWSXRayRecorder recorder) {
this.filter = filter;
this.recorder = recorder;
}
private AWSXRayRecorder getRecorder() {
if (recorder == null) {
recorder = AWSXRay.getGlobalRecorder();
}
return recorder;
}
private void processEvent(AsyncEvent event) throws IOException {
AWSXRayRecorder recorder = getRecorder();
Enreplacedy enreplacedy = (Enreplacedy) event.getSuppliedRequest().getAttribute(ENreplacedY_ATTRIBUTE_KEY);
enreplacedy.run(() -> {
if (event.getThrowable() != null) {
enreplacedy.addException(event.getThrowable());
}
filter.postFilter(event.getSuppliedRequest(), event.getSuppliedResponse());
});
}
@Override
public void onComplete(AsyncEvent event) throws IOException {
processEvent(event);
}
@Override
public void onTimeout(AsyncEvent event) throws IOException {
processEvent(event);
}
@Override
public void onError(AsyncEvent event) throws IOException {
processEvent(event);
}
@Override
public void onStartAsync(AsyncEvent event) throws IOException {
}
}
19
Source : TraceID.java
with Apache License 2.0
from aws
with Apache License 2.0
from aws
/**
* Returns a new {@code TraceID} which represents the start of a new trace. This new
* ID is generated according to the settings provided by the AWSXRayRecorder instance
* that created it.
*/
public static TraceID create(AWSXRayRecorder creator) {
return new TraceID(TimeUtils.currentEpochSecond(), creator);
}
19
Source : NoOpSubSegment.java
with Apache License 2.0
from aws
with Apache License 2.0
from aws
clreplaced NoOpSubSegment implements Subsegment {
private final Segment parentSegment;
private final AWSXRayRecorder creator;
private volatile Enreplacedy parent;
NoOpSubSegment(Segment parentSegment, AWSXRayRecorder creator) {
this.parentSegment = parentSegment;
this.creator = creator;
parent = parentSegment;
}
@Override
public boolean end() {
return false;
}
@Override
public String getName() {
return "";
}
@Override
public String getId() {
return "";
}
@Override
public void setId(String id) {
}
@Override
public double getStartTime() {
return 0;
}
@Override
public void setStartTime(double startTime) {
}
@Override
public double getEndTime() {
return 0;
}
@Override
public void setEndTime(double endTime) {
}
@Override
public boolean isFault() {
return false;
}
@Override
public void setFault(boolean fault) {
}
@Override
public boolean isError() {
return false;
}
@Override
public void setError(boolean error) {
}
@Override
public String getNamespace() {
return "";
}
@Override
public void setNamespace(String namespace) {
}
@Override
public ReentrantLock getSubsegmentsLock() {
return NoOpReentrantLock.get();
}
@Override
public void setSubsegmentsLock(ReentrantLock subsegmentsLock) {
}
@Override
public Cause getCause() {
// It should not be common for this to be called on an unsampled segment so we lazily initialize here.
return new Cause(NoOpList.get(), NoOpList.get());
}
@Override
public Map<String, Object> getHttp() {
return NoOpMap.get();
}
@Override
public void setHttp(Map<String, Object> http) {
}
@Override
public Map<String, Object> getAws() {
return NoOpMap.get();
}
@Override
public void setAws(Map<String, Object> aws) {
}
@Override
public Map<String, Object> getSql() {
return NoOpMap.get();
}
@Override
public void setSql(Map<String, Object> sql) {
}
@Override
public Map<String, Map<String, Object>> getMetadata() {
return NoOpMap.get();
}
@Override
public void setMetadata(Map<String, Map<String, Object>> metadata) {
}
@Override
public Map<String, Object> getAnnotations() {
return NoOpMap.get();
}
@Override
public void setAnnotations(Map<String, Object> annotations) {
}
@Override
public Enreplacedy getParent() {
return parent;
}
@Override
public void setParent(Enreplacedy parent) {
this.parent = parent;
}
@Override
public boolean isThrottle() {
return false;
}
@Override
public void setThrottle(boolean throttle) {
}
@Override
public boolean isInProgress() {
return false;
}
@Override
public void setInProgress(boolean inProgress) {
}
@Override
public TraceID getTraceId() {
return parentSegment.getTraceId();
}
@Override
public void setTraceId(TraceID traceId) {
}
@Override
@Nullable
public String getParentId() {
return null;
}
@Override
public void setParentId(@Nullable String parentId) {
}
@Override
public AWSXRayRecorder getCreator() {
return creator;
}
@Override
public void setCreator(AWSXRayRecorder creator) {
}
@Override
public Segment getParentSegment() {
return parentSegment;
}
@Override
public List<Subsegment> getSubsegments() {
return NoOpList.get();
}
@Override
public void addSubsegment(Subsegment subsegment) {
}
@Override
public void addException(Throwable exception) {
}
@Override
public int getReferenceCount() {
return 0;
}
@Override
public LongAdder getTotalSize() {
// It should not be common for this to be called on an unsampled segment so we lazily initialize here.
return new LongAdder();
}
@Override
public void incrementReferenceCount() {
}
@Override
public boolean decrementReferenceCount() {
return false;
}
@Override
public void putHttp(String key, Object value) {
}
@Override
public void putAllHttp(Map<String, Object> all) {
}
@Override
public void putAws(String key, Object value) {
}
@Override
public void putAllAws(Map<String, Object> all) {
}
@Override
public void putSql(String key, Object value) {
}
@Override
public void putAllSql(Map<String, Object> all) {
}
@Override
public void putAnnotation(String key, String value) {
}
@Override
public void putAnnotation(String key, Number value) {
}
@Override
public void putAnnotation(String key, Boolean value) {
}
@Override
public void putMetadata(String key, Object object) {
}
@Override
public void putMetadata(String namespace, String key, Object object) {
}
@Override
public void removeSubsegment(Subsegment subsegment) {
}
@Override
public boolean isEmitted() {
return false;
}
@Override
public void setEmitted(boolean emitted) {
}
@Override
public String serialize() {
return "";
}
@Override
public String prettySerialize() {
return "";
}
@Override
public void setParentSegment(Segment parentSegment) {
}
@Override
public Set<String> getPrecursorIds() {
return NoOpSet.get();
}
@Override
public void setPrecursorIds(Set<String> precursorIds) {
}
@Override
public void addPrecursorId(String precursorId) {
}
@Override
public String streamSerialize() {
return "";
}
@Override
public String prettyStreamSerialize() {
return "";
}
@Override
public void close() {
}
}
19
Source : NoOpSubSegment.java
with Apache License 2.0
from aws
with Apache License 2.0
from aws
@Override
public void setCreator(AWSXRayRecorder creator) {
}
19
Source : NoOpSegment.java
with Apache License 2.0
from aws
with Apache License 2.0
from aws
clreplaced NoOpSegment implements Segment {
private final TraceID traceId;
private final AWSXRayRecorder creator;
NoOpSegment(TraceID traceId, AWSXRayRecorder creator) {
this.traceId = traceId;
this.creator = creator;
}
@Override
public boolean end() {
return false;
}
@Override
public boolean isRecording() {
return false;
}
@Override
public boolean isSampled() {
return false;
}
@Override
public void setSampled(boolean sampled) {
}
@Override
public String getResourceArn() {
return "";
}
@Override
public void setResourceArn(String resourceArn) {
}
@Override
public String getUser() {
return "";
}
@Override
public void setUser(String user) {
}
@Override
public String getOrigin() {
return "";
}
@Override
public void setOrigin(String origin) {
}
@Override
public Map<String, Object> getService() {
return NoOpMap.get();
}
@Override
public void setService(Map<String, Object> service) {
}
@Override
public String getName() {
return "";
}
@Override
public String getId() {
return "";
}
@Override
public void setId(String id) {
}
@Override
public double getStartTime() {
return 0;
}
@Override
public void setStartTime(double startTime) {
}
@Override
public double getEndTime() {
return 0;
}
@Override
public void setEndTime(double endTime) {
}
@Override
public boolean isFault() {
return false;
}
@Override
public void setFault(boolean fault) {
}
@Override
public boolean isError() {
return false;
}
@Override
public void setError(boolean error) {
}
@Override
public String getNamespace() {
return "";
}
@Override
public void setNamespace(String namespace) {
}
@Override
public ReentrantLock getSubsegmentsLock() {
return NoOpReentrantLock.get();
}
@Override
public void setSubsegmentsLock(ReentrantLock subsegmentsLock) {
}
@Override
public Cause getCause() {
// It should not be common for this to be called on an unsampled segment so we lazily initialize here.
return new Cause(NoOpList.get(), NoOpList.get());
}
@Override
public Map<String, Object> getHttp() {
return NoOpMap.get();
}
@Override
public void setHttp(Map<String, Object> http) {
}
@Override
public Map<String, Object> getAws() {
return NoOpMap.get();
}
@Override
public void setAws(Map<String, Object> aws) {
}
@Override
public Map<String, Object> getSql() {
return NoOpMap.get();
}
@Override
public void setSql(Map<String, Object> sql) {
}
@Override
public Map<String, Map<String, Object>> getMetadata() {
return NoOpMap.get();
}
@Override
public void setMetadata(Map<String, Map<String, Object>> metadata) {
}
@Override
public Map<String, Object> getAnnotations() {
return NoOpMap.get();
}
@Override
public void setAnnotations(Map<String, Object> annotations) {
}
@Override
public Enreplacedy getParent() {
return this;
}
@Override
public void setParent(Enreplacedy parent) {
}
@Override
public boolean isThrottle() {
return false;
}
@Override
public void setThrottle(boolean throttle) {
}
@Override
public boolean isInProgress() {
return false;
}
@Override
public void setInProgress(boolean inProgress) {
}
@Override
public TraceID getTraceId() {
return traceId;
}
@Override
public void setTraceId(TraceID traceId) {
}
@Override
@Nullable
public String getParentId() {
return null;
}
@Override
public void setParentId(@Nullable String parentId) {
}
@Override
public AWSXRayRecorder getCreator() {
return creator;
}
@Override
public void setCreator(AWSXRayRecorder creator) {
}
@Override
public void putService(String key, Object object) {
}
@Override
public void putAllService(Map<String, Object> all) {
}
@Override
public void setRuleName(String name) {
}
@Override
public Segment getParentSegment() {
return this;
}
@Override
public List<Subsegment> getSubsegments() {
return NoOpList.get();
}
@Override
public void addSubsegment(Subsegment subsegment) {
}
@Override
public void addException(Throwable exception) {
}
@Override
public int getReferenceCount() {
return 0;
}
@Override
public LongAdder getTotalSize() {
// It should not be common for this to be called on an unsampled segment so we lazily initialize here.
return new LongAdder();
}
@Override
public void incrementReferenceCount() {
}
@Override
public boolean decrementReferenceCount() {
return false;
}
@Override
public void putHttp(String key, Object value) {
}
@Override
public void putAllHttp(Map<String, Object> all) {
}
@Override
public void putAws(String key, Object value) {
}
@Override
public void putAllAws(Map<String, Object> all) {
}
@Override
public void putSql(String key, Object value) {
}
@Override
public void putAllSql(Map<String, Object> all) {
}
@Override
public void putAnnotation(String key, String value) {
}
@Override
public void putAnnotation(String key, Number value) {
}
@Override
public void putAnnotation(String key, Boolean value) {
}
@Override
public void putMetadata(String key, Object object) {
}
@Override
public void putMetadata(String namespace, String key, Object object) {
}
@Override
public void removeSubsegment(Subsegment subsegment) {
}
@Override
public boolean isEmitted() {
return false;
}
@Override
public void setEmitted(boolean emitted) {
}
@Override
public String serialize() {
return "";
}
@Override
public String prettySerialize() {
return "";
}
@Override
public void close() {
}
}
19
Source : FacadeSegment.java
with Apache License 2.0
from aws
with Apache License 2.0
from aws
/**
* Unsupported as FacadeSegments cannot be mutated.
* @throws UnsupportedOperationException in all cases
*/
@Override
public void setCreator(AWSXRayRecorder creator) {
throw new UnsupportedOperationException(MUTATION_UNSUPPORTED_MESSAGE);
}
19
Source : EntityImpl.java
with Apache License 2.0
from aws
with Apache License 2.0
from aws
/**
* @param creator the creator to set
*/
@Override
public void setCreator(AWSXRayRecorder creator) {
synchronized (lock) {
checkAlreadyEmitted();
this.creator = creator;
}
}
19
Source : DummySubsegment.java
with Apache License 2.0
from aws
with Apache License 2.0
from aws
/**
* @deprecated Use {@link Subsegment#noOp(AWSXRayRecorder)}.
*/
@Deprecated
public clreplaced DummySubsegment implements Subsegment {
private Cause cause = new Cause();
private Map<String, Object> map = new ConcurrentHashMap<>();
private Map<String, Map<String, Object>> metadataMap = new ConcurrentHashMap<>();
private List<Subsegment> list = new ArrayList<>();
private Set<String> set = new HashSet<>();
private ReentrantLock lock = new ReentrantLock();
private AWSXRayRecorder creator;
private TraceID traceId;
private Segment parentSegment;
public DummySubsegment(AWSXRayRecorder creator) {
this(creator, TraceID.create(creator));
}
public DummySubsegment(AWSXRayRecorder creator, TraceID traceId) {
this.creator = creator;
this.traceId = traceId;
this.parentSegment = new DummySegment(creator);
}
@Override
public String getName() {
return "";
}
@Override
public String getId() {
return "";
}
@Override
public void setId(String id) {
}
@Override
public double getStartTime() {
return 0;
}
@Override
public void setStartTime(double startTime) {
}
@Override
public double getEndTime() {
return 0;
}
@Override
public void setEndTime(double endTime) {
}
@Override
public boolean isFault() {
return false;
}
@Override
public void setFault(boolean fault) {
}
@Override
public boolean isError() {
return false;
}
@Override
public void setError(boolean error) {
}
@Override
public String getNamespace() {
return "";
}
@Override
public void setNamespace(String namespace) {
}
@Override
public Cause getCause() {
return cause;
}
@Override
public Map<String, Object> getHttp() {
return map;
}
@Override
public void setHttp(Map<String, Object> http) {
}
@Override
public Map<String, Object> getAws() {
return map;
}
@Override
public void setAws(Map<String, Object> aws) {
}
@Override
public Map<String, Object> getSql() {
return map;
}
@Override
public void setSql(Map<String, Object> sql) {
}
@Override
public Map<String, Map<String, Object>> getMetadata() {
return metadataMap;
}
@Override
public void setMetadata(Map<String, Map<String, Object>> metadata) {
}
@Override
public void setAnnotations(Map<String, Object> annotations) {
}
@Override
public Enreplacedy getParent() {
return this;
}
@Override
public void setParent(Enreplacedy parent) {
}
@Override
public boolean isThrottle() {
return false;
}
@Override
public void setThrottle(boolean throttle) {
}
@Override
public boolean isInProgress() {
return false;
}
@Override
public void setInProgress(boolean inProgress) {
}
@Override
public TraceID getTraceId() {
return traceId;
}
@Override
public void setTraceId(TraceID traceId) {
}
/**
* @return the creator
*/
@Override
public AWSXRayRecorder getCreator() {
return creator;
}
/**
* @param creator the creator to set
*/
@Override
public void setCreator(AWSXRayRecorder creator) {
this.creator = creator;
}
@Override
public String getParentId() {
return "";
}
@Override
public void setParentId(@Nullable String parentId) {
}
@Override
public List<Subsegment> getSubsegments() {
return list;
}
@Override
public void addSubsegment(Subsegment subsegment) {
}
@Override
public void addException(Throwable exception) {
}
@Override
public void putHttp(String key, Object value) {
}
@Override
public void putAllHttp(Map<String, Object> all) {
}
@Override
public void putAws(String key, Object value) {
}
@Override
public void putAllAws(Map<String, Object> all) {
}
@Override
public void putSql(String key, Object value) {
}
@Override
public void putAllSql(Map<String, Object> all) {
}
@Override
public void putAnnotation(String key, String value) {
}
@Override
public void putAnnotation(String key, Number value) {
}
@Override
public void putAnnotation(String key, Boolean value) {
}
@Override
public void putMetadata(String key, Object object) {
}
@Override
public void putMetadata(String namespace, String key, Object object) {
}
@Override
public boolean isEmitted() {
return false;
}
@Override
public void setEmitted(boolean emitted) {
}
@Override
public String serialize() {
return "";
}
@Override
public String prettySerialize() {
return "";
}
@Override
public boolean end() {
return false;
}
@Override
public Map<String, Object> getAnnotations() {
return map;
}
@Override
public Segment getParentSegment() {
return parentSegment;
}
@Override
public void close() {
}
@Override
public void setParentSegment(Segment parentSegment) {
}
@Override
public Set<String> getPrecursorIds() {
return set;
}
@Override
public void setPrecursorIds(Set<String> precursorIds) {
}
@Override
public void addPrecursorId(String precursorId) {
}
@Override
public String streamSerialize() {
return "";
}
@Override
public String prettyStreamSerialize() {
return "";
}
@Override
public ReentrantLock getSubsegmentsLock() {
return lock;
}
@Override
public void setSubsegmentsLock(ReentrantLock subsegmentsLock) {
}
@Override
public int getReferenceCount() {
return 0;
}
@Override
public LongAdder getTotalSize() {
return parentSegment.getTotalSize();
}
@Override
public void incrementReferenceCount() {
}
@Override
public boolean decrementReferenceCount() {
return false;
}
@Override
public void removeSubsegment(Subsegment subsegment) {
}
}
19
Source : DummySubsegment.java
with Apache License 2.0
from aws
with Apache License 2.0
from aws
/**
* @param creator the creator to set
*/
@Override
public void setCreator(AWSXRayRecorder creator) {
this.creator = creator;
}
19
Source : ThreadLocalSegmentContext.java
with Apache License 2.0
from aws
with Apache License 2.0
from aws
@Override
public void endSubsegment(AWSXRayRecorder recorder) {
Enreplacedy current = getTraceEnreplacedy();
if (current instanceof Subsegment) {
if (logger.isDebugEnabled()) {
logger.debug("Ending subsegment named: " + current.getName());
}
Subsegment currentSubsegment = (Subsegment) current;
List<SegmentListener> segmentListeners = recorder.getSegmentListeners();
segmentListeners.stream().filter(Objects::nonNull).forEach(listener -> listener.beforeEndSubsegment(currentSubsegment));
if (currentSubsegment.end()) {
recorder.sendSegment(currentSubsegment.getParentSegment());
} else {
if (recorder.getStreamingStrategy().requiresStreaming(currentSubsegment.getParentSegment())) {
recorder.getStreamingStrategy().streamSome(currentSubsegment.getParentSegment(), recorder.getEmitter());
}
segmentListeners.stream().filter(Objects::nonNull).forEach(listener -> listener.afterEndSubsegment(currentSubsegment));
setTraceEnreplacedy(current.getParent());
}
} else {
recorder.getContextMissingStrategy().contextMissing("Failed to end subsegment: subsegment cannot be found.", SubsegmentNotFoundException.clreplaced);
}
}
19
Source : SegmentContextExecutors.java
with Apache License 2.0
from aws
with Apache License 2.0
from aws
/**
* Returns a new {@link Executor} which will run any tasks with the provided {@link Segment} mounted in the provided
* {@link AWSXRayRecorder}. If {@code segment} is {@code null}, the executor is a no-op.
*/
public static Executor newSegmentContextExecutor(AWSXRayRecorder recorder, @Nullable Segment segment) {
if (!checkNotNull(recorder, "recorder") || segment == null) {
return Runnable::run;
}
return new SegmentContextExecutor(recorder, segment);
}
19
Source : LambdaSegmentContext.java
with Apache License 2.0
from aws
with Apache License 2.0
from aws
private static FacadeSegment newFacadeSegment(AWSXRayRecorder recorder, String name) {
TraceHeader traceHeader = getTraceHeaderFromEnvironment();
if (isInitializing(traceHeader)) {
logger.warn(LAMBDA_TRACE_HEADER_KEY + " is missing a trace ID, parent ID, or sampling decision. Subsegment " + name + " discarded.");
return new FacadeSegment(recorder, TraceID.create(recorder), "", SampleDecision.NOT_SAMPLED);
}
return new FacadeSegment(recorder, traceHeader.getRootTraceId(), traceHeader.getParentId(), traceHeader.getSampled());
}
19
Source : LambdaSegmentContext.java
with Apache License 2.0
from aws
with Apache License 2.0
from aws
@Override
public void endSubsegment(AWSXRayRecorder recorder) {
Enreplacedy current = getTraceEnreplacedy();
if (current instanceof Subsegment) {
if (logger.isDebugEnabled()) {
logger.debug("Ending subsegment named: " + current.getName());
}
Subsegment currentSubsegment = (Subsegment) current;
List<SegmentListener> segmentListeners = recorder.getSegmentListeners();
segmentListeners.stream().filter(Objects::nonNull).forEach(listener -> listener.beforeEndSubsegment(currentSubsegment));
currentSubsegment.end();
if (recorder.getStreamingStrategy().requiresStreaming(currentSubsegment.getParentSegment())) {
recorder.getStreamingStrategy().streamSome(currentSubsegment.getParentSegment(), recorder.getEmitter());
}
segmentListeners.stream().filter(Objects::nonNull).forEach(listener -> listener.afterEndSubsegment(currentSubsegment));
Enreplacedy parentEnreplacedy = current.getParent();
if (parentEnreplacedy instanceof FacadeSegment) {
if (((FacadeSegment) parentEnreplacedy).isSampled()) {
current.getCreator().getEmitter().sendSubsegment((Subsegment) current);
}
clearTraceEnreplacedy();
} else {
setTraceEnreplacedy(current.getParent());
}
} else {
throw new SubsegmentNotFoundException("Failed to end a subsegment: subsegment cannot be found.");
}
}
19
Source : TracingInterceptor.java
with Apache License 2.0
from aws
with Apache License 2.0
from aws
public clreplaced TracingInterceptor implements ExecutionInterceptor {
/**
* @deprecated For internal use only.
*/
@Deprecated
@SuppressWarnings("checkstyle:ConstantName")
public static final ExecutionAttribute<Subsegment> // TODO(anuraaga): Make private in next major version and rename.
enreplacedyKey = new ExecutionAttribute("AWS X-Ray Enreplacedy");
private static final Log logger = LogFactory.getLog(TracingInterceptor.clreplaced);
private static final ObjectMapper MAPPER = new ObjectMapper().setPropertyNamingStrategy(PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES).configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false).configure(JsonParser.Feature.ALLOW_COMMENTS, true);
private static final URL DEFAULT_OPERATION_PARAMETER_WHITELIST = TracingInterceptor.clreplaced.getResource("/com/amazonaws/xray/interceptors/DefaultOperationParameterWhitelist.json");
private static final String UNKNOWN_REQUEST_ID = "UNKNOWN";
private static final List<String> REQUEST_ID_KEYS = Arrays.asList("x-amz-request-id", "x-amzn-requestid");
private AWSServiceHandlerManifest awsServiceHandlerManifest;
private AWSXRayRecorder recorder;
private final String accountId;
public TracingInterceptor() {
this(null, null, null);
}
public TracingInterceptor(AWSXRayRecorder recorder, String accountId, URL parameterWhitelist) {
this.recorder = recorder;
this.accountId = accountId;
initInterceptorManifest(parameterWhitelist);
}
private void initInterceptorManifest(URL parameterWhitelist) {
if (parameterWhitelist != null) {
try {
awsServiceHandlerManifest = MAPPER.readValue(parameterWhitelist, AWSServiceHandlerManifest.clreplaced);
return;
} catch (IOException e) {
logger.error("Unable to parse operation parameter whitelist at " + parameterWhitelist.getPath() + ". Falling back to default operation parameter whitelist at " + TracingInterceptor.DEFAULT_OPERATION_PARAMETER_WHITELIST.getPath() + ".", e);
}
}
try {
awsServiceHandlerManifest = MAPPER.readValue(TracingInterceptor.DEFAULT_OPERATION_PARAMETER_WHITELIST, AWSServiceHandlerManifest.clreplaced);
} catch (IOException e) {
logger.error("Unable to parse default operation parameter whitelist at " + TracingInterceptor.DEFAULT_OPERATION_PARAMETER_WHITELIST.getPath() + ". This will affect this handler's ability to capture AWS operation parameter information.", e);
}
}
private AWSOperationHandler getOperationHandler(ExecutionAttributes executionAttributes) {
String serviceName = executionAttributes.getAttribute(SdkExecutionAttribute.SERVICE_NAME);
String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME);
if (awsServiceHandlerManifest == null) {
return null;
}
AWSOperationHandlerManifest operationManifest = awsServiceHandlerManifest.getOperationHandlerManifest(serviceName);
if (operationManifest == null) {
return null;
}
return operationManifest.getOperationHandler(operationName);
}
private HashMap<String, Object> extractRequestParameters(Context.BeforeExecution context, ExecutionAttributes executionAttributes) {
HashMap<String, Object> parameters = new HashMap<>();
AWSOperationHandler operationHandler = getOperationHandler(executionAttributes);
if (operationHandler == null) {
return parameters;
}
if (operationHandler.getRequestParameters() != null) {
operationHandler.getRequestParameters().forEach((parameterName) -> {
SdkRequest request = context.request();
Optional<Object> parameterValue = request.getValueForField(parameterName, Object.clreplaced);
if (parameterValue.isPresent()) {
parameters.put(StringTransform.toSnakeCase(parameterName), parameterValue.get());
}
});
}
if (operationHandler.getRequestDescriptors() != null) {
operationHandler.getRequestDescriptors().forEach((key, descriptor) -> {
if (descriptor.isMap() && descriptor.shouldGetKeys()) {
SdkRequest request = context.request();
Optional<Map> parameterValue = request.getValueForField(key, Map.clreplaced);
if (parameterValue.isPresent()) {
String renameTo = descriptor.getRenameTo() != null ? descriptor.getRenameTo() : key;
parameters.put(StringTransform.toSnakeCase(renameTo), parameterValue.get().keySet());
}
} else if (descriptor.isList() && descriptor.shouldGetCount()) {
SdkRequest request = context.request();
Optional<List> parameterValue = request.getValueForField(key, List.clreplaced);
if (parameterValue.isPresent()) {
String renameTo = descriptor.getRenameTo() != null ? descriptor.getRenameTo() : key;
parameters.put(StringTransform.toSnakeCase(renameTo), parameterValue.get().size());
}
}
});
}
return parameters;
}
private HashMap<String, Object> extractResponseParameters(Context.AfterExecution context, ExecutionAttributes executionAttributes) {
HashMap<String, Object> parameters = new HashMap<>();
AWSOperationHandler operationHandler = getOperationHandler(executionAttributes);
if (operationHandler == null) {
return parameters;
}
if (operationHandler.getResponseParameters() != null) {
operationHandler.getResponseParameters().forEach((parameterName) -> {
SdkResponse response = context.response();
Optional<Object> parameterValue = response.getValueForField(parameterName, Object.clreplaced);
if (parameterValue.isPresent()) {
parameters.put(StringTransform.toSnakeCase(parameterName), parameterValue.get());
}
});
}
if (operationHandler.getResponseDescriptors() != null) {
operationHandler.getResponseDescriptors().forEach((key, descriptor) -> {
if (descriptor.isMap() && descriptor.shouldGetKeys()) {
SdkResponse response = context.response();
Optional<Map> parameterValue = response.getValueForField(key, Map.clreplaced);
if (parameterValue.isPresent()) {
String renameTo = descriptor.getRenameTo() != null ? descriptor.getRenameTo() : key;
parameters.put(StringTransform.toSnakeCase(renameTo), parameterValue.get().keySet());
}
} else if (descriptor.isList() && descriptor.shouldGetCount()) {
SdkResponse response = context.response();
Optional<List> parameterValue = response.getValueForField(key, List.clreplaced);
if (parameterValue.isPresent()) {
String renameTo = descriptor.getRenameTo() != null ? descriptor.getRenameTo() : key;
parameters.put(StringTransform.toSnakeCase(renameTo), parameterValue.get().size());
}
}
});
}
return parameters;
}
@Override
public void beforeExecution(Context.BeforeExecution context, ExecutionAttributes executionAttributes) {
AWSXRayRecorder recorder = getRecorder();
Enreplacedy origin = recorder.getTraceEnreplacedy();
Subsegment subsegment = recorder.beginSubsegment(executionAttributes.getAttribute(SdkExecutionAttribute.SERVICE_NAME));
subsegment.setNamespace(Namespace.AWS.toString());
subsegment.putAws(EnreplacedyDataKeys.AWS.OPERATION_KEY, executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME));
Region region = executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION);
if (region != null) {
subsegment.putAws(EnreplacedyDataKeys.AWS.REGION_KEY, region.id());
}
subsegment.putAllAws(extractRequestParameters(context, executionAttributes));
if (accountId != null) {
subsegment.putAws(EnreplacedyDataKeys.AWS.ACCOUNT_ID_SUBSEGMENT_KEY, accountId);
}
recorder.setTraceEnreplacedy(origin);
// store the subsegment in the AWS SDK's executionAttributes so it can be accessed across threads
executionAttributes.putAttribute(enreplacedyKey, subsegment);
}
@Override
public SdkHttpRequest modifyHttpRequest(Context.ModifyHttpRequest context, ExecutionAttributes executionAttributes) {
SdkHttpRequest httpRequest = context.httpRequest();
Subsegment subsegment = executionAttributes.getAttribute(enreplacedyKey);
if (subsegment == null) {
return httpRequest;
}
boolean isSampled = subsegment.getParentSegment().isSampled();
TraceHeader header = new TraceHeader(subsegment.getParentSegment().getTraceId(), isSampled ? subsegment.getId() : null, isSampled ? TraceHeader.SampleDecision.SAMPLED : TraceHeader.SampleDecision.NOT_SAMPLED);
return httpRequest.toBuilder().appendHeader(TraceHeader.HEADER_KEY, header.toString()).build();
}
@Override
public void beforeTransmission(Context.BeforeTransmission context, ExecutionAttributes executionAttributes) {
Subsegment subsegment = executionAttributes.getAttribute(enreplacedyKey);
if (subsegment == null) {
return;
}
Map<String, Object> awsProperties = subsegment.getAws();
// beforeTransmission is run before every API call attempt
// default value is set to -1 and will always be -1 on the first API call attempt
// this value will be incremented by 1, so initial run will have a stored retryCount of 0
int retryCount = (int) awsProperties.getOrDefault(EnreplacedyDataKeys.AWS.RETRIES_KEY, -1);
awsProperties.put(EnreplacedyDataKeys.AWS.RETRIES_KEY, retryCount + 1);
}
@Override
public void afterExecution(Context.AfterExecution context, ExecutionAttributes executionAttributes) {
Subsegment subsegment = executionAttributes.getAttribute(enreplacedyKey);
if (subsegment == null) {
return;
}
populateRequestId(subsegment, context);
populateSubsegmentWithResponse(subsegment, context.httpResponse());
subsegment.putAllAws(extractResponseParameters(context, executionAttributes));
getRecorder().endSubsegment(subsegment);
}
@Override
public void onExecutionFailure(Context.FailedExecution context, ExecutionAttributes executionAttributes) {
Subsegment subsegment = executionAttributes.getAttribute(enreplacedyKey);
if (subsegment == null) {
return;
}
populateSubsegmentException(subsegment, context);
populateRequestId(subsegment, context);
if (context.httpResponse().isPresent()) {
populateSubsegmentWithResponse(subsegment, context.httpResponse().get());
}
getRecorder().endSubsegment(subsegment);
}
private HashMap<String, Object> extractHttpResponseParameters(SdkHttpResponse httpResponse) {
HashMap<String, Object> parameters = new HashMap<>();
HashMap<String, Object> responseData = new HashMap<>();
responseData.put(EnreplacedyDataKeys.HTTP.STATUS_CODE_KEY, httpResponse.statusCode());
try {
if (httpResponse.headers().containsKey(EnreplacedyHeaderKeys.HTTP.CONTENT_LENGTH_HEADER)) {
responseData.put(EnreplacedyDataKeys.HTTP.CONTENT_LENGTH_KEY, Long.parseLong(httpResponse.headers().get(EnreplacedyHeaderKeys.HTTP.CONTENT_LENGTH_HEADER).get(0)));
}
} catch (NumberFormatException e) {
logger.warn("Unable to parse Content-Length header.", e);
}
parameters.put(EnreplacedyDataKeys.HTTP.RESPONSE_KEY, responseData);
return parameters;
}
private void setRemoteForException(Subsegment subsegment, Throwable exception) {
subsegment.getCause().getExceptions().forEach((e) -> {
if (e.getThrowable() == exception) {
e.setRemote(true);
}
});
}
private void populateSubsegmentException(Subsegment subsegment, Context.FailedExecution context) {
Throwable exception = context.exception();
subsegment.addException(exception);
int statusCode = -1;
if (exception instanceof SdkServiceException) {
statusCode = ((SdkServiceException) exception).statusCode();
subsegment.getCause().setMessage(exception.getMessage());
if (((SdkServiceException) exception).isThrottlingException()) {
subsegment.setThrottle(true);
// throttling errors are considered client-side errors
subsegment.setError(true);
}
setRemoteForException(subsegment, exception);
} else if (context.httpResponse().isPresent()) {
statusCode = context.httpResponse().get().statusCode();
}
if (statusCode == -1) {
return;
}
if (statusCode >= 400 && statusCode < 500) {
subsegment.setFault(false);
subsegment.setError(true);
if (statusCode == 429) {
subsegment.setThrottle(true);
}
} else if (statusCode >= 500) {
subsegment.setFault(true);
}
}
private void populateRequestId(Subsegment subsegment, Optional<SdkResponse> response, Optional<SdkHttpResponse> httpResponse, Throwable exception) {
String requestId = null;
if (exception != null) {
requestId = extractRequestIdFromThrowable(exception);
}
if (requestId == null || requestId.equals(UNKNOWN_REQUEST_ID)) {
requestId = extractRequestIdFromResponse(response);
}
if (requestId == null || requestId.equals(UNKNOWN_REQUEST_ID)) {
requestId = extractRequestIdFromHttp(httpResponse);
}
if (requestId != null && !requestId.equals(UNKNOWN_REQUEST_ID)) {
subsegment.putAws(EnreplacedyDataKeys.AWS.REQUEST_ID_KEY, requestId);
}
}
private void populateRequestId(Subsegment subsegment, Context.FailedExecution context) {
populateRequestId(subsegment, context.response(), context.httpResponse(), context.exception());
}
private void populateRequestId(Subsegment subsegment, Context.AfterExecution context) {
populateRequestId(subsegment, Optional.of(context.response()), Optional.of(context.httpResponse()), null);
}
private String extractRequestIdFromHttp(Optional<SdkHttpResponse> httpResponse) {
if (!httpResponse.isPresent()) {
return null;
}
return extractRequestIdFromHttp(httpResponse.get());
}
private String extractRequestIdFromHttp(SdkHttpResponse httpResponse) {
Map<String, List<String>> headers = httpResponse.headers();
Set<String> headerKeys = headers.keySet();
String requestIdKey = headerKeys.stream().filter(key -> REQUEST_ID_KEYS.contains(key.toLowerCase())).findFirst().orElse(null);
return requestIdKey != null ? headers.get(requestIdKey).get(0) : null;
}
private String extractExtendedRequestIdFromHttp(SdkHttpResponse httpResponse) {
Map<String, List<String>> headers = httpResponse.headers();
return headers.containsKey(EnreplacedyHeaderKeys.AWS.EXTENDED_REQUEST_ID_HEADER) ? headers.get(EnreplacedyHeaderKeys.AWS.EXTENDED_REQUEST_ID_HEADER).get(0) : null;
}
private String extractRequestIdFromThrowable(Throwable exception) {
if (exception instanceof SdkServiceException) {
return ((SdkServiceException) exception).requestId();
}
return null;
}
private String extractRequestIdFromResponse(Optional<SdkResponse> response) {
if (response.isPresent()) {
return extractRequestIdFromResponse(response.get());
}
return null;
}
private String extractRequestIdFromResponse(SdkResponse response) {
if (response instanceof AwsResponse) {
return ((AwsResponse) response).responseMetadata().requestId();
}
return null;
}
private void populateSubsegmentWithResponse(Subsegment subsegment, SdkHttpResponse httpResponse) {
if (subsegment == null || httpResponse == null) {
return;
}
String extendedRequestId = extractExtendedRequestIdFromHttp(httpResponse);
if (extendedRequestId != null) {
subsegment.putAws(EnreplacedyDataKeys.AWS.EXTENDED_REQUEST_ID_KEY, extendedRequestId);
}
subsegment.putAllHttp(extractHttpResponseParameters(httpResponse));
}
private AWSXRayRecorder getRecorder() {
if (recorder == null) {
recorder = AWSXRay.getGlobalRecorder();
}
return recorder;
}
}
19
Source : TracingHandler.java
with Apache License 2.0
from aws
with Apache License 2.0
from aws
/**
* Extension of {@code RequestHandler2} that intercepts requests made by {@code AmazonWebServiceClient}s and generates
* corresponding subsegments. Operation-level customization of this request handler is by default performed based on the
* information contained in the file at {@code "/com/amazonaws/xray/handlers/DefaultOperationParameterWhitelist.json")}.
*/
public clreplaced TracingHandler extends RequestHandler2 {
private static final Log logger = LogFactory.getLog(TracingHandler.clreplaced);
private static final ObjectMapper MAPPER = new ObjectMapper().setPropertyNamingStrategy(PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES).configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false).configure(JsonParser.Feature.ALLOW_COMMENTS, true);
private static final URL DEFAULT_OPERATION_PARAMETER_WHITELIST = TracingHandler.clreplaced.getResource("/com/amazonaws/xray/handlers/DefaultOperationParameterWhitelist.json");
private static final String GETTER_METHOD_NAME_PREFIX = "get";
private static final String S3_SERVICE_NAME = "Amazon S3";
private static final String S3_PRESIGN_REQUEST = "GeneratePresignedUrl";
private static final String S3_REQUEST_ID_HEADER_KEY = "x-amz-request-id";
private static final String XRAY_SERVICE_NAME = "AWSXRay";
private static final String XRAY_SAMPLING_RULE_REQUEST = "GetSamplingRules";
private static final String XRAY_SAMPLING_TARGET_REQUEST = "GetSamplingTargets";
private static final String REQUEST_ID_SUBSEGMENT_KEY = "request_id";
private static final HandlerContextKey<Enreplacedy> ENreplacedY_KEY = new HandlerContextKey<>("AWS X-Ray Enreplacedy");
private static final HandlerContextKey<Long> EXECUTING_THREAD_KEY = new HandlerContextKey<>("AWS X-Ray Executing Thread ID");
private static final String TO_SNAKE_CASE_REGEX = "([a-z])([A-Z]+)";
private static final String TO_SNAKE_CASE_REPLACE = "$1_$2";
private final String accountId;
private AWSServiceHandlerManifest awsServiceHandlerManifest;
private AWSXRayRecorder recorder;
public TracingHandler() {
this(AWSXRay.getGlobalRecorder(), null, null);
}
public TracingHandler(AWSXRayRecorder recorder) {
this(recorder, null, null);
}
public TracingHandler(String accountId) {
this(AWSXRay.getGlobalRecorder(), accountId, null);
}
public TracingHandler(AWSXRayRecorder recorder, String accountId) {
this(recorder, accountId, null);
}
public TracingHandler(URL operationParameterWhitelist) {
this(AWSXRay.getGlobalRecorder(), null, operationParameterWhitelist);
}
public TracingHandler(AWSXRayRecorder recorder, URL operationParameterWhitelist) {
this(recorder, null, operationParameterWhitelist);
}
public TracingHandler(String accountId, URL operationParameterWhitelist) {
this(AWSXRay.getGlobalRecorder(), accountId, operationParameterWhitelist);
}
public TracingHandler(AWSXRayRecorder recorder, String accountId, URL operationParameterWhitelist) {
this.recorder = recorder;
this.accountId = accountId;
initRequestManifest(operationParameterWhitelist);
}
private void initRequestManifest(URL operationParameterWhitelist) {
if (null != operationParameterWhitelist) {
try {
awsServiceHandlerManifest = MAPPER.readValue(operationParameterWhitelist, AWSServiceHandlerManifest.clreplaced);
return;
} catch (IOException e) {
logger.error("Unable to parse operation parameter whitelist at " + operationParameterWhitelist.getPath() + ". Falling back to default operation parameter whitelist at " + TracingHandler.DEFAULT_OPERATION_PARAMETER_WHITELIST.getPath() + ".", e);
}
}
try {
awsServiceHandlerManifest = MAPPER.readValue(TracingHandler.DEFAULT_OPERATION_PARAMETER_WHITELIST, AWSServiceHandlerManifest.clreplaced);
} catch (IOException e) {
logger.error("Unable to parse default operation parameter whitelist at " + TracingHandler.DEFAULT_OPERATION_PARAMETER_WHITELIST.getPath() + ". This will affect this handler's ability to capture AWS operation parameter information.", e);
}
}
private boolean isSubsegmentDuplicate(Optional<Subsegment> subsegment, Request<?> request) {
return subsegment.isPresent() && Namespace.AWS.toString().equals(subsegment.get().getNamespace()) && (null != extractServiceName(request) && extractServiceName(request).equals(subsegment.get().getName()));
}
@Override
public AmazonWebServiceRequest beforeExecution(AmazonWebServiceRequest request) {
lazyLoadRecorder();
request.addHandlerContext(ENreplacedY_KEY, recorder.getTraceEnreplacedy());
request.addHandlerContext(EXECUTING_THREAD_KEY, Thread.currentThread().getId());
return request;
}
@Override
public void beforeRequest(Request<?> request) {
String serviceName = extractServiceName(request);
String operationName = extractOperationName(request);
if (S3_SERVICE_NAME.equals(serviceName) && S3_PRESIGN_REQUEST.equals(operationName)) {
return;
}
if (XRAY_SERVICE_NAME.equals(serviceName) && (XRAY_SAMPLING_RULE_REQUEST.equals(operationName) || XRAY_SAMPLING_TARGET_REQUEST.equals(operationName))) {
return;
}
if (isSubsegmentDuplicate(recorder.getCurrentSubsegmentOptional(), request)) {
return;
}
Enreplacedy enreplacedyContext = request.getHandlerContext(ENreplacedY_KEY);
if (null != enreplacedyContext) {
recorder.setTraceEnreplacedy(enreplacedyContext);
}
Subsegment currentSubsegment = recorder.beginSubsegment(serviceName);
currentSubsegment.putAllAws(extractRequestParameters(request));
currentSubsegment.putAws(EnreplacedyDataKeys.AWS.OPERATION_KEY, operationName);
if (null != accountId) {
currentSubsegment.putAws(EnreplacedyDataKeys.AWS.ACCOUNT_ID_SUBSEGMENT_KEY, accountId);
}
currentSubsegment.setNamespace(Namespace.AWS.toString());
if (recorder.getCurrentSegment() != null) {
TraceHeader header = new TraceHeader(recorder.getCurrentSegment().getTraceId(), recorder.getCurrentSegment().isSampled() ? currentSubsegment.getId() : null, recorder.getCurrentSegment().isSampled() ? SampleDecision.SAMPLED : SampleDecision.NOT_SAMPLED);
request.addHeader(TraceHeader.HEADER_KEY, header.toString());
}
}
private String extractServiceName(Request<?> request) {
return request.getServiceName();
}
private String extractOperationName(Request<?> request) {
String ret = request.getOriginalRequest().getClreplaced().getSimpleName();
// remove 'Request'
ret = ret.substring(0, ret.length() - 7);
return ret;
}
private static String toSnakeCase(String camelCase) {
return camelCase.replaceAll(TO_SNAKE_CASE_REGEX, TO_SNAKE_CASE_REPLACE).toLowerCase();
}
private HashMap<String, Object> extractRequestParameters(Request<?> request) {
HashMap<String, Object> ret = new HashMap<>();
if (null == awsServiceHandlerManifest) {
return ret;
}
AWSOperationHandlerManifest serviceHandler = awsServiceHandlerManifest.getOperationHandlerManifest(extractServiceName(request));
if (null == serviceHandler) {
return ret;
}
AWSOperationHandler operationHandler = serviceHandler.getOperationHandler(extractOperationName(request));
if (null == operationHandler) {
return ret;
}
Object originalRequest = request.getOriginalRequest();
if (null != operationHandler.getRequestParameters()) {
operationHandler.getRequestParameters().forEach(parameterName -> {
try {
Object parameterValue = originalRequest.getClreplaced().getMethod(GETTER_METHOD_NAME_PREFIX + parameterName).invoke(originalRequest);
if (null != parameterValue) {
ret.put(TracingHandler.toSnakeCase(parameterName), parameterValue);
}
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
logger.error("Error getting request parameter: " + parameterName, e);
}
});
}
if (null != operationHandler.getRequestDescriptors()) {
operationHandler.getRequestDescriptors().forEach((requestKeyName, requestDescriptor) -> {
try {
if (requestDescriptor.isMap() && requestDescriptor.shouldGetKeys()) {
@SuppressWarnings("unchecked")
Map<String, Object> parameterValue = (Map<String, Object>) originalRequest.getClreplaced().getMethod(GETTER_METHOD_NAME_PREFIX + requestKeyName).invoke(originalRequest);
if (null != parameterValue) {
String renameTo = null != requestDescriptor.getRenameTo() ? requestDescriptor.getRenameTo() : requestKeyName;
ret.put(TracingHandler.toSnakeCase(renameTo), parameterValue.keySet());
}
} else if (requestDescriptor.isList() && requestDescriptor.shouldGetCount()) {
@SuppressWarnings("unchecked")
List<Object> parameterValue = (List<Object>) originalRequest.getClreplaced().getMethod(GETTER_METHOD_NAME_PREFIX + requestKeyName).invoke(originalRequest);
if (null != parameterValue) {
String renameTo = null != requestDescriptor.getRenameTo() ? requestDescriptor.getRenameTo() : requestKeyName;
ret.put(TracingHandler.toSnakeCase(renameTo), parameterValue.size());
}
}
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | ClreplacedCastException e) {
logger.error("Error getting request parameter: " + requestKeyName, e);
}
});
}
return ret;
}
private HashMap<String, Object> extractResponseParameters(Request<?> request, Object response) {
HashMap<String, Object> ret = new HashMap<>();
if (null == awsServiceHandlerManifest) {
return ret;
}
AWSOperationHandlerManifest serviceHandler = awsServiceHandlerManifest.getOperationHandlerManifest(extractServiceName(request));
if (null == serviceHandler) {
return ret;
}
AWSOperationHandler operationHandler = serviceHandler.getOperationHandler(extractOperationName(request));
if (null == operationHandler) {
return ret;
}
if (null != operationHandler.getResponseParameters()) {
operationHandler.getResponseParameters().forEach(parameterName -> {
try {
Object parameterValue = response.getClreplaced().getMethod(GETTER_METHOD_NAME_PREFIX + parameterName).invoke(response);
if (null != parameterValue) {
ret.put(TracingHandler.toSnakeCase(parameterName), parameterValue);
}
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
logger.error("Error getting response parameter: " + parameterName, e);
}
});
}
if (null != operationHandler.getResponseDescriptors()) {
operationHandler.getResponseDescriptors().forEach((responseKeyName, responseDescriptor) -> {
try {
if (responseDescriptor.isMap() && responseDescriptor.shouldGetKeys()) {
@SuppressWarnings("unchecked")
Map<String, Object> parameterValue = (Map<String, Object>) response.getClreplaced().getMethod(GETTER_METHOD_NAME_PREFIX + responseKeyName).invoke(response);
if (null != parameterValue) {
String renameTo = null != responseDescriptor.getRenameTo() ? responseDescriptor.getRenameTo() : responseKeyName;
ret.put(TracingHandler.toSnakeCase(renameTo), parameterValue.keySet());
}
} else if (responseDescriptor.isList() && responseDescriptor.shouldGetCount()) {
@SuppressWarnings("unchecked")
List<Object> parameterValue = (List<Object>) response.getClreplaced().getMethod(GETTER_METHOD_NAME_PREFIX + responseKeyName).invoke(response);
if (null != parameterValue) {
String renameTo = null != responseDescriptor.getRenameTo() ? responseDescriptor.getRenameTo() : responseKeyName;
ret.put(TracingHandler.toSnakeCase(renameTo), parameterValue.size());
}
}
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | ClreplacedCastException e) {
logger.error("Error getting request parameter: " + responseKeyName, e);
}
});
}
return ret;
}
private HashMap<String, Object> extractHttpResponseInformation(AmazonServiceException ase) {
HashMap<String, Object> ret = new HashMap<>();
HashMap<String, Object> response = new HashMap<>();
response.put(EnreplacedyDataKeys.HTTP.STATUS_CODE_KEY, ase.getStatusCode());
try {
if (null != ase.getHttpHeaders() && null != ase.getHttpHeaders().get(EnreplacedyHeaderKeys.HTTP.CONTENT_LENGTH_HEADER)) {
response.put(EnreplacedyDataKeys.HTTP.CONTENT_LENGTH_KEY, Long.parseLong(ase.getHttpHeaders().get(EnreplacedyHeaderKeys.HTTP.CONTENT_LENGTH_HEADER)));
}
} catch (NumberFormatException nfe) {
logger.warn("Unable to parse Content-Length header.", nfe);
}
ret.put(EnreplacedyDataKeys.HTTP.RESPONSE_KEY, response);
return ret;
}
private HashMap<String, Object> extractHttpResponseInformation(HttpResponse httpResponse) {
HashMap<String, Object> ret = new HashMap<>();
HashMap<String, Object> response = new HashMap<>();
response.put(EnreplacedyDataKeys.HTTP.STATUS_CODE_KEY, httpResponse.getStatusCode());
try {
if (null != httpResponse.getHeaders().get(EnreplacedyHeaderKeys.HTTP.CONTENT_LENGTH_HEADER)) {
response.put(EnreplacedyDataKeys.HTTP.CONTENT_LENGTH_KEY, Long.parseLong(httpResponse.getHeaders().get(EnreplacedyHeaderKeys.HTTP.CONTENT_LENGTH_HEADER)));
}
} catch (NumberFormatException nfe) {
logger.warn("Unable to parse Content-Length header.", nfe);
}
ret.put(EnreplacedyDataKeys.HTTP.RESPONSE_KEY, response);
return ret;
}
@Override
public void afterResponse(Request<?> request, Response<?> response) {
if (isSubsegmentDuplicate(recorder.getCurrentSubsegmentOptional(), request)) {
Optional<Subsegment> currentSubsegmentOptional = recorder.getCurrentSubsegmentOptional();
if (!currentSubsegmentOptional.isPresent()) {
return;
}
Subsegment currentSubsegment = currentSubsegmentOptional.get();
populateAndEndSubsegment(currentSubsegment, request, response, null);
}
}
@Override
public void afterError(Request<?> request, Response<?> response, Exception e) {
if (isSubsegmentDuplicate(recorder.getCurrentSubsegmentOptional(), request)) {
Optional<Subsegment> currentSubsegmentOptional = recorder.getCurrentSubsegmentOptional();
if (!currentSubsegmentOptional.isPresent()) {
return;
}
Subsegment currentSubsegment = currentSubsegmentOptional.get();
int statusCode = -1;
if (null != response) {
statusCode = response.getHttpResponse().getStatusCode();
} else {
if (e instanceof AmazonServiceException) {
AmazonServiceException ase = (AmazonServiceException) e;
statusCode = ase.getStatusCode();
// The S3 client will throw and re-swallow AmazonServiceExceptions if they have these status codes. Customers
// will never see the exceptions in their application code but they still travel through our
// TracingHandler#afterError method. We special case these status codes in order to prevent addition of the
// full exception object to the current subsegment. Instead, we'll just add any exception error message to the
// current subsegment's cause's message.
if ((304 == statusCode || 412 == statusCode) && S3_SERVICE_NAME.equals(ase.getServiceName())) {
populateAndEndSubsegment(currentSubsegment, request, response, ase);
return;
}
if (RetryUtils.isThrottlingException(ase)) {
currentSubsegment.setError(true);
currentSubsegment.setThrottle(true);
}
}
}
if (-1 != statusCode) {
int statusCodePrefix = statusCode / 100;
if (4 == statusCodePrefix) {
currentSubsegment.setError(true);
if (429 == statusCode) {
currentSubsegment.setThrottle(true);
}
}
}
currentSubsegment.addException(e);
if (e instanceof AmazonServiceException) {
populateAndEndSubsegment(currentSubsegment, request, response, (AmazonServiceException) e);
} else {
populateAndEndSubsegment(currentSubsegment, request, response);
}
}
}
private void populateAndEndSubsegment(Subsegment currentSubsegment, Request<?> request, Response<?> response) {
if (null != response) {
String requestId = null;
if (response.getAwsResponse() instanceof AmazonWebServiceResult<?>) {
// Not all services return responses extending AmazonWebServiceResult (e.g. S3)
ResponseMetadata metadata = ((AmazonWebServiceResult<?>) response.getAwsResponse()).getSdkResponseMetadata();
if (null != metadata) {
requestId = metadata.getRequestId();
if (null != requestId) {
currentSubsegment.putAws(REQUEST_ID_SUBSEGMENT_KEY, requestId);
}
}
} else if (null != response.getHttpResponse()) {
// S3 does not follow request id header convention
if (null != response.getHttpResponse().getHeader(S3_REQUEST_ID_HEADER_KEY)) {
currentSubsegment.putAws(REQUEST_ID_SUBSEGMENT_KEY, response.getHttpResponse().getHeader(S3_REQUEST_ID_HEADER_KEY));
}
if (null != response.getHttpResponse().getHeader(EnreplacedyHeaderKeys.AWS.EXTENDED_REQUEST_ID_HEADER)) {
currentSubsegment.putAws(EnreplacedyDataKeys.AWS.EXTENDED_REQUEST_ID_KEY, response.getHttpResponse().getHeader(EnreplacedyHeaderKeys.AWS.EXTENDED_REQUEST_ID_HEADER));
}
}
currentSubsegment.putAllAws(extractResponseParameters(request, response.getAwsResponse()));
currentSubsegment.putAllHttp(extractHttpResponseInformation(response.getHttpResponse()));
}
finalizeSubsegment(request);
}
private void populateAndEndSubsegment(Subsegment currentSubsegment, Request<?> request, Response<?> response, AmazonServiceException ase) {
if (null != response) {
populateAndEndSubsegment(currentSubsegment, request, response);
return;
} else if (null != ase) {
if (null != ase.getRequestId()) {
currentSubsegment.putAws(REQUEST_ID_SUBSEGMENT_KEY, ase.getRequestId());
}
if (null != ase.getHttpHeaders() && null != ase.getHttpHeaders().get(EnreplacedyHeaderKeys.AWS.EXTENDED_REQUEST_ID_HEADER)) {
currentSubsegment.putAws(EnreplacedyDataKeys.AWS.EXTENDED_REQUEST_ID_KEY, ase.getHttpHeaders().get(EnreplacedyHeaderKeys.AWS.EXTENDED_REQUEST_ID_HEADER));
}
if (null != ase.getErrorMessage()) {
currentSubsegment.getCause().setMessage(ase.getErrorMessage());
}
currentSubsegment.putAllHttp(extractHttpResponseInformation(ase));
}
finalizeSubsegment(request);
}
private void finalizeSubsegment(Request<?> request) {
recorder.endSubsegment();
Long executingThreadContext = request.getHandlerContext(EXECUTING_THREAD_KEY);
if (executingThreadContext != null && Thread.currentThread().getId() != executingThreadContext) {
recorder.clearTraceEnreplacedy();
}
}
private void lazyLoadRecorder() {
if (recorder != null) {
return;
}
recorder = AWSXRay.getGlobalRecorder();
}
}
19
Source : TracedHttpClient.java
with Apache License 2.0
from aws
with Apache License 2.0
from aws
@SuppressWarnings("deprecation")
public clreplaced TracedHttpClient extends CloseableHttpClient {
private final CloseableHttpClient wrappedClient;
private final AWSXRayRecorder recorder;
/**
* Constructs a TracedHttpClient instance using the provided client and global recorder.
*
* @param wrappedClient
* the HTTP client to wrap
*/
public TracedHttpClient(final CloseableHttpClient wrappedClient) {
this(wrappedClient, AWSXRay.getGlobalRecorder());
}
/**
* Constructs a TracedHttpClient instance using the provided client and provided recorder.
*
* @param wrappedClient
* the HTTP client to wrap
* @param recorder
* the recorder instance to use when generating subsegments around calls made by {@code wrappedClient}
*/
public TracedHttpClient(final CloseableHttpClient wrappedClient, AWSXRayRecorder recorder) {
this.wrappedClient = wrappedClient;
this.recorder = recorder;
}
public static HttpHost determineTarget(final HttpUriRequest request) throws ClientProtocolException {
// A null target may be acceptable if there is a default target.
// Otherwise, the null target is detected in the director.
HttpHost target = null;
final URI requestUri = request.getURI();
if (requestUri.isAbsolute()) {
target = URIUtils.extractHost(requestUri);
if (target == null) {
throw new ClientProtocolException("URI does not specify a valid host name: " + requestUri);
}
}
return target;
}
public static String getUrl(HttpUriRequest request) {
return request.getURI().toString();
}
public static String getUrl(HttpHost target, HttpRequest request) {
String uri = request.getRequestLine().getUri();
try {
URI requestUri = new URI(uri);
if (requestUri.isAbsolute()) {
return requestUri.toString();
}
} catch (URISyntaxException ex) {
// Not a valid URI
}
return target.toURI() + uri;
}
public static void addRequestInformation(Subsegment subsegment, HttpRequest request, String url) {
subsegment.setNamespace(Namespace.REMOTE.toString());
Segment parentSegment = subsegment.getParentSegment();
TraceHeader header = new TraceHeader(parentSegment.getTraceId(), parentSegment.isSampled() ? subsegment.getId() : null, parentSegment.isSampled() ? SampleDecision.SAMPLED : SampleDecision.NOT_SAMPLED);
request.addHeader(TraceHeader.HEADER_KEY, header.toString());
Map<String, Object> requestInformation = new HashMap<>();
requestInformation.put("url", url);
requestInformation.put("method", request.getRequestLine().getMethod());
subsegment.putHttp("request", requestInformation);
}
@FunctionalInterface
public interface HttpSupplier<// Necessary to define a get() method that may throw checked exceptions
R> {
R get() throws IOException, ClientProtocolException;
}
private <R> R wrapHttpSupplier(Subsegment subsegment, HttpSupplier<R> supplier) throws IOException, ClientProtocolException {
try {
return supplier.get();
} catch (Exception e) {
if (null != subsegment) {
subsegment.addException(e);
}
throw e;
} finally {
if (null != subsegment) {
recorder.endSubsegment();
}
}
}
@Override
public CloseableHttpResponse execute(final HttpHost target, final HttpRequest request, final HttpContext context) throws IOException, ClientProtocolException {
Subsegment subsegment = recorder.beginSubsegment(target.getHostName());
return wrapHttpSupplier(subsegment, () -> {
TracedHttpClient.addRequestInformation(subsegment, request, TracedHttpClient.getUrl(target, request));
CloseableHttpResponse response = wrappedClient.execute(target, request, context);
TracedResponseHandler.addResponseInformation(subsegment, response);
return response;
});
}
@Override
public CloseableHttpResponse execute(final HttpUriRequest request, final HttpContext context) throws IOException, ClientProtocolException {
Subsegment subsegment = recorder.beginSubsegment(determineTarget(request).getHostName());
return wrapHttpSupplier(subsegment, () -> {
TracedHttpClient.addRequestInformation(subsegment, request, TracedHttpClient.getUrl(request));
CloseableHttpResponse response = wrappedClient.execute(request, context);
TracedResponseHandler.addResponseInformation(subsegment, response);
return response;
});
}
@Override
public CloseableHttpResponse execute(final HttpUriRequest request) throws IOException, ClientProtocolException {
Subsegment subsegment = recorder.beginSubsegment(determineTarget(request).getHostName());
return wrapHttpSupplier(subsegment, () -> {
TracedHttpClient.addRequestInformation(subsegment, request, TracedHttpClient.getUrl(request));
CloseableHttpResponse response = wrappedClient.execute(request);
TracedResponseHandler.addResponseInformation(subsegment, response);
return response;
});
}
@Override
public CloseableHttpResponse execute(final HttpHost target, final HttpRequest request) throws IOException, ClientProtocolException {
Subsegment subsegment = recorder.beginSubsegment(target.getHostName());
return wrapHttpSupplier(subsegment, () -> {
TracedHttpClient.addRequestInformation(subsegment, request, TracedHttpClient.getUrl(target, request));
CloseableHttpResponse response = wrappedClient.execute(target, request);
TracedResponseHandler.addResponseInformation(subsegment, response);
return response;
});
}
@Override
public <T> T execute(final HttpUriRequest request, final ResponseHandler<? extends T> responseHandler) throws IOException, ClientProtocolException {
Subsegment subsegment = recorder.beginSubsegment(determineTarget(request).getHostName());
return wrapHttpSupplier(subsegment, () -> {
TracedHttpClient.addRequestInformation(subsegment, request, TracedHttpClient.getUrl(request));
TracedResponseHandler<? extends T> wrappedHandler = new TracedResponseHandler<>(responseHandler);
return wrappedClient.execute(request, wrappedHandler);
});
}
@Override
public <T> T execute(final HttpUriRequest request, final ResponseHandler<? extends T> responseHandler, final HttpContext context) throws IOException, ClientProtocolException {
Subsegment subsegment = recorder.beginSubsegment(determineTarget(request).getHostName());
return wrapHttpSupplier(subsegment, () -> {
TracedHttpClient.addRequestInformation(subsegment, request, TracedHttpClient.getUrl(request));
TracedResponseHandler<? extends T> wrappedHandler = new TracedResponseHandler<>(responseHandler);
return wrappedClient.execute(request, wrappedHandler, context);
});
}
@Override
public <T> T execute(final HttpHost target, final HttpRequest request, final ResponseHandler<? extends T> responseHandler) throws IOException, ClientProtocolException {
Subsegment subsegment = recorder.beginSubsegment(target.getHostName());
return wrapHttpSupplier(subsegment, () -> {
TracedHttpClient.addRequestInformation(subsegment, request, TracedHttpClient.getUrl(target, request));
TracedResponseHandler<? extends T> wrappedHandler = new TracedResponseHandler<>(responseHandler);
return wrappedClient.execute(target, request, wrappedHandler);
});
}
@Override
public <T> T execute(final HttpHost target, final HttpRequest request, final ResponseHandler<? extends T> responseHandler, final HttpContext context) throws IOException, ClientProtocolException {
Subsegment subsegment = recorder.beginSubsegment(target.getHostName());
return wrapHttpSupplier(subsegment, () -> {
TracedHttpClient.addRequestInformation(subsegment, request, TracedHttpClient.getUrl(target, request));
TracedResponseHandler<? extends T> wrappedHandler = new TracedResponseHandler<>(responseHandler);
return wrappedClient.execute(target, request, wrappedHandler, context);
});
}
@Override
public ClientConnectionManager getConnectionManager() {
return wrappedClient.getConnectionManager();
}
@Override
public HttpParams getParams() {
return wrappedClient.getParams();
}
@Override
public void close() throws IOException {
wrappedClient.close();
}
@Override
protected CloseableHttpResponse doExecute(HttpHost httpHost, HttpRequest httpRequest, HttpContext httpContext) throws IOException, ClientProtocolException {
// gross hack to call the wrappedClient's doExecute...
// see line 67 of Apache's CloseableHttpClient
return wrappedClient.execute(httpHost, httpRequest, httpContext);
}
}
19
Source : HttpClientBuilder.java
with Apache License 2.0
from aws
with Apache License 2.0
from aws
/**
* Wraps and overrides some of {@code org.apache.http.impl.client.HttpClientBuilder}'s methods. Will build a TracedHttpClient
* wrapping the usual CloseableHttpClient result. Uses the global recorder by default, with an option to provide an alternative.
*/
public clreplaced HttpClientBuilder extends org.apache.http.impl.client.HttpClientBuilder {
private AWSXRayRecorder recorder;
protected HttpClientBuilder() {
super();
}
public static HttpClientBuilder create() {
HttpClientBuilder newBuilder = new HttpClientBuilder();
newBuilder.setRecorder(AWSXRay.getGlobalRecorder());
return newBuilder;
}
public HttpClientBuilder setRecorder(AWSXRayRecorder recorder) {
this.recorder = recorder;
return this;
}
@Override
public CloseableHttpClient build() {
CloseableHttpClient result = super.build();
return new TracedHttpClient(result, recorder);
}
}
19
Source : HttpClientBuilder.java
with Apache License 2.0
from aws
with Apache License 2.0
from aws
public HttpClientBuilder setRecorder(AWSXRayRecorder recorder) {
this.recorder = recorder;
return this;
}
19
Source : ServletHandlerIntegTest.java
with Apache License 2.0
from aws
with Apache License 2.0
from aws
public clreplaced ServletHandlerIntegTest {
private final static String TRACE_HEADER_KEY = TraceHeader.HEADER_KEY;
private final static String PREDEFINED_TRACE_HEADER_SAMPLED = "Root=1-5dc20232-c5f804c16e231025e5cf0d74;Parent=1d62b25534e7d360;Sampled=1";
private final static String PREDEFINED_TRACE_HEADER_NOT_SAMPLED = "Root=1-5dc203d8-8d0b0d30aab25f0cfcfaf63a;Parent=38e0df8c9363d068;Sampled=0";
// This is hardcoded in the Pom.xml file
private final static String SERVICE_NAME = "IntegTest";
private HttpServlet theServlet;
private MockHttpServletRequest request;
private HttpServletResponse response;
private AWSXRayRecorder recorder;
private UDPEmitter mockEmitter;
@Before
public void setup() throws Exception {
theServlet = new SimpleHttpServlet();
request = new MockHttpServletRequest();
request.setMethod("GET");
request.setHeader(TRACE_HEADER_KEY, null);
response = mock(HttpServletResponse.clreplaced);
when(response.getStatus()).thenReturn(200);
mockEmitter = mock(UDPEmitter.clreplaced);
recorder = AWSXRay.getGlobalRecorder();
recorder.setSamplingStrategy(new AllSamplingStrategy());
// Even though we're sampling them all, none are sent. This is to test.
recorder.setEmitter(mockEmitter);
}
@After
public void cleanup() {
AWSXRay.clearTraceEnreplacedy();
}
@Test
public void testReceiveGetRequest() throws Exception {
theServlet.service(request, response);
Segment currentSegment = interceptSegment();
// Check Subsegment properties
verifyHttpSegment(currentSegment);
}
@Test
public void testReceivePostRequest() throws Exception {
request.setMethod("POST");
theServlet.service(request, response);
Segment currentSegment = interceptSegment();
// Check Subsegment properties
verifyHttpSegment(currentSegment);
}
@Test
public void testReceive200() throws Exception {
when(response.getStatus()).thenReturn(200);
theServlet.service(request, response);
Segment currentSegment = interceptSegment();
// Check Subsegment properties
verifyHttpSegment(currentSegment);
}
@Test
public void testReceiveThrottle() throws Exception {
when(response.getStatus()).thenReturn(429);
theServlet.service(request, response);
Segment currentSegment = interceptSegment();
// Check Subsegment properties
verifyHttpSegment(currentSegment);
replacedertTrue(currentSegment.isError());
replacedertTrue(currentSegment.isThrottle());
replacedertFalse(currentSegment.isFault());
}
@Test
public void testReceiveFault() throws Exception {
when(response.getStatus()).thenReturn(500);
theServlet.service(request, response);
Segment currentSegment = interceptSegment();
// Check Subsegment properties
verifyHttpSegment(currentSegment);
replacedertFalse(currentSegment.isError());
replacedertFalse(currentSegment.isThrottle());
replacedertTrue(currentSegment.isFault());
}
@Test
public void testReceiveError() throws Exception {
when(response.getStatus()).thenReturn(400);
theServlet.service(request, response);
Segment currentSegment = interceptSegment();
// Check Subsegment properties
verifyHttpSegment(currentSegment);
replacedertTrue(currentSegment.isError());
replacedertFalse(currentSegment.isThrottle());
replacedertFalse(currentSegment.isFault());
}
@Test
public void testReceiveTraceHeaderSampled() throws Exception {
// Add trace header to X-Ray through the request object.
request.setHeader(TRACE_HEADER_KEY, PREDEFINED_TRACE_HEADER_SAMPLED);
theServlet.service(request, response);
Segment currentSegment = interceptSegment();
verifyHttpSegment(currentSegment);
TraceHeader origTH = TraceHeader.fromString(PREDEFINED_TRACE_HEADER_SAMPLED);
TraceHeader.SampleDecision segmentSampleDecision = TraceHeader.SampleDecision.SAMPLED;
replacedertEquals(origTH.toString(), new TraceHeader(currentSegment.getTraceId(), currentSegment.getParentId(), segmentSampleDecision).toString());
}
@Test
public void testReceiveTraceHeaderUnsampled() throws Exception {
// Add trace header to X-Ray through the request object.
request.setHeader(TRACE_HEADER_KEY, PREDEFINED_TRACE_HEADER_NOT_SAMPLED);
theServlet.service(request, response);
verify(mockEmitter, times(0)).sendSegment(any());
}
private void verifyHttpSegment(Segment segment) {
replacedertEquals(SERVICE_NAME, segment.getName());
Map<String, String> httpRequestMap = (Map<String, String>) segment.getHttp().get("request");
replacedertEquals(request.getMethod(), httpRequestMap.get("method"));
replacedertEquals(request.getRemoteAddr(), httpRequestMap.get("client_ip"));
replacedertEquals(request.getRequestURL().toString(), httpRequestMap.get("url"));
Map<String, String> httpResponseMap = (Map<String, String>) segment.getHttp().get("response");
replacedertEquals(response.getStatus(), httpResponseMap.get("status"));
}
// Return the segment generated by the call to the servlet.
// Returns null if none had been intercepted.
private Segment interceptSegment() {
ArgumentCaptor<Segment> segmentArgumentCaptor = ArgumentCaptor.forClreplaced(Segment.clreplaced);
verify(mockEmitter).sendSegment(segmentArgumentCaptor.capture());
List<Segment> capturedSegments = segmentArgumentCaptor.getAllValues();
// This should only be called after a single call to sendSegment has been made.
replacedertEquals(1, capturedSegments.size());
try {
return capturedSegments.get(0);
} catch (IndexOutOfBoundsException e) {
return null;
}
}
}
19
Source : ClientProvider.java
with Apache License 2.0
from aws
with Apache License 2.0
from aws
public static AmazonDynamoDB instrumentedV1Client(AWSXRayRecorder recorder) {
return (AmazonDynamoDB) getTestableV1Client(AmazonDynamoDBClientBuilder.standard()).withRequestHandlers(new TracingHandler(recorder)).build();
}
19
Source : BenchmarkUtils.java
with Apache License 2.0
from aws
with Apache License 2.0
from aws
/**
* This initializes the static recorder if the agent is not present, and ensures we don't actually emit
* segments regardless of whether or not we're using the agent
*
* @return the configured X-Ray recorder, also retrievable by AWSXRay.getGlobalRecorder
*/
public static AWSXRayRecorder configureXRayRecorder() {
AWSXRayRecorder recorder = AWSXRay.getGlobalRecorder();
recorder.setEmitter(new NoOpEmitter());
recorder.setSamplingStrategy(new AllSamplingStrategy());
return AWSXRay.getGlobalRecorder();
}
19
Source : XRaySDKConfigurationTest.java
with Apache License 2.0
from aws
with Apache License 2.0
from aws
@Test
public void testLazyLoadTraceIdInjection() {
AWSXRayRecorder recorder = AWSXRayRecorderBuilder.defaultRecorder();
config.setAgentConfiguration(new AgentConfiguration());
config.lazyLoadTraceIdInjection(recorder);
replacedert.replacedertEquals(2, recorder.getSegmentListeners().size());
}
19
Source : XRayTransactionContext.java
with Apache License 2.0
from aws
with Apache License 2.0
from aws
@Override
public void endSubsegment(AWSXRayRecorder recorder) {
Enreplacedy current = getTraceEnreplacedy();
if (current instanceof Subsegment) {
if (log.isDebugEnabled()) {
log.debug("Ending subsegment named: " + current.getName());
}
Subsegment currentSubsegment = (Subsegment) current;
if (currentSubsegment.end()) {
recorder.sendSegment(currentSubsegment.getParentSegment());
} else {
if (recorder.getStreamingStrategy().requiresStreaming(currentSubsegment.getParentSegment())) {
recorder.getStreamingStrategy().streamSome(currentSubsegment.getParentSegment(), recorder.getEmitter());
}
setTraceEnreplacedy(current.getParent());
}
} else {
recorder.getContextMissingStrategy().contextMissing("Failed to end subsegment: subsegment cannot be found.", SubsegmentNotFoundException.clreplaced);
}
}
19
Source : XRaySDKConfiguration.java
with Apache License 2.0
from aws
with Apache License 2.0
from aws
/**
* Attempts to enable trace ID injection via reflection. This can be called during runtime as opposed to agent
* startup in case required trace ID injection clreplacedes aren't available on the clreplacedpath during premain.
*
* @param recorder - the X-Ray Recorder to configure
*/
public void lazyLoadTraceIdInjection(AWSXRayRecorder recorder) {
// Fail fast if injection disabled or we've already tried to lazy load
if (!agentConfiguration.isTraceIdInjection() || traceIdInjectionConfigured) {
return;
}
traceIdInjectionConfigured = true;
// We must use the context clreplaced loader because the whole reason we're lazy loading the injection libraries
// is that they're only visible to the clreplacedloader used by the customer app
recorder.addAllSegmentListeners(getTraceIdInjectorsReflectively(Thread.currentThread().getContextClreplacedLoader()));
}
18
Source : AWSXRayServletAsyncListener.java
with Apache License 2.0
from aws
with Apache License 2.0
from aws
private void processEvent(AsyncEvent event) throws IOException {
AWSXRayRecorder recorder = getRecorder();
Enreplacedy enreplacedy = (Enreplacedy) event.getSuppliedRequest().getAttribute(ENreplacedY_ATTRIBUTE_KEY);
enreplacedy.run(() -> {
if (event.getThrowable() != null) {
enreplacedy.addException(event.getThrowable());
}
filter.postFilter(event.getSuppliedRequest(), event.getSuppliedResponse());
});
}
18
Source : DummySegment.java
with Apache License 2.0
from aws
with Apache License 2.0
from aws
/**
* @deprecated Use {@link Segment#noOp(TraceID, AWSXRayRecorder)}.
*/
@Deprecated
public clreplaced DummySegment implements Segment {
private Cause cause = new Cause();
private Map<String, Object> map = new ConcurrentHashMap<>();
private Map<String, Map<String, Object>> metadataMap = new ConcurrentHashMap<>();
private List<Subsegment> list = new ArrayList<>();
private LongAdder longAdder = new LongAdder();
private ReentrantLock lock = new ReentrantLock();
private String name = "";
private String origin = "";
private double startTime;
private double endTime;
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
private boolean fault;
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
private boolean error;
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
private boolean throttle;
private AWSXRayRecorder creator;
private TraceID traceId;
public DummySegment(AWSXRayRecorder creator, String name, TraceID traceId) {
this(creator, traceId);
this.name = name;
}
public DummySegment(AWSXRayRecorder creator) {
this(creator, TraceID.create(creator));
}
public DummySegment(AWSXRayRecorder creator, TraceID traceId) {
this.startTime = System.currentTimeMillis() / 1000.0d;
this.creator = creator;
this.traceId = traceId;
}
@Override
public String getName() {
return name;
}
@Override
public String getId() {
return "";
}
@Override
public void setId(String id) {
}
@Override
public double getStartTime() {
return startTime;
}
@Override
public void setStartTime(double startTime) {
this.startTime = startTime;
}
@Override
public double getEndTime() {
return endTime;
}
@Override
public void setEndTime(double endTime) {
this.endTime = endTime;
}
@Override
public boolean isFault() {
return fault;
}
@Override
public void setFault(boolean fault) {
this.fault = fault;
}
@Override
public boolean isError() {
return error;
}
@Override
public void setError(boolean error) {
this.error = error;
}
@Override
public String getNamespace() {
return "";
}
@Override
public void setNamespace(String namespace) {
}
@Override
public Cause getCause() {
return cause;
}
@Override
public Map<String, Object> getHttp() {
return map;
}
@Override
public void setHttp(Map<String, Object> http) {
}
@Override
public Map<String, Object> getAws() {
return map;
}
@Override
public void setAws(Map<String, Object> aws) {
}
@Override
public Map<String, Object> getSql() {
return map;
}
@Override
public void setSql(Map<String, Object> sql) {
}
@Override
public Map<String, Map<String, Object>> getMetadata() {
return metadataMap;
}
@Override
public void setMetadata(Map<String, Map<String, Object>> metadata) {
}
@Override
public void setAnnotations(Map<String, Object> annotations) {
}
@Override
public Enreplacedy getParent() {
return this;
}
@Override
public void setParent(Enreplacedy parent) {
}
@Override
public boolean isThrottle() {
return throttle;
}
@Override
public void setThrottle(boolean throttle) {
this.throttle = throttle;
}
@Override
public boolean isInProgress() {
return false;
}
@Override
public void setInProgress(boolean inProgress) {
}
@Override
public TraceID getTraceId() {
return traceId;
}
@Override
public void setTraceId(TraceID traceId) {
}
/**
* @return the creator
*/
@Override
public AWSXRayRecorder getCreator() {
return creator;
}
/**
* @param creator the creator to set
*/
@Override
public void setCreator(AWSXRayRecorder creator) {
this.creator = creator;
}
@Override
public String getParentId() {
return "";
}
@Override
public void setParentId(@Nullable String parentId) {
}
@Override
public List<Subsegment> getSubsegments() {
return list;
}
@Override
public void addSubsegment(Subsegment subsegment) {
}
@Override
public void addException(Throwable exception) {
}
@Override
public void putHttp(String key, Object value) {
}
@Override
public void putAllHttp(Map<String, Object> all) {
}
@Override
public void putAws(String key, Object value) {
}
@Override
public void putAllAws(Map<String, Object> all) {
}
@Override
public void putSql(String key, Object value) {
}
@Override
public void putAllSql(Map<String, Object> all) {
}
@Override
public void putAnnotation(String key, String value) {
}
@Override
public void putAnnotation(String key, Number value) {
}
@Override
public void putAnnotation(String key, Boolean value) {
}
@Override
public void putMetadata(String key, Object object) {
}
@Override
public void putMetadata(String namespace, String key, Object object) {
}
@Override
public boolean isEmitted() {
return false;
}
@Override
public void setEmitted(boolean emitted) {
}
@Override
public String serialize() {
return "";
}
@Override
public String prettySerialize() {
return "";
}
@Override
public boolean end() {
if (getEndTime() < Double.MIN_NORMAL) {
setEndTime(System.currentTimeMillis() / 1000.0d);
}
return false;
}
@Override
public boolean isRecording() {
return false;
}
@Override
public void putService(String key, Object object) {
}
@Override
public boolean isSampled() {
return false;
}
@Override
public void setSampled(boolean sampled) {
}
@Override
public int getReferenceCount() {
return 0;
}
@Override
public LongAdder getTotalSize() {
return longAdder;
}
@Override
public void incrementReferenceCount() {
}
@Override
public boolean decrementReferenceCount() {
return false;
}
@Override
public String getResourceArn() {
return "";
}
@Override
public void setResourceArn(String resourceArn) {
}
@Override
public String getUser() {
return "";
}
@Override
public void setUser(String user) {
}
@Override
public String getOrigin() {
return origin;
}
@Override
public void setOrigin(String origin) {
this.origin = origin;
}
@Override
public Map<String, Object> getService() {
return map;
}
@Override
public Map<String, Object> getAnnotations() {
return map;
}
@Override
public Segment getParentSegment() {
return this;
}
@Override
public void close() {
}
@Override
public ReentrantLock getSubsegmentsLock() {
return lock;
}
@Override
public void setSubsegmentsLock(ReentrantLock subsegmentsLock) {
}
@Override
public void putAllService(Map<String, Object> all) {
}
@Override
public void setService(Map<String, Object> service) {
}
@Override
public void removeSubsegment(Subsegment subsegment) {
}
@Override
public void setRuleName(String name) {
}
}
18
Source : ThreadLocalSegmentContext.java
with Apache License 2.0
from aws
with Apache License 2.0
from aws
@Override
public Subsegment beginSubsegment(AWSXRayRecorder recorder, String name) {
Enreplacedy current = getTraceEnreplacedy();
if (current == null) {
recorder.getContextMissingStrategy().contextMissing("Failed to begin subsegment named '" + name + "': segment cannot be found.", SegmentNotFoundException.clreplaced);
return Subsegment.noOp(recorder);
}
if (logger.isDebugEnabled()) {
logger.debug("Beginning subsegment named: " + name);
}
Segment parentSegment = current.getParentSegment();
Subsegment subsegment = parentSegment.isRecording() ? new SubsegmentImpl(recorder, name, parentSegment) : Subsegment.noOp(parentSegment, recorder);
subsegment.setParent(current);
current.addSubsegment(subsegment);
setTraceEnreplacedy(subsegment);
List<SegmentListener> segmentListeners = recorder.getSegmentListeners();
segmentListeners.stream().filter(Objects::nonNull).forEach(listener -> listener.onBeginSubsegment(subsegment));
return subsegment;
}
18
Source : LambdaSegmentContext.java
with Apache License 2.0
from aws
with Apache License 2.0
from aws
@Override
public Subsegment beginSubsegment(AWSXRayRecorder recorder, String name) {
if (logger.isDebugEnabled()) {
logger.debug("Beginning subsegment named: " + name);
}
Enreplacedy enreplacedy = getTraceEnreplacedy();
if (enreplacedy == null) {
// First subsgment of a subsegment branch.
Segment parentSegment = newFacadeSegment(recorder, name);
Subsegment subsegment = parentSegment.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);
setTraceEnreplacedy(subsegment);
return subsegment;
} else {
// Continuation of a subsegment branch.
Subsegment parentSubsegment = (Subsegment) enreplacedy;
// Ensure customers have not leaked subsegments across invocations
TraceID environmentRootTraceId = LambdaSegmentContext.getTraceHeaderFromEnvironment().getRootTraceId();
if (environmentRootTraceId != null && !environmentRootTraceId.equals(parentSubsegment.getParentSegment().getTraceId())) {
clearTraceEnreplacedy();
return beginSubsegment(recorder, name);
}
Segment parentSegment = parentSubsegment.getParentSegment();
Subsegment subsegment = parentSegment.isRecording() ? new SubsegmentImpl(recorder, name, parentSegment) : Subsegment.noOp(parentSegment, recorder);
subsegment.setParent(parentSubsegment);
parentSubsegment.addSubsegment(subsegment);
setTraceEnreplacedy(subsegment);
List<SegmentListener> segmentListeners = recorder.getSegmentListeners();
segmentListeners.stream().filter(Objects::nonNull).forEach(listener -> listener.onBeginSubsegment(subsegment));
return subsegment;
}
}
18
Source : XRayTransactionContext.java
with Apache License 2.0
from aws
with Apache License 2.0
from aws
@Override
public Subsegment beginSubsegment(AWSXRayRecorder recorder, String name) {
Enreplacedy current = getTraceEnreplacedy();
if (null == current) {
recorder.getContextMissingStrategy().contextMissing("Failed to begin subsegment named '" + name + "': segment cannot be found.", SegmentNotFoundException.clreplaced);
return Subsegment.noOp(recorder);
}
if (log.isDebugEnabled()) {
log.debug("Beginning subsegment named: " + name);
}
Segment parentSegment = getTraceEnreplacedy().getParentSegment();
Subsegment subsegment = new SubsegmentImpl(recorder, name, parentSegment);
subsegment.setParent(current);
current.addSubsegment(subsegment);
setTraceEnreplacedy(subsegment);
return subsegment;
}
17
Source : EntityImpl.java
with Apache License 2.0
from aws
with Apache License 2.0
from aws
/**
* The base clreplaced from which {@code Segment} and {@code Subsegment} extend.
*/
public abstract clreplaced EnreplacedyImpl implements Enreplacedy {
/**
* @deprecated For internal use only.
*/
@SuppressWarnings("checkstyle:ConstantName")
@Deprecated
protected static final ObjectMapper mapper = new ObjectMapper().setPropertyNamingStrategy(PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES).setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
private static final Log logger = LogFactory.getLog(EnreplacedyImpl.clreplaced);
private static final String DEFAULT_METADATA_NAMESPACE = "default";
protected final Object lock = new Object();
private final String name;
/*
* Reference counter to track how many subsegments are in progress on this enreplacedy. Starts with a value of 0.
*/
@JsonIgnore
protected int referenceCount;
@JsonIgnore
protected LongAdder totalSize;
@GuardedBy("lock")
private String id;
@GuardedBy("lock")
@Nullable
private String parentId;
@GuardedBy("lock")
private double startTime;
@JsonInclude(Include.NON_DEFAULT)
@JsonSerialize(using = ToStringSerializer.clreplaced)
@GuardedBy("lock")
private TraceID traceId;
@JsonInclude(Include.NON_DEFAULT)
@GuardedBy("lock")
private double endTime;
@JsonInclude(Include.NON_DEFAULT)
@GuardedBy("lock")
private boolean fault;
@JsonInclude(Include.NON_DEFAULT)
@GuardedBy("lock")
private boolean error;
@JsonInclude(Include.NON_DEFAULT)
@GuardedBy("lock")
private boolean throttle;
@JsonInclude(Include.NON_DEFAULT)
@GuardedBy("lock")
private boolean inProgress;
@Nullable
@GuardedBy("lock")
private String namespace;
// TODO(anuraaga): Check final for other variables, for now this is most important since it's also a lock.
private final List<Subsegment> subsegments;
@GuardedBy("lock")
private Cause cause;
@GuardedBy("lock")
private Map<String, Object> http;
@GuardedBy("lock")
private Map<String, Object> aws;
@GuardedBy("lock")
private Map<String, Object> sql;
@GuardedBy("lock")
private Map<String, Map<String, Object>> metadata;
@GuardedBy("lock")
private Map<String, Object> annotations;
@JsonIgnore
@GuardedBy("lock")
private Enreplacedy parent;
@JsonIgnore
@GuardedBy("lock")
private AWSXRayRecorder creator;
@JsonIgnore
@GuardedBy("lock")
private ReentrantLock subsegmentsLock;
@JsonIgnore
@GuardedBy("lock")
private boolean emitted = false;
static {
/*
* Inject the CauseSerializer and StackTraceElementSerializer clreplacedes into the local mapper such that they will serialize
* their respective object types.
*/
mapper.registerModule(new SimpleModule() {
private static final long serialVersionUID = 545800949242254918L;
@Override
public void setupModule(SetupContext setupContext) {
super.setupModule(setupContext);
setupContext.addBeanSerializerModifier(new BeanSerializerModifier() {
@SuppressWarnings("unchecked")
@Override
public JsonSerializer<?> modifySerializer(SerializationConfig serializationConfig, BeanDescription beanDescription, JsonSerializer<?> jsonSerializer) {
Clreplaced<?> beanClreplaced = beanDescription.getBeanClreplaced();
if (Cause.clreplaced.isreplacedignableFrom(beanClreplaced)) {
return new CauseSerializer((JsonSerializer<Object>) jsonSerializer);
} else if (StackTraceElement.clreplaced.isreplacedignableFrom(beanClreplaced)) {
return new StackTraceElementSerializer();
}
return jsonSerializer;
}
});
}
});
}
// default constructor for Jackson, so it can understand the default values to compare when using the Include.NON_DEFAULT
// annotation.
@SuppressWarnings("nullness")
protected EnreplacedyImpl() {
// TODO(anuraaga): Check this is working as intended, empty lists are currently serialized.
subsegments = null;
name = null;
}
// TODO(anuraaga): Refactor the enreplacedy relationship. There isn't a great reason to use a type hierarchy for data clreplacedes and
// it makes the code to hard to reason about e.g., nullness.
@SuppressWarnings("nullness")
protected EnreplacedyImpl(AWSXRayRecorder creator, String name) {
StringValidator.throwIfNullOrBlank(name, "(Sub)segment name cannot be null or blank.");
validateNotNull(creator);
this.creator = creator;
this.name = name;
this.subsegments = new ArrayList<>();
this.subsegmentsLock = new ReentrantLock();
this.cause = new Cause();
this.http = new HashMap<>();
this.aws = new HashMap<>();
this.sql = new HashMap<>();
this.annotations = new HashMap<>();
this.metadata = new HashMap<>();
this.startTime = System.currentTimeMillis() / 1000d;
this.id = creator.getIdGenerator().newEnreplacedyId();
this.inProgress = true;
this.referenceCount = 0;
this.totalSize = new LongAdder();
}
/**
* Checks if the enreplacedy has already been emitted to the X-Ray daemon.
*
* @throws AlreadyEmittedException
* if the enreplacedy has already been emitted to the X-Ray daemon and the ContextMissingStrategy of the
* AWSXRayRecorder used to create this enreplacedy is configured to throw exceptions
*/
protected void checkAlreadyEmitted() {
synchronized (lock) {
if (emitted) {
getCreator().getContextMissingStrategy().contextMissing("Segment " + getName() + " has already been emitted.", AlreadyEmittedException.clreplaced);
}
}
}
@Override
public String getName() {
return name;
}
@Override
public String getId() {
synchronized (lock) {
return id;
}
}
@Override
public void setId(String id) {
synchronized (lock) {
checkAlreadyEmitted();
this.id = id;
}
}
@Override
public double getStartTime() {
synchronized (lock) {
return startTime;
}
}
@Override
public void setStartTime(double startTime) {
synchronized (lock) {
checkAlreadyEmitted();
this.startTime = startTime;
}
}
@Override
public double getEndTime() {
synchronized (lock) {
return endTime;
}
}
@Override
public void setEndTime(double endTime) {
synchronized (lock) {
checkAlreadyEmitted();
this.endTime = endTime;
}
}
@Override
public boolean isFault() {
synchronized (lock) {
return fault;
}
}
@Override
public void setFault(boolean fault) {
synchronized (lock) {
checkAlreadyEmitted();
this.fault = fault;
}
}
@Override
public boolean isError() {
synchronized (lock) {
return error;
}
}
@Override
public void setError(boolean error) {
synchronized (lock) {
checkAlreadyEmitted();
this.error = error;
}
}
@Override
@Nullable
public String getNamespace() {
synchronized (lock) {
return namespace;
}
}
@Override
public void setNamespace(String namespace) {
synchronized (lock) {
checkAlreadyEmitted();
this.namespace = namespace;
}
}
@Override
public ReentrantLock getSubsegmentsLock() {
synchronized (lock) {
return subsegmentsLock;
}
}
@Override
public void setSubsegmentsLock(ReentrantLock subsegmentsLock) {
synchronized (lock) {
checkAlreadyEmitted();
this.subsegmentsLock = subsegmentsLock;
}
}
@Override
public Cause getCause() {
synchronized (lock) {
return cause;
}
}
@Override
public Map<String, Object> getHttp() {
synchronized (lock) {
return http;
}
}
@Override
public void setHttp(Map<String, Object> http) {
synchronized (lock) {
checkAlreadyEmitted();
this.http = http;
}
}
@Override
public Map<String, Object> getAws() {
synchronized (lock) {
return aws;
}
}
@Override
public void setAws(Map<String, Object> aws) {
synchronized (lock) {
checkAlreadyEmitted();
this.aws = aws;
}
}
@Override
public Map<String, Object> getSql() {
synchronized (lock) {
return sql;
}
}
@Override
public void setSql(Map<String, Object> sql) {
synchronized (lock) {
checkAlreadyEmitted();
this.sql = sql;
}
}
@Override
public Map<String, Map<String, Object>> getMetadata() {
synchronized (lock) {
return metadata;
}
}
@Override
public void setMetadata(Map<String, Map<String, Object>> metadata) {
synchronized (lock) {
checkAlreadyEmitted();
this.metadata = metadata;
}
}
@Override
public Map<String, Object> getAnnotations() {
synchronized (lock) {
return annotations;
}
}
@Override
public void setAnnotations(Map<String, Object> annotations) {
synchronized (lock) {
checkAlreadyEmitted();
this.annotations = annotations;
}
}
@Override
public Enreplacedy getParent() {
synchronized (lock) {
return parent;
}
}
@Override
public void setParent(Enreplacedy parent) {
synchronized (lock) {
checkAlreadyEmitted();
this.parent = parent;
}
}
/**
* @return the creator
*/
@Override
public AWSXRayRecorder getCreator() {
synchronized (lock) {
return creator;
}
}
/**
* @param creator the creator to set
*/
@Override
public void setCreator(AWSXRayRecorder creator) {
synchronized (lock) {
checkAlreadyEmitted();
this.creator = creator;
}
}
@Override
public boolean isThrottle() {
synchronized (lock) {
return throttle;
}
}
@Override
public void setThrottle(boolean throttle) {
synchronized (lock) {
checkAlreadyEmitted();
if (throttle) {
this.fault = false;
this.error = true;
}
this.throttle = throttle;
}
}
@Override
public boolean isInProgress() {
synchronized (lock) {
return inProgress;
}
}
@Override
public void setInProgress(boolean inProgress) {
synchronized (lock) {
checkAlreadyEmitted();
this.inProgress = inProgress;
}
}
@Override
public TraceID getTraceId() {
synchronized (lock) {
return traceId;
}
}
@Override
@EnsuresNonNull("this.traceId")
public void setTraceId(TraceID traceId) {
synchronized (lock) {
checkAlreadyEmitted();
this.traceId = traceId;
}
}
@Override
@Nullable
public String getParentId() {
synchronized (lock) {
return parentId;
}
}
@Override
public void setParentId(@Nullable String parentId) {
synchronized (lock) {
checkAlreadyEmitted();
this.parentId = parentId;
}
}
@JsonIgnore
@Override
public abstract Segment getParentSegment();
@Override
public List<Subsegment> getSubsegments() {
synchronized (lock) {
return subsegments;
}
}
@Override
public void addSubsegment(Subsegment subsegment) {
synchronized (lock) {
checkAlreadyEmitted();
getSubsegmentsLock().lock();
try {
subsegments.add(subsegment);
} finally {
getSubsegmentsLock().unlock();
}
}
}
@Override
public void addException(Throwable exception) {
synchronized (lock) {
checkAlreadyEmitted();
setFault(true);
getSubsegmentsLock().lock();
try {
cause.addExceptions(creator.getThrowableSerializationStrategy().describeInContext(this, exception, subsegments));
} finally {
getSubsegmentsLock().unlock();
}
}
}
@Override
public void putHttp(String key, Object value) {
synchronized (lock) {
checkAlreadyEmitted();
validateNotNull(key);
validateNotNull(value);
http.put(key, value);
}
}
@Override
public void putAllHttp(Map<String, Object> all) {
synchronized (lock) {
checkAlreadyEmitted();
validateNotNull(all);
http.putAll(all);
}
}
@Override
public void putAws(String key, Object value) {
synchronized (lock) {
checkAlreadyEmitted();
validateNotNull(key);
validateNotNull(value);
aws.put(key, value);
}
}
@Override
public void putAllAws(Map<String, Object> all) {
synchronized (lock) {
checkAlreadyEmitted();
validateNotNull(all);
aws.putAll(all);
}
}
@Override
public void putSql(String key, Object value) {
synchronized (lock) {
checkAlreadyEmitted();
validateNotNull(key);
validateNotNull(value);
sql.put(key, value);
}
}
@Override
public void putAllSql(Map<String, Object> all) {
synchronized (lock) {
checkAlreadyEmitted();
validateNotNull(all);
sql.putAll(all);
}
}
@Override
public void putAnnotation(String key, String value) {
synchronized (lock) {
checkAlreadyEmitted();
validateNotNull(key);
validateNotNull(value);
annotations.put(key, value);
}
}
@Override
public void putAnnotation(String key, Number value) {
synchronized (lock) {
checkAlreadyEmitted();
validateNotNull(key);
validateNotNull(value);
annotations.put(key, value);
}
}
@Override
public void putAnnotation(String key, Boolean value) {
synchronized (lock) {
checkAlreadyEmitted();
validateNotNull(key);
validateNotNull(value);
annotations.put(key, value);
}
}
@Override
public void putMetadata(String key, Object object) {
synchronized (lock) {
checkAlreadyEmitted();
putMetadata(DEFAULT_METADATA_NAMESPACE, key, object);
}
}
@Override
public void putMetadata(String namespace, String key, Object object) {
synchronized (lock) {
checkAlreadyEmitted();
validateNotNull(namespace);
validateNotNull(key);
if (null == object) {
object = NullNode.instance;
}
metadata.computeIfAbsent(namespace, unused -> new HashMap<>()).put(key, object);
}
}
@Override
public void incrementReferenceCount() {
synchronized (lock) {
checkAlreadyEmitted();
referenceCount++;
totalSize.increment();
}
}
@Override
public boolean decrementReferenceCount() {
synchronized (lock) {
checkAlreadyEmitted();
referenceCount--;
return !isInProgress() && referenceCount <= 0;
}
}
/**
* Returns the reference count of the segment. This number represents how many open subsegments are children of this segment.
* The segment is emitted when its reference count reaches 0.
*
* @return the reference count
*/
@Override
public int getReferenceCount() {
synchronized (lock) {
return referenceCount;
}
}
/**
* @return the totalSize
*/
@Override
public LongAdder getTotalSize() {
synchronized (lock) {
return totalSize;
}
}
/**
* @return the emitted
*/
@Override
public boolean isEmitted() {
synchronized (lock) {
return emitted;
}
}
/**
* @param emitted
* the emitted to set
*/
@Override
public void setEmitted(boolean emitted) {
synchronized (lock) {
checkAlreadyEmitted();
this.emitted = emitted;
}
}
@Override
public String serialize() {
synchronized (lock) {
try {
return mapper.writeValuereplacedtring(this);
} catch (JsonProcessingException jpe) {
logger.error("Exception while serializing enreplacedy.", jpe);
}
return "";
}
}
@Override
public String prettySerialize() {
synchronized (lock) {
try {
return mapper.writerWithDefaultPrettyPrinter().writeValuereplacedtring(this);
} catch (JsonProcessingException jpe) {
logger.error("Exception while serializing segment.", jpe);
}
return "";
}
}
@Override
public void removeSubsegment(Subsegment subsegment) {
synchronized (lock) {
getSubsegmentsLock().lock();
try {
subsegments.remove(subsegment);
} finally {
getSubsegmentsLock().unlock();
}
getParentSegment().getTotalSize().decrement();
}
}
public static void validateNotNull(Object object) {
if (null == object) {
throw new NullPointerException();
}
}
}
See More Examples