/** * Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.engine.calcnode.stats; import org.threeten.bp.Instant; import com.opengamma.util.ArgumentChecker; /** * Records statistics about nodes. * <p> * This is run centrally to aggregate statistics. * The statistics recorded include the number of successful and unsuccessful jobs. * Old data is decayed to be less relevant. */ public class CalculationNodeStatistics { /** * The node id. */ private final String _nodeId; /** * The number of successful jobs. */ private long _successfulJobs; /** * The number of unsuccessful jobs. */ private long _unsuccessfulJobs; /** * The number of job items. */ private long _jobItems; /** * The execution time in nanoseconds. */ private long _executionNanos; /** * The non-execution time in nanoseconds. */ private long _nonExecutionNanos; /** * The last instant that a job was sent. */ private Instant _lastJobInstant; /** * Creates an instance for a specific node. * * @param nodeId the node id, not null */ public CalculationNodeStatistics(final String nodeId) { ArgumentChecker.notNull(nodeId, "nodeId"); _nodeId = nodeId; } private CalculationNodeStatistics(final CalculationNodeStatistics other) { _nodeId = other.getNodeId(); // the caller already holds the lock on the other object _successfulJobs = other._successfulJobs; _unsuccessfulJobs = other._unsuccessfulJobs; _executionNanos = other._executionNanos; _nonExecutionNanos = other._nonExecutionNanos; _lastJobInstant = other._lastJobInstant; } // ------------------------------------------------------------------------- /** * Gets the node id. * * @return the node id, not null */ public String getNodeId() { return _nodeId; } /** * Gets the number of job items. * * @return the number of job items */ public synchronized long getJobItems() { return _jobItems; } /** * Gets the number of successful jobs. * * @return the number of successful jobs */ public synchronized long getSuccessfulJobs() { return _successfulJobs; } /** * Gets the number of unsuccessful jobs. * * @return the number of unsuccessful jobs */ public synchronized long getUnsuccessfulJobs() { return _unsuccessfulJobs; } /** * Gets the execution time in nanoseconds. * * @return the execution time */ public synchronized long getExecutionTime() { return _executionNanos; } /** * Gets the non-execution time in nanoseconds. Non-execution time is the time from job dispatch to job completion * less the time the node reported as spent working on the job. It is a measure of overhead. A high non-execution * to execution ratio could indicate the jobs being dispatched are too small. High non-execution time could also * mean a large number of failed jobs; the entire duration of which is considered overhead as the job must be * repeated. * * @return the non-execution time */ public synchronized long getNonExecutionTime() { return _nonExecutionNanos; } /** * Gets the last instant a job ran. * * @return the last job instant, null if no job has run */ public synchronized Instant getLastJobTime() { return _lastJobInstant; } // ------------------------------------------------------------------------- /** * Gets the average execution time in seconds. * <p> * This method is for debugging only. A snapshot should be taken and then * analysis on the values and their relationships to each other be used. * * @return the average execution time */ public synchronized double getAverageExecutionTime() { final long jobs = getSuccessfulJobs(); if (jobs > 0) { return (double) getExecutionTime() / (double) jobs / 1e9; } else { return 0; } } /** * Gets the average non-execution time in seconds. * <p> * This method is for debugging only. A snapshot should be taken and then * analysis on the values and their relationships to each other be used. * * @return the average non-execution time */ public synchronized double getAverageNonExecutionTime() { final long jobs = getSuccessfulJobs(); if (jobs > 0) { return (double) getNonExecutionTime() / (double) jobs / 1e9; } else { return 0; } } /** * Gets the average number of job items. * <p> * This method is for debugging only. A snapshot should be taken and then * analysis on the values and their relationships to each other be used. * * @return the average number of job items */ public synchronized double getAverageJobItems() { final long jobs = getSuccessfulJobs(); if (jobs > 0) { return (double) getJobItems() / (double) jobs; } else { return 0; } } // ------------------------------------------------------------------------- /** * Records a successful job. * * @param jobItems the number of job items * @param executionNanos the execution time in nanoseconds * @param durationNanos the duration in nanoseconds */ public synchronized void recordSuccessfulJob(final int jobItems, final long executionNanos, final long durationNanos) { _successfulJobs++; _jobItems += jobItems; _executionNanos += executionNanos; _nonExecutionNanos += (durationNanos - executionNanos); _lastJobInstant = Instant.now(); } /** * Records an unsuccessful job. * * @param durationNanos the duration in nanoseconds */ public synchronized void recordUnsuccessfulJob(final long durationNanos) { _unsuccessfulJobs++; _nonExecutionNanos += durationNanos; _lastJobInstant = Instant.now(); } // ------------------------------------------------------------------------- /** * Resets the counters to zero. */ public synchronized void reset() { _successfulJobs = 0; _unsuccessfulJobs = 0; _jobItems = 0; _executionNanos = 0; _nonExecutionNanos = 0; } /** * Decays the values by a specific factor. * * @param factor the factor to decay by */ public synchronized void decay(final double factor) { _successfulJobs -= ((double) _successfulJobs * factor); _unsuccessfulJobs -= ((double) _unsuccessfulJobs * factor); _jobItems -= ((double) _jobItems * factor); _executionNanos -= ((double) _executionNanos * factor); _nonExecutionNanos -= ((double) _nonExecutionNanos * factor); } /** * Creates a snapshot of the current values. * * @return a snapshot, not null */ public synchronized CalculationNodeStatistics snapshot() { return new CalculationNodeStatistics(this); } }