lib/request_log_analyzer/request.rb in wvanbergen-request-log-analyzer-1.3.5 vs lib/request_log_analyzer/request.rb in wvanbergen-request-log-analyzer-1.3.6

- old
+ new

@@ -7,110 +7,122 @@ # This class provides several methods to access the data that was parsed from the log files. # Request#first(field_name) returns the first (only) value corresponding to the given field # Request#every(field_name) returns all values corresponding to the given field name as array. class Request + def self.inherited(klass) + # klass.send(:include, Converters) + end + module Converters - + + # Default converter function, which converts the parsed strings to a native Ruby type + # using the type indication in the line definition. It will use a custom connverter + # method if one is available. def convert_value(value, capture_definition) - custom_converter_method = "convert_#{capture_definition[:type]}".to_sym - if respond_to?(custom_converter_method) - send(custom_converter_method, value, capture_definition) - elsif !value.nil? - case capture_definition[:type] - when :decimal; value.to_f - when :float; value.to_f - when :double; value.to_f - when :integer; value.to_i - when :int; value.to_i - when :symbol; value.to_sym - else; value.to_s - end - else - nil - end + return capture_definition[:default] if value.nil? + custom_converter_method = :"convert_#{capture_definition[:type]}" + send(custom_converter_method, value, capture_definition) end + def convert_string(value, capture_definition); value; end + def convert_decimal(value, capture_definition); value.to_f; end + def convert_float(value, capture_definition); value.to_f; end + def convert_decimal(value, capture_definition); value.to_f; end + def convert_int(value, capture_definition); value.to_i; end + def convert_integer(value, capture_definition); value.to_i; end + def convert_sym(value, capture_definition); value.to_sym; end + def convert_symbol(value, capture_definition); value.to_sym; end + + # Converts :eval field, which should evaluate to a hash. def convert_eval(value, capture_definition) eval(value).inject({}) { |h, (k, v)| h[k.to_sym] = v; h} rescue SyntaxError nil end - # Slow default method to parse timestamps + # Slow default method to parse timestamps. + # Reimplement this function in a file format specific Request class + # to improve the timestamp parsing speed. def convert_timestamp(value, capture_definition) - DateTime.parse(value).strftime('%Y%m%d%H%M%S').to_i unless value.nil? + DateTime.parse(value).strftime('%Y%m%d%H%M%S').to_i end + # Converts traffic fields to (whole) bytes based on the given unit. def convert_traffic(value, capture_definition) - return nil if value.nil? case capture_definition[:unit] + when nil, :b, :B, :byte then value.to_i when :GB, :G, :gigabyte then (value.to_f * 1000_000_000).round when :GiB, :gibibyte then (value.to_f * (2 ** 30)).round when :MB, :M, :megabyte then (value.to_f * 1000_000).round when :MiB, :mebibyte then (value.to_f * (2 ** 20)).round when :KB, :K, :kilobyte, :kB then (value.to_f * 1000).round when :KiB, :kibibyte then (value.to_f * (2 ** 10)).round - else value.to_i + else raise "Unknown traffic unit" end end + # Convert duration fields to float, and make sure the values are in seconds. def convert_duration(value, capture_definition) - return nil if value.nil? case capture_definition[:unit] + when nil, :sec, :s then value.to_f when :microsec, :musec then value.to_f / 1000000.0 when :msec, :millisec then value.to_f / 1000.0 - else value.to_f + else raise "Unknown duration unit" end end end - - include RequestLogAnalyzer::FileFormat::Awareness + + # Install the default converter methods include Converters - - attr_reader :lines - attr_reader :attributes + + attr_reader :lines, :attributes, :file_format # Initializes a new Request object. # It will apply the the provided FileFormat module to this instance. def initialize(file_format, attributes = {}) - @lines = [] - @attributes = attributes - register_file_format(file_format) + @lines = [] + @attributes = attributes + @file_format = file_format end # Creates a new request that was parsed from the log with the given FileFormat. The hashes # that are passed to this function are added as lines to this request. def self.create(file_format, *hashes) request = self.new(file_format) hashes.flatten.each { |hash| request << hash } return request end - # Adds another line to the request. - # The line should be provides as a hash of the fields parsed from the line. + # Adds another line to the request when it is parsed in the LogParser. + # + # The line should be provided as a hash with the attributes line_definition, :captures, + # :lineno and :source set. This function is called from LogParser. def add_parsed_line (parsed_line) value_hash = parsed_line[:line_definition].convert_captured_values(parsed_line[:captures], self) value_hash[:line_type] = parsed_line[:line_definition].name value_hash[:lineno] = parsed_line[:lineno] value_hash[:source] = parsed_line[:source] add_line_hash(value_hash) end + # Adds another line to the request using a plain hash. + # + # The line should be provides as a hash of the fields parsed from the line. def add_line_hash(value_hash) @lines << value_hash @attributes = value_hash.merge(@attributes) end - + # Adds another line to the request. This method switches automatically between + # the add_line_hash and add_parsed_line based on the keys of the provided hash. def <<(hash) hash[:line_definition] ? add_parsed_line(hash) : add_line_hash(hash) end # Checks whether the given line type was parsed from the log file for this request def has_line_type?(line_type) return true if @lines.length == 1 && @lines[0][:line_type] == line_type.to_sym - @lines.detect { |l| l[:line_type] == line_type.to_sym } end alias :=~ :has_line_type? \ No newline at end of file