From e8a43a198bb37d3d41fa11ded539e8f61a5fcfc8 Mon Sep 17 00:00:00 2001 From: wu-sheng Date: Fri, 3 Nov 2017 16:09:42 +0800 Subject: [PATCH 1/3] Support limiting the amount of spans per segment. default 300. --- .../src/main/proto/TraceSegmentService.proto | 1 + .../apm/agent/core/conf/Config.java | 31 ++++--- .../agent/core/context/TracingContext.java | 93 +++++++++++-------- .../core/context/trace/AbstractSpan.java | 27 +++++- .../context/trace/AbstractTracingSpan.java | 31 ++++--- .../agent/core/context/trace/NoopSpan.java | 20 ++++ .../core/context/trace/TraceSegment.java | 61 +++++------- apm-sniffer/config/agent.config | 4 + 8 files changed, 158 insertions(+), 110 deletions(-) diff --git a/apm-network/src/main/proto/TraceSegmentService.proto b/apm-network/src/main/proto/TraceSegmentService.proto index bc6f75817cd4..95eb1de6bc3a 100644 --- a/apm-network/src/main/proto/TraceSegmentService.proto +++ b/apm-network/src/main/proto/TraceSegmentService.proto @@ -26,6 +26,7 @@ message TraceSegmentObject { repeated SpanObject spans = 3; int32 applicationId = 4; int32 applicationInstanceId = 5; + bool isSizeLimited = 6; } message TraceSegmentReference { diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/conf/Config.java b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/conf/Config.java index 55e58942f1ba..f2903d5300b5 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/conf/Config.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/conf/Config.java @@ -31,22 +31,27 @@ public class Config { public static class Agent { /** - * Application code is showed in sky-walking-ui. - * Suggestion: set an unique name for each application, one application's nodes share the same code. + * Application code is showed in sky-walking-ui. Suggestion: set an unique name for each application, one + * application's nodes share the same code. */ public static String APPLICATION_CODE = ""; /** - * Negative or zero means off, by default. - * {@link #SAMPLE_N_PER_3_SECS} means sampling N {@link TraceSegment} in 10 seconds tops. + * Negative or zero means off, by default. {@link #SAMPLE_N_PER_3_SECS} means sampling N {@link TraceSegment} in + * 10 seconds tops. */ public static int SAMPLE_N_PER_3_SECS = -1; /** - * If the operation name of the first span is included in this set, - * this segment should be ignored. + * If the operation name of the first span is included in this set, this segment should be ignored. */ public static String IGNORE_SUFFIX = ".jpg,.jpeg,.js,.css,.png,.bmp,.gif,.ico,.mp3,.mp4,.html,.svg"; + + /** + * The max number of spans in a single segment. Through this config item, skywalking keep your application + * memory cost estimated. + */ + public static int SPAN_LIMIT_PER_SEGMENT = 300; } public static class Collector { @@ -63,9 +68,7 @@ public static class Collector { */ public static long DISCOVERY_CHECK_INTERVAL = 60; /** - * Collector REST-Service address. - * e.g. - * SERVERS="127.0.0.1:8080" for single collector node. + * Collector REST-Service address. e.g. SERVERS="127.0.0.1:8080" for single collector node. * SERVERS="10.2.45.126:8080,10.2.45.127:7600" for multi collector nodes. */ public static String SERVERS = ""; @@ -105,16 +108,15 @@ public static class Logging { public static String FILE_NAME = "skywalking-api.log"; /** - * Log files directory. - * Default is blank string, means, use "system.out" to output logs. + * Log files directory. Default is blank string, means, use "system.out" to output logs. * * @see {@link WriterFactory#getLogWriter()} */ public static String DIR = ""; /** - * The max size of log file. - * If the size is bigger than this, archive the current file, and write into a new file. + * The max size of log file. If the size is bigger than this, archive the current file, and write into a new + * file. */ public static int MAX_FILE_SIZE = 300 * 1024 * 1024; @@ -129,8 +131,7 @@ public static class Logging { public static class Plugin { public static class MongoDB { /** - * If true, trace all the parameters, default is false. - * Only trace the operation, not include parameters. + * If true, trace all the parameters, default is false. Only trace the operation, not include parameters. */ public static boolean TRACE_PARAM = false; } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/TracingContext.java b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/TracingContext.java index bde4d7c723f5..1a417a8f4252 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/TracingContext.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/TracingContext.java @@ -21,11 +21,13 @@ import java.util.LinkedList; import java.util.List; import org.skywalking.apm.agent.core.boot.ServiceManager; +import org.skywalking.apm.agent.core.conf.Config; import org.skywalking.apm.agent.core.context.trace.AbstractSpan; import org.skywalking.apm.agent.core.context.trace.AbstractTracingSpan; import org.skywalking.apm.agent.core.context.trace.EntrySpan; import org.skywalking.apm.agent.core.context.trace.ExitSpan; import org.skywalking.apm.agent.core.context.trace.LocalSpan; +import org.skywalking.apm.agent.core.context.trace.NoopSpan; import org.skywalking.apm.agent.core.context.trace.TraceSegment; import org.skywalking.apm.agent.core.context.trace.TraceSegmentRef; import org.skywalking.apm.agent.core.dictionary.DictionaryManager; @@ -34,17 +36,15 @@ import org.skywalking.apm.agent.core.sampling.SamplingService; /** - * The TracingContext represents a core tracing logic controller. - * It build the final {@link TracingContext}, by the stack mechanism, - * which is similar with the codes work. + * The TracingContext represents a core tracing logic controller. It build the final {@link + * TracingContext}, by the stack mechanism, which is similar with the codes work. * - * In opentracing concept, it means, all spans in a segment tracing context(thread) - * are CHILD_OF relationship, but no FOLLOW_OF. + * In opentracing concept, it means, all spans in a segment tracing context(thread) are CHILD_OF relationship, but no + * FOLLOW_OF. * - * In skywalking core concept, FOLLOW_OF is an abstract concept - * when cross-process MQ or cross-thread async/batch tasks happen, - * we used {@link TraceSegmentRef} for these scenarios. - * Check {@link TraceSegmentRef} which is from {@link ContextCarrier} or {@link ContextSnapshot}. + * In skywalking core concept, FOLLOW_OF is an abstract concept when cross-process MQ or cross-thread async/batch tasks + * happen, we used {@link TraceSegmentRef} for these scenarios. Check {@link TraceSegmentRef} which is from {@link + * ContextCarrier} or {@link ContextSnapshot}. * * @author wusheng */ @@ -60,13 +60,11 @@ public class TracingContext implements AbstractTracerContext { private TraceSegment segment; /** - * Active spans stored in a Stack, usually called 'ActiveSpanStack'. - * This {@link LinkedList} is the in-memory storage-structure. - *

- * I use {@link LinkedList#removeLast()}, {@link LinkedList#addLast(Object)} and {@link LinkedList#last} instead of - * {@link #pop()}, {@link #push(AbstractTracingSpan)}, {@link #peek()} + * Active spans stored in a Stack, usually called 'ActiveSpanStack'. This {@link LinkedList} is the in-memory + * storage-structure.

I use {@link LinkedList#removeLast()}, {@link LinkedList#addLast(Object)} and {@link + * LinkedList#last} instead of {@link #pop()}, {@link #push(AbstractSpan)}, {@link #peek()} */ - private LinkedList activeSpanStack = new LinkedList(); + private LinkedList activeSpanStack = new LinkedList(); /** * A counter for the next span. @@ -93,7 +91,7 @@ public class TracingContext implements AbstractTracerContext { */ @Override public void inject(ContextCarrier carrier) { - AbstractTracingSpan span = this.activeSpan(); + AbstractSpan span = this.activeSpan(); if (!span.isExit()) { throw new IllegalStateException("Inject can be done only in Exit Span"); } @@ -119,7 +117,7 @@ public void inject(ContextCarrier carrier) { operationName = ref.getEntryOperationName(); entryApplicationInstanceId = ref.getEntryApplicationInstanceId(); } else { - AbstractTracingSpan firstSpan = first(); + AbstractSpan firstSpan = first(); operationId = firstSpan.getOperationId(); operationName = firstSpan.getOperationName(); entryApplicationInstanceId = this.segment.getApplicationInstanceId(); @@ -169,7 +167,7 @@ public ContextSnapshot capture() { int entryOperationId; String entryOperationName; int entryApplicationInstanceId; - AbstractTracingSpan firstSpan = first(); + AbstractSpan firstSpan = first(); if (refs != null && refs.size() > 0) { TraceSegmentRef ref = refs.get(0); entryOperationId = ref.getEntryOperationId(); @@ -225,8 +223,12 @@ public String getReadableGlobalTraceId() { */ @Override public AbstractSpan createEntrySpan(final String operationName) { - AbstractTracingSpan entrySpan; - final AbstractTracingSpan parentSpan = peek(); + if (isLimitMechanismWorking()) { + NoopSpan span = new NoopSpan(); + return push(span); + } + AbstractSpan entrySpan; + final AbstractSpan parentSpan = peek(); final int parentSpanId = parentSpan == null ? -1 : parentSpan.getSpanId(); if (parentSpan == null) { entrySpan = (AbstractTracingSpan)DictionaryManager.findOperationNameCodeSection() @@ -269,7 +271,11 @@ public AbstractSpan createEntrySpan(final String operationName) { */ @Override public AbstractSpan createLocalSpan(final String operationName) { - AbstractTracingSpan parentSpan = peek(); + if (isLimitMechanismWorking()) { + NoopSpan span = new NoopSpan(); + return push(span); + } + AbstractSpan parentSpan = peek(); final int parentSpanId = parentSpan == null ? -1 : parentSpan.getSpanId(); AbstractTracingSpan span = (AbstractTracingSpan)DictionaryManager.findOperationNameCodeSection() .findOrPrepare4Register(segment.getApplicationId(), operationName) @@ -298,8 +304,12 @@ public Object doProcess() { */ @Override public AbstractSpan createExitSpan(final String operationName, final String remotePeer) { - AbstractTracingSpan exitSpan; - AbstractTracingSpan parentSpan = peek(); + if (isLimitMechanismWorking()) { + NoopSpan span = new NoopSpan(); + return push(span); + } + AbstractSpan exitSpan; + AbstractSpan parentSpan = peek(); if (parentSpan != null && parentSpan.isExit()) { exitSpan = parentSpan; } else { @@ -354,8 +364,8 @@ public Object doProcess() { * @return the active span of current context, the top element of {@link #activeSpanStack} */ @Override - public AbstractTracingSpan activeSpan() { - AbstractTracingSpan span = peek(); + public AbstractSpan activeSpan() { + AbstractSpan span = peek(); if (span == null) { throw new IllegalStateException("No active span."); } @@ -363,16 +373,21 @@ public AbstractTracingSpan activeSpan() { } /** - * Stop the given span, if and only if this one is the top element of {@link #activeSpanStack}. - * Because the tracing core must make sure the span must match in a stack module, like any program did. + * Stop the given span, if and only if this one is the top element of {@link #activeSpanStack}. Because the tracing + * core must make sure the span must match in a stack module, like any program did. * * @param span to finish */ @Override public void stopSpan(AbstractSpan span) { - AbstractTracingSpan lastSpan = peek(); + AbstractSpan lastSpan = peek(); if (lastSpan == span) { - if (lastSpan.finish(segment)) { + if (lastSpan instanceof AbstractTracingSpan) { + AbstractTracingSpan toFinishSpan = (AbstractTracingSpan)lastSpan; + if (toFinishSpan.finish(segment)) { + pop(); + } + } else { pop(); } } else { @@ -389,7 +404,7 @@ public void stopSpan(AbstractSpan span) { * TracingContext.ListenerManager} */ private void finish() { - TraceSegment finishedSegment = segment.finish(); + TraceSegment finishedSegment = segment.finish(isLimitMechanismWorking()); /** * Recheck the segment if the segment contains only one span. * Because in the runtime, can't sure this segment is part of distributed trace. @@ -421,9 +436,9 @@ public static synchronized void add(TracingContextListener listener) { } /** - * Notify the {@link TracingContext.ListenerManager} about the given {@link TraceSegment} have finished. - * And trigger {@link TracingContext.ListenerManager} to notify all {@link #LISTENERS} 's - * {@link TracingContextListener#afterFinished(TraceSegment)} + * Notify the {@link TracingContext.ListenerManager} about the given {@link TraceSegment} have finished. And + * trigger {@link TracingContext.ListenerManager} to notify all {@link #LISTENERS} 's {@link + * TracingContextListener#afterFinished(TraceSegment)} * * @param finishedSegment */ @@ -445,7 +460,7 @@ public static synchronized void remove(TracingContextListener listener) { /** * @return the top element of 'ActiveSpanStack', and remove it. */ - private AbstractTracingSpan pop() { + private AbstractSpan pop() { return activeSpanStack.removeLast(); } @@ -454,7 +469,7 @@ private AbstractTracingSpan pop() { * * @param span */ - private AbstractTracingSpan push(AbstractTracingSpan span) { + private AbstractSpan push(AbstractSpan span) { activeSpanStack.addLast(span); return span; } @@ -462,14 +477,18 @@ private AbstractTracingSpan push(AbstractTracingSpan span) { /** * @return the top element of 'ActiveSpanStack' only. */ - private AbstractTracingSpan peek() { + private AbstractSpan peek() { if (activeSpanStack.isEmpty()) { return null; } return activeSpanStack.getLast(); } - private AbstractTracingSpan first() { + private AbstractSpan first() { return activeSpanStack.getFirst(); } + + private boolean isLimitMechanismWorking() { + return spanIdGenerator > Config.Agent.SPAN_LIMIT_PER_SEGMENT; + } } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/AbstractSpan.java b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/AbstractSpan.java index 9d0d2097f653..7ba4344e1c7a 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/AbstractSpan.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/AbstractSpan.java @@ -22,8 +22,7 @@ import org.skywalking.apm.network.trace.component.Component; /** - * The AbstractSpan represents the span's skeleton, - * which contains all open methods. + * The AbstractSpan represents the span's skeleton, which contains all open methods. * * @author wusheng */ @@ -37,8 +36,8 @@ public interface AbstractSpan { AbstractSpan setComponent(Component component); /** - * Only use this method in explicit instrumentation, like opentracing-skywalking-bridge. - * It it higher recommend don't use this for performance consideration. + * Only use this method in explicit instrumentation, like opentracing-skywalking-bridge. It it higher recommend + * don't use this for performance consideration. * * @param componentName * @return the span for chaining. @@ -89,4 +88,24 @@ public interface AbstractSpan { * @return this Span instance, for chaining */ AbstractSpan setOperationName(String operationName); + + /** + * Start a span. + * + * @return this Span instance, for chaining + */ + AbstractSpan start(); + + /** + * Get the id of span + * + * @return id value. + */ + int getSpanId(); + + int getOperationId(); + + String getOperationName(); + + AbstractSpan setOperationId(int operationId); } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/AbstractTracingSpan.java b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/AbstractTracingSpan.java index 41920a1998b0..8ef9ea275016 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/AbstractTracingSpan.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/AbstractTracingSpan.java @@ -29,8 +29,8 @@ import org.skywalking.apm.network.trace.component.Component; /** - * The AbstractTracingSpan represents a group of {@link AbstractSpan} implementations, - * which belongs a real distributed trace. + * The AbstractTracingSpan represents a group of {@link AbstractSpan} implementations, which belongs a real + * distributed trace. * * @author wusheng */ @@ -59,9 +59,7 @@ public abstract class AbstractTracingSpan implements AbstractSpan { protected String componentName; /** - * Log is a concept from OpenTracing spec. - *

- * {@see https://github.com/opentracing/specification/blob/master/specification.md#log-structured-data} + * Log is a concept from OpenTracing spec.

{@see https://github.com/opentracing/specification/blob/master/specification.md#log-structured-data} */ protected List logs; @@ -94,8 +92,8 @@ public AbstractTracingSpan tag(String key, String value) { } /** - * Finish the active Span. - * When it is finished, it will be archived by the given {@link TraceSegment}, which owners it. + * Finish the active Span. When it is finished, it will be archived by the given {@link TraceSegment}, which owners + * it. * * @param owner of the Span. */ @@ -105,6 +103,7 @@ public boolean finish(TraceSegment owner) { return true; } + @Override public AbstractTracingSpan start() { this.startTime = System.currentTimeMillis(); return this; @@ -150,8 +149,8 @@ public AbstractTracingSpan log(long timestampMicroseconds, Map fields } /** - * In the scope of this span tracing context, error occurred, - * in auto-instrumentation mechanism, almost means throw an exception. + * In the scope of this span tracing context, error occurred, in auto-instrumentation mechanism, almost means throw + * an exception. * * @return span instance, for chaining. */ @@ -162,8 +161,8 @@ public AbstractTracingSpan errorOccurred() { } /** - * Set the operation name, just because these is not compress dictionary value for this name. - * Use the entire string temporarily, the agent will compress this name in async mode. + * Set the operation name, just because these is not compress dictionary value for this name. Use the entire string + * temporarily, the agent will compress this name in async mode. * * @param operationName * @return span instance, for chaining. @@ -181,20 +180,24 @@ public AbstractTracingSpan setOperationName(String operationName) { * @param operationId * @return span instance, for chaining. */ + @Override public AbstractTracingSpan setOperationId(int operationId) { this.operationId = operationId; this.operationName = null; return this; } + @Override public int getSpanId() { return spanId; } + @Override public int getOperationId() { return operationId; } + @Override public String getOperationName() { return operationName; } @@ -206,8 +209,7 @@ public AbstractTracingSpan setLayer(SpanLayer layer) { } /** - * Set the component of this span, with internal supported. - * Highly recommend to use this way. + * Set the component of this span, with internal supported. Highly recommend to use this way. * * @param component * @return span instance, for chaining. @@ -219,8 +221,7 @@ public AbstractTracingSpan setComponent(Component component) { } /** - * Set the component name. - * By using this, cost more memory and network. + * Set the component name. By using this, cost more memory and network. * * @param componentName * @return span instance, for chaining. diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/NoopSpan.java b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/NoopSpan.java index 8f129d643a98..da4e735f255d 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/NoopSpan.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/NoopSpan.java @@ -78,4 +78,24 @@ public AbstractSpan tag(String key, String value) { @Override public AbstractSpan setOperationName(String operationName) { return this; } + + @Override public AbstractSpan start() { + return this; + } + + @Override public int getSpanId() { + return 0; + } + + @Override public int getOperationId() { + return 0; + } + + @Override public String getOperationName() { + return ""; + } + + @Override public AbstractSpan setOperationId(int operationId) { + return this; + } } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/TraceSegment.java b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/TraceSegment.java index 597edaa9ea18..244b5c62c9fc 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/TraceSegment.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/TraceSegment.java @@ -26,68 +26,51 @@ import org.skywalking.apm.agent.core.context.ids.GlobalIdGenerator; import org.skywalking.apm.agent.core.context.ids.ID; import org.skywalking.apm.agent.core.context.ids.NewDistributedTraceId; -import org.skywalking.apm.agent.core.logging.api.ILog; -import org.skywalking.apm.agent.core.logging.api.LogManager; import org.skywalking.apm.network.proto.TraceSegmentObject; import org.skywalking.apm.network.proto.UpstreamSegment; /** - * {@link TraceSegment} is a segment or fragment of the distributed trace. - * {@see https://github.com/opentracing/specification/blob/master/specification.md#the-opentracing-data-model} - * A {@link - * TraceSegment} means the segment, which exists in current {@link Thread}. And the distributed trace is formed by multi - * {@link TraceSegment}s, because the distributed trace crosses multi-processes, multi-threads. - *

+ * {@link TraceSegment} is a segment or fragment of the distributed trace. {@see https://github.com/opentracing/specification/blob/master/specification.md#the-opentracing-data-model} + * A {@link TraceSegment} means the segment, which exists in current {@link Thread}. And the distributed trace is formed + * by multi {@link TraceSegment}s, because the distributed trace crosses multi-processes, multi-threads.

* * @author wusheng */ public class TraceSegment { - private static final ILog logger = LogManager.getLogger(TraceSegment.class); - - private static final String ID_TYPE = "S"; - /** - * The id of this trace segment. - * Every segment has its unique-global-id. + * The id of this trace segment. Every segment has its unique-global-id. */ private ID traceSegmentId; /** - * The refs of parent trace segments, except the primary one. - * For most RPC call, {@link #refs} contains only one element, - * but if this segment is a start span of batch process, the segment faces multi parents, - * at this moment, we use this {@link #refs} to link them. + * The refs of parent trace segments, except the primary one. For most RPC call, {@link #refs} contains only one + * element, but if this segment is a start span of batch process, the segment faces multi parents, at this moment, + * we use this {@link #refs} to link them. */ private List refs; /** - * The spans belong to this trace segment. - * They all have finished. - * All active spans are hold and controlled by "skywalking-api" module. + * The spans belong to this trace segment. They all have finished. All active spans are hold and controlled by + * "skywalking-api" module. */ private List spans; /** * The relatedGlobalTraces represent a set of all related trace. Most time it contains only one * element, because only one parent {@link TraceSegment} exists, but, in batch scenario, the num becomes greater - * than 1, also meaning multi-parents {@link TraceSegment}. - *

- * The difference between relatedGlobalTraces and {@link #refs} is: - * {@link #refs} targets this {@link TraceSegment}'s direct parent, - *

- * and - *

- * relatedGlobalTraces targets this {@link TraceSegment}'s related call chain, a call chain contains - * multi {@link TraceSegment}s, only using {@link #refs} is not enough for analysis and ui. + * than 1, also meaning multi-parents {@link TraceSegment}.

The difference between + * relatedGlobalTraces and {@link #refs} is: {@link #refs} targets this {@link TraceSegment}'s direct + * parent,

and

relatedGlobalTraces targets this {@link TraceSegment}'s related call chain, a + * call chain contains multi {@link TraceSegment}s, only using {@link #refs} is not enough for analysis and ui. */ private DistributedTraceIds relatedGlobalTraces; private boolean ignore = false; + private boolean isSizeLimited = false; + /** - * Create a default/empty trace segment, - * with current time as start time, - * and generate a new segment id. + * Create a default/empty trace segment, with current time as start time, and generate a new segment id. */ public TraceSegment() { this.traceSegmentId = GlobalIdGenerator.generate(); @@ -118,8 +101,8 @@ public void relatedGlobalTraces(DistributedTraceId distributedTraceId) { } /** - * After {@link AbstractSpan} is finished, as be controller by "skywalking-api" module, - * notify the {@link TraceSegment} to archive it. + * After {@link AbstractSpan} is finished, as be controller by "skywalking-api" module, notify the {@link + * TraceSegment} to archive it. * * @param finishedSpan */ @@ -128,11 +111,10 @@ public void archive(AbstractTracingSpan finishedSpan) { } /** - * Finish this {@link TraceSegment}. - *

- * return this, for chaining + * Finish this {@link TraceSegment}.

return this, for chaining */ - public TraceSegment finish() { + public TraceSegment finish(boolean isSizeLimited) { + this.isSizeLimited = isSizeLimited; return this; } @@ -195,6 +177,7 @@ public UpstreamSegment transform() { } traceSegmentBuilder.setApplicationId(RemoteDownstreamConfig.Agent.APPLICATION_ID); traceSegmentBuilder.setApplicationInstanceId(RemoteDownstreamConfig.Agent.APPLICATION_INSTANCE_ID); + traceSegmentBuilder.setIsSizeLimited(this.isSizeLimited); upstreamBuilder.setSegment(traceSegmentBuilder.build().toByteString()); return upstreamBuilder.build(); diff --git a/apm-sniffer/config/agent.config b/apm-sniffer/config/agent.config index a81175845663..d85abb433c60 100644 --- a/apm-sniffer/config/agent.config +++ b/apm-sniffer/config/agent.config @@ -5,6 +5,10 @@ agent.application_code=Your_ApplicationName # Negative number means sample traces as many as possible, most likely 100% # agent.sample_n_per_3_secs=-1 +# The max amount of spans in a single segment. +# Through this config item, skywalking keep your application memory cost estimated. +# agent.span_limit_per_segment=300 + # Ignore the segments if their operation names start with these suffix. # agent.ignore_suffix=.jpg,.jpeg,.js,.css,.png,.bmp,.gif,.ico,.mp3,.mp4,.html,.svg From 0eb0907ddd1278a7e140a62934cfb266384a647a Mon Sep 17 00:00:00 2001 From: ascrutae Date: Sun, 12 Nov 2017 16:24:41 +0800 Subject: [PATCH 2/3] support span amount control mechanism --- .../agent/core/context/TracingContext.java | 36 ++++-- .../core/context/trace/AbstractNoopSpan.java | 27 +++++ .../core/context/trace/NoopExitSpan.java | 104 ++++++++++++++++++ .../agent/core/context/trace/NoopSpan.java | 2 +- 4 files changed, 158 insertions(+), 11 deletions(-) create mode 100644 apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/AbstractNoopSpan.java create mode 100644 apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/NoopExitSpan.java diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/TracingContext.java b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/TracingContext.java index 1a417a8f4252..65679c6c18f8 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/TracingContext.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/TracingContext.java @@ -27,6 +27,7 @@ import org.skywalking.apm.agent.core.context.trace.EntrySpan; import org.skywalking.apm.agent.core.context.trace.ExitSpan; import org.skywalking.apm.agent.core.context.trace.LocalSpan; +import org.skywalking.apm.agent.core.context.trace.NoopExitSpan; import org.skywalking.apm.agent.core.context.trace.NoopSpan; import org.skywalking.apm.agent.core.context.trace.TraceSegment; import org.skywalking.apm.agent.core.context.trace.TraceSegmentRef; @@ -95,17 +96,28 @@ public void inject(ContextCarrier carrier) { if (!span.isExit()) { throw new IllegalStateException("Inject can be done only in Exit Span"); } - ExitSpan exitSpan = (ExitSpan)span; + + String peer; + int peerId; + if (span instanceof NoopExitSpan) { + NoopExitSpan exitSpan = (NoopExitSpan)span; + peerId = exitSpan.getPeerId(); + peer = exitSpan.getPeer(); + } else { + ExitSpan exitSpan = (ExitSpan)span; + peerId = exitSpan.getPeerId(); + peer = exitSpan.getPeer(); + } carrier.setTraceSegmentId(this.segment.getTraceSegmentId()); carrier.setSpanId(span.getSpanId()); carrier.setParentApplicationInstanceId(segment.getApplicationInstanceId()); - if (DictionaryUtil.isNull(exitSpan.getPeerId())) { - carrier.setPeerHost(exitSpan.getPeer()); + if (DictionaryUtil.isNull(peerId)) { + carrier.setPeerHost(peer); } else { - carrier.setPeerId(exitSpan.getPeerId()); + carrier.setPeerId(peerId); } List refs = this.segment.getRefs(); int operationId; @@ -304,21 +316,21 @@ public Object doProcess() { */ @Override public AbstractSpan createExitSpan(final String operationName, final String remotePeer) { - if (isLimitMechanismWorking()) { - NoopSpan span = new NoopSpan(); - return push(span); - } AbstractSpan exitSpan; AbstractSpan parentSpan = peek(); if (parentSpan != null && parentSpan.isExit()) { exitSpan = parentSpan; } else { final int parentSpanId = parentSpan == null ? -1 : parentSpan.getSpanId(); - exitSpan = (AbstractTracingSpan)DictionaryManager.findApplicationCodeSection() + exitSpan = (AbstractSpan)DictionaryManager.findApplicationCodeSection() .find(remotePeer).doInCondition( new PossibleFound.FoundAndObtain() { @Override public Object doProcess(final int peerId) { + if (isLimitMechanismWorking()) { + return new NoopExitSpan(peerId); + } + return DictionaryManager.findOperationNameCodeSection() .findOnly(segment.getApplicationId(), operationName) .doInCondition( @@ -338,6 +350,10 @@ public Object doProcess() { new PossibleFound.NotFoundAndObtain() { @Override public Object doProcess() { + if (isLimitMechanismWorking()) { + return new NoopExitSpan(remotePeer); + } + return DictionaryManager.findOperationNameCodeSection() .findOnly(segment.getApplicationId(), operationName) .doInCondition( @@ -489,6 +505,6 @@ private AbstractSpan first() { } private boolean isLimitMechanismWorking() { - return spanIdGenerator > Config.Agent.SPAN_LIMIT_PER_SEGMENT; + return spanIdGenerator >= Config.Agent.SPAN_LIMIT_PER_SEGMENT; } } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/AbstractNoopSpan.java b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/AbstractNoopSpan.java new file mode 100644 index 000000000000..270a804025d0 --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/AbstractNoopSpan.java @@ -0,0 +1,27 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.agent.core.context.trace; + +/** + * The AbstractNoopSpan represents a span implementation without any actual operation. + * + * @author zhangxin + */ +public interface AbstractNoopSpan extends AbstractSpan { +} diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/NoopExitSpan.java b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/NoopExitSpan.java new file mode 100644 index 000000000000..7b2aa256e0f6 --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/NoopExitSpan.java @@ -0,0 +1,104 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.agent.core.context.trace; + +import java.util.Map; +import org.skywalking.apm.network.trace.component.Component; + +public class NoopExitSpan implements AbstractNoopSpan { + + private String peer; + private int peerId; + + public NoopExitSpan(int peerId) { + this.peerId = peerId; + } + + public NoopExitSpan(String peer) { + this.peer = peer; + } + + @Override public AbstractSpan setComponent(Component component) { + return this; + } + + @Override public AbstractSpan setComponent(String componentName) { + return this; + } + + @Override public AbstractSpan setLayer(SpanLayer layer) { + return this; + } + + @Override public AbstractSpan tag(String key, String value) { + return this; + } + + @Override public AbstractSpan log(Throwable t) { + return this; + } + + @Override public AbstractSpan errorOccurred() { + return null; + } + + @Override public boolean isEntry() { + return false; + } + + @Override public boolean isExit() { + return true; + } + + @Override public AbstractSpan log(long timestamp, Map event) { + return this; + } + + @Override public AbstractSpan setOperationName(String operationName) { + return this; + } + + @Override public AbstractSpan start() { + return this; + } + + @Override public int getSpanId() { + return 0; + } + + @Override public int getOperationId() { + return 0; + } + + @Override public String getOperationName() { + return ""; + } + + @Override public AbstractSpan setOperationId(int operationId) { + return this; + } + + public int getPeerId() { + return peerId; + } + + public String getPeer() { + return peer; + } +} diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/NoopSpan.java b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/NoopSpan.java index da4e735f255d..6e20728200ee 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/NoopSpan.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/NoopSpan.java @@ -29,7 +29,7 @@ * * @author wusheng */ -public class NoopSpan implements AbstractSpan { +public class NoopSpan implements AbstractNoopSpan { public NoopSpan() { } From 41e459df199444931ac0f2b024825a8e838b6579 Mon Sep 17 00:00:00 2001 From: wusheng Date: Tue, 14 Nov 2017 19:27:45 +0800 Subject: [PATCH 3/3] Change the hierarchy of noopspan. And add WithPeerInfo interface. --- ...icationRegisterServiceHandlerTestCase.java | 3 +- .../agent/core/context/TracingContext.java | 15 ++-- .../agent/core/context/trace/ExitSpan.java | 4 +- .../core/context/trace/NoopExitSpan.java | 72 +++---------------- .../agent/core/context/trace/NoopSpan.java | 2 +- ...bstractNoopSpan.java => WithPeerInfo.java} | 9 +-- 6 files changed, 22 insertions(+), 83 deletions(-) rename apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/{AbstractNoopSpan.java => WithPeerInfo.java} (81%) diff --git a/apm-collector/apm-collector-agent/collector-agent-grpc-provider/src/test/java/org/skywalking/apm/collector/agent/grpc/handler/ApplicationRegisterServiceHandlerTestCase.java b/apm-collector/apm-collector-agent/collector-agent-grpc-provider/src/test/java/org/skywalking/apm/collector/agent/grpc/handler/ApplicationRegisterServiceHandlerTestCase.java index f39e797a26ce..c599f01a6659 100644 --- a/apm-collector/apm-collector-agent/collector-agent-grpc-provider/src/test/java/org/skywalking/apm/collector/agent/grpc/handler/ApplicationRegisterServiceHandlerTestCase.java +++ b/apm-collector/apm-collector-agent/collector-agent-grpc-provider/src/test/java/org/skywalking/apm/collector/agent/grpc/handler/ApplicationRegisterServiceHandlerTestCase.java @@ -20,7 +20,6 @@ import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; -import org.junit.Test; import org.skywalking.apm.network.proto.Application; import org.skywalking.apm.network.proto.ApplicationMapping; import org.skywalking.apm.network.proto.ApplicationRegisterServiceGrpc; @@ -36,7 +35,7 @@ public class ApplicationRegisterServiceHandlerTestCase { private ApplicationRegisterServiceGrpc.ApplicationRegisterServiceBlockingStub stub; - @Test + //@Test public void testRegister() { ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 11800).usePlaintext(true).build(); stub = ApplicationRegisterServiceGrpc.newBlockingStub(channel); diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/TracingContext.java b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/TracingContext.java index 65679c6c18f8..39d06c4496a2 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/TracingContext.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/TracingContext.java @@ -31,6 +31,7 @@ import org.skywalking.apm.agent.core.context.trace.NoopSpan; import org.skywalking.apm.agent.core.context.trace.TraceSegment; import org.skywalking.apm.agent.core.context.trace.TraceSegmentRef; +import org.skywalking.apm.agent.core.context.trace.WithPeerInfo; import org.skywalking.apm.agent.core.dictionary.DictionaryManager; import org.skywalking.apm.agent.core.dictionary.DictionaryUtil; import org.skywalking.apm.agent.core.dictionary.PossibleFound; @@ -97,17 +98,9 @@ public void inject(ContextCarrier carrier) { throw new IllegalStateException("Inject can be done only in Exit Span"); } - String peer; - int peerId; - if (span instanceof NoopExitSpan) { - NoopExitSpan exitSpan = (NoopExitSpan)span; - peerId = exitSpan.getPeerId(); - peer = exitSpan.getPeer(); - } else { - ExitSpan exitSpan = (ExitSpan)span; - peerId = exitSpan.getPeerId(); - peer = exitSpan.getPeer(); - } + WithPeerInfo spanWithPeer = (WithPeerInfo)span; + String peer = spanWithPeer.getPeer(); + int peerId = spanWithPeer.getPeerId(); carrier.setTraceSegmentId(this.segment.getTraceSegmentId()); carrier.setSpanId(span.getSpanId()); diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/ExitSpan.java b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/ExitSpan.java index 07c054d44c6c..329c019be6be 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/ExitSpan.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/ExitSpan.java @@ -35,7 +35,7 @@ * * @author wusheng */ -public class ExitSpan extends StackBasedTracingSpan { +public class ExitSpan extends StackBasedTracingSpan implements WithPeerInfo { private String peer; private int peerId; @@ -147,10 +147,12 @@ public AbstractTracingSpan setOperationId(int operationId) { } } + @Override public int getPeerId() { return peerId; } + @Override public String getPeer() { return peer; } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/NoopExitSpan.java b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/NoopExitSpan.java index 7b2aa256e0f6..c8c1ec69bfd6 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/NoopExitSpan.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/NoopExitSpan.java @@ -18,10 +18,7 @@ package org.skywalking.apm.agent.core.context.trace; -import java.util.Map; -import org.skywalking.apm.network.trace.component.Component; - -public class NoopExitSpan implements AbstractNoopSpan { +public class NoopExitSpan extends NoopSpan implements WithPeerInfo { private String peer; private int peerId; @@ -34,71 +31,18 @@ public NoopExitSpan(String peer) { this.peer = peer; } - @Override public AbstractSpan setComponent(Component component) { - return this; - } - - @Override public AbstractSpan setComponent(String componentName) { - return this; - } - - @Override public AbstractSpan setLayer(SpanLayer layer) { - return this; - } - - @Override public AbstractSpan tag(String key, String value) { - return this; - } - - @Override public AbstractSpan log(Throwable t) { - return this; - } - - @Override public AbstractSpan errorOccurred() { - return null; - } - - @Override public boolean isEntry() { - return false; - } - - @Override public boolean isExit() { - return true; - } - - @Override public AbstractSpan log(long timestamp, Map event) { - return this; - } - - @Override public AbstractSpan setOperationName(String operationName) { - return this; - } - - @Override public AbstractSpan start() { - return this; - } - - @Override public int getSpanId() { - return 0; - } - - @Override public int getOperationId() { - return 0; - } - - @Override public String getOperationName() { - return ""; - } - - @Override public AbstractSpan setOperationId(int operationId) { - return this; - } - + @Override public int getPeerId() { return peerId; } + @Override public String getPeer() { return peer; } + + @Override + public boolean isExit() { + return true; + } } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/NoopSpan.java b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/NoopSpan.java index 6e20728200ee..da4e735f255d 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/NoopSpan.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/NoopSpan.java @@ -29,7 +29,7 @@ * * @author wusheng */ -public class NoopSpan implements AbstractNoopSpan { +public class NoopSpan implements AbstractSpan { public NoopSpan() { } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/AbstractNoopSpan.java b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/WithPeerInfo.java similarity index 81% rename from apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/AbstractNoopSpan.java rename to apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/WithPeerInfo.java index 270a804025d0..4c6a30f7461d 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/AbstractNoopSpan.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/trace/WithPeerInfo.java @@ -19,9 +19,10 @@ package org.skywalking.apm.agent.core.context.trace; /** - * The AbstractNoopSpan represents a span implementation without any actual operation. - * - * @author zhangxin + * @author wusheng */ -public interface AbstractNoopSpan extends AbstractSpan { +public interface WithPeerInfo { + int getPeerId(); + + String getPeer(); }