private Span createSpanForServiceRouteCall()

in trace-java-client/src/main/java/com/amazon/opentelemetry/trace/utils/TraceGenerator.java [59:135]


    private Span createSpanForServiceRouteCall(TagSet parentTagSet, ServiceTier serviceTier, String routeName, long startTimeMicros) {
        String instanceName = serviceTier.instances.get(
                random.nextInt(serviceTier.instances.size()));
        ServiceRoute route = serviceTier.getRoute(routeName);

        // send tags of serviceTier and serviceTier instance
        Service service = new Service(serviceTier.serviceName, instanceName, new ArrayList<>());
        Span span = new Span();
        span.startTimeMicros = startTimeMicros;
        span.operationName = route.route;
        span.service = service;
        span.tags.add(KeyValue.ofLongType("load_generator.seq_num", sequenceNumber.getAndIncrement()));

        // Setup base tags
        span.setHttpMethodTag("GET");
        span.setHttpUrlTag("http://" + serviceTier.serviceName + routeName);
        // Get additional tags for this route, and update with any inherited tags
        TagSet routeTags = serviceTier.getTagSet(routeName);
        HashMap<String, Object> tagsToSet = new HashMap<>(routeTags.tags);
        for (TagGenerator tagGenerator : routeTags.tagGenerators) {
            tagsToSet.putAll(tagGenerator.generateTags());
        }
        if (parentTagSet != null && routeTags.inherit != null) {
            for (String inheritTagKey : routeTags.inherit) {
                Object value = parentTagSet.tags.get(inheritTagKey);
                if (value != null) {
                    tagsToSet.put(inheritTagKey, value);
                }
            }
        }

        // Set the additional tags on the span
        List<KeyValue> spanTags = tagsToSet.entrySet().stream()
            .map(t -> {
                Object val = t.getValue();
                if (val instanceof String) {
                    return KeyValue.ofStringType(t.getKey(), (String) val);
                }
                if (val instanceof Double) {
                    return KeyValue.ofLongType(t.getKey(), ((Double) val).longValue());
                }
                if (val instanceof Boolean) {
                    return KeyValue.ofBooleanType(t.getKey(), (Boolean) val);
                }
                return null;
            })
            .filter(Objects::nonNull)
            .collect(Collectors.toList());
        span.tags.addAll(spanTags);

        final AtomicLong maxEndTime = new AtomicLong(startTimeMicros);
        if (span.isErrorSpan()) {
            // inject root cause error and terminate trace there
            span.markRootCauseError();
        } else {
            // no error, make downstream calls
            route.downstreamCalls.forEach((s, r) -> {
                long childStartTimeMicros = startTimeMicros + TimeUnit.MILLISECONDS.toMicros(random.nextInt(route.maxLatencyMillis));
                ServiceTier childSvc = this.topology.getServiceTier(s);
                Span childSpan = createSpanForServiceRouteCall(routeTags, childSvc, r, childStartTimeMicros);
                Reference ref = new Reference(RefType.CHILD_OF, span.id, childSpan.id);
                childSpan.refs.add(ref);
                maxEndTime.set(Math.max(maxEndTime.get(), childSpan.endTimeMicros));
                if (childSpan.isErrorSpan()) {
                    Integer httpCode = childSpan.getHttpCode();
                    if (httpCode != null) {
                        span.setHttpCode(httpCode);
                    }
                    span.markError();
                }
            });
        }
        long ownDuration = TimeUnit.MILLISECONDS.toMicros((long)this.random.nextInt(route.maxLatencyMillis));
        span.endTimeMicros = maxEndTime.get() + ownDuration;
        trace.addSpan(span);
        return span;
    }