Οι τρεις κολώνες και το λεξιλόγιο

17 λεπτά
Κοινό
αρχάριοι, μάθημα 01 διαβασμένο
Διάρκεια
35 έως 45 λεπτά
Ενότητα
1/7
Στόχος δεξιότητας
να αναγνωρίζεις τους τέσσερις τύπους μετρικών Prometheus πάνω στις πραγματικές γραμμές του /metrics του API του εργαστηρίου, να κατανοείς τα labels και την πληθικότητα, να διακρίνεις pull και push, να διαβάζεις μια γραμμή log JSON πεδίο προς πεδίο, και να τοποθετείς τις δέκα υπηρεσίες του εργαστηρίου με τη θύρα και το URL τους

Σε μια εικόνα

Ξαναπιάσε το ταμπλό του αυτοκινήτου από το μάθημα 01. Ο χιλιομετρητής μόνο αυξάνεται: είναι ένας μετρητής (counter), όπως το http_requetes_total. Ο δείκτης βενζίνης ανεβαίνει στο γέμισμα και κατεβαίνει στην οδήγηση: είναι ένας δείκτης στιγμιαίας τιμής (gauge), όπως το requetes_en_cours. Το βιβλίο συντήρησης που σημειώνει «12 διαδρομές κάτω από 10 km, 30 κάτω από 50 km, 3 πάνω από 100 km» ταξινομεί κάθε διαδρομή σε μια ζώνη: είναι ένα ιστόγραμμα, όπως το http_duree_requete_seconds. Και το μαύρο κουτί, που γράφει μια γραμμή ανά συμβάν με την ακριβή ώρα, είναι το log JSON του API. Ο Prometheus δεν λαμβάνει τίποτα: είναι αυτός που έρχεται να διαβάσει τους μετρητές κάθε 15 δευτερόλεπτα, όπως ένας ελεγκτής που περνά να καταγράψει τους μετρητές κάθε αυτοκινήτου του στόλου.

Πώς λειτουργεί

Οι τέσσερις τύποι μετρικών, πάνω στις πραγματικές γραμμές του εργαστηρίου

Μια μετρική Prometheus έχει πάντα ένα όνομα, ενδεχομένως labels, και μια αριθμητική τιμή. Ο τύπος λέει πώς να διαβάσεις αυτή την τιμή στον χρόνο. Ο Prometheus γνωρίζει τέσσερις: τον μετρητή, το gauge, το ιστόγραμμα και την περίληψη (summary). Οι τρεις πρώτοι χρησιμοποιούνται από το API καταλόγου· ο τέταρτος όχι, και ο λόγος είναι διδακτικός. Όλες οι παρακάτω γραμμές έχουν αντιγραφεί από το http://localhost:8000/metrics στο μηχάνημα του μαθήματος· οι τιμές θα είναι διαφορετικές σε σένα.

Μετρητής (counter). Ένας μετρητής μόνο αυξάνεται, ή ξαναρχίζει από το μηδέν αν η υπηρεσία επανεκκινήσει. Μετρά συσσωρευμένα συμβάντα. Το API εκθέτει το http_requetes_total, με τρία labels: τον κωδικό απόκρισης, τη μέθοδο HTTP και τη διαδρομή:

text
# HELP http_requetes_total Nombre de requêtes HTTP reçues, par méthode, route normalisée et code de réponse.
# TYPE http_requetes_total counter
http_requetes_total{code="200",methode="GET",route="/cours"} 3247.0
http_requetes_total{code="201",methode="POST",route="/inscriptions"} 855.0
http_requetes_total{code="404",methode="GET",route="/cours/{id}"} 210.0
http_requetes_total{code="500",methode="GET",route="/cours"} 32.0

Αυτό που δεν κάνεις ποτέ με έναν μετρητή: να διαβάσεις την ακατέργαστη τιμή του για να πεις «υπάρχουν 3247 αιτήματα αυτή τη στιγμή». Ένας μετρητής δεν κατεβαίνει ποτέ· αυτό που σε ενδιαφέρει είναι η ταχύτητα αύξησής του, υπολογισμένη με τη συνάρτηση rate() (ενότητα 2). Τεκμηρίωση: Prometheus — Metric types, Counter.

Gauge. Ένα gauge ανεβαίνει και κατεβαίνει ελεύθερα: μια τιμή σε μια δεδομένη στιγμή. Το API εκθέτει το requetes_en_cours, τον αριθμό αιτημάτων που βρίσκονται υπό επεξεργασία την ακριβή στιγμή της καταγραφής:

text
# HELP requetes_en_cours Nombre de requêtes HTTP en cours de traitement à cet instant.
# TYPE requetes_en_cours gauge
requetes_en_cours 1.0

Ένα αίτημα είναι σε εξέλιξη τη στιγμή της καταγραφής· την επόμενη στιγμή, αυτός ο αριθμός μπορεί να είναι 0 ή 4. Το API εκθέτει επίσης gauges ρύθμισης, των οποίων η τιμή είναι περισσότερο πληροφορία παρά μέτρηση: api_info{version="1.0.0"} 1.0 (η έκδοση βρίσκεται στο label, η τιμή είναι πάντα 1) και api_panne_taux_erreurs 0.01 (το μερίδιο αιτημάτων που το API κάνει επίτηδες να αποτύχουν: 1 % σε κανονική λειτουργία). Τεκμηρίωση: Prometheus — Metric types, Gauge.

Ιστόγραμμα (histogram). Ένα ιστόγραμμα μετρά την κατανομή μιας τιμής, όπως τη διάρκεια ενός αιτήματος HTTP: πόσα αιτήματα πήραν λιγότερο από 5 ms, λιγότερο από 10 ms, λιγότερο από 25 ms…; Το API εκθέτει το http_duree_requete_seconds. Αντίθετα με έναν μετρητή ή ένα gauge, ένα ιστόγραμμα δημοσιεύει πολλές γραμμές για μια μόνο μετρική: έναν μετρητή ανά ζώνη (bucket), πλέον ένα συνολικό πλήθος και ένα άθροισμα. Εδώ είναι οι δώδεκα γραμμές της διαδρομής /cours:

text
# HELP http_duree_requete_seconds Durée de traitement des requêtes HTTP, en secondes, par route normalisée.
# TYPE http_duree_requete_seconds histogram
http_duree_requete_seconds_bucket{le="0.005",route="/cours"} 32.0
http_duree_requete_seconds_bucket{le="0.01",route="/cours"} 74.0
http_duree_requete_seconds_bucket{le="0.025",route="/cours"} 1566.0
http_duree_requete_seconds_bucket{le="0.05",route="/cours"} 3248.0
http_duree_requete_seconds_bucket{le="0.1",route="/cours"} 3276.0
http_duree_requete_seconds_bucket{le="0.25",route="/cours"} 3278.0
http_duree_requete_seconds_bucket{le="0.5",route="/cours"} 3279.0
http_duree_requete_seconds_bucket{le="1.0",route="/cours"} 3279.0
http_duree_requete_seconds_bucket{le="2.0",route="/cours"} 3279.0
http_duree_requete_seconds_bucket{le="+Inf",route="/cours"} 3279.0
http_duree_requete_seconds_count{route="/cours"} 3279.0
http_duree_requete_seconds_sum{route="/cours"} 85.42293146001248

Κάθε _bucket{le="…"} (le για less or equal) μετρά τα αιτήματα ταχύτερα ή ίσα με αυτό το κατώφλι, με σωρευτικό τρόπο: τα 32 αιτήματα κάτω από 5 ms μετριούνται και στα 74 κάτω από 10 ms, και στα 3279 του κάδου +Inf (όλα). Το _count είναι ο συνολικός αριθμός παρατηρήσεων (3279, ίσος με τον κάδο +Inf), το _sum το άθροισμα όλων των διαρκειών (85,4 δευτερόλεπτα συνολικά, δηλαδή 26 ms κατά μέσο όρο ανά αίτημα). Αυτό είναι που επιτρέπει να ανακατασκευάσεις ένα ποσοστημόριο εκ των υστέρων, με το histogram_quantile() (ενότητα 2). Άμεση ανάγνωση: 3248 αιτήματα από τα 3279 πήραν λιγότερο από 50 ms, δηλαδή 99 %. Τεκμηρίωση: Prometheus — Metric types, Histogram.

Περίληψη (summary), και γιατί το εργαστήριο δεν τη χρησιμοποιεί. Μια περίληψη μετρά επίσης μια κατανομή, αλλά υπολογίζει τα ποσοστημόριά της απευθείας μέσα στο παρατηρούμενο πρόγραμμα, πριν τα δημοσιεύσει: μια γραμμή {quantile="0.5"}, μια γραμμή {quantile="0.9"}, πλέον _sum και _count. Το πρόβλημα: ένα ποσοστημόριο υπολογισμένο στην πλευρά του πελάτη δεν μπορεί να ανασυνδυαστεί με αυτό μιας άλλης instance. Αν το εργαστήριο έτρεχε τρία αντίγραφα του API, δεν θα μπορούσες να πάρεις τον μέσο όρο των τριών quantile="0.9" για να πάρεις το πραγματικό 90ό εκατοστημόριο του συνόλου. Ένα ιστόγραμμα δημοσιεύει ακατέργαστους μετρητές ανά ζώνη: ο Prometheus μπορεί να τους προσθέσει μεταξύ instances πριν υπολογίσει το ποσοστημόριο. Δεν υπάρχει λοιπόν καμία γραμμή summary στο /metrics του API του εργαστηρίου. Τεκμηρίωση: Prometheus — Histograms and summaries.

ΤύποςΤι μετράΣτο εργαστήριοΕρώτηση στην οποία απαντά
ΜετρητήςΜια συσσώρευση που μόνο αυξάνεταιhttp_requetes_total, inscriptions_total, cours_consultes_total«Πόσα αιτήματα ανά δευτερόλεπτο;» (με rate)
GaugeΜια στιγμιαία τιμή που ανεβαίνει και κατεβαίνειrequetes_en_cours, api_disque_libre_octets, api_info«Πόσα αυτή τη στιγμή;»
ΙστόγραμμαΜια κατανομή, σε σωρευτικές ζώνεςhttp_duree_requete_seconds«Το 95 % των αιτημάτων παίρνει λιγότερο από πόσο;»
ΠερίληψηΜια κατανομή, ποσοστημόρια υπολογισμένα στην πλευρά του πελάτηκαμίαΗ ίδια, αλλά χωρίς δυνατότητα συνάθροισης μεταξύ instances

Χρονοσειρά, labels και πληθικότητα

Κάθε μοναδικός συνδυασμός ονόματος μετρικής και labels σχηματίζει μια χρονοσειρά: μια ακολουθία ζευγών (χρονοσφραγίδα, τιμή) που ο Prometheus αποθηκεύει και ερωτά. Το http_requetes_total{code="200",methode="GET",route="/cours"} είναι μια σειρά· το http_requetes_total{code="201",methode="POST",route="/inscriptions"} είναι μια άλλη. Στο μηχάνημα του μαθήματος, το http_requetes_total αριθμεί 14 σειρές (14 συνδυασμοί κωδικού, μεθόδου και διαδρομής που εμφανίστηκαν από την εκκίνηση). Τα labels επιτρέπουν να φιλτράρεις και να ομαδοποιείς χωρίς να αλλάζεις το όνομα: «τα σφάλματα διακομιστή, μόνο στο /inscriptions» γράφεται http_requetes_total{route="/inscriptions",code=~"5.."}. Τεκμηρίωση: Prometheus — Data model.

Η πληθικότητα (cardinality) μιας μετρικής είναι ο αριθμός διακριτών σειρών που παράγει. Το http_requetes_total{code,methode,route}, με πέντε κωδικούς, δύο μεθόδους και επτά διαδρομές σε πρότυπο, δίνει το πολύ μερικές δεκάδες σειρές. Κοίτα το log του βήματος 2 του μαθήματος 01: το αίτημα κάλεσε το /cours/C0038, αλλά η μετρική φέρει route="/cours/{id}", το πρότυπο της διαδρομής όπως το δήλωσε το FastAPI. Αν το label περιείχε το πραγματικό αναγνωριστικό, κάθε μάθημα που θα ανοιγόταν θα δημιουργούσε μια σειρά: 64 μαθήματα × 5 κωδικοί × 2 μέθοδοι. Σε έναν πραγματικό κατάλογο δεκάδων χιλιάδων μαθημάτων, η μετρική θα εκρηγνυόταν και ο Prometheus θα επιβραδυνόταν. Ο κανόνας: ένα label πρέπει να έχει έναν φραγμένο και λογικό αριθμό τιμών· ένα μοναδικό αναγνωριστικό, μια διεύθυνση IP ή μια χρονοσφραγίδα δεν έχουν καμία θέση σε ένα label. Μια διαδρομή που δεν υπάρχει μετριέται κάτω από route="inconnue", ποτέ κάτω από την πραγματική της διαδρομή, για τον ίδιο λόγο.

Το εργαστήριο περιέχει επίτηδες μια διδακτική εξαίρεση: το inscriptions_total{cours_id="C0028"} και το cours_consultes_total{cours_id="…"} έχουν ένα label ανά μάθημα. Με 64 μαθήματα, παραμένει φραγμένο (64 σειρές το καθένα). Με ένα εκατομμύριο μαθήματα, θα ήταν λάθος. Το εργαστήριο έχει άλλωστε μια ειδοποίηση PrometheusTropDeSeries που ηχεί πάνω από 100 000 σειρές. Τεκμηρίωση: Prometheus — Instrumentation, cardinality.

Pull, scrape, target, exporter, job, instance

Ο Prometheus λειτουργεί σε pull (πηγαίνει να πάρει): ερωτά ο ίδιος, κάθε 15 δευτερόλεπτα στο εργαστήριο (scrape_interval: 15s στο prometheus/prometheus.yml), το URL /metrics κάθε υπηρεσίας που επιτηρεί. Είναι το αντίστροφο ενός συστήματος push, όπου η παρατηρούμενη υπηρεσία στέλνει τις μετρικές της σε έναν συλλέκτη. Το pull έχει ένα άμεσο πλεονέκτημα: αν μια υπηρεσία δεν απαντά πλέον, ο Prometheus το ξέρει αμέσως, η μετρική up περνά σε 0, χωρίς να εξαρτάται από την υπηρεσία που έχει βλάβη για να σηματοδοτήσει η ίδια την απουσία της. Αυτό ακριβώς σε κάνει να προκαλέσεις η πρακτική αυτής της ενότητας με το casser api.

ΌροςΤι είναιΣτο εργαστήριο
scrapeΜια ανάγνωση του /metrics από τον PrometheusΚάθε 15 s, σε καθέναν από τους 8 στόχους
target (στόχος)Ένα URL /metrics που διαβάζει ο Prometheushttp://api:8000/metrics, http://node-exporter:9100/metrics
exporterΈνα πρόγραμμα που εκθέτει σε μορφή Prometheus τις μετρικές ενός συστήματος που δεν τη μιλά εγγενώςnode-exporter (το μηχάνημα-οικοδεσπότης), cadvisor (τα containers)
jobΜια ομάδα στόχων που κάνουν την ίδια δουλειάjob="api", job="prometheus", job="loki"… 8 jobs
instanceΈνας μεμονωμένος στόχος μέσα σε ένα jobinstance="api:8000"
upΗ μετρική που κατασκευάζει ο ίδιος ο Prometheus σε κάθε scrape: 1 αν ο στόχος απάντησε, 0 αλλιώςΤο up{job="api"} ισούται με 1 σε κανονική λειτουργία

Τα ονόματα api:8000, node-exporter:9100 είναι αυτά του εσωτερικού δικτύου του Docker Compose: είναι ο Prometheus, μέσα στο container του, που μιλά στο API μέσα στο δικό του. Από τον υπολογιστή σου, η ίδια σελίδα είναι http://localhost:8000/metrics. Τεκμηρίωση: Prometheus — Configuration, scrape_config και Prometheus — Jobs and instances.

Τα δομημένα logs: μια γραμμή JSON ανά συμβάν

Ένα δομημένο log γράφεται σε μια μορφή που η μηχανή τεμαχίζει χωρίς να μαντεύει (JSON, τις περισσότερες φορές), αντί για μια ελεύθερη φράση. Το API γράφει στην τυπική έξοδό του μια γραμμή JSON ανά επεξεργασμένο αίτημα. Εδώ είναι μια πραγματική γραμμή, διαβασμένη με .\labo.ps1 journal api στο μηχάνημα του μαθήματος:

json
{"horodatage": "2026-09-15T19:33:25.839+00:00", "niveau": "INFO", "id_requete": "46bb533b33e9", "methode": "GET", "route": "/cours/{id}", "code": 200, "duree_ms": 13.9, "message": "GET /cours/C0038 -> 200"}
ΠεδίοΠαράδειγμαΤι είναι
horodatage2026-09-15T19:33:25.839+00:00Η ακριβής στιγμή του συμβάντος, σε μορφή ISO 8601, σε UTC (+00:00)
niveauINFOΗ σοβαρότητα: INFO (2xx), WARNING (404, 422), ERROR (500). Τρεις τιμές στο εργαστήριο
id_requete46bb533b33e9Ένα μοναδικό αναγνωριστικό 12 χαρακτήρων που παράγεται για αυτό το αίτημα, επιστρέφεται στον πελάτη στην κεφαλίδα HTTP x-id-requete
methodeGETΗ μέθοδος HTTP
route/cours/{id}Το πρότυπο της διαδρομής, το ίδιο με αυτό της μετρικής
code200Ο κωδικός απόκρισης HTTP
duree_ms13.9Η διάρκεια επεξεργασίας, σε χιλιοστά του δευτερολέπτου
messageGET /cours/C0038 -> 200Η αναγνώσιμη φράση: εδώ, και μόνο εδώ, εμφανίζεται το πραγματικό αναγνωριστικό του μαθήματος

Τι πρέπει να δεις: το route κρατά το πρότυπο /cours/{id} (όπως η μετρική), αλλά το message περιέχει C0038, το πραγματικό αναγνωριστικό. Ένα log μπορεί να επιτρέψει στον εαυτό του αυτή τη λεπτομέρεια: το Loki δεν ευρετηριάζει το κείμενο του μηνύματος, ευρετηριάζει μόνο τέσσερα labels (service, conteneur, niveau, code) που εξάγει το Alloy. Η ενότητα 5 σου δείχνει πώς το Alloy διαβάζει το JSON και κατασκευάζει αυτά τα labels. Τεκμηρίωση: Grafana Loki — Labels.

Οι άλλες υπηρεσίες του εργαστηρίου δεν γράφουν όλες JSON. Το webhook, στην εκκίνηση, γράφει ελεύθερο κείμενο: INFO: Uvicorn running on http://0.0.0.0:8090 (Press CTRL+C to quit). Η υπηρεσία charge γράφει JSON, αλλά με άλλα πεδία: κάθε 30 δευτερόλεπτα, μια περίληψη {"niveau": "INFO", "message": "résumé des 30 dernières secondes", "requetes": {"200": 214, "total": 262, "201": 26, "500": 4, "404": 16, "422": 2}}. Ένα δομημένο log δεν είναι μια παγκόσμια μορφή: είναι μια απόφαση που λαμβάνεται υπηρεσία προς υπηρεσία.

Τα traces: αναφορά, κανένα εργαλείο σε αυτό το εργαστήριο

Ένα trace ακολουθεί ένα μοναδικό αίτημα μέσα από πολλές υπηρεσίες: κάθε βήμα (ένα span) καταγράφει το όνομά του, τη διάρκειά του, και τη σχέση γονέα-παιδιού με τα άλλα. Απαντά στο «το αίτημα πήρε 800 ms, σε ποια υπηρεσία δαπανήθηκε αυτός ο χρόνος;». Το εργαστήριο δεν εγκαθιστά κανένα εργαλείο ιχνηλάτησης: το API καταλόγου και η γεννήτρια φορτίου είναι οι δύο μόνες εφαρμογές, συνδεδεμένες με μια απλή κλήση HTTP, γεγονός που περιορίζει το παιδαγωγικό ενδιαφέρον ενός κατανεμημένου trace εδώ. Το id_requete του log είναι ήδη το πρώτο κομμάτι ενός trace: αυτό θα το έλεγε το OpenTelemetry trace id. Η ενότητα 7 λέει μια λέξη παραπάνω. Τεκμηρίωση: OpenTelemetry — Traces.

Οι δέκα υπηρεσίες: ρόλος, θύρα, URL

ΥπηρεσίαΡόλοςΘύραURL από τον υπολογιστή σου
prometheusΔιαβάζει τους στόχους, αποθηκεύει τις σειρές, αξιολογεί τους κανόνες9090http://localhost:9090
alertmanagerΛαμβάνει τις ειδοποιήσεις του Prometheus, τις ομαδοποιεί και τις δρομολογεί9093http://localhost:9093
grafanaΕξερευνά και οπτικοποιεί Prometheus, Loki και Alertmanager3000 (GRAFANA_PORT)http://localhost:3000 (admin / aiopsatlas2026)
lokiΑποθηκεύει τα logs, ευρετηριασμένα με labels3100http://localhost:3100/ready
alloyΑνακαλύπτει τα containers και μεταφέρει τα logs τους στο Loki12345http://localhost:12345
node-exporterΜετρικές του μηχανήματος-οικοδεσπότη9100http://localhost:9100/metrics
cadvisorΜετρικές κάθε container8080http://localhost:8080
apiΗ παρατηρούμενη υπηρεσία8000http://localhost:8000/cours · http://localhost:8000/metrics
webhookΛαμβάνει και εμφανίζει τις ειδοποιήσεις8090http://localhost:8090
chargeΠαράγει κίνηση προς το APIκαμίακαμία: δεν έχει διεπαφή, μόνο ένα ημερολόγιο (journal)

Εννέα θύρες, δέκα υπηρεσίες: το charge δεν ακούει σε τίποτα. Οκτώ στόχοι Prometheus, δέκα υπηρεσίες: το charge και το webhook δεν εκθέτουν /metrics.

Βήμα προς βήμα

Αυτό το βήμα προς βήμα υποθέτει ότι το εργαστήριο έχει ξεκινήσει (μάθημα 04). Αν διαβάζεις αυτό το μάθημα πριν, κράτησέ το για αργότερα: κάθε βήμα γίνεται στον περιηγητή ή σε ένα τερματικό, μόνο για ανάγνωση.

  1. Άνοιξε το http://localhost:8000/metrics στον περιηγητή. Είναι η ακατέργαστη σελίδα που ο Prometheus διαβάζει κάθε 15 δευτερόλεπτα: κείμενο, μια γραμμή ανά σειρά, με τις γραμμές # HELP και # TYPE πριν από αυτήν. Στο μηχάνημα του μαθήματος, αριθμεί 271 γραμμές. Σύγκρινε με το http://localhost:9100/metrics (node-exporter: 1578 γραμμές) και το http://localhost:8080/metrics (cAdvisor: 3444 γραμμές, για δέκα containers).

    Τι πρέπει να δεις: οι γραμμές που αρχίζουν με python_ και process_ στην κορυφή της σελίδας του API δεν γράφονται από το εργαστήριο. Η βιβλιοθήκη prometheus_client τις προσθέτει από μόνη της (μνήμη της διεργασίας, συλλέκτης απορριμμάτων Python). Οι μετρικές του μαθήματος αρχίζουν στο http_requetes_total.

  2. Ψάξε τα τέσσερα # TYPE του API. Στη σελίδα, ψάξε (Ctrl+F) # TYPE http_: βρίσκεις counter για το http_requetes_total και histogram για το http_duree_requete_seconds. Ψάξε # TYPE requetes_en_cours: gauge. Ψάξε summary: κανένα αποτέλεσμα.

    Τι πρέπει να δεις: οι τρεις τύποι που χρησιμοποιούνται, και η εκούσια απουσία του τέταρτου.

  3. Μέτρησε τις σειρές του http_requetes_total στον Prometheus. Άνοιξε το http://localhost:9090, πληκτρολόγησε http_requetes_total στο πεδίο ερωτήματος και εκτέλεσε. Στο μηχάνημα του μαθήματος, ο πίνακας εμφανίζει 14 γραμμές, ανάμεσά τους:

    text
    http_requetes_total{code="200", instance="api:8000", job="api", methode="GET", route="/cours", service="api"}   3241
    http_requetes_total{code="500", instance="api:8000", job="api", methode="GET", route="/cours", service="api"}   32

    Τι πρέπει να δεις: ο Prometheus πρόσθεσε τρία labels σε αυτά της σελίδας /metrics: job="api" και instance="api:8000" (που ταυτοποιούν τον στόχο) και service="api" (που προστίθεται από τη ρύθμιση του job στο prometheus.yml). Η τιμή 3241 είναι λίγο μικρότερη από το 3247 που διαβάστηκε στο βήμα 1: ο Prometheus δείχνει το τελευταίο scrape, που είναι 0 έως 15 δευτερόλεπτα πριν.

  4. Διάβασε μια γραμμή log του API στο τερματικό. Από τον φάκελο lab3:

    powershell
    .\labo.ps1 journal api

    Στο μηχάνημα του μαθήματος, οι τελευταίες γραμμές μοιάζουν με:

    text
    labo-api  | {"horodatage": "2026-09-15T19:33:25.916+00:00", "niveau": "INFO", "id_requete": "5ccaee4d1a2a", "methode": "GET", "route": "/sante", "code": 200, "duree_ms": 1.0, "message": "GET /sante -> 200"}
    labo-api  | {"horodatage": "2026-09-15T19:33:26.217+00:00", "niveau": "INFO", "id_requete": "e64206564a68", "methode": "GET", "route": "/cours/{id}", "code": 200, "duree_ms": 8.2, "message": "GET /cours/C0043 -> 200"}

    Τι πρέπει να δεις: το GET /sante κάθε λίγα δευτερόλεπτα είναι το Docker που ελέγχει την υγεία του container (το healthcheck)· τα υπόλοιπα είναι η υπηρεσία charge. Το πρόθεμα labo-api | προστίθεται από το Docker Compose, δεν ανήκει στο JSON.

  5. Έλεγξε τα labels που γνωρίζει το Loki. Άνοιξε το http://localhost:3100/loki/api/v1/labels:

    json
    {"status":"success","data":["code","conteneur","niveau","service"]}

    Μετά το http://localhost:3100/loki/api/v1/label/niveau/values:

    json
    {"status":"success","data":["ERROR","INFO","WARNING"]}

    Τι πρέπει να δεις: τέσσερα labels, όχι οκτώ. Το Loki δεν ευρετηριάζει ούτε το id_requete, ούτε το duree_ms, ούτε το message: αυτά τα πεδία μένουν στο κείμενο της γραμμής, όπου η LogQL μπορεί να τα εξαγάγει κατά παραγγελία με | json (ενότητα 5). Οι τρεις τιμές του niveau επιβεβαιώνουν τον πίνακα παραπάνω.

Αν κολλήσει

Τα παρακάτω μηνύματα προκλήθηκαν στα αλήθεια στον Prometheus, στο μηχάνημα του μαθήματος. Θα επανέλθουν στην ενότητα 2· καλύτερα να τα αναγνωρίζεις από τώρα.

  • Να ξεχάσεις τα εισαγωγικά γύρω από μια τιμή label: το up{job=api} επιστρέφει

    text
    invalid parameter "query": 1:8: parse error: unexpected identifier "api" in label matching, expected string

    Μια τιμή label είναι πάντα μια συμβολοσειρά μέσα σε εισαγωγικά: up{job="api"}. Ακόμη και για έναν αριθμό: το http_requetes_total{code=500} επιστρέφει parse error: unexpected character inside braces: '5'· πρέπει να γράψεις code="500".

  • Να καλέσεις το rate() χωρίς χρονικό παράθυρο: το rate(http_requetes_total) επιστρέφει

    text
    invalid parameter "query": 1:6: parse error: expected type range vector in call to function "rate", got instant vector

    Το rate() χρειάζεται ένα διάστημα μέσα σε αγκύλες: rate(http_requetes_total[1m]). Χωρίς αγκύλες, του δίνεις την τελευταία τιμή (ένα instant vector) ενώ χρειάζεται μια ακολουθία τιμών (ένα range vector).

  • Να καλέσεις το rate() σε ένα gauge: το rate(requetes_en_cours[1m]) δεν προκαλεί σφάλμα, αλλά ο Prometheus εμφανίζει μια προειδοποίηση:

    text
    PromQL info: metric might not be a counter, name does not end in _total/_sum/_count/_bucket: "requetes_en_cours" (1:6)

    Το αποτέλεσμα (0.017… στο μηχάνημα του μαθήματος) δεν έχει κανένα νόημα: η ταχύτητα αύξησης μιας τιμής που ανεβαίνει και κατεβαίνει δεν είναι πληροφορία. Το rate() προορίζεται για μετρητές.

  • Να κάνεις λάθος στο όνομα μιας μετρικής: το http_request_total (στον ενικό, χωρίς το γαλλικό e) επιστρέφει κενό αποτέλεσμα, χωρίς μήνυμα σφάλματος. Ο Prometheus δεν γνωρίζει αυτή τη μετρική, δεν τη διορθώνει. Το ακριβές όνομα είναι http_requetes_total. Ομοίως, το http_requetes_total{route="/inexistant"} επιστρέφει κενό αποτέλεσμα: η άγνωστη διαδρομή μετριέται κάτω από route="inconnue", όχι κάτω από την πραγματική της διαδρομή.

Να θυμάσαι

Οι τέσσερις τύποι μετρικών Prometheus είναι ο μετρητής (http_requetes_total, που αυξάνεται μόνο προς μία κατεύθυνση και διαβάζεται με rate()), το gauge (requetes_en_cours, που ανεβαίνει και κατεβαίνει), το ιστόγραμμα (http_duree_requete_seconds, δώδεκα γραμμές ανά διαδρομή: δέκα σωρευτικά _bucket, _count, _sum) και η περίληψη (απούσα από το εργαστήριο, γιατί τα ποσοστημόριά της δεν συναθροίζονται μεταξύ instances). Μια χρονοσειρά είναι ένας μοναδικός συνδυασμός ονόματος και labels· το http_requetes_total έχει 14 στο μηχάνημα του μαθήματος. Η πληθικότητα εξηγεί γιατί η μετρική φέρει route="/cours/{id}" ενώ το log περιέχει C0038 στο μήνυμά του. Ο Prometheus λειτουργεί σε pull: διαβάζει (scrape) οκτώ στόχους (targets) κάθε 15 δευτερόλεπτα, ομαδοποιημένους ανά job, ταυτοποιημένους ανά instance, και κατασκευάζει ο ίδιος τη μετρική up. Ένα δομημένο log του εργαστηρίου είναι μια γραμμή JSON με οκτώ πεδία, ανάμεσά τους το id_requete, που επιστρέφεται επίσης στην κεφαλίδα x-id-requete· το Loki ευρετηριάζει από αυτό μόνο τέσσερα labels: service, conteneur, niveau, code. Δέκα υπηρεσίες, εννέα θύρες (το charge δεν έχει), οκτώ στόχοι Prometheus (το charge και το webhook δεν εκθέτουν /metrics).

Για να πας παρακάτω

  • Prometheus — Exposition formats: η ακριβής γραμματική της σελίδας /metrics που άνοιξες στο βήμα 1 (οι γραμμές # HELP, # TYPE, η διαφυγή των labels).
  • Prometheus — Metric and label naming: γιατί _total για έναν μετρητή, _seconds για μια διάρκεια, _bytes για ένα μέγεθος· το API του εργαστηρίου σέβεται αυτές τις συμβάσεις, με μία εξαίρεση: τα ονόματα είναι στα γαλλικά.
  • Prometheus — Histograms and summaries: το άρθρο αναφοράς για την επιλογή ιστόγραμμα / περίληψη, με τα σφάλματα προσέγγισης του histogram_quantile.
  • prometheus_client (Python): η βιβλιοθήκη που χρησιμοποιεί το api/app.py για να εκθέσει τις μετρικές· η ενότητα 3 σε κάνει να προσθέσεις τη δική σου μετρική με αυτήν.
  • Grafana Loki — Labels: γιατί λίγα labels, και ποτέ ένα μοναδικό αναγνωριστικό μέσα τους: ο ίδιος κανόνας πληθικότητας όπως και για τον Prometheus.
  • Η ενότητα 2 ξαναπιάνει κάθε όρο στην πράξη: να γράψεις up, να φιλτράρεις ανά label, να υπολογίσεις ένα rate(), να διαβάσεις ένα ιστόγραμμα με histogram_quantile().