Created
July 8, 2011 13:10
-
-
Save danslimmon/1071789 to your computer and use it in GitHub Desktop.
Factory/Dictionary solution to log grammar
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class LogFormatElement | |
@_caster = nil | |
attr_accessor :abbrev, :name, :regex | |
# Class variables that determine the _default_ for abbrev, name, and regex in an instance. | |
# That is, an instance will initialize with these values for the instance variables @abbrev, | |
# @name, and @regex. | |
class << self; attr_accessor :abbrev, :name, :regex end | |
# Additionally we need to access this from within the instance: | |
class << self; attr_accessor :_caster end | |
def initialize | |
@abbrev = self.class.abbrev | |
@name = self.class.name | |
@regex = self.class.regex | |
end | |
# Casts a string found in the log to the correct type, using the class's @@_caster attribute. | |
def cast(string_value) | |
... | |
end | |
# Derives any other element values that we can, given the parsed value for the deriving element. | |
def derived_values(our_own_value) | |
{} | |
end | |
end | |
class RemoteHostElement < LogFormatElement | |
@abbrev = "%h" | |
@name = "remote_host" | |
@regex = %q![A-Za-z0-9.-]+! | |
end | |
class LogNameElement < LogFormatElement | |
@abbrev = "%l" | |
@name = "log_name" | |
@regex = %q!\S+! | |
end | |
class RemoteUserElement < LogFormatElement | |
@abbrev = "%u" | |
@name = "remote_user" | |
@regex = %q![^:]+! | |
end | |
# Finds log format elements given information about them. | |
class ElementDictionary | |
@@_ELEMENTS = [ | |
RemoteHostElement, | |
LogNameElement, | |
RemoteUserElement, | |
] | |
# Returns the LogFormatElement subclass with the given format-string abbreviation. | |
# | |
# If none exists, returns nil. | |
def self.find_by_abbrev(abbrev) | |
@@_ELEMENTS.each do |element| | |
if element.abbrev == abbrev | |
return element | |
end | |
end | |
nil | |
end | |
end | |
# Generates LogFormatElement instances. | |
# | |
# This class does the work of figuring out which LogFormatElement subclass to make and makes it. | |
class LogFormatElementFactory | |
# Takes an Apache log format abbreviation and returns a corresponding LogFormatElement | |
def from_abbrev(abbrev) | |
element_cls = ElementDictionary.find_by_abbrev(abbrev) | |
if element_cls | |
# We found it in the dictionary, so just return an instance | |
return element_cls.new | |
elsif abbrev =~ /^%\{([A-Za-z0-9-]+)\}i/ | |
# HTTP request header | |
return _reqheader_element(abbrev, $1) | |
elsif abbrev =~ /^%\{(.*?):([^}]+)\}r/ | |
# Arbitrary regex | |
return _regex_element(abbrev, $1, $2) | |
end | |
raise "Unknown element format '#{abbrev}'" | |
end | |
# Returns a format element based on an HTTP header | |
def _reqheader_element(abbrev, header_name) | |
... | |
end | |
# Returns a format element based on an arbitrary regex | |
def _regex_element(abbrev, regex_name, regex) | |
... | |
end | |
# Lowercases header name and turns hyphens into underscores | |
def _header_name_to_element_name(header_name) | |
... | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment