private void exportRpcRequest(Map<String, String> out, RequestLog log) { if (!log.isAvailable(RequestLogAvailability.REQUEST_CONTENT)) { return; } final Object requestContent = log.requestContent(); if (requestContent instanceof RpcRequest) { final RpcRequest rpcReq = (RpcRequest) requestContent; if (builtIns.contains(REQ_RPC_METHOD)) { out.put(REQ_RPC_METHOD.mdcKey, rpcReq.method()); } if (builtIns.contains(REQ_RPC_PARAMS)) { out.put(REQ_RPC_PARAMS.mdcKey, String.valueOf(rpcReq.params())); } } }
/** * Creates a new instance with the specified parameters. */ static RpcRequest of(Class<?> serviceType, String method, Object... params) { requireNonNull(params, "params"); switch (params.length) { case 0: return of(serviceType, method); case 1: return of(serviceType, method, params[0]); default: return new DefaultRpcRequest(serviceType, method, params); } }
private static void verifyOneWayInvocation(Class<?> expectedServiceType, String expectedParam) { await().untilAsserted(() -> { final RequestLog log = requestLogs.poll(); assertThat(log).isNotNull(); final RpcRequest req = (RpcRequest) log.requestContent(); final RpcResponse res = (RpcResponse) log.responseContent(); assertThat(req).isNotNull(); assertThat(req.serviceType()).isSameAs(expectedServiceType); assertThat(req.method()).isEqualTo("hello"); assertThat(req.params()).containsExactly(expectedParam); assertThat((Object) res).isNotNull(); assertThat(res.get()).isNull(); }); }
@Test public void emptyUnary() throws Exception { assertThat(blockingStub.emptyCall(EMPTY)).isEqualTo(EMPTY); checkRequestLog((rpcReq, rpcRes, grpcStatus) -> { assertThat(rpcReq.params()).containsExactly(EMPTY); assertThat(rpcRes.get()).isEqualTo(EMPTY); }); }
if (requestContent instanceof RpcRequest) { requestLine.append('#') .append(((RpcRequest) requestContent).method());
private void checkRequestLogError(RequestLogErrorChecker checker) throws Exception { final RequestLog log = requestLogQueue.take(); assertThat(log.availabilities()).contains(RequestLogAvailability.COMPLETE); final RpcRequest rpcReq = (RpcRequest) log.requestContent(); if (rpcReq != null) { assertThat(rpcReq.serviceType()).isEqualTo(GrpcLogUtil.class); } checker.check(log.responseHeaders(), rpcReq, log.responseCause()); }
@Override public RpcResponse serve(ServiceRequestContext ctx, RpcRequest req) throws Exception { ctx.setRequestTimeoutMillis(((Number) req.params().get(0)).longValue() + ctx.requestTimeoutMillis()); return delegate().serve(ctx, req); } }
private List<Tag> buildTags(RequestLog log) { final RequestContext ctx = log.context(); final Object requestContent = log.requestContent(); String methodName = null; if (requestContent instanceof RpcRequest) { methodName = ((RpcRequest) requestContent).method(); } if (methodName == null) { final HttpHeaders requestHeaders = log.requestHeaders(); final HttpMethod httpMethod = requestHeaders.method(); if (httpMethod != null) { methodName = httpMethod.name(); } } if (methodName == null) { methodName = MoreObjects.firstNonNull(log.method().name(), "__UNKNOWN_METHOD__"); } final List<Tag> tags = new ArrayList<>(4); // method, hostNamePattern, pathMapping, status tags.add(Tag.of("method", methodName)); if (ctx instanceof ServiceRequestContext) { final ServiceRequestContext sCtx = (ServiceRequestContext) ctx; tags.add(Tag.of("hostnamePattern", sCtx.virtualHost().hostnamePattern())); tags.add(Tag.of("pathMapping", sCtx.pathMapping().meterTag())); } return tags; } };
private void checkRequestLog(RequestLogChecker checker) throws Exception { final RequestLog log = requestLogQueue.take(); assertThat(log.availabilities()).contains(RequestLogAvailability.COMPLETE); final RpcRequest rpcReq = (RpcRequest) log.requestContent(); final RpcResponse rpcRes = (RpcResponse) log.responseContent(); assertThat(rpcReq).isNotNull(); assertThat((Object) rpcRes).isNotNull(); assertThat(rpcReq.serviceType()).isEqualTo(GrpcLogUtil.class); final Status grpcStatus; if (rpcRes.cause() != null) { grpcStatus = ((StatusException) rpcRes.cause()).getStatus(); } else { grpcStatus = null; } checker.check(rpcReq, rpcRes, grpcStatus); }
@Override public RpcResponse serve(ServiceRequestContext ctx, RpcRequest call) throws Exception { final int colonPos = call.method().indexOf(':'); final String method; final String serviceName; if (colonPos < 0) { serviceName = ""; method = call.method(); } else { serviceName = call.method().substring(0, colonPos); method = call.method().substring(colonPos + 1); } // Ensure that such a service exists. final ThriftServiceEntry e = entries.get(serviceName); if (e != null) { // Ensure that such a method exists. final ThriftFunction f = e.metadata.function(method); if (f != null) { final DefaultRpcResponse reply = new DefaultRpcResponse(); invoke(ctx, e.implementation, f, call.params(), reply); return reply; } } return new DefaultRpcResponse(new TApplicationException( TApplicationException.UNKNOWN_METHOD, "unknown method: " + call.method())); }
@Test(timeout = 10000) public void testMessageLogsForOneWay() throws Exception { final OnewayHelloService.Iface client = Clients.newClient(clientFactory(), getURI(Handlers.HELLO), Handlers.ONEWAYHELLO.iface(), clientOptions); recordMessageLogs = true; client.hello("trustin"); final RequestLog log = requestLogs.take(); assertThat(log.requestHeaders()).isInstanceOf(HttpHeaders.class); assertThat(log.requestContent()).isInstanceOf(RpcRequest.class); assertThat(log.rawRequestContent()).isInstanceOf(ThriftCall.class); final RpcRequest request = (RpcRequest) log.requestContent(); assertThat(request.serviceType()).isEqualTo(OnewayHelloService.Iface.class); assertThat(request.method()).isEqualTo("hello"); assertThat(request.params()).containsExactly("trustin"); final ThriftCall rawRequest = (ThriftCall) log.rawRequestContent(); assertThat(rawRequest.header().type).isEqualTo(TMessageType.ONEWAY); assertThat(rawRequest.header().name).isEqualTo("hello"); assertThat(rawRequest.args()).isInstanceOf(OnewayHelloService.hello_args.class); assertThat(((OnewayHelloService.hello_args) rawRequest.args()).getName()).isEqualTo("trustin"); assertThat(log.responseHeaders()).isInstanceOf(HttpHeaders.class); assertThat(log.responseContent()).isInstanceOf(RpcResponse.class); assertThat(log.rawResponseContent()).isNull(); final RpcResponse response = (RpcResponse) log.responseContent(); assertThat(response.get()).isNull(); }
@Override public RpcResponse execute(ClientRequestContext ctx, RpcRequest req) throws Exception { ctx.setResponseTimeoutMillis(((Number) req.params().get(0)).longValue() + ctx.responseTimeoutMillis()); return delegate().execute(ctx, req); } }
span.name(((RpcRequest) requestContent).method());
/** * Returns a {@link RpcRequest} corresponding to the given {@link MethodDescriptor}. */ public static RpcRequest rpcRequest(MethodDescriptor<?, ?> method) { // See below to learn why we use GrpcLogUtil.class here. return RpcRequest.of(GrpcLogUtil.class, method.getFullMethodName()); }
private static void checkRequestLog(RequestLogChecker checker) throws Exception { final RequestLog log = requestLogQueue.take(); assertThat(log.availabilities()).contains(RequestLogAvailability.COMPLETE); final RpcRequest rpcReq = (RpcRequest) log.requestContent(); final RpcResponse rpcRes = (RpcResponse) log.responseContent(); assertThat(rpcReq).isNotNull(); assertThat((Object) rpcRes).isNotNull(); assertThat(rpcReq.serviceType()).isEqualTo(GrpcLogUtil.class); final Status grpcStatus; if (rpcRes.cause() != null) { grpcStatus = ((StatusException) rpcRes.cause()).getStatus(); } else { grpcStatus = null; } checker.check(rpcReq, rpcRes, grpcStatus); }
@Test public void compressedClient_compressedEndpoint() throws Exception { assertThat(blockingClient.staticUnaryCallSetsMessageCompression(REQUEST_MESSAGE)) .isEqualTo(RESPONSE_MESSAGE); checkRequestLog((rpcReq, rpcRes, grpcStatus) -> { assertThat(rpcReq.method()).isEqualTo( "armeria.grpc.testing.UnitTestService/StaticUnaryCallSetsMessageCompression"); assertThat(rpcReq.params()).containsExactly(REQUEST_MESSAGE); assertThat(rpcRes.get()).isEqualTo(RESPONSE_MESSAGE); }); }
@Test(timeout = 10000) public void testMessageLogsForException() throws Exception { final HelloService.Iface client = Clients.newClient(clientFactory(), getURI(Handlers.EXCEPTION), Handlers.EXCEPTION.iface(), clientOptions); recordMessageLogs = true; assertThatThrownBy(() -> client.hello("trustin")).isInstanceOf(TApplicationException.class); final RequestLog log = requestLogs.take(); assertThat(log.requestHeaders()).isInstanceOf(HttpHeaders.class); assertThat(log.requestContent()).isInstanceOf(RpcRequest.class); assertThat(log.rawRequestContent()).isInstanceOf(ThriftCall.class); final RpcRequest request = (RpcRequest) log.requestContent(); assertThat(request.serviceType()).isEqualTo(HelloService.Iface.class); assertThat(request.method()).isEqualTo("hello"); assertThat(request.params()).containsExactly("trustin"); final ThriftCall rawRequest = (ThriftCall) log.rawRequestContent(); assertThat(rawRequest.header().type).isEqualTo(TMessageType.CALL); assertThat(rawRequest.header().name).isEqualTo("hello"); assertThat(rawRequest.args()).isInstanceOf(HelloService.hello_args.class); assertThat(((HelloService.hello_args) rawRequest.args()).getName()).isEqualTo("trustin"); assertThat(log.responseHeaders()).isInstanceOf(HttpHeaders.class); assertThat(log.responseContent()).isInstanceOf(RpcResponse.class); assertThat(log.rawResponseContent()).isInstanceOf(ThriftReply.class); final RpcResponse response = (RpcResponse) log.responseContent(); assertThat(response.cause()).isNotNull(); final ThriftReply rawResponse = (ThriftReply) log.rawResponseContent(); assertThat(rawResponse.header().type).isEqualTo(TMessageType.EXCEPTION); assertThat(rawResponse.header().name).isEqualTo("hello"); assertThat(rawResponse.exception()).isNotNull(); }
/** Sends an rpc to an unimplemented method within TestService. */ @Test public void unimplementedMethod() throws Exception { final Throwable t = catchThrowable(() -> blockingStub.unimplementedCall(Empty.getDefaultInstance())); assertThat(t).isInstanceOf(StatusRuntimeException.class); assertThat(((StatusRuntimeException) t).getStatus().getCode()) .isEqualTo(Status.UNIMPLEMENTED.getCode()); checkRequestLogError((headers, rpcReq, cause) -> { assertThat(rpcReq).isNotNull(); assertThat(rpcReq.params()).containsExactly(Empty.getDefaultInstance()); assertThat(headers.get(GrpcHeaderNames.GRPC_STATUS)).isEqualTo( String.valueOf(Status.UNIMPLEMENTED.getCode().value())); }); }
@Override protected void configure(ServerBuilder sb) throws Exception { sb.service( "/", THttpService.of(ImmutableMap.of("", (Iface) name -> "none:" + name, "foo", name -> "foo:" + name, "bar", name -> "bar:" + name)) .decorate((delegate, ctx, req) -> { ctx.log().addListener(log -> { final RpcRequest call = (RpcRequest) log.requestContent(); if (call != null) { methodNames.add(call.method()); } }, RequestLogAvailability.REQUEST_CONTENT); return delegate.serve(ctx, req); })); } };
/** * Returns a {@link RpcRequest} corresponding to the given {@link MethodDescriptor}. */ public static RpcRequest rpcRequest(MethodDescriptor<?, ?> method, Object message) { // We don't actually use the RpcRequest for request processing since it doesn't fit well with streaming. // We still populate it with a reasonable method name for use in logging. The service type is currently // arbitrarily set as gRPC doesn't use Class<?> to represent services - if this becomes a problem, we // would need to refactor it to take a Object instead. return RpcRequest.of(GrpcLogUtil.class, method.getFullMethodName(), message); }