16
16
import java .util .Iterator ;
17
17
import org .jooq .Record ;
18
18
import org .jooq .TableField ;
19
- import zipkin .internal . DependencyLinkSpan ;
19
+ import zipkin .Endpoint ;
20
20
import zipkin .internal .Nullable ;
21
21
import zipkin .internal .PeekingIterator ;
22
+ import zipkin .internal .Span2 ;
22
23
import zipkin .storage .mysql .internal .generated .tables .ZipkinSpans ;
23
24
24
25
import static zipkin .Constants .CLIENT_ADDR ;
25
26
import static zipkin .Constants .CLIENT_SEND ;
26
27
import static zipkin .Constants .SERVER_ADDR ;
27
28
import static zipkin .Constants .SERVER_RECV ;
29
+ import static zipkin .internal .Util .equal ;
28
30
import static zipkin .storage .mysql .internal .generated .tables .ZipkinAnnotations .ZIPKIN_ANNOTATIONS ;
29
31
30
32
/**
31
- * Convenience that lazy converts rows into {@linkplain DependencyLinkSpan} objects.
33
+ * Lazy converts rows into {@linkplain Span2} objects suitable for dependency links. This takes
34
+ * short-cuts to require less data. For example, it folds shared RPC spans into one, and doesn't
35
+ * include tags, non-core annotations or time units.
32
36
*
33
37
* <p>Out-of-date schemas may be missing the trace_id_high field. When present, this becomes {@link
34
- * DependencyLinkSpan.TraceId#hi } used as the left-most 16 characters of the traceId in logging
38
+ * Span2#traceIdHigh() } used as the left-most 16 characters of the traceId in logging
35
39
* statements.
36
40
*/
37
- final class DependencyLinkSpanIterator implements Iterator <DependencyLinkSpan > {
41
+ final class DependencyLinkSpan2Iterator implements Iterator <Span2 > {
38
42
39
43
/** Assumes the input records are sorted by trace id, span id */
40
- static final class ByTraceId implements Iterator <Iterator <DependencyLinkSpan >> {
44
+ static final class ByTraceId implements Iterator <Iterator <Span2 >> {
41
45
final PeekingIterator <Record > delegate ;
42
46
final boolean hasTraceIdHigh ;
43
47
@@ -53,10 +57,10 @@ static final class ByTraceId implements Iterator<Iterator<DependencyLinkSpan>> {
53
57
return delegate .hasNext ();
54
58
}
55
59
56
- @ Override public Iterator <DependencyLinkSpan > next () {
60
+ @ Override public Iterator <Span2 > next () {
57
61
currentTraceIdHi = hasTraceIdHigh ? traceIdHigh (delegate ) : null ;
58
62
currentTraceIdLo = delegate .peek ().getValue (ZipkinSpans .ZIPKIN_SPANS .TRACE_ID );
59
- return new DependencyLinkSpanIterator (delegate , currentTraceIdHi , currentTraceIdLo );
63
+ return new DependencyLinkSpan2Iterator (delegate , currentTraceIdHi , currentTraceIdLo );
60
64
}
61
65
62
66
@ Override public void remove () {
@@ -68,7 +72,7 @@ static final class ByTraceId implements Iterator<Iterator<DependencyLinkSpan>> {
68
72
@ Nullable final Long traceIdHi ;
69
73
final long traceIdLo ;
70
74
71
- DependencyLinkSpanIterator (PeekingIterator <Record > delegate , Long traceIdHi , long traceIdLo ) {
75
+ DependencyLinkSpan2Iterator (PeekingIterator <Record > delegate , Long traceIdHi , long traceIdLo ) {
72
76
this .delegate = delegate ;
73
77
this .traceIdHi = traceIdHi ;
74
78
this .traceIdLo = traceIdLo ;
@@ -83,17 +87,11 @@ public boolean hasNext() {
83
87
}
84
88
85
89
@ Override
86
- public DependencyLinkSpan next () {
90
+ public Span2 next () {
87
91
Record row = delegate .peek ();
88
92
89
93
long spanId = row .getValue (ZipkinSpans .ZIPKIN_SPANS .ID );
90
- DependencyLinkSpan .Builder result = DependencyLinkSpan .builder (
91
- traceIdHi != null ? traceIdHi : 0L ,
92
- traceIdLo ,
93
- row .getValue (ZipkinSpans .ZIPKIN_SPANS .PARENT_ID ),
94
- spanId
95
- );
96
-
94
+ String srService = null , csService = null , caService = null , saService = null ;
97
95
while (hasNext ()) { // there are more values for this trace
98
96
if (spanId != delegate .peek ().getValue (ZipkinSpans .ZIPKIN_SPANS .ID )) {
99
97
break ; // if we are in a new span
@@ -105,18 +103,48 @@ public DependencyLinkSpan next() {
105
103
if (key == null || value == null ) continue ; // neither client nor server
106
104
switch (key ) {
107
105
case CLIENT_ADDR :
108
- result . caService ( value ) ;
106
+ caService = value ;
109
107
break ;
110
108
case CLIENT_SEND :
111
- result . csService ( value ) ;
109
+ csService = value ;
112
110
break ;
113
111
case SERVER_ADDR :
114
- result . saService ( value ) ;
112
+ saService = value ;
115
113
break ;
116
114
case SERVER_RECV :
117
- result . srService ( value ) ;
115
+ srService = value ;
118
116
}
119
117
}
118
+
119
+ // The client address is more authoritative than the client send owner.
120
+ if (caService == null ) caService = csService ;
121
+
122
+ // Finagle labels two sides of the same socket ("ca", "sa") with the same name.
123
+ // Skip the client side, so it isn't mistaken for a loopback request
124
+ if (equal (saService , caService )) caService = null ;
125
+
126
+ Span2 .Builder result = Span2 .builder ()
127
+ .traceIdHigh (traceIdHi != null ? traceIdHi : 0L )
128
+ .traceId (traceIdLo )
129
+ .parentId (row .getValue (ZipkinSpans .ZIPKIN_SPANS .PARENT_ID ))
130
+ .id (spanId );
131
+
132
+ if (srService != null ) {
133
+ return result .kind (Span2 .Kind .SERVER )
134
+ .localEndpoint (ep (srService ))
135
+ .remoteEndpoint (ep (caService ))
136
+ .build ();
137
+ } else if (saService != null ) {
138
+ return result
139
+ .kind (csService != null ? Span2 .Kind .CLIENT : null )
140
+ .localEndpoint (ep (caService ))
141
+ .remoteEndpoint (ep (saService ))
142
+ .build ();
143
+ } else if (csService != null ) {
144
+ return result .kind (Span2 .Kind .SERVER )
145
+ .localEndpoint (ep (caService ))
146
+ .build ();
147
+ }
120
148
return result .build ();
121
149
}
122
150
@@ -129,8 +157,12 @@ static long traceIdHigh(PeekingIterator<Record> delegate) {
129
157
return delegate .peek ().getValue (ZipkinSpans .ZIPKIN_SPANS .TRACE_ID_HIGH );
130
158
}
131
159
132
- static String emptyToNull (Record next , TableField <Record , String > field ) {
160
+ static @ Nullable String emptyToNull (Record next , TableField <Record , String > field ) {
133
161
String result = next .getValue (field );
134
162
return result != null && !"" .equals (result ) ? result : null ;
135
163
}
164
+
165
+ static Endpoint ep (@ Nullable String serviceName ) {
166
+ return serviceName != null ? Endpoint .builder ().serviceName (serviceName ).build () : null ;
167
+ }
136
168
}
0 commit comments