Logging¶
Keywords: application logs, logging levels, debug logging, log rotation, error logging
Asok provides a centralized, configuration-aware logging system out of the box.
1. Application Logger¶
The recommended way to log messages is via the app.logger instance. This logger is automatically configured to respect your application’s settings (LOG_LEVEL, LOG_FILE, etc.).
from asok import Asok
app = Asok()
# Standard logging
app.logger.info("Application initialized")
app.logger.warning("Low disk space")
# Convenient shortcuts
app.log_info("Hello Asok!")
app.log_error("Something went wrong")
Usage in a page¶
In your src/pages/page.py, you can access the app logger via the request environment:
# src/pages/page.py
def render(request):
app = request.environ.get("asok.app")
if app:
app.log_info("User visited the home page")
return "Welcome to Asok!"
2. Request Logger Middleware¶
To log every incoming HTTP request, create src/middlewares/logger.py:
from asok import RequestLogger
# Uses app.logger settings automatically
log = RequestLogger()
def handle(request, next):
return log(request, next)
Output example:
[2026-05-14 12:00:01] INFO asok.request: GET / 200 OK 3.2ms
[2026-05-14 12:00:02] INFO asok.request: POST /contact 302 Found 12.5ms
3. Configuration¶
You can configure logging via your .env file or directly in app.config.
| Key | Default | Description | |
5. Built-in Observability & Prometheus Metrics¶
Asok includes a zero-dependency, thread-safe Prometheus metrics registry and health check endpoints out of the box:
Health Probe Endpoints (/healthz, /health)¶
Returns JSON status (200 OK or 503 Service Unavailable) for Kubernetes and container orchestration:
{
"status": "healthy",
"version": "0.8.0",
"uptime_seconds": 3612.4,
"checks": {
"database": "ok",
"cache": "ok"
}
}
Prometheus Metrics Endpoint (/metrics)¶
Exports metrics in standard Prometheus text format:
asok_http_requests_total{method="GET",status="200",path="/"} 42asok_http_request_duration_seconds_count 42asok_http_request_duration_seconds_sum 1.4502asok_db_queries_total{engine="sqlite"} 128asok_db_query_duration_seconds_sum 0.3214asok_db_slow_queries_total 1asok_websocket_active_connections 8asok_uptime_seconds 3612.4
—|—|—|
| LOG_LEVEL | DEBUG | Logging level (DEBUG, INFO, WARNING, ERROR). |
| LOG_FILE | None | Optional path to a file for persistent logging. |
| LOG_FORMAT| text | Format of logs: text or json. |
Example .env:
LOG_LEVEL=INFO
LOG_FILE=logs/app.log
LOG_FORMAT=json
4. Standalone Logger¶
For logging in modules where app is not available, you can still use get_logger():
from asok import get_logger
logger = get_logger("my_module")
logger.info("Standalone log message")
5. Distributed Tracing (W3C TraceContext & OpenTelemetry)¶
Asok includes a pure-Python, zero-dependency distributed tracing engine fully compliant with the W3C TraceContext specification.
Enabling the Middleware¶
from asok import Asok, TracingMiddleware
app = Asok()
app.use(TracingMiddleware())
Response Headers¶
Every HTTP response processed by TracingMiddleware includes standard tracing headers:
traceparent:00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01X-Trace-ID:4bf92f3577b34da6a3ce929d0e0e4736X-Span-ID:00f067aa0ba902b7
Programmatic Spans in Views¶
Use the contextual tracer to record child spans within your application logic:
from asok import tracer
def process_order(request):
with tracer.start_span("validate_cart", attributes={"cart.items": 3}) as span:
span.add_event("cart_validated")
with tracer.start_span("charge_payment") as span:
span.set_attribute("payment.provider", "stripe")
return request.json({"status": "success"})
Each span automatically measures its duration in milliseconds (duration_ms), records exceptions, and can be exported as an OpenTelemetry-compatible dictionary via span.to_dict().