Class: NginxTail::LogLine

Inherits:
Object
  • Object
show all
Includes:
KnownIpAddresses, LocalIpAddresses
Defined in:
lib/ntail/log_line.rb

Constant Summary collapse

COMPONENTS =

formatting token:

[ # formatting token:

  # NGINX

  :remote_addr,     # %a
  :remote_user,     # %u
  :time_local,      # %t
  :request,         # %r
  :status,          # %s
  :body_bytes_sent, # %b
  :http_referer,    # %R
  :http_user_agent, # %U
  :proxy_addresses, # %p

  # UPSTREAM = NGINX + ...

  :upstream_response_time, #       %<T (seconds, with millisecond resolution)
  :request_time,           # %T or %>T (seconds, with millisecond resolution) / but also see: %D (microseconds)

  # APACHE

  :server_name,     # %V
  # :remote_addr,     # %h
  :remote_log_name, # %l
  # :remote_user,     # %u
  # :time_local,      # %t
  # :request,         # %r
  # :status,          # %s
  # :body_bytes_sent, # %b
  # :http_referer,    # %%{Referer}i
  # :http_user_agent, # %%{User-agent}i
  :http_cookie,     # %{Cookie}i
  :time_taken,      # %D

]
SUBCOMPONENTS =
[
  :http_method,
  :uri,
  :http_version,
]
APACHE_LOG_PATTERN =

httpd.apache.org/docs/2.0/mod/mod_log_config.html - we currently only support the following custom log format…

“%V %h %l %u %t "%r" %s %b "%Refereri" "%User-agenti" "%Cookiei" %I %O %D %deflate_ration%%”

Regexp.compile(/\A([\S]*) ([\S]+) ([\S]+|-) ([\S]+|-) \[([^\]]+)\] "(.*)" ([\d]+) ([\d]+|-) "(.*?)" "(.*?)" "(.*?)" [\d]+ [\d]+ ([\d]+) .*\Z/)
UPSTREAM_LOG_PATTERN =

wiki.nginx.org/NginxHttpLogModule#log_format - we currently only support the default “combined” log format…

Regexp.compile(/\A(\S+) - (\S+) \[([^\]]+)\] "([^"]+)" (\S+) (\S+) "([^"]*?)" "([^"]*?)"( "([^"]*?)")? - ([\d]+\.[\d]+|-) ([\d]+\.[\d]+|-)\Z/)
NGINX_LOG_PATTERN =

wiki.nginx.org/NginxHttpLogModule#log_format - we currently only support the default “combined” log format…

Regexp.compile(/\A(\S+) - (\S+) \[([^\]]+)\] "([^"]+)" (\S+) (\S+) "([^"]*?)" "([^"]*?)"( "([^"]*?)")?\Z/)
NGINX_REQUEST_PATTERN =
Regexp.compile(/\A(\S+) (.*?) (\S+)\Z/)
NGINX_PROXY_PATTERN =
Regexp.compile(/\A "([^"]*)"\Z/)
@@log_pattern =

the actual pattern used for line matching, either nginx (default) or apache

NGINX_LOG_PATTERN
@@output_format =
:ansi
@@parser =
FormattingParser.new
@@result =
@@format = nil

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from LocalIpAddresses

included, #local_ip_address?

Methods included from KnownIpAddresses

included, #known_ip_address?

Constructor Details

#initialize(line, filename = nil, line_number = nil) ⇒ LogLine

Returns a new instance of LogLine.



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/ntail/log_line.rb', line 108

def initialize(line, filename = nil, line_number = nil)
  @filename = filename ; @line_number = line_number
  @parsable = if @@log_pattern.match(@raw_line = line)
    if @@log_pattern == NGINX_LOG_PATTERN
      @remote_addr, @remote_user, @time_local, @request, @status, @body_bytes_sent, @http_referer, @http_user_agent, @proxy_addresses = $~.captures
    elsif @@log_pattern == UPSTREAM_LOG_PATTERN
      @remote_addr, @remote_user, @time_local, @request, @status, @body_bytes_sent, @http_referer, @http_user_agent, @proxy_addresses, _, @upstream_response_time, @request_time = $~.captures
    elsif @@log_pattern == APACHE_LOG_PATTERN
      @server_name, @remote_addr, @remote_log_name, @remote_user, @time_local, @request, @status, @body_bytes_sent, @http_referer, @http_user_agent, @http_cookie, @time_taken = $~.captures
      @proxy_addresses = nil
    end
    if NGINX_REQUEST_PATTERN.match(@request)
      # counter example (ie. HTTP request that cannot by parsed)
      # 91.203.96.51 - - [21/Dec/2010:05:26:53 +0000] "-" 400 0 "-" "-"
      @http_method, @uri, @http_version = $~.captures
    end
    if @proxy_addresses and NGINX_PROXY_PATTERN.match(@proxy_addresses)
      @proxy_addresses = $~.captures.first.split(/, /)
    end
    true
  else
    false
  end
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *params) ⇒ Object

for now, until we make it fancier…



136
137
138
# File 'lib/ntail/log_line.rb', line 136

def method_missing(method, *params)
  raw_line.send method, *params
end

Instance Attribute Details

#filenameObject (readonly)

Returns the value of attribute filename.



11
12
13
# File 'lib/ntail/log_line.rb', line 11

def filename
  @filename
end

#line_numberObject (readonly)

Returns the value of attribute line_number.



12
13
14
# File 'lib/ntail/log_line.rb', line 12

def line_number
  @line_number
end

#parsableObject (readonly)

Returns the value of attribute parsable.



10
11
12
# File 'lib/ntail/log_line.rb', line 10

def parsable
  @parsable
end

#raw_lineObject (readonly)

Returns the value of attribute raw_line.



9
10
11
# File 'lib/ntail/log_line.rb', line 9

def raw_line
  @raw_line
end

Class Method Details

.format=(format) ⇒ Object



150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/ntail/log_line.rb', line 150

def self.format= format
  unless @@result = @@parser.parse(@@format = format)
    raise @@parser.terminal_failures.join("\n")
  else
    def @@result.value(log_line, color)
      if @@output_format == :ansi
        elements.map { |element| element.value(log_line, color) }.join
      elsif @@output_format == :html
        line = elements.map { |element| element.value(log_line, nil) }.join
        "<span style=\"font-family: monospace; color: #{color}\">%s</span></br>" % line
      end
    end
  end
end

.set_output(output) ⇒ Object



142
143
144
# File 'lib/ntail/log_line.rb', line 142

def self.set_output(output)
  @@output_format = output
end

.set_pattern(pattern) ⇒ Object



97
98
99
100
101
102
103
# File 'lib/ntail/log_line.rb', line 97

def self.set_pattern(pattern)
  @@log_pattern = case pattern
    when :nginx then NGINX_LOG_PATTERN
    when :upstream then UPSTREAM_LOG_PATTERN
    when :apache then APACHE_LOG_PATTERN
  end
end

Instance Method Details

#to_s(options = {}) ⇒ Object



167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/ntail/log_line.rb', line 167

def to_s(options = {})

  # simple but boring:
  # raw_line.to_s

  # a bit less boring:
  color = options[:color] && if redirect_status?
    @@output_format == :ansi ? :yellow : :orange
  elsif !success_status?
    :red
  else
    :default
  end
  @@result.value(self, color)

end