class RequestLogAnalyzer::FileFormat::Oink < RequestLogAnalyzer::FileFormat::Rails # capture the PID HODEL3000_PROCESSING = /\[(\d+)\]: Processing ((?:\w+::)*\w+)#(\w+)(?: to (\w+))? \(for (#{ip_address}) at (#{timestamp('%Y-%m-%d %H:%M:%S')})\) \[([A-Z]+)\]/ # TODO: fix me! line_definition :processing do |line| line.header = true line.regexp = Regexp.union(LINE_DEFINITIONS[:processing].regexp, HODEL3000_PROCESSING) line.captures = [{ name: :controller, type: :string }, # Default Rails Processing { name: :action, type: :string }, { name: :format, type: :string, default: 'html' }, { name: :ip, type: :string }, { name: :timestamp, type: :timestamp }, { name: :method, type: :string }, { name: :pid, type: :integer }, # Hodel 3000 Processing w/PID { name: :controller, type: :string }, { name: :action, type: :string }, { name: :format, type: :string, default: 'html' }, { name: :ip, type: :string }, { name: :timestamp, type: :timestamp }, { name: :method, type: :string }] end line_definition :memory_usage do |line| line.regexp = /\[(\d+)\]: Memory usage: (\d+)/ line.capture(:pid).as(:integer) line.capture(:memory).as(:traffic) end line_definition :instance_type_counter do |line| line.regexp = /\[(\d+)\]: Instantiation Breakdown: (.*)$/ line.capture(:pid).as(:integer) line.capture(:instance_counts).as(:pipe_separated_counts) end report(:append) do |analyze| analyze.traffic :memory_diff, category: REQUEST_CATEGORIZER, title: 'Largest Memory Increases', line_type: :memory_usage end # Keep a record of PIDs and their memory usage when validating requests. def pids @pids ||= {} end class Request < RequestLogAnalyzer::FileFormat::Rails::Request # Overrides the #validate method to handle PID updating. def validate update_pids super end # Accessor for memory information associated with the specified request PID. If no memory exists # for this request's :pid, the memory tracking is initialized. def pid_memory file_format.pids[self[:pid]] ||= { last_memory_reading: -1, current_memory_reading: -1 } end # Calculates :memory_diff for each request based on the last completed request that was not a failure. def update_pids # memory isn't recorded with exceptions. need to set #last_memory_reading+ to -1 as # the memory used could have changed. for the next request the memory change will not be recorded. # # NOTE - the failure regex was not matching with a Rails Development log file. if has_line_type?(:failure) && processing = has_line_type?(:processing) pid_memory[:last_memory_reading] = -1 elsif mem_line = has_line_type?(:memory_usage) memory_reading = mem_line[:memory] pid_memory[:current_memory_reading] = memory_reading # calcuate the change in memory unless pid_memory[:current_memory_reading] == -1 || pid_memory[:last_memory_reading] == -1 # logged as kB, need to convert to bytes for the :traffic Tracker memory_diff = (pid_memory[:current_memory_reading] - pid_memory[:last_memory_reading]) * 1024 if memory_diff > 0 attributes[:memory_diff] = memory_diff end # if memory_diff > 0 end # unless pid_memory[:last_memory_reading] = pid_memory[:current_memory_reading] pid_memory[:current_memory_reading] = -1 end # if mem_line true end def convert_pipe_separated_counts(value, _capture_definition) count_strings = value.split(' | ') count_arrays = count_strings.map do |count_string| if count_string =~ /^(\w+): (\d+)/ [Regexp.last_match[1], Regexp.last_match[2].to_i] end end Hash[count_arrays] end end # class Request end