Skip to main content

Logging Customization

Overview

TeaQL logging is designed to be controlled at runtime and enriched by UserContext. The context can provide user identity, tenant, trace ID, request metadata, enabled log markers, and environment-specific policies.

Logging customization is useful when teams need:

  • SQL debugging for a single user
  • Tenant-aware diagnostics
  • Request tracing
  • Production-safe log filtering
  • Dynamic marker enablement
  • Compliance-friendly audit context

For dynamic marker operations, see also the TeaQL debugging and logging guide.


What Can Be Customized

AreaExamples
Log identityUser name, tenant, organization, trace ID
Log markersSQL_SELECT, SQL_UPDATE, HTTP_REQUEST, domain-specific markers
Log scopeGlobal, tenant, user, request, endpoint
Sensitive data handlingMask fields, suppress payloads, deny URLs
Output formatPlain text, JSON, structured logs
Runtime switchesEnable or disable markers without restart

Use CustomUserContext to provide log context:

public class CustomUserContext extends UserContext {

public String traceId() {
return getOrCreateLocalValue("traceId", () -> "T" + System.nanoTime());
}

public String logIdentity() {
return currentUserName() + "@" + currentTenantCode();
}
}

Then make log output consistently include this context:

[traceId] [tenant] [user] [marker] message

Marker-Based Logging

Markers make logs controllable.

Common TeaQL markers include:

  • SEARCH_REQUEST_START
  • SEARCH_REQUEST_END
  • SQL_SELECT
  • SQL_UPDATE
  • HTTP_REQUEST
  • HTTP_RESPONSE

Project-specific markers can also be added:

  • PERMISSION_CHECK
  • CACHE_HIT
  • CACHE_MISS
  • AUDIT_WRITE
  • LOCK_ACQUIRE
  • LOCK_RELEASE

Example:

userContext.debug("SQL_SELECT", "Loading active orders for user {}", userContext.currentUserId());

Adapt this to the actual logging facade used in your runtime.


User-Specific Debugging

Production debugging often needs to inspect one user without increasing logs for everyone.

Recommended policy:

public boolean shouldLogMarker(String marker) {
return logConfiguration().isGlobalMarkerEnabled(marker)
|| logConfiguration().isUserMarkerEnabled(currentUserId(), marker)
|| isCurrentRequestInDebugMode(marker);
}

This lets support teams enable SQL logging for one user or one request.


Sensitive Data Protection

Logging must not expose secrets.

Always mask:

  • Passwords
  • Tokens
  • Authorization headers
  • Payment data
  • Personally identifiable information when not needed
  • Large request bodies

Example masking hook:

public Map<String, Object> sanitizeLogFields(Map<String, Object> fields) {
fields.remove("password");
fields.remove("accessToken");
fields.computeIfPresent("phone", (key, value) -> maskPhone(value.toString()));
return fields;
}

Structured Logs

For production observability, prefer structured fields:

{
"traceId": "T2004754077140779008",
"tenant": "MICROSOFT",
"user": "Alice",
"marker": "SQL_SELECT",
"entity": "EmployeePermission",
"durationMs": 18
}

This format works better with log search systems and metrics dashboards.


Best Practices

  • Include trace ID in every log line.
  • Use markers instead of ad-hoc log text.
  • Keep SQL logging disabled by default in production.
  • Enable user-specific logs when debugging real support issues.
  • Mask sensitive fields before output.
  • Avoid logging full entity graphs unless debugging locally.
  • Use CustomUserContext as the source of tenant, user, and request metadata.

Testing Checklist

  • Trace ID is present across request logs.
  • SQL markers can be enabled and disabled.
  • User-specific logging does not affect other users.
  • Sensitive fields are masked.
  • Denied URLs are not logged.
  • Log output includes tenant and user identity.

Summary

Logging customization should be context-aware. CustomUserContext gives TeaQL logs the missing business context: who made the request, which tenant it belongs to, what trace ID connects the operation, and which markers should be visible.