Skip to content

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.