Metadata-Version: 2.4
Name: fastapi-logkit
Version: 0.1.0
Summary: FastAPI logging bootstrap: dev-friendly console, production structlog JSON
Author: APT
License: MIT
Requires-Python: >=3.10
Requires-Dist: fastapi>=0.100.0
Requires-Dist: starlette>=0.27.0
Requires-Dist: structlog>=24.1.0
Provides-Extra: dev
Requires-Dist: httpx>=0.27.0; extra == 'dev'
Requires-Dist: pytest>=8.0.0; extra == 'dev'
Description-Content-Type: text/markdown

# fastapi-logkit

FastAPI logging bootstrap: readable console logs in development, structured structlog JSON to `stdout` in production-minded environments.

- Prefer turning off Uvicorn/Gunicorn access logs and emitting HTTP access as structured middleware logs instead.
- The global exception handler logs unhandled request errors; process-level logs are normalized via Uvicorn/Gunicorn logger wiring.

## Usage

`fastapi_logkit` does **not read OS environment variables.** Read deploy env, log level, etc. in your app and pass values into helpers.

```python
import os
from fastapi import FastAPI
from fastapi_logkit import setup_logging
from fastapi_logkit.fastapi import install_logkit

def app_env() -> str:
    return (os.getenv("APP_ENV") or os.getenv("ENVIRONMENT") or "development").strip()

cfg = setup_logging(
    env=app_env(),
    level=os.getenv("LOG_LEVEL", "INFO").strip().upper(),
)

app = FastAPI()
install_logkit(app, config=cfg)
```

- With `install_logkit(..., config=cfg)`, the exception handler mirrors `cfg.json_logs` (structured JSON vs `app.error` text).
- If `access_log` is omitted, it defaults from `is_production_environment(cfg.env)`.

When running Uvicorn, pass the **same** `env` semantics into `get_uvicorn_log_config_for_run(env=..., silence_uvicorn=...)` as for `setup_logging`. Example:

```python
from fastapi_logkit.env_util import is_json_logging_environment
from fastapi_logkit.integrations.uvicorn import get_uvicorn_log_config_for_run

e = app_env()
uvicorn.run(
    "main:app",
    log_config=get_uvicorn_log_config_for_run(
        env=e, silence_uvicorn=is_json_logging_environment(e)
    ),
)
```

Production-style run: `uvicorn main:app --host 0.0.0.0 --port 8000 --no-access-log`

---

## Behaviour summary (arguments / helpers)

| API / helper | Description |
|----------------|-------------|
| `setup_logging(env=..., level="INFO", json_logs=None, ...)` | Omit `json_logs` to derive it from `is_json_logging_environment(env)` (`production` / `prod` / `staging` → JSON pipeline). |
| `is_json_logging_environment(env)` | Whether `env` is treated as a JSON-logging env; **string only** (does not touch `os`). |
| `is_production_environment(env)` | True only for `production` / `prod` — default access middleware install in `install_logkit`. |
| `resolve_env_name(env)` | If `env` is `None`, returns `"development"` (no env var lookup). |
| `configure_logging(...)` | Alias of `setup_logging`. |

Body redaction, proxy IP trust, and **which access lines are emitted** are configured via **`AccessLogOptions`** + `install_logkit(..., access_log_options=...)`.

### HTTP access line threshold

Each access line is classified with a stdlib severity: **2xx/3xx → `INFO`**, **4xx → `WARNING`**, **5xx → `ERROR`**. A line is emitted only if that severity is **≥** the configured minimum.

- By default, `install_logkit(..., config=cfg)` sets the access minimum from **`cfg.level`** (same string as `setup_logging(..., level=...)`). For example, `level="WARNING"` suppresses successful **2xx/3xx** access lines but still records **4xx** and **5xx**.
- Set **`AccessLogOptions(access_min_level=logging.WARNING)`** (or another numeric level) to override the threshold without changing the global structlog floor.

---

## JSON line fields (JSON mode)

Each `stdout` line is produced by `structlog.processors.JSONRenderer()`, with fields merged as follows:

| Category | Fields |
|----------|--------|
| Common (processors) | `env` — name passed into `setup_logging`. `logLevel` — numeric Pino-like level (e.g. info=30). The `event` key is stripped right before rendering. |
| Request context (`RequestContextMiddleware`) | `request_id`, `method`, `path` merged from structlog contextvars. |
| Access log (`AccessLogMiddleware`) | `statusCode`, `userAgent`, `clientIP`, `originIP`, `dateTime` (ms timestamp), `endPoint`, `pathParams`, `method`, `traceBack` when present. For 4xx/5xx with body logging enabled, `requestBody`. |
| JSON `unhandled_exception_handler` without access middleware on the stack | `traceBack`, `endPoint`, `method`, `statusCode` (500). May skip when access middleware already logged the same failure. |
| App kwargs | Any keys passed to `logger.info("name", **fields)` are included verbatim. |

---

See the `fastapi_logkit/` source for processors and middleware details.
