Context¶
The EvaluationContext provides attributes for targeting rules and percentage
rollouts during flag evaluation. It follows the OpenFeature specification patterns.
Overview¶
The context is an immutable dataclass that carries information about the current evaluation request. This includes:
Targeting key: Primary identifier for consistent hashing in percentage rollouts
User attributes: User ID, organization, tenant for user-level targeting
Environment info: Environment name, app version for deployment-based rules
Custom attributes: Flexible key-value pairs for any targeting logic
Request metadata: IP address, user agent, country for request-level targeting
Key Features:
Immutable by design (frozen dataclass)
Flexible attribute access via
get()methodMerge support for combining contexts
Builder-style methods for creating variations
Quick Example¶
from litestar_flags import EvaluationContext
# Create a context for a specific user
context = EvaluationContext(
targeting_key="user-123",
user_id="user-123",
organization_id="org-456",
environment="production",
attributes={
"plan": "premium",
"beta_tester": True,
"signup_date": "2024-01-15",
},
)
# Access attributes
plan = context.get("plan") # "premium"
beta = context.get("beta_tester") # True
API Reference¶
Evaluation context for feature flag evaluation.
- class litestar_flags.context.EvaluationContext[source]¶
Bases:
objectImmutable context for flag evaluation.
Follows OpenFeature specification patterns. The context provides attributes that can be used for targeting rules and percentage rollouts.
- targeting_key¶
Primary identifier for consistent hashing in percentage rollouts.
- user_id¶
User identifier for user-level targeting.
- organization_id¶
Organization identifier for org-level targeting.
- tenant_id¶
Tenant identifier for multi-tenant applications.
- environment¶
Environment name (e.g., “production”, “staging”).
- app_version¶
Application version for version-based rollouts.
- attributes¶
Custom attributes for flexible targeting rules.
- ip_address¶
Client IP address (can be auto-populated by middleware).
- user_agent¶
Client user agent string.
- country¶
Country code (e.g., “US”, “GB”).
- timestamp¶
Evaluation timestamp for time-based rules.
Example
>>> context = EvaluationContext( ... targeting_key="user-123", ... user_id="user-123", ... attributes={"plan": "premium", "beta_tester": True}, ... ) >>> context.get("plan") 'premium'
- Parameters:
- merge(other)[source]¶
Merge with another context (other takes precedence).
Creates a new context with values from both contexts, where the other context’s values override this context’s values.
- Parameters:
other (
EvaluationContext) – The context to merge with (takes precedence).- Return type:
- Returns:
A new merged EvaluationContext.
- with_targeting_key(targeting_key)[source]¶
Create a new context with an updated targeting key.
- Parameters:
targeting_key (
str) – The new targeting key.- Return type:
- Returns:
A new EvaluationContext with the updated targeting key.
- with_attributes(**kwargs)[source]¶
Create a new context with additional attributes.
- Parameters:
**kwargs (
Any) – Additional attributes to add.- Return type:
- Returns:
A new EvaluationContext with the additional attributes.
- __init__(targeting_key=None, user_id=None, organization_id=None, tenant_id=None, environment=None, app_version=None, attributes=<factory>, ip_address=None, user_agent=None, country=None, timestamp=<factory>)¶
Creating Contexts¶
Basic Context¶
# Minimal context with just a targeting key
context = EvaluationContext(targeting_key="user-123")
# User context with common attributes
context = EvaluationContext(
targeting_key="user-123",
user_id="user-123",
organization_id="org-456",
environment="production",
)
With Custom Attributes¶
context = EvaluationContext(
targeting_key="user-123",
attributes={
"plan": "enterprise",
"feature_tier": 3,
"enabled_addons": ["analytics", "export"],
"created_at": "2024-01-01",
},
)
Request Context¶
For request-level targeting (often populated by middleware):
context = EvaluationContext(
targeting_key="user-123",
ip_address="192.168.1.1",
user_agent="Mozilla/5.0...",
country="US",
)
Accessing Attributes¶
The get() method provides unified access to both standard and custom attributes:
context = EvaluationContext(
user_id="user-123",
attributes={"plan": "premium"},
)
# Access standard attributes
user_id = context.get("user_id") # "user-123"
# Access custom attributes
plan = context.get("plan") # "premium"
# Default values for missing attributes
tier = context.get("tier", default="free") # "free"
Modifying Contexts¶
Since contexts are immutable, modification methods return new instances:
With New Targeting Key¶
base_context = EvaluationContext(
user_id="user-123",
environment="production",
)
# Create a new context with different targeting key
session_context = base_context.with_targeting_key("session-abc")
With Additional Attributes¶
base_context = EvaluationContext(
targeting_key="user-123",
attributes={"plan": "free"},
)
# Add new attributes (original attributes are preserved)
upgraded_context = base_context.with_attributes(
plan="premium",
upgraded_at="2024-06-01",
)
Merging Contexts¶
Merge two contexts, with the second context taking precedence:
default_context = EvaluationContext(
environment="production",
attributes={"version": "1.0"},
)
request_context = EvaluationContext(
targeting_key="user-123",
user_id="user-123",
attributes={"source": "api"},
)
# Merge: request_context values override default_context
merged = default_context.merge(request_context)
# Result has: environment="production", targeting_key="user-123",
# user_id="user-123", attributes={"version": "1.0", "source": "api"}
Integration with Middleware¶
When using the FeatureFlagsMiddleware, context can be automatically extracted
from requests:
from litestar_flags import (
FeatureFlagsConfig,
FeatureFlagsPlugin,
EvaluationContext,
)
def extract_context(request) -> EvaluationContext:
"""Custom context extractor."""
return EvaluationContext(
targeting_key=str(request.user.id) if request.user else None,
user_id=str(request.user.id) if request.user else None,
ip_address=request.client.host if request.client else None,
user_agent=request.headers.get("user-agent"),
)
config = FeatureFlagsConfig(
backend="memory",
enable_middleware=True,
context_extractor=extract_context,
)