ML-158: force single-line log output in production
Three-layer architecture: - Logster v2 handles HTTP request and LiveView socket telemetry in logfmt format - Custom formatter as safety net escaping any remaining embedded newlines - Config flag (single_line_logging) gating Logster attachment to prod only Dev environment retains multi-line format for readability.
This commit is contained in:
@@ -42,6 +42,9 @@ MusicLibrary.Application (one_for_one)
|
||||
└── MusicLibraryWeb.Endpoint
|
||||
```
|
||||
|
||||
Logster v2 (production-only) is attached as a telemetry handler via `application.ex`
|
||||
when `single_line_logging` is `true` — not a supervised process.
|
||||
|
||||
---
|
||||
|
||||
## Database & Repos
|
||||
@@ -145,6 +148,7 @@ Last.fm schemas (separate, not Ecto-persisted to main DB):
|
||||
| `MusicLibrary.Mailer` | Swoosh mailer (Mailgun in prod, local adapter in dev) |
|
||||
| `FormatNumber` | Number formatting utility |
|
||||
| `QueryReporter` | Dev-only Ecto telemetry reporter: captures executed SQL to a log file with interpolated params, source locations, and timing. Activated at runtime via `start/1` / `stop/0` |
|
||||
| `MusicLibrary.Logger.SingleLineFormatter` | Production-only Logger.Formatter safety net: replaces embedded newlines (`\n`) with escaped `\\n` in all log messages, ensuring every physical log line is exactly one log event |
|
||||
|
||||
---
|
||||
|
||||
@@ -327,6 +331,7 @@ All authenticated routes live inside a single `live_session` with three `on_moun
|
||||
| `LiveHelpers.Params` | URL query param parsing: pagination, search query, sort order, display mode, fallback index |
|
||||
| `LiveHelpers.IndexActions` | Shared index page logic (search, pagination, import, delete, display mode) for Collection/Wishlist index pages, parameterized by config map |
|
||||
| `LiveHelpers.RecordActions` | Shared record action handlers (refresh cover, genres, embeddings, MusicBrainz data) for Collection/Wishlist show pages |
|
||||
| — | Logster v2 handles `[:phoenix, :socket_connected]` telemetry — not a custom module |
|
||||
|
||||
### Controllers
|
||||
|
||||
|
||||
@@ -196,6 +196,47 @@ ERL_FLAGS: `+JPperf true` (JIT performance monitoring).
|
||||
`GET /health` — queries the main database, returns 200 or 500. Used by Docker health
|
||||
checks and post-deploy verification.
|
||||
|
||||
### Logging
|
||||
|
||||
Production logs are configured for single-line output so every physical log line
|
||||
corresponds to exactly one log event. This makes log files reliably filterable with
|
||||
line-oriented tools (grep, tail, sort) and enables deterministic reverse-order reading.
|
||||
|
||||
Three layers work together:
|
||||
|
||||
1. **Logster v2** — Replaces `Phoenix.Logger` for HTTP request and LiveView socket
|
||||
telemetry. Merges `GET + Sent` into a single logfmt line with `method`, `path`,
|
||||
`status`, `duration`, and `request_id` fields. Handles `[:phoenix, :socket_connected]`
|
||||
telemetry, flattening the multi-line handshake output into one line.
|
||||
|
||||
2. **Custom formatter** (`MusicLibrary.Logger.SingleLineFormatter`) — Safety net that
|
||||
replaces any remaining embedded newlines (`\n`) with escaped `\\n` in ALL log
|
||||
messages. Catches stack traces, Erlang runtime messages, and any multi-line strings
|
||||
that Logster does not cover. Configured in `config/prod.exs`.
|
||||
|
||||
3. **Config flag** (`single_line_logging`) — Boolean in `config/config.exs` (default
|
||||
`false`) and overridden to `true` in `config/prod.exs`. Controls `Logster.attach_phoenix_logger()`
|
||||
in `application.ex`. Dev/test environments keep the default multi-line format for readability.
|
||||
|
||||
Configuration summary:
|
||||
|
||||
```elixir
|
||||
# config/prod.exs
|
||||
config :phoenix, :logger, false
|
||||
config :music_library, :single_line_logging, true
|
||||
|
||||
config :logster,
|
||||
extra_fields: [:request_id],
|
||||
filter_parameters: Application.get_env(:phoenix, :filter_parameters, ["password"])
|
||||
|
||||
config :logger, :default_formatter,
|
||||
format: {MusicLibrary.Logger.SingleLineFormatter, :format},
|
||||
metadata: [:request_id, :pid]
|
||||
```
|
||||
|
||||
Dev environment retains the default `"$time $metadata[$level] $message\n"` format with
|
||||
`Phoenix.Logger` active.
|
||||
|
||||
### Error tracking
|
||||
|
||||
`ErrorTracker` with email notifications via Mailgun:
|
||||
|
||||
Reference in New Issue
Block a user