A Flask API for querying Thor chain node logs stored in Loki by block number range. Converts block numbers to timestamps via the Thor node REST API, then queries Loki for logs in that time window.
pip install -r requirements.txt
cp .env.example .env
# edit .env with your Thor node and Loki URLspython run.pyThe server starts on http://localhost:5000 by default.
For production, use gunicorn:
gunicorn run:app -b 0.0.0.0:5000 -w 4All configuration is via environment variables (or .env file):
| Variable | Default | Description |
|---|---|---|
THOR_NODE_URL |
http://localhost:8669 |
Thor node REST API URL |
LOKI_URL |
http://localhost:3100 |
Loki HTTP API URL |
LOKI_QUERY |
{job="thor"} |
Default LogQL stream selector |
BLOCK_CACHE_MAX_SIZE |
10000 |
Max cached block timestamps (LRU) |
LOKI_CACHE_MAX_SIZE |
256 |
Max cached Loki query results (LRU) |
GET /api/logs?from_block=1000&to_block=2000
| Parameter | Required | Description |
|---|---|---|
from_block |
Yes | Starting block number |
to_block |
Yes | Ending block number (inclusive) |
level |
No | Filter by log level: trace, debug, info, warn, error, fatal |
query |
No | Custom LogQL query (overrides default LOKI_QUERY) |
limit |
No | Max log lines per page (default 5000) |
cursor |
No | Nanosecond timestamp cursor from a previous response for pagination |
The response includes a next_cursor field when there are more results. Pass it back as cursor to fetch the next page.
Examples:
# Get all logs between blocks 1000 and 2000
curl "http://localhost:5000/api/logs?from_block=1000&to_block=2000"
# Filter by error level
curl "http://localhost:5000/api/logs?from_block=1000&to_block=2000&level=error"
# Custom LogQL query with a limit
curl "http://localhost:5000/api/logs?from_block=1000&to_block=2000&query={job=\"thor\"}&limit=100"
# Paginate through large results
curl "http://localhost:5000/api/logs?from_block=1000&to_block=2000&limit=500"
# Response includes: "next_cursor": "1530014510000000000"
curl "http://localhost:5000/api/logs?from_block=1000&to_block=2000&limit=500&cursor=1530014510000000000"GET /api/block/<block_number>
Returns the unix timestamp for a given block. Useful for debugging block-to-time mapping.
curl http://localhost:5000/api/block/1000
# {"block": 1000, "timestamp": 1530014510}# View cache sizes
curl http://localhost:5000/api/cache/stats
# Clear all caches
curl -X POST http://localhost:5000/api/cache/clearGET /health
thor-log-API/
├── app/
│ ├── __init__.py # App factory
│ ├── config.py # Configuration from env vars
│ ├── services/
│ │ ├── cache.py # LRU cache implementation
│ │ ├── thor.py # Thor node client (block -> timestamp)
│ │ └── loki.py # Loki query client
│ └── routes/
│ ├── logs.py # GET /api/logs
│ ├── blocks.py # GET /api/block/<n>
│ └── health.py # GET /health, cache stats/clear
├── run.py # Entrypoint
├── requirements.txt
├── .env.example
└── .gitignore