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)/i
CALL_ID_ALIASES =

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.

%w[callid call-id call_id].freeze
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:



320
321
322
323
# File 'lib/openai/internal/logging.rb', line 320

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:



284
285
286
287
288
289
290
291
# File 'lib/openai/internal/logging.rb', line 284

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:



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

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:



251
252
253
# File 'lib/openai/internal/logging.rb', line 251

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.



310
311
312
313
314
315
316
317
318
# File 'lib/openai/internal/logging.rb', line 310

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)


293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
# File 'lib/openai/internal/logging.rb', line 293

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.



325
326
327
328
329
330
331
332
333
334
335
336
337
338
# File 'lib/openai/internal/logging.rb', line 325

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)


233
234
235
236
237
238
# File 'lib/openai/internal/logging.rb', line 233

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)


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

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)


255
256
257
258
259
260
261
# File 'lib/openai/internal/logging.rb', line 255

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)


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

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:



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

def sensitive_header?(name)
  normalized_name = name.to_s.downcase
  REDACTED_HEADERS.include?(normalized_name) ||
    SENSITIVE_QUERY_KEY.match?(normalized_name) ||
    sensitive_call_id?(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)


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

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