Log Events Reference
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 UTClevel— debug / info / warning / error / criticalevent— event name (e.g.user_login_success)correlation_id— request correlation id when presentservice— typicallyoutlabs_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 IDemail(string) - User's emailmethod(string) - Auth method:password,google,facebook,apple,github,api_keyduration_ms(float) - Time taken for login operationip_address(string, optional) - Client IP addressuser_agent(string, optional) - Client user agentdevice_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:
# 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 attemptedreason(string) - Failure reason:invalid_credentials- Wrong passworduser_not_found- Email doesn't existaccount_locked- Too many failed attemptsaccount_suspended- Account suspended by adminaccount_deleted- Account has been deletedemail_not_verified- Email verification requiredoauth_error- OAuth provider error
duration_ms(float) - Time takenip_address(string, optional) - Client IPuser_agent(string, optional) - Client user agentfailed_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:
# 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 IDemail(string) - User's emailmethod(string) - Logout trigger:explicit- User clicked logouttoken_expiry- Refresh token expiredadmin_revoke- Admin revoked sessionsecurity_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 IDduration_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 existexpired_token- Refresh token expiredrevoked_token- Token was revokeduser_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 IDemail(string) - User's emailfailed_attempts(int) - Number of failed attempts that triggered lockoutlocked_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:
# 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 IDpermission(string) - Permission checked (e.g.,user:read)resource_id(string, optional) - Specific resource being accessedentity_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 IDemail(string, optional) - User's emailpermission(string) - Permission checkedresource_id(string, optional) - Specific resourceentity_id(string, optional) - Entity contextduration_ms(float) - Time takenreason(string, optional) - Denial reason:no_permission- User doesn't have permissionabac_denied- ABAC condition failedentity_denied- Not member of required entityinactive_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:
# 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 IDpermission(string) - Permission checkedentity_id(string, optional) - Entity contextduration_ms(float) - Time taken (>100ms)hierarchy_depth(int, optional) - Entity hierarchy depth traversedabac_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 IDuser_id(string, optional) - Associated user IDduration_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 validreason(string) - Failure reason:invalid_format- Malformed API keynot_found- API key doesn't existexpired- API key expireddisabled- API key was disabledrate_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:
# 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 prefixapi_key_id(string) - API key IDrate_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 loginssession_hijack- IP/user agent changed mid-sessionrate_limit_abuse- Excessive requestsinvalid_token_flood- Many invalid tokensapi_key_scanning- Scanning for valid API keys
user_id(string, optional) - Affected useremail(string, optional) - User emailip_address(string, optional) - Suspicious IPdetails(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 IDemail(string) - User's emailreason(string) - Detection reason:ip_changed- IP address changed during sessionuser_agent_changed- User agent changedlocation_anomaly- Geographic location jumped
original_ip(string, optional) - Original IPnew_ip(string, optional) - New IPoriginal_user_agent(string, optional) - Original user agentnew_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,entitycache_key(string) - Invalidated keyreason(string) - Invalidation reason:update- Data was updateddelete- Data was deletedttl_expired- TTL expiredmanual_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 durationcollection(string or null) - Alwaysnullfrom engine instrumentation; accepted bylog_db_query()for callers that pass a table nameexecutemany(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 nameerror_message(string) - Error messagestack_trace(string, optional) - Stack trace (if enabled)user_id(string, optional) - User ID if availablemethod(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 nameerror_message(string) - Error messageuser_id(string, optional) - User IDpermission(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 messagemethod(string, optional) - HTTP method (GET, POST, etc.)user_id(string, optional) - User ID if authenticatedrequest_id(string, optional) - Request/correlation IDstack_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:
# 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 nameerror_message(string) - Error messageuser_id(string, optional) - User ID if availablestack_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:
# 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 nameerror_message(string) - Error messageuser_id(string, optional) - User ID if availablestack_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:
# 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 nameerror_message(string) - Error messagecontext(string) - Context where exception occurreduser_id(string, optional) - User ID if availablestack_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,deleteentity_id(string) - Entity IDentity_type(string) - Entity type (e.g.,department,team,project)duration_ms(float, optional) - Operation durationparent_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:
# 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,reactivateuser_id(string) - User being added/removedentity_id(string) - Entity membership is forroles(array, optional) - Role names assigned (for add)reason(string, optional) - Reason for suspensionduration_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:
# 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 IDperiod(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 durationrecords_synced(int) - Total records synceddaily_count(int) - Daily active users syncedmonthly_count(int) - Monthly active users syncedquarterly_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 notifieduser_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 typechannel(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:
# 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
# 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
- 97-Observability.md - Main observability guide
- 98-Metrics-Reference.md - Complete metrics catalog
- Grafana Dashboard - Pre-built dashboard
Last Updated: 2025-01-20 Related: 97-Observability.md, 98-Metrics-Reference.md