OutlabsAuth
Reference

Log Events Reference

Structured log event catalog.
— structured log event catalog. Setup: Observability.

Lookup page — jump to the event name you need. For integration modes and host ownership rules, start with 97.

Overview

OutlabsAuth emits structured log events for auth-domain operations. Each event has a consistent schema plus event-specific fields.

Standard fields (most events):

  • timestamp — ISO 8601 UTC
  • level — debug / info / warning / error / critical
  • event — event name (e.g. user_login_success)
  • correlation_id — request correlation id when present
  • service — typically outlabs_auth

Often present: user_id, email (if not redacted), ip_address, user_agent, duration_ms.


Authentication Events

user_login_success

Level: INFO When: User successfully logs in with any authentication method Frequency: Per login (moderate volume)

Fields:

  • user_id (string) - User's ID
  • email (string) - User's email
  • method (string) - Auth method: password, google, facebook, apple, github, api_key
  • duration_ms (float) - Time taken for login operation
  • ip_address (string, optional) - Client IP address
  • user_agent (string, optional) - Client user agent
  • device_name (string, optional) - Device name if provided

Example:

{
  "timestamp": "2025-01-24T10:15:23.456Z",
  "level": "info",
  "event": "user_login_success",
  "correlation_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "service": "outlabs_auth",
  "user_id": "3f8a1c2e-7b4d-4e19-9a52-8c6f0d1b3e47",
  "email": "john@example.com",
  "method": "password",
  "duration_ms": 145.3,
  "ip_address": "192.168.1.1",
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)..."
}

Search Examples:

Terminal
# Find all logins by specific user
jq 'select(.event == "user_login_success" and .user_id == "3f8a1c2e-...")' app.log

# Find all Google OAuth logins
jq 'select(.event == "user_login_success" and .method == "google")' app.log

# Find slow logins (>500ms)
jq 'select(.event == "user_login_success" and .duration_ms > 500)' app.log

user_login_failed

Level: WARNING When: Login attempt fails Frequency: Per failed login (should be low, spikes indicate attacks)

Fields:

  • email (string, optional) - Email attempted (may be invalid)
  • method (string) - Auth method attempted
  • reason (string) - Failure reason:
    • invalid_credentials - Wrong password
    • user_not_found - Email doesn't exist
    • account_locked - Too many failed attempts
    • account_suspended - Account suspended by admin
    • account_deleted - Account has been deleted
    • email_not_verified - Email verification required
    • oauth_error - OAuth provider error
  • duration_ms (float) - Time taken
  • ip_address (string, optional) - Client IP
  • user_agent (string, optional) - Client user agent
  • failed_attempts (int, optional) - Current failed attempt count

Example:

{
  "timestamp": "2025-01-24T10:16:45.123Z",
  "level": "warning",
  "event": "user_login_failed",
  "correlation_id": "b2c3d4e5-f6a7-8901-bcde-f23456789abc",
  "service": "outlabs_auth",
  "email": "john@example.com",
  "method": "password",
  "reason": "invalid_credentials",
  "duration_ms": 98.2,
  "ip_address": "192.168.1.1",
  "failed_attempts": 3
}

Search Examples:

Terminal
# Find all failed login attempts
jq 'select(.event == "user_login_failed")' app.log

# Find brute force attempts (multiple failures from same IP)
jq 'select(.event == "user_login_failed") | .ip_address' app.log | sort | uniq -c | sort -rn

# Find accounts being targeted
jq 'select(.event == "user_login_failed") | .email' app.log | sort | uniq -c | sort -rn

user_logout

Level: INFO When: User logs out (explicit or token expiry) Frequency: Per logout (moderate volume)

Fields:

  • user_id (string) - User's ID
  • email (string) - User's email
  • method (string) - Logout trigger:
    • explicit - User clicked logout
    • token_expiry - Refresh token expired
    • admin_revoke - Admin revoked session
    • security_revoke - Revoked for security reasons
  • session_duration_seconds (int) - How long user was logged in

Example:

{
  "timestamp": "2025-01-24T12:30:15.789Z",
  "level": "info",
  "event": "user_logout",
  "correlation_id": "c3d4e5f6-a7b8-9012-cdef-34567890abcd",
  "service": "outlabs_auth",
  "user_id": "3f8a1c2e-7b4d-4e19-9a52-8c6f0d1b3e47",
  "email": "john@example.com",
  "method": "explicit",
  "session_duration_seconds": 7892
}

token_refreshed

Level: INFO When: Access token successfully refreshed Frequency: High volume (every 15 minutes per active user) Default: Not logged (use metrics instead)

Fields:

  • user_id (string) - User's ID
  • duration_ms (float) - Refresh operation duration

Example:

{
  "timestamp": "2025-01-24T10:30:00.123Z",
  "level": "info",
  "event": "token_refreshed",
  "correlation_id": "d4e5f6a7-b8c9-0123-def4-567890abcdef",
  "service": "outlabs_auth",
  "user_id": "3f8a1c2e-7b4d-4e19-9a52-8c6f0d1b3e47",
  "duration_ms": 12.5
}

token_refresh_failed

Level: WARNING When: Token refresh fails (invalid or expired refresh token) Frequency: Low (users need to re-login when this happens)

Fields:

  • reason (string) - Failure reason:
    • invalid_token - Token malformed or doesn't exist
    • expired_token - Refresh token expired
    • revoked_token - Token was revoked
    • user_not_found - User deleted

Example:

{
  "timestamp": "2025-01-24T10:31:00.456Z",
  "level": "warning",
  "event": "token_refresh_failed",
  "correlation_id": "e5f6a7b8-c9d0-1234-ef56-7890abcdef01",
  "service": "outlabs_auth",
  "reason": "expired_token"
}

account_locked

Level: WARNING When: Account locked due to failed login attempts Frequency: Low (should be rare, spikes indicate attacks)

Fields:

  • user_id (string) - User's ID
  • email (string) - User's email
  • failed_attempts (int) - Number of failed attempts that triggered lockout
  • locked_until (string, optional) - ISO timestamp when lock expires (if temporary)
  • ip_address (string, optional) - Last IP address that attempted login

Example:

{
  "timestamp": "2025-01-24T10:20:00.789Z",
  "level": "warning",
  "event": "account_locked",
  "correlation_id": "f6a7b8c9-d0e1-2345-f678-90abcdef0123",
  "service": "outlabs_auth",
  "user_id": "3f8a1c2e-7b4d-4e19-9a52-8c6f0d1b3e47",
  "email": "john@example.com",
  "failed_attempts": 5,
  "locked_until": "2025-01-24T11:20:00.000Z",
  "ip_address": "192.168.1.1"
}

Search Examples:

Terminal
# Find all locked accounts today
jq 'select(.event == "account_locked")' app.log | jq -r '.email' | sort | uniq

# Find IPs causing lockouts
jq 'select(.event == "account_locked") | .ip_address' app.log | sort | uniq -c

Authorization Events

permission_check_granted

Level: DEBUG When: Permission check allows access Frequency: Very high volume Default: Not logged (use log_permission_checks="all" to enable)

Fields:

  • user_id (string) - User's ID
  • permission (string) - Permission checked (e.g., user:read)
  • resource_id (string, optional) - Specific resource being accessed
  • entity_id (string, optional) - Entity context (EnterpriseRBAC)
  • duration_ms (float) - Time taken for check

Example:

{
  "timestamp": "2025-01-24T10:15:30.123Z",
  "level": "debug",
  "event": "permission_check_granted",
  "correlation_id": "a7b8c9d0-e1f2-3456-789a-bcdef0123456",
  "service": "outlabs_auth",
  "user_id": "3f8a1c2e-7b4d-4e19-9a52-8c6f0d1b3e47",
  "permission": "user:read",
  "duration_ms": 2.3
}

permission_check_denied

Level: WARNING When: Permission check denies access Frequency: Should be low (high rates indicate misconfigured roles) Default: Always logged (can disable with log_permission_checks="none")

Fields:

  • user_id (string) - User's ID
  • email (string, optional) - User's email
  • permission (string) - Permission checked
  • resource_id (string, optional) - Specific resource
  • entity_id (string, optional) - Entity context
  • duration_ms (float) - Time taken
  • reason (string, optional) - Denial reason:
    • no_permission - User doesn't have permission
    • abac_denied - ABAC condition failed
    • entity_denied - Not member of required entity
    • inactive_user - User account inactive

Example:

{
  "timestamp": "2025-01-24T10:16:00.456Z",
  "level": "warning",
  "event": "permission_check_denied",
  "correlation_id": "b8c9d0e1-f2a3-4567-890b-cdef01234567",
  "service": "outlabs_auth",
  "user_id": "3f8a1c2e-7b4d-4e19-9a52-8c6f0d1b3e47",
  "email": "john@example.com",
  "permission": "user:delete",
  "reason": "no_permission",
  "duration_ms": 3.1
}

Search Examples:

Terminal
# Find all denied permissions
jq 'select(.event == "permission_check_denied")' app.log

# Top denied permissions
jq 'select(.event == "permission_check_denied") | .permission' app.log | sort | uniq -c | sort -rn

# Users experiencing denials
jq 'select(.event == "permission_check_denied") | .email' app.log | sort | uniq -c

permission_check_slow

Level: WARNING When: Permission check takes >100ms (performance issue) Frequency: Should be rare Default: Always logged

Fields:

  • user_id (string) - User's ID
  • permission (string) - Permission checked
  • entity_id (string, optional) - Entity context
  • duration_ms (float) - Time taken (>100ms)
  • hierarchy_depth (int, optional) - Entity hierarchy depth traversed
  • abac_conditions_evaluated (int, optional) - Number of ABAC conditions

Example:

{
  "timestamp": "2025-01-24T10:17:00.789Z",
  "level": "warning",
  "event": "permission_check_slow",
  "correlation_id": "c9d0e1f2-a3b4-5678-901c-def012345678",
  "service": "outlabs_auth",
  "user_id": "3f8a1c2e-7b4d-4e19-9a52-8c6f0d1b3e47",
  "permission": "lead:read_tree",
  "entity_id": "ent_workspace_abc123",
  "duration_ms": 156.7,
  "hierarchy_depth": 8,
  "abac_conditions_evaluated": 3
}

API Key Events

api_key_validated

Level: DEBUG When: API key successfully validated Frequency: Very high volume Default: Not logged (use log_api_key_hits=True to enable)

Fields:

  • api_key_prefix (string) - First 12 chars of API key (e.g., sk_live_abc1)
  • api_key_id (string) - API key ID
  • user_id (string, optional) - Associated user ID
  • duration_ms (float) - Validation time

Example:

{
  "timestamp": "2025-01-24T10:18:00.123Z",
  "level": "debug",
  "event": "api_key_validated",
  "correlation_id": "d0e1f2a3-b4c5-6789-012d-ef0123456789",
  "service": "outlabs_auth",
  "api_key_prefix": "sk_live_abc1",
  "api_key_id": "key_123456",
  "duration_ms": 1.2
}

api_key_validation_failed

Level: WARNING When: API key validation fails Frequency: Should be low (spikes indicate scanning attacks)

Fields:

  • api_key_prefix (string, optional) - Prefix if key format is valid
  • reason (string) - Failure reason:
    • invalid_format - Malformed API key
    • not_found - API key doesn't exist
    • expired - API key expired
    • disabled - API key was disabled
    • rate_limited - Rate limit exceeded
  • ip_address (string, optional) - Client IP

Example:

{
  "timestamp": "2025-01-24T10:19:00.456Z",
  "level": "warning",
  "event": "api_key_validation_failed",
  "correlation_id": "e1f2a3b4-c5d6-7890-123e-f01234567890",
  "service": "outlabs_auth",
  "api_key_prefix": "sk_live_xyz9",
  "reason": "not_found",
  "ip_address": "203.0.113.42"
}

Search Examples:

Terminal
# Find invalid API key attempts
jq 'select(.event == "api_key_validation_failed")' app.log

# Find API key scanning attacks (invalid formats)
jq 'select(.event == "api_key_validation_failed" and .reason == "invalid_format")' app.log

# IPs attempting invalid keys
jq 'select(.event == "api_key_validation_failed") | .ip_address' app.log | sort | uniq -c

api_key_rate_limit_exceeded

Level: WARNING When: API key hits rate limit Frequency: Depends on usage patterns

Fields:

  • api_key_prefix (string) - API key prefix
  • api_key_id (string) - API key ID
  • rate_limit (int) - Configured rate limit (requests per minute)
  • current_rate (int) - Current request rate

Example:

{
  "timestamp": "2025-01-24T10:20:00.789Z",
  "level": "warning",
  "event": "api_key_rate_limit_exceeded",
  "correlation_id": "f2a3b4c5-d6e7-8901-234f-012345678901",
  "service": "outlabs_auth",
  "api_key_prefix": "sk_live_abc1",
  "api_key_id": "key_123456",
  "rate_limit": 1000,
  "current_rate": 1247
}

Security Events

suspicious_activity_detected

Level: WARNING / ERROR When: Suspicious activity patterns detected Frequency: Should be rare

Fields:

  • type (string) - Activity type:
    • brute_force - Multiple failed logins
    • session_hijack - IP/user agent changed mid-session
    • rate_limit_abuse - Excessive requests
    • invalid_token_flood - Many invalid tokens
    • api_key_scanning - Scanning for valid API keys
  • user_id (string, optional) - Affected user
  • email (string, optional) - User email
  • ip_address (string, optional) - Suspicious IP
  • details (object) - Additional context

Example:

{
  "timestamp": "2025-01-24T10:21:00.123Z",
  "level": "error",
  "event": "suspicious_activity_detected",
  "correlation_id": "a3b4c5d6-e7f8-9012-345a-123456789012",
  "service": "outlabs_auth",
  "type": "brute_force",
  "email": "target@example.com",
  "ip_address": "203.0.113.42",
  "details": {
    "failed_attempts": 50,
    "time_window_minutes": 5,
    "accounts_targeted": 12
  }
}

session_hijack_suspected

Level: ERROR When: Session shows signs of hijacking Frequency: Should be very rare

Fields:

  • user_id (string) - User's ID
  • email (string) - User's email
  • reason (string) - Detection reason:
    • ip_changed - IP address changed during session
    • user_agent_changed - User agent changed
    • location_anomaly - Geographic location jumped
  • original_ip (string, optional) - Original IP
  • new_ip (string, optional) - New IP
  • original_user_agent (string, optional) - Original user agent
  • new_user_agent (string, optional) - New user agent

Example:

{
  "timestamp": "2025-01-24T10:22:00.456Z",
  "level": "error",
  "event": "session_hijack_suspected",
  "correlation_id": "b4c5d6e7-f8a9-0123-456b-234567890123",
  "service": "outlabs_auth",
  "user_id": "3f8a1c2e-7b4d-4e19-9a52-8c6f0d1b3e47",
  "email": "john@example.com",
  "reason": "ip_changed",
  "original_ip": "192.168.1.1",
  "new_ip": "203.0.113.99"
}

Performance Events

cache_invalidated

Level: DEBUG When: Cache entry invalidated (Redis pub/sub) Frequency: Per cache invalidation

Fields:

  • cache_type (string) - Type: permission, role, user, entity
  • cache_key (string) - Invalidated key
  • reason (string) - Invalidation reason:
    • update - Data was updated
    • delete - Data was deleted
    • ttl_expired - TTL expired
    • manual_flush - Manually flushed

Example:

{
  "timestamp": "2025-01-24T10:23:00.789Z",
  "level": "debug",
  "event": "cache_invalidated",
  "correlation_id": "c5d6e7f8-a9b0-1234-567c-345678901234",
  "service": "outlabs_auth",
  "cache_type": "permission",
  "cache_key": "perm:3f8a1c2e-7b4d-4e19-9a52-8c6f0d1b3e47:user:read",
  "reason": "update"
}

db_query

Level: DEBUG When: Every SQL statement executed, when log_db_queries=TrueFrequency: Very high - enabled only in development/debug presets

Emitted by the SQLAlchemy cursor-event instrumentation (ObservabilityService.instrument_sqlalchemy_engine), which times each statement at the DBAPI level.

Fields:

  • operation (string) - First word of the SQL statement, lowercased: select, insert, update, delete, begin, ...
  • duration_ms (float) - Statement duration
  • collection (string or null) - Always null from engine instrumentation; accepted by log_db_query() for callers that pass a table name
  • executemany (bool) - Whether the statement ran as a batch execute

Query parameters are never logged - they may contain secrets or PII.

Example:

{
  "timestamp": "2025-01-24T10:24:00.123Z",
  "level": "debug",
  "event": "db_query",
  "correlation_id": "d6e7f8a9-b0c1-2345-678d-456789012345",
  "service": "outlabs_auth",
  "operation": "select",
  "duration_ms": 156.3,
  "collection": null,
  "executemany": false
}

Also observed into the outlabs_auth_db_query_duration_seconds histogram, labelled by operation.


Error Events

authentication_error

Level: ERROR When: Unexpected error during authentication Frequency: Should be very rare

Fields:

  • error_type (string) - Error class name
  • error_message (string) - Error message
  • stack_trace (string, optional) - Stack trace (if enabled)
  • user_id (string, optional) - User ID if available
  • method (string, optional) - Auth method being attempted

Example:

{
  "timestamp": "2025-01-24T10:25:00.456Z",
  "level": "error",
  "event": "authentication_error",
  "correlation_id": "e7f8a9b0-c1d2-3456-789e-567890123456",
  "service": "outlabs_auth",
  "error_type": "DatabaseConnectionError",
  "error_message": "Unable to connect to PostgreSQL",
  "method": "password"
}

authorization_error

Level: ERROR When: Unexpected error during permission check Frequency: Should be very rare

Fields:

  • error_type (string) - Error class name
  • error_message (string) - Error message
  • user_id (string, optional) - User ID
  • permission (string, optional) - Permission being checked

Example:

{
  "timestamp": "2025-01-24T10:26:00.789Z",
  "level": "error",
  "event": "authorization_error",
  "correlation_id": "f8a9b0c1-d2e3-4567-890f-678901234567",
  "service": "outlabs_auth",
  "error_type": "ABACEvaluationError",
  "error_message": "Failed to evaluate ABAC condition",
  "user_id": "3f8a1c2e-7b4d-4e19-9a52-8c6f0d1b3e47",
  "permission": "lead:read"
}

http_500_internal_server_error

Level: ERROR When: HTTP 500 Internal Server Error occurs Frequency: Should be very rare in production

How it's logged: Automatically logged when using ObservabilityContext.log_500_error():

try:
    user = await auth.user_service.create_user(data)
except Exception as e:
    obs.log_500_error(e, email=data.email)  # Logs this event
    raise HTTPException(500, detail="Failed to create user")

Fields:

  • endpoint (string) - API endpoint that failed (e.g., "/v1/users/")
  • error_class (string) - Exception class name (e.g., "UserAlreadyExistsError")
  • error_message (string) - Error message
  • method (string, optional) - HTTP method (GET, POST, etc.)
  • user_id (string, optional) - User ID if authenticated
  • request_id (string, optional) - Request/correlation ID
  • stack_trace (string, optional) - Full stack trace (if enabled in config)
  • Plus any extra fields you provide to log_500_error(**extra)

Example:

{
  "timestamp": "2025-01-26T10:15:23.456Z",
  "level": "error",
  "event": "http_500_internal_server_error",
  "correlation_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "service": "outlabs_auth",
  "endpoint": "/v1/users",
  "error_class": "DatabaseConnectionError",
  "error_message": "Unable to connect to PostgreSQL",
  "method": "GET",
  "user_id": "3f8a1c2e-7b4d-4e19-9a52-8c6f0d1b3e47",
  "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "stack_trace": "Traceback (most recent call last):\n  File..."
}

Search Examples:

Terminal
# Find all 500 errors
jq 'select(.event == "http_500_internal_server_error")' app.log

# 500 errors by endpoint
jq 'select(.event == "http_500_internal_server_error") | .endpoint' app.log | sort | uniq -c

# 500 errors by error type
jq 'select(.event == "http_500_internal_server_error") | .error_class' app.log | sort | uniq -c

# Recent 500 errors with stack traces
jq 'select(.event == "http_500_internal_server_error") | {timestamp, endpoint, error_class, stack_trace}' app.log | tail -10

router_error

Level: ERROR When: Error occurs in a FastAPI router/route handler Frequency: Should be rare

Fields:

  • router (string) - Router name (e.g., "users", "roles", "auth")
  • endpoint (string) - Full endpoint path (e.g., "/v1/users/{user_id}")
  • operation (string) - Operation being performed (e.g., "list_users", "create_role")
  • error_type (string) - Exception class name
  • error_message (string) - Error message
  • user_id (string, optional) - User ID if available
  • stack_trace (string, optional) - Stack trace

Example:

{
  "timestamp": "2025-01-26T10:20:00.789Z",
  "level": "error",
  "event": "router_error",
  "correlation_id": "b2c3d4e5-f6a7-8901-bcde-f23456789abc",
  "service": "outlabs_auth",
  "router": "users",
  "endpoint": "/v1/users",
  "operation": "list_users",
  "error_type": "OperationalError",
  "error_message": "Connection timeout",
  "user_id": "3f8a1c2e-7b4d-4e19-9a52-8c6f0d1b3e47",
  "stack_trace": "Traceback..."
}

Search Examples:

Terminal
# Errors by router
jq 'select(.event == "router_error") | .router' app.log | sort | uniq -c

# Errors in users router
jq 'select(.event == "router_error" and .router == "users")' app.log

# Most error-prone operations
jq 'select(.event == "router_error") | .operation' app.log | sort | uniq -c | sort -rn

service_error

Level: ERROR When: Error occurs in a business logic service Frequency: Should be rare

Fields:

  • service (string) - Service name (e.g., "auth", "user", "role", "permission")
  • operation (string) - Operation being performed (e.g., "login", "create_user")
  • error_type (string) - Exception class name
  • error_message (string) - Error message
  • user_id (string, optional) - User ID if available
  • stack_trace (string, optional) - Stack trace

Example:

{
  "timestamp": "2025-01-26T10:25:00.123Z",
  "level": "error",
  "event": "service_error",
  "correlation_id": "c3d4e5f6-a7b8-9012-cdef-34567890abcd",
  "service": "outlabs_auth",
  "service": "auth",
  "operation": "login",
  "error_type": "DatabaseError",
  "error_message": "Failed to query users collection",
  "user_id": "3f8a1c2e-7b4d-4e19-9a52-8c6f0d1b3e47",
  "stack_trace": "Traceback..."
}

Search Examples:

Terminal
# Errors by service
jq 'select(.event == "service_error") | .service' app.log | sort | uniq -c

# Auth service errors
jq 'select(.event == "service_error" and .service == "auth")' app.log

# Database errors across all services
jq 'select(.event == "service_error" and .error_type == "DatabaseError")' app.log

exception_occurred

Level: ERROR When: Generic exception logged via log_exception()Frequency: Varies by usage

Fields:

  • error_type (string) - Exception class name
  • error_message (string) - Error message
  • context (string) - Context where exception occurred
  • user_id (string, optional) - User ID if available
  • stack_trace (string, optional) - Stack trace

Example:

{
  "timestamp": "2025-01-26T10:30:00.456Z",
  "level": "error",
  "event": "exception_occurred",
  "correlation_id": "d4e5f6a7-b8c9-0123-def4-567890abcdef",
  "service": "outlabs_auth",
  "error_type": "ValueError",
  "error_message": "Invalid user ID format",
  "context": "users_router.get_user",
  "user_id": "3f8a1c2e-7b4d-4e19-9a52-8c6f0d1b3e47",
  "stack_trace": "Traceback..."
}

Entity Events

entity_operation

Level: INFO When: Entity created, updated, moved, or deleted Frequency: Per entity operation (moderate volume in EnterpriseRBAC)

Fields:

  • operation (string) - Operation type: create, update, move, delete
  • entity_id (string) - Entity ID
  • entity_type (string) - Entity type (e.g., department, team, project)
  • duration_ms (float, optional) - Operation duration
  • parent_id (string, optional) - Parent entity ID (for create/move)
  • old_parent_id (string, optional) - Previous parent ID (for move)
  • changes (object, optional) - Changed fields (for update)

Example:

{
  "timestamp": "2025-01-20T10:30:00.123Z",
  "level": "info",
  "event": "entity_operation",
  "correlation_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "service": "outlabs_auth",
  "operation": "create",
  "entity_id": "ent_abc123",
  "entity_type": "department",
  "parent_id": "ent_root",
  "duration_ms": 45.2
}

Search Examples:

Terminal
# All entity operations
jq 'select(.event == "entity_operation")' app.log

# Entity hierarchy changes (moves)
jq 'select(.event == "entity_operation" and .operation == "move")' app.log

# Operations on specific entity
jq 'select(.event == "entity_operation" and .entity_id == "ent_abc123")' app.log

Membership Events

membership_operation

Level: INFO When: Membership added, removed, suspended, or reactivated Frequency: Per membership change (moderate volume in EnterpriseRBAC)

Fields:

  • operation (string) - Operation type: add, remove, suspend, reactivate
  • user_id (string) - User being added/removed
  • entity_id (string) - Entity membership is for
  • roles (array, optional) - Role names assigned (for add)
  • reason (string, optional) - Reason for suspension
  • duration_ms (float, optional) - Operation duration

Example:

{
  "timestamp": "2025-01-20T10:35:00.456Z",
  "level": "info",
  "event": "membership_operation",
  "correlation_id": "b2c3d4e5-f6a7-8901-bcde-f23456789012",
  "service": "outlabs_auth",
  "operation": "add",
  "user_id": "usr_xyz789",
  "entity_id": "ent_abc123",
  "roles": ["editor", "viewer"],
  "duration_ms": 32.1
}

Search Examples:

Terminal
# All membership changes for a user
jq 'select(.event == "membership_operation" and .user_id == "usr_xyz789")' app.log

# Membership suspensions (security events)
jq 'select(.event == "membership_operation" and .operation == "suspend")' app.log

# Memberships added to specific entity
jq 'select(.event == "membership_operation" and .entity_id == "ent_abc123" and .operation == "add")' app.log

Activity Events

activity_tracked

Level: DEBUG When: User activity tracked for DAU/MAU/QAU metrics Frequency: Per user activity (high volume, typically DEBUG level)

Fields:

  • user_id (string) - User ID
  • period (string) - Period type: daily, monthly, quarterly

Example:

{
  "timestamp": "2025-01-20T10:40:00.789Z",
  "level": "debug",
  "event": "activity_tracked",
  "correlation_id": "c3d4e5f6-a7b8-9012-cdef-34567890abcd",
  "service": "outlabs_auth",
  "user_id": "usr_xyz789",
  "period": "daily"
}

activity_sync

Level: INFO When: Activity metrics synced from Redis to database Frequency: Per sync interval (low volume, typically every few minutes)

Fields:

  • duration_ms (float) - Sync operation duration
  • records_synced (int) - Total records synced
  • daily_count (int) - Daily active users synced
  • monthly_count (int) - Monthly active users synced
  • quarterly_count (int) - Quarterly active users synced

Example:

{
  "timestamp": "2025-01-20T10:45:00.123Z",
  "level": "info",
  "event": "activity_sync",
  "correlation_id": "d4e5f6a7-b8c9-0123-def4-567890abcdef",
  "service": "outlabs_auth",
  "duration_ms": 150.5,
  "records_synced": 42,
  "daily_count": 25,
  "monthly_count": 15,
  "quarterly_count": 2
}

Notification Events

notification_event

Level: INFO When: Notification event emitted Frequency: Per notification (moderate volume)

Fields:

  • event_type (string) - Notification event type (e.g., user_registered, password_reset)
  • channels_count (int) - Number of channels notified
  • user_id (string, optional) - Related user ID

Example:

{
  "timestamp": "2025-01-20T10:50:00.456Z",
  "level": "info",
  "event": "notification_event",
  "correlation_id": "e5f6a7b8-c9d0-1234-ef56-7890abcdef12",
  "service": "outlabs_auth",
  "event_type": "user_registered",
  "channels_count": 3,
  "user_id": "usr_new123"
}

notification_delivery_failure

Level: WARNING When: Notification delivery to a channel fails Frequency: Per failed delivery (should be low)

Fields:

  • event_type (string) - Original event type
  • channel (string) - Failed channel (e.g., email, webhook, pubsub)
  • error (string) - Error message

Example:

{
  "timestamp": "2025-01-20T10:51:00.789Z",
  "level": "warning",
  "event": "notification_delivery_failure",
  "correlation_id": "f6a7b8c9-d0e1-2345-f678-90abcdef1234",
  "service": "outlabs_auth",
  "event_type": "user_registered",
  "channel": "email",
  "error": "SMTP connection timeout"
}

Search Examples:

Terminal
# All notification failures
jq 'select(.event == "notification_delivery_failure")' app.log

# Failures by channel
jq 'select(.event == "notification_delivery_failure") | .channel' app.log | sort | uniq -c

# Email delivery failures
jq 'select(.event == "notification_delivery_failure" and .channel == "email")' app.log

Filtering & Searching

Common jq Patterns

Terminal
# All events for specific user
jq 'select(.user_id == "3f8a1c2e-7b4d-4e19-9a52-8c6f0d1b3e47")' app.log

# All events with specific correlation ID
jq 'select(.correlation_id == "a1b2c3d4-...")' app.log

# All WARNING and ERROR level events
jq 'select(.level == "warning" or .level == "error")' app.log

# Events in time range
jq 'select(.timestamp >= "2025-01-24T10:00:00Z" and .timestamp <= "2025-01-24T11:00:00Z")' app.log

# Group events by type
jq -r '.event' app.log | sort | uniq -c | sort -rn

# Count events per user
jq -r '.user_id' app.log | sort | uniq -c | sort -rn

# Find slow operations (>100ms)
jq 'select(.duration_ms > 100)' app.log

Next Steps


Last Updated: 2025-01-20 Related: 97-Observability.md, 98-Metrics-Reference.md