HTTPower.Logger (HTTPower v0.16.0)

View Source

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).

Summary

Functions

Attaches the HTTPower logger as a telemetry event handler.

Detaches the HTTPower logger from telemetry events.

Generates a unique correlation ID for request tracing.

Sanitizes request/response body by redacting sensitive data.

Sanitizes headers by redacting sensitive values.

Types

log_level()

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

Functions

attach(opts \\ [])

@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()

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

Detaches the HTTPower logger from telemetry events.

Examples

HTTPower.Logger.detach()

generate_correlation_id()

@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(body)

@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(headers)

@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"}