package com.linkedin.databus.container.netty;
/*
*
* Copyright 2013 LinkedIn Corp. 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.
*
*/
import java.net.InetSocketAddress;
import org.apache.log4j.Logger;
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 com.linkedin.databus.core.monitoring.mbean.DbusEventsStatisticsCollector;
import com.linkedin.databus2.core.container.monitoring.mbean.HttpStatisticsCollector;
import com.linkedin.databus2.core.container.netty.DatabusRequestExecutionHandler;
import com.linkedin.databus2.core.container.netty.HttpRequestHandler;
import com.linkedin.databus2.core.container.request.DatabusRequest;
/**
* A class that listens for DatabusRequest messages sent over the pipeline and assigns connection-
* specific relay stats collectors.
*
* The handler should be added to the pipeline before {@link DatabusRequestExecutionHandler} and
* after {@link HttpRequestHandler}
*
* @author cbotev
*
*/
public class RelayStatisticsCollectingHandler extends SimpleChannelHandler
{
public static final String MODULE = RelayStatisticsCollectingHandler.class.getName();
public static final Logger LOG = Logger.getLogger(MODULE);
private final HttpRelay _relay;
private DbusEventsStatisticsCollector _outEventStatsCollector;
private DbusEventsStatisticsCollector _connOutEventStatsCollector;
private HttpStatisticsCollector _outHttpStatsCollector;
private HttpStatisticsCollector _connOutHttpStatsCollector;
private DatabusRequest _latestDbusRequest = null;
public RelayStatisticsCollectingHandler(HttpRelay relay)
{
_relay = relay;
_outEventStatsCollector = _relay.getOutboundEventStatisticsCollector();
_outHttpStatsCollector = _relay.getHttpStatisticsCollector();
_connOutEventStatsCollector = null;
}
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();
}
}
@Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception
{
if (null != _outEventStatsCollector || null != _outHttpStatsCollector)
{
//Opening a new connection
Object value = e.getValue();
String client = null;
if (value instanceof InetSocketAddress)
{
InetSocketAddress inetAddress = (InetSocketAddress)value;
client = inetAddress.getAddress().isLoopbackAddress() ?
"localhost" :
inetAddress.getAddress().getHostAddress();
}
else
{
client = e.getValue().toString();
}
if (null != _outEventStatsCollector)
{
_connOutEventStatsCollector = _outEventStatsCollector.createForPeerConnection(client);
}
if (null != _outHttpStatsCollector)
{
_connOutHttpStatsCollector = _outHttpStatsCollector.createForClientConnection(client);
}
}
super.channelConnected(ctx, e);
}
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception
{
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);
}
}
else if (shouldMerge(e))
{
//First or Last message in a call
mergePerConnStats();
}
}
super.messageReceived(ctx, e);
}
@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;
super.channelClosed(ctx, e);
}
}