@Override
        public void streamClosed(Status status) {
            stopwatch.stop();
            attemptNanos = stopwatch.elapsed(TimeUnit.NANOSECONDS);
            Deadline deadline = info.getCallOptions().getDeadline();
            statusCode = status.getCode();
            if (statusCode == Status.Code.CANCELLED && deadline != null) {
                // When the server's deadline expires, it can only reset the stream with CANCEL and no
                // description. Since our timer may be delayed in firing, we double-check the deadline and
                // turn the failure into the likely more helpful DEADLINE_EXCEEDED status.
                if (deadline.isExpired()) {
                    statusCode = Code.DEADLINE_EXCEEDED;
                }
            }
            attemptsState.attemptEnded();
            if (inboundReceivedOrClosed.compareAndSet(false, true)) {
                // Stream is closed early. So no need to record metrics for any inbound events after this
                // point.
                recordFinishedAttempt();
            } // Otherwise will report metrics in callEnded() to guarantee all inbound metrics are
              // recorded.
        }
Provides factories for {@link io.grpc.StreamTracer} that records metrics.

<p>
On the client-side, a factory is created for each call, and the factory creates a stream tracer for each attempt.

<b>Note:</b> This class uses experimental grpc-java-API features.
grpc-client-spring-boot-starter/src/main/java/net/devh/boot/grpc/client/metrics/MetricsClientStreamTracers.java