Class: OneApm::Collector::Commands::XraySessionCollection

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/one_apm/collector/commands/xray_session_collection.rb

Constant Summary collapse

NO_PROFILES =
[].freeze

Instance Method Summary collapse

Constructor Details

#initialize(backtrace_service, event_listener) ⇒ XraySessionCollection

Returns a new instance of XraySessionCollection.



13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/one_apm/collector/commands/xray_session_collection.rb', line 13

def initialize(backtrace_service, event_listener)
  @backtrace_service = backtrace_service

  # This lock protects access to the sessions hash, but it's expected
  # that individual session objects within the hash will be manipulated
  # outside the lock.  This is safe because manipulation of the session
  # objects is expected from only a single thread (the harvest thread)
  @sessions_lock = Mutex.new
  @sessions = {}

  if event_listener
    event_listener.subscribe(:before_harvest, &method(:cleanup_finished_sessions))
  end
end

Instance Method Details

#activate_sessions(incoming_ids) ⇒ Object

Session activation



90
91
92
93
94
# File 'lib/one_apm/collector/commands/xray_session_collection.rb', line 90

def activate_sessions(incoming_ids)
  (ids_to_activate(incoming_ids)).each do |raw|
    add_session(XraySession.new(raw))
  end
end

#active_thread_profiling_sessionsObject



82
83
84
85
86
# File 'lib/one_apm/collector/commands/xray_session_collection.rb', line 82

def active_thread_profiling_sessions
  @sessions_lock.synchronize do
    @sessions.values.select { |s| s.active? && s.run_profiler? }
  end
end

#add_session(session) ⇒ Object



109
110
111
112
113
114
115
116
117
118
119
# File 'lib/one_apm/collector/commands/xray_session_collection.rb', line 109

def add_session(session)
  OneApm::Manager.logger.debug("Adding X-Ray session #{session.inspect}")
  OneApm::Manager.increment_metric("Supportability/XraySessions/Starts")

  @sessions_lock.synchronize { @sessions[session.id] = session }

  session.activate
  if session.run_profiler?
    @backtrace_service.subscribe(session.key_transaction_name, session.command_arguments)
  end
end

#cleanup_finished_sessionsObject



65
66
67
68
69
70
# File 'lib/one_apm/collector/commands/xray_session_collection.rb', line 65

def cleanup_finished_sessions
  finished_session_ids.each do |id|
    OneApm::Manager.logger.debug("Finished X-Ray session #{id} by duration. Removing it from active sessions.")
    remove_session_by_id(id)
  end
end

#deactivate_for_incoming_sessions(incoming_ids) ⇒ Object

Session deactivation



123
124
125
126
127
# File 'lib/one_apm/collector/commands/xray_session_collection.rb', line 123

def deactivate_for_incoming_sessions(incoming_ids)
  ids_to_remove(incoming_ids).each do |session_id|
    remove_session_by_id(session_id)
  end
end

#finished_session_idsObject



147
148
149
150
151
# File 'lib/one_apm/collector/commands/xray_session_collection.rb', line 147

def finished_session_ids
  @sessions_lock.synchronize do
    @sessions.map{|k, s| k if s.finished?}.compact
  end
end

#handle_active_xray_sessions(agent_command) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/one_apm/collector/commands/xray_session_collection.rb', line 28

def handle_active_xray_sessions(agent_command)
  # If X-Rays are disabled, just be quiet about it and don't start the
  # command. Other hosts might be running the X-Ray, so we don't need
  # to bark on every get_agent_commands.
  if !OneApm::Manager.config[:'xray_session.enabled']
    OneApm::Manager.logger.debug("Not responding to X-Ray command because of config 'xray_session.enabled' = #{OneApm::Manager.config[:'xray_session.enabled']}")
    return
  end

  incoming_ids = agent_command.arguments["xray_ids"]
  deactivate_for_incoming_sessions(incoming_ids)
  activate_sessions(incoming_ids)
end

#harvest_thread_profilesObject



50
51
52
53
54
55
56
57
58
59
# File 'lib/one_apm/collector/commands/xray_session_collection.rb', line 50

def harvest_thread_profiles
  return NO_PROFILES unless OneApm::Agent::Threading::BacktraceService.is_supported?

  profiles = active_thread_profiling_sessions.map do |session|
    OneApm::Manager.logger.debug("Harvesting profile for X-Ray session #{session.inspect}")
    @backtrace_service.harvest(session.key_transaction_name)
  end
  profiles.reject! {|p| p.empty?}
  profiles.compact
end

#ids_to_activate(incoming_ids) ⇒ Object



96
97
98
# File 'lib/one_apm/collector/commands/xray_session_collection.rb', line 96

def ids_to_activate(incoming_ids)
  @sessions_lock.synchronize { incoming_ids - @sessions.keys }
end

#ids_to_remove(incoming_ids) ⇒ Object



129
130
131
# File 'lib/one_apm/collector/commands/xray_session_collection.rb', line 129

def ids_to_remove(incoming_ids)
  @sessions_lock.synchronize { @sessions.keys - incoming_ids }
end

#lookup_metadata_for(ids_to_activate) ⇒ Object

Please don’t hold the @sessions_lock across me! Calling the service is time-consuming, and will block request threads. Which is rude.



102
103
104
105
106
107
# File 'lib/one_apm/collector/commands/xray_session_collection.rb', line 102

def (ids_to_activate)
  return [] if ids_to_activate.empty?

  OneApm::Manager.logger.debug("Retrieving metadata for X-Ray sessions #{ids_to_activate.inspect}")
  one_apm_service.(ids_to_activate)
end

#one_apm_serviceObject

Internals



75
76
77
# File 'lib/one_apm/collector/commands/xray_session_collection.rb', line 75

def one_apm_service
  OneApm::Manager.agent.service
end

#remove_session_by_id(id) ⇒ Object



133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/one_apm/collector/commands/xray_session_collection.rb', line 133

def remove_session_by_id(id)
  session = @sessions_lock.synchronize { @sessions.delete(id) }

  if session
    OneApm::Manager.logger.debug("Removing X-Ray session #{session.inspect}")
    OneApm::Manager.increment_metric("Supportability/XraySessions/Stops")

    if session.run_profiler?
      @backtrace_service.unsubscribe(session.key_transaction_name)
    end
    session.deactivate
  end
end

#session_id_for_transaction_name(name) ⇒ Object



42
43
44
45
46
# File 'lib/one_apm/collector/commands/xray_session_collection.rb', line 42

def session_id_for_transaction_name(name)
  @sessions_lock.synchronize do
    @sessions.keys.find { |id| @sessions[id].key_transaction_name == name }
  end
end

#stop_all_sessionsObject



61
62
63
# File 'lib/one_apm/collector/commands/xray_session_collection.rb', line 61

def stop_all_sessions
  deactivate_for_incoming_sessions([])
end