Distributed traces contain enough structure to derive a live service dependency map. Each child span records a call from its parent span's service, and repeated calls must be aggregated without losing their failures.
Design a ServiceDependencyMapBuilder class:
ServiceDependencyMapBuilder() creates a stateless builder.String[] dependencySummary(...) returns one summary for each unique directed service edge.String[] edgesAtOrAboveErrors(..., int minErrors) returns edges whose error count is at least minErrors.
The three input arrays describe trace spans at matching positions:
services[i] is span i's service.parentIndices[i] == -1 marks a root span; otherwise it is the index of span i's parent.errorFlags[i] is 1 when span i failed and 0 otherwise.
Each non-root span contributes one request to:
services[parentIndices[i]]->services[i]
It contributes one error to that edge when errorFlags[i] == 1. Format each summary as caller->callee:requests:errors. Both methods return results sorted by the caller->callee edge key.
Example 1:
Input:
Output:
Explanation: Two spans create each edge, and one payments span failed.
Example 2:
Input:
Output:
Explanation: The inclusive threshold retains api->db because it has exactly two errors.
Constraints
1 <= services.length == parentIndices.length == errorFlags.length <= 10^5- Service names contain lowercase letters, digits, underscores, or hyphens.
parentIndices[i] == -1 or references a valid parent span; the spans form a forest.errorFlags[i] is 0 or 1.1 <= minErrors <= 10^5- Inputs are not modified.
- At most
100 total method calls are made.