Observability conceptsEvents - Point-in-Time Occurrences
Events - Point-in-Time Occurrences
Understanding events and how they track point-in-time occurrences during trace execution
Events are point-in-time occurrences that happen during the execution of a trace or span. They provide a timeline of what happened, when it happened, and what the context was at that moment.
🎯 What are Events?
Events represent:
- State changes during operation execution
- Important milestones in your application flow
- Error conditions and recovery actions
- User interactions and system responses
- Business logic decisions and outcomes
🏗️ Event Structure
Every event has:
- Name: Descriptive name of what happened
- Timestamp: When the event occurred
- Attributes: Key-value metadata about the event
- Span Context: Which span the event belongs to
📊 Event Categories
Operation Events
# Start and completion events
span.add_event("operation.started", {
"timestamp": time.time(),
"input.size": len(input_data),
"input.type": "json"
})
span.add_event("operation.completed", {
"timestamp": time.time(),
"output.size": len(output_data),
"success": True,
"duration_ms": 1800
})AI Events
# Model selection and response events
span.add_event("ai.model.selected", {
"timestamp": time.time(),
"model": "gpt-4",
"reason": "complex_query",
"fallback_used": False
})
span.add_event("ai.response.generated", {
"timestamp": time.time(),
"tokens_used": 200,
"finish_reason": "stop",
"response_time_ms": 1800
})Business Events
# Customer interaction events
span.add_event("customer.query.received", {
"timestamp": time.time(),
"query.length": 45,
"query.sentiment": "neutral",
"customer.tier": "premium"
})
span.add_event("customer.query.processed", {
"timestamp": time.time(),
"processing_time_ms": 2000,
"confidence_score": 0.85,
"response.quality": "high"
})Error Events
# Error tracking events
span.add_event("error.occurred", {
"timestamp": time.time(),
"error.type": "APIError",
"error.message": "Rate limit exceeded",
"error.retry_count": 3,
"error.retry_after": 60
})
span.add_event("error.recovered", {
"timestamp": time.time(),
"recovery.action": "retry_with_backoff",
"recovery.success": True,
"total_retry_time_ms": 5000
})🔄 Adding Events
Basic Event
span.add_event("user.login.attempted", {
"timestamp": time.time(),
"user.id": "user_123",
"login.method": "email"
})Event with Rich Context
span.add_event("ai.model.switched", {
"timestamp": time.time(),
"from.model": "gpt-3.5-turbo",
"to.model": "gpt-4",
"reason": "complex_query_detected",
"query.complexity_score": 0.85,
"fallback.triggered": True
})Conditional Events
# Add events based on conditions
if response.confidence < 0.7:
span.add_event("low.confidence.detected", {
"timestamp": time.time(),
"confidence.score": response.confidence,
"threshold": 0.7,
"action.taken": "escalate_to_human"
})🎯 Event Naming Conventions
Hierarchical Naming
Use dot notation to create logical hierarchies:
# Customer events
"customer.query.received"
"customer.query.processed"
"customer.query.completed"
# AI events
"ai.model.selected"
"ai.response.generated"
"ai.error.occurred"
# System events
"system.cache.hit"
"system.cache.miss"
"system.retry.attempted"Action-Based Naming
Use action verbs to describe what happened:
# Good: Action-based naming
"user.login.attempted"
"user.login.succeeded"
"user.login.failed"
"ai.model.switched"
"ai.response.generated"
# Bad: State-based naming
"user.logged_in"
"ai.model_is_gpt4"
"ai.response_ready"📈 Event Attributes
Timestamp Attributes
span.add_event("operation.started", {
"timestamp": time.time(),
"timestamp.iso": "2024-01-15T10:30:00Z",
"timestamp.unix": 1705312200
})Context Attributes
span.add_event("ai.model.selected", {
"timestamp": time.time(),
"context.query_type": "technical_support",
"context.customer_tier": "premium",
"context.complexity_score": 0.85
})Result Attributes
span.add_event("ai.response.generated", {
"timestamp": time.time(),
"result.tokens_used": 200,
"result.finish_reason": "stop",
"result.quality_score": 0.92
})Error Attributes
span.add_event("error.occurred", {
"timestamp": time.time(),
"error.type": "APIError",
"error.code": 429,
"error.message": "Rate limit exceeded",
"error.retry_count": 3,
"error.retry_after": 60
})🎪 Event Patterns
Start/Complete Pattern
with trace_operation("process-query") as span:
# Start event
span.add_event("operation.started", {
"timestamp": time.time(),
"input.size": len(query),
"input.type": "text"
})
try:
# Process the query
result = process_query(query)
# Complete event
span.add_event("operation.completed", {
"timestamp": time.time(),
"output.size": len(result),
"success": True,
"duration_ms": time.time() - start_time
})
except Exception as e:
# Error event
span.add_event("operation.failed", {
"timestamp": time.time(),
"error.type": type(e).__name__,
"error.message": str(e),
"duration_ms": time.time() - start_time
})
raiseState Change Pattern
with trace_operation("ai-completion") as span:
# Initial state
span.add_event("ai.initialization", {
"timestamp": time.time(),
"model": "gpt-3.5-turbo",
"temperature": 0.7
})
# State change
if query_complexity > 0.8:
span.add_event("ai.model.upgraded", {
"timestamp": time.time(),
"from.model": "gpt-3.5-turbo",
"to.model": "gpt-4",
"reason": "high_complexity"
})
# Final state
span.add_event("ai.completion.ready", {
"timestamp": time.time(),
"final.model": "gpt-4",
"tokens.estimated": 200
})Retry Pattern
with trace_operation("api-call") as span:
retry_count = 0
max_retries = 3
while retry_count <= max_retries:
try:
span.add_event("api.call.attempted", {
"timestamp": time.time(),
"attempt": retry_count + 1,
"max_retries": max_retries
})
result = make_api_call()
span.add_event("api.call.succeeded", {
"timestamp": time.time(),
"attempt": retry_count + 1,
"duration_ms": time.time() - start_time
})
break
except Exception as e:
retry_count += 1
span.add_event("api.call.failed", {
"timestamp": time.time(),
"attempt": retry_count,
"error.type": type(e).__name__,
"error.message": str(e),
"will_retry": retry_count <= max_retries
})
if retry_count > max_retries:
raise🔍 Event Analysis
Timeline Analysis
Events provide a timeline of what happened:
# Find all events for a specific trace
events = get_trace_events(trace_id)
# Sort by timestamp
events.sort(key=lambda e: e.timestamp)
# Analyze the timeline
for event in events:
print(f"{event.timestamp}: {event.name} - {event.attributes}")Event Frequency
# Count events by type
event_counts = count_events_by_type(trace_id)
# Find common event patterns
common_events = find_common_event_patterns(traces)Error Analysis
# Find all error events
error_events = find_events(trace_id, event_name="error.occurred")
# Analyze error patterns
error_patterns = analyze_error_patterns(error_events)🚀 Next Steps
Now that you understand events, explore these related concepts:
- Traces - Complete request journeys
- Spans - Individual operations
- Attributes - Metadata and context
Best Practices
- Events Best Practices - Learn how to create effective events
Events provide the timeline and context that make your traces meaningful. They enable detailed analysis, debugging, and optimization of your AI applications.
