Grafana - Daten aus einem Array auswerten

Falc410

Vice Admiral
Registriert
Juni 2006
Beiträge
6.420
Ich bin leider ein absoluter Grafana Anfänger. Betreiben es an einer Elasticsearch Datenbank.
Dort habe ich mehrere Einträge und Feld ist (fiktives Beispiel) Farben. Da kann ich ähnlich wie bei Tags eine Liste zuweisen und in Elastic wird das als Array gespeichert. Die Einträge könnten dann z.B. folgendermaßen aussehen (JSON natürlich):

_index: test _id: 1 farben: ["Rot", "Grün"]
_index: test _id: 2 farben: ["Rot"]
_index: test _id: 3 farben: ["Blau", "Grün"]

Jetzt würden wir in Grafana gerne zählen wie oft "Rot" oder "Blau" oder "Grün" vorkommt. Problem ist aber, dass Grafana die Werte aus einem Array nicht aufsplittet. Das heißt in diesem Beispiel wären es 3 verschiedene Werte und nicht Rot: 2, Blau: 1, Grün: 2

Kurze Suche mit Google sagt wohl, dass das nicht geht. Vorschlag von meinem Kollegen, wir legen 3 Felder an, für Rot, Grün, Blau und speichern das alles einzeln. Grundsätzlich kein Problem, nur ist die Anzahl der Farben theoretisch unlimitiert. Haben uns dann überlegt ob wir einfach nur die Top 5 auswerten und 5 Felder in der Datenbank anlegen. Finde ich aber ziemlich unschön aus Backend-Sicht

Hat da jemand eine bessere Idee?
 
Wie gesagt, es ist eine Elasticsearch Datenbank die abgefragt wird. Ich bin aber weder ein Elasticsearch Experte, noch kenne ich mich wirklich mit Grafana aus.
Ich bekomme aus Elasticsearch JSON raus wenn ich über die API darauf zugreife (also z.B. auf curl GET test/_doc/$ID). Verkürztes Beispiel für ID 77933:
JSON:
{
    "_index": "issues",
    "_type": "_doc",
    "_id": "77933",
    "_version": 1037,
    "_seq_no": 2328494,
    "_primary_term": 2,
    "found": true,
    "_source": {
        "id": "77933",
        "created": "2022-06-30T19:42:02+0200",
      
        "farben": [
            "Blau"
        ]
    }
}

Da das Array also beliebig lang sein kann, müsste Grafana jetzt über die Werte iterieren und diese einzeln verfügbar machen. Kibana kann das angeblich (muss ich selbst noch testen).
 
Versuche es mal mit Elasticsearchs "Terms Aggregation", zumindest für normale String-Werte habe ich das schon häufiger genutzt. Sollte aber auch mit Arrays funktionieren, weil ES bzw. Lucene das Array vor dem Indizieren auseinandernimmt, und jeden Array-Eintrag separat als Index-Key benutzt.

https://www.elastic.co/guide/en/ela...#search-aggregations-bucket-terms-aggregation

In deinem Fall dann also in etwa:
Code:
{
  "aggs": {
    "my_key_name_for_the_aggregation": {
      "terms": { "field": "farben" }
    }
  }
}

Mit Grafana kenne ich mich leider nicht wirklich aus, aber vielleicht lässt sich da ja auch zur Not ein manuelles Query hinterlegen.

EDIT: Das könnte evtl. weiterhelfen:
https://github.com/grafana/grafana/issues/5428

EDIT2:
Möglicherweise musst du den Mapping type für "farben" noch anpassen, damit das funktioniert - bzw. einen zusätzlichen type hinzufügen. "keyword" wäre hier sinnvoll, damit ES den String als Ganzes benutzt, und nicht analysiert. https://www.elastic.co/guide/en/elasticsearch/reference/current/keyword.html
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: tomgit und Falc410
Das hört sich spannend an und könnte die Lösung sein. Danke dir!

Wie gesagt, mit Elastic kenne ich mich nicht aus und ich hab den Index automatisch erstellen lassen. Da gibt es sicher noch einige Dinge ich einstellen könnte oder vielleicht auch müsste. Ich werde das mal testen.

Die Frage ist nur wie ich das in Grafana rein bekomme und im Moment geht es noch nicht weil:
Code:
root_cause": [

            {

                "type": "illegal_argument_exception",

                "reason": "Text fields are not optimised for operations that require per-document field data like aggregations and sorting, so these operations are disabled by default. Please use a keyword field instead. Alternatively, set fielddata=true on [t_label] in order to load field data by uninverting the inverted index. Note that this can use significant memory."

            }

Edit:

Mein Fehler ich muss natürlich nicht t_label sondern t_label.keyword angeben. Nun spuckt die Suche am Ende Aggregations aus und genau das was ich möchte - jetzt ist nur noch die Frage - wie bekomme ich das in Grafana dargestellt. Aber wohl ein anderes Problem. Ich google mal nach Grafana und Elastic Aggregations!
 
Zuletzt bearbeitet:
Falc410 schrieb:
ich hab den Index automatisch erstellen lassen. Da gibt es sicher noch einige Dinge ich einstellen könnte oder vielleicht auch müsste.
Das Mapping solltest du definitiv von Hand überarbeiten. Elasticsearch erstellt das mit besten Wissen und Gewissen anhand des ersten Datensatzes für ein Feld, und das kann auch gerne mal nach hinten losgehen :D Z.B. wenn im ersten Datensatz einfach nur "2000-01-01" steht, dann wird für das Feld ein type für Datumsangaben benutzt, aber wenn alle anderen Datensätze da Text drin stehen haben, wird es Fehler regnen.

Und generell wird alles was nach Text aussieht erst mal als type "text" benutzt, also der Datentyp, der Strings (u.a. an Leerzeichen und Bindestrichen) auseinander nimmt und jedes Wort einzeln indiziert, damit man schöne Textsuchen darauf machen kann. In 90% der Fälle ist das sicherlich auch gut und richtig so.
Aber hier in deinem Fall willst du aggregieren, und da könnte es dann problematisch werden, wenn "grün-blau" vom Analyzer als "grün" und "blau" auseinander genommen wird, und dann eben auch "grün" und "blau" im Index landet, und nicht "grün-blau". Daher der Vorschlag den type "keyword" zu benutzen, weil dann die Strings genau so wie sie sind im Index landen.

Man kann aber auch einfach beides haben. Elasticsearch bietet dafür "Multi Fields", damit kann man dann sagen, dass "farben" vom type "text" ist, und zusätzlich kann man noch beliebig viele weitere types angeben, so dass man dann z.B. über "farben.keyword" auf dieselben Daten als type "keyword" zugreifen kann:
Code:
{
  "mappings": {
    "properties": {
      "farben": { // dein property name
        "type": "text", // der standard type
        "fields": {
          "keyword": { // der name für einen weiteren type, hier also effektiv dann "farben.keyword"
            "type": "keyword" // der type für diesen zusätzlichen type
          }
        }
      }
    }
  }
}
 
  • Gefällt mir
Reaktionen: Falc410
Ja damit muss ich mich auf jeden Fall noch beschäftigen. Bis jetzt hat es ganz gut funktioniert. Hatte einmal ein Problem, dass Elasticsearch zu viele Felder erstellt weil ich verschachteltes JSON hatte und dann explodierte alles :)

Aber im Moment für meine "Farben" wurde auch automatisch ein farben.keyword Eintrag wohl angelegt und damit funktioniert die Term Aggregation, also in der Ausgabe bei einer Suche kommt genau das was ich möchte. Ich habe nur keine Ahnung wie ich das in Grafana reinbekomme - da fehlen mir die Grafana Skills.

https://grafana.com/docs/grafana/latest/datasources/elasticsearch/
Bildschirmfoto 2022-07-11 um 13.35.11.png

Hier steht zwar etwas beschrieben, aber in Grafana macht man Lucene Queries und die haben wohl ein anderes Format. Wenn ich den Searchterm aus der Doku rüberkopiere bekomme ich einen Parsing Fehler.

Aber über curl bzw. ich nutze ElasticVue im Browser, funktioniert es. Genau was ich brauche. Jetzt muss ich es nur noch irgendwie in Grafana reinbekommen. Aber du hast mir schon einmal viel weiter geholfen.

Und einen Elasticsearch Crashcourse sollte ich mir auch mal geben :) Wobei ich auf AWS Opensearch wechseln werde, damit die ganze Cluster Administration schon einmal wegfällt.


Bildschirmfoto 2022-07-11 um 14.09.11.png



P.S. Den Feature Request hatte ich auch schon gefunden, ist halt von 2016 - ich denke das ist schon eingebaut. Siehe auch die offizielle Grafana Doku bzgl. Elasticsearch
 
Falc410 schrieb:
Den Feature Request hatte ich auch schon gefunden, ist halt von 2016 - ich denke das ist schon eingebaut.
Aber dann sollte das in Grafana doch eigentlich einfach zusammenklickbar sein, ohne dass man noch groß manuell ein Query braucht. Zumindest war das immer mein Eindruck von Grafana, wirklich mit gearbeitet habe ich noch nicht :D

Aber bestimmt findet sich ja noch jemand hier im Forum, der mehr Ahnung von Grafana hat.

EDIT: bzgl. deines Doku Screenshots. Ich denke, dass es da eher um "Terms Query" geht, und nicht um "Terms Aggregation". Um Treffer zusammenzuzählen brauchst du aber Aggregation. Mit Query kann man nur Dokumente filtern.
 
  • Gefällt mir
Reaktionen: Falc410
Zurück
Oben