Class: Ask::Agent::Telemetry
- Inherits:
-
Object
- Object
- Ask::Agent::Telemetry
- Defined in:
- lib/ask/agent/telemetry.rb
Constant Summary collapse
- TELEMETRY_DIR =
File.("~/.ask/agent/telemetry")
- EVENT_TYPES =
%i[tool_error loop_detected max_turns_exceeded compaction_end reflection_end].freeze
Instance Attribute Summary collapse
-
#enabled ⇒ Object
readonly
Returns the value of attribute enabled.
Instance Method Summary collapse
- #clear! ⇒ Object
- #increment_session_count! ⇒ Object
-
#initialize(enabled: true, dir: nil) ⇒ Telemetry
constructor
A new instance of Telemetry.
- #log(event_type, data) ⇒ Object
- #read(event_type = nil) ⇒ Object
- #read_recommendations(status: nil) ⇒ Object
- #reset_session_count! ⇒ Object
- #session_count ⇒ Object
- #track_recommendation(recommendation) ⇒ Object
- #track_resolution(recommendation_id) ⇒ Object
Constructor Details
#initialize(enabled: true, dir: nil) ⇒ Telemetry
Returns a new instance of Telemetry.
15 16 17 18 19 |
# File 'lib/ask/agent/telemetry.rb', line 15 def initialize(enabled: true, dir: nil) @enabled = enabled @dir = dir || TELEMETRY_DIR @mutex = Mutex.new end |
Instance Attribute Details
#enabled ⇒ Object (readonly)
Returns the value of attribute enabled.
13 14 15 |
# File 'lib/ask/agent/telemetry.rb', line 13 def enabled @enabled end |
Instance Method Details
#clear! ⇒ Object
150 151 152 153 154 |
# File 'lib/ask/agent/telemetry.rb', line 150 def clear! return unless File.directory?(@dir) Dir[File.join(@dir, "**/*.json")].each { |f| File.delete(f) } end |
#increment_session_count! ⇒ Object
118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/ask/agent/telemetry.rb', line 118 def increment_session_count! return unless @enabled FileUtils.mkdir_p(@dir) path = File.join(@dir, "session_counter.json") @mutex.synchronize do count = File.exist?(path) ? JSON.parse(File.read(path))["count"] : 0 File.write(path, JSON.pretty_generate({ count: count + 1, updated_at: Time.now.utc.iso8601(3) }) + "\n") end end |
#log(event_type, data) ⇒ Object
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/ask/agent/telemetry.rb', line 21 def log(event_type, data) return unless @enabled return unless EVENT_TYPES.include?(event_type) entry = { timestamp: Time.now.utc.iso8601(3), event_type: event_type, session_id: data[:session_id], details: data.reject { |k, _| k == :session_id } } dir = File.join(@dir, event_type.to_s) FileUtils.mkdir_p(dir) filename = "#{entry[:timestamp].tr(':', '-')}_#{SecureRandom.hex(4)}.json" @mutex.synchronize do File.write(File.join(dir, filename), JSON.pretty_generate(entry) + "\n") end end |
#read(event_type = nil) ⇒ Object
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/ask/agent/telemetry.rb', line 42 def read(event_type = nil) return {} unless File.directory?(@dir) entries = [] dirs = event_type ? [File.join(@dir, event_type.to_s)] : Dir[File.join(@dir, "*")].select { |d| File.directory?(d) } dirs.each do |dir| Dir[File.join(dir, "*.json")].sort.each do |file| entries << JSON.parse(File.read(file)) rescue JSON::ParserError nil end end entries.group_by { |e| e["event_type"] } end |
#read_recommendations(status: nil) ⇒ Object
104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/ask/agent/telemetry.rb', line 104 def read_recommendations(status: nil) rec_dir = File.join(@dir, "recommendations") return [] unless File.directory?(rec_dir) entries = Dir[File.join(rec_dir, "*.json")].sort.map do |file| JSON.parse(File.read(file)) rescue JSON::ParserError nil end.compact return entries unless status entries.select { |e| e["status"] == status } end |
#reset_session_count! ⇒ Object
141 142 143 144 145 146 147 148 |
# File 'lib/ask/agent/telemetry.rb', line 141 def reset_session_count! return unless @enabled path = File.join(@dir, "session_counter.json") @mutex.synchronize do File.write(path, JSON.pretty_generate({ count: 0, updated_at: Time.now.utc.iso8601(3) }) + "\n") end end |
#session_count ⇒ Object
130 131 132 133 134 135 136 137 138 139 |
# File 'lib/ask/agent/telemetry.rb', line 130 def session_count return 0 unless @enabled path = File.join(@dir, "session_counter.json") return 0 unless File.exist?(path) JSON.parse(File.read(path))["count"] rescue JSON::ParserError 0 end |
#track_recommendation(recommendation) ⇒ Object
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/ask/agent/telemetry.rb', line 59 def track_recommendation(recommendation) return unless @enabled entry = recommendation.to_h.merge( recommendation_id: "rec_#{SecureRandom.hex(8)}", timestamp: Time.now.utc.iso8601(3), status: "open" ) rec_dir = File.join(@dir, "recommendations") FileUtils.mkdir_p(rec_dir) filename = "#{entry[:timestamp].tr(':', '-')}_#{entry[:recommendation_id]}.json" @mutex.synchronize do File.write(File.join(rec_dir, filename), JSON.pretty_generate(entry) + "\n") end entry[:recommendation_id] end |
#track_resolution(recommendation_id) ⇒ Object
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/ask/agent/telemetry.rb', line 80 def track_resolution(recommendation_id) return unless @enabled rec_dir = File.join(@dir, "recommendations") return unless File.directory?(rec_dir) Dir[File.join(rec_dir, "*.json")].each do |file| entry = JSON.parse(File.read(file)) next unless entry["recommendation_id"] == recommendation_id entry["status"] = "resolved" entry["resolved_at"] = Time.now.utc.iso8601(3) @mutex.synchronize do File.write(file, JSON.pretty_generate(entry) + "\n") end return true rescue JSON::ParserError nil end false end |