Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
953c909
Recycle via reference counting
felixbarny Apr 16, 2019
847aecd
Revert unrelated changes
felixbarny Apr 16, 2019
8bc8dd1
Introduce Labels
felixbarny Apr 16, 2019
d0e5d51
Add breakdown
felixbarny Apr 16, 2019
dffbba0
Make tracking breakdown metrics garbage free
felixbarny Apr 23, 2019
576f2da
Merge remote-tracking branch 'origin/master' into timing-breakdown
felixbarny May 3, 2019
790f2e2
Update to new metric names
felixbarny May 3, 2019
2c8d6d2
Merge remote-tracking branch 'origin/master' into timing-breakdown
felixbarny Jun 3, 2019
33bfcae
Thread safe publication of immutable labels
felixbarny Jun 3, 2019
b5395a1
Add span.subtype to breakdown metrics
felixbarny Jun 3, 2019
a609d71
Disable all breakdown code paths when disable_metrics=span.self_time
felixbarny Jun 4, 2019
dc701f7
Document metrics
felixbarny Jun 4, 2019
280f663
Clarify docs
felixbarny Jun 5, 2019
a336827
Another docs clarification
felixbarny Jun 5, 2019
833bbe1
Fix tests
felixbarny Jun 5, 2019
5639197
Guard agains concurrent reads/writes
felixbarny Jun 5, 2019
a0d167d
Limit number of metricsets
felixbarny Jun 5, 2019
9aca16f
Add some Javadocs
felixbarny Jun 5, 2019
253ad87
Eliminate allocations
felixbarny Jun 5, 2019
dbf5884
Addressed some comments
felixbarny Jun 21, 2019
6549546
Merge remote-tracking branch 'origin/master' into timing-breakdown
felixbarny Jun 21, 2019
d8394c3
Report timers in microseconds and use .us suffix
felixbarny Jun 21, 2019
308f519
Merge remote-tracking branch 'origin/master' into timing-breakdown
felixbarny Jul 12, 2019
580bf1d
Merge remote-tracking branch 'origin/master' into timing-breakdown
felixbarny Jul 17, 2019
bf6c221
Fix race condition between trackMetrics and incrementTimer
felixbarny Jul 18, 2019
f84852a
Renaming and add comments
felixbarny Jul 19, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions NOTICE
Original file line number Diff line number Diff line change
Expand Up @@ -359,3 +359,48 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

###############################################################################

This product includes code from HdrHistogram, dual-licensed under CC0 and BSD 2-Clause License

The code in this repository code was Written by Gil Tene, Michael Barker,
and Matt Warren, and released to the public domain, as explained at
http://creativecommons.org/publicdomain/zero/1.0/

For users of this code who wish to consume it under the "BSD" license
rather than under the public domain or CC0 contribution text mentioned
above, the code found under this directory is *also* provided under the
following license (commonly referred to as the BSD 2-Clause License). This
license does not detract from the above stated release of the code into
the public domain, and simply represents an additional license granted by
the Author.

-----------------------------------------------------------------------------
** Beginning of "BSD 2-Clause License" text. **

Copyright (c) 2012, 2013, 2014, 2015, 2016 Gil Tene
Copyright (c) 2014 Michael Barker
Copyright (c) 2014 Matt Warren
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
THE POSSIBILITY OF SUCH DAMAGE.

###############################################################################
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ public void setUp(Blackhole blackhole) {

@TearDown
public void tearDown() throws ExecutionException, InterruptedException {
Thread.sleep(1000);
tracer.getReporter().flush().get();
server.stop();
System.out.println("Reported: " + tracer.getReporter().getReported());
Expand Down
5 changes: 5 additions & 0 deletions apm-agent-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,11 @@
<artifactId>byte-buddy</artifactId>
<version>${version.byte-buddy}</version>
</dependency>
<dependency>
<groupId>org.hdrhistogram</groupId>
<artifactId>HdrHistogram</artifactId>
<version>2.1.11</version>
</dependency>

<dependency>
<groupId>com.squareup.okhttp3</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
* 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
Expand Down Expand Up @@ -399,7 +399,7 @@ public void endSpan(Span span) {
if (span.isSampled() && !span.isDiscard()) {
long spanFramesMinDurationMs = stacktraceConfiguration.getSpanFramesMinDurationMs();
if (spanFramesMinDurationMs != 0 && span.isSampled()) {
if (span.getDuration() >= spanFramesMinDurationMs) {
if (span.getDurationMs() >= spanFramesMinDurationMs) {
span.withStacktrace(new Throwable());
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
* 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
* 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
* 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
Expand All @@ -26,13 +26,17 @@

import co.elastic.apm.agent.impl.ElasticApmTracer;
import co.elastic.apm.agent.impl.context.AbstractContext;
import co.elastic.apm.agent.matcher.WildcardMatcher;
import co.elastic.apm.agent.objectpool.Recyclable;
import co.elastic.apm.agent.report.ReporterConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nullable;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

public abstract class AbstractSpan<T extends AbstractSpan> extends TraceContextHolder<T> {
private static final Logger logger = LoggerFactory.getLogger(AbstractSpan.class);
Expand All @@ -43,37 +47,98 @@ public abstract class AbstractSpan<T extends AbstractSpan> extends TraceContextH
* Generic designation of a transaction in the scope of a single service (eg: 'GET /users/:id')
*/
protected final StringBuilder name = new StringBuilder();
protected final boolean collectBreakdownMetrics;
private long timestamp;

/**
* How long the transaction took to complete, in ms with 3 decimal points
* (Required)
*/
protected double duration;
// in microseconds
protected long duration;
private ChildDurationTimer childDurations = new ChildDurationTimer();
protected AtomicInteger references = new AtomicInteger();
protected volatile boolean finished = true;

public int getReferenceCount() {
return references.get();
}

private static class ChildDurationTimer implements Recyclable {

private AtomicInteger activeChildren = new AtomicInteger();
private AtomicLong start = new AtomicLong();
private AtomicLong duration = new AtomicLong();

/**
* Starts the timer if it has not been started already.
*
* @param startTimestamp
*/
void onChildStart(long startTimestamp) {
if (activeChildren.incrementAndGet() == 1) {
start.set(startTimestamp);
}
}

/**
* Stops the timer and increments the duration if no other direct children are still running
* @param endTimestamp
*/
void onChildEnd(long endTimestamp) {
if (activeChildren.decrementAndGet() == 0) {
incrementDuration(endTimestamp);
}
}

/**
* Stops the timer and increments the duration even if there are direct children which are still running
*
* @param endTimestamp
*/
void onSpanEnd(long endTimestamp) {
if (activeChildren.getAndSet(0) != 0) {
incrementDuration(endTimestamp);
}
}

private void incrementDuration(long epochMicros) {
duration.addAndGet(epochMicros - start.get());
}

@Override
public void resetState() {
activeChildren.set(0);
start.set(0);
duration.set(0);
}

public long getDuration() {
return duration.get();
}
}

public AbstractSpan(ElasticApmTracer tracer) {
super(tracer);
traceContext = TraceContext.with64BitId(this.tracer);
collectBreakdownMetrics = !WildcardMatcher.isAnyMatch(tracer.getConfig(ReporterConfiguration.class).getDisableMetrics(), "span.self_time");
}

public boolean isReferenced() {
return references.get() > 0;
}

/**
* How long the transaction took to complete, in ms with 3 decimal points
* (Required)
* How long the transaction took to complete, in µs
*/
public double getDuration() {
public long getDuration() {
return duration;
}

public long getSelfDuration() {
return duration - childDurations.getDuration();
}

public double getDurationMs() {
return duration / AbstractSpan.MS_IN_MICROS;
}

/**
* Generic designation of a transaction in the scope of a single service (eg: 'GET /users/:id')
*/
Expand Down Expand Up @@ -124,6 +189,7 @@ public void resetState() {
timestamp = 0;
duration = 0;
traceContext.resetState();
childDurations.resetState();
references.set(0);
}

Expand Down Expand Up @@ -177,20 +243,23 @@ public void end() {

public final void end(long epochMicros) {
if (!finished) {
this.duration = (epochMicros - timestamp) / AbstractSpan.MS_IN_MICROS;
this.duration = (epochMicros - timestamp);
if (name.length() == 0) {
name.append("unnamed");
}
doEnd(epochMicros);
// has to be set last so doEnd callbacks don't think it has already been finished
childDurations.onSpanEnd(epochMicros);
beforeEnd(epochMicros);
this.finished = true;
afterEnd();
} else {
logger.warn("End has already been called: {}", this);
assert false;
}
}

protected abstract void doEnd(long epochMicros);
protected abstract void beforeEnd(long epochMicros);

protected abstract void afterEnd();

@Override
public boolean isChildOf(TraceContextHolder other) {
Expand Down Expand Up @@ -242,6 +311,18 @@ public void setStartTimestamp(long epochMicros) {
timestamp = epochMicros;
}

void onChildStart(long epochMicros) {
if (collectBreakdownMetrics) {
childDurations.onChildStart(epochMicros);
}
}

void onChildEnd(long epochMicros) {
if (collectBreakdownMetrics) {
childDurations.onChildEnd(epochMicros);
}
}

public void incrementReferences() {
references.incrementAndGet();
if (logger.isDebugEnabled()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
* 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
Expand Down Expand Up @@ -77,12 +77,10 @@ public <T> Span start(TraceContext.ChildContextCreator<T> childContextCreator, T
if (parentContext instanceof Transaction) {
this.transaction = (Transaction) parentContext;
this.parent = this.transaction;
this.parent.incrementReferences();
} else if (parentContext instanceof Span) {
final Span parentSpan = (Span) parentContext;
this.parent = parentSpan;
this.transaction = parentSpan.transaction;
this.parent.incrementReferences();
}
if (dropped) {
traceContext.setRecorded(false);
Expand All @@ -103,6 +101,15 @@ public <T> Span start(TraceContext.ChildContextCreator<T> childContextCreator, T
return this;
}

@Override
protected void onAfterStart() {
super.onAfterStart();
if (parent != null) {
this.parent.incrementReferences();
this.parent.onChildStart(getTimestamp());
}
}

/**
* Any other arbitrary data captured by the agent, optionally provided by the user
*/
Expand Down Expand Up @@ -188,7 +195,7 @@ public String getAction() {
}

@Override
public void doEnd(long epochMicros) {
public void beforeEnd(long epochMicros) {
if (logger.isDebugEnabled()) {
logger.debug("} endSpan {}", this);
if (logger.isTraceEnabled()) {
Expand All @@ -198,9 +205,17 @@ public void doEnd(long epochMicros) {
if (type == null) {
type = "custom";
}
if (transaction != null) {
transaction.incrementTimer(type, subtype, getSelfDuration());
}
if (parent != null) {
parent.onChildEnd(epochMicros);
parent.decrementReferences();
}
}

@Override
protected void afterEnd() {
this.tracer.endSpan(this);
}

Expand Down
Loading