שינוי פורמט לוג של Rack, והסתרת אזהרות ברובי

יש לי מערכת העובדת עם Sinatra, unicorn ו nginx ביחד.

הבעיה היא, ש nginx נמצא בראש, והוא מעביר את הבקשה ל unicorn, אני מקבל את כתובת ה ip בלוג של ה nginx ולא של הפונה המקורי, ורציתי לשנות את זה, שאראה את הכתובת של הפונה, ולא של nginx.

לשם כך, צריך לשנות את הפורמט ללוג של Rack.
אז עשיתי קצת duck typing לקוד המקורי, כמובן בקובץ חדש שלי:

# ... 
# snips 
# ...

# Overriding the original constant
FORMAT = %{%s - %s [%s] "%s %s%s %s" %d %s %0.4f\n}

# ... 
# snips 
# ...

def log(env, status, header, began_at)
  now = Time.now
  length = extract_content_length(header)

  logger = @logger || env['rack.errors']
  logger.write FORMAT % [
    # adding IP
    env['HTTP_X_REAL_IP'] || env['HTTP_X_FORWARDED_FOR'] || 
    env["REMOTE_ADDR"] || "-",
    env["REMOTE_USER"] || "-",
    now.strftime("%d/%m/%Y %H:%M:%S"),
    env["REQUEST_METHOD"],
    env["PATH_INFO"],
    env["QUERY_STRING"].empty? ? "" : "?"+env["QUERY_STRING"],
    env["HTTP_VERSION"],
    status.to_s[0..3],
    length,
    now - began_at 
  ]
end

# ...
# snips 
# ...

רוב הקוד לא מעניין, כי זה בעצם להשתמש בקוד קיים, אבל log מעניין אותנו, ולכן אני מציג רק אותו.
ברירת המחדל אומרת לספק את REMOTE_ADDR, אבל זו הכתובת של nginx.
אז ב nginx יצרתי הדר שאני מעביר את הפניה המקורית. השם שלו קיבל את השם HTTP_X_REAL_IP. ככה בחרתי.
יצרתי אותו בצורה הבאה:

proxy_set_header        X-Real-IP       $remote_addr;

במידה והוא אינו קיים, אני מנסה לבדוק האם HTTP_X_FORWARDED_FOR קיים, במידה ולא, אז אנסה את מזלי עם REMOTE_IP, ואם זה גם לא, אז אין IP.

במידה ותריצו את זה, תגלו אבל בעיה חדשה – הודעת אזהרה ש FORMAT כבר הוגדר:

warning: already initialized constant Rack::CommonLogger::FORMAT
/home/ik/.gem/ruby/2.0.0/gems/rack-1.5.2/lib/rack/commonlogger.rb:24: warning: previous definition of FORMAT was here

אז מצאתי להודעה הזו פתרון נחמד ופשוט:

module Kernel
  def suppress_warnings
    original_verbosity = $VERBOSE
    $VERBOSE = nil
    result = yield
    $VERBOSE = original_verbosity
    return result
  end
end

והשימוש בו יהיה בצורה הבאה:

module Rack
  class CommonLogger
    Kernel::suppress_warnings do
      # Overriding the original constant
      FORMAT = %{%s - %s [%s] "%s %s%s %s" %d %s %0.4f\n}
    end

    def initialize(app, logger=nil)
...

ועכשיו לא נקבל על כך הודעה, היות ואנחנו מודעים לכך שאנחנו מבצעים את הפעולה, היות והיא נעשת במודע, ואנחנו מעוניינים בה.

הקוד המלא נמצא כאן.

להשאיר תגובה

הזינו את פרטיכם בטופס, או לחצו על אחד מהאייקונים כדי להשתמש בחשבון קיים:

הלוגו של WordPress.com

אתה מגיב באמצעות חשבון WordPress.com שלך. לצאת מהמערכת / לשנות )

תמונת Twitter

אתה מגיב באמצעות חשבון Twitter שלך. לצאת מהמערכת / לשנות )

תמונת Facebook

אתה מגיב באמצעות חשבון Facebook שלך. לצאת מהמערכת / לשנות )

תמונת גוגל פלוס

אתה מגיב באמצעות חשבון Google+ שלך. לצאת מהמערכת / לשנות )

מתחבר ל-%s