private void propagateRequestSideLog(RequestLog child) { child.addListener(log -> startRequest0(log.channel(), log.sessionProtocol(), null, log.requestStartTimeNanos(), log.requestStartTimeMicros(), true), REQUEST_START); child.addListener(log -> serializationFormat(log.serializationFormat()), SCHEME); child.addListener(log -> requestFirstBytesTransferred(log.requestFirstBytesTransferredTimeNanos()), REQUEST_FIRST_BYTES_TRANSFERRED); child.addListener(log -> requestHeaders(log.requestHeaders()), REQUEST_HEADERS); child.addListener(log -> requestContent(log.requestContent(), log.rawRequestContent()), REQUEST_CONTENT); child.addListener(log -> endRequest0(log.requestCause(), log.requestEndTimeNanos()), REQUEST_END); }
private void propagateResponseSideLog(RequestLog lastChild) { // update the available logs if the lastChild already has them if (lastChild.isAvailable(RESPONSE_START)) { startResponse0(lastChild.responseStartTimeNanos(), lastChild.responseStartTimeMicros(), true); } if (lastChild.isAvailable(RESPONSE_FIRST_BYTES_TRANSFERRED)) { responseFirstBytesTransferred(lastChild.responseFirstBytesTransferredTimeNanos()); } if (lastChild.isAvailable(RESPONSE_HEADERS)) { responseHeaders(lastChild.responseHeaders()); } if (lastChild.isAvailable(RESPONSE_CONTENT)) { responseContent(lastChild.responseContent(), lastChild.rawResponseContent()); } if (lastChild.isAvailable(RESPONSE_END)) { endResponse0(lastChild.responseCause(), lastChild.responseEndTimeNanos()); } lastChild.addListener(log -> startResponse0( log.responseStartTimeNanos(), log.responseStartTimeMicros(), true), RESPONSE_START); lastChild.addListener(log -> responseFirstBytesTransferred( log.responseFirstBytesTransferredTimeNanos()), RESPONSE_FIRST_BYTES_TRANSFERRED); lastChild.addListener(log -> responseHeaders(log.responseHeaders()), RESPONSE_HEADERS); lastChild.addListener(log -> responseContent( log.responseContent(), log.rawResponseContent()), RESPONSE_CONTENT); lastChild.addListener(log -> endResponse0( log.responseCause(), log.responseEndTimeNanos()), RESPONSE_END); }
final String host = log.requestHeaders().authority(); assert host != null; span.tag("http.host", host); final StringBuilder uriBuilder = new StringBuilder() .append(log.scheme().uriText()) .append("://") .append(host) .append(log.path()); if (log.query() != null) { uriBuilder.append('?').append(log.query()); span.tag("http.method", log.method().name()) .tag("http.path", log.path()) .tag("http.url", uriBuilder.toString()) .tag("http.status_code", log.status().codeAsText()); final Throwable responseCause = log.responseCause(); if (responseCause != null) { span.tag("error", responseCause.toString()); final SocketAddress raddr = log.context().remoteAddress(); if (raddr != null) { span.tag("address.remote", raddr.toString()); final SocketAddress laddr = log.context().localAddress(); if (laddr != null) { span.tag("address.local", laddr.toString()); final Object requestContent = log.requestContent(); if (requestContent instanceof RpcRequest) {
private static void exportRequestContentLength(Map<String, String> out, RequestLog log) { if (log.isAvailable(RequestLogAvailability.REQUEST_END)) { out.put(REQ_CONTENT_LENGTH.mdcKey, String.valueOf(log.requestLength())); } }
private static void exportElapsedNanos(Map<String, String> out, RequestLog log) { if (log.isAvailable(RequestLogAvailability.COMPLETE)) { out.put(ELAPSED_NANOS.mdcKey, String.valueOf(log.totalDurationNanos())); } }
@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(); }
private static void exportAuthority(Map<String, String> out, RequestContext ctx, RequestLog log) { final Set<RequestLogAvailability> availabilities = log.availabilities(); if (availabilities.contains(RequestLogAvailability.REQUEST_HEADERS)) { final String authority = getAuthority(ctx, log.requestHeaders()); if (authority != null) { out.put(REQ_AUTHORITY.mdcKey, authority); if (log.isAvailable(RequestLogAvailability.REQUEST_START)) { final String authority = log.authority(); if (!"?".equals(authority)) { out.put(REQ_AUTHORITY.mdcKey, authority);
private static void assertNoRpcContent() throws InterruptedException { final RequestLog log = requestLogQueue.take(); assertThat(log.availabilities()).contains(RequestLogAvailability.COMPLETE); assertThat(log.requestContent()).isNull(); assertThat(log.responseContent()).isNull(); }
switch (type) { case LOCAL_IP_ADDRESS: final InetSocketAddress local = log.context().localAddress(); return local == null || local.isUnresolved() ? null : local.getAddress().getHostAddress(); final InetSocketAddress remote = log.context().remoteAddress(); return remote == null || remote.isUnresolved() ? null : remote.getAddress().getHostAddress(); } else { final ServiceRequestContext ctx = (ServiceRequestContext) log.context(); return ctx.clientAddress().getHostAddress(); final SocketAddress ra = log.context().remoteAddress(); return ra instanceof InetSocketAddress ? ((InetSocketAddress) ra).getHostString() : null; requestLine.append(log.method()) .append(' ') .append(log.requestHeaders().path()); final Object requestContent = log.requestContent(); if (requestContent instanceof RpcRequest) { requestLine.append('#') .append(firstNonNull(log.sessionProtocol(), log.context().sessionProtocol()).uriText()); return requestLine.toString(); return log.statusCode();
private void exportHttpResponseHeaders(Map<String, String> out, RequestLog log) { if (httpResHeaders == null || !log.isAvailable(RequestLogAvailability.RESPONSE_HEADERS)) { return; } exportHttpHeaders(out, log.responseHeaders(), httpResHeaders); }
/** * Constructs {@link ThriftStructuredLog} from {@link RequestContext} and {@link RequestLog}. * Can be used as {@link StructuredLogBuilder}. */ public ThriftStructuredLog(RequestLog reqLog) { super(reqLog); final Object requestContent = reqLog.rawRequestContent(); if (requestContent == null) { // Request might be responded as error before reading arguments. thriftServiceName = null; thriftMethodName = null; thriftCall = null; thriftReply = null; return; } if (!(requestContent instanceof ThriftCall)) { throw new IllegalArgumentException( "expected ApacheThriftCall instance for RequestLog.requestContent() but was " + requestContent); } final ThriftCall thriftCall = (ThriftCall) requestContent; // Get the service name from the args class name. final String argsTypeName = thriftCall.args().getClass().getName(); thriftServiceName = argsTypeName.substring(0, argsTypeName.indexOf('$')); thriftMethodName = thriftCall.header().name; this.thriftCall = thriftCall; thriftReply = (ThriftReply) reqLog.rawResponseContent(); }
return RequestLog::requestStartTimeMillis; case "requestEndTimeMillis": return log -> Instant.ofEpochMilli(log.requestStartTimeMillis()) .plusNanos(log.requestDurationNanos()).toEpochMilli(); case "requestDurationMillis": return log -> Duration.ofNanos(log.requestDurationNanos()).toMillis(); case "requestDurationNanos": return RequestLog::requestDurationNanos; return RequestLog::requestLength; case "requestCause": return log -> handleThrowable(log.requestCause()); return log -> Instant.ofEpochMilli(log.responseStartTimeMillis()) .plusNanos(log.responseDurationNanos()).toEpochMilli(); case "responseDurationMillis": return log -> Duration.ofNanos(log.responseDurationNanos()).toMillis(); case "responseDurationNanos": return RequestLog::responseDurationNanos; return RequestLog::responseLength; case "responseCause": return log -> handleThrowable(log.responseCause()); return log -> Duration.ofNanos(log.totalDurationNanos()).toMillis(); case "totalDurationNanos": return RequestLog::totalDurationNanos; case "host":
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()); }
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())); } } }
private void addCallbackAndFlush(Throwable cause, State oldState, ChannelFuture future) { if (oldState != State.DONE) { future.addListener(unused -> { // Write an access log always with a cause. Respect the first specified cause. if (tryComplete()) { logBuilder().endResponse(cause); reqCtx.log().addListener(accessLogWriter::log, RequestLogAvailability.COMPLETE); } }); } ctx.flush(); }
private static void exportStatusCode(Map<String, String> out, RequestLog log) { if (log.isAvailable(RequestLogAvailability.RESPONSE_HEADERS)) { out.put(RES_STATUS_CODE.mdcKey, log.status().codeAsText()); } }
@Override protected HttpResponse doExecute(ClientRequestContext ctx, HttpRequest req, CircuitBreaker circuitBreaker) throws Exception { final HttpResponse response; try { response = delegate().execute(ctx, req); } catch (Throwable cause) { if (needsContentInStrategy) { reportSuccessOrFailure(circuitBreaker, strategyWithContent().shouldReportAsSuccess( ctx, HttpResponse.ofFailure(cause))); } else { reportSuccessOrFailure(circuitBreaker, strategy().shouldReportAsSuccess(ctx, cause)); } throw cause; } if (needsContentInStrategy) { final HttpResponseDuplicator resDuplicator = new HttpResponseDuplicator( response, maxSignalLength(ctx.maxResponseLength()), ctx.eventLoop()); reportSuccessOrFailure(circuitBreaker, strategyWithContent().shouldReportAsSuccess( ctx, resDuplicator.duplicateStream())); return resDuplicator.duplicateStream(true); } ctx.log().addListener(log -> { final Throwable cause = log.isAvailable(RequestLogAvailability.RESPONSE_END) ? log.responseCause() : null; reportSuccessOrFailure(circuitBreaker, strategy().shouldReportAsSuccess(ctx, cause)); }, RequestLogAvailability.RESPONSE_HEADERS); return response; }
assertThat(log.availabilities()).contains(RequestLogAvailability.COMPLETE); assertThat(log.requestContent()).isNotNull(); assertThat(log.responseContent()).isNull(); final RpcRequest rpcReq = (RpcRequest) log.requestContent(); assertThat(rpcReq.method()).isEqualTo( "armeria.grpc.testing.UnitTestService/StreamClientCancelsBeforeResponseClosedCancels"); assertThat(rpcReq.params()).containsExactly(SimpleRequest.getDefaultInstance()); assertThat(log.responseCause()).isInstanceOf(AbortedStreamException.class);
/** * Returns {@code true} if all of the specified {@link RequestLogAvailability}s are satisfied. */ default boolean isAvailable(RequestLogAvailability... availabilities) { for (RequestLogAvailability k : requireNonNull(availabilities, "availabilities")) { if (!isAvailable(k)) { return false; } } return true; }
private void exportHttpRequestHeaders(Map<String, String> out, RequestLog log) { if (httpReqHeaders == null || !log.isAvailable(RequestLogAvailability.REQUEST_HEADERS)) { return; } exportHttpHeaders(out, log.requestHeaders(), httpReqHeaders); }