-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #817 from openzipkin/eager-span-timestamp-duration
Converts scala functions Span.timestamp, duration to vals
- Loading branch information
Showing
35 changed files
with
287 additions
and
234 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
34 changes: 34 additions & 0 deletions
34
zipkin-common/src/main/scala/com/twitter/zipkin/adjuster/ApplyTimestampAndDuration.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package com.twitter.zipkin.adjuster | ||
|
||
import com.twitter.zipkin.common._ | ||
|
||
/** | ||
* This applies timestamp and duration to spans, based on interpretation of | ||
* annotations. Spans who already have timestamp and duration set and left | ||
* alone. | ||
* | ||
* After application, spans without a timestamp are filtered out, as they are | ||
* not possible to present on a timeline. The only scenario where this is | ||
* possible is when instrumentation sends binary annotations ahead of the span | ||
* start event, or when a span's start even was lost. Considering this is error | ||
* -case or transient, there's no option to control this behavior. | ||
*/ | ||
object ApplyTimestampAndDuration extends ((List[Span]) => List[Span]) { | ||
|
||
override def apply(spans: List[Span]): List[Span] = spans.map { span => | ||
if (span.timestamp.isDefined && span.duration.isDefined) span else apply(span) | ||
}.filter(_.timestamp.nonEmpty).sorted | ||
|
||
def apply(span: Span) = { | ||
val sorted = span.annotations.sorted | ||
val firstOption = sorted.headOption.map(_.timestamp) | ||
val lastOption = sorted.lastOption.map(_.timestamp) | ||
span.copy( | ||
timestamp = span.timestamp.orElse(firstOption), | ||
duration = span.duration.orElse { | ||
for (first <- firstOption; last <- lastOption; if (first != last)) | ||
yield last - first | ||
} | ||
) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
62 changes: 62 additions & 0 deletions
62
zipkin-common/src/test/scala/com/twitter/zipkin/adjuster/ApplyTimestampAndDurationTest.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
package com.twitter.zipkin.adjuster | ||
|
||
import com.twitter.zipkin.common._ | ||
import org.scalatest.FunSuite | ||
|
||
class ApplyTimestampAndDurationTest extends FunSuite { | ||
|
||
test("noop when no annotations") { | ||
val span = Span(1, "n", 2, None, None, None) | ||
|
||
val adjusted = ApplyTimestampAndDuration(span) | ||
assert(adjusted.timestamp === None) | ||
assert(adjusted.duration === None) | ||
} | ||
|
||
test("duration is difference between annotation timestamps") { | ||
val span = Span(12345, "methodcall", 666, None, None, None, List( | ||
Annotation(1, "value1", Some(Endpoint(1, 2, "service"))), | ||
Annotation(2, "value2", Some(Endpoint(3, 4, "service"))), | ||
Annotation(3, "value3", Some(Endpoint(5, 6, "service"))) | ||
)) | ||
|
||
val adjusted = ApplyTimestampAndDuration(span) | ||
assert(adjusted.timestamp === Some(1)) | ||
assert(adjusted.duration === Some(2)) | ||
} | ||
|
||
test("noop when duration already set") { | ||
val span = Span(12345, "methodcall", 666, None, Some(83L), Some(11L), List( | ||
Annotation(10, "value1", Some(Endpoint(1, 2, "service"))) | ||
)) | ||
|
||
val adjusted = ApplyTimestampAndDuration(span) | ||
assert(adjusted === span) | ||
} | ||
|
||
test("duration isn't set when only one annotation") { | ||
val span = Span(1, "n", 2, None, None, None, annotations = List( | ||
Annotation(1, "value1", Some(Endpoint(1, 2, "service"))) | ||
)) | ||
|
||
val adjusted = ApplyTimestampAndDuration(span) | ||
assert(adjusted.timestamp === Some(1)) | ||
assert(adjusted.duration === None) | ||
} | ||
|
||
test("duration isn't set when only same timestamps") { | ||
val span = Span(1, "n", 2, None, None, None, annotations = List( | ||
Annotation(1, "value1", Some(Endpoint(1, 2, "service"))), | ||
Annotation(1, "value2", Some(Endpoint(1, 2, "service"))) | ||
)) | ||
|
||
val adjusted = ApplyTimestampAndDuration(span) | ||
assert(adjusted.timestamp === Some(1)) | ||
assert(adjusted.duration === None) | ||
} | ||
|
||
/** Missing timestamp means the span cannot be placed on a timeline */ | ||
test("filters spans without a timestamp") { | ||
assert(ApplyTimestampAndDuration(List(Span(12345, "methodcall2", 2))) == List()) | ||
} | ||
} |
Oops, something went wrong.