module HAProxyLogParser

Constants

VERSION

Public Class Methods

decode_captured_headers(string) click to toggle source

Converts a captured headers string to an Array.

@param string [String] a captured headers section @return [Array<String>] array of captured header values

# File lib/haproxy_log_parser.rb, line 80
def decode_captured_headers(string)
  string.split('|', -1).map! { |header| unescape(header) }
end
parse(line) click to toggle source

Returns an Entry or ErrorEntry object resulting from the given HAProxy HTTP-format log line.

@param line [String] a line from an HAProxy log @return [Entry, ErrorEntry] @raise [ParseError] if the line was not parsed successfully

# File lib/haproxy_log_parser.rb, line 20
def parse(line)
  parser = LineParser.new
  result = parser.parse(line)

  unless result
    raise ParseError, parser.failure_reason
  end

  entry =
    if result.suffix.respond_to?(:http_request)
      create_normal_entry(result.suffix)
    else
      create_error_entry(result.suffix)
    end
  entry.client_ip = result.client_ip.text_value
  entry.client_port = result.client_port.text_value.to_i
  entry.accept_date = parse_accept_date(result.accept_date.text_value)

  entry
end
parse_accept_date(string) click to toggle source

Converts the value of an accept_date field to a Time object.

@param string [String] value of an accept_date field @return [Time]

# File lib/haproxy_log_parser.rb, line 56
def parse_accept_date(string)
  parts = string.split(/[\/:.]/)
  Time.local(*parts.values_at(2, 1, 0, 3..6))
end
unescape(string) click to toggle source

Returns the given string un-escaped. See the “Logging > Non-printable characters” section in HAProxy documentation.

@param string [String] string to unescape @return [String] an unescaped string

# File lib/haproxy_log_parser.rb, line 46
def unescape(string)
  string.gsub(/#[[:xdigit:]]{2}/) do |match|
    match[1..-1].to_i(16).chr
  end
end

Private Class Methods

create_error_entry(result) click to toggle source

@param result [Treetop::Runtime::SyntaxNode] @return [ErrorEntry]

# File lib/haproxy_log_parser.rb, line 127
def create_error_entry(result)
  entry = ErrorEntry.new

  %i(frontend_name bind_name message).each do |field|
    entry.send("#{field}=", result.send(field).text_value)
  end

  entry
end
create_normal_entry(result) click to toggle source

@param result [Treetop::Runtime::SyntaxNode] @return [Entry]

# File lib/haproxy_log_parser.rb, line 88
def create_normal_entry(result)
  entry = Entry.new

  %i(
    frontend_name transport_mode
    backend_name server_name termination_state
  ).each do |field|
    entry.send("#{field}=", result.send(field).text_value)
  end

  %i(
    tq tw tc tr tt status_code bytes_read
    actconn feconn beconn srv_conn retries srv_queue backend_queue
  ).each do |field|
    entry.send("#{field}=", result.send(field).text_value.to_i)
  end

  %i(captured_request_cookie captured_response_cookie).each do |field|
    cookie = decode_captured_cookie(result.send(field).text_value)
    entry.send("#{field}=", cookie)
  end

  %i(captured_request_headers captured_response_headers).each do |field|
    if result.send(field).respond_to?(:headers)
      headers = decode_captured_headers(
        result.send(field).headers.text_value
      )
    else
      headers = []
    end
    entry.send("#{field}=", headers)
  end

  entry.http_request = unescape(result.http_request.text_value)
  entry
end