Moved packages from old io.moquette.server to new io.moquette.broker

This commit is contained in:
andsel
2018-11-11 18:06:13 +01:00
parent 58fd90d33d
commit 1ba9eb3613
127 changed files with 274 additions and 1414 deletions
@@ -1,172 +0,0 @@
/*
* Copyright (c) 2012-2016 The original author or authors
* ------------------------------------------------------
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* The Apache License v2.0 is available at
* http://www.opensource.org/licenses/apache2.0.php
*
* You may elect to redistribute this code under either of these licenses.
*/
package io.moquette.server.netty;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.concurrent.EventExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
/**
* Auto-flush data on channel after a read timeout. It's inspired by IdleStateHandler but it's
* specialized version, just flushing data after no read is done on the channel after a period. It's
* used to avoid aggressively flushing from the ProtocolProcessor.
*/
public class AutoFlushHandler extends ChannelDuplexHandler {
private static final Logger LOG = LoggerFactory.getLogger(AutoFlushHandler.class);
private static final long MIN_TIMEOUT_NANOS = TimeUnit.MILLISECONDS.toNanos(1);
private final long writerIdleTimeNanos;
volatile ScheduledFuture<?> writerIdleTimeout;
volatile long lastWriteTime;
// private boolean firstWriterIdleEvent = true;
private volatile int state; // 0 - none, 1 - initialized, 2 - destroyed
public AutoFlushHandler(long writerIdleTime, TimeUnit unit) {
if (unit == null) {
throw new NullPointerException("unit");
}
writerIdleTimeNanos = Math.max(unit.toNanos(writerIdleTime), MIN_TIMEOUT_NANOS);
}
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
if (ctx.channel().isActive() && ctx.channel().isRegistered()) {
// channelActive() event has been fired already, which means this.channelActive() will
// not be invoked. We have to initialize here instead.
initialize(ctx);
} else {
// channelActive() event has not been fired yet. this.channelActive() will be invoked
// and initialization will occur there.
}
}
@Override
public void handlerRemoved(ChannelHandlerContext ctx) {
destroy();
}
@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
// Initialize early if channel is active already.
// if (ctx.channel().isActive()) {
// initialize(ctx);
// }
super.channelRegistered(ctx);
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
// This method will be invoked only if this handler was added
// before channelActive() event is fired. If a user adds this handler
// after the channelActive() event, initialize() will be called by beforeAdd().
// initialize(ctx);
super.channelActive(ctx);
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
destroy();
super.channelInactive(ctx);
}
private void initialize(ChannelHandlerContext ctx) {
// Avoid the case where destroy() is called before scheduling timeouts.
// See: https://github.com/netty/netty/issues/143
if (LOG.isDebugEnabled()) {
LOG.debug("Initializing autoflush handler on channel {} Cid: {}", ctx.channel(),
NettyUtils.clientID(ctx.channel()));
}
switch (state) {
case 1:
case 2:
return;
}
state = 1;
EventExecutor loop = ctx.executor();
lastWriteTime = System.nanoTime();
writerIdleTimeout = loop.schedule(new WriterIdleTimeoutTask(ctx), writerIdleTimeNanos, TimeUnit.NANOSECONDS);
}
private void destroy() {
state = 2;
if (writerIdleTimeout != null) {
writerIdleTimeout.cancel(false);
writerIdleTimeout = null;
}
}
/**
* Is called when the write timeout expire.
*
* @param ctx the channel context.
*/
private void channelIdle(ChannelHandlerContext ctx) {
// ctx.fireUserEventTriggered(evt);
if (LOG.isTraceEnabled()) {
LOG.trace("Flushing idle Netty channel {} Cid: {}", ctx.channel(), NettyUtils.clientID(ctx.channel()));
}
ctx.channel().flush();
}
private final class WriterIdleTimeoutTask implements Runnable {
private final ChannelHandlerContext ctx;
WriterIdleTimeoutTask(ChannelHandlerContext ctx) {
this.ctx = ctx;
}
@Override
public void run() {
if (!ctx.channel().isOpen()) {
return;
}
// long lastWriteTime = IdleStateHandler.this.lastWriteTime;
// long lastWriteTime = lastWriteTime;
long nextDelay = writerIdleTimeNanos - (System.nanoTime() - lastWriteTime);
if (nextDelay <= 0) {
// Writer is idle - set a new timeout and notify the callback.
writerIdleTimeout = ctx.executor().schedule(this, writerIdleTimeNanos, TimeUnit.NANOSECONDS);
try {
/*
* IdleStateEvent event; if (firstWriterIdleEvent) { firstWriterIdleEvent =
* false; event = IdleStateEvent.FIRST_WRITER_IDLE_STATE_EVENT; } else { event =
* IdleStateEvent.WRITER_IDLE_STATE_EVENT; }
*/
channelIdle(ctx/* , event */);
} catch (Throwable t) {
ctx.fireExceptionCaught(t);
}
} else {
// Write occurred before the timeout - set a new timeout with shorter delay.
writerIdleTimeout = ctx.executor().schedule(this, nextDelay, TimeUnit.NANOSECONDS);
}
}
}
}
@@ -1,41 +0,0 @@
/*
* Copyright (c) 2012-2018 The original author or authors
* ------------------------------------------------------
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* The Apache License v2.0 is available at
* http://www.opensource.org/licenses/apache2.0.php
*
* You may elect to redistribute this code under either of these licenses.
*/
package io.moquette.server.netty;
import com.bugsnag.Bugsnag;
import io.moquette.server.config.IConfig;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import static io.moquette.BrokerConstants.BUGSNAG_TOKEN_PROPERTY_NAME;
@Sharable
public class BugSnagErrorsHandler extends ChannelInboundHandlerAdapter {
private Bugsnag bugsnag;
public void init(IConfig props) {
final String token = props.getProperty(BUGSNAG_TOKEN_PROPERTY_NAME);
this.bugsnag = new Bugsnag(token);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
bugsnag.notify(cause);
ctx.fireExceptionCaught(cause);
}
}
@@ -1,51 +0,0 @@
/*
* Copyright (c) 2012-2018 The original author or authors
* ------------------------------------------------------
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* The Apache License v2.0 is available at
* http://www.opensource.org/licenses/apache2.0.php
*
* You may elect to redistribute this code under either of these licenses.
*/
package io.moquette.server.netty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import static io.netty.channel.ChannelFutureListener.CLOSE_ON_FAILURE;
@Sharable
public class MoquetteIdleTimeoutHandler extends ChannelDuplexHandler {
private static final Logger LOG = LoggerFactory.getLogger(MoquetteIdleTimeoutHandler.class);
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
if (evt instanceof IdleStateEvent) {
IdleState e = ((IdleStateEvent) evt).state();
if (e == IdleState.READER_IDLE) {
LOG.info("Firing channel inactive event. MqttClientId = {}.", NettyUtils.clientID(ctx.channel()));
// fire a close that then fire channelInactive to trigger publish of Will
ctx.close().addListener(CLOSE_ON_FAILURE);
}
} else {
if (LOG.isTraceEnabled()) {
LOG.trace("Firing Netty event CId = {}, eventClass = {}", NettyUtils.clientID(ctx.channel()),
evt.getClass().getName());
}
super.userEventTriggered(ctx, evt);
}
}
}
@@ -1,74 +0,0 @@
/*
* Copyright (c) 2012-2018 The original author or authors
* ------------------------------------------------------
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* The Apache License v2.0 is available at
* http://www.opensource.org/licenses/apache2.0.php
*
* You may elect to redistribute this code under either of these licenses.
*/
package io.moquette.server.netty;
import io.moquette.server.Constants;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.Attribute;
import io.netty.util.AttributeKey;
/**
* Some Netty's channels utilities.
*/
public final class NettyUtils {
public static final String ATTR_USERNAME = "username";
public static final String ATTR_SESSION_STOLEN = "sessionStolen";
public static final String ATTR_CHANNEL_STATUS = "channelStatus";
private static final AttributeKey<Object> ATTR_KEY_KEEPALIVE = AttributeKey.valueOf(Constants.KEEP_ALIVE);
private static final AttributeKey<Object> ATTR_KEY_CLEANSESSION = AttributeKey.valueOf(Constants.CLEAN_SESSION);
private static final AttributeKey<Object> ATTR_KEY_CLIENTID = AttributeKey.valueOf(Constants.ATTR_CLIENTID);
private static final AttributeKey<Object> ATTR_KEY_USERNAME = AttributeKey.valueOf(ATTR_USERNAME);
public static Object getAttribute(ChannelHandlerContext ctx, AttributeKey<Object> key) {
Attribute<Object> attr = ctx.channel().attr(key);
return attr.get();
}
public static void keepAlive(Channel channel, int keepAlive) {
channel.attr(NettyUtils.ATTR_KEY_KEEPALIVE).set(keepAlive);
}
public static void cleanSession(Channel channel, boolean cleanSession) {
channel.attr(NettyUtils.ATTR_KEY_CLEANSESSION).set(cleanSession);
}
public static boolean cleanSession(Channel channel) {
return (Boolean) channel.attr(NettyUtils.ATTR_KEY_CLEANSESSION).get();
}
public static void clientID(Channel channel, String clientID) {
channel.attr(NettyUtils.ATTR_KEY_CLIENTID).set(clientID);
}
public static String clientID(Channel channel) {
return (String) channel.attr(NettyUtils.ATTR_KEY_CLIENTID).get();
}
public static void userName(Channel channel, String username) {
channel.attr(NettyUtils.ATTR_KEY_USERNAME).set(username);
}
public static String userName(Channel channel) {
return (String) channel.attr(NettyUtils.ATTR_KEY_USERNAME).get();
}
private NettyUtils() {
}
}
@@ -1,39 +0,0 @@
/*
* Copyright (c) 2012-2018 The original author or authors
* ------------------------------------------------------
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* The Apache License v2.0 is available at
* http://www.opensource.org/licenses/apache2.0.php
*
* You may elect to redistribute this code under either of these licenses.
*/
package io.moquette.server.netty.metrics;
public class BytesMetrics {
private long m_readBytes;
private long m_wroteBytes;
void incrementRead(long numBytes) {
m_readBytes += numBytes;
}
void incrementWrote(long numBytes) {
m_wroteBytes += numBytes;
}
public long readBytes() {
return m_readBytes;
}
public long wroteBytes() {
return m_wroteBytes;
}
}
@@ -1,43 +0,0 @@
/*
* Copyright (c) 2012-2018 The original author or authors
* ------------------------------------------------------
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* The Apache License v2.0 is available at
* http://www.opensource.org/licenses/apache2.0.php
*
* You may elect to redistribute this code under either of these licenses.
*/
package io.moquette.server.netty.metrics;
import java.util.concurrent.atomic.AtomicLong;
/**
* Collects all the metrics from the various pipeline.
*/
public class BytesMetricsCollector {
private AtomicLong readBytes = new AtomicLong();
private AtomicLong wroteBytes = new AtomicLong();
public BytesMetrics computeMetrics() {
BytesMetrics allMetrics = new BytesMetrics();
allMetrics.incrementRead(readBytes.get());
allMetrics.incrementWrote(wroteBytes.get());
return allMetrics;
}
public void sumReadBytes(long count) {
readBytes.getAndAdd(count);
}
public void sumWroteBytes(long count) {
wroteBytes.getAndAdd(count);
}
}
@@ -1,72 +0,0 @@
/*
* Copyright (c) 2012-2018 The original author or authors
* ------------------------------------------------------
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* The Apache License v2.0 is available at
* http://www.opensource.org/licenses/apache2.0.php
*
* You may elect to redistribute this code under either of these licenses.
*/
package io.moquette.server.netty.metrics;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;
import io.netty.util.Attribute;
import io.netty.util.AttributeKey;
import static io.netty.channel.ChannelFutureListener.CLOSE_ON_FAILURE;
public class BytesMetricsHandler extends ChannelDuplexHandler {
private static final AttributeKey<BytesMetrics> ATTR_KEY_METRICS = AttributeKey.valueOf("BytesMetrics");
private BytesMetricsCollector m_collector;
public BytesMetricsHandler(BytesMetricsCollector collector) {
m_collector = collector;
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
Attribute<BytesMetrics> attr = ctx.channel().attr(ATTR_KEY_METRICS);
attr.set(new BytesMetrics());
super.channelActive(ctx);
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
BytesMetrics metrics = ctx.channel().attr(ATTR_KEY_METRICS).get();
metrics.incrementRead(((ByteBuf) msg).readableBytes());
ctx.fireChannelRead(msg);
}
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
BytesMetrics metrics = ctx.channel().attr(ATTR_KEY_METRICS).get();
metrics.incrementWrote(((ByteBuf) msg).writableBytes());
ctx.write(msg, promise).addListener(CLOSE_ON_FAILURE);
}
@Override
public void close(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception {
BytesMetrics metrics = ctx.channel().attr(ATTR_KEY_METRICS).get();
m_collector.sumReadBytes(metrics.readBytes());
m_collector.sumWroteBytes(metrics.wroteBytes());
super.close(ctx, promise);
}
public static BytesMetrics getBytesMetrics(Channel channel) {
return channel.attr(ATTR_KEY_METRICS).get();
}
}
@@ -1,95 +0,0 @@
/*
* Copyright (c) 2012-2018 The original author or authors
* ------------------------------------------------------
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* The Apache License v2.0 is available at
* http://www.opensource.org/licenses/apache2.0.php
*
* You may elect to redistribute this code under either of these licenses.
*/
package io.moquette.server.netty.metrics;
import com.codahale.metrics.Counter;
import com.codahale.metrics.Meter;
import com.codahale.metrics.MetricRegistry;
import com.librato.metrics.reporter.Librato;
import io.moquette.server.config.IConfig;
import io.moquette.server.netty.NettyUtils;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.mqtt.MqttMessage;
import io.netty.handler.codec.mqtt.MqttMessageType;
import java.util.concurrent.TimeUnit;
import static io.moquette.BrokerConstants.*;
import static io.netty.channel.ChannelHandler.Sharable;
/**
* Pipeline handler use to track some MQTT metrics.
*/
@Sharable
public final class DropWizardMetricsHandler extends ChannelInboundHandlerAdapter {
private MetricRegistry metrics;
private Meter publishesMetrics;
private Meter subscribeMetrics;
private Counter connectedClientsMetrics;
public void init(IConfig props) {
this.metrics = new MetricRegistry();
this.publishesMetrics = metrics.meter("publish.requests");
this.subscribeMetrics = metrics.meter("subscribe.requests");
this.connectedClientsMetrics = metrics.counter("connect.num_clients");
// ConsoleReporter reporter = ConsoleReporter.forRegistry(metrics)
// .convertRatesTo(TimeUnit.SECONDS)
// .convertDurationsTo(TimeUnit.MILLISECONDS)
// .build();
// reporter.start(1, TimeUnit.MINUTES);
final String email = props.getProperty(METRICS_LIBRATO_EMAIL_PROPERTY_NAME);
final String token = props.getProperty(METRICS_LIBRATO_TOKEN_PROPERTY_NAME);
final String source = props.getProperty(METRICS_LIBRATO_SOURCE_PROPERTY_NAME);
Librato.reporter(this.metrics, email, token)
.setSource(source)
.start(10, TimeUnit.SECONDS);
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object message) {
MqttMessage msg = (MqttMessage) message;
MqttMessageType messageType = msg.fixedHeader().messageType();
switch (messageType) {
case PUBLISH:
this.publishesMetrics.mark();
break;
case SUBSCRIBE:
this.subscribeMetrics.mark();
break;
case CONNECT:
this.connectedClientsMetrics.inc();
break;
case DISCONNECT:
this.connectedClientsMetrics.dec();
break;
default:
break;
}
ctx.fireChannelRead(message);
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
String clientID = NettyUtils.clientID(ctx.channel());
if (clientID != null && !clientID.isEmpty()) {
this.connectedClientsMetrics.dec();
}
ctx.fireChannelInactive();
}
}
@@ -1,120 +0,0 @@
/*
* Copyright (c) 2012-2018 The original author or authors
* ------------------------------------------------------
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* The Apache License v2.0 is available at
* http://www.opensource.org/licenses/apache2.0.php
*
* You may elect to redistribute this code under either of these licenses.
*/
package io.moquette.server.netty.metrics;
import io.moquette.server.netty.NettyUtils;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;
import io.netty.handler.codec.mqtt.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.List;
import static io.moquette.spi.impl.Utils.messageId;
import static io.netty.channel.ChannelFutureListener.CLOSE_ON_FAILURE;
/**
*
* @author andrea
*/
@Sharable
public class MQTTMessageLogger extends ChannelDuplexHandler {
private static final Logger LOG = LoggerFactory.getLogger("messageLogger");
@Override
public void channelRead(ChannelHandlerContext ctx, Object message) throws Exception {
logMQTTMessageRead(ctx, message);
ctx.fireChannelRead(message);
}
private void logMQTTMessageRead(ChannelHandlerContext ctx, Object message) throws Exception {
logMQTTMessage(ctx, message, "C->B");
}
private void logMQTTMessageWrite(ChannelHandlerContext ctx, Object message) throws Exception {
logMQTTMessage(ctx, message, "C<-B");
}
private void logMQTTMessage(ChannelHandlerContext ctx, Object message, String direction) throws Exception {
if (!(message instanceof MqttMessage)) {
return;
}
MqttMessage msg = (MqttMessage) message;
if (msg.fixedHeader() == null) {
throw new IOException("Unknown packet");
}
String clientID = NettyUtils.clientID(ctx.channel());
MqttMessageType messageType = msg.fixedHeader().messageType();
switch (messageType) {
case CONNACK:
case PINGREQ:
case PINGRESP:
LOG.debug("{} {} <{}>", direction, messageType, clientID);
break;
case CONNECT:
case DISCONNECT:
LOG.info("{} {} <{}>", direction, messageType, clientID);
break;
case SUBSCRIBE:
MqttSubscribeMessage subscribe = (MqttSubscribeMessage) msg;
LOG.info("{} SUBSCRIBE <{}> to topics {}", direction, clientID,
subscribe.payload().topicSubscriptions());
break;
case UNSUBSCRIBE:
MqttUnsubscribeMessage unsubscribe = (MqttUnsubscribeMessage) msg;
LOG.info("{} UNSUBSCRIBE <{}> to topics <{}>", direction, clientID, unsubscribe.payload().topics());
break;
case PUBLISH:
MqttPublishMessage publish = (MqttPublishMessage) msg;
LOG.debug("{} PUBLISH <{}> to topics <{}>", direction, clientID, publish.variableHeader().topicName());
break;
case PUBREC:
case PUBCOMP:
case PUBREL:
case PUBACK:
case UNSUBACK:
LOG.info("{} {} <{}> packetID <{}>", direction, messageType, clientID, messageId(msg));
break;
case SUBACK:
MqttSubAckMessage suback = (MqttSubAckMessage) msg;
final List<Integer> grantedQoSLevels = suback.payload().grantedQoSLevels();
LOG.info("{} SUBACK <{}> packetID <{}>, grantedQoses {}", direction, clientID, messageId(msg),
grantedQoSLevels);
break;
}
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
String clientID = NettyUtils.clientID(ctx.channel());
if (clientID != null && !clientID.isEmpty()) {
LOG.info("Channel closed <{}>", clientID);
}
ctx.fireChannelInactive();
}
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
logMQTTMessageWrite(ctx, msg);
ctx.write(msg, promise).addListener(CLOSE_ON_FAILURE);
}
}
@@ -1,39 +0,0 @@
/*
* Copyright (c) 2012-2018 The original author or authors
* ------------------------------------------------------
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* The Apache License v2.0 is available at
* http://www.opensource.org/licenses/apache2.0.php
*
* You may elect to redistribute this code under either of these licenses.
*/
package io.moquette.server.netty.metrics;
public class MessageMetrics {
private long m_messagesRead;
private long m_messageWrote;
void incrementRead(long numMessages) {
m_messagesRead += numMessages;
}
void incrementWrote(long numMessages) {
m_messageWrote += numMessages;
}
public long messagesRead() {
return m_messagesRead;
}
public long messagesWrote() {
return m_messageWrote;
}
}
@@ -1,43 +0,0 @@
/*
* Copyright (c) 2012-2018 The original author or authors
* ------------------------------------------------------
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* The Apache License v2.0 is available at
* http://www.opensource.org/licenses/apache2.0.php
*
* You may elect to redistribute this code under either of these licenses.
*/
package io.moquette.server.netty.metrics;
import java.util.concurrent.atomic.AtomicLong;
/**
* Collects all the metrics from the various pipeline.
*/
public class MessageMetricsCollector {
private AtomicLong readMsgs = new AtomicLong();
private AtomicLong wroteMsgs = new AtomicLong();
public MessageMetrics computeMetrics() {
MessageMetrics allMetrics = new MessageMetrics();
allMetrics.incrementRead(readMsgs.get());
allMetrics.incrementWrote(wroteMsgs.get());
return allMetrics;
}
public void sumReadMessages(long count) {
readMsgs.getAndAdd(count);
}
public void sumWroteMessages(long count) {
wroteMsgs.getAndAdd(count);
}
}
@@ -1,71 +0,0 @@
/*
* Copyright (c) 2012-2018 The original author or authors
* ------------------------------------------------------
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* The Apache License v2.0 is available at
* http://www.opensource.org/licenses/apache2.0.php
*
* You may elect to redistribute this code under either of these licenses.
*/
package io.moquette.server.netty.metrics;
import io.netty.channel.Channel;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;
import io.netty.util.Attribute;
import io.netty.util.AttributeKey;
import static io.netty.channel.ChannelFutureListener.CLOSE_ON_FAILURE;
public class MessageMetricsHandler extends ChannelDuplexHandler {
private static final AttributeKey<MessageMetrics> ATTR_KEY_METRICS = AttributeKey.valueOf("MessageMetrics");
private MessageMetricsCollector m_collector;
public MessageMetricsHandler(MessageMetricsCollector collector) {
m_collector = collector;
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
Attribute<MessageMetrics> attr = ctx.channel().attr(ATTR_KEY_METRICS);
attr.set(new MessageMetrics());
super.channelActive(ctx);
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
MessageMetrics metrics = ctx.channel().attr(ATTR_KEY_METRICS).get();
metrics.incrementRead(1);
ctx.fireChannelRead(msg);
}
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
MessageMetrics metrics = ctx.channel().attr(ATTR_KEY_METRICS).get();
metrics.incrementWrote(1);
ctx.write(msg, promise).addListener(CLOSE_ON_FAILURE);
}
@Override
public void close(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception {
MessageMetrics metrics = ctx.channel().attr(ATTR_KEY_METRICS).get();
m_collector.sumReadMessages(metrics.messagesRead());
m_collector.sumWroteMessages(metrics.messagesWrote());
super.close(ctx, promise);
}
public static MessageMetrics getMessageMetrics(Channel channel) {
return channel.attr(ATTR_KEY_METRICS).get();
}
}