# Queries mit PromQL

PromQL wird benutzt um aus einer Prometheus Time-Series-Database (TSD) Daten
abzufragen.

Die Daten liegen als Metriken vor, die bei jedem erneuten Abruf (scrape) von den
Exportern aktualisiert werden. Dabei wird den Metriken jeweils der aktuelle
Timestamp hinzugefügt. Über PromQL lässt sich daher sehr einfach die Veränderung
der Metriken über die Zeit nachverfolgen.

Zusätzlich zu den Metriken selber werden Attribute (label) gesetzt um die Metrik
genauer zu beschreiben.

```promql
> node_cpu_seconds_total
node_cpu_seconds_total{cpu="0", instance="server:9100", job="node", mode="idle"}	 206390.26
node_cpu_seconds_total{cpu="0", instance="server:9100", job="node", mode="iowait"}	 23.46
node_cpu_seconds_total{cpu="0", instance="server:9100", job="node", mode="irq"}	 0
node_cpu_seconds_total{cpu="0", instance="server:9100", job="node", mode="nice"}	 6.45
node_cpu_seconds_total{cpu="0", instance="server:9100", job="node", mode="softirq"} 13.44
node_cpu_seconds_total{cpu="0", instance="server:9100", job="node", mode="steal"}	 0
node_cpu_seconds_total{cpu="0", instance="server:9100", job="node", mode="system"}	 804.72
node_cpu_seconds_total{cpu="0", instance="server:9100", job="node", mode="user"}	 1166.13
node_cpu_seconds_total{cpu="1", instance="server:9100", job="node", mode="idle"}	 206535.23
node_cpu_seconds_total{cpu="1", instance="server:9100", job="node", mode="iowait"}	 15.85
node_cpu_seconds_total{cpu="1", instance="server:9100", job="node", mode="irq"}	 0
node_cpu_seconds_total{cpu="1", instance="server:9100", job="node", mode="nice"}	 16.85
node_cpu_seconds_total{cpu="1", instance="server:9100", job="node", mode="softirq"} 11.24
node_cpu_seconds_total{cpu="1", instance="server:9100", job="node", mode="steal"}	 0
node_cpu_seconds_total{cpu="1", instance="server:9100", job="node", mode="system"}	 828
node_cpu_seconds_total{cpu="1", instance="server:9100", job="node", mode="user"}	 1201.18
```

Wie bei der Ausgabe ersichtlich sind für `node_cpu_seconds_total` 3 Attribute
gesetzt: `instance`, `job` und `mode`

Um auf ein oder mehrer Attribute zu filtern werden sie hinter der Metrik in
geschweiften Klammern angegeben.

```promql
> node_cpu_seconds_total{mode="user"}
node_cpu_seconds_total{cpu="0", instance="server:9100", job="node", mode="user"}	 1166.13
node_cpu_seconds_total{cpu="1", instance="server:9100", job="node", mode="user"}	 1201.18
```

Hierdurch wird die Ausgabe eingeschränkt.

Um die Anzahl der CPU Kerne herauszufinden könnte reicht die Zählung der
Ergebniszeilen (`count`).

```promql
> count (node_cpu_seconds_total)
```

Allerdings nur solange es nicht mehrere Instanzen
gibt. Bei einer zusätzlichen Instanz mit gleicher Anzahl an CPUs würde nicht
2 pro Instanz ausgegeben, sondern nur 4, da die Zeilen zusammengezählt werden.

Das richtige Ergebnis erhält man nur, wenn man den `count` nur auf die gleiche
Instanz anwendet, also eine Gruppierung auf die Instanz vornimmt.

```promql
> count by (instanc) (node_cpu_seconds_total)
node_cpu_seconds_total{instance="server:9100"} 2
```

Sollte der Wert häufiger benötigt werden, machen eine 'recording rule' Sinn.
Hierbei werden - parallel zum Abholen neuer Metriken durch den Prometheus
Server - auch auf Grund der recording rules eigene Metriken berechnet. Dies
verhindert, dass oft genutzte Werte immer wieder innerhalb der PromQL Queries
erneut berechnet werden.

```yaml
groups:
  - name: cpu
    rules:
      - record: instance:node_cpu_seconds_total:count
        expr: count by (instance) (node_cpu_seconds_total{mode="user"})
```

Diese recording rule definiert eine neue Metrik
`instance:node_cpu_seconds_total:count`, die genau der im vorherigen Bespiel
erzeugten Abfrage entspricht.

Um diese recording rule zu aktivieren wird sie in eine `yaml` Datei gepackt und
über `rules_file` in der Prometheus Konfiguration geladen.

Mit dieser Metrik ist es dann recht enfach die Load der Instanzen
(`node_load1`), die die Summer der Loads aller Scheduler darstellt, durch die
Anzahl der Scheduler (= Anzahl der CPU Kerne) zu teilen und einen vergleichbaren
Wert für alle Instanzen zu haben. Wir müssen dann nicht mehr wissen wieviele CPU
Kerne die Instanzen haben, da alles relativ zu einem CPU Kern dargestellt wird.

Eigentlich ist es nur die Division der Load (`node_load1`) durch unsere Metrik
(`instance:node_cpu_seconds_total:count`).

Allerdings haben die beiden Werte nicht alle Attribute gleich. `node_load1` hat
noch das zusätzliche Attribut `job`. Dieses gibt es bei
`instance:node_cpu_seconds_total:count` nicht.

Daher ist bei der Division dieses Attribut zu ignorieren oder die Division nur
auf das Attribut `intance` anzuwenden.

```yaml
> node_load1 / ignoring(mode) instance:node_cpu_seconds_total:count
> node_load1 / on(instance) instance:node_cpu_seconds_total:count
```
