Skip to content

Commit

Permalink
Closes #459 - Implemented stack trace sampling (#930)
Browse files Browse the repository at this point in the history
  • Loading branch information
Jonas Kunz authored Oct 2, 2020
1 parent 7840de5 commit 636f8fb
Show file tree
Hide file tree
Showing 33 changed files with 2,646 additions and 63 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package rocks.inspectit.ocelot.instrumentation.tracing;

import io.opencensus.trace.export.SpanData;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import rocks.inspectit.ocelot.utils.TestUtils;

import java.util.Collection;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

import static org.assertj.core.api.Assertions.assertThat;

public class AutoTracingTest extends TraceTestBase {

@BeforeAll
static void waitForInstrumentation() {
TestUtils.waitForClassInstrumentation(AutoTracingTest.class, true, 30, TimeUnit.SECONDS);
}

SpanData getSpanWithName(Collection<? extends SpanData> spans, String name) {
Optional<? extends SpanData> spanOptional = spans.stream()
.filter(s -> ((SpanData) s).getName().equals(name))
.findFirst();
assertThat(spanOptional).isNotEmpty();
return spanOptional.get();
}

@Test
void verifyStackTraceSampling() {
instrumentMe();

assertTraceExported((spans) -> {

SpanData root = getSpanWithName(spans, "AutoTracingTest.instrumentMe");
SpanData activeWait = getSpanWithName(spans, "*AutoTracingTest.activeWait");
SpanData passiveWait = getSpanWithName(spans, "*Thread.sleep");

assertThat(activeWait.getParentSpanId()).isEqualTo(root.getContext().getSpanId());
assertThat(passiveWait.getParentSpanId()).isEqualTo(root.getContext().getSpanId());

assertThat(activeWait.getEndTimestamp()).isLessThan(passiveWait.getStartTimestamp());
});
}

private void passiveWait(long duration) {
try {
Thread.sleep(duration);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}

private void activeWait(long duration) {
long durationNanos = duration * 1000 * 1000;
long start = System.nanoTime();
while ((System.nanoTime() - start) < durationNanos) {
}
}

private void nestedWait(long duration) {
passiveWait(duration);
}

private void instrumentMe() {
activeWait(150);
nestedWait(100);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@

inspectit:
tracing:
auto-tracing:
frequency: 10ms
instrumentation:

scopes:
AutoTracingTest-instrumentMe:
type:
name: AutoTracingTest
matcher-mode: ENDS_WITH
methods:
- name: instrumentMe

rules:
AutoTracingTest-instrumentMe:
scopes:
AutoTracingTest-instrumentMe: true
tracing:
start-span: true
auto-tracing: true
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,20 @@ public class RuleTracingSettings {
*/
private String continueSpan;

/**
* Enables or disables auto-tracing (=stack trace sampling).
* If this field is set to true, all sub-invocations of the instrumented method will be traced via stack-trace sampling.
* This only takes effect if either {@link #startSpan} or {@link #continueSpan} is configured and the current method is actually traced.
* <p>
* In addition this field can be set to false. In this case if any parent method has started a stack-trace sampling session,
* it will be paused for the duration of this method.
* This means effectively children of this method will be excluded from being traced using stack trace sampling.
* <p>
* If this field is null (the default value), no changes will be made to the current threads sampling session:
* If a parent has started a sampling session, it will be continued. If no sampling has been activated, none will be started.
*/
private Boolean autoTracing;

/**
* If not null, the span started or continued by this rule will be stored under the given data key.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package rocks.inspectit.ocelot.config.model.tracing;

import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.Duration;

/**
* Defines global settings regarding the stack trace sampling feature.
*/
@Data
@NoArgsConstructor
public class AutoTracingSettings {

/**
* Defines the frequency at which stack trace samples are taken.
* The higher the frequency, the greater the accuracy of the resulting trace.
* <p>
* However, taking stack traces is very expensive, therefore high frequencies can induce a big performance penalty.
*/
private Duration frequency;

/**
* When the first method executes with auto-tracing enabled, a separate Thread is started as a timer for taking stack trace samples.
* If at some point no more methods with stack-trace sampling are executed, this thread spins unnecessarily.
* <p>
* Therefore if no samples has been taken for at least the duration of {@link #shutdownDelay}, the timer will be shutdown.
* If a span requests sampling after the timer has shutdown, it will restart it.
*/
private Duration shutdownDelay;
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,18 @@ public enum AddCommonTags {
@Valid
private LogCorrelationSettings logCorrelation = new LogCorrelationSettings();


/**
* Generically defines behavior of adding common tags to spans.
*/
@NotNull
private AddCommonTags addCommonTags;

/**
* Settings for automatic tracing (stack trace sampling)
*/
@Valid
private AutoTracingSettings autoTracing;

/**
* The propagation format to use.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ inspectit:
# defines when to add common tags as attributes to spans
# options are: NEVER, ON_GLOBAL_ROOT, ON_LOCAL_ROOT, ALWAYS
add-common-tags: ON_LOCAL_ROOT
# settings regarding automatic tracing (stack-trace-sampling)
auto-tracing:
frequency: 50ms
shutdown-delay: 30s
# settings regarding log correlation
log-correlation:
trace-id-mdc-injection:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ inspectit:
's_apacheclient_doExecute': true
tracing:
start-span: true
auto-tracing: false
kind: CLIENT
start-span-conditions:
only-if-true: 'http_is_entry'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ inspectit:
's_httpurlconnection_getOutputStream': true
tracing:
start-span: true
auto-tracing: false
start-span-conditions:
only-if-true: 'httpurlconnection_is_start'
end-span: false
Expand Down Expand Up @@ -42,6 +43,7 @@ inspectit:
's_httpurlconnection_requestInitiators': true
tracing:
start-span: true
auto-tracing: false
continue-span: 'httpurlconnection_span'
continue-span-conditions:
only-if-true: 'httpurlconnection_is_end'
Expand Down
1 change: 1 addition & 0 deletions inspectit-ocelot-core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ dependencies {
compileOnly(
project(':inspectit-ocelot-bootstrap'),
"io.opencensus:opencensus-api:${openCensusVersion}",
"io.opencensus:opencensus-impl:${openCensusVersion}",
'org.projectlombok:lombok:1.18.12'
)
buildTools(
Expand Down
Loading

0 comments on commit 636f8fb

Please sign in to comment.