Skip to content

Commit 93039cf

Browse files
committed
[timeseries] Add initial support for elasticsearch #99
1 parent 2f60e22 commit 93039cf

26 files changed

+1359
-159
lines changed

.travis.yml

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,27 +24,30 @@ addons:
2424

2525
services:
2626
- docker
27-
- redis-server
2827

2928
branches:
3029
only:
3130
- master
3231
- dev
3332

3433
before_install:
35-
- docker run -d --name influxdb -e INFLUXDB_DB=openwisp2 -p 8086:8086 influxdb:alpine
34+
- docker-compose up -d
3635
- pip install -U pip wheel setuptools
3736
- pip install $DJANGO
3837
- pip install -U -r requirements-test.txt
3938

4039
install:
41-
- pip install -e .
40+
- pip install -e .[influxdb,elasticsearch]
4241
- sh install-dev.sh
4342

4443
script:
4544
- ./run-qa-checks
46-
- SAMPLE_APP=1 coverage run --source=openwisp_monitoring runtests.py
47-
- coverage run -a --source=openwisp_monitoring runtests.py
45+
- SAMPLE_APP=1 coverage run -p --source=openwisp_monitoring runtests.py
46+
- coverage run -p --source=openwisp_monitoring runtests.py
47+
- elasticsearch=1 SAMPLE_APP=1 coverage run -p --source=openwisp_monitoring runtests.py
48+
- elasticsearch=1 coverage run -p --source=openwisp_monitoring runtests.py
49+
- coverage combine
50+
- coverage report -m
4851

4952
jobs:
5053
include:

Dockerfile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ WORKDIR /opt/openwisp/tests/
1919
ENV NAME=openwisp-monitoring \
2020
PYTHONBUFFERED=1 \
2121
INFLUXDB_HOST=influxdb \
22-
REDIS_HOST=redis
22+
REDIS_HOST=redis \
23+
ELASTICSEARCH_HOST=es01
2324
CMD ["sh", "docker-entrypoint.sh"]
2425
EXPOSE 8000

README.rst

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ Available Features
2828
* Collects and displays `device status <#device-status>`_ information like uptime, RAM status, CPU load averages,
2929
Interface properties and addresses, WiFi interface status and associated clients,
3030
Neighbors information, DHCP Leases, Disk/Flash status
31-
* Collection of monitoring information in a timeseries database (currently only influxdb is supported)
31+
* Collection of monitoring information in a timeseries database (`InfluxDB <https://www.influxdata.com/>`_ and `Elasticsearch <https://www.elastic.co/elasticsearch/>`_ are currently supported)
3232
* Monitoring charts for uptime, packet loss, round trip time (latency), associated wifi clients, interface traffic,
3333
RAM usage, CPU load, flash/disk usage
3434
* Charts can be viewed at resolutions of 1 day, 3 days, a week, a month and a year
@@ -50,6 +50,8 @@ beforehand.
5050
In case you prefer not to use Docker you can `install InfluxDB <https://docs.influxdata.com/influxdb/v1.8/introduction/install/>`_
5151
and Redis from your repositories, but keep in mind that the version packaged by your distribution may be different.
5252

53+
If you wish to use ``Elasticsearch`` for storing and retrieving timeseries data then `install Elasticsearch <https://www.elastic.co/guide/en/elasticsearch/reference/current/install-elasticsearch.html>`_.
54+
5355
Install spatialite and sqlite:
5456

5557
.. code-block:: shell
@@ -110,6 +112,19 @@ Follow the setup instructions of `openwisp-controller
110112
'PORT': '8086',
111113
}
112114
115+
In case, you wish to use ``Elasticsearch`` for timeseries data storage and retrieval,
116+
make use of the following settings
117+
118+
.. code-block:: python
119+
TIMESERIES_DATABASE = {
120+
'BACKEND': 'openwisp_monitoring.db.backends.elasticsearch',
121+
'USER': 'openwisp',
122+
'PASSWORD': 'openwisp',
123+
'NAME': 'openwisp2',
124+
'HOST': 'localhost',
125+
'PORT': '9200',
126+
}
127+
113128
``urls.py``:
114129

115130
.. code-block:: python
@@ -422,6 +437,9 @@ This data is only used to assess the recent status of devices, keeping
422437
it for a long time would not add much benefit and would cost a lot more
423438
in terms of disk space.
424439

440+
**Note**: In case you use ``Elasticsearch`` then time shall be taken as integral multiple of a day.
441+
That means the time ``36h0m0s`` shall be interpreted as ``24h0m0s`` (integral multiple of a day).
442+
425443
``OPENWISP_MONITORING_AUTO_PING``
426444
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
427445

@@ -702,18 +720,30 @@ MB (megabytes) instead of GB (Gigabytes) you can use:
702720
"SUM(rx_bytes) / 1000000 AS download FROM {key} "
703721
"WHERE time >= '{time}' AND content_type = '{content_type}' "
704722
"AND object_id = '{object_id}' GROUP BY time(1d)"
705-
)
723+
),
724+
'elasticsearch': _make_query({
725+
'upload': {'sum': {'field': 'points.fields.tx_bytes'}},
726+
'download': {'avg': {'field': 'points.fields.rx_bytes'}},
727+
})
706728
},
707729
}
708730
}
709731
732+
# Please declare the operations separately in case you use elasticsearch as done below
733+
OPENWISP_MONITORING_ADDITIONAL_CHART_OPERATIONS = {
734+
'upload': {'operator': '/', 'value': 1000000},
735+
'download': {'operator': '/', 'value': 1000000},
736+
}
737+
710738
Or if you want to define a new chart configuration, which you can then
711739
call in your custom code (eg: a custom check class), you can do so as follows:
712740

713741
.. code-block:: python
714742
715743
from django.utils.translation import gettext_lazy as _
716744
745+
from openwisp_monitoring.db.backends.elasticsearch import _make_query
746+
717747
OPENWISP_MONITORING_CHARTS = {
718748
'ram': {
719749
'type': 'line',
@@ -727,7 +757,12 @@ call in your custom code (eg: a custom check class), you can do so as follows:
727757
"MEAN(buffered) AS buffered FROM {key} WHERE time >= '{time}' AND "
728758
"content_type = '{content_type}' AND object_id = '{object_id}' "
729759
"GROUP BY time(1d)"
730-
)
760+
),
761+
'elasticsearch': _make_query({
762+
'total': {'avg': {'field': 'points.fields.total'}},
763+
'free': {'avg': {'field': 'points.fields.free'}},
764+
'buffered': {'avg': {'field': 'points.fields.buffered'}},
765+
})
731766
},
732767
}
733768
}

docker-compose.yml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ services:
1111
depends_on:
1212
- influxdb
1313
- redis
14+
- es01
15+
- es02
1416

1517
influxdb:
1618
image: influxdb:1.8-alpine
@@ -22,6 +24,45 @@ services:
2224
INFLUXDB_DB: openwisp2
2325
INFLUXDB_USER: openwisp
2426
INFLUXDB_USER_PASSWORD: openwisp
27+
# clustered version of elasticsearch is used as that might be used in production
28+
es01:
29+
image: docker.elastic.co/elasticsearch/elasticsearch:7.8.0
30+
container_name: es01
31+
environment:
32+
- "node.name=es01"
33+
- "discovery.seed_hosts=es02"
34+
- "cluster.initial_master_nodes=es01,es02"
35+
- "cluster.name=openwisp2"
36+
- "bootstrap.memory_lock=true"
37+
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
38+
ulimits:
39+
memlock:
40+
soft: -1
41+
hard: -1
42+
volumes:
43+
- esdata01:/usr/share/elasticsearch/data
44+
ports:
45+
- 9200:9200
46+
networks:
47+
- esnet
48+
es02:
49+
image: docker.elastic.co/elasticsearch/elasticsearch:7.8.0
50+
container_name: es02
51+
environment:
52+
- "node.name=es02"
53+
- "discovery.seed_hosts=es01"
54+
- "cluster.initial_master_nodes=es01,es02"
55+
- "cluster.name=openwisp2"
56+
- "bootstrap.memory_lock=true"
57+
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
58+
ulimits:
59+
memlock:
60+
soft: -1
61+
hard: -1
62+
volumes:
63+
- esdata02:/usr/share/elasticsearch/data
64+
networks:
65+
- esnet
2566

2667
redis:
2768
image: redis:5.0-alpine
@@ -31,3 +72,10 @@ services:
3172

3273
volumes:
3374
influxdb-data: {}
75+
esdata01:
76+
driver: local
77+
esdata02:
78+
driver: local
79+
80+
networks:
81+
esnet:

openwisp_monitoring/db/__init__.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
from .backends import timeseries_db
22

33
chart_query = timeseries_db.queries.chart_query
4-
default_chart_query = timeseries_db.queries.default_chart_query
5-
device_data_query = timeseries_db.queries.device_data_query
64

7-
__all__ = ['timeseries_db', 'chart_query', 'default_chart_query', 'device_data_query']
5+
__all__ = ['timeseries_db', 'chart_query']

openwisp_monitoring/db/backends/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ def load_backend_module(backend_name=TIMESERIES_DB['BACKEND'], module=None):
4848
except ImportError as e:
4949
# The database backend wasn't found. Display a helpful error message
5050
# listing all built-in database backends.
51-
builtin_backends = ['influxdb']
51+
builtin_backends = ['influxdb', 'elasticsearch']
52+
raise e
5253
if backend_name not in [
5354
f'openwisp_monitoring.db.backends.{b}' for b in builtin_backends
5455
]:
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from .queries import _make_query
2+
3+
__all__ = ['_make_query']

0 commit comments

Comments
 (0)