コード例 #1
0
ファイル: test_influx.py プロジェクト: svencowart/loudml
    def setUp(self):

        self.db = "test-{}".format(int(datetime.datetime.now().timestamp()))
        self.source = InfluxDataSource({
            'name': 'test',
            'addr': ADDR,
            'database': self.db,
        })
        self.source.drop()
        self.source.init()
        self.storage = TempStorage()

        generator = SinEventGenerator(base=3, sigma=0.05)

        self.to_date = datetime.datetime.now().timestamp()
        self.from_date = self.to_date - 3600 * 24 * 7

        for ts in generator.generate_ts(
                self.from_date,
                self.to_date,
                step_ms=60000,
        ):
            self.source.insert_times_data(
                measurement='measure1',
                ts=ts,
                data={'foo': random.lognormvariate(10, 1)},
            )
        self.source.commit()
コード例 #2
0
ファイル: test_influx.py プロジェクト: svencowart/loudml
 def test_validation(self):
     with self.assertRaises(errors.Invalid):
         InfluxDataSource({
             'addr': 'localhost',
         })
     with self.assertRaises(errors.Invalid):
         InfluxDataSource({
             'database': 'foo',
         })
コード例 #3
0
    def setUp(self):
        self.app = app.test_client()
        self.app.testing = True

        self.bucket_interval = 20 * 60

        t0 = int(datetime.datetime.now().timestamp())
        t0 -= t0 % self.bucket_interval
        self.t0 = t0

        self.db = 'test-{}'.format(t0)
        logging.info("creating database %s", self.db)
        self.source = InfluxDataSource({
            'name': 'nose',
            'addr': ADDR,
            'database': self.db,
        })
        self.source.drop()
        self.source.init()

        self.generator = SinEventGenerator(base=3, amplitude=3, sigma=0.01)

        to_date = datetime.datetime.now().timestamp()

        # Be sure that date range is aligned
        self.to_date = math.floor(
            to_date / self.bucket_interval) * self.bucket_interval  # noqa E501
        self.from_date = self.to_date - 3600 * 24 * 7 * 3

        for ts in self.generator.generate_ts(self.from_date,
                                             self.to_date,
                                             step_ms=600000):  # noqa E501
            self.source.insert_times_data(measurement='bar',
                                          ts=ts,
                                          data={
                                              'foo':
                                              random.normalvariate(10, 1),
                                          })

        self.source.commit()

        self.dirpath = tempfile.mkdtemp()
        configyml = os.path.join(self.dirpath, 'config.yml')
        cfg = open(configyml, 'w')
        cfg.write(CONFIG.format(ADDR, self.db, self.dirpath))
        cfg.close()

        g_app_init(configyml)
コード例 #4
0
ファイル: test_influx.py プロジェクト: wade1990/loudml
    def test_build_times_queries(self):
        where = "time >= 1515404366123400000 and time < 1515423565456000000"
        queries = list(
            self.source._build_times_queries(
                self.model,
                from_date=1515404366.1234,
                to_date="2018-01-08T14:59:25.456Z",
            ))
        self.assertEqual(
            queries,
            [
                "select MEAN(\"foo\") as \"avg_foo\" from \"measure1\" "
                "where {} group by time(3000ms);".format(where),
                "select COUNT(\"bar\") as \"count_bar\" from \"measure2\" "
                "where {} group by time(3000ms);".format(where),
                "select MEAN(\"baz\") as \"avg_baz\" from \"measure1\" "
                "where {} and \"mytag\"='myvalue' group by time(3000ms);".
                format(where),
            ],
        )

        source = InfluxDataSource({
            'name': 'test',
            'addr': ADDR,
            'database': self.db,
            'retention_policy': 'custom',
        })

        queries = list(
            source._build_times_queries(
                self.model,
                from_date=1515404366.1234,
                to_date="2018-01-08T14:59:25.456Z",
            ))
        from_prefix = '"{}"."custom".'.format(self.db)
        self.assertEqual(
            queries,
            [
                "select MEAN(\"foo\") as \"avg_foo\" from {}\"measure1\" "
                "where {} group by time(3000ms);".format(from_prefix, where),
                "select COUNT(\"bar\") as \"count_bar\" from {}\"measure2\" "
                "where {} group by time(3000ms);".format(from_prefix, where),
                "select MEAN(\"baz\") as \"avg_baz\" from {}\"measure1\" "
                "where {} and \"mytag\"='myvalue' group by time(3000ms);".
                format(from_prefix, where),
            ],
        )
コード例 #5
0
ファイル: test_api.py プロジェクト: snapcrab/loudml
    def setUp(self):
        if 'LOUDML_ADDR' in os.environ:
            self.loudml_addr = os.environ['LOUDML_ADDR']
        else:
            self.loudml_addr = 'localhost:8077'

        self.bucket_interval = 20 * 60

        t0 = int(datetime.datetime.now().timestamp())
        t0 -= t0 % self.bucket_interval
        self.t0 = t0

        self.db = 'test-{}'.format(t0)
        logging.info("creating database %s", self.db)
        if 'INFLUXDB_ADDR' in os.environ:
            addr = os.environ['INFLUXDB_ADDR']
        else:
            addr = 'localhost'

        self.source = InfluxDataSource({
            'name': 'nosetests',
            'addr': addr,
            'database': self.db,
        })
        self.source.drop()
        self.source.init()

        self.generator = SinEventGenerator(base=3, amplitude=3, sigma=0.01)

        to_date = datetime.datetime.now().timestamp()

        # Be sure that date range is aligned
        self.to_date = math.floor(to_date / self.bucket_interval) * self.bucket_interval  # noqa E501
        self.from_date = self.to_date - 3600 * 24 * 7 * 3

        for ts in self.generator.generate_ts(self.from_date, self.to_date, step_ms=600000):  # noqa E501
            self.source.insert_times_data(
                measurement='bar',
                ts=ts,
                data={
                    'foo': random.normalvariate(10, 1),
                }
            )

        self.source.commit()
コード例 #6
0
ファイル: test_influx.py プロジェクト: svencowart/loudml
class TestInfluxLong(unittest.TestCase):
    def setUp(self):

        self.db = "test-{}".format(int(datetime.datetime.now().timestamp()))
        self.source = InfluxDataSource({
            'name': 'test',
            'addr': ADDR,
            'database': self.db,
        })
        self.source.drop()
        self.source.init()
        self.storage = TempStorage()

        generator = SinEventGenerator(base=3, sigma=0.05)

        self.to_date = datetime.datetime.now().timestamp()
        self.from_date = self.to_date - 3600 * 24 * 7

        for ts in generator.generate_ts(
                self.from_date,
                self.to_date,
                step_ms=60000,
        ):
            self.source.insert_times_data(
                measurement='measure1',
                ts=ts,
                data={'foo': random.lognormvariate(10, 1)},
            )
        self.source.commit()

    def test_train(self):
        model = DonutModel(
            dict(
                name='test',
                offset=30,
                span=5,
                bucket_interval=20 * 60,
                interval=60,
                features=FEATURES[0:1],
                max_evals=1,
            ))

        # Train
        model.train(self.source,
                    from_date=self.from_date,
                    to_date=self.to_date)

        # Check
        self.assertTrue(model.is_trained)
コード例 #7
0
ファイル: test_influx.py プロジェクト: svencowart/loudml
    def setUp(self):
        this_day = int(
            datetime.datetime.now(tz=datetime.timezone.utc).replace(
                hour=0,
                minute=0,
                second=0,
                microsecond=0,
            ).timestamp())

        self.database = 'test-times-%d' % this_day
        logging.info("creating database %s", self.database)
        self.source = InfluxDataSource({
            'name': 'test',
            'type': 'influx',
            'addr': ADDR,
            'database': self.database,
        })
        self.source.drop()
        self.source.init()

        # Sin wave. 600s period.
        generator = SinEventGenerator(base=50,
                                      amplitude=50,
                                      period=600,
                                      sigma=0.01)

        # Normal data in range 06-12
        dt = datetime.datetime(2018, 8, 1, 6, 0)
        from_date = dt.replace(tzinfo=timezone.utc).timestamp()
        dt = datetime.datetime(2018, 8, 1, 12, 0)
        to_date = dt.replace(tzinfo=timezone.utc).timestamp()
        for ts, data in self.generate_data(generator,
                                           from_date,
                                           to_date,
                                           step_ms=1000,
                                           errors=0):
            self.source.insert_times_data(
                measurement='test_auto',
                ts=ts,
                data=data,
            )

        # Random 20s drops range 12-13
        dt = datetime.datetime(2018, 8, 1, 12, 0)
        from_date = dt.replace(tzinfo=timezone.utc).timestamp()
        dt = datetime.datetime(2018, 8, 1, 13, 0)
        to_date = dt.replace(tzinfo=timezone.utc).timestamp()
        for ts, data in self.generate_data(generator,
                                           from_date,
                                           to_date,
                                           step_ms=1000,
                                           errors=0.0001,
                                           burst_ms=20000):
            self.source.insert_times_data(
                measurement='test_auto',
                ts=ts,
                data=data,
            )

        # Again normal data in range 13-14
        dt = datetime.datetime(2018, 8, 1, 13, 0)
        from_date = dt.replace(tzinfo=timezone.utc).timestamp()
        dt = datetime.datetime(2018, 8, 1, 14, 0)
        to_date = dt.replace(tzinfo=timezone.utc).timestamp()
        for ts, data in self.generate_data(generator,
                                           from_date,
                                           to_date,
                                           step_ms=1000,
                                           errors=0):
            self.source.insert_times_data(
                measurement='test_auto',
                ts=ts,
                data=data,
            )

        # Duplicate normal data in range 06-14 and measurement=normal
        dt = datetime.datetime(2018, 8, 1, 6, 0)
        from_date = dt.replace(tzinfo=timezone.utc).timestamp()
        dt = datetime.datetime(2018, 8, 1, 14, 0)
        to_date = dt.replace(tzinfo=timezone.utc).timestamp()
        for ts, data in self.generate_data(generator,
                                           from_date,
                                           to_date,
                                           step_ms=1000,
                                           errors=0):
            self.source.insert_times_data(
                measurement='normal',
                ts=ts,
                data=data,
            )

        self.source.commit()
コード例 #8
0
ファイル: test_influx.py プロジェクト: svencowart/loudml
class TestInfluxTimes(unittest.TestCase):
    def setUp(self):
        this_day = int(
            datetime.datetime.now(tz=datetime.timezone.utc).replace(
                hour=0,
                minute=0,
                second=0,
                microsecond=0,
            ).timestamp())

        self.database = 'test-times-%d' % this_day
        logging.info("creating database %s", self.database)
        self.source = InfluxDataSource({
            'name': 'test',
            'type': 'influx',
            'addr': ADDR,
            'database': self.database,
        })
        self.source.drop()
        self.source.init()

        # Sin wave. 600s period.
        generator = SinEventGenerator(base=50,
                                      amplitude=50,
                                      period=600,
                                      sigma=0.01)

        # Normal data in range 06-12
        dt = datetime.datetime(2018, 8, 1, 6, 0)
        from_date = dt.replace(tzinfo=timezone.utc).timestamp()
        dt = datetime.datetime(2018, 8, 1, 12, 0)
        to_date = dt.replace(tzinfo=timezone.utc).timestamp()
        for ts, data in self.generate_data(generator,
                                           from_date,
                                           to_date,
                                           step_ms=1000,
                                           errors=0):
            self.source.insert_times_data(
                measurement='test_auto',
                ts=ts,
                data=data,
            )

        # Random 20s drops range 12-13
        dt = datetime.datetime(2018, 8, 1, 12, 0)
        from_date = dt.replace(tzinfo=timezone.utc).timestamp()
        dt = datetime.datetime(2018, 8, 1, 13, 0)
        to_date = dt.replace(tzinfo=timezone.utc).timestamp()
        for ts, data in self.generate_data(generator,
                                           from_date,
                                           to_date,
                                           step_ms=1000,
                                           errors=0.0001,
                                           burst_ms=20000):
            self.source.insert_times_data(
                measurement='test_auto',
                ts=ts,
                data=data,
            )

        # Again normal data in range 13-14
        dt = datetime.datetime(2018, 8, 1, 13, 0)
        from_date = dt.replace(tzinfo=timezone.utc).timestamp()
        dt = datetime.datetime(2018, 8, 1, 14, 0)
        to_date = dt.replace(tzinfo=timezone.utc).timestamp()
        for ts, data in self.generate_data(generator,
                                           from_date,
                                           to_date,
                                           step_ms=1000,
                                           errors=0):
            self.source.insert_times_data(
                measurement='test_auto',
                ts=ts,
                data=data,
            )

        # Duplicate normal data in range 06-14 and measurement=normal
        dt = datetime.datetime(2018, 8, 1, 6, 0)
        from_date = dt.replace(tzinfo=timezone.utc).timestamp()
        dt = datetime.datetime(2018, 8, 1, 14, 0)
        to_date = dt.replace(tzinfo=timezone.utc).timestamp()
        for ts, data in self.generate_data(generator,
                                           from_date,
                                           to_date,
                                           step_ms=1000,
                                           errors=0):
            self.source.insert_times_data(
                measurement='normal',
                ts=ts,
                data=data,
            )

        self.source.commit()

# queries to plot the data in Chronograf
# SELECT count("foo") AS "count_foo" FROM "test-times-*"."autogen"."test_auto" \
#   WHERE time > :dashboardTime: GROUP BY time(10s) FILL(null)
# SELECT last("count_foo") AS "predicted" FROM "test-times-*"."autogen"."prediction_test" \
#   WHERE time > :dashboardTime: GROUP BY time(10s) FILL(null)
#    def tearDown(self):
#        self.source.drop()

    def generate_data(self,
                      generator,
                      from_date,
                      to_date,
                      step_ms=1000,
                      errors=0,
                      burst_ms=0):
        ano = False
        previous_ts = None
        for ts in generator.generate_ts(from_date, to_date, step_ms=step_ms):
            if ano == False and errors > 0:
                val = random.random()
                if val < errors:
                    ano = True
                    total_burst_ms = 0
                    previous_ts = ts

            if ano == True and total_burst_ms < burst_ms:
                total_burst_ms += (ts - previous_ts) * 1000.0
                previous_ts = ts
            else:
                ano = False
                yield ts, {
                    'foo': random.lognormvariate(10, 1),
                }

    def test_loudmld(self):
        model = DonutModel(
            dict(
                name='test',
                offset=30,
                span=200,
                bucket_interval=10,
                interval=10,
                features=[{
                    'measurement': 'test_auto',
                    'name': 'count_foo',
                    'metric': 'count',
                    'field': 'foo',
                }],
                max_evals=21,
            ))
        model2 = DonutModel(
            dict(
                name='normal',
                offset=30,
                span=200,
                bucket_interval=10,
                interval=10,
                features=[{
                    'measurement': 'normal',
                    'name': 'count_foo',
                    'metric': 'count',
                    'field': 'foo',
                }],
                max_evals=1,
            ))

        # Normal data in range 06-12
        dt = datetime.datetime(2018, 8, 1, 6, 0)
        from_date = dt.replace(tzinfo=timezone.utc).timestamp()
        dt = datetime.datetime(2018, 8, 1, 12, 0)
        to_date = dt.replace(tzinfo=timezone.utc).timestamp()

        print("training model")
        model.train(self.source, from_date, to_date)
        print("training done")

        # simulate loudmld loop in range 11h00 - 13h30
        dt = datetime.datetime(2018, 8, 1, 11, 00)
        from_date = dt.replace(tzinfo=timezone.utc).timestamp()
        dt = datetime.datetime(2018, 8, 1, 13, 30)
        to_date = dt.replace(tzinfo=timezone.utc).timestamp()

        normal = []
        data = self.source.get_times_data(
            model2,
            from_date=from_date,
            to_date=to_date,
        )
        for line in data:
            normal.append(line[1])
        normal = np.array(normal)

        prediction = model.predict2(self.source,
                                    from_date,
                                    to_date,
                                    mse_rtol=4)
        model.detect_anomalies(prediction)
        self.source.save_timeseries_prediction(prediction, model)

        self.source.commit()

        self.assertEqual(normal.T[0].shape, prediction.predicted.shape)
        for j, _ in enumerate(normal):
            np.testing.assert_allclose(
                prediction.predicted[j],
                normal[j],
                rtol=0.10,
                atol=20,
            )
コード例 #9
0
ファイル: test_influx.py プロジェクト: svencowart/loudml
    def setUp(self):
        bucket_interval = 3

        t0 = int(datetime.datetime.now().timestamp())

        # XXX Bucket returned by InfluxDB are aligne on modulo(bucket_interval), that's why
        # timestamp must be aligned for unit tests.
        t0 -= t0 % bucket_interval

        self.t0 = t0

        self.db = 'test-{}'.format(t0)
        logging.info("creating database %s", self.db)
        self.source = InfluxDataSource({
            'name': 'test',
            'addr': ADDR,
            'database': self.db,
        })
        self.source.drop()
        self.source.init()

        self.model = Model(
            dict(
                name="test-model",
                offset=30,
                span=300,
                bucket_interval=3,
                interval=60,
                features=FEATURES,
            ))

        data = [
            # (foo, bar, timestamp)
            (1, 33, t0 - 1),  # excluded
            (2, 120, t0),
            (3, 312, t0 + 1),
            # empty
            (4, 18, t0 + 7),
            (5, 78, t0 + 9),  # excluded
        ]
        for foo, bar, ts in data:
            self.source.insert_times_data(measurement='measure1',
                                          ts=ts,
                                          data={
                                              'foo': foo,
                                          })
            self.source.insert_times_data(measurement='measure2',
                                          ts=ts,
                                          data={
                                              'bar': bar,
                                          })
            self.source.insert_times_data(measurement='measure3',
                                          ts=ts,
                                          tags={
                                              'tag_kw': 'tag1',
                                              'tag_int': 9,
                                              'tag_bool': False,
                                          },
                                          data={
                                              'baz': bar,
                                          })
            self.source.insert_times_data(measurement='measure3',
                                          ts=ts,
                                          tags={
                                              'tag_kw': 'tag2',
                                              'tag_int': 7,
                                              'tag_bool': True,
                                          },
                                          data={
                                              'baz': -bar,
                                          })

        self.source.commit()
コード例 #10
0
ファイル: test_influx.py プロジェクト: svencowart/loudml
class TestInfluxQuick(unittest.TestCase):
    def setUp(self):
        bucket_interval = 3

        t0 = int(datetime.datetime.now().timestamp())

        # XXX Bucket returned by InfluxDB are aligne on modulo(bucket_interval), that's why
        # timestamp must be aligned for unit tests.
        t0 -= t0 % bucket_interval

        self.t0 = t0

        self.db = 'test-{}'.format(t0)
        logging.info("creating database %s", self.db)
        self.source = InfluxDataSource({
            'name': 'test',
            'addr': ADDR,
            'database': self.db,
        })
        self.source.drop()
        self.source.init()

        self.model = Model(
            dict(
                name="test-model",
                offset=30,
                span=300,
                bucket_interval=3,
                interval=60,
                features=FEATURES,
            ))

        data = [
            # (foo, bar, timestamp)
            (1, 33, t0 - 1),  # excluded
            (2, 120, t0),
            (3, 312, t0 + 1),
            # empty
            (4, 18, t0 + 7),
            (5, 78, t0 + 9),  # excluded
        ]
        for foo, bar, ts in data:
            self.source.insert_times_data(measurement='measure1',
                                          ts=ts,
                                          data={
                                              'foo': foo,
                                          })
            self.source.insert_times_data(measurement='measure2',
                                          ts=ts,
                                          data={
                                              'bar': bar,
                                          })
            self.source.insert_times_data(measurement='measure3',
                                          ts=ts,
                                          tags={
                                              'tag_kw': 'tag1',
                                              'tag_int': 9,
                                              'tag_bool': False,
                                          },
                                          data={
                                              'baz': bar,
                                          })
            self.source.insert_times_data(measurement='measure3',
                                          ts=ts,
                                          tags={
                                              'tag_kw': 'tag2',
                                              'tag_int': 7,
                                              'tag_bool': True,
                                          },
                                          data={
                                              'baz': -bar,
                                          })

        self.source.commit()

    def tearDown(self):
        self.source.drop()

    def test_validation(self):
        with self.assertRaises(errors.Invalid):
            InfluxDataSource({
                'addr': 'localhost',
            })
        with self.assertRaises(errors.Invalid):
            InfluxDataSource({
                'database': 'foo',
            })

    def test_build_time_predicates(self):
        self.assertEqual(
            _build_time_predicates(),
            [],
        )
        self.assertEqual(
            _build_time_predicates(
                from_date=1515404366.1234,
                to_date="2018-01-08T14:59:25.456Z",
            ),
            [
                "time >= 1515404366123400000",
                "time < 1515423565456000000",
            ],
        )

    def test_build_tags_predicates(self):
        self.assertEqual(
            _build_tags_predicates(),
            [],
        )
        self.assertEqual(
            _build_tags_predicates([
                {
                    'tag': 'foo',
                    'value': 'bar'
                },
                {
                    'tag': 'a "',
                    'value': 'b \''
                },
                {
                    'tag': 'int',
                    'value': 42
                },
                {
                    'tag': 'bool',
                    'value': True
                },
            ]), [
                "\"foo\"='bar'",
                "\"a \\\"\"='b \\''",
                "(\"int\"='42' OR \"int\"=42)",
                "(\"bool\"='True' OR \"bool\"=True)",
            ])

    def test_build_times_queries(self):
        where = "time >= 1515404366123400000 and time < 1515423565456000000"
        queries = list(
            self.source._build_times_queries(
                self.model,
                from_date=1515404366.1234,
                to_date="2018-01-08T14:59:25.456Z",
            ))
        self.assertEqual(
            queries,
            [
                "select MEAN(\"foo\") as \"avg_foo\" from \"measure1\" "\
                "where {} group by time(3000ms);".format(where),
                "select COUNT(\"bar\") as \"count_bar\" from \"measure2\" "\
                "where {} group by time(3000ms);".format(where),
                "select MEAN(\"baz\") as \"avg_baz\" from \"measure1\" "\
                "where {} and \"mytag\"='myvalue' group by time(3000ms);".format(where),
            ],
        )

        source = InfluxDataSource({
            'name': 'test',
            'addr': ADDR,
            'database': self.db,
            'retention_policy': 'custom',
        })

        queries = list(
            source._build_times_queries(
                self.model,
                from_date=1515404366.1234,
                to_date="2018-01-08T14:59:25.456Z",
            ))
        from_prefix = '"{}"."custom".'.format(self.db)
        self.assertEqual(
            queries,
            [
                "select MEAN(\"foo\") as \"avg_foo\" from {}\"measure1\" "\
                "where {} group by time(3000ms);".format(from_prefix, where),
                "select COUNT(\"bar\") as \"count_bar\" from {}\"measure2\" "\
                "where {} group by time(3000ms);".format(from_prefix, where),
                "select MEAN(\"baz\") as \"avg_baz\" from {}\"measure1\" "\
                "where {} and \"mytag\"='myvalue' group by time(3000ms);".format(from_prefix, where),
            ],
        )

    def test_get_times_data(self):
        logging.info("[%d %d]", self.t0, self.t0)
        res = self.source.get_times_data(
            self.model,
            from_date=self.t0,
            to_date=self.t0 + 8,
        )

        foo_avg = []
        bar_count = []

        for line in res:
            foo_avg.append(nan_to_none(line[1][0]))
            bar_count.append(nan_to_none(line[1][1]))

        self.assertEqual(foo_avg, [2.5, None, 4.0])
        self.assertEqual(bar_count, [2.0, 0, 1.0])

    def test_get_times_data2(self):
        res = self.source.get_times_data(
            self.model,
            from_date=self.t0,
            to_date=self.t0 + 8,
        )

        # _source to write aggregate data to RAM
        _source = MemDataSource()
        _features = copy.deepcopy(self.model.features)
        for _, feature in enumerate(self.model.features):
            feature.metric = 'avg'

        i = None
        for i, (_, val, timeval) in enumerate(res):
            bucket = {
                feature.field: val[i]
                for i, feature in enumerate(self.model.features)
            }
            bucket.update({'timestamp': make_ts(timeval)})
            _source.insert_times_data(bucket)

        res2 = _source.get_times_data(
            self.model,
            from_date=self.t0,
            to_date=self.t0 + 8,
        )
        self.model.features = _features

        for i, (_, val2, timeval2) in enumerate(res2):
            (_, val, timeval) = res[i]
            np.testing.assert_allclose(val, val2)

    def test_match_all(self):
        model = Model(
            dict(
                name="test-model",
                offset=30,
                span=300,
                bucket_interval=3,
                interval=60,
                features=FEATURES_MATCH_ALL_TAG1,
            ))
        res = self.source.get_times_data(
            model,
            from_date=self.t0,
            to_date=self.t0 + 8,
        )
        baz_avg = []
        for line in res:
            baz_avg.append(line[1][0])

        np.testing.assert_allclose(
            np.array(baz_avg),
            np.array([216.0, np.nan, 18.0]),
            rtol=0,
            atol=0,
        )

        model = Model(
            dict(
                name="test-model",
                offset=30,
                span=300,
                bucket_interval=3,
                interval=60,
                features=FEATURES_MATCH_ALL_TAG2,
            ))

        res = self.source.get_times_data(
            model,
            from_date=self.t0,
            to_date=self.t0 + 8,
        )
        baz_avg = []
        for line in res:
            baz_avg.append(line[1][0])

        np.testing.assert_allclose(
            np.array(baz_avg),
            np.array([-216.0, np.nan, -18.0]),
            rtol=0,
            atol=0,
        )
コード例 #11
0
class AppTests(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        pass

    @classmethod
    def tearDownClass(cls):
        pass

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def setUp(self):
        self.app = app.test_client()
        self.app.testing = True

        self.bucket_interval = 20 * 60

        t0 = int(datetime.datetime.now().timestamp())
        t0 -= t0 % self.bucket_interval
        self.t0 = t0

        self.db = 'test-{}'.format(t0)
        logging.info("creating database %s", self.db)
        self.source = InfluxDataSource({
            'name': 'nose',
            'addr': ADDR,
            'database': self.db,
        })
        self.source.drop()
        self.source.init()

        self.generator = SinEventGenerator(base=3, amplitude=3, sigma=0.01)

        to_date = datetime.datetime.now().timestamp()

        # Be sure that date range is aligned
        self.to_date = math.floor(
            to_date / self.bucket_interval) * self.bucket_interval  # noqa E501
        self.from_date = self.to_date - 3600 * 24 * 7 * 3

        for ts in self.generator.generate_ts(self.from_date,
                                             self.to_date,
                                             step_ms=600000):  # noqa E501
            self.source.insert_times_data(measurement='bar',
                                          ts=ts,
                                          data={
                                              'foo':
                                              random.normalvariate(10, 1),
                                          })

        self.source.commit()

        self.dirpath = tempfile.mkdtemp()
        configyml = os.path.join(self.dirpath, 'config.yml')
        cfg = open(configyml, 'w')
        cfg.write(CONFIG.format(ADDR, self.db, self.dirpath))
        cfg.close()

        g_app_init(configyml)

    def tearDown(self):
        g_app_stop()
        self.source.drop()
        shutil.rmtree(self.dirpath)

    def _wait_job(self, job_id):
        state = None
        while not state_is_done(state):
            time.sleep(5)
            result = self.app.get('/jobs/{}'.format(job_id))
            res = json.loads(result.data.decode('utf-8'))
            print(res)
            state = res['state']
        return state

    def _get_models(self):
        result = self.app.get('/models', )
        self.assertEqual(result.status_code, 200)
        d = json.loads(result.data.decode('utf-8'))
        return d

    def _require_model(self):
        d = self._get_models()
        if len(d) > 0 and d[0]['name'] == 'test-model':
            return

        model = dict(
            name='test-model',
            default_datasource='nose',
            offset=30,
            span=24 * 3,
            bucket_interval=self.bucket_interval,
            interval=60,
            features=FEATURES,
            grace_period="140m",  # = 7 points
            max_threshold=99.7,
            min_threshold=68,
            max_evals=1,
        )
        model['type'] = 'donut'

        result = self.app.put(
            '/models',
            follow_redirects=True,
            content_type='application/json',
            data=json.dumps(model),
        )
        self.assertEqual(result.status_code, 201)
        d = self._get_models()
        self.assertEqual(len(d), 1)
        self.assertEqual(d[0]['settings']['name'], 'test-model')
        return d[0]

    def _require_training(self):
        model = self._require_model()
        if model['state']['trained']:
            return
        result = self.app.post(
            '/models/{}/_train?from={}&to={}'.format(
                'test-model',
                str(self.from_date),
                str(self.to_date),
            ), )
        job_id = read_job_id(result)
        status = self._wait_job(job_id)
        self.assertEqual(status, 'done')

    def test_train(self):
        self._require_training()

    def test_home(self):
        result = self.app.get('/')
        self.assertEqual(result.status_code, 200)
        d = json.loads(result.data.decode('utf-8'))
        self.assertIsNotNone(d.get('host_id'))
        self.assertIsNotNone(d.get('version'))
コード例 #12
0
ファイル: test_api.py プロジェクト: snapcrab/loudml
class AppTests(unittest.TestCase):

    @classmethod
    def setUpClass(cls):
        pass

    @classmethod
    def tearDownClass(cls):
        pass

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._jwt = None

    def setUp(self):
        if 'LOUDML_ADDR' in os.environ:
            self.loudml_addr = os.environ['LOUDML_ADDR']
        else:
            self.loudml_addr = 'localhost:8077'

        self.bucket_interval = 20 * 60

        t0 = int(datetime.datetime.now().timestamp())
        t0 -= t0 % self.bucket_interval
        self.t0 = t0

        self.db = 'test-{}'.format(t0)
        logging.info("creating database %s", self.db)
        if 'INFLUXDB_ADDR' in os.environ:
            addr = os.environ['INFLUXDB_ADDR']
        else:
            addr = 'localhost'

        self.source = InfluxDataSource({
            'name': 'nosetests',
            'addr': addr,
            'database': self.db,
        })
        self.source.drop()
        self.source.init()

        self.generator = SinEventGenerator(base=3, amplitude=3, sigma=0.01)

        to_date = datetime.datetime.now().timestamp()

        # Be sure that date range is aligned
        self.to_date = math.floor(to_date / self.bucket_interval) * self.bucket_interval  # noqa E501
        self.from_date = self.to_date - 3600 * 24 * 7 * 3

        for ts in self.generator.generate_ts(self.from_date, self.to_date, step_ms=600000):  # noqa E501
            self.source.insert_times_data(
                measurement='bar',
                ts=ts,
                data={
                    'foo': random.normalvariate(10, 1),
                }
            )

        self.source.commit()

    def tearDown(self):
        self.source.drop()

    def get(self, url, data=None, **kwargs):
        headers = kwargs.pop('headers', {})
        if self._jwt:
            headers['Authorization'] = 'Bearer {}'.format(self._jwt)
        return requests.get(
            self.get_url(url),
            data=data,
            headers=headers,
            **kwargs
        )

    def post(self, url, data=None, **kwargs):
        headers = kwargs.pop('headers', {})
        if self._jwt:
            headers['Authorization'] = 'Bearer {}'.format(self._jwt)
        return requests.post(
            self.get_url(url),
            data=data,
            headers=headers,
            **kwargs
        )

    def patch(self, url, data=None, **kwargs):
        headers = kwargs.pop('headers', {})
        if self._jwt:
            headers['Authorization'] = 'Bearer {}'.format(self._jwt)
        return requests.patch(
            self.get_url(url),
            data=data,
            headers=headers,
            **kwargs
        )

    def delete(self, url, data=None, **kwargs):
        headers = kwargs.pop('headers', {})
        if self._jwt:
            headers['Authorization'] = 'Bearer {}'.format(self._jwt)
        return requests.delete(
            self.get_url(url),
            data=data,
            headers=headers,
            **kwargs
        )

    def put(self, url, data=None, content_type=None, **kwargs):
        headers = kwargs.pop('headers', {})
        if self._jwt:
            headers['Authorization'] = 'Bearer {}'.format(self._jwt)
        if content_type:
            headers['Content-Type'] = content_type
        return requests.put(
            self.get_url(url),
            data=data,
            headers=headers,
            **kwargs
        )

    def get_url(self, url):
        if 'USE_SSL' in os.environ:
            scheme = 'https://'
        else:
            scheme = 'http://'

        return scheme + self.loudml_addr + url

    def _wait_job(self, job_id):
        state = None
        while not state_is_done(state):
            time.sleep(5)
            response = self.get(
                '/jobs/{}'.format(job_id)
            )
            res = response.json()
            # print(res)
            state = res['state']
        return state

    def _get_models(self):
        response = self.get(
            '/models',
        )
        self.assertEqual(response.status_code, 200)
        return response.json()

    def _get_sources(self):
        response = self.get(
            '/datasources',
        )
        self.assertEqual(response.status_code, 200)
        return response.json()

    def _require_source(self):
        sources = {
            source['name']: source
            for source in self._get_sources()
        }
        if self.db in sources:
            return

        if 'INFLUXDB_ADDR' in os.environ:
            addr = os.environ['INFLUXDB_ADDR']
        else:
            addr = 'localhost:8086'

        source = {
            'name': self.db,
            'type': 'influxdb',
            'addr': addr,
            'database': self.db,
            'create_database': 'true',
            'retention_policy': 'autogen',
            'max_series_per_request': 2000,
        }
        response = self.put(
            '/datasources',
            content_type='application/json',
            data=json.dumps(source),
        )
        self.assertEqual(response.status_code, 201)
        sources = {
            source['name']: source
            for source in self._get_sources()
        }
        self.assertTrue(self.db in sources)

    def _del_model(self, model_name):
        response = self.delete(
            '/models/{}'.format(model_name),
        )
        self.assertTrue(response.status_code in [200, 404])

    def _require_model(self):
        self._require_source()
        models = {
            model['settings']['name']: model
            for model in self._get_models()
        }
        if 'test-model' in models:
            return models['test-model']

        model = dict(
            name='test-model',
            default_datasource=self.db,
            offset=30,
            span=24 * 3,
            bucket_interval=self.bucket_interval,
            interval=60,
            features=FEATURES,
            grace_period="140m",  # = 7 points
            max_threshold=99.7,
            min_threshold=68,
            max_evals=1,
        )
        model['type'] = 'donut'

        response = self.put(
            '/models',
            content_type='application/json',
            data=json.dumps(model),
        )
        self.assertEqual(response.status_code, 201)
        models = {
            model['settings']['name']: model
            for model in self._get_models()
        }
        self.assertTrue('test-model' in models)
        return models['test-model']

    def _require_training(self):
        model = self._require_model()
        if model['state']['trained']:
            return
        response = self.post(
            '/models/{}/_train?from={}&to={}'.format(
                'test-model',
                str(self.from_date),
                str(self.to_date),
            ),
        )
        job_id = read_job_id(response.text)
        status = self._wait_job(job_id)
        self.assertEqual(status, 'done')

    def test_training(self):
        self._del_model('test-model')
        self._require_training()

    def test_home(self):
        response = self.get('/')
        self.assertEqual(response.status_code, 200)
        home = response.json()
        self.assertIsNotNone(home.get('host_id'))
        self.assertIsNotNone(home.get('version'))