16
16
import java .util .ArrayList ;
17
17
import java .util .Iterator ;
18
18
import java .util .LinkedHashMap ;
19
+ import java .util .LinkedHashSet ;
19
20
import java .util .List ;
20
21
import java .util .Map ;
22
+ import java .util .Set ;
21
23
import java .util .logging .Logger ;
22
24
import zipkin2 .DependencyLink ;
23
25
import zipkin2 .Span ;
@@ -38,6 +40,8 @@ public final class DependencyLinker {
38
40
private final Logger logger ;
39
41
private final Map <Pair , Long > callCounts = new LinkedHashMap <>();
40
42
private final Map <Pair , Long > errorCounts = new LinkedHashMap <>();
43
+ private final Map <Pair , Set <String >> callTraceIds = new LinkedHashMap <>();
44
+ private final Map <Pair , Set <String >> errorTraceIds = new LinkedHashMap <>();
41
45
42
46
public DependencyLinker () {
43
47
this (Logger .getLogger (DependencyLinker .class .getName ()));
@@ -84,10 +88,11 @@ public DependencyLinker putTrace(Iterator<Span> spans) {
84
88
if (!spans .hasNext ()) return this ;
85
89
Span first = spans .next ();
86
90
list .add (first );
87
- if (logger .isLoggable (FINE )) logger .fine ("linking trace " + first .traceId ());
91
+ String traceId = first .traceId ();
92
+ if (logger .isLoggable (FINE )) logger .fine ("linking trace " + traceId );
88
93
89
94
// Build a tree based on spanId and parentId values
90
- Node .TreeBuilder <Span > builder = new Node .TreeBuilder <>(logger , MERGE_RPC , first . traceId () );
95
+ Node .TreeBuilder <Span > builder = new Node .TreeBuilder <>(logger , MERGE_RPC , traceId );
91
96
builder .addNode (first .parentId (), first .id (), first );
92
97
while (spans .hasNext ()) {
93
98
Span next = spans .next ();
@@ -156,7 +161,7 @@ public DependencyLinker putTrace(Iterator<Span> spans) {
156
161
if (parent == null || child == null ) {
157
162
logger .fine ("cannot link messaging span to its broker; skipping" );
158
163
} else {
159
- addLink (parent , child , isError );
164
+ addLink (traceId , parent , child , isError );
160
165
}
161
166
continue ;
162
167
}
@@ -172,7 +177,7 @@ public DependencyLinker putTrace(Iterator<Span> spans) {
172
177
// Check for this and backfill a link from the nearest remote to that service as necessary.
173
178
if (kind == Kind .CLIENT && serviceName != null && !rpcAncestorName .equals (serviceName )) {
174
179
logger .fine ("detected missing link to client span" );
175
- addLink (rpcAncestorName , serviceName , false ); // we don't know if there's an error here
180
+ addLink (traceId , rpcAncestorName , serviceName , false ); // we don't know if there's an error here
176
181
}
177
182
178
183
// Local spans may be between the current node and its remote parent
@@ -191,7 +196,7 @@ public DependencyLinker putTrace(Iterator<Span> spans) {
191
196
continue ;
192
197
}
193
198
194
- addLink (parent , child , isError );
199
+ addLink (traceId , parent , child , isError );
195
200
}
196
201
return this ;
197
202
}
@@ -209,17 +214,19 @@ Span findRpcAncestor(Node<Span> current) {
209
214
return null ;
210
215
}
211
216
212
- void addLink (String parent , String child , boolean isError ) {
217
+ void addLink (String traceId , String parent , String child , boolean isError ) {
213
218
if (logger .isLoggable (FINE )) {
214
219
logger .fine ("incrementing " + (isError ? "error " : "" ) + "link " + parent + " -> " + child );
215
220
}
216
221
Pair key = new Pair (parent , child );
222
+ add (callTraceIds , key , traceId );
217
223
if (callCounts .containsKey (key )) {
218
224
callCounts .put (key , callCounts .get (key ) + 1 );
219
225
} else {
220
226
callCounts .put (key , 1L );
221
227
}
222
228
if (!isError ) return ;
229
+ add (errorTraceIds , key , traceId );
223
230
if (errorCounts .containsKey (key )) {
224
231
errorCounts .put (key , errorCounts .get (key ) + 1 );
225
232
} else {
@@ -228,29 +235,41 @@ void addLink(String parent, String child, boolean isError) {
228
235
}
229
236
230
237
public List <DependencyLink > link () {
231
- return link (callCounts , errorCounts );
238
+ return link (callCounts , errorCounts , callTraceIds , errorTraceIds );
232
239
}
233
240
234
241
/** links are merged by mapping to parent/child and summing corresponding links */
235
242
public static List <DependencyLink > merge (Iterable <DependencyLink > in ) {
236
243
Map <Pair , Long > callCounts = new LinkedHashMap <>();
237
244
Map <Pair , Long > errorCounts = new LinkedHashMap <>();
245
+ Map <Pair , Set <String >> callTraceIds = new LinkedHashMap <>();
246
+ Map <Pair , Set <String >> errorTraceIds = new LinkedHashMap <>();
238
247
239
248
for (DependencyLink link : in ) {
240
249
Pair parentChild = new Pair (link .parent (), link .child ());
241
250
long callCount = callCounts .containsKey (parentChild ) ? callCounts .get (parentChild ) : 0L ;
242
251
callCount += link .callCount ();
243
252
callCounts .put (parentChild , callCount );
253
+ for (int i = 0 , length = link .callTraceIds ().size (); i < length ; i ++) {
254
+ add (callTraceIds , parentChild , link .callTraceIds ().get (i ));
255
+ }
244
256
long errorCount = errorCounts .containsKey (parentChild ) ? errorCounts .get (parentChild ) : 0L ;
245
257
errorCount += link .errorCount ();
246
258
errorCounts .put (parentChild , errorCount );
259
+ for (int i = 0 , length = link .errorTraceIds ().size (); i < length ; i ++) {
260
+ add (callTraceIds , parentChild , link .errorTraceIds ().get (i ));
261
+ }
247
262
}
248
263
249
- return link (callCounts , errorCounts );
264
+ return link (callCounts , errorCounts , callTraceIds , errorTraceIds );
250
265
}
251
266
252
- static List <DependencyLink > link (Map <Pair , Long > callCounts ,
253
- Map <Pair , Long > errorCounts ) {
267
+ static List <DependencyLink > link (
268
+ Map <Pair , Long > callCounts ,
269
+ Map <Pair , Long > errorCounts ,
270
+ Map <Pair , Set <String >> callTraceIds ,
271
+ Map <Pair , Set <String >> errorTraceIds
272
+ ) {
254
273
List <DependencyLink > result = new ArrayList <>(callCounts .size ());
255
274
for (Map .Entry <Pair , Long > entry : callCounts .entrySet ()) {
256
275
Pair parentChild = entry .getKey ();
@@ -259,6 +278,8 @@ static List<DependencyLink> link(Map<Pair, Long> callCounts,
259
278
.child (parentChild .right )
260
279
.callCount (entry .getValue ())
261
280
.errorCount (errorCounts .containsKey (parentChild ) ? errorCounts .get (parentChild ) : 0L )
281
+ .callTraceIds (maybeGet (callTraceIds , parentChild ))
282
+ .errorTraceIds (maybeGet (errorTraceIds , parentChild ))
262
283
.build ());
263
284
}
264
285
return result ;
@@ -290,4 +311,19 @@ public int hashCode() {
290
311
return h$ ;
291
312
}
292
313
}
314
+
315
+ static void add (Map <Pair , Set <String >> linkToTraceIds , Pair link , String traceId ) {
316
+ if (linkToTraceIds .containsKey (link )) {
317
+ linkToTraceIds .get (link ).add (traceId );
318
+ } else {
319
+ LinkedHashSet <String > traceIds = new LinkedHashSet <>();
320
+ traceIds .add (traceId );
321
+ linkToTraceIds .put (link , traceIds );
322
+ }
323
+ }
324
+
325
+ static List <String > maybeGet (Map <Pair , Set <String >> linkToTraceIds , Pair link ) {
326
+ Set <String > result = linkToTraceIds .get (link );
327
+ return result == null ? null : new ArrayList <>(result );
328
+ }
293
329
}
0 commit comments