# `PdfElixide.Logging`
[🔗](https://github.com/r8/pdf_elixide/blob/v0.16.0/lib/pdf_elixide/logging.ex#L1)

Diagnostics for content that extraction drops without failing.

Most damaged pages do not produce an error. A content stream that will not
decode, a font that fails to load, a Form XObject that cannot be processed
and a character with no usable mapping are all handled by continuing with
less content, so `PdfElixide.Document.text/1` returns `{:ok, text}` with
material missing and no way to tell that page from a blank one. Each of those
is reported internally as a log record. Enable capture and the records reach
Elixir's `Logger`, naming the page and the reason.

This is off by default and is a diagnostic aid, not an error channel — a
captured record does not change what a call returns, and neither does a
failure to forward one, which is reported at `:error` level and nothing more.
Errors still arrive as `t:PdfElixide.Error.t/0`; see
`t:PdfElixide.Document.text_opts/0` for what `:on_page_error` can and cannot
catch.

## Enabling

    iex> PdfElixide.Logging.set_level(:warning)
    :ok

Records are then forwarded to `Logger` at the matching level, tagged with
`pdf_elixide: true` and the originating module in `:pdf_source` metadata.
Turn it back off with `set_level(:off)`, which also discards anything
captured but not yet forwarded.

To capture at startup, set it in your application's `start/2` before opening
any document.

## Attribution

Under concurrent use, a record may be forwarded by a process other than the
one whose work produced it. Forwarded records therefore omit that process's
`Logger` metadata. Use `:pdf_source`, the message and the timestamp instead;
the `:pid` added by `Logger` identifies only the forwarding process.

## Cost, and why it is off by default

Capture is process-global, not per-document or per-process: it affects every
document handle in the VM. Records are buffered as they are produced and
forwarded when the next call returns, so a level of `:debug` or `:trace` on a
large document produces a great deal of output and measurably slows
extraction. `:warning` is the level that reports dropped content.

The buffer is bounded. If it fills before anything drains it — capture
enabled but no further calls made — the oldest records are discarded, and a
single warning reports how many were lost so a truncated capture cannot be
mistaken for a complete one.

# `level`

```elixir
@type level() :: :off | :error | :warning | :info | :debug | :trace
```

Capture level, from `:off` (capture nothing) through `:trace` (capture
everything).

`:warning` is the level at which dropped content is reported. `:error` is
quieter than it sounds — a failure severe enough to be logged as an error is
usually also returned as a `t:PdfElixide.Error.t/0`, so `:warning` is the
useful floor for diagnosing missing text.

# `enabled?`

```elixir
@spec enabled?() :: boolean()
```

Returns whether capture is currently enabled.

# `flush`

```elixir
@spec flush() :: non_neg_integer()
```

Forwards every captured record to `Logger` and empties the buffer.

Called automatically after each library call while capture is enabled, so
reach for it directly only to flush records left by a call that raised.
Returns the number of records forwarded.

Records reach `Logger` without the calling process's own metadata; see
"Attribution" in the module documentation.

# `set_level`

```elixir
@spec set_level(level()) :: :ok
```

Sets the capture level, returning `:ok`.

Raises `ArgumentError` unless `level` is one of `[:off, :error, :warning, :info, :debug, :trace]`.
Setting `:off` also discards any records captured but not yet forwarded.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
