F
Fabra

Hooks & Extensibility

At a Glance

Base Class fabra.hooks.Hook
Register FeatureStore(hooks=[YourHook()])
Events before_feature_retrieval, after_feature_retrieval, after_ingest
Built-in WebhookHook(url="...", headers={...})

Fabra provides a powerful Hook System that allows you to intercept key lifecycle events in the Feature Store. This is useful for:

  • Validation: Check feature values before returning them.
  • Audit Logging: specific compliance logging requirements.
  • Webhooks: Notify external systems (Slack, PagerDuty, CI capabilities) when data is ingested.

The `Hook` Interface

To create a custom hook, subclass fabra.hooks.Hook and valid methods.

from fabra.hooks import Hook
from typing import List, Dict, Any
import structlog

logger = structlog.get_logger()

class AuditLogHook(Hook):
    async def before_feature_retrieval(
        self, entity_name: str, entity_id: str, features: List[str]
    ) -> None:
        logger.info("audit_access", user="system", entity=entity_name, entity_id=entity_id, features=features)

    async def after_feature_retrieval(
        self, entity_name: str, entity_id: str, features: List[str], result: Dict[str, Any]
    ) -> None:
        # Inspect values
        for k, v in result.items():
            if v is None:
                logger.warning("null_feature_detected", feature=k, entity=entity_id)

    async def after_ingest(self, event_type: str, entity_id: str, payload: Dict[str, Any]) -> None:
        logger.info("data_ingested", event=event_type, entity=entity_id)

Registering Hooks

Register your hooks when initializing the FeatureStore.

from fabra.core import FeatureStore

store = FeatureStore(
    hooks=[
        AuditLogHook(),
        # ... other hooks
    ]
)

Webhooks

Fabra includes a built-in WebhookHook to trigger external HTTP endpoints when events occur (e.g., via fabra events or the Ingest API).

Configuration

from fabra.core import FeatureStore
from fabra.hooks import WebhookHook

store = FeatureStore(
    hooks=[
        WebhookHook(
            url="https://api.example.com/webhooks/fabra",
            headers={"Authorization": "Bearer secret-token"}
        )
    ]
)

Triggering Webhooks

Webhooks are triggered automatically when you call the Ingest API:

# Function call
await store.hooks.trigger_after_ingest(
    event_type="document_updated",
    entity_id="doc_123",
    payload={"status": "indexed"}
)

Or via HTTP:

curl -X POST http://localhost:8000/v1/ingest/document_updated \
  -d '{"entity_id": "doc_123", "payload": {"status": "indexed"}}'

The external URL will receive a POST request with the event payload.

FAQ

Q: How do I add custom hooks to Fabra? A: Subclass fabra.hooks.Hook and implement the lifecycle methods (before_feature_retrieval, after_feature_retrieval, after_ingest). Register via FeatureStore(hooks=[YourHook()]).

Q: Can I add validation to feature retrieval? A: Yes. Implement before_feature_retrieval to validate inputs or after_feature_retrieval to validate/transform outputs. Raise exceptions to block invalid data.

Q: How do I send webhooks when data is ingested? A: Use the built-in WebhookHook: WebhookHook(url="https://...", headers={"Authorization": "..."}). Triggers automatically on ingest API calls.

Q: What lifecycle events can I hook into? A: Three events: before_feature_retrieval (before fetch), after_feature_retrieval (after fetch with values), after_ingest (after data written).