/* * Copyright 2012-2015, the original author or authors. * * 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 com.flipkart.aesop.runtime.relay.netty; import com.flipkart.aesop.runtime.relay.DefaultRelay; import com.linkedin.databus.container.request.ReadEventsRequestProcessor; import com.linkedin.databus.core.Checkpoint; import com.linkedin.databus.core.monitoring.mbean.DbusEventsStatisticsCollector; import com.linkedin.databus2.core.container.monitoring.mbean.DbusHttpTotalStats; import com.linkedin.databus2.core.container.monitoring.mbean.HttpStatisticsCollector; import com.linkedin.databus2.core.container.request.DatabusRequest; import org.jboss.netty.channel.ChannelHandlerContext; import org.jboss.netty.channel.ChannelStateEvent; import org.jboss.netty.channel.MessageEvent; import org.jboss.netty.channel.SimpleChannelHandler; import org.jboss.netty.handler.codec.http.HttpChunkTrailer; import org.jboss.netty.handler.codec.http.HttpResponse; import org.trpr.platform.core.impl.logging.LogFactory; import org.trpr.platform.core.spi.logging.Logger; import java.net.InetSocketAddress; /** * The <code>RelayStatisticsCollectingHandler</code> class is code port of the Databus {@link com.linkedin.databus.container.netty.RelayStatisticsCollectingHandler} that * listens for DatabusRequest messages sent over the pipeline and assigns connection-specific relay stats collectors. * Additionally, this collector also registers the stream request with connection-specific {@link DbusHttpTotalStats} if the Databus request is for reading events * i.e. contains a {@link Checkpoint} * * @author Regunath B * @version 1.0, 12 May 2014 */ public class RelayStatisticsCollectingHandler extends SimpleChannelHandler { /** Logger for this class*/ protected static final Logger LOGGER = LogFactory.getLogger(RelayStatisticsCollectingHandler.class); /** Member variables for this class*/ private DbusEventsStatisticsCollector outEventStatsCollector; private DbusEventsStatisticsCollector connOutEventStatsCollector; private HttpStatisticsCollector outHttpStatsCollector; private HttpStatisticsCollector connOutHttpStatsCollector; private DatabusRequest latestDbusRequest = null; /** relay instance */ private DefaultRelay relay; /** the client reference*/ private String client = null; public RelayStatisticsCollectingHandler(DefaultRelay relay) { this.relay = relay; outEventStatsCollector = relay.getOutboundEventStatisticsCollector(); outHttpStatsCollector = relay.getHttpStatisticsCollector(); connOutEventStatsCollector = null; } @Override public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception{ if (null != outEventStatsCollector || null != outHttpStatsCollector) { //Opening a new connection Object value = e.getValue(); if (value instanceof InetSocketAddress){ InetSocketAddress inetAddress = (InetSocketAddress)value; this.client = inetAddress.getAddress().isLoopbackAddress() ? "localhost" : inetAddress.getAddress().getHostAddress(); this.client = this.client + "-" + inetAddress.getPort(); } else { this.client = e.getValue().toString(); } if (null != outEventStatsCollector){ connOutEventStatsCollector = outEventStatsCollector.createForPeerConnection(client); } if (null != outHttpStatsCollector) { connOutHttpStatsCollector = outHttpStatsCollector.createForClientConnection(client); } } // Inform the Relay of a client connection, for stats tracking this.relay.firePeerConnect(this.client); super.channelConnected(ctx, e); } @Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { try { if (null != outEventStatsCollector || null != outHttpStatsCollector ) { if (e.getMessage() instanceof DatabusRequest){ latestDbusRequest = (DatabusRequest)e.getMessage(); if (null != outEventStatsCollector){ latestDbusRequest.getParams().put(outEventStatsCollector.getName(), connOutEventStatsCollector); } if (null != outHttpStatsCollector){ latestDbusRequest.getParams().put(outHttpStatsCollector.getName(), connOutHttpStatsCollector); } // check if a checkpoint exists and register the stream request with the connection-specific stats if (latestDbusRequest.getParams().getProperty(ReadEventsRequestProcessor.CHECKPOINT_PARAM) != null) { Checkpoint cp = new Checkpoint(latestDbusRequest.getParams().getProperty(ReadEventsRequestProcessor.CHECKPOINT_PARAM)); String peer = connOutHttpStatsCollector.getPeers().get(0); // the only peer that the connection-specific stats collector will have points to the remote client connOutHttpStatsCollector.getPeerStats(peer).registerStreamRequest(peer, cp); relay.getMetricsCollector().setClientSCN(peer,cp.getWindowScn()); } // update client scn } else if (shouldMerge(e)){ //First or Last message in a call mergePerConnStats(); } } super.messageReceived(ctx, e); } catch (Exception ex) { LOGGER.error("Exception while processing message in RelayStatisticsCollectingHandler"); } } @Override public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception{ if (null != connOutEventStatsCollector || null != connOutHttpStatsCollector){ mergePerConnStats(); if (null != connOutEventStatsCollector) connOutEventStatsCollector.unregisterMBeans(); if (null != connOutHttpStatsCollector) connOutHttpStatsCollector.unregisterMBeans(); connOutEventStatsCollector = null; connOutHttpStatsCollector = null; } latestDbusRequest = null; // Inform the Relay of a client disconnect, for stats tracking this.relay.firePeerDisconnect(this.client); super.channelClosed(ctx, e); } private boolean shouldMerge(MessageEvent me){ return ((me.getMessage() instanceof HttpChunkTrailer) || (me.getMessage() instanceof HttpResponse)); } private void mergePerConnStats(){ if (null != connOutEventStatsCollector){ outEventStatsCollector.merge(connOutEventStatsCollector); connOutEventStatsCollector.reset(); } if (null != connOutHttpStatsCollector){ outHttpStatsCollector.merge(connOutHttpStatsCollector); connOutHttpStatsCollector.reset(); } } }