Initial commit
This commit is contained in:
158
skills/hyperindex-development/references/logging-debugging.md
Normal file
158
skills/hyperindex-development/references/logging-debugging.md
Normal file
@@ -0,0 +1,158 @@
|
||||
# Logging & Debugging
|
||||
|
||||
Effective logging is essential for troubleshooting indexer issues. HyperIndex uses [pino](https://github.com/pinojs/pino) for high-performance logging.
|
||||
|
||||
## context.log Methods
|
||||
|
||||
Use the logging methods available on the context object in handlers:
|
||||
|
||||
```typescript
|
||||
MyContract.Event.handler(async ({ event, context }) => {
|
||||
// Different severity levels
|
||||
context.log.debug(`Processing transfer ${event.transactionHash}`);
|
||||
context.log.info(`Transfer from ${event.params.from} to ${event.params.to}`);
|
||||
context.log.warn(`Large transfer detected: ${event.params.value}`);
|
||||
context.log.error(`Failed to process: ${event.transactionHash}`);
|
||||
});
|
||||
```
|
||||
|
||||
## Structured Logging
|
||||
|
||||
Pass an object as the second argument for structured logs:
|
||||
|
||||
```typescript
|
||||
context.log.info("Processing transfer", {
|
||||
from: event.params.from,
|
||||
to: event.params.to,
|
||||
value: event.params.value.toString(),
|
||||
block: event.block.number,
|
||||
});
|
||||
|
||||
// With error object
|
||||
context.log.error("Handler failed", {
|
||||
error: err,
|
||||
event: event.transactionHash,
|
||||
});
|
||||
```
|
||||
|
||||
## Debugging Workflow
|
||||
|
||||
### Disable TUI for Full Logs
|
||||
|
||||
The Terminal UI can hide errors. Disable it to see all output:
|
||||
|
||||
```bash
|
||||
# Option 1: Environment variable
|
||||
TUI_OFF=true pnpm dev
|
||||
|
||||
# Option 2: Flag
|
||||
pnpm dev --tui-off
|
||||
```
|
||||
|
||||
### Recommended Debug Command
|
||||
|
||||
```bash
|
||||
TUI_OFF=true pnpm dev 2>&1 | tee debug.log
|
||||
```
|
||||
|
||||
This shows all output AND saves to a file for later analysis.
|
||||
|
||||
## Environment Variables
|
||||
|
||||
### Log Level
|
||||
|
||||
```bash
|
||||
# Console log level (default: "info")
|
||||
LOG_LEVEL="debug" # Show debug logs
|
||||
LOG_LEVEL="trace" # Most verbose
|
||||
|
||||
# File log level (default: "trace")
|
||||
FILE_LOG_LEVEL="debug"
|
||||
```
|
||||
|
||||
### Log Strategy
|
||||
|
||||
```bash
|
||||
# Default: Human-readable with colors
|
||||
LOG_STRATEGY="console-pretty"
|
||||
|
||||
# ECS format for Elastic Stack / Kibana
|
||||
LOG_STRATEGY="ecs-file"
|
||||
LOG_STRATEGY="ecs-console"
|
||||
|
||||
# Efficient file-only logging
|
||||
LOG_STRATEGY="file-only"
|
||||
LOG_FILE="./indexer.log"
|
||||
|
||||
# Both console and file
|
||||
LOG_STRATEGY="both-prettyconsole"
|
||||
LOG_FILE="./debug.log"
|
||||
```
|
||||
|
||||
## Common Debugging Patterns
|
||||
|
||||
### Log Entity State
|
||||
|
||||
```typescript
|
||||
MyContract.Event.handler(async ({ event, context }) => {
|
||||
const entity = await context.Account.get(event.params.user);
|
||||
|
||||
context.log.debug("Entity state before update", {
|
||||
id: event.params.user,
|
||||
exists: !!entity,
|
||||
currentBalance: entity?.balance?.toString() ?? "N/A",
|
||||
});
|
||||
|
||||
// ... update logic
|
||||
});
|
||||
```
|
||||
|
||||
### Log Only During Execution (Skip Preload)
|
||||
|
||||
```typescript
|
||||
MyContract.Event.handler(async ({ event, context }) => {
|
||||
// Preload phase: load data
|
||||
const account = await context.Account.get(event.params.user);
|
||||
|
||||
// Only log during actual execution
|
||||
if (!context.isPreload) {
|
||||
context.log.info("Processing account", {
|
||||
id: event.params.user,
|
||||
balance: account?.balance?.toString(),
|
||||
});
|
||||
}
|
||||
|
||||
// ... rest of handler
|
||||
});
|
||||
```
|
||||
|
||||
### Debug Missing Data
|
||||
|
||||
```typescript
|
||||
MyContract.Event.handler(async ({ event, context }) => {
|
||||
const token = await context.Token.get(event.params.token);
|
||||
|
||||
if (!token) {
|
||||
context.log.warn("Token not found - may be created by later event", {
|
||||
tokenAddress: event.params.token,
|
||||
block: event.block.number,
|
||||
txHash: event.transactionHash,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
## Preload Phase Logging Note
|
||||
|
||||
**Important:** `context.log` calls are ignored during the preload phase. Logs only appear during the execution phase. This is intentional - it prevents duplicate log entries since handlers run twice with preload optimization enabled.
|
||||
|
||||
## Troubleshooting Checklist
|
||||
|
||||
1. **Can't see errors?** → Run with `TUI_OFF=true`
|
||||
2. **Need more detail?** → Set `LOG_LEVEL="debug"` or `"trace"`
|
||||
3. **Want persistent logs?** → Set `LOG_STRATEGY="both-prettyconsole"` with `LOG_FILE`
|
||||
4. **Logs appearing twice?** → Normal if you're logging outside `!context.isPreload` check
|
||||
5. **No logs at all?** → Check you're not in preload phase; use `!context.isPreload` guard
|
||||
Reference in New Issue
Block a user