# TeaQL Debugging & Logging Guide (Java)

When you need to debug a TeaQL application, investigate slow queries, or verify the SQL being executed, use the built-in debugging features.

## 1. Environment Variables

Configure logging behavior without changing code:

| Variable | Default | Values | Description |
|----------|---------|--------|-------------|
| `TEAQL_LOG_ENDPOINT` | *(stdout)* | file path or empty | Log output destination. Empty = System.out |
| `TEAQL_LOG_FORMAT` | `human` | `human`, `json` | Log format: human-readable or JSON |
| `TEAQL_LOG_SELECT` | `false` | `true`, `false` | Log SELECT/QUERY SQL statements |
| `TEAQL_LOG_MUTATION` | `true` | `true`, `false` | Log INSERT/UPDATE/DELETE SQL statements |
| `TEAQL_ENFORCE_INTENT` | `off` | `off`, `warn`, `strict` | Triple-Intent enforcement: require `.comment()` + `.purpose()` + `.auditAs()` |
| `TEAQL_LOG_MAX_SIZE` | `50M` | size string | Max log file size before rotation (supports K/KB, M/MB, G/GB) |
| `TEAQL_LOG_MAX_FILES` | `7` | integer | Max number of rotated log files to keep |

*Example:*
```bash
TEAQL_LOG_SELECT=true TEAQL_LOG_FORMAT=human java -jar app.jar
```

## 2. Programmatic Logging (Code Level)

Use the built-in logging methods on `UserContext` with SLF4J markers for structured output:

```java
// General logging (SLF4J-based)
ctx.info("Processing entity: {}", entityName);
ctx.debug("Query returned {} rows", count);
ctx.warn("Unexpected state: {}", state);
ctx.error(exception, "Failed to process: {}", entityName);

// Use SLF4J Markers for fine-grained filtering
import io.teaql.core.log.Markers;

ctx.info(Markers.SQL_SELECT, "SELECT query: {}", sql);
ctx.info(Markers.SQL_UPDATE, "UPDATE query: {}", sql);
```

### Available SLF4J Markers

| Marker | Purpose |
|--------|---------|
| `Markers.SQL_SELECT` | SELECT/query SQL statements |
| `Markers.SQL_UPDATE` | INSERT/UPDATE/DELETE SQL statements |
| `Markers.SEARCH_REQUEST_START` | Start of a search request |
| `Markers.SEARCH_REQUEST_END` | End of a search request |
| `Markers.HTTP_REQUEST` | Outgoing HTTP request (full) |
| `Markers.HTTP_SHORT_REQUEST` | Outgoing HTTP request (summary) |
| `Markers.HTTP_RESPONSE` | HTTP response (full) |
| `Markers.HTTP_SHORT_RESPONSE` | HTTP response (summary) |

## 3. Capturing Logs Per-Request (Custom Sink)

To capture log output programmatically for a specific request (e.g., for a debug API or unit test):

```java
import io.teaql.core.log.CustomLogSink;

// 1. Create a sink that collects log entries
List<String> capturedLogs = new ArrayList<>();
ctx.registerCustomSink(content -> capturedLogs.add(content));

// 2. Perform your database operations
SmartList<Merchant> result = Q.merchants()
    .comment("debug query")
    .purpose("testing")
    .executeForList(ctx);

// 3. Review captured logs
for (String log : capturedLogs) {
    System.out.println("Captured: " + log);
}
```

## 4. Execution Metadata (SQL Diagnostics)

Every SQL execution produces an `ExecutionMetadata` record with detailed diagnostics:

```java
import io.teaql.core.ExecutionMetadata;

// Access after execution via custom sink
ctx.registerCustomSink(new ExecutionLogSink() {
    @Override
    public void log(UserContext ctx, ExecutionMetadata metadata) {
        System.out.println("SQL:      " + metadata.getDebugQuery());
        System.out.println("Duration: " + metadata.getElapsedUs() + " μs");
        System.out.println("Rows:     " + metadata.getResultCount());
        System.out.println("Backend:  " + metadata.getBackend());
        System.out.println("Summary:  " + metadata.getResultSummary());
    }
});
```

## 5. Audit Events (Change Tracking)

TeaQL automatically emits audit events for every entity mutation (create/update/delete). You can tap into these:

```java
import io.teaql.runtime.log.AuditEvent;
import io.teaql.runtime.log.FieldChange;

// AuditEvent contains:
// - entityType: which entity was changed
// - entityId: the ID of the changed entity
// - mutationKind: CREATE, UPDATE, or DELETE
// - changes: list of FieldChange(field, oldValue, newValue)
```

## 6. Trace Chain (Request Tracking)

Use the trace chain to track the call path through your business logic:

```java
// Push a trace node before an operation
ctx.pushTrace("Load merchant for order processing");

SmartList<Merchant> merchants = Q.merchants()
    .comment("load active merchants")
    .purpose("order processing")
    .executeForList(ctx);

// Pop when done
ctx.popTrace();

// The trace chain appears in logs and audit events automatically
List<TraceNode> chain = ctx.getTraceChain();
```

## 7. Intent Enforcement

Control how strictly TeaQL enforces the Triple-Intent pattern (`.comment()` + `.purpose()` + `.auditAs()`):

| Mode | Behavior |
|------|----------|
| `off` | No enforcement (default) |
| `warn` | Logs a warning when intent is missing |
| `strict` | Throws an exception when intent is missing |

Set via environment variable:
```bash
TEAQL_ENFORCE_INTENT=strict java -jar app.jar
```

> **Remember:** Enable `TEAQL_LOG_SELECT=true` during development to see all SQL queries. In production, keep it `false` to avoid log noise — mutation logging (`TEAQL_LOG_MUTATION=true`) is usually sufficient.