/** * Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.util.monitor; import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; import org.slf4j.Logger; /** * Collects statistics on the number of bytes written and emits info to a log. * This is for testing/development and not intended for use in production code. */ public class ReportingInputStream extends FilterInputStream { /** * The frequency of logging. */ private static final long TIME_TO_REPORT = 1000000000; // 1s /** * The logger. */ private final Logger _logger; /** * The name of the stream. */ private final String _streamName; /** * The next time (system nano time) that reporting will occur. */ private long _nextReportTime; /** * The call stack. */ private int _callStack; /** * The read time (system nano time). */ private long _readTime; /** * The bytes read. */ private long _readBytes; /** * The number of read operations. */ private long _readOperations; /** * Creates an instance. * * @param logger the device to report to, not null * @param streamName the name to include in the log output, should not be null * @param underlying the underlying stream, not null */ public ReportingInputStream(final Logger logger, final String streamName, final InputStream underlying) { super(underlying); _logger = logger; _streamName = streamName; _nextReportTime = System.nanoTime() + TIME_TO_REPORT; } //------------------------------------------------------------------------- @Override public int read() throws IOException { beginRead(); try { final int value = in.read(); _readBytes++; return value; } finally { endRead(); } } @Override public int read(final byte[] b, final int off, final int len) throws IOException { beginRead(); try { final int bytes = in.read(b, off, len); if (bytes > 0) { _readBytes += bytes; } return bytes; } finally { endRead(); } } //------------------------------------------------------------------------- /** * Called when beginning to read. */ private void beginRead() { if (_callStack++ == 0) { _readOperations++; _readTime -= System.nanoTime(); } } /** * Called when ending the read. */ private void endRead() { if (--_callStack == 0) { long time = System.nanoTime(); _readTime += time; if (time - _nextReportTime >= 0) { _nextReportTime = time + TIME_TO_REPORT; _logger.info("Stream {} read {}Kb in {}ms from {} operations ({}M)}", new Object[] {_streamName, (double) _readBytes / 1024d, (double) _readTime / 1000000d, _readOperations, (double) _readBytes * 8192d / (double) _readTime }); // scale down influence of older data _readOperations >>= 1; _readBytes >>= 1; _readTime >>= 1; } } } }