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:



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

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:



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

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:



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

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:



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

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.



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

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)


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

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.



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

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)


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

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)


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

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)


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

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)


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

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:



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

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)


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

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