# Logging
faucet takes care of logging both HTTP requests and responses, as well as
the `stdout` and `stderr` of the worker processes. This section describes
how logging works in faucet and how to filter the logs.
## Basic structure
All logs generated by faucet take the following form:
```
[<time stamp> level <source>] <message>
```
- The time stamp is the format `YYYY-MM-DDTHH:MM:SSZ` and is in UTC.
- The level is one of:
- `ERROR`
- `WARN`
- `INFO`
- `DEBUG`
- `TRACE`
- The source is either `faucet` or the name of the worker `Worker::<id>`.
## HTTP logging
HTTP logs are all logged at the `INFO` level. The source is the worker in
charge of handling the request. The message has the following form:
```
<ip> "<method> <path> <protocol>" <status> "<user-agent>" <duration>
```
- `ip` is the IP address of the client (determined by the `--ip-from` option).
- `method` is the HTTP method used.
- `path` is the path of the request.
- `protocol` is the HTTP protocol version used.
- `status` is the HTTP status code returned.
- `user-agent` is the user agent of the client.
- `duration` is the time it took to handle the request in milliseconds.
## Worker logging
Worker logs are divided into two components: `stdout` and `stderr`.
`stdout` is logged at the `INFO` level and `stderr` is logged at the `WARN`
level. The source is the worker who owns the underlying process. The message
is the line of output from the process.
## Event Tracing
Beyond basic logging, faucet allows you to emit structured "events" from your R Shiny applications. These events provide rich, machine-readable data about what's happening within your application, making it easier to monitor, debug, and analyze its behavior.
### Emitting Events from R (Shiny)
To send structured events from your Shiny application, use the `faucet` R package. It provides a set of logging functions that wrap the core event emission logic:
- `faucet::info()`: For general informational events.
- `faucet::warn()`: For non-critical issues or warnings.
- `faucet::error()`: For significant errors that require attention.
- `faucet::debug()`: For detailed debugging information (typically enabled during development).
- `faucet::trace()`: For very fine-grained operational details (most verbose).
Each of these functions allows you to specify a `message`, an optional `body` for additional data, and a `parent` event to link related actions.
**1. Logging a simple informational message**
Use the `message` argument for a human-readable description of the event. You can also use `glue` syntax for dynamic messages.
```/dev/null/example.R#L1-1
faucet::info("Application started successfully.")
```
This would generate a structured log entry containing:
- A unique `event_id` for this specific log.
- `level: "Info"` indicating it's an informational message.
- `message: "Application started successfully."`
**2. Including additional data with `body`**
The `body` argument accepts any R object that can be converted to JSON, such as a list. This is useful for attaching contextual data, diagnostics, or payload details to your events.
```/dev/null/example.R#L1-1
faucet::info("User {user_id} logged in", user_id = "abc-123", body = list(session_duration_minutes = 15, ip_address = "192.168.1.10"))
```
This event will capture:
- The dynamic message: `"User abc-123 logged in"`.
- A `body` containing a list with `session_duration_minutes` and `ip_address`, allowing you to store specific metrics or details alongside the log message.
**3. Tracing a sequence of operations with `parent`**
You can link related events by passing the `event_id` of a previous event as the `parent` argument. This creates a "parent-child" relationship, helping you trace the flow of complex operations through your application.
```/dev/null/example.R#L1-2
event_id_start <- faucet::debug("Starting data retrieval from API.")
# ... perform data retrieval ...
faucet::info("Data retrieval complete.", parent = event_id_start, body = list(records_fetched = 1200))
```
In this example:
- The `debug` event marks the start of an operation, generating its own `event_id`.
- The subsequent `info` event related to completion will include the `event_id_start` as its `parent_event_id`, clearly indicating that it's a follow-up to the data retrieval initiation.
### Storing and Analyzing Event Data
All structured events emitted by your Shiny applications are automatically captured by faucet and stored in the `faucet_log_events` table within your PostgreSQL database. This enables you to:
- **Query and Filter**: Easily search for specific events based on `level`, `message` content, or data within the `body`.
- **Analyze Trends**: Track the frequency of certain events or errors over time.
- **Reconstruct User Journeys**: Use `event_id` and `parent_event_id` to trace a user's interactions or the execution flow of a specific request through your application.
- **Build Dashboards**: Use the structured data to create monitoring dashboards that provide real-time insights into your application's health and performance.
## Filtering logs
By default, faucet logs at the `INFO` level, which means that `ERROR`,
`WARN`, and `INFO` logs are shown. To change the log level, use the
`FAUCET_LOG` environment variable.
> **Note:** Plumber prints errors that occur on endpoints to `stdout`, so
> if you want to see those errors, you will need to set the log level to
> `INFO` or lower. Shiny on the other hand prints errors to `stderr`, so
> you will need to set the log level to `WARN` or lower to see those errors.
## Writing logs a file
faucet allows you to redirect log output to a file. This will disable colors
on `stderr`.
You can redirect to a file by specifying the path on the `FAUCET_LOG_FILE`
environment variable or by passing the `--log-file` argument to `faucet start`
or `faucet router`.