Class: UniversalAccessLogParser

Inherits:
Object
  • Object
show all
Defined in:
lib/universal-access-log-parser.rb

Defined Under Namespace

Classes: ElementGroup, ElementParsingError, EntryIterator, ParsedLogLine, ParserError, ParsingError

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(&block) ⇒ UniversalAccessLogParser

Returns a new instance of UniversalAccessLogParser.



299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
# File 'lib/universal-access-log-parser.rb', line 299

def initialize(&block)
	@@parser_id ||= 0
	@@parser_id += 1

	@elements = ElementGroup::Root.new(' ', &block)

	@skip_lines = @elements.skip_lines.map{|s| Regexp.new(s)}
	@regexp = Regexp.new('^' + @elements.regexp + '$')

	@names = @elements.names

	@parsers = {}
	@names.zip(@elements.parsers).each do |name, parser|
		@parsers[name] = parser
	end

	@parsed_log_entry_class = Class.new(ParsedLogLine) do
		def self.name
			superclass.name
		end

		def self.make_metods(names)
			names.each do |name|
				class_eval """
					def #{name}
						return @cache[:#{name}] if @cache.member? :#{name}
						begin
							value = @parsers[:#{name}].call(@strings[:#{name}])
						rescue => e
							raise ElementParsingError.new(e)
						end
						@cache[:#{name}] = value
						value
					end
				"""
			end
		end

		def initialize(names, parsers, strings)
			@parsers = parsers

			@strings = {}
			names.zip(strings).each do |name, string|
				@strings[name] = string
			end

			@cache = {}
		end

		def parse!
			@strings.keys.each do |name|
				send(name)
			end
			self
		end

		def to_hash
			parse!
			@cache
		end

		def inspect
			hash = @cache.dup
			@strings.keys.each do |name|
				hash[name] = '<unparsed>' unless hash.member? name
			end
			"#<#{self.class.name}: #{hash.keys.map{|s| s.to_s}.sort.map{|name| "#{name}: #{hash[name.to_sym].inspect}"}.join(', ')}>"
		end

		def to_s
			"#<#{self.class.name}:#{object_id}>"
		end
	end

	@parsed_log_entry_class.make_metods(@names)
end

Class Method Details

.parser(name, &block) ⇒ Object

custom parser definition



377
378
379
380
381
382
383
384
385
# File 'lib/universal-access-log-parser.rb', line 377

def self.parser(name, &block)
	ElementGroup.parser(name, &block)

	eval """
		def self.#{name}
				self.new{ #{name} }
		end
	"""
end

Instance Method Details

#inspectObject



416
417
418
# File 'lib/universal-access-log-parser.rb', line 416

def inspect
	"#<#{self.class.name}:#{@regexp.inspect} => #{@elements.names.join(' ')}>"
end

#parse(line) ⇒ Object

Raises:



394
395
396
397
398
399
400
401
402
403
404
# File 'lib/universal-access-log-parser.rb', line 394

def parse(line)
	begin
		matched, *strings = @regexp.match(line).to_a
	rescue ArgumentError => e
		raise ParsingError.new("parser regexp error: #{e}", self, line)
	end

	raise ParsingError.new('parser regexp did not match log line', self, line) if strings.empty?

	@parsed_log_entry_class.new(@names, @parsers, strings)
end

#parse_file(file_path) ⇒ Object



410
411
412
413
414
# File 'lib/universal-access-log-parser.rb', line 410

def parse_file(file_path)
	io = File.open(file_path)
	# io will be closed after each
	parse_io(io, true)
end

#parse_io(io, close_io = false) ⇒ Object



406
407
408
# File 'lib/universal-access-log-parser.rb', line 406

def parse_io(io, close_io = false)
	EntryIterator.new(self, io, close_io)
end

#skip?(line) ⇒ Boolean

Returns:

  • (Boolean)


387
388
389
390
391
392
# File 'lib/universal-access-log-parser.rb', line 387

def skip?(line)
	@skip_lines.each do |regexp|
		return true if line =~ regexp
	end
	return false
end