Skip to main content

Understanding Sessions and Events

The base unit of data in HoneyHive is an event. HoneyHive uses a “wide-event” data model, where every event carries its full context in a single record: inputs, outputs, timing, metrics, metadata, feedback, and errors. Unlike the traditional three-pillar approach (separate stores for traces, logs, and metrics joined at query time), all data for a given operation lives on one record. There is no separate log or metrics pipeline to correlate. Events form a hierarchical tree:
Tree structure of a trace showing nested eventsDetailed view of a trace in the HoneyHive UI
customer_support_session    # event_type: session (root)
├── validate_input          # event_type: tool
├── retrieve_context        # event_type: tool
├── llm_completion          # event_type: model
│   ├── prompt_preparation
│   └── api_call
└── format_response         # event_type: chain

Sessions

The root of every tree is a session. A session is itself an event with event_type: "session". It shares the same schema as every other event (inputs, outputs, metrics, etc.), but serves a specific role: it carries a session_id that all child events share to belong to the same trace. Sessions can be single-turn or multi-turn. A single-turn session groups the events from one request. A multi-turn session groups events across an entire conversation. We chose “session” over “trace” for this reason: in traditional distributed tracing, one inbound request equals one trace, and correlating multiple requests into a conversation requires external tooling. In HoneyHive, a session is the correlation unit, and it handles both cases natively.
If you’re coming from APM tools (Datadog, Jaeger, etc.): a session is equivalent to a trace, and an event is equivalent to a span. If you’re coming from LangSmith or LangFuse: the concepts map to runs/traces/spans.

Events

Child events represent discrete operations. Each has an event_type that determines what it represents:
event_typeWhat it representsExamples
modelAn LLM API requestGPT-4 completion, Claude message
toolAn external service or function callVector DB search, API call, database query
chainA logical grouping of child eventsRAG pipeline, agent workflow, multi-step reasoning
Events nest via parent_id. A chain event can contain model and tool children, and chains can nest inside other chains. This lets you represent arbitrarily complex execution graphs.

Event Schema

All event types (including sessions) share the same schema:
FieldDescription
event_idUnique identifier (UUID)
session_idShared identifier that groups all events in the same trace
parent_idLinks child to parent event (null for the session)
event_type"session", "model", "tool", or "chain"
event_nameHuman-readable operation name
start_time / end_timeTimestamps
duration_msExecution time in milliseconds
inputsInput data (messages, parameters)
outputsOutput data (responses, results)
configConfiguration (model hyperparameters, prompt template, version, git context)
metadataCustom key-value pairs
metricsNumeric measurements (latency, tokens, cost)
feedbackUser ratings, corrections
errorError details if failed
{
  "event_id": "fead4996-5bec-4710-bc71-c1f97d311782",
  "session_id": "397c9cbc-297f-42e9-bc1d-b2b0db850df5",
  "parent_id": "397c9cbc-297f-42e9-bc1d-b2b0db850df5",
  "event_type": "model",
  "event_name": "openai-chat-completion",
  "start_time": 1710147521798,
  "end_time": 1710147531367,
  "duration": 9569,
  "config": {
    "model": "gpt-4o",
    "provider": "openai",
    "temperature": 0.7,
    "max_tokens": 1024,
    "template": [
      {"role": "system", "content": "Answer using the provided context.\n\nContext: {{context}}"},
      {"role": "user", "content": "{{question}}"}
    ]
  },
  "inputs": {
    "messages": [
      {"role": "system", "content": "Answer using the provided context.\n\nContext: ..."},
      {"role": "user", "content": "How do I build an integration?"}
    ]
  },
  "outputs": {
    "choices": [
      {"message": {"role": "assistant", "content": "To build an integration, you need to..."}}
    ]
  },
  "metrics": {
    "cost": 0.0048,
    "tokens_per_second": 42.3
  },
  "metadata": {
    "total_tokens": 305,
    "prompt_tokens": 203,
    "completion_tokens": 102
  },
  "feedback": {},
  "error": null
}
For complete field types and per-event-type details, see the Python SDK schema reference.

Enriching Traces

Events are automatically populated with inputs, outputs, timing, and instrumentor-specific metadata. You can enrich any event with additional context:
  • Config: Model hyperparameters, prompt template, app version, git context, or any configuration that defines how the operation ran
  • Metadata: Custom key-value pairs (user ID, environment, request ID, etc.)
  • Metrics: Numeric scores from evaluators, custom KPIs, or business metrics
  • Feedback: End-user ratings, corrections, or thumbs up/down signals
  • User properties: User-level attributes (tier, tenant, country) for filtering and segmentation
Enrichments can be set from your application code at trace time, or added later via the API or UI. They apply to any event type, including the session itself.

Enriching Traces

How to add config, metadata, feedback, metrics, and user properties to events

OpenTelemetry Architecture

HoneyHive is built on OpenTelemetry (OTel). The SDK wraps an OTel TracerProvider and exports spans via OTLP. This means:
  • Any OTel-compatible instrumentor works with HoneyHive
  • Traces follow W3C Trace Context and are portable to other backends
  • You can export to HoneyHive and your existing backend simultaneously by adding multiple span processors

How HoneyHive Captures Data

When your application runs, data flows through several layers before reaching the HoneyHive dashboard. Your code calls an LLM provider as usual. The instrumentor (e.g. OpenAI instrumentor) intercepts that call, records the request and response as OTel span attributes, and the HoneyHive exporter sends them to the API via OTLP when each span completes.
Handling sensitive data: Instrumentors capture full request and response payloads for your LLM calls, which can include PII (names, emails, phone numbers, and similar fields). Redact or mask sensitive values in your application code before data reaches the LLM call. For organizations with strict compliance requirements, HoneyHive also offers self-hosted deployments.

Semantic Conventions

HoneyHive uses the official OTel GenAI semantic conventions as its primary standard for AI-specific attributes:
AttributeDescription
gen_ai.systemAI provider ("openai", "anthropic")
gen_ai.modelModel identifier ("gpt-4", "claude-3-opus")
gen_ai.usage.prompt_tokensInput token count
gen_ai.usage.completion_tokensOutput token count
HoneyHive also supports OpenInference and OpenLLMetry conventions, so instrumentors from either ecosystem work out of the box.

BYOI: Bring Your Own Instrumentor

The HoneyHive SDK itself has zero dependencies on AI libraries. Instrumentors (the packages that know how to trace OpenAI, Anthropic, etc.) are installed separately. This means the core SDK never conflicts with your application’s dependency versions, and you only install instrumentors for the providers you actually use. For setup, see the Quickstart or individual Integration Guides.

Context Propagation

Within a single process, trace context flows automatically. Child events created inside a traced function are linked to their parent without any manual wiring. Across service boundaries, context propagates via W3C traceparent headers. The client injects trace context into outgoing HTTP headers; the server extracts it from incoming headers. All events on the server side then join the same session as the client. The trace ID threads through every hop. In HoneyHive, all events from all services appear in a single session, giving you a unified view of the entire request. For implementation details, see Distributed Tracing.

Multi-Instance Tracing

HoneyHive supports multiple tracer instances in a single application. Each instance maintains its own session context and configuration, and can target a different project. This is relevant for multi-tenant platforms, environment-based routing, A/B testing, or isolating traces from different agents in a multi-agent system. Each tracer instance has its own OTel TracerProvider and span processor pipeline. Instances do not share context. For setup patterns, see Multi-Instance Tracing.

Sampling

High-volume applications can use sampling to control cost and overhead. HoneyHive traces asynchronously and batches span exports, so overhead is minimal, but at very high volumes you may want to selectively trace:
  • Always trace errors and high-priority requests
  • Always trace premium or flagged users
  • Sample a percentage of regular traffic
For strategies and implementation, see Sampling.