Class: HTTP::Features::Logging
- Inherits:
-
HTTP::Feature
- Object
- HTTP::Feature
- HTTP::Features::Logging
- Defined in:
- lib/http/features/logging.rb,
sig/http.rbs
Overview
Log requests and responses. Request verb and uri, and Response status are
logged at info, and the headers and bodies of both are logged at
debug. Be sure to specify the logger when enabling the feature:
HTTP.use(logging: {logger: Logger.new(STDOUT)}).get("https://example.com/")
Binary bodies (IO/Enumerable request sources and binary-encoded
responses) are formatted using the binary_formatter option instead
of being dumped raw. Available formatters:
:stats(default) — logs BINARY DATA (N bytes):base64— logs BINARY DATA (N bytes)\nProc— calls the proc with the raw binary string
Defined Under Namespace
Classes: BodyLogger, NullLogger
Instance Attribute Summary collapse
-
#logger ⇒ #info, #debug
readonly
The logger instance.
Instance Method Summary collapse
-
#format_binary(data) ⇒ String
private
Format binary data according to the configured binary_formatter.
-
#initialize(logger: NullLogger.new, binary_formatter: :stats) ⇒ Logging
constructor
Initializes the Logging feature.
-
#log_request_details(request) ⇒ void
private
Log request headers and body (when loggable).
-
#log_response_body_inline(response) ⇒ HTTP::Response
private
Log response with body inline (for non-streaming string bodies).
-
#logged_body(body) ⇒ HTTP::Response::Body
private
Wrap a response body with a logging stream.
-
#logged_response_options(response) ⇒ Hash
private
Build options hash for a response with body logging.
-
#stringify_headers(headers) ⇒ String
private
Convert headers to a string representation.
-
#validate_binary_formatter!(formatter) ⇒ :stats, ...
private
Validate and return the binary_formatter option.
-
#wrap_request(request) ⇒ HTTP::Request
Logs and returns the request.
-
#wrap_response(response) ⇒ HTTP::Response
Logs and returns the response.
Methods inherited from HTTP::Feature
#around_request, #on_error, #on_request
Constructor Details
#initialize(logger: NullLogger.new, binary_formatter: :stats) ⇒ Logging
Initializes the Logging feature
60 61 62 63 64 |
# File 'lib/http/features/logging.rb', line 60 def initialize(logger: NullLogger.new, binary_formatter: :stats) super() @logger = logger @binary_formatter = validate_binary_formatter!(binary_formatter) end |
Instance Attribute Details
#logger ⇒ #info, #debug (readonly)
The logger instance
46 47 48 |
# File 'lib/http/features/logging.rb', line 46 def logger @logger end |
Instance Method Details
#format_binary(data) ⇒ String
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Format binary data according to the configured binary_formatter
169 170 171 172 173 174 175 176 177 178 |
# File 'lib/http/features/logging.rb', line 169 def format_binary(data) case @binary_formatter when :stats format("BINARY DATA (%d bytes)", data.bytesize) when :base64 format("BINARY DATA (%d bytes)\n%s", data.bytesize, [data].pack("m0")) else @binary_formatter.call(data) # steep:ignore end end |
#log_request_details(request) ⇒ void
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
Log request headers and body (when loggable)
117 118 119 120 121 122 123 124 125 126 |
# File 'lib/http/features/logging.rb', line 117 def log_request_details(request) headers = stringify_headers(request.headers) if request.body.loggable? source = request.body.source body = source.encoding.eql?(Encoding::BINARY) ? format_binary(source) : source logger.debug { "#{headers}\n\n#{body}" } else logger.debug { headers } end end |
#log_response_body_inline(response) ⇒ HTTP::Response
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Log response with body inline (for non-streaming string bodies)
131 132 133 134 135 136 137 138 139 140 |
# File 'lib/http/features/logging.rb', line 131 def log_response_body_inline(response) body = response.body headers = stringify_headers(response.headers) if body.respond_to?(:encoding) && body.encoding.eql?(Encoding::BINARY) logger.debug { "#{headers}\n\n#{format_binary(body)}" } # steep:ignore else logger.debug { "#{headers}\n\n#{body}" } end response end |
#logged_body(body) ⇒ HTTP::Response::Body
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Wrap a response body with a logging stream
160 161 162 163 164 |
# File 'lib/http/features/logging.rb', line 160 def logged_body(body) formatter = (method(:format_binary) unless body.loggable?) stream = BodyLogger.new(body.instance_variable_get(:@stream), logger, formatter: formatter) # steep:ignore Response::Body.new(stream, encoding: body.encoding) end |
#logged_response_options(response) ⇒ Hash
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Build options hash for a response with body logging
145 146 147 148 149 150 151 152 153 154 155 |
# File 'lib/http/features/logging.rb', line 145 def (response) { status: response.status, version: response.version, headers: response.headers, proxy_headers: response.proxy_headers, connection: response.connection, body: logged_body(response.body), request: response.request } end |
#stringify_headers(headers) ⇒ String
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Convert headers to a string representation
183 184 185 |
# File 'lib/http/features/logging.rb', line 183 def stringify_headers(headers) headers.map { |name, value| "#{name}: #{value}" }.join("\n") end |
#validate_binary_formatter!(formatter) ⇒ :stats, ...
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Validate and return the binary_formatter option
106 107 108 109 110 111 112 |
# File 'lib/http/features/logging.rb', line 106 def validate_binary_formatter!(formatter) return formatter if formatter.eql?(:stats) || formatter.eql?(:base64) || formatter.respond_to?(:call) raise ArgumentError, "binary_formatter must be :stats, :base64, or a callable " \ "(got #{formatter.inspect})" end |
#wrap_request(request) ⇒ HTTP::Request
Logs and returns the request
74 75 76 77 78 79 |
# File 'lib/http/features/logging.rb', line 74 def wrap_request(request) logger.info { format("> %s %s", String(request.verb).upcase, request.uri) } log_request_details(request) request end |
#wrap_response(response) ⇒ HTTP::Response
Logs and returns the response
89 90 91 92 93 94 95 96 97 98 |
# File 'lib/http/features/logging.rb', line 89 def wrap_response(response) logger.info { "< #{response.status}" } return log_response_body_inline(response) unless response.body.is_a?(Response::Body) logger.debug { stringify_headers(response.headers) } return response unless logger.debug? Response.new(**(response)) # steep:ignore end |