Module: LlmCostTracker::Integrations::Base

Included in:
Anthropic, Openai, RubyLlm
Defined in:
lib/llm_cost_tracker/integrations/base.rb

Defined Under Namespace

Classes: Result

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.object_dig(object, *path) ⇒ Object



95
96
97
98
99
100
101
# File 'lib/llm_cost_tracker/integrations/base.rb', line 95

def object_dig(object, *path)
  path.reduce(object) do |current, key|
    return nil if current.nil?

    read_object_value(current, key)
  end
end

.object_value(object, *keys) ⇒ Object



87
88
89
90
91
92
93
# File 'lib/llm_cost_tracker/integrations/base.rb', line 87

def object_value(object, *keys)
  keys.each do |key|
    value = read_object_value(object, key)
    return value unless value.nil?
  end
  nil
end

Instance Method Details

#active?Boolean

Returns:

  • (Boolean)


16
17
18
# File 'lib/llm_cost_tracker/integrations/base.rb', line 16

def active?
  LlmCostTracker.configuration.instrumented?(integration_name)
end

#elapsed_ms(started_at) ⇒ Object



43
44
45
# File 'lib/llm_cost_tracker/integrations/base.rb', line 43

def elapsed_ms(started_at)
  Timing.elapsed_ms(started_at)
end

#enforce_budget!Object



47
48
49
# File 'lib/llm_cost_tracker/integrations/base.rb', line 47

def enforce_budget!
  LlmCostTracker::Tracker.enforce_budget! if active?
end

#installObject



20
21
22
23
24
25
26
# File 'lib/llm_cost_tracker/integrations/base.rb', line 20

def install
  validate_contract!
  patch_targets.each do |target|
    target_class = target.fetch(:constant_name).to_s.safe_constantize
    install_patch(target_class, target.fetch(:patch)) if target_class
  end
end

#minimum_versionObject



103
# File 'lib/llm_cost_tracker/integrations/base.rb', line 103

def minimum_version = nil

#patch_target(constant_name, with:, methods:, optional: false) ⇒ Object



109
110
111
112
113
114
115
116
# File 'lib/llm_cost_tracker/integrations/base.rb', line 109

def patch_target(constant_name, with:, methods:, optional: false)
  {
    constant_name: constant_name,
    patch: with,
    method_names: Array(methods),
    optional: optional
  }
end

#patch_targetsObject



107
# File 'lib/llm_cost_tracker/integrations/base.rb', line 107

def patch_targets = []

#record_safelyObject



51
52
53
54
55
56
57
# File 'lib/llm_cost_tracker/integrations/base.rb', line 51

def record_safely
  yield
rescue LlmCostTracker::Error
  raise
rescue StandardError => e
  Logging.warn("#{integration_name} integration failed to record usage: #{e.class}: #{e.message}")
end

#request_params(args, kwargs) ⇒ Object



59
60
61
62
# File 'lib/llm_cost_tracker/integrations/base.rb', line 59

def request_params(args, kwargs)
  params = args.first.is_a?(Hash) ? args.first : {}
  params.merge(kwargs).with_indifferent_access
end

#statusObject



28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/llm_cost_tracker/integrations/base.rb', line 28

def status
  name = integration_name
  problems = version_problems + target_problems
  if problems.any?
    return Result.new(name, :warn, "#{name} integration cannot be installed: #{problems.join('; ')}")
  end

  installed = patch_targets.reject { |target| target.fetch(:optional) }.all? do |target|
    target.fetch(:constant_name).to_s.safe_constantize&.ancestors&.include?(target.fetch(:patch))
  end
  return Result.new(name, :ok, "#{name} integration installed") if installed

  Result.new(name, :warn, "#{name} integration is enabled but not installed")
end

#stream_collector(request) ⇒ Object



75
76
77
78
79
80
81
# File 'lib/llm_cost_tracker/integrations/base.rb', line 75

def stream_collector(request)
  LlmCostTracker::Capture::StreamCollector.new(
    provider: integration_name.to_s,
    model: request[:model],
    pricing_mode: stream_pricing_mode(request)
  )
end

#stream_pricing_mode(_request) ⇒ Object



83
84
85
# File 'lib/llm_cost_tracker/integrations/base.rb', line 83

def stream_pricing_mode(_request)
  nil
end

#track_stream(stream, collector:) ⇒ Object



64
65
66
67
68
69
70
71
72
73
# File 'lib/llm_cost_tracker/integrations/base.rb', line 64

def track_stream(stream, collector:)
  return stream unless active?

  LlmCostTracker::Capture::StreamTracker.new(
    stream: stream,
    collector: collector,
    active: -> { active? },
    finish: ->(errored:) { record_safely { collector.finish!(errored: errored) } }
  ).wrap
end

#version_constantObject



105
# File 'lib/llm_cost_tracker/integrations/base.rb', line 105

def version_constant = nil