
Sesjoner, sporinger og spenn i LLM-observabilitet: Én av disse er ikke et strukturnivå
Terminsiden til Datadog, det første Google-treffet for LLM observability sessions traces spans, definerer to av disse tre ordene. Ikke tre. Det som mangler, mappes til gen_ai.conversation.id, og grunnen til at det mangler, er at OpenTelemetry-spesifikasjonen aldri gjorde det til et strukturnivå. Trenger du argumentene for observabilitet i seg selv, starter du her. Dette innlegget tar over der det slutter: datamodellen.
Nøkkelpoenger
- Spenn nøstes inni sporinger; sporinger grupperes i sesjoner. Nøstingen går fra innerst til ytterst: spenn, så sporing, så sesjon.
- Et spenn er én tidsmålt operasjon. En sporing er én ende-til-ende-forespørsel. En sesjon er én samtale med flere runder.
- GenAI-konvensjonene til OpenTelemetry definerer spenn og attributtet
gen_ai.conversation.id. De definerer ikke et sesjonsnivå. - Sporings-ID-er og spenn-ID-er propageres automatisk gjennom kontekst. Det gjør ikke sesjons-ID-en. Den setter du selv, hver runde.
Sesjoner vs. sporinger vs. spenn, på ett blikk
I LLM-observabilitet er et spenn én tidsmålt operasjon (et modellkall, et hentesteg), en sporing er treet av spenn som én forespørsel produserer, og en sesjon grupperer mange sporinger fra samme samtale. Nøstingen går innover: spenn inni sporinger, sporinger inni sesjoner. Den tredje grupperingen er den som ikke er det den ser ut som.
| Nivå | Hva det omslutter | Hvor lenge det lever | Hvem som setter ID-en | Hva det svarer på | Typisk antall per samtale |
|---|---|---|---|---|---|
| Sesjon | Mange sporinger fra én brukersamtale | Minutter til dager; avsluttes ved inaktivitetstime-out eller en eksplisitt lukking (leverandørdefinert) | Deg, manuelt, hver runde | Lyktes hele samtalen? | 1 |
| Sporing | Én ende-til-ende-forespørsel eller runde | Millisekunder til sekunder | Automatisk (SDK / OTel) | Hva skjedde i denne runden? | Vanligvis 5–20 |
| Spenn | Én operasjon: en henting, et modellkall, et verktøykall | Submillisekund til sekunder | Automatisk (SDK / OTel) | Hvilket steg var tregt, feil eller dyrt? | Omtrent 3–30 per sporing |
Disse tallene for antall og levetid er typiske intervaller du kan forvente i en RAG-chatbot eller en agentsløyfe, ikke målinger fra en kontrollert test. Tallene dine vil være annerledes. Det som ikke endrer seg: Sesjon-raden er den som ikke er et strukturnivå i spesifikasjonen, og delen «Sesjoner: Nivået verktøyet ditt sannsynligvis fant opp» beviser det.
Hva er et spenn, og hva er en spenntype?
Et spenn er én tidsmålt operasjon med et navn, et start-timestamp, et slutt-timestamp, en statuskode og en pose med nøkkel-verdi-attributter. I LLM-sporing er det i attributtene de nyttige dataene bor: gen_ai.usage.input_tokens, gen_ai.usage.output_tokens og gen_ai.request.model forteller deg hva operasjonen kostet og hvilken modell som kjørte den.
Et spenn er én operasjon, ikke ett funksjonskall
Hvert spenn bærer en peker til foreldre-spenn-ID (tom på rotspennet) som bygger treet. Attributtposen er åpen: du legger ved den konteksten du trenger. OpenTelemetry GenAI-spennkonvensjonene (status: Development) krever gen_ai.operation.name og gen_ai.provider.name på alle GenAI-spenn, og anbefaler tokenforbruksattributtene ovenfor.
Én praktisk regel fra terminsiden til Datadog: LLM-, Workflow- og Agent-spenn kan fungere som rotspenn; Tool-, Task-, Embedding- og Retrieval-spenn kan ikke. Det er regelen til Datadog, ikke en universell regel, men de er den eneste leverandøren som slår det fast, og den sparer deg for å bygge en sporing som starter på et verktøykall uten foreldre.
Spanntyper: samme idé, fem vokabularer
Alle verktøy trenger en måte å si «dette spennet er et modellkall» kontra «dette spennet er en henting» på. De er bare ikke enige om ordet:
| Verktøy | Deres ord for «type operasjon» | Verdier |
|---|---|---|
| OpenTelemetry GenAI | Attributtet gen_ai.operation.name | 15 velkjente verdier (chat, embeddings, execute_tool, invoke_agent, retrieval og 10 til); én MÅ brukes hvis den gjelder, egendefinerte verdier tillatt når ingen passer |
| 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 |
OpenInference-spesifikasjonen lister ti typer. Datadog lister syv. OTel tar en tredje vei: GenAI-attributtregisteret publiserer 15 velkjente verdier for 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) og slår fast at hvis én av dem gjelder, MÅ den verdien brukes; en egendefinert verdi KAN bare brukes når ingen passer. Så det er en semi-åpen enum, ikke fraværet av en. Tre lister, tre lengder, og ingen samstemming mellom dem. Hvis du velger verktøy, betyr dette vokabulargapet mer enn funksjonslisten, fordi det er dette dashbordene og varselfiltrene dine nøkles på.
Hva er en sporing, og hvorfor betyr treformen noe?
En sporing er treet av spenn som én forespørsel produserer. Ett rotspenn sitter øverst; alle andre spenn henger under det via kanter med foreldre-spenn-ID. Treformen er hele poenget: en flat logg forteller deg at noe var tregt, men treet forteller deg hvilket steg som var tregt og hvilket steg som produserte det dårlige svaret.
chat_request (root) 2,340ms
├── retrieval 410ms
│ └── rerank 85ms
├── chat gpt-4o 1,720ms
└── tool_call: search_calendar 190msLes det treet, og diagnosen er umiddelbar: 74 % av latensen lå i modellkallet, ikke i henting. En flat logg med fem tidsstempler gir deg samme total, men ingen av tilskrivningen.
En agentsløyfe gjør dette treet dypere og bredere enn en vanlig RAG-forespørsel. Hvert verktøykall føder sitt eget deltre; en agentrunde med fem steg kan lett produsere 30+ spann under én rot. Det er normalt, og det er grunnen til at spørsmålet om spenngranularitet nedenfor finnes.
Skillet mellom sporing og logging betyr noe her også: logging registrerer hendelser, sporing registrerer kausalitet. Hvis du fortsatt bestemmer deg for hva som skal logges kontra spores, trekker innlegget vårt om beste praksis for LLM-logging den grensen.
Sesjoner: Nivået verktøyet ditt sannsynligvis fant opp
Nei. En sesjon er ikke et strukturnivå i OpenTelemetry GenAI-konvensjonene. Spesifikasjonen definerer spenn og attributtet gen_ai.conversation.id (betinget påkrevd, «når tilgjengelig», status: Development), beskrevet som den unike identifikatoren for en samtale eller tråd som brukes til å korrelere meldinger. Leverandører bygger så sitt eget sesjonsobjekt oppå det attributtet. Ingen andre på denne SERP-en slår fast spesifikasjonsstatusen like rett frem, så her er den.
Konsekvensen er setningen hele dette innlegget finnes for å levere:
En sesjon er en grupperingsnøkkel, ikke et foreldrespenn. Den propageres ikke slik en sporings-ID gjør; du setter den selv hver runde.
Bom på én runde, og den runden faller ut av sesjonen. Det finnes ingen automatisk kontekstpropagering for den.
Når starter og slutter en sesjon?
Leverandørdefinert. Noen verktøy åpner en sesjon på den første sporingen som bærer en ny samtale-ID, og lukker den ved en inaktivitetstime-out (Langfuse har et konfigurerbart vindu som standard). Andre krever et eksplisitt lukkekall. Spesifikasjonen sier ingenting om livssyklus, fordi spesifikasjonen ikke modellerer en sesjon som et objekt.
Hva følger med på tvers av runder, og hva som ikke gjør det
Kontekstvinduet til modellen er ikke sesjonen. Sesjonen er en grupperingsnøkkel over uavhengige sporinger. Hver runde får sin egen sporing, sitt eget rotspenn, sine egne tokentellinger. Det som følger med, er samtale-ID-attributtet du stemplet på hvert rotspenn. Det som ikke følger med: latens, tokenforbruk, spennstruktur. Det er per sporing.
Hva måler en sesjonsnivå-metrikk?
Ting en enkelt sporing ikke kan: løsningsrate (løste samtalen problemet til brukeren?), runder-til-svar (hvor mange sporinger før brukeren fikk det de trengte?) og forlatte samtaler (sesjoner uten lukkesignal). Å kjøre evalueringer på live-sporinger på sesjonsnivå er slik du fanger feil over flere runder som ser fine ut runde for runde.
Koden, leverandørnøytral
Denne kodesnutten bruker bare stabile OTel-primitiver. Ingen leverandør-SDK. Den lager et rotspenn for én runde, et barnespenn for henting, et barn for modellkallet, og setter gen_ai.conversation.id slik at tre runder havner i én sesjon:
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 responseKall handle_turn tre ganger med samme SESSION_ID, og alle tre sporingene grupperes under én sesjon i hvilken som helst backend som leser attributtet. Endre ID-en, og du har startet en ny sesjon. Det er hele mekanismen.
Vi leste dokumentasjonen til fem leverandører side om side. De er ikke enige.
- juli 2026 leste vi den gjeldende datamodell-dokumentasjonen for Langfuse, LangSmith, OpenInference / Phoenix og Datadog side om side, pluss OpenTelemetry GenAI-spennspesifikasjonen. Fire av de fem kaller det samme objektet noe forskjellig. Bare én behandler en sesjon som et førsteklasseobjekt i stedet for et attributt. Terminsiden til Datadog, det første Google-treffet for dette søket, definerer ikke en sesjon i det hele tatt.
| Konsept | OTel GenAI semconv | Langfuse | LangSmith | OpenInference / Phoenix | Datadog |
|---|---|---|---|---|---|
| Hele samtalen | Attributtet gen_ai.conversation.id | Session (valgfri gruppering av sporinger) | Thread (via session_id / thread_id-metadata) | session.id-spennattributt | Ikke definert på terminsiden |
| Én forespørsel | Trace | Trace | Trace («a collection of runs») | Trace | Trace |
| Én operasjon | Span | Observation (span / generation / event) | Run («a span representing a single unit of work») | Span med en spanntype | Span med en spanntype |
Én kildekommentar til den første raden: session.id fra OpenInference finnes ikke i sporingsspesifikasjonen lenket ovenfor, som dekker de ti spanntypene. Den er definert i søsterfilen OpenInference semantic conventions som den unike identifikatoren for en sesjon. To filer, én spesifikasjon.
Vi fant ikke opp sammenligningen på tvers av leverandører; FutureAGI publiserer også en OTel-mot-leverandør-tabell. Våre to tillegg er sesjonsraden (FutureAGI hopper over den) og samme-ord-ulik-betydning-fellen: «observation» hos Langfuse og «run» hos LangSmith er det samme objektet som et spann, mens spanntypene til Datadog og OpenInference er forskjellige vokabularer for den samme idéen.
Langfuse kaller det en observation, LangSmith kaller det en run, Datadog kaller det et span. Samme objekt, tre dashbord som brekker når du migrerer.
Det er vår lesning av migrasjonskostnaden, ikke en påstand fra en leverandør. Men det er grunnen til at lagrede filtre, evalueringskonfigurasjoner og varselregler nøklet på «observation» eller «run» slutter å virke den dagen du bytter verktøy. Du gir ikke nytt navn til et felt. Du gir nytt navn til et nivå. Hvis du veier akkurat de to verktøyene, går Langfuse vs LangSmith-sammenligningen vår dypere i uenigheten.
Lesere har kanskje allerede Opik, PostHog, Sentry eller Weights & Biases i stacken sin; Google assosierer alle fire med llm tracing, og hver av dem mapper disse konseptene litt annerledes. Velge den riktige? Observabilitetsplattform-oversikten vår dekker feltet.
Én aktuell merknad: GenAI-konvensjonene har flyttet inn i sitt eget repository, ut av hovedrepoet semantic-conventions. Den gamle stien opentelemetry.io/docs/specs/semconv/gen-ai/ bærer nå bare en peker.
Hvilken ID hører hvor?
En sporings-ID identifiserer én forespørsel og propageres automatisk gjennom kontekst. En spenn-ID identifiserer én operasjon innenfor den sporingen, også automatisk. En korrelasjons-ID (eller forespørsels-ID) kommer fra weblaget ditt før sporingen starter, og det er den folk oftest forveksler med sporings-ID-en. Sesjons-ID-en er den som skiller seg ut: den setter du selv, manuelt, hver runde.
| ID | Satt av | Virkefelt | Forveksles med |
|---|---|---|---|
| Sporings-ID | Automatisk | Én forespørsel; propageres gjennom kontekst | Korrelasjons-ID-en fra weblaget ditt |
| Spenn-ID | Automatisk | Én operasjon | , |
| Foreldre-spenn-ID | Automatisk | Bygger treet; tom på rotspennet | , |
| Sesjons- / samtale-ID | Deg, manuelt, hver runde | Mange sporinger | Antas å propageres. Det gjør den ikke. |
| Bruker-ID | Deg, manuelt | Mange sesjoner | Sesjons-ID-en |
| Forespørsels- / korrelasjons-ID | Weblaget ditt, før sporingen starter | Én HTTP-forespørsel | Sporings-ID-en (dette er den store) |
Den praktiske regelen: legg gen_ai.conversation.id ved som et spennattributt på rotspennet til hver runde, og stemple bruker-ID-en ved siden av. Hopp over én runde, og sesjonsnivå-metrikkene dine mister den runden i stillhet.
Én advarsel om kardinalitet: bruker-ID-er og sesjons-ID-er er verdier med høy kardinalitet. Det betyr noe for indekseringsregningen til backenden din, som er problemet i neste avsnitt.
Hvor granular bør et spenn være?
To feilmoduser, begge vanlige:
For mange spenn. Et spenn per funksjonskall gir deg en 400-spenn-sporing ingen kan lese og en per-spenn-regning ingen har godkjent. Hostede backender (Datadog, Langfuse Cloud) priser etter spennvolum. En pratsom agentsløyfe som instrumenterer hver strengkonkatenering, brenner gjennom et gratisnivå på en ettermiddag.
For få spenn. Ett spenn for «hele kjeden» forteller deg at den var treg, men ikke hvor. Du ender opp med å legge til print-setninger igjen, som er det sporing skulle erstatte.
Tommelfingerregelen (og det er en tommelfingerregel, ikke en måling): spann grensene der en beslutning eller et eksternt kall skjer.
- Hentesteg: spann det.
- Rerank-kall: spann det.
- Hvert modellkall: spann det.
- Hvert verktøykall: spann det.
- Hver guardrail-kontroll: spann det.
- Rene in-prosess-transformasjoner (strengformatering, JSON-parsing, promptmontering): attributter på foreldrespennet, ikke egne spenn.
Om kardinalitet, sampling og retensjon:
- Attributter med høy kardinalitet (bruker-ID-er, hele prompter) blåser opp lagringskostnadene. Sample eller trunker dem.
- De fleste backender lar deg sample på sporingsnivå. Behold 100 % av feilsporingene; sample happy path.
- Retensjonsvinduer varierer: 7 dager på gratisnivåer, 30–90 dager på betalte. Bestem deg før du trenger dataene.
For den faktiske kostnadsmodellen bak spennvolum og per-spenn-prising, se LLM-kostnadsovervåkingsguiden vår. Vi bygger den ikke om igjen her.
Hvordan Techsy griper dette an
For agentarbeid for kunder standardiserer vi på tre regler:
- Én sporing per runde. Slå aldri sammen to brukerrunder til én sporing, selv om agenten løkker internt.
- En sesjons-ID stemplet på hvert rotspenn, satt i applikasjonskoden, aldri antatt å propageres.
- Spanntyper holdt til et lite fast sett (retrieval, inference, tool, guardrail) slik at dashbord overlever et leverandørbytte.
Den tredje regelen er den team hopper over, og det er den som redder en migrasjon. Hvis spennvokabularet ditt er bundet til en leverandørs enum, brekker hvert varsel og hver lagret visning den dagen du bytter.
Hvis du bygger et agentsystem og vil ha en andremening om sporingsarkitekturen, få en gratis konsultasjon.
Om forfatteren
Mert Batur er medgrunnlegger av Techsy.io, der teamet leverer AI-agenter, automatiseringssystemer og tale-/SDR-pipelines for B2B-kunder. Han skriver om LLM-verktøystacken Techsy-teamet faktisk bruker i produksjon. Koble deg til på LinkedIn.
Ofte stilte spørsmål
Hva er et spenn i distribuert sporing?
Et spenn er én tidsmålt arbeidsenhet: det har et navn, en starttid, en sluttid, en status og et sett med attributter. Spenn lenkes til hverandre gjennom referanser til foreldre-spenn-ID, og danner et tre. I LLM-applikasjoner omslutter et spenn vanligvis ett modellkall, én henting eller én verktøyinvokering.
Hva er et spenn i Datadog?
I LLM Observability fra Datadog er et spenn den samme tidsmålte operasjonen, men Datadog legger til en spanntype-taksonomi: LLM, Workflow, Agent, Tool, Task, Embedding og Retrieval. Bare LLM-, Workflow- og Agent-typene kan fungere som rotspenn. Taksonomien er Datadog-spesifikk; den er ikke en del av OpenTelemetry-standarden.
Hva er de fire pilarene for observabilitet?
De fire pilarene er logger, metrikker, sporinger og (avhengig av hvem sin innramming) profiler eller hendelser. Sporinger er pilaren dette innlegget lever i. LLM-tilfellet legger til en krøll: tokenforbruk og modellidentitet er attributter på sporingspenn, ikke separate metrikkstrømmer, noe som kollapser det som ville vært to pilarer til én spørring.
Hva er de fire gylne signalene for observabilitet?
Latens, trafikk, feil og metning. For LLM-systemer betyr latens tid-til-første-token og total genereringstid; trafikk betyr forespørsler per sekund per modell; feil betyr mislykkede spenn (statuskode ERROR); metning betyr oppbruk av tokenbudsjettet eller kødybde. Signalene er de samme; enhetene er forskjellige.
Er en sesjon en del av OpenTelemetry-spesifikasjonen?
Ikke som et strukturnivå. OTel GenAI-spennkonvensjonene definerer gen_ai.conversation.id som et betinget påkrevd attributt («når tilgjengelig») for å korrelere meldinger i en samtale eller tråd. Det sitter på spenn. Leverandører som Langfuse og LangSmith bygger sine egne sesjons- eller trådobjekter oppå det.
Hva er forskjellen på en sporings-ID, en spenn-ID og en korrelasjons-ID?
En sporings-ID identifiserer én forespørsel og propageres automatisk gjennom alle nedstrøms tjenester. En spenn-ID identifiserer én operasjon innenfor den sporingen. En korrelasjons-ID (eller forespørsels-ID) genereres av weblaget ditt før sporingen begynner, og er verdien folk oftest tar feil av for sporings-ID-en. De overlapper i virkefelt, men har forskjellig opphav.
Hvor mange spenn bør én sporing ha?
Det finnes ikke noe fast svar, men typiske intervaller er 3–30 for en RAG-forespørsel og 10–50+ for en agentsløyfe med flere verktøykall. Tommelfingerregelen: spann eksterne kall og beslutningspunkter, ikke in-prosess-transformasjoner. Hvis sporingen din passerer 100 spenn, instrumenterer du sannsynligvis for mye.
Er «observations» i Langfuse det samme som spenn?
Ja. En observation i Langfuse er det samme objektet som et OTel-spenn: én tidsmålt operasjon med attributter. Langfuse deler observations i tre typer (generation, span, event) der OTel bruker gen_ai.operation.name. Hvis du evaluerer verktøy som leser sporingene dine, dekker LLM-evalueringsverktøy-oversikten vår hvilke som godtar begge vokabularene.
Hvordan grupperer du en chatbotsamtale med flere runder i én sesjon?
Sett den samme samtaleidentifikatoren på rotspennet til hver runde. I OTel-termer er det gen_ai.conversation.id. I Langfuse sender du en session_id når du lager sporinger. I LangSmith setter du session_id- eller thread_id-metadata. Bom på én runde, og den runden faller ut av grupperingen.
Trenger jeg sesjoner hvis jeg bare håndterer enkeltstående forespørsler?
Sannsynligvis ikke. Sesjoner finnes for å korrelere flere sporinger til én samtale. Hvis hver forespørsel er uavhengig (et klassifiserings-API, en one-shot-oppsummerer), holder metrikker på sporingsnivå. Legg til sesjoner når du trenger metrikker på tvers av runder: løsningsrate, runder-til-svar eller kostnad på samtalenivå. LLM-evalueringsguiden vår dekker når evalueringer på sesjonsnivå er verdt det.
Den korte versjonen
Spenn nøstes inni sporinger; sporinger grupperes i sesjoner. Nøstingen er reell, men spesifikasjonen strukturerer bare to av de tre nivåene. gen_ai.conversation.id er et attributt du setter selv, ikke et foreldrespenn som propageres. Og leverandøren du velger i dag, navngir disse objektene annerledes enn leverandøren du bytter til om 18 måneder, så hold spennvokabularet lite og portabelt.
Hvis du velger en plattform, starter du med observabilitetsplattform-sammenligningen vår. Hvis du bygger evalueringer oppå sporingene dine, tar LLM-evalueringsguiden over herfra.