Expose rich server context ---- * Author(s): stpierre * Approver: gnossen * Status: Draft * Implemented in: [python](https://github.com/grpc/grpc/pull/25457) * Last updated: 2021-02-17 * Discussion at: https://groups.google.com/g/grpc-io/c/ctZJkd4MfHg ## Abstract Expose context status code, details, and trailing metadata on the server side. ## Background Currently, on the server-side `ServicerContext` object, status code, details, and trailing metadata are private. As a result, an interceptor cannot take action based on any of those properties. ## Proposal We will add three methods to the servicer context interface (`grpc.ServicerContext`), and synchronous (`grpc._server._Context`) and AIO server (`grpc.aio.ServicerContext`) implementations: * `code()` returns the status code. * `details()` returns the state details. * `trailing_metadata()` returns the trailing metadata. All three are functions (not properties) for symmetry with the stub context class. ## Rationale One use case for that is a logging interceptor that logs the status of every response; ideally, with something like `grpc-interceptor`, you'd want to do something like: ```python def intercept( self, method: Callable, request: Any, context: grpc.ServicerContext, method_name: str, ) -> Any: LOG.info('[REQUEST] %s', method_name) try: retval = method(request, context) except Exception: LOG.info('[RESPONSE] %s (%s): %s', method_name, context.code(), context.details()) raise else: LOG.info('[RESPONSE] %s: OK', method_name) return retval ``` But, of course, `context.code()` and `context.details()` don't exist, and are instead the private attributes `context._state.code` and `context._state.details`. Why add getter methods to the ServicerContext when the author of the service handler is the one that calls the corresponding setter methods? They could keep track of what they set themselves. Interceptor authors, however, don't have this option. They're not necessarily in control of the service handler. So it makes sense to make these getters available to them. But once we add the getters to the interceptors, we want them added to the non-interceptor `ServicerContext` to maintain uniformity between the two interfaces. https://github.com/grpc/grpc/issues/24605 sketches out an earlier iteration of this. https://github.com/grpc/grpc/pull/25600 is an (unrelated but relevant) PR that adds most of the functionality for asyncio; that work will be used in the implementation. ## Implementation 1. Add the new API calls. https://github.com/grpc/grpc/pull/25457 holds an incomplete draft.