// Copyright 2017 The Nomulus Authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package google.registry.proxy.handler; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; import static google.registry.proxy.Protocol.PROTOCOL_KEY; import static google.registry.proxy.handler.EppServiceHandler.CLIENT_CERTIFICATE_HASH_KEY; import static google.registry.proxy.handler.RelayHandler.RELAY_CHANNEL_KEY; import google.registry.proxy.handler.RelayHandler.FullHttpResponseRelayHandler; import google.registry.proxy.metric.BackendMetrics; import google.registry.util.Clock; import io.netty.channel.Channel; import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; import java.util.ArrayDeque; import java.util.Optional; import java.util.Queue; import javax.inject.Inject; import org.joda.time.DateTime; /** * Handler that records metrics a backend channel. * *
This handler is added right before {@link FullHttpResponseRelayHandler} in the backend * protocol handler provider method. {@link FullHttpRequest} outbound messages encounter this first * before being handed over to HTTP related handler. {@link FullHttpResponse} inbound messages are * first constructed (from plain bytes) by preceding handlers and then logged in this handler. */ public class BackendMetricsHandler extends ChannelDuplexHandler { private final Clock clock; private final BackendMetrics metrics; private String relayedProtocolName; private String clientCertHash; private Channel relayedChannel; /** * A queue that saves the time at which a request is sent to the GAE app. * *
This queue is used to calculate HTTP request-response latency. HTTP 1.1 specification allows * for pipelining, in which a client can sent multiple requests without waiting for each * responses. Therefore a queue is needed to record all the requests that are sent but have not * yet received a response. * *
A server must send its response in the same order it receives requests. This invariance
* guarantees that the request time at the head of the queue always corresponds to the response
* received in {@link #channelRead}.
*
* @see RFC 2616 8.1.2.2
* Pipelining
*/
private final Queue