# `HTTPower.Logger`
[🔗](https://github.com/mdepolli/httpower/blob/v0.22.0/lib/httpower/logger.ex#L1)

PCI-compliant HTTP request/response logging via telemetry for HTTPower.

This module provides a telemetry event handler that logs HTTP requests and responses
with automatic PCI-compliant data sanitization, redacting sensitive data like credit
card numbers, authorization tokens, passwords, and other PII.

## Features

- Telemetry-based logging (opt-in by attaching)
- **Structured logging with metadata** - All logs include machine-readable metadata
- Automatic PCI-compliant data sanitization
- Correlation IDs for request tracing
- Header and body sanitization
- Performance timing information
- Configurable log levels and format

## Structured Logging

All log entries include structured metadata accessible via `Logger.metadata()`:

**Request metadata:**
- `httpower_correlation_id` - Unique request identifier
- `httpower_event` - Event type (`:request`, `:response`, or `:exception`)
- `httpower_method` - HTTP method (`:get`, `:post`, etc.)
- `httpower_url` - Request URL
- `httpower_headers` - Sanitized request headers (if enabled)
- `httpower_body` - Sanitized request body (if enabled)

**Response metadata:**
- `httpower_correlation_id` - Matches request correlation ID
- `httpower_event` - `:response`
- `httpower_status` - HTTP status code
- `httpower_duration_ms` - Request duration in milliseconds
- `httpower_response_headers` - Sanitized response headers (if enabled)
- `httpower_response_body` - Sanitized response body (if enabled)

**Exception metadata:**
- `httpower_correlation_id` - Request correlation ID
- `httpower_event` - `:exception`
- `httpower_duration_ms` - Time until exception
- `httpower_exception_kind` - Exception kind (`:error`, `:exit`, `:throw`)
- `httpower_exception_reason` - Exception reason

This structured metadata enables powerful querying in log aggregation systems
like Datadog, Splunk, ELK, or Loki:

    # Query all slow requests
    httpower_duration_ms:>1000

    # Find all 5xx errors
    httpower_status:>=500

    # Trace a specific request
    httpower_correlation_id:"req_abc123"

## Sanitization Rules

The logger automatically sanitizes:
- Credit card numbers (any 13-19 digit sequence)
- CVV codes (3-4 digit security codes)
- Authorization headers (Bearer tokens, Basic auth)
- API keys and secret tokens
- Password fields
- Email addresses (optional)
- Phone numbers (optional)

## Configuration

    config :httpower, :logging,
      level: :info,
      log_headers: true,
      log_body: true,
      sanitize_headers: ["authorization", "api-key", "x-api-key"],
      sanitize_body_fields: ["password", "credit_card", "cvv"]

## Usage

Attach the logger in your application startup:

    # In application.ex
    def start(_type, _args) do
      HTTPower.Logger.attach()
      # ... rest of your supervision tree
    end

Or attach with custom configuration:

    HTTPower.Logger.attach(
      level: :debug,
      log_headers: false,
      log_body: true
    )

To detach:

    HTTPower.Logger.detach()

## Integration with Phoenix

    # In your endpoint.ex or application.ex
    HTTPower.Logger.attach()

The logger will automatically use correlation IDs from `Logger.metadata()[:request_id]`
if available (e.g., from Phoenix requests).

# `log_level`

```elixir
@type log_level() :: :debug | :info | :warning | :error
```

# `attach`

```elixir
@spec attach(keyword()) :: :ok | {:error, :already_exists}
```

Attaches the HTTPower logger as a telemetry event handler.

## Options

- `:level` - Log level to use (default: `:info`)
- `:log_headers` - Whether to log headers (default: `true`)
- `:log_body` - Whether to log body (default: `true`)
- `:sanitize_headers` - Additional headers to sanitize (list of strings)
- `:sanitize_body_fields` - Additional body fields to sanitize (list of strings)

## Examples

    # Use defaults from config
    HTTPower.Logger.attach()

    # Override specific options
    HTTPower.Logger.attach(level: :debug, log_body: false)

# `detach`

```elixir
@spec detach() :: :ok | {:error, :not_found}
```

Detaches the HTTPower logger from telemetry events.

## Examples

    HTTPower.Logger.detach()

# `generate_correlation_id`

```elixir
@spec generate_correlation_id() :: String.t()
```

Generates a unique correlation ID for request tracing.

Format: "req_" + 16 random hexadecimal characters

## Examples

    iex> id = HTTPower.Logger.generate_correlation_id()
    iex> String.starts_with?(id, "req_")
    true
    iex> String.length(id)
    20

# `sanitize_body`

```elixir
@spec sanitize_body(String.t() | map() | nil) :: String.t() | map() | nil
```

Sanitizes request/response body by redacting sensitive data.

Handles both string and map bodies. Applies pattern matching for credit cards,
CVV codes, and sanitizes configured field names.

## Examples

    iex> HTTPower.Logger.sanitize_body(~s({"password": "secret123"}))
    ~s({"password": "[REDACTED]"})

    iex> HTTPower.Logger.sanitize_body("card: 4111111111111111")
    "card: [REDACTED]"

# `sanitize_headers`

```elixir
@spec sanitize_headers(map()) :: map()
```

Sanitizes headers by redacting sensitive values.

Headers in the configured sanitization list are replaced with "[REDACTED]".

## Examples

    iex> HTTPower.Logger.sanitize_headers(%{"Authorization" => "Bearer token123"})
    %{"authorization" => "[REDACTED]"}

    iex> HTTPower.Logger.sanitize_headers(%{"Content-Type" => "application/json"})
    %{"content-type" => "application/json"}

---

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