= cockpit.js: Series DataSeries data consists of values along a continuous (usually time) axis.We can place these in grids which expose a distinct subset of thesevalues. These are the underlying mechanism for displaying metrics datain graphs.[[cockpit-grid]]== cockpit.grid()....grid = cockpit.grid(interval, [beg, end])....Creates a grid object to contain series data.The `+interval+` is the granularity of the grid. Usually this is anumber of milliseconds, when used with time series data. The `+beg+` and`+end+` are the bounds of the grid. If omitted they will be set to zerofor an initially empty grid.If `+beg+` and/or `+end+` are negative (including negative zero) thenthey are interpreted in number of intervals relative to the currenttime. Thus cockpit.grid(1000, -300, -0) will create a grid for the mostrecent 5 minutes.[[cockpit-grid-add]]== grid.add()....row = grid.add(series, path)row = grid.add(callback, [early])row = grid.add()....Adds a row to the grid. The returned `+row+` is a Javascript array thatwill contain series data. The arguments control how the row is populatedfrom the series data. The `+row+` is a sparse array. Its `+row.length+`will not match the expected size of the grid, unless and until the rowhas been completely filled in. The first index of the `+row+` willcontain the data from the series data at thelink:#cockpit-grid-beg[`+grid.beg+`] offset.When no arguments are passed, an empty row is added, and it is notpopulated with data.When called with a `+series+` and `+path+` argument then the row will bepopulated directly with series data. The `+series+` can either be alink:#cockpit-series[series object] or an object that has an`+obj.series+` property. The link:#cockpit-series-interval[seriesinterval] must match the interval of this grid. If `+path+` is missingor empty, then the series data is placed into the row directly.Otherwise `+path+` indicates which part of the series data to place inthe row. When `+path+` is an array, it is used as a set of propertynames or array indexes to follow into nested series data. When `+path+`is a dotted string, it is split and used the same way to locate thecorrect value in nested series data. The exact format of the series datadepends on its producer, and relevant paths will be documented there.If a `+callback+` function is specified, then it will be invoked toprovide series data for the row. The function is invoked as`+callback(row, index, count)+`, where the `+row+` is the row to fillin, the `+index+` is the index to start filling in and `+count+` is thenumber of items to fill in. The `+this+` variable will be set to thegrid while invoking the `+callback+`. The callback is called after otherdata rows for a given series have been filled in. Callbacks are calledin the order added, unless the `+early+` argument is set to `+true+`, inwhich case the callback is called earlier than callbacks without the`+early+` argument set.To remove the row use the link:#cockpit-grid-remove[`+grid.remove()+`method.]The row will start being populated with data when the `+series+`produces data. To make this happen right away, use thelink:#cockpit-grid-sync[`+grid.sync()+`] method.[[cockpit-grid-remove]]== grid.remove()....grid.remove(row)....Remove a previously added `+row+` from the grid. The row will no longerbe updated with series data.[[cockpit-grid-sync]]== grid.sync()....grid.sync()....Load or reload data from the series into the rows. This does not clearthe rows before populating them. Some data may be populated immediately,others may have to wait until data can be loaded. Internally thisfunction calls link:#cockpit-series-load[`+series.load()+`] for eachseries.All rows with callbacks will be invoked to regenerate all the data. Thelink:#cockpit-grid-onnotify[`+grid.onnotify+`] event will be triggered.It is not necessary to call this function after a call of thelink:#cockpit-grid-move[`+grid.move()+`] method.[[cockpit-grid-move]]== grid.move()....grid.move(beg[, end])....Move the grid to new `+beg+` and `+end+` range. Data will be discardedfrom the rows and link:#cockpit-grid-sync[`+grid.sync()+`] will becalled to load or reload series data for the new range of offsets.If `+end+` is not specified it will be set to `+beg+`. If `+beg+` and/or`+end+` are negative (including negative zero) then they will be set tothe number of intervals prior to the current time taken as an interval.If `+beg+` and/or `+end+` are negative (including negative zero) thenthey are interpreted in number of intervals relative to the currenttime. Thus cockpit.grid(1000, -300, -0) will create a grid for the mostrecent 5 minutes.[[cockpit-grid-walk]]== grid.walk()....grid.walk()....Move the grid forward everylink:#cockpit-grid-interval[`+grid.interval+`] milliseconds. To stopmoving forward, call link:#cockpit-grid-move[`+grid.move()+`].[[cockpit-grid-notify]]== grid.notify()....grid.notify(index, count)....This function is called to have rows with callbacks recalculate theirdata. It is not normally necessary to call this function, as it will beinvoked automatically when new series data is available or has beenloaded. This function triggers thelink:#cockpit-grid-onnotify[`+grid.onnotify+`] event.[[cockpit-grid-onnotify]]== grid.onnotify....grid.addEventListener("notify", function(index, count) { ... });....An event that is triggered when some part of the series data in gridchanges. The `+index+` is the row index where things changed, and the`+count+` is the length of the data that changed.[[cockpit-grid-close]]== grid.close()....grid.close()....Close the grid, and stop updating the rows.[[cockpit-grid-interval]]== grid.intervalThe granularity of the grid. For time series data this is an interval inmilliseconds. In order to use a given link:#cockpit-grid[grid] andlink:#cockpit-series[series] together, their interval properties mustmatch.[[cockpit-grid-beg]]== grid.begThe beginning offset of the series data in the grid. Do not set thisproperty directly. Use the link:#cockpit-grid-move[grid.move()] methodinstead.[[cockpit-grid-end]]== grid.endThe ending offset of the series data in the grid. Do not set thisproperty directly. Use the link:#cockpit-grid-move[grid.move()] methodinstead.[[cockpit-series]]== cockpit.series()....series = cockpit.series(interval, [cache, fetch])....Create a new sink of series data. This is usually done by producers ofseries data, and it is rare to invoke this function directly.The `+interval+` is the granularity of the series data. For time seriesdata this is an interval in milliseconds. If a `+cache+` string isspecified, series data will be cached across frames for series with thesame `+cache+` cache identifier to load and/or reload.If a `+fetch+` callback is specified, then it will be invoked when gridsrequest certain ranges of data. The `+fetch+` callback is invoked with`+function fetch(beg, end) { ... }+` range offsets. Thelink:#cockpit-series-input[series.input()] should be called with dataretrieved, either immediately or at a later time. The callback may becalled multiple times for the same ranges of data. It is up to thecallback to determine when or whether it should retrieve the data morethan once.A producer of series data, usually calls this function and createsitself a `+obj.series+` property containing this series object.[[cockpit-series-input]]== series.input()....series.input(beg, items[, mapping])....Send series data into the series sink. Any grids that have added rowsbased on this series, will have data filled in. The `+beg+` is thebeginning offset of `+items+`. The `+items+` are an array one or moreseries data items.Producers may wish to provide additional properties that can be used inlookup paths that rows can pull from. This is done in the `+mapping+`argument. If specified it is a tree of objects. Each sub object shouldhave a property with the name `+""+` empty string, which will be used asthe property name or index in place of the one used in the lookup path.[[cockpit-series-load]]== series.load()....series.load(beg, end)....Load data from the series into any grids that have rows based on thisseries data. Any cached data will be filled in immediately. Any data notcached, will be requested from the producer, if possible, and may arriveat a later time.The `+beg+` and `+end+` denote the range of data to load.[[cockpit-series-interval]]== series.intervalThe granularity of the series. For time series data this is an intervalin milliseconds. In order to use a given link:#cockpit-grid[grid] andlink:#cockpit-series[series] together, their interval properties mustmatch.[[cockpit-series-limit]]== series.limitThe maximum number of items to cache for loading and/or reloading. Youcan change this value to a different number. Having a number close tozero will break certain usage of grids, such aslink:#cockpit-grid-walk[`+grid.walk()+`].