package com.ldbc.driver.runtime.metrics; import com.ldbc.driver.Operation; import com.ldbc.driver.control.LoggingServiceFactory; import com.ldbc.driver.csv.simple.SimpleCsvFileWriter; import com.ldbc.driver.runtime.ConcurrentErrorReporter; import com.ldbc.driver.runtime.metrics.sbe.MetricsEvent; import com.ldbc.driver.temporal.TimeSource; import com.lmax.disruptor.EventHandler; import uk.co.real_logic.sbe.codec.java.DirectBuffer; import java.util.Map; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicStampedReference; import static java.lang.String.format; class DisruptorSbeMetricsEventHandler implements EventHandler<DirectBuffer> { private final AtomicStampedReference<WorkloadStatusSnapshot> statusSnapshotReference = new AtomicStampedReference<>( null, 0 ); private final AtomicStampedReference<WorkloadResultsSnapshot> resultsSnapshotReference = new AtomicStampedReference<>( null, 0 ); private final MetricsManager metricsManager; private final ConcurrentErrorReporter errorReporter; private final SimpleCsvFileWriter csvResultsLogWriter; private final TimeUnit unit; private long processedEventCount = 0L; private final String[] operationNames; private final MetricsEvent metricsEvent; DisruptorSbeMetricsEventHandler( ConcurrentErrorReporter errorReporter, SimpleCsvFileWriter csvResultsLogWriter, TimeUnit unit, TimeSource timeSource, long maxRuntimeDurationAsNano, Map<Integer,Class<? extends Operation>> operationTypeToClassMapping, LoggingServiceFactory loggingServiceFactory ) throws MetricsCollectionException { this.errorReporter = errorReporter; this.csvResultsLogWriter = csvResultsLogWriter; this.unit = unit; this.metricsManager = new MetricsManager( timeSource, unit, maxRuntimeDurationAsNano, operationTypeToClassMapping, loggingServiceFactory ); operationNames = MetricsManager.toOperationNameArray( operationTypeToClassMapping ); this.metricsEvent = new MetricsEvent(); } AtomicStampedReference<WorkloadStatusSnapshot> statusSnapshot() { return statusSnapshotReference; } AtomicStampedReference<WorkloadResultsSnapshot> resultsSnapshot() { return resultsSnapshotReference; } long processedEventCount() { return processedEventCount; } @Override public void onEvent( DirectBuffer event, long l, boolean b ) throws Exception { metricsEvent.wrapForDecode( event, DisruptorSbeMetricsEvent.MESSAGE_HEADER_SIZE, DisruptorSbeMetricsEvent.ACTING_BLOCK_LENGTH, DisruptorSbeMetricsEvent.ACTING_VERSION ); switch ( metricsEvent.eventType() ) { case DisruptorSbeMetricsEvent.SUBMIT_OPERATION_RESULT: { int operationType = metricsEvent.operationType(); long scheduledStartTimeAsMilli = metricsEvent.scheduledStartTimeAsMilli(); long actualStartTimeAsMilli = metricsEvent.actualStartTimeAsMilli(); long runDurationAsNano = metricsEvent.runDurationAsNano(); int resultCode = metricsEvent.resultCode(); long originalStartTime = metricsEvent.originalStartTime(); if ( null != csvResultsLogWriter ) { csvResultsLogWriter.writeRow( operationNames[operationType], Long.toString( scheduledStartTimeAsMilli ), Long.toString( actualStartTimeAsMilli ), Long.toString( unit.convert( runDurationAsNano, TimeUnit.NANOSECONDS ) ), Integer.toString( resultCode ), Long.toString( originalStartTime ) ); } metricsManager.measure( actualStartTimeAsMilli, runDurationAsNano, operationType ); processedEventCount++; break; } case DisruptorSbeMetricsEvent.GET_WORKLOAD_STATUS: { WorkloadStatusSnapshot newStatus = metricsManager.status(); WorkloadStatusSnapshot oldStatus; int oldStamp; do { oldStatus = statusSnapshotReference.getReference(); oldStamp = statusSnapshotReference.getStamp(); } while ( !statusSnapshotReference.compareAndSet( oldStatus, newStatus, oldStamp, oldStamp + 1 ) ); break; } case DisruptorSbeMetricsEvent.GET_WORKLOAD_RESULTS: { WorkloadResultsSnapshot newResults = metricsManager.snapshot(); WorkloadResultsSnapshot oldResults; int oldStamp; do { oldResults = resultsSnapshotReference.getReference(); oldStamp = resultsSnapshotReference.getStamp(); } while ( !resultsSnapshotReference.compareAndSet( oldResults, newResults, oldStamp, oldStamp + 1 ) ); break; } default: { errorReporter.reportError( this, format( "Encountered unexpected event: %s", event.toString() ) ); break; } } } }