Module: Foam::Otel::LLM::OpenAIShim

Defined in:
lib/foam/otel/llm/openai_shim.rb

Overview

Gap-filler for the OFFICIAL OpenAI Ruby SDK (gem "openai"). Patches the two public non-streaming call sites — Chat::Completions#create and Responses#create (the reasoning-model path python's gap-filler covers) — with a gen_ai CLIENT span. Streaming (#stream/#stream_raw) is a recorded follow-up, same as the js/python gap-fillers.

Defined Under Namespace

Modules: ChatPatch, ResponsesPatch

Constant Summary collapse

SUPPORTED_BELOW =
Gem::Version.new("2.0.0")
CHAT_RESPONSE =

ChatCompletion → response attributes (usage: prompt/completion).

lambda do |response|
  usage = response.respond_to?(:usage) ? response.usage : nil
  choices = response.respond_to?(:choices) ? Array(response.choices) : []
  LLM.response_attributes(
    model: response.respond_to?(:model) ? response.model : nil,
    id: response.respond_to?(:id) ? response.id : nil,
    finish_reasons: choices.map { |c| c.respond_to?(:finish_reason) ? c.finish_reason : nil }.compact,
    input_tokens: usage.respond_to?(:prompt_tokens) ? usage.prompt_tokens : nil,
    output_tokens: usage.respond_to?(:completion_tokens) ? usage.completion_tokens : nil,
    output_messages: choices.map { |c| c.respond_to?(:message) ? c.message : nil }.compact
  )
end
RESPONSES_RESPONSE =

Responses-API Response → response attributes (usage: input/output).

lambda do |response|
  usage = response.respond_to?(:usage) ? response.usage : nil
  LLM.response_attributes(
    model: response.respond_to?(:model) ? response.model : nil,
    id: response.respond_to?(:id) ? response.id : nil,
    input_tokens: usage.respond_to?(:input_tokens) ? usage.input_tokens : nil,
    output_tokens: usage.respond_to?(:output_tokens) ? usage.output_tokens : nil,
    output_messages: response.respond_to?(:output) ? response.output : nil
  )
end

Class Method Summary collapse

Class Method Details

.chat_request(params) ⇒ Object



52
53
54
55
56
57
58
59
60
61
# File 'lib/foam/otel/llm/openai_shim.rb', line 52

def chat_request(params)
  params = params.is_a?(Hash) ? params : {}
  LLM.request_attributes(
    provider: "openai", operation: "chat",
    model: params[:model] || params["model"],
    max_tokens: params[:max_tokens] || params["max_tokens"] ||
                params[:max_completion_tokens] || params["max_completion_tokens"],
    input_messages: params[:messages] || params["messages"]
  )
end

.install!Object



21
22
23
24
25
26
27
28
29
30
# File 'lib/foam/otel/llm/openai_shim.rb', line 21

def install!
  return true if @installed

  ::OpenAI::Resources::Chat::Completions.prepend(ChatPatch)
  if defined?(::OpenAI::Resources::Responses) && ::OpenAI::Resources::Responses.method_defined?(:create)
    ::OpenAI::Resources::Responses.prepend(ResponsesPatch)
  end
  Diagnostics.info("LLM shim installed: openai (chat.completions.create, responses.create)")
  @installed = true
end

.installed?Boolean

Returns:

  • (Boolean)


32
# File 'lib/foam/otel/llm/openai_shim.rb', line 32

def installed? = @installed

.present?Boolean

Returns:

  • (Boolean)


15
16
17
18
19
# File 'lib/foam/otel/llm/openai_shim.rb', line 15

def present?
  defined?(::OpenAI::Resources::Chat::Completions) &&
    ::OpenAI::Resources::Chat::Completions.method_defined?(:create) &&
    supported_version?
end

.responses_request(params) ⇒ Object



63
64
65
66
67
68
69
70
71
72
# File 'lib/foam/otel/llm/openai_shim.rb', line 63

def responses_request(params)
  params = params.is_a?(Hash) ? params : {}
  LLM.request_attributes(
    provider: "openai", operation: "chat",
    model: params[:model] || params["model"],
    max_tokens: params[:max_output_tokens] || params["max_output_tokens"],
    input_messages: params[:input] || params["input"],
    system_instructions: params[:instructions] || params["instructions"]
  )
end

.supported_version?Boolean

Version guard: shape-checked AND version-windowed — a future major can rearrange the resource layer; foam then goes dark for this SDK (warned) instead of emitting garbage.

Returns:

  • (Boolean)


37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/foam/otel/llm/openai_shim.rb', line 37

def supported_version?
  spec = Gem.loaded_specs["openai"]
  return true if spec.nil? # vendored/unknown: the shape checks decide

  supported = spec.version < SUPPORTED_BELOW
  unless supported || @version_warned
    @version_warned = true
    Diagnostics.warn("openai #{spec.version} is outside foam's LLM-shim window (< #{SUPPORTED_BELOW}) " \
                     "— the OpenAI shim stays dark; file this with foam support")
  end
  supported
rescue StandardError
  true
end