- All Implemented Interfaces:
RateSummaryListener
Field Summary
Modifier and TypeFieldDescriptionprivate longWall-clock ms when this listener took its Rate registration, or 0 if never.private longSteps written bybackfill(List)since this listener attached.private longCoalesce count of the Rate when this listener attached.private intCurrent consecutive error count.private final I2PAppContextThe context whose stats are graphed.private RrdDbThe RRD database instance.private StringRRD datasource name for the event count.private final booleanTrue if the rate is saved between runs.private longWall-clock ms of the newest step stored, live or backfilled; 0 if none.private longWall-clock ms of the last successful RRD write, or 0 if none has succeeded.private final LogLogger for this class.private StringRRD datasource name for the primary stat value.private final RateRate the samples are recorded into.private GraphRendererRenderer for generating graph images.private intNumber of rows in the RRD archive.private SampleCurrent sample being populated.private longCoalesce delta at which_unrecoverableStepswas last charged.private longSteps proven lost because the Rate no longer retains them.private longWrite count of this listener when it attached; 0 for a fresh instance.private longTotal successful RRD writes.(package private) static final ConsolFunConsolidation function used for RRD archives.(package private) static final DsTypeData source type used for RRD datasources.(package private) static final intOffset (seconds) subtracted from "now" when computing the fetch window end, so a clock skewed slightly ahead of system time does not yield NaNs.private static final intConsecutive write failures at which the report stops being routine.static final intMost rows a persistent RRD archive keeps, three months at one-minute resolution.private static final intMinimum number of rows to keep in the archive.(package private) static final intNumber of periods in one day (1440 = 60 minutes * 24 hours at 1-minute resolution).static final StringWhether RRDs are kept on disk between restarts rather than held in memory.(package private) static final StringNote that .jrb files are NOT compatible with .rrd files.(package private) static final StringPrefix for RRD file names.(package private) static final StringSuffix for RRD file names.private static final ConcurrentMap<String, String> Datasource id to the stat it records, so a log line can name the stat rather than the 20-character munge JRobin requires.private static final intNumber of primary steps per consolidation.private static final longThree months in milliseconds (used to compute max rows for persistent RRDs).private static final doubleX-factor (allowed fraction of unknown data) for RRD consolidation.Constructor Summary
ConstructorsMethod Summary
Modifier and TypeMethodDescriptionvoidadd(double totalValue, long eventCount, double totalEventTime, long period) Add a new data point to the RRD database.intbackfill(List<Rate.CoalescedSample> samples) Replay retained samples whose steps this listener never stored, oldest first.(package private) longchargePermanentLoss(long coalesceDelta) Record that the drift on this listener cannot be backfilled.private voidDrop our registration on the Rate, but only if we still hold it.private voidRelease the RRD handle, leaving the Rate registration alone.private voidcloseQuietly(RrdDb db, String baseName) Drop a half-built handle so a failed open cannot leak a file descriptor.(package private) static StringcreateName(I2PAppContext ctx, String wanted) JRobin can only deal with 20 character data source names, so we need to create a unique, munged version from the user/developer-visible name.booleanCompare with another listener by the underlying rate.(package private) longWhen this listener attached, the origin for a never-written listener's age.(package private) RrdBackendFactoryThe backend factory matching this listener's persistence setting.private static RrdBackendFactorygetBackendFactory(boolean isPersistent) The RRD backend for persistent or in-memory data.(package private) longSteps written bybackfill(List)since this listener attached.(package private) longCoalesces on this Rate since this listener attached.(package private) longThe ledger invariant: coalesces the Rate produced, minus steps this listener stored.(package private) intConsecutive failed writes, reset by any successful live write.(package private) RrdDbgetData()Get the RRD database instance.(package private) StringGet the RRD datasource name for the event count.(package private) longNewest archive step stored, live or backfilled.(package private) longWhen the most recent RRD write succeeded, or 0 if none has.double[]getLastValues(int count) Fetch the lastcountdata points from the RRD database for use by the dual-baseline minigraph renderer (data-rx/data-tx attributes on the canvas).(package private) StringgetName()Get the RRD datasource name for the primary stat.getRate()Retrieve the tracked rate.(package private) intgetRows()Get the number of rows in the RRD archive.(package private) longSteps this listener has stored since it attached.(package private) longSteps proven lost beyond the Rate's retained-sample ring.(package private) longNumber of successful RRD writes since startup.inthashCode()Hash code based on the underlying rate.(package private) booleanWhether this listener has stopped recording.(package private) booleanWhether this listener is still the one its Rate notifies on coalesce.(package private) booleanWhether the open RRD handle can still take a write.private voidnoteWrite(long whenSeconds) Record a step that is now in the RRD, advancing the write ledger.private voidCount a failed write and report it, without giving up the listener.(package private) longnow()Get the current time from the router clock.private booleanopenRdd()Build the RRD handle, sample and renderer for this listener.(package private) static booleanownsRegistration(RateSummaryListener registered, RateSummaryListener self) Doesselfstill own a Rate's summary-listener registration?private StringrateName()Name the rate this listener records, for log lines that must say which graph.(package private) static booleanrecoverable(long lastStoredTimeMs, List<Rate.CoalescedSample> retained) Can a listener still recover its drift, or are the missing steps gone?(package private) static voidregisterName(String id, String statName) Record which stat a datasource id stands for.voidrenderGraph(OutputStream out) Render a graph of the stat data using default settings.voidrenderGraph(OutputStream out, int width, int height, boolean hideLegend, boolean hideGrid, boolean hideTitle, boolean showEvents, int periodCount, int end, boolean showCredit) Single graph.voidrenderGraph(OutputStream out, int width, int height, boolean hideLegend, boolean hideGrid, boolean hideTitle, boolean showEvents, int periodCount, int end, boolean showCredit, List<GraphListener> extras, String titleOverride, boolean showRestarts) Render this stat with any number of extra series overlaid as lines.voidrenderGraph(OutputStream out, int width, int height, boolean hideLegend, boolean hideGrid, boolean hideTitle, boolean showEvents, int periodCount, int end, boolean showCredit, GraphListener lsnr2, String titleOverride, boolean showRestarts) Single or two-data-source graph.voidrenderGraphLines(OutputStream out, int width, int height, boolean hideLegend, boolean hideGrid, boolean hideTitle, boolean showEvents, int periodCount, int end, boolean showCredit, List<GraphListener> extras, String titleOverride, boolean showRestarts) Render this stat with any number of extra series, every series drawn as a line.voidrenderGraphMeta(OutputStream out, int width, int height, boolean hideLegend, boolean hideGrid, boolean hideTitle, boolean showEvents, int periodCount, int end, boolean showCredit, List<GraphListener> extras, String titleOverride, boolean showRestarts, boolean meta) AsrenderGraph(OutputStream, int, int, boolean, boolean, boolean, boolean, int, int, boolean), but emitting the plot geometry and series as JSON.voidrenderGraphMeta(OutputStream out, int width, int height, boolean hideLegend, boolean hideGrid, boolean hideTitle, boolean showEvents, int periodCount, int end, boolean showCredit, GraphListener lsnr2, String titleOverride, boolean showRestarts, boolean meta) AsrenderGraph(OutputStream, int, int, boolean, boolean, boolean, boolean, int, int, boolean), but emitting the plot geometry and series as JSON rather than drawing the graph.voidrenderGraphMetaLines(OutputStream out, int width, int height, boolean hideLegend, boolean hideGrid, boolean hideTitle, boolean showEvents, int periodCount, int end, boolean showCredit, List<GraphListener> extras, String titleOverride, boolean showRestarts, boolean meta) AsrenderGraphLines(OutputStream, int, int, boolean, boolean, boolean, boolean, int, int, boolean, List, String, boolean), but emitting the plot geometry and series as JSON.(package private) booleanreopen()Re-obtain the RRD handle, keeping this listener registered and its ledger intact.(package private) static doublesampleValue(double totalValue, long eventCount) Value to store for a period, given the totals the rate hands its listeners.booleanOpen (or re-open) the RRD database and take the Rate's summary registration.(package private) static StringTranslate a datasource id back to the stat it records.voidStop listening and close the RRD database.(package private) static longtoArchiveSecondMs(long timestampMs) Truncate a wall-clock stamp to the whole second an RRD actually stores.
Field Details
PROP_PERSISTENT
Whether RRDs are kept on disk between restarts rather than held in memory.- See Also:
RRD_DIR
Note that .jrb files are NOT compatible with .rrd files.- See Also:
RRD_PREFIX
RRD_SUFFIX
CF
Consolidation function used for RRD archives.DS
Data source type used for RRD datasources.XFF
private static final double XFFX-factor (allowed fraction of unknown data) for RRD consolidation.- See Also:
STEPS
private static final int STEPSNumber of primary steps per consolidation.- See Also:
_context
The context whose stats are graphed._log
Logger for this class._rate
Rate the samples are recorded into._isPersistent
private final boolean _isPersistentTrue if the rate is saved between runs._name
RRD datasource name for the primary stat value._eventName
RRD datasource name for the event count._db
The RRD database instance._sample
Current sample being populated._renderer
Renderer for generating graph images._rows
private int _rowsNumber of rows in the RRD archive.MAX_CONSECUTIVE_ERRORS
private static final int MAX_CONSECUTIVE_ERRORSConsecutive write failures at which the report stops being routine.No longer a teardown threshold. A momentary I/O error used to detach the listener here, which converted a transient fault into a permanent hole in the graph and then left it unfilled for up to a full sync interval. Retirement is now only ever the heal ladder's explicit REBUILD.
- See Also:
_consecutiveErrors
private volatile int _consecutiveErrorsCurrent consecutive error count._lastUpdateSuccess
private volatile long _lastUpdateSuccessWall-clock ms of the last successful RRD write, or 0 if none has succeeded._attachedMs
private volatile long _attachedMsWall-clock ms when this listener took its Rate registration, or 0 if never.The origin for how long a listener that has never written has had the chance to write. Measured from the router's graphing start instead, a listener created a second ago inherits the age of the whole graphing session and is reported as stalled before it has ever had a period to coalesce, so every rebuild and every on-demand graph would trip the error.
_updateCount
private volatile long _updateCountTotal successful RRD writes._lastStoredTimeMs
private volatile long _lastStoredTimeMsWall-clock ms of the newest step stored, live or backfilled; 0 if none._backfillCount
private volatile long _backfillCountSteps written bybackfill(List)since this listener attached._coalesceBaseline
private volatile long _coalesceBaselineCoalesce count of the Rate when this listener attached.Rate.getCoalesceCount()counts from the Rate's construction, and a stat registered at router startup has been coalescing long before the console attaches to it. Comparing that absolute count against this listener's own write count would report the entire pre-attach history as drift, on every listener, forever. The baseline is what makes the ledger an actual invariant rather than a number that only ever grows._updateBaseline
private volatile long _updateBaselineWrite count of this listener when it attached; 0 for a fresh instance._unrecoverableSteps
private volatile long _unrecoverableStepsSteps proven lost because the Rate no longer retains them.The retained-sample ring holds a fixed handful of coalesces, so a listener that was unreachable for longer than that can never recover the intervening steps. Those are reported once rather than retried forever, which needs a counter as well as a flag: "drift is positive" says a step was lost, but only a count says how many are gone for good.
- See Also:
_unrecoverableCoalesceDelta
private volatile long _unrecoverableCoalesceDeltaCoalesce delta at which_unrecoverableStepswas last charged.Keyed on the coalesce delta rather than on the drift because the coalesce delta only ever grows, so each lost step is charged exactly once even when the drift dips back to zero after a heal and climbs again.
PERIODS
static final int PERIODSNumber of periods in one day (1440 = 60 minutes * 24 hours at 1-minute resolution).- See Also:
GRAPH_END_OFFSET_SECONDS
static final int GRAPH_END_OFFSET_SECONDSOffset (seconds) subtracted from "now" when computing the fetch window end, so a clock skewed slightly ahead of system time does not yield NaNs. Shared withGraphRenderer, which applies the same window for plotting.- See Also:
MIN_ROWS
private static final int MIN_ROWSMinimum number of rows to keep in the archive.- See Also:
MAX_ROWS
public static final int MAX_ROWSMost rows a persistent RRD archive keeps, three months at one-minute resolution.- See Also:
THREE_MONTHS
private static final long THREE_MONTHSThree months in milliseconds (used to compute max rows for persistent RRDs).- See Also:
STAT_NAMES
Datasource id to the stat it records, so a log line can name the stat rather than the 20-character munge JRobin requires.Bounded by the distinct stat-and-period pairs ever graphed - one entry each, replaced in place when a listener is rebuilt - so it holds no per-rebuild state.
Constructor Details
GraphListener
Create a listener for the given rate stat.- Parameters:
r- the rate to track
Method Details
getLastUpdateSuccess
long getLastUpdateSuccess()When the most recent RRD write succeeded, or 0 if none has.- Returns:
- wall-clock ms of the last successful write, or 0 if none
getAttachedMs
long getAttachedMs()When this listener attached, the origin for a never-written listener's age.- Returns:
- wall-clock ms when the listener took its Rate registration, or 0 if never
getUpdateCount
long getUpdateCount()Number of successful RRD writes since startup.- Returns:
- the live-write count, backfilled steps included
getBackfillCount
long getBackfillCount()Steps written bybackfill(List)since this listener attached.- Returns:
- backfilled step count
getLastStoredTimeMs
long getLastStoredTimeMs()Newest archive step stored, live or backfilled.- Returns:
- wall-clock ms of the newest stored step, whole seconds, or 0 if none
getConsecutiveErrors
int getConsecutiveErrors()Consecutive failed writes, reset by any successful live write.- Returns:
- current streak length
getUnrecoverableSteps
long getUnrecoverableSteps()Steps proven lost beyond the Rate's retained-sample ring.- Returns:
- cumulative permanently lost step count
getCoalesceDelta
long getCoalesceDelta()Coalesces on this Rate since this listener attached.- Returns:
- coalesce delta since attach, never negative
- See Also:
getStoredDelta
long getStoredDelta()Steps this listener has stored since it attached.- Returns:
- stored delta since attach, never negative
getCoalesceDrift
long getCoalesceDrift()The ledger invariant: coalesces the Rate produced, minus steps this listener stored.Positive means a coalesce produced a sample this listener never put into the RRD, which is a provably lost step rather than an inference from a stalled write. Zero is the only healthy value; negative is not reachable, because a step is only stored after its coalesce has already been counted.
- Returns:
- coalesces minus stored steps
chargePermanentLoss
long chargePermanentLoss(long coalesceDelta) Record that the drift on this listener cannot be backfilled.Charged against the coalesce delta rather than the drift, which only grows, so every lost step is charged exactly once. A later heal that drops the drift back to zero and a further outage both still get reported.
- Parameters:
coalesceDelta- coalesce delta fromgetCoalesceDelta()- Returns:
- steps newly charged, 0 when they were already charged
add
public void add(double totalValue, long eventCount, double totalEventTime, long period) Add a new data point to the RRD database.- Specified by:
addin interfaceRateSummaryListener- Parameters:
totalValue- the total value for the periodeventCount- the number of events in the periodtotalEventTime- the total event time for the periodperiod- the period duration in milliseconds
sampleValue
static double sampleValue(double totalValue, long eventCount) Value to store for a period, given the totals the rate hands its listeners.Pure so the backfill path and the live path cannot drift apart: a backfilled step recorded with a different rule than the live steps around it would put a spike in the middle of an otherwise consistent trace.
- Parameters:
totalValue- the total value for the periodeventCount- the number of events in the period- Returns:
- the primary datasource value for the step
noteWrite
private void noteWrite(long whenSeconds) Record a step that is now in the RRD, advancing the write ledger.Synchronized because the count is the numerator of the drift invariant the watchdog reads: a lost increment here is reported as a lost step, so the ledger has to be exact rather than a volatile increment that the delivery thread and the watchdog's backfill can race. The monitor covers the field updates only, never the RRD write that precedes them.
- Parameters:
whenSeconds- archive step written, in seconds
noteWriteFailure
Count a failed write and report it, without giving up the listener.Below the threshold this is routine and rate limited; from the threshold on it is an ERROR naming the rate, because a streak this long is not going to clear itself and the operator has to know which graph is affected. Reported every
MAX_CONSECUTIVE_ERRORSfailures rather than on every one, so a rate with a persistently failing RRD cannot turn the log into the stall it used to avoid.Deliberately does not call
stopListening(). Retiring on a transient I/O error left a hole in the graph that nothing refilled for up to a full sync interval, and the detach was indistinguishable from a real fault in the logs. Recording now stops on its own - the ledger drift grows - and the heal ladder reopens or rebuilds the handle when it can.- Parameters:
t- the write failure, counted toward the consecutive-error limit
rateName
Name the rate this listener records, for log lines that must say which graph.- Returns:
- the rate's stat name and period
backfill
Replay retained samples whose steps this listener never stored, oldest first.Recovery for a listener that missed a few steps while nothing was obviously wrong: the values are still in the Rate's retained-sample ring, and an archive step is empty forever once nothing writes it, so writing them late beats losing them.
RrdDb.storerejects any timestamp not strictly newer than the last one stored, so a sample that lands on or beforegetLastStoredTimeMs()is skipped rather than attempted: the write path has already covered the recent steps and the ring can overlap them.- Parameters:
samples- retained samples, oldest first; may be null or empty- Returns:
- number of steps written
toArchiveSecondMs
static long toArchiveSecondMs(long timestampMs) Truncate a wall-clock stamp to the whole second an RRD actually stores.Pure because the whole skip rule is this truncation applied against
getLastStoredTimeMs(): comparing raw milliseconds would let a sample 999ms into a step the listener already stored look newer than it is, and the write would then be rejected by the archive as non-monotonic.- Parameters:
timestampMs- wall-clock ms, not monotonic time- Returns:
- the same instant truncated down to a whole second, in ms
recoverable
Can a listener still recover its drift, or are the missing steps gone?The Rate retains a fixed, small ring of coalesces. Once every retained sample is already stored, the steps the listener missed are older than anything the Rate remembers, and no amount of retrying will produce them. Telling those two cases apart is what keeps the watchdog from re-attempting a hopeless backfill every ten seconds and from calling a permanent gap a transient one.
Pure, so the boundary is unit tested without a Rate, an RRD or a clock.
- Parameters:
lastStoredTimeMs- newest stored step fromgetLastStoredTimeMs()retained- the Rate's retained samples, oldest first; may be null- Returns:
- true if at least one retained sample is newer than the last stored step
isWritable
boolean isWritable()Whether the open RRD handle can still take a write.Distinct from
isDetached(): a detached listener has no handle at all, whereas this can be false for a listener that still holds a handle which something else has already closed. That is the cheapest fault to heal, since the listener, its registration and its RRD file all survive and only the handle has to be re-obtained.- Returns:
- true if the handle is open and can accept a write
isDetached
boolean isDetached()Whether this listener has stopped recording.A detached listener keeps its entry in
GraphGenerator's rate-to-listener map, so the generator uses this to notice that it needs re-creating.- Returns:
- true if the RRD database is closed and no longer receiving samples
isRegistered
boolean isRegistered()Whether this listener is still the one its Rate notifies on coalesce.Distinct from
isDetached(): a Rate holds exactly one summary listener, so registering a replacement silently orphans this instance while its RRD stays open. That instance is attached - so it renders fine and the console shows a plausible graph - but it can never be called again, and nothing about that state is visible without asking the Rate.- Returns:
- true if
Rate.getSummaryListener()is this instance
ownsRegistration
Doesselfstill own a Rate's summary-listener registration?Reference identity, deliberately not
equals(Object): two listeners for the same Rate areequalsbut only one of them is ever called, so only reference equality answers "is this instance the live one".- Parameters:
registered- current registration, as returned byRate.getSummaryListener()self- the listener asking- Returns:
- true only if
selfis the registered instance
createName
JRobin can only deal with 20 character data source names, so we need to create a unique, munged version from the user/developer-visible name.- Parameters:
ctx- the context whose SHA munges the namewanted- the stat name, or the stat name and period, to munge- Returns:
- a 20-character datasource id, distinct for each name
registerName
Record which stat a datasource id stands for.Called when a listener opens its RRD, which is the only place the id is minted.
- Parameters:
id- the 20-character datasource id fromcreateName(I2PAppContext, String)statName- the stat name and period the id was minted from
statName
Translate a datasource id back to the stat it records.The ids are a hash of the stat name, so they cannot be inverted - a log line quoting one names nothing an operator can look up. Pass every id a human reads through here.
- Parameters:
id- the datasource id- Returns:
- the registered stat name, or
iditself when nothing registered it (an unknown id is still worth logging)
getRate
startListening
public boolean startListening()Open (or re-open) the RRD database and take the Rate's summary registration.The ledger baseline is taken before the file is touched, not after: a coalesce that happens while this method is opening the database is a step the listener was never registered for, so it is lost and the drift has to say so. Baselineing afterwards would quietly forgive it.
- Returns:
- true if the database was opened and the summary listener registered
reopen
boolean reopen()Re-obtain the RRD handle, keeping this listener registered and its ledger intact.The cheapest heal there is, for the case where the handle is closed but the listener itself, its Rate registration and its recorded history all survive. Rebuilding instead would work too, at the cost of a new listener, a new renderer and a window in which the rate has no listener at all - so the ladder tries this first.
Neither the ledger baseline nor the write count is reset: the drift is the fault being healed, and a heal that quietly rebased it would hide the very loss it is repairing.
- Returns:
- true if a fresh, writable handle is in place
openRdd
private boolean openRdd()Build the RRD handle, sample and renderer for this listener.Split out of
startListening()soreopen()can obtain a new handle without touching the Rate. Does no I/O on any rate's monitor: it is called from the sync task and from the health watchdog, never from a Rate-synchronized callback.The three fields are published together, at the end and only on success, so a failure part-way through leaves the listener detached rather than attached with a null sample that the delivery thread would dereference.
- Returns:
- true if
_dbis set and writable
closeQuietly
stopListening
public void stopListening()Stop listening and close the RRD database.The registration on the Rate is dropped only if this instance still holds it, so tearing down a superseded listener cannot silence its live replacement.
closeHandle
private void closeHandle()Release the RRD handle, leaving the Rate registration alone.Shared by
stopListening()andreopen(): the only difference between tearing a listener down and healing it is whether the Rate keeps pointing at this instance, and that has to be the caller's decision.The handle is cleared before it is closed, so a delivery thread that is midway through a write sees a null database and skips rather than writing to a handle that is on its way out.
clearRateRegistration
private void clearRateRegistration()Drop our registration on the Rate, but only if we still hold it.Ratekeeps a single summary listener, so an instance tearing down after a newer one has registered would otherwise stop the newer one being called. The newer one keeps its open RRD and still reports itself attached, so recording dies with no write error, no detach, and no exception anywhere - every health check keeps saying healthy.Rate.clearSummaryListener(RateSummaryListener)does the ownership test and the clear as one atomic operation, so a registration that appears between the two cannot be dropped. A clear that finds the registration already gone is the ordinary post-detach case and is not reported; only a registration held by a different live listener is, because that means two teardowns raced.renderGraph
public void renderGraph(OutputStream out, int width, int height, boolean hideLegend, boolean hideGrid, boolean hideTitle, boolean showEvents, int periodCount, int end, boolean showCredit) throws IOException Single graph.- Parameters:
out- the output stream to write the graph towidth- image width in pixelsheight- image height in pixelshideLegend- if true, omit the legendhideGrid- if true, omit the grid lineshideTitle- if true, omit the titleshowEvents- if true, plot the event count rather than the statperiodCount- number of time periods to display, or -1 for defaultend- number of periods before nowshowCredit- if true, keep the signature line- Throws:
IOException- if this listener has no open RRD, or the graph cannot be produced
renderGraph
public void renderGraph(OutputStream out, int width, int height, boolean hideLegend, boolean hideGrid, boolean hideTitle, boolean showEvents, int periodCount, int end, boolean showCredit, GraphListener lsnr2, String titleOverride, boolean showRestarts) throws IOException Single or two-data-source graph.- Parameters:
out- the output stream to write the graph towidth- image width in pixelsheight- image height in pixelshideLegend- if true, omit the legendhideGrid- if true, omit the grid lineshideTitle- if true, omit the titleshowEvents- if true, plot the event count rather than the statperiodCount- number of time periods to display, or -1 for defaultend- number of periods before nowshowCredit- if true, keep the signature linelsnr2- 2nd data source to plot on same graph, or null. Not recommended for events.titleOverride- If non-null, overrides the titleshowRestarts- if true, draw the vertical restart lines and "Router restarted" label- Throws:
IOException- if this listener has no open RRD, or the graph cannot be produced
renderGraphMeta
public void renderGraphMeta(OutputStream out, int width, int height, boolean hideLegend, boolean hideGrid, boolean hideTitle, boolean showEvents, int periodCount, int end, boolean showCredit, GraphListener lsnr2, String titleOverride, boolean showRestarts, boolean meta) throws IOException AsrenderGraph(OutputStream, int, int, boolean, boolean, boolean, boolean, int, int, boolean), but emitting the plot geometry and series as JSON rather than drawing the graph.A graph is served as an
<img>, so its SVG is an isolated document and a client cannot read the numbers out of it. This is the separate request that carries them, for a cursor readout.- Parameters:
out- the output stream to write the graph or the metadata towidth- image width in pixelsheight- image height in pixelshideLegend- if true, omit the legendhideGrid- if true, omit the grid lineshideTitle- if true, omit the titleshowEvents- if true, plot the event count rather than the statperiodCount- number of time periods to display, or -1 for defaultend- number of periods before nowshowCredit- if true, keep the signature linelsnr2- 2nd data source to plot on same graph, or null. Not recommended for events.titleOverride- If non-null, overrides the titleshowRestarts- if true, draw the vertical restart lines and "Router restarted" labelmeta- true to write the metadata instead of the image- Throws:
IOException- if this listener has no open RRD, or the graph cannot be produced
renderGraph
public void renderGraph(OutputStream out, int width, int height, boolean hideLegend, boolean hideGrid, boolean hideTitle, boolean showEvents, int periodCount, int end, boolean showCredit, List<GraphListener> extras, String titleOverride, boolean showRestarts) throws IOException Render this stat with any number of extra series overlaid as lines.Every series shares one axis, so the caller must supply stats that measure the same thing; see
GraphGroupsfor the sanctioned groupings.- Parameters:
out- the output stream to write the graph towidth- image width in pixelsheight- image height in pixelshideLegend- if true, omit the legendhideGrid- if true, omit the grid lineshideTitle- if true, omit the titleshowEvents- if true, plot the event count rather than the statperiodCount- number of time periods to display, or -1 for defaultend- number of periods before nowshowCredit- if true, keep the signature lineextras- extra series in legend order, or null for nonetitleOverride- If non-null, overrides the titleshowRestarts- if true, draw the vertical restart lines and "Router restarted" label- Throws:
IOException- if this listener has no open RRD, or the graph cannot be produced
renderGraphMeta
public void renderGraphMeta(OutputStream out, int width, int height, boolean hideLegend, boolean hideGrid, boolean hideTitle, boolean showEvents, int periodCount, int end, boolean showCredit, List<GraphListener> extras, String titleOverride, boolean showRestarts, boolean meta) throws IOException AsrenderGraph(OutputStream, int, int, boolean, boolean, boolean, boolean, int, int, boolean), but emitting the plot geometry and series as JSON.- Parameters:
out- the output stream to write the graph or the metadata towidth- image width in pixelsheight- image height in pixelshideLegend- if true, omit the legendhideGrid- if true, omit the grid lineshideTitle- if true, omit the titleshowEvents- if true, plot the event count rather than the statperiodCount- number of time periods to display, or -1 for defaultend- number of periods before nowshowCredit- if true, keep the signature lineextras- extra series in legend order, or null for nonetitleOverride- If non-null, overrides the titleshowRestarts- if true, draw the vertical restart lines and "Router restarted" labelmeta- true to write the metadata instead of the image- Throws:
IOException- if this listener has no open RRD, or the graph cannot be produced
renderGraphLines
public void renderGraphLines(OutputStream out, int width, int height, boolean hideLegend, boolean hideGrid, boolean hideTitle, boolean showEvents, int periodCount, int end, boolean showCredit, List<GraphListener> extras, String titleOverride, boolean showRestarts) throws IOException Render this stat with any number of extra series, every series drawn as a line.Identical to
renderGraph(OutputStream, int, int, boolean, boolean, boolean, boolean, int, int, boolean, List, String, boolean)except that the primary is a line rather than a filled area, so no member of the group is hidden behind another.- Parameters:
out- the output stream to write the graph towidth- image width in pixelsheight- image height in pixelshideLegend- if true, omit the legendhideGrid- if true, omit the grid lineshideTitle- if true, omit the titleshowEvents- if true, plot the event count rather than the statperiodCount- number of time periods to display, or -1 for defaultend- number of periods before nowshowCredit- if true, keep the signature lineextras- extra series in legend order, or null for nonetitleOverride- If non-null, overrides the titleshowRestarts- if true, draw the vertical restart lines and "Router restarted" label- Throws:
IOException- if this listener has no open RRD, or the graph cannot be produced
renderGraphMetaLines
public void renderGraphMetaLines(OutputStream out, int width, int height, boolean hideLegend, boolean hideGrid, boolean hideTitle, boolean showEvents, int periodCount, int end, boolean showCredit, List<GraphListener> extras, String titleOverride, boolean showRestarts, boolean meta) throws IOException AsrenderGraphLines(OutputStream, int, int, boolean, boolean, boolean, boolean, int, int, boolean, List, String, boolean), but emitting the plot geometry and series as JSON.- Parameters:
out- the output stream to write the graph or the metadata towidth- image width in pixelsheight- image height in pixelshideLegend- if true, omit the legendhideGrid- if true, omit the grid lineshideTitle- if true, omit the titleshowEvents- if true, plot the event count rather than the statperiodCount- number of time periods to display, or -1 for defaultend- number of periods before nowshowCredit- if true, keep the signature lineextras- extra series in legend order, or null for nonetitleOverride- If non-null, overrides the titleshowRestarts- if true, draw the vertical restart lines and "Router restarted" labelmeta- true to write the metadata instead of the image- Throws:
IOException- if this listener has no open RRD, or the graph cannot be produced
renderGraph
Render a graph of the stat data using default settings.- Parameters:
out- the output stream to write the graph to- Throws:
IOException- if rendering fails
getName
getEventName
String getEventName()Get the RRD datasource name for the event count.- Returns:
- the event datasource name
getData
now
long now()Get the current time from the router clock.- Returns:
- the current time in milliseconds
getBackendFactory
RrdBackendFactory getBackendFactory()The backend factory matching this listener's persistence setting.- Returns:
- the NIO file factory when persistent, otherwise the in-memory one
getBackendFactory
The RRD backend for persistent or in-memory data.- Parameters:
isPersistent- whether the graph data is kept in files on disk- Returns:
- the default NIO file factory when persistent, the in-memory factory otherwise
getRows
int getRows()Get the number of rows in the RRD archive.- Returns:
- the row count
getLastValues
public double[] getLastValues(int count) Fetch the lastcountdata points from the RRD database for use by the dual-baseline minigraph renderer (data-rx/data-tx attributes on the canvas). Points are right-aligned. The returned array is NaN-padded on the left when fewer points are available.- Specified by:
getLastValuesin interfaceRateSummaryListener- Parameters:
count- number of most recent data points to retrieve- Returns:
- array of average values (units depend on the stat), length = count
equals
hashCode