package com.atlassian.bitbucket.mesh.grpc;

import io.grpc.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LoggingServerInterceptor implements ServerInterceptor {

    private static final Logger log = LoggerFactory.getLogger(LoggingServerInterceptor.class);

    @Override
    public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> call, Metadata headers,
                                                                 ServerCallHandler<ReqT, RespT> next) {
        return next.startCall(new LoggingServerCall<>(call), headers);
    }

    private static class LoggingServerCall<ReqT, RespT>
            extends ForwardingServerCall.SimpleForwardingServerCall<ReqT, RespT> {

        LoggingServerCall(ServerCall<ReqT, RespT> delegate) {
            super(delegate);
        }

        @Override
        public void close(Status status, Metadata trailers) {
            if (status != null && status.getCode() == Status.Code.UNKNOWN) {
                //To try and aid debugging we UNKNOWN errors; these are unexpected and indicate incorrect/missing
                //exception handling in the RPC server implementation
                if (isCancelled()) {
                    log.debug("Canceled RPC failed with an UNKNOWN error: {}",
                            status.getDescription(), status.getCause());
                } else {
                    log.warn("RPC failed with an UNKNOWN error: {}", status.getDescription(), status.getCause());
                }
            }

            super.close(status, trailers);
        }
    }
}
