[Agent Core] Support lazy ContextCarrier injection and lazy peer id setting (#4462)
* Support lazy ContextCarrier injection and lazy peer id setting for exit span * Close the set component id for exit and local spans * Follow the review. * Remove `void inject(AbstractSpan exitSpan, ContextCarrier carrier)` from AbstractTracerContext
This commit is contained in:
parent
0439dccc30
commit
74b0af9d85
|
|
@ -82,7 +82,8 @@ public interface AbstractTracerContext {
|
|||
* Create an exit span
|
||||
*
|
||||
* @param operationName most likely a service name of remote
|
||||
* @param remotePeer the network id(ip:port, hostname:port or ip1:port1,ip2,port, etc.)
|
||||
* @param remotePeer the network id(ip:port, hostname:port or ip1:port1,ip2,port, etc.). Remote peer could be set
|
||||
* later, but must be before injecting.
|
||||
* @return the span represent an exit point of this segment.
|
||||
*/
|
||||
AbstractSpan createExitSpan(String operationName, String remotePeer);
|
||||
|
|
|
|||
|
|
@ -29,12 +29,12 @@ import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
|
|||
import org.apache.skywalking.apm.agent.core.context.trace.AbstractTracingSpan;
|
||||
import org.apache.skywalking.apm.agent.core.context.trace.EntrySpan;
|
||||
import org.apache.skywalking.apm.agent.core.context.trace.ExitSpan;
|
||||
import org.apache.skywalking.apm.agent.core.context.trace.ExitTypeSpan;
|
||||
import org.apache.skywalking.apm.agent.core.context.trace.LocalSpan;
|
||||
import org.apache.skywalking.apm.agent.core.context.trace.NoopExitSpan;
|
||||
import org.apache.skywalking.apm.agent.core.context.trace.NoopSpan;
|
||||
import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment;
|
||||
import org.apache.skywalking.apm.agent.core.context.trace.TraceSegmentRef;
|
||||
import org.apache.skywalking.apm.agent.core.context.trace.WithPeerInfo;
|
||||
import org.apache.skywalking.apm.agent.core.dictionary.DictionaryManager;
|
||||
import org.apache.skywalking.apm.agent.core.dictionary.DictionaryUtil;
|
||||
import org.apache.skywalking.apm.agent.core.logging.api.ILog;
|
||||
|
|
@ -129,21 +129,37 @@ public class TracingContext implements AbstractTracerContext {
|
|||
* Inject the context into the given carrier, only when the active span is an exit one.
|
||||
*
|
||||
* @param carrier to carry the context for crossing process.
|
||||
* @throws IllegalStateException if the active span isn't an exit one. Ref to {@link AbstractTracerContext#inject(ContextCarrier)}
|
||||
* @throws IllegalStateException if (1) the active span isn't an exit one. (2) doesn't include peer. Ref to {@link
|
||||
* AbstractTracerContext#inject(ContextCarrier)}
|
||||
*/
|
||||
@Override
|
||||
public void inject(ContextCarrier carrier) {
|
||||
AbstractSpan span = this.activeSpan();
|
||||
if (!span.isExit()) {
|
||||
this.inject(this.activeSpan(), carrier);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject the context into the given carrier and given span, only when the active span is an exit one. This method
|
||||
* wouldn't be opened in {@link ContextManager} like {@link #inject(ContextCarrier)}, it is only supported to be
|
||||
* called inside the {@link ExitTypeSpan#inject(ContextCarrier)}
|
||||
*
|
||||
* @param carrier to carry the context for crossing process.
|
||||
* @param exitSpan to represent the scope of current injection.
|
||||
* @throws IllegalStateException if (1) the span isn't an exit one. (2) doesn't include peer.
|
||||
*/
|
||||
public void inject(AbstractSpan exitSpan, ContextCarrier carrier) {
|
||||
if (!exitSpan.isExit()) {
|
||||
throw new IllegalStateException("Inject can be done only in Exit Span");
|
||||
}
|
||||
|
||||
WithPeerInfo spanWithPeer = (WithPeerInfo) span;
|
||||
ExitTypeSpan spanWithPeer = (ExitTypeSpan) exitSpan;
|
||||
String peer = spanWithPeer.getPeer();
|
||||
int peerId = spanWithPeer.getPeerId();
|
||||
if (StringUtil.isEmpty(peer) && DictionaryUtil.isNull(peerId)) {
|
||||
throw new IllegalStateException("Exit span doesn't include meaningful peer information.");
|
||||
}
|
||||
|
||||
carrier.setTraceSegmentId(this.segment.getTraceSegmentId());
|
||||
carrier.setSpanId(span.getSpanId());
|
||||
carrier.setSpanId(exitSpan.getSpanId());
|
||||
|
||||
carrier.setParentServiceInstanceId(segment.getApplicationInstanceId());
|
||||
|
||||
|
|
@ -235,7 +251,8 @@ public class TracingContext implements AbstractTracerContext {
|
|||
@Override
|
||||
public ContextSnapshot capture() {
|
||||
List<TraceSegmentRef> refs = this.segment.getRefs();
|
||||
ContextSnapshot snapshot = new ContextSnapshot(segment.getTraceSegmentId(), activeSpan().getSpanId(), segment.getRelatedGlobalTraces());
|
||||
ContextSnapshot snapshot = new ContextSnapshot(
|
||||
segment.getTraceSegmentId(), activeSpan().getSpanId(), segment.getRelatedGlobalTraces());
|
||||
int entryOperationId;
|
||||
String entryOperationName = "";
|
||||
int entryApplicationInstanceId;
|
||||
|
|
@ -332,15 +349,23 @@ public class TracingContext implements AbstractTracerContext {
|
|||
if (parentSpan != null && parentSpan.isEntry()) {
|
||||
entrySpan = (AbstractTracingSpan) DictionaryManager.findEndpointSection()
|
||||
.findOnly(segment.getServiceId(), operationName)
|
||||
.doInCondition(parentSpan::setOperationId, () -> parentSpan
|
||||
.setOperationName(operationName));
|
||||
.doInCondition(
|
||||
parentSpan::setOperationId, () -> parentSpan
|
||||
.setOperationName(operationName));
|
||||
return entrySpan.start();
|
||||
} else {
|
||||
entrySpan = (AbstractTracingSpan) DictionaryManager.findEndpointSection()
|
||||
.findOnly(segment.getServiceId(), operationName)
|
||||
.doInCondition(operationId -> new EntrySpan(spanIdGenerator++, parentSpanId, operationId, owner), () -> {
|
||||
return new EntrySpan(spanIdGenerator++, parentSpanId, operationName, owner);
|
||||
});
|
||||
.doInCondition(
|
||||
operationId -> new EntrySpan(spanIdGenerator++,
|
||||
parentSpanId,
|
||||
operationId, owner
|
||||
), () -> {
|
||||
return new EntrySpan(
|
||||
spanIdGenerator++, parentSpanId,
|
||||
operationName, owner
|
||||
);
|
||||
});
|
||||
entrySpan.start();
|
||||
return push(entrySpan);
|
||||
}
|
||||
|
|
@ -373,7 +398,8 @@ public class TracingContext implements AbstractTracerContext {
|
|||
* Create an exit span
|
||||
*
|
||||
* @param operationName most likely a service name of remote
|
||||
* @param remotePeer the network id(ip:port, hostname:port or ip1:port1,ip2,port, etc.)
|
||||
* @param remotePeer the network id(ip:port, hostname:port or ip1:port1,ip2,port, etc.). Remote peer could be set
|
||||
* later, but must be before injecting.
|
||||
* @return the span represent an exit point of this segment.
|
||||
* @see ExitSpan
|
||||
*/
|
||||
|
|
@ -391,11 +417,21 @@ public class TracingContext implements AbstractTracerContext {
|
|||
exitSpan = parentSpan;
|
||||
} else {
|
||||
final int parentSpanId = parentSpan == null ? -1 : parentSpan.getSpanId();
|
||||
exitSpan = (AbstractSpan) DictionaryManager.findNetworkAddressSection()
|
||||
.find(remotePeer)
|
||||
.doInCondition(peerId -> new ExitSpan(spanIdGenerator++, parentSpanId, operationName, peerId, owner), () -> {
|
||||
return new ExitSpan(spanIdGenerator++, parentSpanId, operationName, remotePeer, owner);
|
||||
});
|
||||
if (StringUtil.isEmpty(remotePeer)) {
|
||||
exitSpan = new ExitSpan(spanIdGenerator++, parentSpanId, operationName, owner);
|
||||
} else {
|
||||
exitSpan = (AbstractSpan) DictionaryManager.findNetworkAddressSection()
|
||||
.find(remotePeer)
|
||||
.doInCondition(
|
||||
peerId -> new ExitSpan(spanIdGenerator++, parentSpanId,
|
||||
operationName, peerId, owner
|
||||
), () -> {
|
||||
return new ExitSpan(
|
||||
spanIdGenerator++, parentSpanId, operationName,
|
||||
remotePeer, owner
|
||||
);
|
||||
});
|
||||
}
|
||||
push(exitSpan);
|
||||
}
|
||||
exitSpan.start();
|
||||
|
|
@ -622,7 +658,10 @@ public class TracingContext implements AbstractTracerContext {
|
|||
if (spanIdGenerator >= Config.Agent.SPAN_LIMIT_PER_SEGMENT) {
|
||||
long currentTimeMillis = System.currentTimeMillis();
|
||||
if (currentTimeMillis - lastWarningTimestamp > 30 * 1000) {
|
||||
logger.warn(new RuntimeException("Shadow tracing context. Thread dump"), "More than {} spans required to create", Config.Agent.SPAN_LIMIT_PER_SEGMENT);
|
||||
logger.warn(
|
||||
new RuntimeException("Shadow tracing context. Thread dump"),
|
||||
"More than {} spans required to create", Config.Agent.SPAN_LIMIT_PER_SEGMENT
|
||||
);
|
||||
lastWarningTimestamp = currentTimeMillis;
|
||||
}
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
package org.apache.skywalking.apm.agent.core.context.trace;
|
||||
|
||||
import org.apache.skywalking.apm.agent.core.context.ContextCarrier;
|
||||
import org.apache.skywalking.apm.agent.core.context.TracingContext;
|
||||
import org.apache.skywalking.apm.agent.core.context.tag.AbstractTag;
|
||||
import org.apache.skywalking.apm.network.trace.component.Component;
|
||||
|
|
@ -33,24 +34,19 @@ import org.apache.skywalking.apm.network.trace.component.Component;
|
|||
* Such as: Dubbox - Apache Httpcomponent - ...(Remote) The <code>ExitSpan</code> represents the Dubbox span, and ignore
|
||||
* the httpcomponent span's info.
|
||||
*/
|
||||
public class ExitSpan extends StackBasedTracingSpan implements WithPeerInfo {
|
||||
|
||||
public class ExitSpan extends StackBasedTracingSpan implements ExitTypeSpan {
|
||||
public ExitSpan(int spanId, int parentSpanId, String operationName, String peer, TracingContext owner) {
|
||||
super(spanId, parentSpanId, operationName, peer, owner);
|
||||
}
|
||||
|
||||
public ExitSpan(int spanId, int parentSpanId, int operationId, int peerId, TracingContext owner) {
|
||||
super(spanId, parentSpanId, operationId, peerId, owner);
|
||||
}
|
||||
|
||||
public ExitSpan(int spanId, int parentSpanId, int operationId, String peer, TracingContext owner) {
|
||||
super(spanId, parentSpanId, operationId, peer, owner);
|
||||
}
|
||||
|
||||
public ExitSpan(int spanId, int parentSpanId, String operationName, int peerId, TracingContext owner) {
|
||||
super(spanId, parentSpanId, operationName, peerId, owner);
|
||||
}
|
||||
|
||||
public ExitSpan(int spanId, int parentSpanId, String operationName, TracingContext owner) {
|
||||
super(spanId, parentSpanId, operationName, owner);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link #startTime}, when the first start, which means the first service provided.
|
||||
*/
|
||||
|
|
@ -122,13 +118,12 @@ public class ExitSpan extends StackBasedTracingSpan implements WithPeerInfo {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Illegal operation. Operation name id is the registered endpoint, only work for entry span.
|
||||
*/
|
||||
@Override
|
||||
public AbstractTracingSpan setOperationId(int operationId) {
|
||||
if (stackDepth == 1) {
|
||||
return super.setOperationId(operationId);
|
||||
} else {
|
||||
return this;
|
||||
}
|
||||
throw new UnsupportedOperationException("Exit span doesn't support operation id");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -141,6 +136,12 @@ public class ExitSpan extends StackBasedTracingSpan implements WithPeerInfo {
|
|||
return peer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExitSpan inject(final ContextCarrier carrier) {
|
||||
this.owner.inject(this, carrier);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEntry() {
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -18,8 +18,15 @@
|
|||
|
||||
package org.apache.skywalking.apm.agent.core.context.trace;
|
||||
|
||||
public interface WithPeerInfo {
|
||||
import org.apache.skywalking.apm.agent.core.context.ContextCarrier;
|
||||
|
||||
/**
|
||||
* The exit span has some additional behaviours
|
||||
*/
|
||||
public interface ExitTypeSpan {
|
||||
int getPeerId();
|
||||
|
||||
String getPeer();
|
||||
|
||||
ExitTypeSpan inject(ContextCarrier carrier);
|
||||
}
|
||||
|
|
@ -47,4 +47,12 @@ public class LocalSpan extends AbstractTracingSpan {
|
|||
public AbstractSpan setPeer(String remotePeer) {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Illegal operation. Operation name id is the registered endpoint, only work for entry span.
|
||||
*/
|
||||
@Override
|
||||
public AbstractTracingSpan setOperationId(int operationId) {
|
||||
throw new UnsupportedOperationException("Exit span doesn't support operation id");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,9 @@
|
|||
|
||||
package org.apache.skywalking.apm.agent.core.context.trace;
|
||||
|
||||
public class NoopExitSpan extends NoopSpan implements WithPeerInfo {
|
||||
import org.apache.skywalking.apm.agent.core.context.ContextCarrier;
|
||||
|
||||
public class NoopExitSpan extends NoopSpan implements ExitTypeSpan {
|
||||
|
||||
private String peer;
|
||||
private int peerId;
|
||||
|
|
@ -41,6 +43,11 @@ public class NoopExitSpan extends NoopSpan implements WithPeerInfo {
|
|||
return peer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NoopExitSpan inject(final ContextCarrier carrier) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExit() {
|
||||
return true;
|
||||
|
|
|
|||
Loading…
Reference in New Issue