Fixing graphite-api on Ubuntu 20.04
graphite-api is a lightweight frontend for
graphite-carbon timeseries database, which enables
grafana to access carbon’s data. I install graphite-api from Ubuntu repository, and by default it runs on
127.0.0.1:8542. The issue is grafana accesses this directly, meaning you access it from your browser, so graphite-api needs to listen on 0.0.0.0 not on localhost. Also, at the moment of writing this post, graphite-api fails to start because of a change in Python 3.8.
Fixing bind address
The configuration file is
/etc/default/graphite-api, but it says:
## This file is not used when using systemd. ## Use "systemctl edit graphite-api" instead.
and this is the case. If you do what it writes here,
systemctl edit graphite-api, then what do you write ? You can check the default configuration options on default systemd files under
/lib/systemd/system, there are two files:
graphite-api.service is where gunicorn3 is started but it does not mention any bind parameters.
graphite-api.socket has this option among others:
so that is what should be changed. However, if you do
systemctl edit graphite-api and create an override.conf to override this, it does not work. Because ListenStream is an option of
graphite-api.service. So you have to run
systemctl edit graphite-api.socket and create an override for that instead.
However, after doing that, it gives an error. The issue is the ListenStream option you thought you overwrote actually by adding options so you did not re-set it. In order to do that, it should be first set to empty, like this:
[Socket] ListenStream= ListenStream=0.0.0.0:8542
and then issue a restart, and now it binds to 0.0.0.0 .
If you are using python3.8, probably graphite-api will fail to start. This is because python3.8 has changed the findCaller signature, and the structlog library used by graphite-api is not updated (yet, at the moment of this post). So I modified the
/usr/lib/python3/dist-packages/structlog/stdlib.py file and changed the findCaller signature and added stacklevel=1 argument.
def findCaller(self, stack_info=False, stacklevel=1):
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.