未验证 提交 74b0af9d 编写于 作者: wu-sheng's avatar wu-sheng 提交者: GitHub

[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
上级 0439dccc
......@@ -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;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册