Class: Aidp::Harness::ProviderMetrics

Inherits:
Object
  • Object
show all
Includes:
RescueLogging
Defined in:
lib/aidp/harness/provider_metrics.rb

Overview

Persists provider metrics and rate limit information to disk Enables the provider dashboard to display real-time state

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from RescueLogging

__log_rescue_impl, #log_rescue, log_rescue

Constructor Details

#initialize(project_dir) ⇒ ProviderMetrics

Returns a new instance of ProviderMetrics.



17
18
19
20
21
22
23
24
# File 'lib/aidp/harness/provider_metrics.rb', line 17

def initialize(project_dir)
  # Store metrics at the repository root so different worktrees/modes share state
  @project_dir = Aidp::Util.find_project_root(project_dir)
  @metrics_file = File.join(@project_dir, ".aidp", "provider_metrics.yml")
  @rate_limit_file = File.join(@project_dir, ".aidp", "provider_rate_limits.yml")
  @usage_tracking_dir = File.join(@project_dir, ".aidp", "usage_tracking")
  ensure_directory
end

Instance Attribute Details

#metrics_fileObject (readonly)

Returns the value of attribute metrics_file.



15
16
17
# File 'lib/aidp/harness/provider_metrics.rb', line 15

def metrics_file
  @metrics_file
end

#project_dirObject (readonly)

Returns the value of attribute project_dir.



15
16
17
# File 'lib/aidp/harness/provider_metrics.rb', line 15

def project_dir
  @project_dir
end

#rate_limit_fileObject (readonly)

Returns the value of attribute rate_limit_file.



15
16
17
# File 'lib/aidp/harness/provider_metrics.rb', line 15

def rate_limit_file
  @rate_limit_file
end

#usage_tracking_dirObject (readonly)

Returns the value of attribute usage_tracking_dir.



15
16
17
# File 'lib/aidp/harness/provider_metrics.rb', line 15

def usage_tracking_dir
  @usage_tracking_dir
end

Instance Method Details

#clearObject

Clear all persisted metrics



79
80
81
82
83
# File 'lib/aidp/harness/provider_metrics.rb', line 79

def clear
  File.delete(@metrics_file) if File.exist?(@metrics_file)
  File.delete(@rate_limit_file) if File.exist?(@rate_limit_file)
  clear_usage_tracking
end

#clear_usage_tracking(provider_name = nil) ⇒ Object

Clear usage tracking data for a specific provider

Parameters:

  • provider_name (String) (defaults to: nil)

    Name of the provider (optional, clears all if nil)



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/aidp/harness/provider_metrics.rb', line 127

def clear_usage_tracking(provider_name = nil)
  if provider_name
    usage_file = usage_tracking_file(provider_name)
    File.delete(usage_file) if File.exist?(usage_file)
  else
    # Clear all usage tracking files
    return unless File.directory?(@usage_tracking_dir)

    Dir.glob(File.join(@usage_tracking_dir, "*.yml")).each do |file|
      File.delete(file)
    rescue => e
      log_rescue(e, component: "provider_metrics", action: "clear_usage_file", fallback: nil)
    end
  end
end

#load_metricsObject

Load provider metrics from disk



39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/aidp/harness/provider_metrics.rb', line 39

def load_metrics
  return {} unless File.exist?(@metrics_file)

  data = YAML.safe_load_file(@metrics_file, permitted_classes: [Time, Date, Symbol], aliases: true)
  return {} unless data.is_a?(Hash)

  # Convert ISO8601 strings back to Time objects
  deserialize_metrics(data)
rescue => e
  log_rescue(e, component: "provider_metrics", action: "load_metrics", fallback: {})
  {}
end

#load_rate_limitsObject

Load rate limit information from disk



65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/aidp/harness/provider_metrics.rb', line 65

def load_rate_limits
  return {} unless File.exist?(@rate_limit_file)

  data = YAML.safe_load_file(@rate_limit_file, permitted_classes: [Time, Date, Symbol], aliases: true)
  return {} unless data.is_a?(Hash)

  # Convert ISO8601 strings back to Time objects
  deserialize_rate_limits(data)
rescue => e
  log_rescue(e, component: "provider_metrics", action: "load_rate_limits", fallback: {})
  {}
end

#load_usage_tracking(provider_name) ⇒ Hash

Load usage tracking data for a provider

Parameters:

  • provider_name (String)

    Name of the provider

Returns:

  • (Hash)

    Usage tracking data or empty hash



111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/aidp/harness/provider_metrics.rb', line 111

def load_usage_tracking(provider_name)
  usage_file = usage_tracking_file(provider_name)
  return {} unless File.exist?(usage_file)

  data = YAML.safe_load_file(usage_file, permitted_classes: [Time, Date, Symbol], aliases: true)
  return {} unless data.is_a?(Hash)

  deserialize_usage_tracking(data)
rescue => e
  log_rescue(e, component: "provider_metrics", action: "load_usage_tracking", fallback: {})
  {}
end

#providers_with_usage_trackingArray<String>

List all providers with usage tracking data

Returns:

  • (Array<String>)

    Array of provider names



146
147
148
149
150
151
152
# File 'lib/aidp/harness/provider_metrics.rb', line 146

def providers_with_usage_tracking
  return [] unless File.directory?(@usage_tracking_dir)

  Dir.glob(File.join(@usage_tracking_dir, "*.yml")).map do |file|
    File.basename(file, ".yml")
  end
end

#save_metrics(metrics_hash) ⇒ Object

Save provider metrics to disk



27
28
29
30
31
32
33
34
35
36
# File 'lib/aidp/harness/provider_metrics.rb', line 27

def save_metrics(metrics_hash)
  return if metrics_hash.nil? || metrics_hash.empty?

  # Convert Time objects to ISO8601 strings for YAML serialization
  serializable_metrics = serialize_metrics(metrics_hash)

  File.write(@metrics_file, YAML.dump(serializable_metrics))
rescue => e
  log_rescue(e, component: "provider_metrics", action: "save_metrics", fallback: nil)
end

#save_rate_limits(rate_limit_hash) ⇒ Object

Save rate limit information to disk



53
54
55
56
57
58
59
60
61
62
# File 'lib/aidp/harness/provider_metrics.rb', line 53

def save_rate_limits(rate_limit_hash)
  return if rate_limit_hash.nil? || rate_limit_hash.empty?

  # Convert Time objects to ISO8601 strings for YAML serialization
  serializable_rate_limits = serialize_rate_limits(rate_limit_hash)

  File.write(@rate_limit_file, YAML.dump(serializable_rate_limits))
rescue => e
  log_rescue(e, component: "provider_metrics", action: "save_rate_limits", fallback: nil)
end

#save_usage_tracking(provider_name, usage_data) ⇒ Object

Save usage tracking data for a provider

Parameters:

  • provider_name (String)

    Name of the provider

  • usage_data (Hash)

    Usage tracking data



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/aidp/harness/provider_metrics.rb', line 89

def save_usage_tracking(provider_name, usage_data)
  return if usage_data.nil? || usage_data.empty?

  ensure_usage_tracking_directory
  usage_file = usage_tracking_file(provider_name)

  # Serialize Time objects for YAML
  serializable_data = serialize_usage_tracking(usage_data)

  # Write atomically using temp file + rename
  temp_file = "#{usage_file}.tmp"
  File.write(temp_file, YAML.dump(serializable_data))
  File.rename(temp_file, usage_file)
rescue => e
  log_rescue(e, component: "provider_metrics", action: "save_usage_tracking", fallback: nil)
  File.delete(temp_file) if defined?(temp_file) && File.exist?(temp_file)
end