In questa pagina sono raccolte alcune note sull'installazione e l'uso preliminare di Grafana, un'applicazione web per visualizzare dati. La versione utilizzata per l'installazione è stata Grafana OSS 9.1.7, l'ultima stabile al momento della stesura di queste note, ma non dovrebbero esserci problemi con versioni più aggiornate.
La macchina utilizzata:
Per i dettagli seguire i rispettivi link. Sono ovviamente possibili modifiche a questa configurazione, in genere intuitivi se utilizzate una qualunque distribuzione Linux a 64 bit.
Qui come procedere con Raspberry Pi.
Innanzitutto occorre avere installato un paio di pacchetti, spesso peraltro già presenti:
vv@IoT-DB:~$ sudo apt install -y apt-transport-https
vv@IoT-DB:~$ sudo apt install curl
Occorre quindi configurare la firma (nota 1) ed il
repository per Grafana:
vv@IoT-DB:~$ curl -sS https://packages.grafana.com/gpg.key | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/grafana.gpg > /dev/null
vv@IoT-DB:~$ sudo nano /etc/apt/sources.list.d/grafana.list
deb [signed-by=/etc/apt/trusted.gpg.d/grafana.gpg]
https://packages.grafana.com/oss/deb stable main
Si procede quindi all'installazione vera e propria:
vv@IoT-DB:~$ sudo apt update
vv@IoT-DB:~$ sudo apt install grafana
Infine si avvia il servizio (nota 2):
vv@IoT-DB:~$ sudo systemctl enable grafana-server.service
vv@IoT-DB:~$ sudo systemctl start grafana-server.service
Per l'amministrazione è possibile accedere via browser all'indirizzo http://test.xxx.yy:3000 (nota 3 e nota 4).
Al primo accesso viene chiesto di modificare la password di admin (che inizialmente è... admin).
La prima operazione da fare è configurare l'accesso al database InfluxDB 2 selezionando DATA SOURCES - Add your first data source. Il database deve già essere installato e, se possibile, deve contenere qualche dato. Se non avete dati "veri" potete ispirarvi a questo esempio oppure a questo.
La pagina da configurare è la seguente; occorre modificare solo le voci evidenziare. In particolare Organization e Token sono specifici per il database.
Occorre infine creare una Dashboard contenete uno o più Panel (grafico). Purtroppo non è presente uno strumento per generare automaticamente query al database: occorre avere una qualche conoscenza di Flux.
Un esempio di query potrebbe essere il seguente, con dati generati con lo script presente in questa pagina:
from(bucket: "Test")
|> range(start: v.timeRangeStart, stop: v.timeRangeStop)
|> filter(fn: (r) => r["_measurement"] == "Esterno")
|> filter(fn: (r) => r["Sensore"] == "OpenMeteo")
|> filter(fn: (r) => r["_field"] == "T")
|> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)
|> yield(name: "mean")
Un altro esempio di query potrebbe essere il seguente, con dati generati dallo script presente in questa pagina:
from(bucket: "Test")
|> range(start: v.timeRangeStart, stop: v.timeRangeStop)
|> filter(fn: (r) => r["_measurement"] == "CPU_Usage")
|> filter(fn: (r) => r["PC"] == "vv-i7")
|> filter(fn: (r) => r["_field"] == "CPU" or r["_field"] == "T")
|> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)
|> yield(name: "mean")
Infine un terzo esempio. I dati sono generati dal sensore sensore IoT con tag 010000000000. Il grafico ottenuto, usando più sensori con tag diversi è visibile in apertura di questa pagina.
from(bucket: "myBucket")
|> range(start: v.timeRangeStart, stop: v.timeRangeStop)
|> filter(fn: (r) => r["_measurement"] == "mysensor")
|> filter(fn: (r) => r["SensorID"] == "010000000000")
|> filter(fn: (r) => r["_field"] == "Temperatura")
|> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)
|> yield(name: "mean")
Quanto descritto in questo paragrafo richiede la registrazione del nome del server su un DNS pubblico (test.xxx.yyy in seguito). Se non è possibile, la configurazione è terminata e Grafana deve essere usato come descritto al punto precedente.
Nella configurazione di default sono però presenti due criticità:
In teoria è possibile modificare il file di configurazione per superare entrambi i problemi, ma ritengo una scelta migliore installare Apache ed usarlo come reverse proxy, aggiungendo semplicità, flessibilità, migliore documentazione in rete e, probabilmente, sicurezza.
Innanzitutto occorre installare Apache e verificarne il funzionamento:
vv@IoT-DB:~$ sudo apt install apache2
Verificare il funzionamento accedendo con un browser al sito web, sia utilizzando l'indirizzo IP (http://1.2.3.4) che il nome (http://test.xxx.yyy): è mostrata la pagina di default di Apache (nota 4).
Se si dispone di un nome registrato su un DNS pubblico conviene configurare un virtual host:
vv@IoT-DB:~$ sudo nano /etc/apache2/sites-available/test.conf
<VirtualHost *:80>
ServerAdmin vv@xxx.yyy
ServerName test.xxx.yyy
DocumentRoot /var/www/test
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
vv@IoT-DB:~$ sudo mkdir /var/www/test
vv@IoT-DB:~$ sudo nano /var/www/test/index.htm
<html>
<head>
<title>Welcome</title>
</head>
<body>
<h1>Success! The http://test.xxx.yyy virtual host is working!</h1>
</body>
</html>
vv@IoT-DB:~$ sudo a2ensite test.conf
vv@IoT-DB:~$ sudo systemctl reload apache2
Verificare il funzionamento accedendo con un browser all'indirizzo http://test.xxx.yyy; è mostrata una stringa di benvenuto (nota 4). Usando l'indirizzo IP, viene invece ancora mostrata la pagina di default.
Il modo più semplice e veloce per configurare Apache con TLS è usare un certificato rilasciato Let’s Encrypt, installato tramite Certbot. Tale scelta è libera e gratuita.
vv@IoT-DB:~$ sudo apt install certbot python3-certbot-apache
La creazione dei certificati, la loro firma, la loro installazione e la configurazione di Apache è fatta con un singolo comando a cui occorre dare poche e semplici risposte guidate:
vv@IoT-DB:~$ sudo certbot --apache
Accedendo con il browser a https://test.xxx.yyy viene mostrata la stringa di benvenuto; accedendo a http://test.xxx.yyy il browser è ridiretto a https://test.xxx.yyy; accedendo all'indirizzo IP viene mostrata la pagina di default, non cifrata.
Due comandi utili per verificare la corretta installazione:
vv@IoT-DB:~$ sudo certbot renew --dry-run
vv@IoT-DB:~$ sudo systemctl status certbot.timer
Il certificato verrà automaticamente rinnovato prima della scadenza direttamente da Certbot.
Occorre innanzitutto abilitare i seguenti moduli in Apache:
vv@IoT-DB:~$ sudo a2enmod proxy
vv@IoT-DB:~$ sudo a2enmod proxy_http
Quindi modificare il file di configurazione del sito aggiungendo le seguenti quattro righe subito prima di </VirtualHost>:
vv@IoT-DB:~$ sudo nano /etc/apache2/sites-enabled/test-le-ssl.conf
ReWriteEngine on
ProxyPass "/" "http://localhost:3000/"
ProxyPassReverse "/" "http://localhost:3000/"
ProxyPreserveHost On
Quindi modificare il file di configurazione di Grafana aggiungendo le seguenti righe dopo le simili righe già esistenti:
vv@IoT-DB:~$ sudo nano /etc/grafana/grafana.ini
domain = test.xxx.yyy
root_url = %(protocol)s://%(domain)s:%(http_port)s/grafana/
serve_from_sub_path = true
Riavviare infine i servizi:
vv@IoT-DB:~$ sudo systemctl restart apache2.service
vv@IoT-DB:~$ sudo systemctl restart grafana-server.service
L'accesso all'URL https://test.xxx.yyy porta direttamente a Grafana.
Se Apache è stato configurato come reverse proxy, non è più richiesto che la porta 3000 rimanga aperta.
La configurazione di Grafana non è sempre semplice anche se con un po' di pazienza si riesce a prendere confidenza con le varie impostazioni. In questo paragrafo trovate alcune cose per nulla intuitive, ma che ho trovato utili.
Per permettere l'accesso senza password occorre innanzitutto selezionare una dashboard come "Home":
Quindi, all'interno del file grafana.ini, modificare le seguenti righe nella sezione [auth.anonymous], in parte già presenti, ma commentate:
vv@IoT-DB:~$ sudo nano /etc/grafana/grafana.ini
[auth.anonymous]
enabled = true
org_name = VincenzoV
org_role = Viewer # Consigliato
Infine riavviare il servizio:
vv@IoT-DB:~$ sudo systemctl restart grafana-server.service
Spesso è necessario personalizzare la legenda di una serie di dati.
Per fare ciò è necessario impostare il campo Display name a (${__field.name} ed impostare nella query le due righe:
|> group(columns: ["_field"])
|> set(key: "_field", value: "S1")
Pagina creata nell'ottobre 2022
Ultima modifica di questa pagina: 31 dicembre 2022
Il taccuino tecnico - Permanentemente in fase di riscrittura
Copyright 2013-2024, Vincenzo Villa (https://www.vincenzov.net)
Quest'opera è stata rilasciata con licenza Creative Commons | Attribuzione 4.0 Internazionale (CC BY 4.0)