
Sessions, Traces & Spans στην Παρατηρησιμότητα LLM: Ένα από Αυτά Δεν Είναι Δομικό Επίπεδο
Η σελίδα όρων της Datadog, το νούμερο 1 αποτέλεσμα Google για sessions traces spans στην παρατηρησιμότητα LLM, ορίζει δύο από αυτές τις τρεις λέξεις. Όχι τρεις. Αυτή που λείπει αντιστοιχεί στο gen_ai.conversation.id, και ο λόγος που λείπει είναι ότι το spec του OpenTelemetry δεν την έκανε ποτέ δομικό επίπεδο. Αν χρειάζεστε την επιχειρηματολογία υπέρ της ίδιας της παρατηρησιμότητας, ξεκινήστε εδώ. Αυτό το άρθρο πιάνει το νήμα από εκεί που σταματάει εκείνο: το μοντέλο δεδομένων.
Βασικά Συμπεράσματα
- Τα spans εμφωλεύονται μέσα σε traces· τα traces ομαδοποιούνται σε sessions. Η εμφώλευση τρέχει από μέσα προς τα έξω: span, μετά trace, μετά session.
- Ένα span είναι μία χρονομετρημένη λειτουργία. Ένα trace είναι ένα αίτημα από άκρη σε άκρη. Ένα session είναι μία συνομιλία πολλών γύρων.
- Οι συμβάσεις GenAI του OpenTelemetry ορίζουν τα spans και το attribute
gen_ai.conversation.id. Δεν ορίζουν επίπεδο session. - Τα αναγνωριστικά trace και span διαδίδονται αυτόματα μέσω του context. Το session ID όχι. Το βάζετε εσείς, σε κάθε γύρο.
Sessions vs Traces vs Spans, με μία Ματιά
Στην παρατηρησιμότητα LLM, ένα span είναι μία χρονομετρημένη λειτουργία (μία κλήση μοντέλου, ένα βήμα ανάκτησης), ένα trace είναι το δέντρο των spans που παράγει ένα αίτημα, και ένα session ομαδοποιεί πολλά traces από την ίδια συνομιλία. Η εμφώλευση πάει προς τα μέσα: spans μέσα σε traces, traces μέσα σε sessions. Η τρίτη ομαδοποίηση είναι αυτή που δεν είναι ό,τι φαίνεται.
| Επίπεδο | Τι τυλίγει | Πόσο ζει | Ποιος βάζει το ID | Τι απαντάει | Τυπικό πλήθος ανά συνομιλία |
|---|---|---|---|---|---|
| Session | Πολλά traces από μία συνομιλία χρήστη | Λεπτά έως μέρες· τελειώνει με timeout αδράνειας ή ρητό κλείσιμο (ορίζεται από τον vendor) | Εσείς, χειροκίνητα, σε κάθε γύρο | Πέτυχε αυτή η συνομιλία συνολικά; | 1 |
| Trace | Ένα αίτημα ή γύρος από άκρη σε άκρη | Χιλιοστά του δευτερολέπτου έως δευτερόλεπτα | Αυτόματο (SDK / OTel) | Τι έγινε σε αυτόν τον γύρο; | Συνήθως 5–20 |
| Span | Μία λειτουργία: ανάκτηση, κλήση μοντέλου, κλήση εργαλείου | Υποχιλιοστοδευτερόλεπτο έως δευτερόλεπτα | Αυτόματο (SDK / OTel) | Ποιο βήμα ήταν αργό, λάθος ή ακριβό; | Περίπου 3–30 ανά trace |
Αυτά τα νούμερα πλήθους και διάρκειας ζωής είναι τυπικά εύρη που θα περιμένατε σε ένα RAG chatbot ή έναν βρόχο agent, όχι μετρήσεις από ελεγχόμενο τεστ. Τα δικά σας νούμερα θα διαφέρουν. Αυτό που δεν θα διαφέρει: η σειρά Session είναι αυτή που δεν αποτελεί δομικό επίπεδο στο spec, και η ενότητα «Sessions: Το Επίπεδο που Μάλλον Εφηύρε το Εργαλείο σας» το αποδεικνύει.
Τι Είναι το Span και Τι Είναι το Είδος Span;
Ένα span είναι μία χρονομετρημένη λειτουργία με όνομα, χρονική σήμανση έναρξης, χρονική σήμανση λήξης, κωδικό κατάστασης και ένα σύνολο attributes κλειδιού-τιμής. Στο LLM tracing, τα attributes είναι εκεί που ζουν τα χρήσιμα δεδομένα: τα gen_ai.usage.input_tokens, gen_ai.usage.output_tokens και gen_ai.request.model σάς λένε πόσο κόστισε η λειτουργία και ποιο μοντέλο την έτρεξε.
Ένα span είναι μία λειτουργία, όχι μία κλήση συνάρτησης
Κάθε span κουβαλάει έναν δείκτη parent span ID (κενό στο root span) που χτίζει το δέντρο. Το σύνολο attributes είναι ανοιχτό: κολλάτε ό,τι context χρειάζεστε. Οι συμβάσεις GenAI span του OpenTelemetry (κατάσταση: Development) απαιτούν gen_ai.operation.name και gen_ai.provider.name σε κάθε GenAI span, και συνιστούν τα attributes χρήσης tokens παραπάνω.
Ένας πρακτικός κανόνας από τη σελίδα όρων της Datadog: τα spans LLM, Workflow και Agent μπορούν να χρησιμεύσουν ως root span· τα spans Tool, Task, Embedding και Retrieval όχι. Αυτός είναι κανόνας της Datadog, όχι καθολικός, αλλά είναι ο μόνος vendor που τον δηλώνει, και σας γλιτώνει από το να χτίσετε ένα trace που ξεκινάει από κλήση εργαλείου χωρίς γονέα.
Είδη span: η ίδια ιδέα, πέντε λεξιλόγια
Κάθε εργαλείο χρειάζεται έναν τρόπο να λέει «αυτό το span είναι κλήση μοντέλου» έναντι «αυτό το span είναι ανάκτηση». Απλά δεν συμφωνούν στη λέξη:
| Εργαλείο | Η λέξη του για το «είδος λειτουργίας» | Τιμές |
|---|---|---|
| OpenTelemetry GenAI | attribute gen_ai.operation.name | 15 γνωστές τιμές (chat, embeddings, execute_tool, invoke_agent, retrieval και 10 ακόμα)· αν μία ισχύει, ΠΡΕΠΕΙ να χρησιμοποιηθεί, επιτρέπονται προσαρμοσμένες τιμές όταν καμία δεν ταιριάζει |
| Datadog | Span kind | LLM, Workflow, Agent, Tool, Task, Embedding, Retrieval |
| OpenInference / Phoenix | Span kind | CHAIN, LLM, TOOL, RETRIEVER, RERANKER, EMBEDDING, AGENT, GUARDRAIL, EVALUATOR, PROMPT |
| Langfuse | Observation type | generation, span, event |
| LangSmith | Run type | LLM, chain, tool, retriever |
Το spec του OpenInference παραθέτει δέκα είδη. Η Datadog παραθέτει επτά. Το OTel ακολουθά τρίτο δρόμο: το μητρώο attributes GenAI δημοσιεύει 15 γνωστές τιμές για το gen_ai.operation.name (chat, create_agent, create_memory, create_memory_store, delete_memory, delete_memory_store, embeddings, execute_tool, generate_content, invoke_agent, invoke_workflow, plan, retrieval, search_memory, text_completion) και ορίζει ότι αν μία από αυτές ισχύει, ΠΡΕΠΕΙ να χρησιμοποιηθεί αυτή η τιμή· προσαρμοσμένη τιμή ΜΠΟΡΕΙ να χρησιμοποιηθεί μόνο όταν καμία δεν ταιριάζει. Άρα είναι ένα ημι-ανοιχτό enum, όχι η απουσία του. Τρεις λίστες, τρία μήκη, καμία ευθυγράμμιση μεταξύ τους. Αν διαλέγετε εργαλείο, αυτό το χάσμα λεξιλογίου μετράει περισσότερο από τη λίστα features, γιατί είναι αυτό στο οποίο θα βασίζονται τα dashboards και τα φίλτρα ειδοποιήσεών σας.
Τι Είναι το Trace και Γιατί Μετράει το Σχήμα του Δέντρου;
Ένα trace είναι το δέντρο των spans που παράγει ένα αίτημα. Ένα root span κάθεται στην κορυφή· κάθε άλλο span κρέμεται από κάτω του μέσω ακμών parent-span-ID. Το σχήμα του δέντρου είναι όλη η ουσία: ένα επίπεδο log σάς λέει ότι κάτι ήταν αργό, αλλά το δέντρο σάς λέει ποιο βήμα ήταν αργό και ποιο βήμα παρήγαγε το λάθος αποτέλεσμα.
chat_request (root) 2,340ms
├── retrieval 410ms
│ └── rerank 85ms
├── chat gpt-4o 1,720ms
└── tool_call: search_calendar 190msΔιαβάστε αυτό το δέντρο και η διάγνωση είναι άμεση: το 74% της καθυστέρησης κάθισε στην κλήση του μοντέλου, όχι στην ανάκτηση. Ένα επίπεδο log με πέντε χρονικές σημάνσεις σάς δίνει το ίδιο σύνολο αλλά καμία απόδοση ευθύνης.
Ένας βρόχος agent κάνει αυτό το δέντρο πιο βαθύ και πιο φαρδύ από ένα απλό RAG αίτημα. Κάθε κλήση εργαλείου γεννάει το δικό της υπο-δέντρο· ένας γύρος agent πέντε βημάτων μπορεί εύκολα να παράγει 30+ spans κάτω από μία ρίζα. Αυτό είναι φυσιολογικό, και είναι ο λόγος που υπάρχει η ερώτηση για την κοκκομετρία των spans παρακάτω.
Η διάκριση μεταξύ tracing και logging μετράει κι εδώ: το logging καταγράφει γεγονότα, το tracing καταγράφει αιτιότητα. Αν ακόμα αποφασίζετε τι να logάρετε έναντι τι να traceάρετε, το άρθρο μας για τις βέλτιστες πρακτικές LLM logging τραβάει αυτή τη γραμμή.
Sessions: Το Επίπεδο που Μάλλον Εφηύρε το Εργαλείο σας
Όχι. Το session δεν είναι δομικό επίπεδο στις συμβάσεις GenAI του OpenTelemetry. Το spec ορίζει τα spans και το attribute gen_ai.conversation.id (υπό όρους απαιτούμενο, «όταν είναι διαθέσιμο», κατάσταση: Development), που περιγράφεται ως το μοναδικό αναγνωριστικό για μια συνομιλία ή νήμα και χρησιμοποιείται για τη συσχέτιση μηνυμάτων. Οι vendors μετά χτίζουν το δικό τους αντικείμενο session πάνω από αυτό το attribute. Κανείς άλλος σε αυτή τη σελίδα αποτελεσμάτων δεν δηλώνει την κατάσταση του spec τόσο καθαρά, ορίστε λοιπόν.
Η συνέπεια είναι η πρόταση που υπάρχει ολόκληρο αυτό το άρθρο για να παραδώσει:
Ένα session είναι κλειδί ομαδοποίησης, όχι γονικό span. Δεν διαδίδεται όπως ένα trace ID· το βάζετε μόνοι σας σε κάθε γύρο.
Χάστε έναν γύρο και αυτός ο γύρος πέφτει έξω από το session. Δεν υπάρχει αυτόματη διάδοση context για αυτό.
Πότε ξεκινάει και πότε τελειώνει ένα session;
Ορίζεται από τον vendor. Κάποια εργαλεία ανοίγουν session στο πρώτο trace που κουβαλάει νέο conversation ID και το κλείνουν με timeout αδράνειας (το Langfuse έχει προεπιλεγμένο ένα παραμετροποιήσιμο παράθυρο). Άλλα απαιτούν ρητή κλήση κλεισίματος. Το spec δεν λέει τίποτα για τον κύκλο ζωής, επειδή το spec δεν μοντελοποιεί το session ως αντικείμενο.
Τι μεταφέρεται μεταξύ γύρων και τι όχι;
Το context window του μοντέλου δεν είναι το session. Το session είναι ένα κλειδί ομαδοποίησης πάνω από ανεξάρτητα traces. Κάθε γύρος παίρνει το δικό του trace, το δικό του root span, τις δικές του μετρήσεις tokens. Αυτό που μεταφέρεται είναι το attribute conversation ID που σφραγίσατε σε κάθε root span. Αυτό που δεν μεταφέρεται: καθυστέρηση, χρήση tokens, δομή spans. Αυτά είναι ανά trace.
Τι μετράει μια μετρική επιπέδου session;
Πράγματα που ένα μεμονωμένο trace δεν μπορεί: ποσοστό επίλυσης (έλυσε η συνομιλία το πρόβλημα του χρήστη;), γύροι μέχρι την απάντηση (πόσα traces πριν ο χρήστης πάρει αυτό που χρειαζόταν;) και εγκαταλελειμμένες συνομιλίες (sessions χωρίς σήμα κλεισίματος). Τρέχοντας evals σε ζωντανά traces σε επίπεδο session, πιάνετε αστοχίες πολλών γύρων που δείχνουν φυσιολογικές σε επίπεδο μεμονωμένου γύρου.
Ο κώδικας, ανεξάρτητος vendor
Αυτό το απόσπασμα χρησιμοποιεί μόνο σταθερά πρωτόγονα του OTel. Κανένα SDK vendor. Φτιάχνει ένα root span για έναν γύρο, ένα παιδί-σπαν για την ανάκτηση, ένα παιδί για την κλήση του μοντέλου, και θέτει το gen_ai.conversation.id ώστε τρεις γύροι να προσγειωθούν σε ένα session:
from opentelemetry import trace
tracer = trace.get_tracer("my-llm-app")
SESSION_ID = "conv-8f3a2c" # same value on every turn
def handle_turn(user_message: str):
with tracer.start_as_current_span("chat_request") as root:
# You set this. It does not propagate automatically.
root.set_attribute("gen_ai.conversation.id", SESSION_ID)
with tracer.start_as_current_span("retrieval") as ret:
ret.set_attribute("gen_ai.operation.name", "retrieval")
docs = retrieve(user_message)
with tracer.start_as_current_span("chat gpt-4o") as llm:
llm.set_attribute("gen_ai.operation.name", "chat")
llm.set_attribute("gen_ai.provider.name", "openai")
llm.set_attribute("gen_ai.request.model", "gpt-4o")
response = call_model(user_message, docs)
llm.set_attribute("gen_ai.usage.input_tokens", 1_204)
llm.set_attribute("gen_ai.usage.output_tokens", 312)
return responseΚαλέστε την handle_turn τρεις φορές με το ίδιο SESSION_ID και όλα τα τρία traces ομαδοποιούνται κάτω από ένα session σε οποιοδήποτε backend διαβάζει το attribute. Αλλάξτε το ID και ξεκινήσατε νέο session. Αυτός είναι όλος ο μηχανισμός.
Διαβάσαμε την Τεκμηρίωση Πέντε Vendors Δίπλα-Δίπλα. Δεν Συμφωνούν.
Στις 30 Ιουλίου 2026 διαβάσαμε την τρέχουσα τεκμηρίωση μοντέλου δεδομένων των Langfuse, LangSmith, OpenInference / Phoenix και Datadog δίπλα-δίπλα, μαζί με το spec GenAI span του OpenTelemetry. Τέσσερις από τους πέντε λένε το ίδιο αντικείμενο διαφορετικά. Μόνο ένας αντιμετωπίζει το session ως αντικείμενο πρώτης κατηγορίας αντί για attribute. Η σελίδα όρων της Datadog, το νούμερο 1 αποτέλεσμα Google για αυτό το ερώτημα, δεν ορίζει καν το session.
| Έννοια | OTel GenAI semconv | Langfuse | LangSmith | OpenInference / Phoenix | Datadog |
|---|---|---|---|---|---|
| Ολόκληρη η συνομιλία | attribute gen_ai.conversation.id | Session (προαιρετική ομαδοποίηση traces) | Thread (μέσω μεταδεδομένων session_id / thread_id) | attribute span session.id | Δεν ορίζεται στη σελίδα όρων |
| Ένα αίτημα | Trace | Trace | Trace («συλλογή από runs») | Trace | Trace |
| Μία λειτουργία | Span | Observation (span / generation / event) | Run («span που αναπαριστά μία μονάδα εργασίας») | Span με είδος span | Span με είδος span |
Μία σημείωση πηγής για αυτή την πρώτη σειρά: το session.id του OpenInference δεν βρίσκεται στο spec traces που παραθέσαμε παραπάνω, το οποίο καλύπτει τα δέκα είδη span. Ορίζεται στο αδελφικό αρχείο σημασιολογικών συμβάσεων του OpenInference ως το μοναδικό αναγνωριστικό ενός session. Δύο αρχεία, ένα spec.
Δεν εμείς εφεύραμε τη σύγκριση μεταξύ vendors· η FutureAGI δημοσιεύει κι αυτή έναν πίνακα OTel-εναντίον-vendor. Οι δύο δικές μας προσθήκες είναι η σειρά του session (η FutureAGI την παραλείπει) και η παγίδα της ίδιας λέξης με διαφορετική σημασία: το «observation» του Langfuse και το «run» του LangSmith είναι το ίδιο αντικείμενο με το span, ενώ τα είδη span της Datadog και του OpenInference είναι διαφορετικά λεξιλόγια για την ίδια ιδέα.
Το Langfuse το λέει observation, το LangSmith το λέει run, η Datadog το λέει span. Το ίδιο αντικείμενο, τρία dashboards που σπάνε όταν μεταναστεύσετε.
Αυτή είναι η δική μας ανάγνωση του κόστους μετανάστευσης, όχι ισχυρισμός vendor. Αλλά είναι ο λόγος που αποθηκευμένα φίλτρα, ρυθμίσεις eval και κανόνες ειδοποιήσεων βασισμένοι στο «observation» ή στο «run» σταματούν να δουλεύουν τη μέρα που αλλάζετε εργαλείο. Δεν μετονομάζετε πεδίο. Μετονομάζετε επίπεδο. Αν ζυγίζετε αυτά τα δύο συγκεκριμένα εργαλεία, η σύγκριση Langfuse εναντίον LangSmith μπαίνει πιο βαθιά στην απόκλιση.
Αναγνώστες μπορεί να έχουν ήδη στο stack τους το Opik, το PostHog, το Sentry ή το Weights & Biases· η Google συσχετίζει και τα τέσσερα με το llm tracing, και το καθένα χαρτογραφεί αυτές τις έννοιες ελαφρώς διαφορετικά. Διαλέγετε το σωστό; Η ανασκόπηση πλατφορμών παρατηρησιμότητας καλύπτει όλο το πεδίο.
Μία σημείωση φρεσκάδας: οι συμβάσεις GenAI έχουν μετακομίσει στο δικό τους αποθετήριο, έξω από το κεντρικό αποθετήριο semantic-conventions. Το παλιό μονοπάτι opentelemetry.io/docs/specs/semconv/gen-ai/ πλέον κουβαλάει μόνο έναν δείκτη.
Ποιο ID Πάει Πού;
Ένα trace ID ταυτοποιεί ένα αίτημα και διαδίδεται αυτόματα μέσω του context. Ένα span ID ταυτοποιεί μία λειτουργία μέσα σε αυτό το trace, επίσης αυτόματα. Ένα correlation ID (ή request ID) έρχεται από το web tier σας πριν ξεκινήσει το tracing, και είναι αυτό που ο κόσμος μπερδεύει πιο συχνά με το trace ID. Το session ID είναι ο περίεργος: δική σας δουλειά να το βάλετε, χειροκίνητα, σε κάθε γύρο.
| ID | Μπαίνει από | Εμβέλεια | Συγχέεται με |
|---|---|---|---|
| Trace ID | Αυτόματα | Ένα αίτημα· διαδίδεται μέσω context | Το correlation ID από το web tier σας |
| Span ID | Αυτόματα | Μία λειτουργία | , |
| Parent span ID | Αυτόματα | Χτίζει το δέντρο· κενό στο root span | , |
| Session / conversation ID | Εσείς, χειροκίνητα, κάθε γύρο | Πολλά traces | Την υπόθεση ότι διαδίδεται. Δεν διαδίδεται. |
| User ID | Εσείς, χειροκίνητα | Πολλά sessions | Το session ID |
| Request / correlation ID | Το web tier σας, πριν ξεκινήσει το tracing | Ένα αίτημα HTTP | Το trace ID (αυτό είναι το μεγάλο) |
Ο πρακτικός κανόνας: κολλήστε το gen_ai.conversation.id ως attribute span στο root span κάθε γύρου, και σφραγίστε το user ID δίπλα του. Παραλείψτε έναν γύρο και οι μετρικές επιπέδου session χάνουν αυτόν τον γύρο σιωπηλά.
Μία προειδοποίηση για την καρδιναλιότητα: τα user IDs και τα session IDs είναι τιμές υψηλής καρδιναλιότητας. Αυτό μετράει για τον λογαριασμό ευρετηρίασης του backend σας, που είναι το πρόβλημα της επόμενης ενότητας.
Πόσο Λεπτομερές Πρέπει να Είναι ένα Span;
Δύο τρόποι αποτυχίας, και οι δύο συχνοί:
Υπερβολικά spans. Ένα span ανά κλήση συνάρτησης σάς δίνει ένα trace 400 spans που κανείς δεν μπορεί να διαβάσει και έναν λογαριασμό ανά span που κανείς δεν ενέκρινε. Τα φιλοξενούμενα backends (Datadog, Langfuse Cloud) τιμολογούν με τον όγκο spans. Ένας φλύαρος βρόχος agent που οργανώνει κάθε συνένωση strings θα κάψει ένα δωρεάν πλάνο σε ένα απόγευμα.
Λίγα spans. Ένα span για «ολόκληρη την αλυσίδα» σάς λέει ότι ήταν αργή αλλά όχι πού. Καταλήγετε να ξαναβάζετε print statements, που είναι ακριβώς αυτό που το tracing υποτίθεται ότι αντικαθιστά.
Ο κανόνας εμπειρίας (και είναι κανόνας εμπειρίας, όχι μέτρηση): βάλτε span στα όρια όπου συμβαίνει μια απόφαση ή μια εξωτερική κλήση.
- Βήμα ανάκτησης: span.
- Κλήση rerank: span.
- Κάθε κλήση μοντέλου: span.
- Κάθε κλήση εργαλείου: span.
- Κάθε έλεγχος guardrail: span.
- Καθαροί μετασχηματισμοί εντός διεργασίας (μορφοποίηση strings, parsing JSON, συναρμολόγηση prompt): attributes στο γονικό span, όχι δικά τους spans.
Για καρδιναλιότητα, δειγματοληψία και διατήρηση:
- Attributes υψηλής καρδιναλιότητας (user IDs, ολόκληρα prompts) φουσκώνουν το κόστος αποθήκευσης. Δειγματοληπτήστε τα ή περικόψτε τα.
- Τα περισσότερα backends σάς αφήνουν να δειγματοληπτείτε σε επίπεδο trace. Κρατήστε το 100% των traces σφάλματος· δειγματοληπτήστε τον ευτυχισμένο δρόμο.
- Τα παράθυρα διατήρησης ποικίλλουν: 7 μέρες στα δωρεάν πλάνα, 30–90 μέρες στα επί πληρωμή. Αποφασίστε πριν χρειαστείτε τα δεδομένα.
Για το πραγματικό μοντέλο κόστους πίσω από τον όγκο spans και την τιμολόγηση ανά span, δείτε τον οδηγό παρακολούθησης κόστους LLM. Δεν θα το ξαναχτίσουμε εδώ.
Πώς το Προσεγγίζει η Techsy
Για δουλειά με agents πελατών, τυποποιούμε τρεις κανόνες:
- Ένα trace ανά γύρο. Ποτέ μην συγχωνεύετε δύο γύρους χρήστη σε ένα trace, ακόμα κι αν ο agent κάνει εσωτερικούς βρόχους.
- Ένα session ID σφραγισμένο σε κάθε root span, που μπαίνει στον κώδικα της εφαρμογής, και ποτέ δεν θεωρείται ότι διαδίδεται.
- Τα είδη span μένουν σε ένα μικρό σταθερό σύνολο (retrieval, inference, tool, guardrail) ώστε τα dashboards να επιβιώνουν μιας αλλαγής vendor.
Αυτός ο τρίτος κανόνας είναι αυτός που οι ομάδες παραλείπουν, και είναι αυτός που σώζει μια μετανάστευση. Αν το λεξιλόγιο των spans σας είναι δεμένο με το enum ενός vendor, κάθε ειδοποίηση και αποθηκευμένη προβολή σπάει τη μέρα που αλλάζετε.
Αν χτίζετε ένα σύστημα agent και θέλετε μια δεύτερη γνώμη για την αρχιτεκτονική tracing, πάρτε μια δωρεάν συμβουλευτική.
Σχετικά με τον Συγγραφέα
Ο Mert Batur είναι Συνιδρυτής της Techsy.io, όπου η ομάδα παραδίδει AI agents, συστήματα αυτοματισμού και pipelines φωνής/SDR για B2B πελάτες. Γράφει για τη στοίβα εργαλείων LLM που η ομάδα της Techsy χρησιμοποιεί πραγματικά στην παραγωγή. Συνδεθείτε στο LinkedIn.
Συχνές Ερωτήσεις
Τι είναι το span στο κατανεμημένο tracing;
Ένα span είναι μία χρονομετρημένη μονάδα εργασίας: έχει όνομα, ώρα έναρξης, ώρα λήξης, κατάσταση και ένα σύνολο attributes. Τα spans συνδέονται μεταξύ τους μέσω αναφορών parent-span-ID, σχηματίζοντας δέντρο. Σε εφαρμογές LLM, ένα span τυπικά τυλίγει μία κλήση μοντέλου, μία ανάκτηση ή μία κλήση εργαλείου.
Τι είναι το span στη Datadog;
Στο LLM Observability της Datadog, ένα span είναι η ίδια χρονομετρημένη λειτουργία, αλλά η Datadog προσθέτει μια ταξινομία span kind: LLM, Workflow, Agent, Tool, Task, Embedding και Retrieval. Μόνο τα είδη LLM, Workflow και Agent μπορούν να χρησιμεύσουν ως root span. Η ταξινομία είναι ειδική για τη Datadog· δεν είναι μέρος του προτύπου OpenTelemetry.
Ποιοι είναι οι τέσσερις πυλώνες της παρατηρησιμότητας;
Οι τέσσερις πυλώνες είναι logs, metrics, traces και (ανάλογα με το πλαίσιο του καθενός) profiles ή events. Τα traces είναι ο πυλώνας στον οποίο ζει αυτό το άρθρο. Η περίπτωση των LLM προσθέτει μια πτυχή: η χρήση tokens και η ταυτότητα μοντέλου είναι attributes στα spans του trace, όχι ξεχωριστές ροές metrics, κάτι που συγχωνεύει ό,τι θα ήταν δύο πυλώνες σε ένα ερώτημα.
Ποια είναι τα τέσσερα χρυσά σήματα της παρατηρησιμότητας;
Καθυστέρηση, κίνηση, σφάλματα και κορεσμός. Για συστήματα LLM, καθυστέρηση σημαίνει χρόνος μέχρι το πρώτο token και συνολικός χρόνος παραγωγής· κίνηση σημαίνει αιτήματα ανά δευτερόλεπτο ανά μοντέλο· σφάλματα σημαίνει αποτυχημένα spans (κωδικός κατάστασης ERROR)· κορεσμός σημαίνει εξάντληση προϋπολογισμού tokens ή βάθος ουράς. Τα σήματα είναι τα ίδια· οι μονάδες διαφέρουν.
Είναι το session μέρος του προτύπου OpenTelemetry;
Όχι ως δομικό επίπεδο. Οι συμβάσεις GenAI span του OTel ορίζουν το gen_ai.conversation.id ως υπό όρους απαιτούμενο attribute («όταν είναι διαθέσιμο») για τη συσχέτιση μηνυμάτων σε μια συνομιλία ή νήμα. Κάθεται πάνω σε spans. Vendors όπως η Langfuse και η LangSmith χτίζουν τα δικά τους αντικείμενα session ή thread πάνω από αυτό.
Ποια η διαφορά μεταξύ trace ID, span ID και correlation ID;
Ένα trace ID ταυτοποιεί ένα αίτημα και διαδίδεται αυτόματα μέσω όλων των κατάντη υπηρεσιών. Ένα span ID ταυτοποιεί μία λειτουργία μέσα σε αυτό το trace. Ένα correlation ID (ή request ID) παράγεται από το web tier σας πριν ξεκινήσει το tracing και είναι η τιμή που ο κόσμος μπερδεύει πιο συχνά με το trace ID. Επικαλύπτονται σε εμβέλεια αλλά προέρχονται διαφορετικά.
Πόσα spans πρέπει να έχει ένα trace;
Δεν υπάρχει σταθερή απάντηση, αλλά τα τυπικά εύρη είναι 3–30 για αίτημα RAG και 10–50+ για βρόχο agent με πολλαπλές κλήσεις εργαλείων. Ο κανόνας εμπειρίας: βάλτε span σε εξωτερικές κλήσεις και σημεία απόφασης, όχι σε μετασχηματισμούς εντός διεργασίας. Αν το trace σας ξεπερνάει τα 100 spans, πιθανότατα το παρα-οργανώνετε.
Τα «observations» του Langfuse είναι το ίδιο πράγμα με τα spans;
Ναι. Ένα observation του Langfuse είναι το ίδιο αντικείμενο με ένα span του OTel: μία χρονομετρημένη λειτουργία με attributes. Το Langfuse χωρίζει τα observations σε τρεις τύπους (generation, span, event) εκεί που το OTel χρησιμοποιεί το gen_ai.operation.name. Αν αξιολογείτε εργαλεία που διαβάζουν τα traces σας, η ανασκόπηση εργαλείων αξιολόγησης LLM καλύπτει ποια δέχονται και τα δύο λεξιλόγια.
Πώς ομαδοποιείτε μια συνομιλία chatbot πολλών γύρων σε ένα session;
Βάλτε το ίδιο αναγνωριστικό συνομιλίας στο root span κάθε γύρου. Σε όρους OTel, αυτό είναι το gen_ai.conversation.id. Στο Langfuse, περνάτε ένα session_id όταν φτιάχνετε traces. Στο LangSmith, θέτετε μεταδεδομένα session_id ή thread_id. Παραλείψτε έναν γύρο και αυτός ο γύρος πέφτει έξω από την ομαδοποίηση.
Χρειάζομαι sessions αν χειρίζομαι μόνο αιτήματα ενός γύρου;
Μάλλον όχι. Τα sessions υπάρχουν για να συσχετίζουν πολλά traces σε μία συνομιλία. Αν κάθε αίτημα είναι ανεξάρτητο (ένα API ταξινόμησης, ένας one-shot συνοψιστής), οι μετρικές επιπέδου trace αρκούν. Προσθέστε sessions όταν χρειάζεστε μετρικές μεταξύ γύρων: ποσοστό επίλυσης, γύρους μέχρι την απάντηση ή κόστος επιπέδου συνομιλίας. Ο οδηγός αξιολόγησης LLM καλύπτει πότε τα evals επιπέδου session αξίζουν τον κόπο τους.
Η Σύντομη Εκδοχή
Τα spans εμφωλεύονται μέσα σε traces· τα traces ομαδοποιούνται σε sessions. Η εμφώλευση είναι πραγματική, αλλά το spec δομεί μόνο δύο από τα τρία επίπεδα. Το gen_ai.conversation.id είναι attribute που βάζετε μόνοι σας, όχι γονικό span που διαδίδεται. Και ο vendor που διαλέγετε σήμερα ονομάζει αυτά τα αντικείμενα διαφορετικά από τον vendor στον οποίο θα μεταβείτε σε 18 μήνες, οπότε κρατήστε το λεξιλόγιο των spans σας μικρό και φορητό.
Αν διαλέγετε πλατφόρμα, ξεκινήστε με τη σύγκριση πλατφορμών παρατηρησιμότητας. Αν χτίζετε evals πάνω από τα traces σας, ο οδηγός αξιολόγησης LLM πιάνει το νήμα από εδώ.