Module: OpenAI::Internal::Logging Private

Defined in:
lib/openai/internal/logging.rb,
sig/openai/internal/logging.rbs

Overview

This module is part of a private API. You should avoid using this module if possible, as it may be removed or be changed in the future.

Request logging helpers shared by generated clients.

Defined Under Namespace

Classes: Context, ObservedBody

Constant Summary collapse

LOG_LEVELS =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Returns:

  • (::Hash[Symbol, Integer])
{off: 0, error: 1, warn: 2, info: 3, debug: 4}.freeze
REDACTED_HEADERS =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Returns:

  • (::Array[String])
%w[
  api-key
  authorization
  cookie
  proxy-authorization
  set-cookie
  x-amz-security-token
  x-api-key
].freeze
MAX_BODY_BYTES =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Returns:

  • (Integer)
16 * 1024
MAX_ARRAY_ITEMS =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Returns:

  • (Integer)
100
OPAQUE_STRING_BYTES =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Returns:

  • (Integer)
1_024
SENSITIVE_BODY_KEY =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Returns:

  • (Regexp)
/(?:api[-_]?key|authorization|credential|password|secret|signature|token)/i
SENSITIVE_QUERY_KEY =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Returns:

  • (Regexp)
/
  (?:
    (?:\A|[-_\[])(?:key|sig)
    | (?-i:K)ey
    | api[-_]?key
    | authorization
    | credentials?
    | password
    | secret
    | signature
    | token
  )
  (?:\[|\]|\z)
/ix
URL_HEADER_KEY =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Returns:

  • (Regexp)
/(?:\A|[-_])(?:location|url|uri)\z|\A(?:link|refresh)\z/i

Class Method Summary collapse

Class Method Details

.capture_response_body?(headers) ⇒ Boolean

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.

Parameters:

  • headers (::Hash[String, String])

Returns:



325
326
327
328
# File 'lib/openai/internal/logging.rb', line 325

def capture_response_body?(headers)
  content_type = headers["content-type"].to_s
  textual_content_type?(content_type) && !content_type.match?(%r{\Atext/event-stream}i)
end

.credential_header?(name) ⇒ Boolean

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.

Parameters:

  • name (String, Symbol)

Returns:



289
290
291
292
293
294
295
296
# File 'lib/openai/internal/logging.rb', line 289

def credential_header?(name)
  normalized_name = name.to_s.downcase
  idempotency = normalized_name.match(/(?:\A|[-_])idempotency[-_]key\z/)
  return sensitive_header?(normalized_name) unless idempotency

  prefix = normalized_name[...idempotency.begin(0)]
  prefix.split(/[-_]/).any? { sensitive_header?(_1) }
end

.default_loggerOpenAI::_Logger

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.

Returns:



256
# File 'lib/openai/internal/logging.rb', line 256

def default_logger = ::Logger.new($stderr)

.enabled?(configured_level, event_level) ⇒ Boolean

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.

Parameters:

  • configured_level (Symbol)
  • event_level (Symbol)

Returns:



258
259
260
# File 'lib/openai/internal/logging.rb', line 258

def enabled?(configured_level, event_level)
  LOG_LEVELS.fetch(configured_level) >= LOG_LEVELS.fetch(event_level)
end

.format_body(body, headers:) ⇒ Object

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.



315
316
317
318
319
320
321
322
323
# File 'lib/openai/internal/logging.rb', line 315

def format_body(body, headers:)
  content_type = headers["content-type"].to_s
  return "[NO BODY]" if body.nil?
  return "[MULTIPART BODY OMITTED]" if content_type.match?(%r{\Amultipart/}i)
  return "[STREAMING BODY OMITTED]" unless body.is_a?(String)
  return "[BINARY BODY OMITTED] bytes=#{body.bytesize}" unless textual_content_type?(content_type)

  format_text_body(body, content_type: content_type, total_bytes: body.bytesize)
end

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

Parameters:

  • headers (::Hash[String, String])

Returns:

  • (String)


298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
# File 'lib/openai/internal/logging.rb', line 298

def format_headers(headers)
  redacted =
    headers.sort.to_h do |name, value|
      normalized_name = name.to_s.downcase
      rendered =
        if sensitive_header?(normalized_name)
          "[REDACTED]"
        elsif URL_HEADER_KEY.match?(normalized_name)
          sanitized_header_url(value)
        else
          value
        end
      [name, rendered]
    end
  JSON.generate(redacted)
end

.format_observed_body(body, headers:, complete:, total_bytes:) ⇒ Object

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.



330
331
332
333
334
335
336
337
338
339
340
341
342
# File 'lib/openai/internal/logging.rb', line 330

def format_observed_body(body, headers:, complete:, total_bytes:)
  content_type = headers["content-type"].to_s
  return "[STREAM BODY OMITTED] bytes=#{total_bytes}" if content_type.match?(%r{\Atext/event-stream}i)
  return "[BODY CLOSED EARLY] bytes=#{total_bytes}" unless complete
  unless textual_content_type?(content_type)
    return "[BINARY BODY OMITTED] bytes=#{total_bytes}"
  end
  if total_bytes > MAX_BODY_BYTES && json_content_type?(content_type)
    return "[JSON BODY OMITTED] bytes=#{total_bytes} reason=too_large"
  end

  format_text_body(body, content_type: content_type, total_bytes: total_bytes)
end

.normalize_level(value) ⇒ Symbol

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.

Parameters:

  • value (Symbol, String)

Returns:

  • (Symbol)

Raises:

  • (ArgumentError)


240
241
242
243
244
245
# File 'lib/openai/internal/logging.rb', line 240

def normalize_level(value)
  level = value.to_s.downcase.to_sym if value.is_a?(String) || value.is_a?(Symbol)
  return level if LOG_LEVELS.key?(level)

  raise ArgumentError, "`log_level` must be one of :off, :error, :warn, :info, or :debug"
end

.safe_field(value) ⇒ 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.

Parameters:

  • value (top, nil)

Returns:

  • (String)


276
277
278
279
280
# File 'lib/openai/internal/logging.rb', line 276

def safe_field(value)
  return "none" if value.nil?

  value.to_s.dump.delete_prefix('"').delete_suffix('"')
end

.safe_path(url) ⇒ 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.

Parameters:

  • url (URI::Generic)

Returns:

  • (String)


262
263
264
265
266
267
268
# File 'lib/openai/internal/logging.rb', line 262

def safe_path(url)
  uri = sanitized_uri(url)
  path = uri.path.to_s.empty? ? "/" : uri.path
  uri.query.nil? ? path : "#{path}?#{uri.query}"
rescue ArgumentError, URI::Error
  "[URL OMITTED]"
end

.safe_url(url) ⇒ 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.

Parameters:

  • url (URI::Generic)

Returns:

  • (String)


270
271
272
273
274
# File 'lib/openai/internal/logging.rb', line 270

def safe_url(url)
  sanitized_uri(url).to_s
rescue ArgumentError, URI::Error
  "[URL OMITTED]"
end

.sensitive_header?(name) ⇒ Boolean

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.

Parameters:

  • name (String, Symbol)

Returns:



283
284
285
286
# File 'lib/openai/internal/logging.rb', line 283

def sensitive_header?(name)
  normalized_name = name.to_s.downcase
  REDACTED_HEADERS.include?(normalized_name) || SENSITIVE_QUERY_KEY.match?(normalized_name)
end

.validate_logger!(logger) ⇒ 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.

Parameters:

Raises:

  • (ArgumentError)


247
248
249
250
251
252
253
254
# File 'lib/openai/internal/logging.rb', line 247

def validate_logger!(logger)
  return if logger.nil?

  methods = [:debug, :info, :warn, :error]
  return if methods.all? { logger.respond_to?(_1) }

  raise ArgumentError, "`logger` must respond to `debug`, `info`, `warn`, and `error`"
end