/** Returns the server-side annotations that should be added to a Zipkin span. */
  protected List<KeyValueAnnotation> annotations(ServiceRequestContext ctx, RequestLog req, O res) {

    final List<KeyValueAnnotation> annotations = new ArrayList<>(5);

    final StringBuilder uriBuilder = new StringBuilder();
    uriBuilder.append(req.scheme().uriText());
    uriBuilder.append("://");
    uriBuilder.append(req.host());
    uriBuilder.append(ctx.path());
    if (req.method() != null) {
      uriBuilder.append('#');
      uriBuilder.append(req.method());
    }
    annotations.add(KeyValueAnnotation.create("server.uri", uriBuilder.toString()));

    if (ctx.remoteAddress() != null) {
      annotations.add(KeyValueAnnotation.create("server.remote", ctx.remoteAddress().toString()));
    }

    if (ctx.localAddress() != null) {
      annotations.add(KeyValueAnnotation.create("server.local", ctx.localAddress().toString()));
    }

    final CompletableFuture<?> f = res.closeFuture();
    if (f.isDone()) {
      // Need to use a callback because CompletableFuture does not have a getter for the cause of
      // failure.
      // The callback will be invoked immediately because the future is done already.
      f.handle(
              voidFunction(
                  (result, cause) -> {
                    final String resultText = cause == null ? "success" : "failure";
                    annotations.add(KeyValueAnnotation.create("server.result", resultText));

                    if (cause != null) {
                      annotations.add(KeyValueAnnotation.create("server.cause", cause.toString()));
                    }
                  }))
          .exceptionally(CompletionActions::log);
    }

    return annotations;
  }
 private void closeSpan(ServiceRequestContext ctx, ServerSpan serverSpan, RequestLog req, O res) {
   if (req.hasAttr(RequestLog.RPC_REQUEST)) {
     serverSpan.getSpan().setName(req.attr(RequestLog.RPC_REQUEST).get().method());
   }
   serverInterceptor.closeSpan(serverSpan, createResponseAdapter(ctx, req, res));
 }