Span Data Models

Note

Technical specification for HoneyHive span data structures

This document defines the exact data models and formats used for spans in the HoneyHive SDK, which follow OpenTelemetry specifications.

Spans represent units of work in a distributed trace, providing detailed timing and context information for operations in your LLM application.

Core Span Model

class Span

The primary span data structure based on OpenTelemetry standards.

span_id: str

Unique identifier for this span.

Format: 16-character hexadecimal string (8 bytes) Example: "a1b2c3d4e5f6g7h8" Required: Auto-generated by SDK

trace_id: str

Unique identifier for the entire trace.

Format: 32-character hexadecimal string (16 bytes) Example: "1a2b3c4d5e6f7g8h9i0j1k2l3m4n5o6p" Required: Auto-generated by SDK

parent_span_id: str | None

Parent span identifier for nested operations.

Format: 16-character hexadecimal string (8 bytes) Example: "b2c3d4e5f6g7h8i9" Required: No (None for root spans)

operation_name: str

Name of the operation represented by this span.

Format: Descriptive string, typically kebab-case Example: "llm-chat-completion" Required: Yes

start_time: int

Span start time in nanoseconds since Unix epoch.

Format: 64-bit integer (nanoseconds) Example: 1642253445123456789 Required: Auto-generated by SDK

end_time: int | None

Span end time in nanoseconds since Unix epoch.

Format: 64-bit integer (nanoseconds) Example: 1642253447654321987 Required: Auto-generated when span ends

duration_ns: int | None

Span duration in nanoseconds.

Calculation: end_time - start_time Example: 2530865198 Required: Auto-calculated by SDK

status: SpanStatus

Span completion status.

Structure:

{
  "code": "OK",
  "message": "Operation completed successfully"
}

Status Codes: - "UNSET" - Default status - "OK" - Operation completed successfully - "ERROR" - Operation failed

Required: Auto-determined by SDK

attributes: Dict[str, str | int | float | bool]

Key-value pairs providing additional context.

Restrictions: - Keys must be strings - Values must be primitives (string, int, float, bool) - Arrays of primitives are also supported

Example:

{
  "llm.model": "gpt-3.5-turbo",
  "llm.provider": "openai",
  "llm.temperature": 0.7,
  "llm.max_tokens": 150,
  "llm.streaming": false,
  "http.status_code": 200,
  "operation.timeout_ms": 30000
}

Required: No

events: List[SpanEvent]

Timestamped events that occurred during the span.

Structure: List of SpanEvent objects Required: No

Links to other spans (causally related).

Structure: List of SpanLink objects Required: No

resource: Resource

Resource information (service, instance, etc.).

Structure: Resource object Required: Yes (auto-populated by SDK)

instrumentation_scope: InstrumentationScope

Information about the instrumentation library.

Structure: InstrumentationScope object Required: Yes (auto-populated by SDK)

Span Event Model

class SpanEvent

Represents a timestamped event within a span.

name: str

Event name.

Example: "request_started", "cache_miss", "retry_attempt" Required: Yes

timestamp: int

Event timestamp in nanoseconds since Unix epoch.

Format: 64-bit integer (nanoseconds) Example: 1642253445500000000 Required: Yes

attributes: Dict[str, str | int | float | bool] | None

Event-specific attributes.

Example:

{
  "retry.attempt": 2,
  "retry.reason": "rate_limit",
  "retry.delay_ms": 1000
}

Required: No

Example Span Event:

{
  "name": "llm_response_received",
  "timestamp": 1642253446123456789,
  "attributes": {
    "response.token_count": 42,
    "response.finish_reason": "stop",
    "response.cached": false
  }
}

Resource Model

class Resource

Represents the entity producing telemetry.

attributes: Dict[str, str | int | float | bool]

Resource attributes following OpenTelemetry semantic conventions.

Common Attributes:

{
  "service.name": "my-llm-app",
  "service.version": "1.2.0",
  "service.instance.id": "instance-001",
  "deployment.environment": "production",
  "host.name": "server-01",
  "process.pid": 12345,
  "telemetry.sdk.name": "honeyhive",
  "telemetry.sdk.version": "0.1.0",
  "telemetry.sdk.language": "python"
}

Required: Yes (auto-populated by SDK)

Instrumentation Scope Model

class InstrumentationScope

Information about the instrumentation library that created the span.

name: str

Name of the instrumentation library.

Example: "honeyhive-python" Required: Yes

version: str | None

Version of the instrumentation library.

Example: "0.1.0" Required: No

schema_url: str | None

Schema URL for semantic conventions.

Example: "https://opentelemetry.io/schemas/1.21.0" Required: No

HoneyHive Span Extensions

In addition to standard OpenTelemetry fields, HoneyHive adds specialized attributes for LLM observability:

LLM Attributes:

{
  "llm.provider": "openai",
  "llm.model": "gpt-3.5-turbo-0613",
  "llm.temperature": 0.7,
  "llm.max_tokens": 150,
  "llm.top_p": 1.0,
  "llm.frequency_penalty": 0.0,
  "llm.presence_penalty": 0.0,
  "llm.streaming": false,
  "llm.function_call": "auto",
  "llm.tools_count": 3
}

Token Usage Attributes:

{
  "llm.usage.prompt_tokens": 50,
  "llm.usage.completion_tokens": 75,
  "llm.usage.total_tokens": 125,
  "llm.usage.cache_hit_tokens": 20,
  "llm.usage.cache_miss_tokens": 30
}

Cost Attributes:

{
  "llm.cost.prompt_cost_usd": 0.0001,
  "llm.cost.completion_cost_usd": 0.00015,
  "llm.cost.total_cost_usd": 0.00025,
  "llm.cost.currency": "USD"
}

Request/Response Attributes:

{
  "llm.request.type": "chat",
  "llm.request.message_count": 3,
  "llm.request.system_message": true,
  "llm.response.finish_reason": "stop",
  "llm.response.choice_count": 1,
  "llm.response.logprobs": false
}

Error Attributes:

{
  "error.type": "RateLimitError",
  "error.message": "Rate limit exceeded",
  "error.code": "rate_limit_exceeded",
  "error.retry_after_s": 60,
  "error.request_id": "req_abc123"
}

Performance Attributes:

{
  "performance.latency_ms": 1250.5,
  "performance.queue_time_ms": 45.2,
  "performance.processing_time_ms": 1205.3,
  "performance.tokens_per_second": 60.8,
  "performance.cache_hit_rate": 0.75
}

User/Session Attributes:

{
  "user.id": "user_12345",
  "user.tier": "premium",
  "session.id": "session_abcdef",
  "session.turn": 3,
  "conversation.id": "conv_xyz789"
}

Span Context Model

class SpanContext

Represents the portion of a span that must be propagated to child spans.

trace_id: str

Trace identifier.

Format: 32-character hexadecimal string Required: Yes

span_id: str

Span identifier.

Format: 16-character hexadecimal string Required: Yes

trace_flags: int

Trace flags (typically 0x01 for sampled).

Values: 8-bit integer Required: Yes

trace_state: str | None

Vendor-specific trace state.

Format: Comma-separated key-value pairs Example: "honeyhive=abc123,vendor2=xyz789" Required: No

is_remote: bool

Whether this context was propagated from a remote parent.

Required: Yes

Complete Span Example

Full LLM Span:

{
  "span_id": "a1b2c3d4e5f6g7h8",
  "trace_id": "1a2b3c4d5e6f7g8h9i0j1k2l3m4n5o6p",
  "parent_span_id": "b2c3d4e5f6g7h8i9",
  "operation_name": "openai-chat-completion",
  "start_time": 1642253445123456789,
  "end_time": 1642253447654321987,
  "duration_ns": 2530865198,
  "status": {
    "code": "OK",
    "message": "Request completed successfully"
  },
  "attributes": {
    "llm.provider": "openai",
    "llm.model": "gpt-3.5-turbo",
    "llm.temperature": 0.7,
    "llm.max_tokens": 150,
    "llm.usage.prompt_tokens": 50,
    "llm.usage.completion_tokens": 75,
    "llm.usage.total_tokens": 125,
    "llm.cost.total_cost_usd": 0.00025,
    "http.method": "POST",
    "http.url": "https://api.openai.com/v1/chat/completions",
    "http.status_code": 200,
    "user.id": "user_12345",
    "session.id": "session_abcdef"
  },
  "events": [
    {
      "name": "request_started",
      "timestamp": 1642253445123456789,
      "attributes": {
        "request.size_bytes": 1024
      }
    },
    {
      "name": "response_received",
      "timestamp": 1642253447600000000,
      "attributes": {
        "response.size_bytes": 2048,
        "response.cached": false
      }
    }
  ],
  "links": [],
  "resource": {
    "attributes": {
      "service.name": "my-llm-app",
      "service.version": "1.2.0",
      "deployment.environment": "production",
      "telemetry.sdk.name": "honeyhive",
      "telemetry.sdk.version": "0.1.0"
    }
  },
  "instrumentation_scope": {
    "name": "honeyhive-python",
    "version": "0.1.0",
    "schema_url": "https://opentelemetry.io/schemas/1.21.0"
  }
}

Trace Hierarchy Example

Parent-Child Span Relationship:

{
  "trace_id": "1a2b3c4d5e6f7g8h9i0j1k2l3m4n5o6p",
  "spans": [
    {
      "span_id": "root00000000",
      "parent_span_id": null,
      "operation_name": "rag-pipeline",
      "attributes": {
        "pipeline.type": "rag",
        "pipeline.version": "v2"
      }
    },
    {
      "span_id": "search000000",
      "parent_span_id": "root00000000",
      "operation_name": "vector-search",
      "attributes": {
        "search.query": "What is machine learning?",
        "search.top_k": 5,
        "search.similarity_threshold": 0.8
      }
    },
    {
      "span_id": "llm000000000",
      "parent_span_id": "root00000000",
      "operation_name": "llm-generation",
      "attributes": {
        "llm.provider": "openai",
        "llm.model": "gpt-3.5-turbo",
        "llm.context_length": 4096
      }
    }
  ]
}

Span Sampling

Sampling Decision:

Spans can be sampled based on various criteria:

{
  "trace_flags": 1,
  "sampling": {
    "decision": "RECORD_AND_SAMPLE",
    "probability": 0.1,
    "reason": "TraceIdRatioBasedSampler",
    "attributes": {
      "sampling.rule": "high_value_users",
      "sampling.tier": "premium"
    }
  }
}

Sampling Strategies:

  • Rate-based: Sample a percentage of traces

  • Adaptive: Adjust sampling based on traffic volume

  • Rule-based: Sample based on attributes (user tier, error status)

  • Tail-based: Sample entire traces based on downstream criteria

Span Export Format

OTLP Format (OpenTelemetry Protocol):

The SDK supports both Protobuf (default) and JSON formats for OTLP export. Set the HH_OTLP_PROTOCOL environment variable to http/json to use JSON format, or http/protobuf (default) for Protobuf format.

{
  "resource_spans": [
    {
      "resource": {
        "attributes": [
          {"key": "service.name", "value": {"string_value": "my-service"}}
        ]
      },
      "scope_spans": [
        {
          "scope": {
            "name": "honeyhive-python",
            "version": "0.1.0"
          },
          "spans": [
            {
              "trace_id": "base64EncodedTraceId",
              "span_id": "base64EncodedSpanId",
              "name": "operation-name",
              "start_time_unix_nano": 1642253445123456789,
              "end_time_unix_nano": 1642253447654321987,
              "attributes": [
                {"key": "llm.model", "value": {"string_value": "gpt-3.5-turbo"}}
              ]
            }
          ]
        }
      ]
    }
  ]
}

HoneyHive Format (Enhanced):

{
  "spans": [
    {
      "span_id": "a1b2c3d4e5f6g7h8",
      "trace_id": "1a2b3c4d5e6f7g8h9i0j1k2l3m4n5o6p",
      "operation_name": "llm-call",
      "honeyhive": {
        "project": "my-project",
        "session_id": "session_abc",
        "event_id": "event_123",
        "evaluation_scores": {
          "relevance": 0.85,
          "accuracy": 0.92
        }
      }
    }
  ]
}

Best Practices

Span Design Guidelines:

  1. Meaningful Names: Use descriptive operation names that clearly indicate what work is being done

  2. Appropriate Granularity: Create spans for significant operations, avoid over-instrumentation

  3. Rich Attributes: Add relevant attributes that aid in debugging and analysis

  4. Error Handling: Always set error status and attributes when operations fail

  5. Resource Attribution: Include user, session, and business context

  6. Performance Metrics: Capture relevant timing and throughput metrics

Attribute Naming:

Follow OpenTelemetry semantic conventions:

  • Use lowercase with underscores: llm.model, http.status_code

  • Namespace related attributes: llm.*, db.*, http.*

  • Use consistent units: _ms for milliseconds, _bytes for bytes

  • Avoid sensitive data: Don’t include API keys, passwords, PII

Performance Considerations:

  1. Attribute Limits: Be mindful of attribute count and size limits

  2. Event Usage: Use events sparingly for significant occurrences only

  3. Link Usage: Use links judiciously to avoid circular references

  4. Sampling: Implement appropriate sampling to control data volume

See Also