Skip to content

Commit 700b9e6

Browse files
authored
Allow setting manual start and end timestamps (#541)
closes #236
1 parent bc4c85c commit 700b9e6

File tree

15 files changed

+179
-11
lines changed

15 files changed

+179
-11
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
As of version 7.x of the stack, labels will be stored under `labels` in Elasticsearch.
88
Previously, they were stored under `context.tags`.
99
* Support async queries made by Elasticsearch REST client
10+
* Added `setStartTimestamp(long epochMicros)` and `end(long epochMicros)` API methods to `Span` and `Transaction`,
11+
allowing to set custom start and end timestamps.
1012

1113
## Bug Fixes
1214

apm-agent-api/src/main/java/co/elastic/apm/api/AbstractSpanImpl.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ public Span startSpan() {
5757
return span != null ? new SpanImpl(span) : NoopSpan.INSTANCE;
5858
}
5959

60+
public void doSetStartTimestamp(long epochMicros) {
61+
// co.elastic.apm.agent.plugin.api.AbstractSpanInstrumentation$SetStartTimestampInstrumentation
62+
}
63+
6064
private Object doCreateSpan() {
6165
// co.elastic.apm.agent.plugin.api.AbstractSpanInstrumentation$DoCreateSpanInstrumentation.doCreateSpan
6266
return null;
@@ -94,7 +98,12 @@ void doAddBooleanLabel(String key, Boolean value) {
9498

9599
@Override
96100
public void end() {
97-
// co.elastic.apm.agent.plugin.api.AbstractSpanInstrumentation$EndInstrumentation.end
101+
// co.elastic.apm.agent.plugin.api.AbstractSpanInstrumentation$EndInstrumentation
102+
}
103+
104+
@Override
105+
public void end(long epochMicros) {
106+
// co.elastic.apm.agent.plugin.api.AbstractSpanInstrumentation$EndWithTimestampInstrumentation
98107
}
99108

100109
@Override

apm-agent-api/src/main/java/co/elastic/apm/api/NoopSpan.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@ public void end() {
6969
// noop
7070
}
7171

72+
@Override
73+
public void end(long epochMicros) {
74+
// noop
75+
}
76+
7277
@Override
7378
public void captureException(Throwable throwable) {
7479
// co.elastic.apm.agent.plugin.api.CaptureExceptionInstrumentation
@@ -114,6 +119,11 @@ public Span startSpan() {
114119
return INSTANCE;
115120
}
116121

122+
@Override
123+
public Span setStartTimestamp(long epochMicros) {
124+
return INSTANCE;
125+
}
126+
117127
@Override
118128
public void injectTraceHeaders(HeaderInjector headerInjector) {
119129
// noop

apm-agent-api/src/main/java/co/elastic/apm/api/NoopTransaction.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,11 @@ public void end() {
8282
// noop
8383
}
8484

85+
@Override
86+
public void end(long epochMicros) {
87+
// noop
88+
}
89+
8590
@Override
8691
public void captureException(Throwable throwable) {
8792
// co.elastic.apm.agent.plugin.api.CaptureExceptionInstrumentation
@@ -133,6 +138,10 @@ public Span startSpan() {
133138
return NoopSpan.INSTANCE;
134139
}
135140

141+
@Override
142+
public Transaction setStartTimestamp(long epochMicros) {
143+
return this;
144+
}
136145

137146
@Override
138147
public void injectTraceHeaders(HeaderInjector headerInjector) {

apm-agent-api/src/main/java/co/elastic/apm/api/Span.java

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,15 @@ public interface Span {
145145
@Nonnull
146146
Span addLabel(String key, boolean value);
147147

148+
/**
149+
* Sets the start timestamp of this event.
150+
*
151+
* @param epochMicros the timestamp of when this event happened, in microseconds (µs) since epoch
152+
* @return {@code this} for chaining
153+
* @since 1.5.0
154+
*/
155+
Span setStartTimestamp(long epochMicros);
156+
148157
/**
149158
* NOTE: THIS METHOD IS DEPRECATED AND WILL BE REMOVED IN VERSION 2.0.
150159
* Instead, start a new span through {@link #startSpan()} or {@link #startSpan(String, String, String)}.
@@ -180,8 +189,8 @@ public interface Span {
180189
* </p>
181190
* <p>
182191
* The type, subtype and action strings are used to group similar spans together, with increasing resolution.
183-
* For instance, all DB spans are given the type `db`; all spans of MySQL queries are given the subtype `mysql` and all spans
184-
* describing queries are give the action `query`.
192+
* For instance, all DB spans are given the type `db`; all spans of MySQL queries are given the subtype `mysql` and all spans
193+
* describing queries are given the action `query`.
185194
* </p>
186195
* <p>
187196
* In the above example `db` is considered the general type. Though there are no naming restrictions for the general types,
@@ -223,7 +232,7 @@ public interface Span {
223232
* NOTE: Spans created via this method can not be retrieved by calling {@link ElasticApm#currentSpan()}.
224233
* See {@link #activate()} on how to achieve that.
225234
* </p>
226-
*
235+
*
227236
* @return the started span, never {@code null}
228237
*/
229238
@Nonnull
@@ -236,6 +245,15 @@ public interface Span {
236245
*/
237246
void end();
238247

248+
/**
249+
* Ends the span and schedules it to be reported to the APM Server.
250+
* It is illegal to call any methods on a span instance which has already ended.
251+
* This also includes this method and {@link #startSpan()}.
252+
*
253+
* @param epochMicros the timestamp of when this event ended, in microseconds (µs) since epoch
254+
*/
255+
void end(long epochMicros);
256+
239257
/**
240258
* Captures an exception and reports it to the APM server.
241259
*

apm-agent-api/src/main/java/co/elastic/apm/api/SpanImpl.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,4 +75,10 @@ public Span addLabel(String key, boolean value) {
7575
return this;
7676
}
7777

78+
@Override
79+
public Span setStartTimestamp(long epochMicros) {
80+
doSetStartTimestamp(epochMicros);
81+
return this;
82+
}
83+
7884
}

apm-agent-api/src/main/java/co/elastic/apm/api/Transaction.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,9 @@ public interface Transaction extends Span {
103103
*/
104104
Transaction setResult(String result);
105105

106+
@Override
107+
Transaction setStartTimestamp(long epochMicros);
108+
106109
/**
107110
* End tracking the transaction.
108111
* <p>

apm-agent-api/src/main/java/co/elastic/apm/api/TransactionImpl.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,4 +96,10 @@ public String ensureParentId() {
9696
return "";
9797
}
9898

99+
@Override
100+
public Transaction setStartTimestamp(long epochMicros) {
101+
doSetStartTimestamp(epochMicros);
102+
return this;
103+
}
104+
99105
}

apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/AbstractSpan.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public abstract class AbstractSpan<T extends AbstractSpan> extends TraceContextH
3939
* Generic designation of a transaction in the scope of a single service (eg: 'GET /users/:id')
4040
*/
4141
protected final StringBuilder name = new StringBuilder();
42-
protected long timestamp;
42+
private long timestamp;
4343
/**
4444
* How long the transaction took to complete, in ms with 3 decimal points
4545
* (Required)
@@ -214,4 +214,9 @@ public <V> Callable<V> withActive(Callable<V> callable) {
214214
return tracer.wrapCallable(callable, traceContext);
215215
}
216216
}
217+
218+
public void setStartTimestamp(long epochMicros) {
219+
timestamp = epochMicros;
220+
}
221+
217222
}

apm-agent-core/src/main/java/co/elastic/apm/agent/impl/transaction/Span.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,9 @@ public <T> Span start(TraceContext.ChildContextCreator<T> childContextCreator, T
7070
traceContext.setRecorded(false);
7171
}
7272
if (epochMicros >= 0) {
73-
timestamp = epochMicros;
73+
setStartTimestamp(epochMicros);
7474
} else {
75-
timestamp = getTraceContext().getClock().getEpochMicros();
75+
setStartTimestamp(getTraceContext().getClock().getEpochMicros());
7676
}
7777
if (logger.isDebugEnabled()) {
7878
logger.debug("startSpan {} {", this);

0 commit comments

Comments
 (0)