package com.linkedin.databus.client.pub.mbean; /* * * 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.io.IOException; import java.io.OutputStream; import java.util.Hashtable; import java.util.List; import java.util.concurrent.locks.Lock; import javax.management.MBeanServer; import javax.management.MalformedObjectNameException; import javax.management.ObjectName; import org.apache.avro.io.JsonEncoder; import org.apache.avro.specific.SpecificDatumWriter; import com.linkedin.databus.client.pub.monitoring.events.ConsumerCallbackStatsEvent; import com.linkedin.databus.core.DbusEvent; import com.linkedin.databus.core.monitoring.mbean.AbstractMonitoringMBean; import com.linkedin.databus.core.monitoring.mbean.DbusEventsStatisticsCollector; import com.linkedin.databus.core.monitoring.mbean.StatsCollectorMergeable; public class ConsumerCallbackStats extends AbstractMonitoringMBean<ConsumerCallbackStatsEvent> implements ConsumerCallbackStatsMBean, StatsCollectorMergeable<ConsumerCallbackStats> { private final String _name; private final String _dimension; private final MBeanServer _mbeanServer; public ConsumerCallbackStats(int ownerId, String name, String dimension, boolean enabled, boolean threadSafe, ConsumerCallbackStatsEvent initData) { this(ownerId, name, dimension,enabled,threadSafe,initData,null); } public ConsumerCallbackStats(int ownerId, String name, String dimension, boolean enabled, boolean threadSafe, ConsumerCallbackStatsEvent initData, MBeanServer server) { super(enabled, threadSafe, initData); _event.ownerId = ownerId; _name = name; _dimension = dimension; _event.dimension = dimension; _event.timestampCreationMs = System.currentTimeMillis(); _event.timestampLastMergeMs =_event.timestampCreationMs; _mbeanServer = server; resetData(); registerAsMbean(); } public String getDimension() { return _dimension; } public String getName() { return _name; } public void registerAsMbean() { super.registerAsMbean(_mbeanServer); } public void unregisterAsMbean() { super.unregisterMbean(_mbeanServer); } @Override public long getTimestampLastResetMs() { Lock readLock = acquireReadLock(); long result = 0; try { result = _event.timestampLastResetMs; } finally { releaseLock(readLock); } return result; } @Override public long getTimeSinceLastResetMs() { Lock readLock = acquireReadLock(); long result = 0; try { result = System.currentTimeMillis() - _event.timestampLastResetMs; } finally { releaseLock(readLock); } return result; } @Override public JsonEncoder createJsonEncoder(OutputStream out) throws IOException { return new JsonEncoder(_event.getSchema(), out); } @Override public ObjectName generateObjectName() throws MalformedObjectNameException { Hashtable<String, String> mbeanProps = generateBaseMBeanProps(); mbeanProps.put("ownerId", Integer.toString(_event.ownerId)); mbeanProps.put("dimension", _dimension); return new ObjectName(AbstractMonitoringMBean.JMX_DOMAIN, mbeanProps); } @Override protected void resetData() { _event.maxSeenWinScn = 0; _event.minSeenWinScn = 0; _event.latencyEventsProcessed = 0; _event.numDataEventsProcessed = 0; _event.numDataEventsReceived = 0; _event.numErrorsReceived = 0; _event.numErrorsProcessed = 0; _event.numSysEventsReceived = 0; _event.numSysEventsProcessed = 0; _event.numSysErrorsProcessed = 0; _event.numDataErrorsProcessed = 0; _event.numEventsProcessed = 0; _event.numEventsReceived = 0; _event.timestampLastResetMs = System.currentTimeMillis(); _event.timestampLastEventProcessed = 0; _event.timestampLastEventReceived = 0; _event.timestampOfLastEventReceived = 0; _event.timestampOfLastEventProcessed = 0; _event.scnOfLastEventProcessed = 0; _event.maxSeenWinTimestamp = 0; } @Override protected void cloneData(ConsumerCallbackStatsEvent event) { event.maxSeenWinScn = _event.maxSeenWinScn ; event.minSeenWinScn = _event.minSeenWinScn; event.latencyEventsProcessed = _event.latencyEventsProcessed ; event.numDataEventsReceived = _event.numDataEventsReceived; event.numDataEventsProcessed = _event.numDataEventsProcessed; event.numDataErrorsProcessed = _event.numDataErrorsProcessed; event.numErrorsReceived = _event.numErrorsReceived; event.numErrorsProcessed = _event.numErrorsProcessed; event.numSysEventsReceived = _event.numSysEventsReceived; event.numSysEventsProcessed = _event.numSysEventsProcessed; event.numSysErrorsProcessed = _event.numSysErrorsProcessed; event.numEventsProcessed = _event.numEventsProcessed; event.numEventsReceived = _event.numEventsReceived; event.scnOfLastEventProcessed = _event.scnOfLastEventProcessed; event.maxSeenWinTimestamp = _event.maxSeenWinTimestamp; } @Override protected ConsumerCallbackStatsEvent newDataEvent() { return new ConsumerCallbackStatsEvent(); } @Override protected SpecificDatumWriter<ConsumerCallbackStatsEvent> getAvroWriter() { return new SpecificDatumWriter<ConsumerCallbackStatsEvent>(ConsumerCallbackStatsEvent.class); } @Override protected void doMergeStats(Object eventData) { if (! (eventData instanceof ConsumerCallbackStatsEvent)) { if (! (eventData instanceof ConsumerCallbackStats)) { LOG.warn("Attempt to merge unknown event class" + eventData.getClass().getName()); return; } eventData = ((ConsumerCallbackStats)eventData)._event; } ConsumerCallbackStatsEvent e = (ConsumerCallbackStatsEvent)eventData; _event.numDataEventsReceived += e.numDataEventsReceived; _event.numDataEventsProcessed += e.numDataEventsProcessed; _event.numDataErrorsProcessed += e.numDataErrorsProcessed; _event.numEventsReceived += e.numEventsReceived; _event.numEventsProcessed += e.numEventsProcessed; _event.numErrorsReceived += e.numErrorsReceived; _event.numErrorsProcessed += e.numErrorsProcessed; _event.numSysEventsProcessed += e.numSysEventsProcessed; _event.numSysEventsReceived+=e.numSysEventsReceived; _event.numSysErrorsProcessed += e.numSysErrorsProcessed; _event.latencyEventsProcessed += e.latencyEventsProcessed; _event.minSeenWinScn = _event.minSeenWinScn != 0 ? Math.min(_event.minSeenWinScn,e.minSeenWinScn) : e.minSeenWinScn; _event.maxSeenWinScn = _event.maxSeenWinScn != 0 ? Math.max(_event.maxSeenWinScn,e.maxSeenWinScn) : e.maxSeenWinScn; _event.timestampLastMergeMs = System.currentTimeMillis(); _event.timestampLastEventProcessed = _event.timestampLastEventProcessed != 0 ? Math.max(_event.timestampLastEventProcessed,e.timestampLastEventProcessed) : e.timestampLastEventProcessed; _event.timestampLastEventReceived = _event.timestampLastEventReceived != 0 ? Math.max(_event.timestampLastEventReceived,e.timestampLastEventReceived) : e.timestampLastEventReceived; _event.timestampOfLastEventProcessed = _event.timestampOfLastEventProcessed != 0 ? Math.max(_event.timestampOfLastEventProcessed,e.timestampOfLastEventProcessed) : e.timestampOfLastEventProcessed; _event.timestampOfLastEventReceived = _event.timestampOfLastEventReceived != 0 ? Math.max(_event.timestampOfLastEventReceived,e.timestampOfLastEventReceived) : e.timestampOfLastEventReceived; _event.scnOfLastEventProcessed = 0 != _event.scnOfLastEventProcessed ? Math.max(_event.scnOfLastEventProcessed, e.scnOfLastEventProcessed) : e.scnOfLastEventProcessed; _event.maxSeenWinTimestamp = 0 != _event.maxSeenWinTimestamp ? Math.max(_event.maxSeenWinTimestamp, e.maxSeenWinTimestamp) : e.maxSeenWinTimestamp; } @Override public void resetAndMerge(List<ConsumerCallbackStats> objList) { Lock writeLock = acquireWriteLock(); try { reset(); for (ConsumerCallbackStats t: objList) { merge(t); } } finally { releaseLock(writeLock); } } @Override public long getNumDataEventsReceived() { Lock readLock = acquireReadLock(); long result = 0; try { result = _event.numDataEventsReceived; } finally { releaseLock(readLock); } return result; } @Override public long getNumDataEventsProcessed() { Lock readLock = acquireReadLock(); long result = 0; try { result = _event.numDataEventsProcessed; } finally { releaseLock(readLock); } return result; } @Override public long getNumDataErrorsProcessed() { Lock readLock = acquireReadLock(); long result = 0; try { result = _event.numDataErrorsProcessed; } finally { releaseLock(readLock); } return result; } @Override public long getNumSysEventsReceived() { Lock readLock = acquireReadLock(); long result = 0; try { result = _event.numSysEventsReceived; } finally { releaseLock(readLock); } return result; } @Override public long getMinSeenWinScn() { Lock readLock = acquireReadLock(); long result = 0; try { result = _event.minSeenWinScn; } finally { releaseLock(readLock); } return result; } @Override public long getMaxSeenWinScn() { Lock readLock = acquireReadLock(); long result = 0; try { result = _event.maxSeenWinScn; } finally { releaseLock(readLock); } return result; } @Override public long getNumErrorsReceived() { Lock readLock = acquireReadLock(); long result = 0; try { result = _event.numErrorsReceived; } finally { releaseLock(readLock); } return result; } @Override public long getNumErrorsProcessed() { Lock readLock = acquireReadLock(); long result = 0; try { result = _event.numErrorsProcessed; } finally { releaseLock(readLock); } return result; } @Override public long getTimeSinceCreation() { Lock readLock = acquireReadLock(); long result = 0; try { result = System.currentTimeMillis() - _event.timestampCreationMs; } finally { releaseLock(readLock); } return result; } // used only in TestMultiConsumerCallback? @Override public long getLatencyEventsProcessed() { Lock readLock = acquireReadLock(); long result = 0; try { result = _event.latencyEventsProcessed; } finally { releaseLock(readLock); } return result; } @Override public long getNumEventsProcessed() { Lock readLock = acquireReadLock(); long result = 0; try { result = _event.numEventsProcessed; } finally { releaseLock(readLock); } return result; } @Override public double getAveLatencyEventsProcessed() { Lock readLock = acquireReadLock(); double result = 0; try { result = (_event.numEventsProcessed != 0) ? (double) _event.latencyEventsProcessed/_event.numEventsProcessed : 0.0; } finally { releaseLock(readLock); } return result; } public void registerDataEventReceived(DbusEvent e) { if (! _enabled.get()) return; Lock writeLock = acquireWriteLock(); try { _event.numEventsReceived++; _event.numDataEventsReceived++; _event.timestampLastEventReceived = System.currentTimeMillis(); _event.timestampOfLastEventReceived = e.timestampInNanos()/1000000; } finally { releaseLock(writeLock); } } public void registerSystemEventReceived() { if (! _enabled.get()) return; Lock writeLock = acquireWriteLock(); try { _event.numEventsReceived++; _event.numSysEventsReceived++; _event.timestampLastEventReceived = System.currentTimeMillis(); } finally { releaseLock(writeLock); } } public void registerSystemEventProcessed(long timeElapsed) { if (! _enabled.get()) return; Lock writeLock = acquireWriteLock(); try { _event.numEventsProcessed++; _event.numSysEventsProcessed++; _event.timestampLastEventProcessed = System.currentTimeMillis(); _event.latencyEventsProcessed += timeElapsed; } finally { releaseLock(writeLock); } } public void registerEventsReceived(int size) { if (! _enabled.get()) return; Lock writeLock = acquireWriteLock(); try { _event.numEventsReceived+=size; _event.timestampLastEventReceived = System.currentTimeMillis(); } finally { releaseLock(writeLock); } } public void registerEventsProcessed(int size,long timeElapsed) { if (! _enabled.get()) return; Lock writeLock = acquireWriteLock(); try { _event.numEventsProcessed+=size; _event.timestampLastEventProcessed = System.currentTimeMillis(); _event.latencyEventsProcessed+=timeElapsed; } finally { releaseLock(writeLock); } } public void registerDataEventsProcessed(int size, long timeElapsed, DbusEvent e) { if (! _enabled.get()) return; Lock writeLock = acquireWriteLock(); try { _event.numEventsProcessed+=size; _event.numDataEventsProcessed+=size; _event.latencyEventsProcessed+=timeElapsed; _event.timestampLastEventProcessed = System.currentTimeMillis(); _event.timestampOfLastEventProcessed = e.timestampInNanos()/1000000; _event.scnOfLastEventProcessed = e.sequence(); } finally { releaseLock(writeLock); } } public void registerErrorEventsProcessed(int size) { if (! _enabled.get()) return; Lock writeLock = acquireWriteLock(); try { _event.numErrorsProcessed+=size; } finally { releaseLock(writeLock); } } public void registerSysErrorsProcessed() { if (! _enabled.get()) return; Lock writeLock = acquireWriteLock(); try { _event.numErrorsProcessed++; _event.numSysErrorsProcessed++; } finally { releaseLock(writeLock); } } public void registerDataErrorsProcessed() { if (! _enabled.get()) return; Lock writeLock = acquireWriteLock(); try { _event.numErrorsProcessed++; _event.numDataErrorsProcessed++; } finally { releaseLock(writeLock); } } public void registerSrcErrors() { if (! _enabled.get()) return; Lock writeLock = acquireWriteLock(); try { _event.numErrorsReceived++; } finally { releaseLock(writeLock); } } public void registerWindowSeen(long timestamp, long scn) { Lock writeLock = acquireWriteLock(); try { _event.maxSeenWinScn = _event.maxSeenWinScn==0 ? scn : Math.max(_event.maxSeenWinScn, scn); _event.minSeenWinScn = _event.minSeenWinScn==0 ? scn : Math.min(_event.minSeenWinScn, scn); _event.maxSeenWinTimestamp = 0 == _event.maxSeenWinTimestamp ? timestamp / 1000000 : Math.max(_event.maxSeenWinTimestamp, timestamp / 1000000); } finally { releaseLock(writeLock); } } @Override /** Deprecated **/ public long getTimeSinceLastMergeMs() { Lock readLock = acquireReadLock(); long result = 0; try { result = System.currentTimeMillis() - _event.timestampLastMergeMs; } finally { releaseLock(readLock); } return result; } @Override public long getTimeSinceLastEventReceived() { Lock readLock = acquireReadLock(); long result = 0; try { result = System.currentTimeMillis() - _event.timestampLastEventReceived; } finally { releaseLock(readLock); } return result; } @Override public long getTimeSinceLastEventProcessed() { Lock readLock = acquireReadLock(); long result = 0; try { result = System.currentTimeMillis() - _event.timestampLastEventProcessed; } finally { releaseLock(readLock); } return result; } @Override public long getTimeDiffLastEventReceived() { Lock readLock = acquireReadLock(); long result = 0; try { result = System.currentTimeMillis() - _event.timestampOfLastEventReceived; } finally { releaseLock(readLock); } return result; } @Override public long getTimeDiffLastEventProcessed() { Lock readLock = acquireReadLock(); long result = 0; try { result = System.currentTimeMillis() - _event.timestampOfLastEventProcessed; } finally { releaseLock(readLock); } return result; } @Override public long getNumSysErrorsProcessed() { Lock readLock = acquireReadLock(); long result = 0; try { result = _event.numSysErrorsProcessed; } finally { releaseLock(readLock); } return result; } @Override public long getNumEventsReceived() { Lock readLock = acquireReadLock(); long result = 0; try { result = _event.numEventsReceived; } finally { releaseLock(readLock); } return result; } @Override public long getNumSysEventsProcessed() { Lock readLock = acquireReadLock(); long result = 0; try { result = _event.numSysEventsProcessed; } finally { releaseLock(readLock); } return result; } @Override public void merge(ConsumerCallbackStats obj) { if (! _enabled.get()) return; Lock writeLock = acquireWriteLock(); try { doMergeStats(obj); } finally { releaseLock(writeLock); } } @Override public long getScnOfLastEventProcessed() { Lock readLock = acquireReadLock(); long result = 0; try { result = _event.scnOfLastEventProcessed; } finally { releaseLock(readLock); } return result; } @Override public long getMaxSeenWinTimestamp() { Lock readLock = acquireReadLock(); long result = 0; try { result = _event.maxSeenWinTimestamp; } finally { releaseLock(readLock); } return result; } }