Head sampling decides before a request's outcome is known. Tail sampling waits for completed traces, making it possible to prioritize errors and unusually slow requests when storage capacity is limited.
Design a TailBasedTraceSampler class:
TailBasedTraceSampler() creates a stateless sampler.int[] selectTraces(int[] traceIds, int[] durations, int[] errorFlags, int capacity) returns retained trace IDs in sampling-priority order.
Arrays are aligned and each errorFlags[i] is 1 for an error or 0 for success. Rank traces by:
- Errors before successes.
- Longer duration before shorter duration within the same error class.
- Smaller trace ID when both preceding values tie.
Return the first capacity IDs under that ordering. The policy is deterministic so its behavior can be tested and audited.
Example 1:
Input:
Output:
Explanation: Trace 3 is the only error and ranks first. Of the successful traces, trace 4 has the greatest duration.
Example 2:
Input:
Output:
Explanation: Error status outranks duration, so successful trace 30 is not selected. Trace 20 is the slower of the two errors.
Constraints
1 <= traceIds.length == durations.length == errorFlags.length <= 10^5- Trace IDs are unique positive integers.
0 <= durations[i] <= 10^9errorFlags[i] is 0 or 1.0 <= capacity <= traceIds.length- Return selected IDs in policy-priority order.
- At most
100 calls are made to selectTraces.