UNPKG

pondjs

Version:

A timeseries library build on top of immutable.js

937 lines (843 loc) 31.4 kB
/** * Copyright (c) 2015-2017, The Regents of the University of California, * through Lawrence Berkeley National Laboratory (subject to receipt * of any required approvals from the U.S. Dept. of Energy). * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. */ /* eslint-disable */ import moment from "moment"; import Collection from "../collection"; import TimeEvent from "../timeevent"; import TimeRange from "../timerange"; import TimeRangeEvent from "../timerangeevent"; import TimeSeries from "../timeseries"; import { sum, max, avg } from "../base/functions"; const TIMESERIES_TEST_DATA = { name: "traffic", columns: ["time", "value", "status"], points: [ [1400425947000, 52, "ok"], [1400425948000, 18, "ok"], [1400425949000, 26, "fail"], [1400425950000, 93, "offline"] ] }; const INDEXED_DATA = { index: "1d-625", name: "traffic", columns: ["time", "value", "status"], points: [ [1400425947000, 52, "ok"], [1400425948000, 18, "ok"], [1400425949000, 26, "fail"], [1400425950000, 93, "offline"] ] }; const AVAILABILITY_DATA = { name: "availability", columns: ["index", "uptime"], points: [ ["2014-07", "100%"], ["2014-08", "88%"], ["2014-09", "95%"], ["2014-10", "99%"], ["2014-11", "91%"], ["2014-12", "99%"], ["2015-01", "100%"], ["2015-02", "92%"], ["2015-03", "99%"], ["2015-04", "87%"], ["2015-05", "92%"], ["2015-06", "100%"] ] }; const AVAILABILITY_DATA_2 = { name: "availability", columns: ["index", "uptime", "notes", "outages"], points: [ ["2014-07", 100, "", 2], ["2014-08", 88, "", 17], ["2014-09", 95, "", 6], ["2014-10", 99, "", 3], ["2014-11", 91, "", 14], ["2014-12", 99, "", 3], ["2015-01", 100, "", 0], ["2015-02", 92, "", 12], ["2015-03", 99, "Minor outage March 2", 4], ["2015-04", 87, "Planned downtime in April", 82], ["2015-05", 92, "Router failure June 12", 26], ["2015-06", 100, "", 0] ] }; const INTERFACE_TEST_DATA = { name: "star-cr5:to_anl_ip-a_v4", description: "star-cr5->anl(as683):100ge:site-ex:show:intercloud", device: "star-cr5", id: 169, interface: "to_anl_ip-a_v4", is_ipv6: false, is_oscars: false, oscars_id: null, resource_uri: "", site: "anl", site_device: "noni", site_interface: "et-1/0/0", stats_type: "Standard", title: null, columns: ["time", "in", "out"], points: [ [1400425947000, 52, 34], [1400425948000, 18, 13], [1400425949000, 26, 67], [1400425950000, 93, 91] ] }; const TRAFFIC_BNL_TO_NEWY = { name: "BNL to NEWY", columns: ["time", "in"], points: [ [1441051950000, 2998846524.2666664], [1441051980000, 2682032885.3333335], [1441052010000, 2753537586.9333334] ] }; const TRAFFIC_NEWY_TO_BNL = { name: "NEWY to BNL", columns: ["time", "out"], points: [ [1441051950000, 22034579982.4], [1441051980000, 24783871443.2], [1441052010000, 26907368572.800003] ] }; const fmt = "YYYY-MM-DD HH:mm"; const BISECT_TEST_DATA = { name: "test", columns: ["time", "value"], points: [ [moment("2012-01-11 01:00", fmt).valueOf(), 22], [moment("2012-01-11 02:00", fmt).valueOf(), 33], [moment("2012-01-11 03:00", fmt).valueOf(), 44], [moment("2012-01-11 04:00", fmt).valueOf(), 55], [moment("2012-01-11 05:00", fmt).valueOf(), 66], [moment("2012-01-11 06:00", fmt).valueOf(), 77], [moment("2012-01-11 07:00", fmt).valueOf(), 88] ] }; const TRAFFIC_DATA_IN = { name: "star-cr5:to_anl_ip-a_v4", columns: ["time", "in"], points: [[1400425947000, 52], [1400425948000, 18], [1400425949000, 26], [1400425950000, 93]] }; const TRAFFIC_DATA_OUT = { name: "star-cr5:to_anl_ip-a_v4", columns: ["time", "out"], points: [[1400425947000, 34], [1400425948000, 13], [1400425949000, 67], [1400425950000, 91]] }; const PARTIAL_TRAFFIC_PART_A = { name: "star-cr5:to_anl_ip-a_v4", columns: ["time", "value"], points: [[1400425947000, 34], [1400425948000, 13], [1400425949000, 67], [1400425950000, 91]] }; const PARTIAL_TRAFFIC_PART_B = { name: "star-cr5:to_anl_ip-a_v4", columns: ["time", "value"], points: [[1400425951000, 65], [1400425952000, 86], [1400425953000, 27], [1400425954000, 72]] }; const OUTAGE_EVENT_LIST = [ { startTime: "2015-03-04T09:00:00Z", endTime: "2015-03-04T14:00:00Z", title: "ANL Scheduled Maintenance", description: "ANL will be switching border routers...", completed: true, external_ticket: "", esnet_ticket: "ESNET-20150302-002", organization: "ANL", type: "Planned" }, { startTime: "2015-04-22T03:30:00Z", endTime: "2015-04-22T13:00:00Z", description: "At 13:33 pacific circuit 06519 went down.", title: "STAR-CR5 < 100 ge 06519 > ANL - Outage", completed: true, external_ticket: "", esnet_ticket: "ESNET-20150421-013", organization: "Internet2 / Level 3", type: "Unplanned" }, { startTime: "2015-04-22T03:35:00Z", endTime: "2015-04-22T16:50:00Z", title: "STAR-CR5 < 100 ge 06519 > ANL - Outage", description: "The listed circuit was unavailable due to bent pins.", completed: true, external_ticket: "3576:144", esnet_ticket: "ESNET-20150421-013", organization: "Internet2 / Level 3", type: "Unplanned" } ]; const sumPart1 = { name: "part1", columns: ["time", "in", "out"], points: [ [1400425951000, 1, 6], [1400425952000, 2, 7], [1400425953000, 3, 8], [1400425954000, 4, 9] ] }; const sumPart2 = { name: "part2", columns: ["time", "in", "out"], points: [ [1400425951000, 9, 1], [1400425952000, 7, 2], [1400425953000, 5, 3], [1400425954000, 3, 4] ] }; const sept2014Data = { utc: false, name: "traffic", columns: ["time", "value"], points: [ [1409529600000, 80], [1409533200000, 88], [1409536800000, 52], [1409540400000, 80], [1409544000000, 26], [1409547600000, 37], [1409551200000, 6], [1409554800000, 32], [1409558400000, 69], [1409562000000, 21], [1409565600000, 6], [1409569200000, 54], [1409572800000, 88], [1409576400000, 41], [1409580000000, 35], [1409583600000, 43], [1409587200000, 84], [1409590800000, 32], [1409594400000, 41], [1409598000000, 57], [1409601600000, 27], [1409605200000, 50], [1409608800000, 13], [1409612400000, 63], [1409616000000, 58], [1409619600000, 80], [1409623200000, 59], [1409626800000, 96], [1409630400000, 2], [1409634000000, 20], [1409637600000, 64], [1409641200000, 7], [1409644800000, 50], [1409648400000, 88], [1409652000000, 34], [1409655600000, 31], [1409659200000, 16], [1409662800000, 38], [1409666400000, 94], [1409670000000, 78], [1409673600000, 86], [1409677200000, 13], [1409680800000, 34], [1409684400000, 29], [1409688000000, 48], [1409691600000, 80], [1409695200000, 30], [1409698800000, 15], [1409702400000, 62], [1409706000000, 66], [1409709600000, 44], [1409713200000, 94], [1409716800000, 78], [1409720400000, 29], [1409724000000, 21], [1409727600000, 4], [1409731200000, 83], [1409734800000, 15], [1409738400000, 89], [1409742000000, 53], [1409745600000, 70], [1409749200000, 41], [1409752800000, 47], [1409756400000, 30], [1409760000000, 68], [1409763600000, 89], [1409767200000, 29], [1409770800000, 17], [1409774400000, 38], [1409778000000, 67], [1409781600000, 75], [1409785200000, 89], [1409788800000, 47], [1409792400000, 82], [1409796000000, 33], [1409799600000, 67], [1409803200000, 93], [1409806800000, 86], [1409810400000, 97], [1409814000000, 19], [1409817600000, 19], [1409821200000, 31], [1409824800000, 56], [1409828400000, 19], [1409832000000, 43], [1409835600000, 29], [1409839200000, 72], [1409842800000, 27], [1409846400000, 21], [1409850000000, 88], [1409853600000, 18], [1409857200000, 30], [1409860800000, 46], [1409864400000, 34], [1409868000000, 31], [1409871600000, 20], [1409875200000, 45], [1409878800000, 17], [1409882400000, 24], [1409886000000, 84], [1409889600000, 6], [1409893200000, 91], [1409896800000, 82], [1409900400000, 71], [1409904000000, 97], [1409907600000, 43], [1409911200000, 38], [1409914800000, 1], [1409918400000, 71], [1409922000000, 50], [1409925600000, 19], [1409929200000, 19], [1409932800000, 86], [1409936400000, 65], [1409940000000, 93], [1409943600000, 35] ] }; const TIMERANGE_EVENT_LIST = OUTAGE_EVENT_LIST.map(event => { const { startTime, endTime, ...other } = event; //eslint-disable-line const b = new Date(startTime); const e = new Date(endTime); return new TimeRangeEvent(new TimeRange(b, e), other); }); // // TESTS // it("can create an series with our wire format", () => { const series = new TimeSeries(TIMESERIES_TEST_DATA); expect(series).toBeDefined(); }); it("can create an series with a list of Events", () => { const events = []; events.push(new TimeEvent(new Date(2015, 7, 1), { value: 27 })); events.push(new TimeEvent(new Date(2015, 8, 1), { value: 14 })); const series = new TimeSeries({ name: "events", events }); expect(series.size()).toBe(2); }); it("can create an series with no events", () => { const events = []; const series = new TimeSeries({ name: "events", events }); expect(series.size()).toBe(0); }); // // Basic Query API // it("can return the size of the series", () => { const series = new TimeSeries(TIMESERIES_TEST_DATA); expect(series.size()).toBe(4); }); it("can return an item in the series as an event", () => { const series = new TimeSeries(TIMESERIES_TEST_DATA); const event = series.at(1); expect(event instanceof TimeEvent).toBeTruthy(); }); it("can return an item in the series with the correct data", () => { const series = new TimeSeries(TIMESERIES_TEST_DATA); const event = series.at(1); expect(JSON.stringify(event.data())).toBe(`{"value":18,"status":"ok"}`); expect(event.timestamp().getTime()).toBe(1400425948000); }); it("can serialize to a string", () => { const series = new TimeSeries(TIMESERIES_TEST_DATA); const expectedString = `{"name":"traffic","utc":true,"columns":["time","value","status"],"points":[[1400425947000,52,"ok"],[1400425948000,18,"ok"],[1400425949000,26,"fail"],[1400425950000,93,"offline"]]}`; expect(series.toString()).toBe(expectedString); }); it("can return the time range of the series", () => { const series = new TimeSeries(TIMESERIES_TEST_DATA); const expectedString = "[Sun, 18 May 2014 15:12:27 GMT, Sun, 18 May 2014 15:12:30 GMT]"; expect(series.timerange().toUTCString()).toBe(expectedString); }); // // Meta data // it("can create a series with meta data and get that data back", () => { const series = new TimeSeries(INTERFACE_TEST_DATA); const expected = `{"site_interface":"et-1/0/0","utc":true,"site":"anl","name":"star-cr5:to_anl_ip-a_v4","site_device":"noni","device":"star-cr5","oscars_id":null,"title":null,"is_oscars":false,"interface":"to_anl_ip-a_v4","stats_type":"Standard","id":169,"resource_uri":"","is_ipv6":false,"description":"star-cr5->anl(as683):100ge:site-ex:show:intercloud","columns":["time","in","out"],"points":[[1400425947000,52,34],[1400425948000,18,13],[1400425949000,26,67],[1400425950000,93,91]]}`; expect(series.toString()).toBe(expected); expect(series.meta("interface")).toBe("to_anl_ip-a_v4"); }); it("can create a series and set a new name", () => { const series = new TimeSeries(INTERFACE_TEST_DATA); expect(series.name()).toBe("star-cr5:to_anl_ip-a_v4"); const newSeries = series.setName("bob"); expect(newSeries.name()).toBe("bob"); }); it("can create a series with meta data and get that data back", () => { const series = new TimeSeries(INTERFACE_TEST_DATA); expect(series.meta("site_interface")).toBe("et-1/0/0"); const newSeries = series.setMeta("site_interface", "bob"); expect(newSeries.meta("site_interface")).toBe("bob"); expect(newSeries.at(0).get("in")).toBe(52); expect(newSeries.meta("site")).toBe("anl"); }); // // Deep event data // it("can create a series with a nested object", () => { const series = new TimeSeries({ name: "Map Traffic", columns: ["time", "NASA_north", "NASA_south"], points: [ [1400425951000, { in: 100, out: 200 }, { in: 145, out: 135 }], [1400425952000, { in: 200, out: 400 }, { in: 146, out: 142 }], [1400425953000, { in: 300, out: 600 }, { in: 147, out: 158 }], [1400425954000, { in: 400, out: 800 }, { in: 155, out: 175 }] ] }); expect(series.at(0).get("NASA_north").in).toBe(100); expect(series.at(0).get("NASA_north").out).toBe(200); }); it("can create a series with nested events", () => { const events = []; events.push( new TimeEvent(new Date(2015, 6, 1), { NASA_north: { in: 100, out: 200 }, NASA_south: { in: 145, out: 135 } }) ); events.push( new TimeEvent(new Date(2015, 7, 1), { NASA_north: { in: 200, out: 400 }, NASA_south: { in: 146, out: 142 } }) ); events.push( new TimeEvent(new Date(2015, 8, 1), { NASA_north: { in: 300, out: 600 }, NASA_south: { in: 147, out: 158 } }) ); events.push( new TimeEvent(new Date(2015, 9, 1), { NASA_north: { in: 400, out: 800 }, NASA_south: { in: 155, out: 175 } }) ); const series = new TimeSeries({ name: "Map traffic", events }); expect(series.at(0).get("NASA_north").in).toBe(100); expect(series.at(3).get("NASA_south").out).toBe(175); expect(series.size()).toBe(4); }); // // Comparing TimeSeries with each other // it("can compare a series and a reference to a series as being equal", () => { const series = new TimeSeries(TIMESERIES_TEST_DATA); const refSeries = series; expect(series).toBe(refSeries); }); it("can use the equals() comparator to compare a series and a copy of the series as true", () => { const series = new TimeSeries(TIMESERIES_TEST_DATA); const copyOfSeries = new TimeSeries(series); expect(TimeSeries.equal(series, copyOfSeries)).toBeTruthy; }); it("can use the equals() comparator to compare a series and a value equivalent series as false", () => { const series = new TimeSeries(TIMESERIES_TEST_DATA); const otherSeries = new TimeSeries(TIMESERIES_TEST_DATA); expect(TimeSeries.equal(series, otherSeries)).toBeFalsy; }); it("can use the is() comparator to compare a series and a value equivalent series as true", () => { const series = new TimeSeries(TIMESERIES_TEST_DATA); const otherSeries = new TimeSeries(TIMESERIES_TEST_DATA); expect(TimeSeries.is(series, otherSeries)).toBeTruthy; }); // // Bisect // it("can find the bisect starting from 0", () => { const series = new TimeSeries(BISECT_TEST_DATA); expect(series.bisect(moment("2012-01-11 00:30", fmt).toDate())).toBe(0); expect(series.bisect(moment("2012-01-11 03:00", fmt).toDate())).toBe(2); expect(series.bisect(moment("2012-01-11 03:30", fmt).toDate())).toBe(2); expect(series.bisect(moment("2012-01-11 08:00", fmt).toDate())).toBe(6); }); it("can find the bisect starting from an begin index", () => { const series = new TimeSeries(BISECT_TEST_DATA); expect(series.bisect(moment("2012-01-11 03:00", fmt).toDate(), 2)).toBe(2); expect(series.bisect(moment("2012-01-11 03:30", fmt).toDate(), 3)).toBe(2); expect(series.bisect(moment("2012-01-11 03:30", fmt).toDate(), 4)).toBe(3); const first = series.bisect(moment("2012-01-11 03:30", fmt).toDate()); const second = series.bisect(moment("2012-01-11 04:30", fmt).toDate(), first); expect(series.at(first).get()).toBe(44); expect(series.at(second).get()).toBe(55); }); // // TimeRangeEvents // it("can make a timeseries with the right timerange", () => { const series = new TimeSeries({ name: "outages", events: TIMERANGE_EVENT_LIST }); expect(series.range().toString()).toBe("[1425459600000,1429721400000]"); }); it("can make a timeseries that can be serialized to a string", () => { const series = new TimeSeries({ name: "outages", events: TIMERANGE_EVENT_LIST }); const expected = `{"name":"outages","utc":true,"columns":["timerange","title","description","completed","external_ticket","esnet_ticket","organization","type"],"points":[[[1425459600000,1425477600000],"ANL Scheduled Maintenance","ANL will be switching border routers...",true,"","ESNET-20150302-002","ANL","Planned"],[[1429673400000,1429707600000],"STAR-CR5 < 100 ge 06519 > ANL - Outage","At 13:33 pacific circuit 06519 went down.",true,"","ESNET-20150421-013","Internet2 / Level 3","Unplanned"],[[1429673700000,1429721400000],"STAR-CR5 < 100 ge 06519 > ANL - Outage","The listed circuit was unavailable due to bent pins.",true,"3576:144","ESNET-20150421-013","Internet2 / Level 3","Unplanned"]]}`; expect(series.toString()).toBe(expected); }); it("can make a timeseries that can be serialized to JSON and then used to construct a TimeSeries again", () => { const series = new TimeSeries({ name: "outages", events: TIMERANGE_EVENT_LIST }); const newSeries = new TimeSeries(series.toJSON()); expect(series.toString()).toBe(newSeries.toString()); }); // // IndexedEvents // it("can serialize to a string", () => { const series = new TimeSeries(INDEXED_DATA); const expectedString = `{"index":"1d-625","name":"traffic","utc":true,"columns":["time","value","status"],"points":[[1400425947000,52,"ok"],[1400425948000,18,"ok"],[1400425949000,26,"fail"],[1400425950000,93,"offline"]]}`; expect(series.toString()).toBe(expectedString); }); it("can return the time range of the series", () => { const series = new TimeSeries(INDEXED_DATA); const expectedString = "[Sat, 18 Sep 1971 00:00:00 GMT, Sun, 19 Sep 1971 00:00:00 GMT]"; expect(series.indexAsRange().toUTCString()).toBe(expectedString); }); it("can create an series with indexed data (in UTC time)", () => { const series = new TimeSeries(AVAILABILITY_DATA); const event = series.at(2); expect(event.timerangeAsUTCString()).toBe( "[Mon, 01 Sep 2014 00:00:00 GMT, Tue, 30 Sep 2014 23:59:59 GMT]" ); expect(series.range().begin().getTime()).toBe(1404172800000); expect(series.range().end().getTime()).toBe(1435708799999); }); // // Slicing a TimeSeries // it("can create a slice of a series", () => { const series = new TimeSeries(AVAILABILITY_DATA); const expectedLastTwo = `{"name":"availability","utc":true,"columns":["index","uptime"],"points":[["2015-05","92%"],["2015-06","100%"]]}`; const lastTwo = series.slice(-2); expect(lastTwo.toString()).toBe(expectedLastTwo); const expectedFirstThree = `{"name":"availability","utc":true,"columns":["index","uptime"],"points":[["2014-07","100%"],["2014-08","88%"],["2014-09","95%"]]}`; const firstThree = series.slice(0, 3); expect(firstThree.toString()).toBe(expectedFirstThree); const expectedAll = `{"name":"availability","utc":true,"columns":["index","uptime"],"points":[["2014-07","100%"],["2014-08","88%"],["2014-09","95%"],["2014-10","99%"],["2014-11","91%"],["2014-12","99%"],["2015-01","100%"],["2015-02","92%"],["2015-03","99%"],["2015-04","87%"],["2015-05","92%"],["2015-06","100%"]]}`; const sliceAll = series.slice(); expect(sliceAll.toString()).toBe(expectedAll); }); // // Cropping a TimeSeries // it("can create crop a series", () => { const series = new TimeSeries({ name: 'exact timestamps', columns: ['time', 'value'], points: [[1504014065240,1],[1504014065243,2],[1504014065244,3],[1504014065245,4],[1504014065249,5]] }); const ts1 = series.crop(new TimeRange([1504014065243,1504014065245])); expect(ts1.size()).toBe(3); const ts2 = series.crop(new TimeRange([1504014065242,1504014065245])); expect(ts2.size()).toBe(3); const ts3 = series.crop(new TimeRange([1504014065243,1504014065247])); expect(ts3.size()).toBe(3); const ts4 = series.crop(new TimeRange([1504014065242,1504014065247])); expect(ts4.size()).toBe(3); }); // // Merging two TimeSeries together // it("can merge two timeseries columns together using merge", () => { const inTraffic = new TimeSeries(TRAFFIC_DATA_IN); const outTraffic = new TimeSeries(TRAFFIC_DATA_OUT); const trafficSeries = TimeSeries.timeSeriesListMerge({ name: "traffic", seriesList: [inTraffic, outTraffic] }); expect(trafficSeries.at(2).get("in")).toBe(26); expect(trafficSeries.at(2).get("out")).toBe(67); }); it("can append two timeseries together using merge", () => { const tile1 = new TimeSeries(PARTIAL_TRAFFIC_PART_A); const tile2 = new TimeSeries(PARTIAL_TRAFFIC_PART_B); const trafficSeries = TimeSeries.timeSeriesListMerge({ name: "traffic", source: "router", seriesList: [tile1, tile2] }); expect(trafficSeries.size()).toBe(8); expect(trafficSeries.at(0).get()).toBe(34); expect(trafficSeries.at(1).get()).toBe(13); expect(trafficSeries.at(2).get()).toBe(67); expect(trafficSeries.at(3).get()).toBe(91); expect(trafficSeries.at(4).get()).toBe(65); expect(trafficSeries.at(5).get()).toBe(86); expect(trafficSeries.at(6).get()).toBe(27); expect(trafficSeries.at(7).get()).toBe(72); expect(trafficSeries.name()).toBe("traffic"); expect(trafficSeries.meta("source")).toBe("router"); }); it("can merge two series and preserve the correct time format", () => { const inTraffic = new TimeSeries(TRAFFIC_BNL_TO_NEWY); const outTraffic = new TimeSeries(TRAFFIC_NEWY_TO_BNL); const trafficSeries = TimeSeries.timeSeriesListMerge({ name: "traffic", seriesList: [inTraffic, outTraffic] }); expect(trafficSeries.at(0).timestampAsUTCString()).toBe("Mon, 31 Aug 2015 20:12:30 GMT"); expect(trafficSeries.at(1).timestampAsUTCString()).toBe("Mon, 31 Aug 2015 20:13:00 GMT"); expect(trafficSeries.at(2).timestampAsUTCString()).toBe("Mon, 31 Aug 2015 20:13:30 GMT"); }); it("can merge two irregular time series together", () => { const A = { name: "a", columns: ["time", "valueA"], points: [ [1400425947000, 34], [1400425948000, 13], [1400425949000, 67], [1400425950000, 91] ] }; const B = { name: "b", columns: ["time", "valueB"], points: [ [1400425951000, 65], [1400425952000, 86], [1400425953000, 27], [1400425954000, 72] ] }; const tile1 = new TimeSeries(A); const tile2 = new TimeSeries(B); const series = TimeSeries.timeSeriesListMerge({ name: "traffic", seriesList: [tile1, tile2] }); const expected = `{"name":"traffic","utc":true,"columns":["time","valueA","valueB"],"points":[[1400425947000,34,null],[1400425948000,13,null],[1400425949000,67,null],[1400425950000,91,null],[1400425951000,null,65],[1400425952000,null,86],[1400425953000,null,27],[1400425954000,null,72]]}`; expect(series.toString()).toBe(expected); }); // // Summing two TimeSeries together // it("can merge two timeseries into a new timeseries that is the sum", () => { const part1 = new TimeSeries(sumPart1); const part2 = new TimeSeries(sumPart2); const result = TimeSeries.timeSeriesListReduce({ name: "sum", seriesList: [part1, part2], reducer: sum(), fieldSpec: ["in", "out"] }); //10, 9, 8, 7 expect(result.at(0).get("in")).toBe(10); expect(result.at(1).get("in")).toBe(9); expect(result.at(2).get("in")).toBe(8); expect(result.at(3).get("in")).toBe(7); //7, 9, 11, 13 expect(result.at(0).get("out")).toBe(7); expect(result.at(1).get("out")).toBe(9); expect(result.at(2).get("out")).toBe(11); expect(result.at(3).get("out")).toBe(13); }); // // Avergage two timeseries together // it("can merge two timeseries into a new timeseries that is the sum", () => { const part1 = new TimeSeries({ name: "part1", columns: ["time", "in", "out"], points: [ [1400425951000, 1, 6], [1400425952000, 2, 7], [1400425953000, 3, 8], [1400425954000, 4, 9] ] }); const part2 = new TimeSeries({ name: "part2", columns: ["time", "in", "out"], points: [ [1400425951000, 9, 1], [1400425952000, 7, 2], [1400425953000, 5, 3], [1400425954000, 3, 4] ] }); const avgSeries = TimeSeries.timeSeriesListReduce({ name: "avg", seriesList: [part1, part2], fieldSpec: ["in", "out"], reducer: avg() }); expect(avgSeries.at(0).get("in")).toBe(5); expect(avgSeries.at(1).get("in")).toBe(4.5); expect(avgSeries.at(2).get("in")).toBe(4); expect(avgSeries.at(3).get("in")).toBe(3.5); expect(avgSeries.at(0).get("out")).toBe(3.5); expect(avgSeries.at(1).get("out")).toBe(4.5); expect(avgSeries.at(2).get("out")).toBe(5.5); expect(avgSeries.at(3).get("out")).toBe(6.5); const avgSeries2 = TimeSeries.timeSeriesListReduce({ name: "avg", seriesList: [part1, part2], reducer: avg(), fieldSpec: ["in", "out"] }); expect(avgSeries2.at(0).get("in")).toBe(5); expect(avgSeries2.at(1).get("in")).toBe(4.5); expect(avgSeries2.at(2).get("in")).toBe(4); expect(avgSeries2.at(3).get("in")).toBe(3.5); }); // // Collapse down columns in a TimeSeries // it("can collapse a timeseries into a new timeseries that is the sum of two columns", () => { const ts = new TimeSeries(sumPart1); const sums = ts.collapse({ name: "sum", fieldSpecList: ["in", "out"], reducer: sum(), append: false }); expect(sums.at(0).get("sum")).toBe(7); expect(sums.at(1).get("sum")).toBe(9); expect(sums.at(2).get("sum")).toBe(11); expect(sums.at(3).get("sum")).toBe(13); }); it("can collapse a timeseries into a new timeseries that is the max of two columns", () => { const timeseries = new TimeSeries(sumPart2); const c = timeseries.collapse({ name: "max_in_out", fieldSpecList: ["in", "out"], reducer: max(), append: true }); expect(c.at(0).get("max_in_out")).toBe(9); expect(c.at(1).get("max_in_out")).toBe(7); expect(c.at(2).get("max_in_out")).toBe(5); expect(c.at(3).get("max_in_out")).toBe(4); }); it("can collapse a timeseries into a new timeseries that is the sum of two columns, then find the max", () => { const ts = new TimeSeries(sumPart1); const sums = ts.collapse({ name: "value", fieldSpecList: ["in", "out"], reducer: sum(), append: false }); expect(sums.max()).toBe(13); }); // // Select specific columns in a TimeSeries // it("can select a single column from a TimeSeries", () => { const timeseries = new TimeSeries(INTERFACE_TEST_DATA); expect(timeseries.columns()).toEqual(["in", "out"]); const ts = timeseries.select({ fieldSpec: "in" }); expect(ts.columns()).toEqual(["in"]); expect(ts.name()).toBe("star-cr5:to_anl_ip-a_v4"); }); it("can select multiple columns from a TimeSeries", () => { const timeseries = new TimeSeries(AVAILABILITY_DATA_2); expect(timeseries.columns()).toEqual(["uptime", "notes", "outages"]); const ts = timeseries.select({ fieldSpec: ["uptime", "notes"] }); expect(ts.columns()).toEqual(["uptime", "notes"]); expect(ts.name()).toBe("availability"); }); // // Remapping Events in a TimeSeries // it("can use re-mapping to reverse the values in a TimeSeries", () => { const timeseries = new TimeSeries(INTERFACE_TEST_DATA); expect(timeseries.columns()).toEqual(["in", "out"]); const ts = timeseries.map(e => e.setData({ in: e.get("out"), out: e.get("in") })); expect(ts.at(0).get("in")).toBe(34); expect(ts.at(0).get("out")).toBe(52); expect(ts.size()).toBe(timeseries.size()); }); // // Rollups // it("can generate 1 day fixed window averages over a TimeSeries", () => { const timeseries = new TimeSeries(sept2014Data); const dailyAvg = timeseries.fixedWindowRollup({ windowSize: "1d", aggregation: { value: { value: avg() } } }); expect(dailyAvg.size()).toBe(5); expect(dailyAvg.at(0).value()).toBe(46.875); expect(dailyAvg.at(2).value()).toBe(54.083333333333336); expect(dailyAvg.at(4).value()).toBe(51.85); }); it("can make Collections for each day in the TimeSeries", () => { const timeseries = new TimeSeries(sept2014Data); const collections = timeseries.collectByFixedWindow({ windowSize: "1d" }); expect(collections["1d-16314"].size()).toBe(24); expect(collections["1d-16318"].size()).toBe(20); }); it("can correctly use atTime()", () => { const t = new Date(1476803711641); let collection = new Collection(); collection = collection.addEvent(new TimeEvent(t, 2)); // Test bisect to get element 0 const ts = new TimeSeries({ collection }); const bisect = ts.bisect(t); expect(bisect).toEqual(0); expect(ts.at(bisect).value()).toEqual(2); // Test atTime to get element 0 expect(ts.atTime(t).value()).toEqual(2); }); class StatusEvent extends TimeEvent { constructor(arg1, arg2) { super(arg1, arg2); } static dataSchema() { return { type: "record", fields: [{ name: "value", type: "long" }, { name: "status", type: "string" }] }; } } class StatusSeries extends TimeSeries { constructor(arg) { super(arg); } metaSchema() { return [{ name: "name", type: "string" }]; } static event(key) { return StatusEvent; } }