Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add logging documentation #1733

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 3 additions & 4 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,9 @@ Moreover, "optional extras" means that:
- `python-dotenv` will be installed should you want to use the `--env-file` option.
- `PyYAML` will be installed to allow you to provide a `.yaml` file to `--log-config`, if desired.

Create an application, in `example.py`:
Create an application:

```python
```py title="example.py"
async def app(scope, receive, send):
assert scope['type'] == 'http'

Expand Down Expand Up @@ -205,8 +205,7 @@ There are several ways to run uvicorn directly from your application.

If you're looking for a programmatic equivalent of the `uvicorn` command line interface, use `uvicorn.run()`:

```python
# main.py
```py title="example.py"
import uvicorn

async def app(scope, receive, send):
Expand Down
86 changes: 86 additions & 0 deletions docs/logging.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# Logging

**Uvicorn** has three logger objects available:

* **ASGI Logger** (`uvicorn.asgi`) - Low level ASGI application logs.
* **Access Logger** (`uvicorn.access`) - HTTP access logs.
* **Main Logger**: `uvicorn.error` - Everything else, **not only errors**.

## ASGI Logger

The **ASGI logger** is used to log low level ASGI interactions.

This logger is useful to **debug ASGI applications**, and to understand how **Uvicorn interacts** with them.
To be able to see its logs, set **`--log-level`** to **`trace`**.

Let's understand a bit better with an example. Assume we have the following ASGI application:

```py title="main.py"
async def app(scope, receive, send):
assert scope["type"] == "http"
await send({
"type": "http.response.start",
"status": 200,
"headers": [[b"content-type", b"text/plain"]],
})
await send({"type": "http.response.body", "body": b"Hello, world!"})
```

Let's run it with the following command:

```bash
uvicorn main:app --log-level trace
```

You'll see the following output:

```bash
INFO: Started server process [73010]
INFO: Waiting for application startup.
TRACE: ASGI [1] Started scope={'type': 'lifespan', 'asgi': {'version': '3.0', 'spec_version': '2.0'}}
TRACE: ASGI [1] Raised exception
INFO: ASGI 'lifespan' protocol appears unsupported.
INFO: Application startup complete.
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```

In case you send a request to the server, you'll see the following output:

```bash
TRACE: 127.0.0.1:45540 - HTTP connection made
TRACE: 127.0.0.1:45540 - ASGI [2] Started scope={'type': 'http', 'asgi': {'version': '3.0', 'spec_version': '2.3'}, 'http_version': '1.1', 'server': ('127.0.0.1', 8000), 'client': ('127.0.0.1', 45540), 'scheme': 'http', 'root_path': '', 'headers': '<...>', 'method': 'GET', 'path': '/', 'raw_path': b'/', 'query_string': b''}
TRACE: 127.0.0.1:45540 - ASGI [2] Send {'type': 'http.response.start', 'status': 200, 'headers': '<...>'}
INFO: 127.0.0.1:45540 - "GET / HTTP/1.1" 200 OK
TRACE: 127.0.0.1:45540 - ASGI [2] Send {'type': 'http.response.body', 'body': '<13 bytes>'}
TRACE: 127.0.0.1:45540 - ASGI [2] Completed
TRACE: 127.0.0.1:45540 - HTTP connection lost
```

## Access Logger

The **Access Logger** is used to log HTTP access logs.

This logger is called **every time a response is sent** to a client. It's useful to **monitor HTTP traffic**.

### Access Log Format

The default access log format is:

```bash
%(levelprefix)s %(client_addr)s - "%(request_line)s" %(status_code)s
```

The following variables are available:

- **`client_addr`**: The client IP address.
- **`status_code`**: The response status code (e.g. `200 OK`).
- **`method`**: The request method.
- **`full_path`**: The full request path (e.g. `/foo?bar=baz`).
- **`http_version`**: The HTTP version (e.g. `HTTP/1.1`).
- **`request_line`**: The request line (e.g. `GET /foo?bar=baz HTTP/1.1`).

## Main Logger

The **Main Logger** is used to log everything else, **not only errors**.

This logger is useful to **monitor Uvicorn** itself, and to understand what's going on.
6 changes: 6 additions & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,18 @@ edit_uri: ""
nav:
- Introduction: "index.md"
- Settings: "settings.md"
- Logging: "logging.md"
- Deployment: "deployment.md"
- Server Behavior: "server-behavior.md"
- Contributing: "contributing.md"

markdown_extensions:
- admonition
- pymdownx.highlight:
anchor_linenums: true
- pymdownx.inlinehilite
- pymdownx.snippets
- pymdownx.superfences
- codehilite:
css_class: highlight
- toc:
Expand Down