# Graaf


[Graaf](https://gitlab.science.ru.nl/cncz/go/-/blob/main/cmd/graaf/) is a Go program that translates
simple dashboards written in YAML to Grafana JSON. It has an extensive [manual
page](https://gitlab.science.ru.nl/cncz/go/-/blob/main/cmd/graaf/graaf.1) that explains its usage.
This is also known as Grafana as code, but then for real.

The following is a dashboard with 4 panels that I use for my own monitoring.

~~~ yaml
title: Overview i
uid: dashboard-overview
panels:
  - timeseries:
      title: 'Network Bytes [5m] - edgemax.i'
      y:
        unit: Bps
      exprs:
        - expr: 'rate(ifHCOutOctets{ifAlias="eth0",job="edgemax"}[5m])'
          legend: '{{ifAlias}} transmit'
        - expr: 'rate(ifHCInOctets{ifAlias="eth0",job="edgemax"}[5m])'
          legend: '{{ifAlias}} receive'
          transform: negative-y
  - timeseries:
      title: 'HTTPS Queries [5m]'
      y:
        unit: rps
      exprs:
        - expr: 'sum by (host) (rate(caddy_http_request_count_total{job="caddy"}[5m]))'
          legend: '{{host}}'
        - expr: 'sum (rate(caddy_http_request_count_total{job="caddy"}[5m]))'
          legend: total
          transform: negative-y
  - timeseries:
      title: 'DNS Queries [5m]'
      y:
        unit: rps
      exprs:
        - expr: 'sum by (zone) (rate(coredns_dns_requests_total{job="nsdns",zone!="dropped"}[5m]))'
          legend: '{{zone}}'
        - expr: 'sum (rate(coredns_dns_requests_total{job="nsdns"}[5m]))'
          legend: total
          transform: negative-y
        - expr: 'sum (rate(coredns_dns_requests_total{job="nsdns",zone="dropped"}[5m]))'
          legend: dropped
          transform: negative-y
  - timeseries:
      title: 'Network Bytes [5m] - nuc.i'
      y:
        unit: Bps
      exprs:
        - expr: 'rate(node_network_transmit_bytes_total{job="node",device="eno1"}[5m])'
          legend: '{{device}} transmit'
          threshold: 'ok{value="0"}'
        - expr: 'rate(node_network_receive_bytes_total{job="node",device="eno1"}[5m])'
          legend: '{{device}} receive'
          transform: negative-y
~~~

This dashboard is 47 lines, the generated JSON dashboard is 500 lines, a ~10-fold reduction in
cruft. Not bad!

## Configure Grafana

In the graaf(1) manual page it is explained how to configure Grafana, so that graaf(1) will actually
work. Repeated here for easier search indexing.

For Grafana to work you only may use OrgID 1 and provision the datasource and dashboards via the
following YAML config:

In `.../provisioning/dashboards/dashboards.yaml`, put:

~~~ yaml
apiVersion: 1

providers:
 - name: 'default'
   orgId: 1
   folder: ''
   folderUid: ''
   type: file
   options:
     path: /var/lib/grafana/dashboards
~~~

And save the output of `graaf` in /var/lig/grafana/dashboards. Next configure a datasource in
`../provisioning/datasources/prometheus.yaml`:

~~~ yaml
apiVersion: 1

datasources:
- name: Prometheus
  type: prometheus
  access: proxy
  orgId: 1
  url: http://localhost:9090
  isDefault: true
~~~

For good measure erase the grafana database: `rm /var/lib/grafana/grafana.db` and restart grafana.
If you want to set a default 'home' dashboard use:

~~~ ini
[dashboards]
default_home_dashboard_path = /var/lib/grafana/dashboards/mydashboard.json
~~~

in `/etc/grafana/grafana.ini`.

