Search in sources :

Example 11 with UnifiedClientStats

use of com.linkedin.databus.client.pub.mbean.UnifiedClientStats in project databus by linkedin.

the class TestGenericDispatcher method testPartialWindowRollback.

@Test(groups = { "small", "functional" })
public /**
     * Tests the case where the dispatcher exits the main processing loop in {@link GenericDispatcher#doDispatchEvents()}
     * with a partial window and the flushing of the outstanding callbacks fails. We want to make sure that a rollback
     * is correctly triggered.
     *
     * The test simulates the following case: e1_1 e1_2 e1_3 <EOW> e2_1 e2_2 e2_3 <EOW> ... with a failure in the e2_2
     * callback.
     *
     * 1) Read full first window: e1_1 e1_2 e1_3 <EOW>
     * 2) Read partial second window: e2_1 e2_2
     * 3) The above should fail -- verify that rollback is called
     * 4) Read the rest
     */
void testPartialWindowRollback() throws Exception {
    final Logger log = Logger.getLogger("TestGenericDispatcher.testPartialWindowRollback");
    //log.setLevel(Level.INFO);
    log.info("start");
    final Level saveLevel = Logger.getLogger("com.linkedin.databus.client").getLevel();
    //Logger.getLogger("com.linkedin.databus.client").setLevel(Level.DEBUG);
    // generate events
    Vector<Short> srcIdList = new Vector<Short>();
    srcIdList.add((short) 1);
    DbusEventGenerator evGen = new DbusEventGenerator(0, srcIdList);
    Vector<DbusEvent> srcTestEvents = new Vector<DbusEvent>();
    final int numEvents = 9;
    //1-based number of the event callback to fail
    final int numOfFailureEvent = 5;
    final int numEventsPerWindow = 3;
    final int payloadSize = 200;
    final int numWindows = (int) Math.ceil(1.0 * numEvents / numEventsPerWindow);
    Assert.assertTrue(evGen.generateEvents(numEvents, numEventsPerWindow, 500, payloadSize, srcTestEvents) > 0);
    // find out how much data we need to stream for the failure
    // account for the EOW event which is < payload size
    int win1Size = payloadSize - 1;
    int win2Size = 0;
    int eventN = 0;
    for (DbusEvent e : srcTestEvents) {
        eventN++;
        if (eventN <= numEventsPerWindow) {
            win1Size += e.size();
        } else if (eventN <= numOfFailureEvent) {
            win2Size += e.size();
        }
    }
    //serialize the events to a buffer so they can be sent to the client
    final TestGenericDispatcherEventBuffer srcEventsBuf = new TestGenericDispatcherEventBuffer(_generic100KBufferStaticConfig);
    DbusEventAppender eventProducer = new DbusEventAppender(srcTestEvents, srcEventsBuf, null, true);
    Thread tEmitter = new Thread(eventProducer);
    tEmitter.start();
    //Create destination (client) buffer
    final TestGenericDispatcherEventBuffer destEventsBuf = new TestGenericDispatcherEventBuffer(_generic100KBufferStaticConfig);
    //Create dispatcher
    final TimeoutTestConsumer mockConsumer = new TimeoutTestConsumer(100, 10, 0, numOfFailureEvent, 0, 1);
    SelectingDatabusCombinedConsumer sdccMockConsumer = new SelectingDatabusCombinedConsumer((DatabusStreamConsumer) mockConsumer);
    List<String> sources = new ArrayList<String>();
    Map<Long, IdNamePair> sourcesMap = new HashMap<Long, IdNamePair>();
    for (int i = 1; i <= 3; ++i) {
        IdNamePair sourcePair = new IdNamePair((long) i, "source" + i);
        sources.add(sourcePair.getName());
        sourcesMap.put(sourcePair.getId(), sourcePair);
    }
    DatabusV2ConsumerRegistration consumerReg = new DatabusV2ConsumerRegistration(sdccMockConsumer, sources, null);
    List<DatabusV2ConsumerRegistration> allRegistrations = Arrays.asList(consumerReg);
    final ConsumerCallbackStats callbackStats = new ConsumerCallbackStats(0, "test", "test", true, false, null);
    final UnifiedClientStats unifiedStats = new UnifiedClientStats(0, "test", "test.unified");
    MultiConsumerCallback callback = new MultiConsumerCallback(allRegistrations, Executors.newFixedThreadPool(2), 1000, new StreamConsumerCallbackFactory(callbackStats, unifiedStats), callbackStats, unifiedStats, null, null);
    callback.setSourceMap(sourcesMap);
    List<DatabusSubscription> subs = DatabusSubscription.createSubscriptionList(sources);
    final RelayDispatcher dispatcher = new RelayDispatcher("dispatcher", _genericRelayConnStaticConfig, subs, new InMemoryPersistenceProvider(), destEventsBuf, callback, null, null, null, null, null);
    dispatcher.setSchemaIdCheck(false);
    Thread dispatcherThread = new Thread(dispatcher);
    dispatcherThread.setDaemon(true);
    log.info("starting dispatcher thread");
    dispatcherThread.start();
    HashMap<Long, List<RegisterResponseEntry>> schemaMap = new HashMap<Long, List<RegisterResponseEntry>>();
    List<RegisterResponseEntry> l1 = new ArrayList<RegisterResponseEntry>();
    List<RegisterResponseEntry> l2 = new ArrayList<RegisterResponseEntry>();
    List<RegisterResponseEntry> l3 = new ArrayList<RegisterResponseEntry>();
    l1.add(new RegisterResponseEntry(1L, (short) 1, SOURCE1_SCHEMA_STR));
    l2.add(new RegisterResponseEntry(2L, (short) 1, SOURCE2_SCHEMA_STR));
    l3.add(new RegisterResponseEntry(3L, (short) 1, SOURCE3_SCHEMA_STR));
    schemaMap.put(1L, l1);
    schemaMap.put(2L, l2);
    schemaMap.put(3L, l3);
    dispatcher.enqueueMessage(SourcesMessage.createSetSourcesIdsMessage(sourcesMap.values()));
    dispatcher.enqueueMessage(SourcesMessage.createSetSourcesSchemasMessage(schemaMap));
    log.info("starting event dispatch");
    //stream the events from the source buffer without the EOW
    //comm channels between reader and writer
    Pipe pipe = Pipe.open();
    Pipe.SinkChannel writerStream = pipe.sink();
    Pipe.SourceChannel readerStream = pipe.source();
    writerStream.configureBlocking(true);
    readerStream.configureBlocking(false);
    //Event writer - Relay in the real world
    Checkpoint cp = Checkpoint.createFlexibleCheckpoint();
    //Event readers - Clients in the real world
    //Checkpoint pullerCheckpoint = Checkpoint.createFlexibleCheckpoint();
    DbusEventsStatisticsCollector clientStats = new DbusEventsStatisticsCollector(0, "client", true, false, null);
    DbusEventBufferReader reader = new DbusEventBufferReader(destEventsBuf, readerStream, null, clientStats);
    UncaughtExceptionTrackingThread tReader = new UncaughtExceptionTrackingThread(reader, "Reader");
    tReader.setDaemon(true);
    tReader.start();
    try {
        log.info("send first window -- that one should be OK");
        StreamEventsResult streamRes = srcEventsBuf.streamEvents(cp, writerStream, new StreamEventsArgs(win1Size));
        Assert.assertEquals(numEventsPerWindow + 1, streamRes.getNumEventsStreamed());
        TestUtil.assertWithBackoff(new ConditionCheck() {

            @Override
            public boolean check() {
                return 1 == callbackStats.getNumSysEventsProcessed();
            }
        }, "first window processed", 5000, log);
        log.info("send the second partial window -- that one should cause an error");
        streamRes = srcEventsBuf.streamEvents(cp, writerStream, new StreamEventsArgs(win2Size));
        Assert.assertEquals(numOfFailureEvent - numEventsPerWindow, streamRes.getNumEventsStreamed());
        log.info("wait for dispatcher to finish");
        TestUtil.assertWithBackoff(new ConditionCheck() {

            @Override
            public boolean check() {
                log.info("events received: " + callbackStats.getNumDataEventsReceived());
                return numOfFailureEvent <= callbackStats.getNumDataEventsProcessed();
            }
        }, "all events until the error processed", 5000, log);
        log.info("all data events have been received but no EOW");
        Assert.assertEquals(numOfFailureEvent, clientStats.getTotalStats().getNumDataEvents());
        Assert.assertEquals(1, clientStats.getTotalStats().getNumSysEvents());
        //at least one failing event therefore < numOfFailureEvent events can be processed
        Assert.assertTrue(numOfFailureEvent <= callbackStats.getNumDataEventsProcessed());
        //onDataEvent callbacks for e2_1 and e2_2 get cancelled
        Assert.assertEquals(2, callbackStats.getNumDataErrorsProcessed());
        //only one EOW
        Assert.assertEquals(1, callbackStats.getNumSysEventsProcessed());
        log.info("Send the remainder of the window");
        streamRes = srcEventsBuf.streamEvents(cp, writerStream, new StreamEventsArgs(100000));
        //remaining events + EOWs
        Assert.assertEquals(srcTestEvents.size() + numWindows - (numOfFailureEvent + 1), streamRes.getNumEventsStreamed());
        log.info("wait for the rollback");
        TestUtil.assertWithBackoff(new ConditionCheck() {

            @Override
            public boolean check() {
                return 1 == mockConsumer.getNumRollbacks();
            }
        }, "rollback seen", 5000, log);
        log.info("wait for dispatcher to finish after the rollback");
        TestUtil.assertWithBackoff(new ConditionCheck() {

            @Override
            public boolean check() {
                log.info("num windows processed: " + callbackStats.getNumSysEventsProcessed());
                return numWindows == callbackStats.getNumSysEventsProcessed();
            }
        }, "all events processed", 5000, log);
    } finally {
        reader.stop();
        dispatcher.shutdown();
        log.info("all events processed");
        verifyNoLocks(null, srcEventsBuf);
        verifyNoLocks(null, destEventsBuf);
    }
    Logger.getLogger("com.linkedin.databus.client").setLevel(saveLevel);
    log.info("end\n");
}
Also used : DbusEventAppender(com.linkedin.databus.core.test.DbusEventAppender) DatabusV2ConsumerRegistration(com.linkedin.databus.client.consumer.DatabusV2ConsumerRegistration) UncaughtExceptionTrackingThread(com.linkedin.databus.core.util.UncaughtExceptionTrackingThread) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) DbusEventsStatisticsCollector(com.linkedin.databus.core.monitoring.mbean.DbusEventsStatisticsCollector) StreamEventsArgs(com.linkedin.databus.core.StreamEventsArgs) Logger(org.apache.log4j.Logger) IdNamePair(com.linkedin.databus.core.util.IdNamePair) List(java.util.List) ArrayList(java.util.ArrayList) Vector(java.util.Vector) DbusEventBufferReader(com.linkedin.databus.core.test.DbusEventBufferReader) ConditionCheck(com.linkedin.databus2.test.ConditionCheck) StreamConsumerCallbackFactory(com.linkedin.databus.client.consumer.StreamConsumerCallbackFactory) UnifiedClientStats(com.linkedin.databus.client.pub.mbean.UnifiedClientStats) DbusEvent(com.linkedin.databus.core.DbusEvent) StreamEventsResult(com.linkedin.databus.core.StreamEventsResult) ConsumerCallbackStats(com.linkedin.databus.client.pub.mbean.ConsumerCallbackStats) MultiConsumerCallback(com.linkedin.databus.client.consumer.MultiConsumerCallback) DbusEventGenerator(com.linkedin.databus.core.test.DbusEventGenerator) Pipe(java.nio.channels.Pipe) DatabusSubscription(com.linkedin.databus.core.data_model.DatabusSubscription) Checkpoint(com.linkedin.databus.core.Checkpoint) UncaughtExceptionTrackingThread(com.linkedin.databus.core.util.UncaughtExceptionTrackingThread) Checkpoint(com.linkedin.databus.core.Checkpoint) SelectingDatabusCombinedConsumer(com.linkedin.databus.client.consumer.SelectingDatabusCombinedConsumer) RegisterResponseEntry(com.linkedin.databus2.core.container.request.RegisterResponseEntry) Level(org.apache.log4j.Level) Test(org.testng.annotations.Test)

Example 12 with UnifiedClientStats

use of com.linkedin.databus.client.pub.mbean.UnifiedClientStats in project databus by linkedin.

the class DatabusV2RegistrationImpl method initializeStatsCollectors.

/**
   * Initialize Statistics Collectors
   */
protected void initializeStatsCollectors(String regId, int ownerId, MBeanServer mbeanServer) {
    _inboundEventsStatsCollector = new DbusEventsStatisticsCollector(ownerId, regId + STREAM_EVENT_STATS_SUFFIX_NAME, true, false, mbeanServer);
    _bootstrapEventsStatsCollector = new DbusEventsStatisticsCollector(ownerId, regId + BOOTSTRAP_EVENT_STATS_SUFFIX_NAME, true, false, mbeanServer);
    _relayConsumerStats = new ConsumerCallbackStats(ownerId, regId + RELAY_CONSUMER_STATS_SUFFIX_NAME, regId, true, false, new ConsumerCallbackStatsEvent());
    _bootstrapConsumerStats = new ConsumerCallbackStats(ownerId, regId + BOOTSTRAP_CONSUMER_STATS_SUFFIX_NAME, regId, true, false, new ConsumerCallbackStatsEvent());
    _unifiedClientStats = new UnifiedClientStats(ownerId, regId + UNIFIED_CLIENT_STATS_SUFFIX_NAME, regId, true, false, _client.getClientStaticConfig().getPullerThreadDeadnessThresholdMs(), new UnifiedClientStatsEvent());
}
Also used : UnifiedClientStats(com.linkedin.databus.client.pub.mbean.UnifiedClientStats) ConsumerCallbackStats(com.linkedin.databus.client.pub.mbean.ConsumerCallbackStats) ConsumerCallbackStatsEvent(com.linkedin.databus.client.pub.monitoring.events.ConsumerCallbackStatsEvent) DbusEventsStatisticsCollector(com.linkedin.databus.core.monitoring.mbean.DbusEventsStatisticsCollector) UnifiedClientStatsEvent(com.linkedin.databus.client.pub.monitoring.events.UnifiedClientStatsEvent)

Example 13 with UnifiedClientStats

use of com.linkedin.databus.client.pub.mbean.UnifiedClientStats in project databus by linkedin.

the class RelayPullThread method onRelayFellOff.

private boolean onRelayFellOff(ConnectionState curState, Checkpoint cp, Throwable knownRemoteError) throws InvalidEventException, InterruptedException {
    boolean enqueueMessage = true;
    _log.error("Retries on SCNNotFoundException exhausted !!");
    _retriesOnFallOff.reset();
    //need to bootstrap, suspend or read From Latest SCN
    if (!_sourcesConn.isBootstrapEnabled()) {
        _log.error("No scn found on relay while no bootstrap services provided:");
        _log.error(" bootstrapServices=" + _sourcesConn.getBootstrapServices() + "; bootstrapRegistrations=" + _sourcesConn.getBootstrapRegistrations());
        if (_isReadLatestScnOnErrorEnabled) {
            // Read From Latest SCN on Error
            _log.error("Read Latest SCN Window on SCNNotFoundException is enabled. Will start reading from the lastest SCN Window !!");
            curState.getRelayConnection().enableReadFromLatestScn(true);
            _currentState.setRelayFellOff(false);
            curState.switchToStreamResponseDone();
        } else {
            _log.fatal("Got SCNNotFoundException but Read Latest SCN Window and bootstrap are disabled !!");
            _remoteExceptionHandler.handleException(new BootstrapDatabaseTooOldException(knownRemoteError));
            enqueueMessage = false;
        }
    } else {
        _log.info("Requested scn " + cp.getWindowScn() + " not found on relay; switching to bootstrap service");
        curState.switchToBootstrap(cp);
        UnifiedClientStats unifiedClientStats = _sourcesConn.getUnifiedClientStats();
        if (unifiedClientStats != null) {
            unifiedClientStats.setBootstrappingState(true);
        }
    }
    return enqueueMessage;
}
Also used : BootstrapDatabaseTooOldException(com.linkedin.databus2.core.container.request.BootstrapDatabaseTooOldException) UnifiedClientStats(com.linkedin.databus.client.pub.mbean.UnifiedClientStats)

Example 14 with UnifiedClientStats

use of com.linkedin.databus.client.pub.mbean.UnifiedClientStats in project databus by linkedin.

the class ClientStatsRequestProcessor method processUnifiedTotalStats.

private void processUnifiedTotalStats(StatsCollectors<UnifiedClientStats> statsCollectors, DatabusRequest request) throws IOException {
    if (null == statsCollectors)
        return;
    UnifiedClientStats unifiedTotalStats = statsCollectors.getStatsCollector();
    if (null == unifiedTotalStats)
        return;
    writeJsonObjectToResponse(unifiedTotalStats, request);
    if (request.getRequestType() == HttpMethod.PUT || request.getRequestType() == HttpMethod.POST) {
        enableOrResetStatsMBean(unifiedTotalStats, request);
    }
}
Also used : UnifiedClientStats(com.linkedin.databus.client.pub.mbean.UnifiedClientStats)

Example 15 with UnifiedClientStats

use of com.linkedin.databus.client.pub.mbean.UnifiedClientStats in project databus by linkedin.

the class BootstrapPullThread method doReadBootstrapEvents.

protected void doReadBootstrapEvents(ConnectionState curState) {
    boolean success = true;
    boolean debugEnabled = _log.isDebugEnabled();
    boolean enqueueMessage = true;
    try {
        Checkpoint cp = curState.getCheckpoint();
        DbusEventBuffer eventBuffer = curState.getDataEventsBuffer();
        if (debugEnabled)
            _log.debug("Sending bootstrap events to buffer");
        //eventBuffer.startEvents();
        DbusEventInternalReadable cpEvent = getEventFactory().createCheckpointEvent(cp);
        byte[] cpEventBytes = new byte[cpEvent.size()];
        if (debugEnabled) {
            _log.debug("checkpoint event size: " + cpEventBytes.length);
            _log.debug("checkpoint event:" + cpEvent.toString());
        }
        cpEvent.getRawBytes().get(cpEventBytes);
        ByteArrayInputStream cpIs = new ByteArrayInputStream(cpEventBytes);
        ReadableByteChannel cpRbc = Channels.newChannel(cpIs);
        UnifiedClientStats unifiedClientStats = _sourcesConn.getUnifiedClientStats();
        sendHeartbeat(unifiedClientStats);
        int ecnt = eventBuffer.readEvents(cpRbc);
        success = (ecnt > 0);
        if (!success) {
            _log.error("Unable to write bootstrap phase marker");
        } else {
            ChunkedBodyReadableByteChannel readChannel = curState.getReadChannel();
            String remoteErrorName = RemoteExceptionHandler.getExceptionName(readChannel);
            Throwable remoteError = _remoteExceptionHandler.getException(readChannel);
            if (null != remoteError && remoteError instanceof BootstrapDatabaseTooOldException) {
                _log.error("Bootstrap database is too old!");
                _remoteExceptionHandler.handleException(remoteError);
                curState.switchToStreamResponseError();
            } else if (null != remoteErrorName) {
                //remote processing error
                _log.error("read events error: " + RemoteExceptionHandler.getExceptionMessage(readChannel));
                curState.switchToStreamResponseError();
            } else {
                sendHeartbeat(unifiedClientStats);
                int eventsNum = eventBuffer.readEvents(readChannel, curState.getListeners(), _sourcesConn.getBootstrapEventsStatsCollector());
                if (eventsNum == 0 && _remoteExceptionHandler.getPendingEventSize(readChannel) > eventBuffer.getMaxReadBufferCapacity()) {
                    String err = "ReadBuffer max capacity(" + eventBuffer.getMaxReadBufferCapacity() + ") is less than event size(" + _remoteExceptionHandler.getPendingEventSize(readChannel) + "). Increase databus.client.connectionDefaults.bstEventBuffer.maxEventSize and restart.";
                    _log.fatal(err);
                    enqueueMessage(LifecycleMessage.createSuspendOnErroMessage(new PendingEventTooLargeException(err)));
                    return;
                } else {
                    resetServerRetries();
                    if (debugEnabled)
                        _log.debug("Sending events to buffer");
                    numEventsInCurrentState += eventsNum;
                    _log.info("Bootstrap events read so far: " + numEventsInCurrentState);
                    String status = readChannel.getMetadata("PhaseCompleted");
                    final BootstrapCheckpointHandler ckptHandler = curState.getBstCheckpointHandler();
                    if (status != null) {
                        // set status in checkpoint to indicate that we are done with the current source
                        if (cp.getConsumptionMode() == DbusClientMode.BOOTSTRAP_CATCHUP) {
                            ckptHandler.finalizeCatchupPhase(cp);
                        } else if (cp.getConsumptionMode() == DbusClientMode.BOOTSTRAP_SNAPSHOT) {
                            ckptHandler.finalizeSnapshotPhase(cp);
                        } else {
                            throw new RuntimeException("Invalid bootstrap phase: " + cp.getConsumptionMode());
                        }
                        _log.info("Bootstrap events read :" + numEventsInCurrentState + " during phase:" + cp.getConsumptionMode() + " [" + cp.getBootstrapSnapshotSourceIndex() + "," + cp.getBootstrapCatchupSourceIndex() + "]");
                        numEventsInCurrentState = 0;
                    } else {
                        // question: how is snapshotOffset maintained in ckpt
                        if (eventsNum > 0) {
                            cp.bootstrapCheckPoint();
                        }
                    }
                    curState.switchToStreamResponseDone();
                }
            }
        }
    } catch (InterruptedException ie) {
        _log.error("interupted", ie);
        success = false;
    } catch (InvalidEventException e) {
        _log.error("error reading events from server: " + e.getMessage(), e);
        success = false;
    } catch (RuntimeException e) {
        _log.error("runtime error reading events from server: " + e.getMessage(), e);
        success = false;
    }
    if (toTearConnAfterHandlingResponse()) {
        tearConnectionAndEnqueuePickServer();
        enqueueMessage = false;
    } else if (!success) {
        curState.switchToPickServer();
    }
    if (enqueueMessage)
        enqueueMessage(curState);
}
Also used : ReadableByteChannel(java.nio.channels.ReadableByteChannel) UnifiedClientStats(com.linkedin.databus.client.pub.mbean.UnifiedClientStats) PendingEventTooLargeException(com.linkedin.databus.core.PendingEventTooLargeException) DbusEventInternalReadable(com.linkedin.databus.core.DbusEventInternalReadable) Checkpoint(com.linkedin.databus.core.Checkpoint) BootstrapCheckpointHandler(com.linkedin.databus.core.BootstrapCheckpointHandler) DbusEventBuffer(com.linkedin.databus.core.DbusEventBuffer) BootstrapDatabaseTooOldException(com.linkedin.databus2.core.container.request.BootstrapDatabaseTooOldException) Checkpoint(com.linkedin.databus.core.Checkpoint) ByteArrayInputStream(java.io.ByteArrayInputStream) InvalidEventException(com.linkedin.databus.core.InvalidEventException)

Aggregations

UnifiedClientStats (com.linkedin.databus.client.pub.mbean.UnifiedClientStats)21 Test (org.testng.annotations.Test)10 ConsumerCallbackStats (com.linkedin.databus.client.pub.mbean.ConsumerCallbackStats)9 Checkpoint (com.linkedin.databus.core.Checkpoint)9 DbusEvent (com.linkedin.databus.core.DbusEvent)9 ArrayList (java.util.ArrayList)7 DbusEventBuffer (com.linkedin.databus.core.DbusEventBuffer)6 DbusEventsStatisticsCollector (com.linkedin.databus.core.monitoring.mbean.DbusEventsStatisticsCollector)6 IdNamePair (com.linkedin.databus.core.util.IdNamePair)6 HashMap (java.util.HashMap)6 DatabusV2ConsumerRegistration (com.linkedin.databus.client.consumer.DatabusV2ConsumerRegistration)5 DatabusSubscription (com.linkedin.databus.core.data_model.DatabusSubscription)5 MultiConsumerCallback (com.linkedin.databus.client.consumer.MultiConsumerCallback)3 SelectingDatabusCombinedConsumer (com.linkedin.databus.client.consumer.SelectingDatabusCombinedConsumer)3 StreamConsumerCallbackFactory (com.linkedin.databus.client.consumer.StreamConsumerCallbackFactory)3 DatabusStreamConsumer (com.linkedin.databus.client.pub.DatabusStreamConsumer)3 ConsumerCallbackResult (com.linkedin.databus.client.pub.ConsumerCallbackResult)2 ServerInfo (com.linkedin.databus.client.pub.ServerInfo)2 ConsumerCallbackStatsEvent (com.linkedin.databus.client.pub.monitoring.events.ConsumerCallbackStatsEvent)2 UnifiedClientStatsEvent (com.linkedin.databus.client.pub.monitoring.events.UnifiedClientStatsEvent)2