Skip to main content
Tags are key-value pairs that provide additional context for filtering and analysis. They’re especially useful for tracking feature flags, experiments, and custom dimensions.

Setting Tags

import proliferate

# Set individual tags
proliferate.set_tag('feature_flag', 'new_checkout_v2')
proliferate.set_tag('subscription_tier', 'premium')
proliferate.set_tag('ab_test', 'variant_b')

# All subsequent errors include these tags

Use Cases

Track which feature flags were active when errors occur:
import proliferate
from my_feature_flags import get_flags

# Set feature flag context
flags = get_flags(user_id)
for flag_name, flag_value in flags.items():
    proliferate.set_tag(f'flag_{flag_name}', str(flag_value))

# Later, if an error occurs:
# Tags show: flag_new_checkout=true, flag_dark_mode=false, ...
Filter in dashboard:
  • “Show errors where flag_new_checkout = true
  • “Compare error rates between flag variants”

Request Context

Track request-specific dimensions with middleware:
@app.middleware("http")
async def add_tags(request: Request, call_next):
    # Track API version
    api_version = request.headers.get('X-API-Version', 'v1')
    proliferate.set_tag('api_version', api_version)

    # Track client type
    client = request.headers.get('X-Client-Type', 'unknown')
    proliferate.set_tag('client_type', client)  # 'ios', 'android', 'web'

    response = await call_next(request)
    return response

Best Practices

# Good - consistent naming
proliferate.set_tag('subscription_tier', tier)
proliferate.set_tag('subscription_status', status)

# Bad - inconsistent naming
proliferate.set_tag('tier', tier)
proliferate.set_tag('subscriptionStatus', status)
proliferate.set_tag('sub-status', status)
Tags work best with a limited set of values:
# Good - low cardinality
proliferate.set_tag('tier', 'free')  # Only a few possible values
proliferate.set_tag('region', 'us-east-1')

# Bad - high cardinality (use user/account context instead)
proliferate.set_tag('user_id', user.id)  # Thousands of values
proliferate.set_tag('order_id', order.id)  # Millions of values
# Good - meaningful values
proliferate.set_tag('feature_enabled', 'true')
proliferate.set_tag('experiment_variant', 'checkout_v2')

# Bad - cryptic values
proliferate.set_tag('feature_enabled', '1')
proliferate.set_tag('experiment_variant', 'v2')
# Good - non-sensitive tags
proliferate.set_tag('account_type', 'enterprise')

# Bad - sensitive information
proliferate.set_tag('api_key', api_key)
proliferate.set_tag('credit_card_last4', card_last4)

Tag Lifecycle

Tags are scoped to the current request/context (using Python’s contextvars):
# In FastAPI middleware
@app.middleware("http")
async def setup_context(request: Request, call_next):
    # These tags apply to this request only
    proliferate.set_tag('endpoint', request.url.path)
    proliferate.set_tag('method', request.method)

    response = await call_next(request)
    # Tags are automatically cleared after request
    return response
For persistent tags, set them in your initialization:
# Set once at startup
import os

def init_proliferate():
    proliferate.init(...)

    # These tags persist for all errors
    proliferate.set_tag('service', 'payment-api')
    proliferate.set_tag('version', os.environ.get('APP_VERSION'))
    proliferate.set_tag('environment', os.environ.get('ENVIRONMENT'))

Viewing Tags in Dashboard

Tags appear in the error detail view:
Error: Payment declined
────────────────────────────────────────────
Tags:
  tier: enterprise
  experiment_checkout: variant_b
  payment_method: card
  flag_retry_logic: true

User: [email protected]
Account: Acme Corp

Filtering by Tags

In the issue list:
  1. Click Add Filter
  2. Select a tag key (e.g., tier)
  3. Choose a value (e.g., enterprise)

Tag Analysis

View tag distribution for an issue:
  • What percentage of errors are from tier=enterprise?
  • Which experiment_variant has more errors?
  • Are errors correlated with certain flag_* values?

Common Tag Patterns

Feature Rollout

proliferate.set_tag(
  'feature_new_editor',
  'enabled' if user.in_rollout else 'disabled'
)

Canary Deployments

proliferate.set_tag(
  'deployment',
  'canary' if is_canary() else 'stable'
)

Geographic Context

proliferate.set_tag(
  'region',
  request.headers.get('CF-IPCountry', 'unknown')
)

Performance Tiers

if response_time > 1000:
    proliferate.set_tag('latency_class', 'slow')
elif response_time > 100:
    proliferate.set_tag('latency_class', 'normal')
else:
    proliferate.set_tag('latency_class', 'fast')

JavaScript Equivalent

While Python has set_tag(), in JavaScript you achieve similar functionality with extra:
// Set tags per-error
Proliferate.captureException(error, {
  extra: {
    tier: 'enterprise',
    feature_flag: 'new_checkout',
    experiment: 'variant_b',
  },
});

// Or add context that persists
// (stored in your app state, included with each capture)
function captureWithContext(error) {
  Proliferate.captureException(error, {
    extra: {
      ...getGlobalTags(),  // Your function that returns current tags
    },
  });
}