2012-10-24 16 views
10

मैं एक समस्या में भाग रहा हूं, मेरी राय में, अधिकांश रेल उपयोगकर्ताओं के लिए एक समस्या होनी चाहिए लेकिन मुझे इसके लिए कोई समाधान नहीं मिला।किसी निश्चित कॉलम के लिए ActiveRecord लॉगिंग को अक्षम कैसे करें?

उदाहरण के लिए, संभावित रूप से बड़ी, बाइनरी फ़ाइल का फ़ाइल अपलोड करने और डेटाबेस में संग्रहीत करने के दौरान, आप निश्चित रूप से रेलवे या ActiveRecord को इस विशिष्ट फ़ील्ड को विकास मोड में लॉग इन नहीं करना चाहते हैं (लॉग फ़ाइल, stdout)। काफी बड़ी फ़ाइल के मामले में, यह क्वेरी निष्पादन को तोड़ने का कारण बनता है और लगभग मेरे टर्मिनल को मारता है।

क्या विशिष्ट फ़ील्ड के लिए लॉगिंग अक्षम करने की कोई विश्वसनीय और गैर-हैकी विधि है? याद रखें, मैं अनुरोध पैरामीटर के लिए लॉगिंग अक्षम करने के बारे में बात कर रहा हूं - यह काफी अच्छी तरह हल हो गया है।

उस पर किसी भी जानकारी के लिए धन्यवाद!

+0

पासवर्ड की तरह फ़िल्टर करने का एक विकल्प है, यह नहीं पता कि इससे मदद मिलेगी या नहीं। क्या आप ActiveRecord को हैक को निष्पादित करने पर विचार करेंगे? यदि नहीं तो आपका संकेत है। –

उत्तर

0

मैं या तो इस पर ज्यादा नहीं मिला है, हालांकि एक बात तुम कर सकते हो

ActiveRecord::Base.logger = nil 

पूरी तरह से प्रवेश करने को अक्षम करना है, हालांकि आप शायद नहीं है कि क्या करना चाहते हैं। ActiveRecord लॉगर को कुछ कस्टम सबक्लास में सेट करने का एक बेहतर समाधान हो सकता है जो किसी निश्चित आकार पर संदेशों को लॉग नहीं करता है, या किसी संदेश के विशिष्ट अनुभागों को पार्स करने के लिए कुछ बेहतर करता है जो बहुत बड़े होते हैं।

यह आदर्श प्रतीत नहीं होता है, लेकिन यह एक व्यावहारिक समाधान की तरह प्रतीत होता है, हालांकि मैंने विशिष्ट कार्यान्वयन विवरण नहीं देखा है। मैं वास्तव में किसी भी बेहतर समाधान सुनने में रुचि रखूंगा।

+0

हां, यह एकमात्र संभावना है जो मेरे दिमाग में आई, लेकिन मुझे यह समाधान काफी बदसूरत लगता है (जैसा कि आपने बताया है) क्योंकि आप निश्चित रूप से कॉल को लॉग इन करना चाहते हैं लेकिन सिर्फ यह फ़ील्ड नहीं। यदि कोई "सही" उत्तर नहीं होगा तो मैं आगे बढ़ सकता हूं और ऐसे कस्टम लॉगर को कार्यान्वित कर सकता हूं जो लॉग स्टेटमेंट को पार्स करता है ... बदसूरत भी। – Remo

+0

ऐसा लगता है कि आप लॉगर पर "एड" विधि को ओवरराइड करना चाहते हैं, उप-वर्गीकृत संस्करण आपके पार्सिंग कर सकता है और फिर सुपरक्लास एड विधि को कॉल कर सकता है, पार्स किए गए संदेश और अन्य पैरामीटर को पास कर सकता है। –

4

नोट: रेल 3 के साथ काम करता है, लेकिन जाहिरा तौर पर नहीं 4 (जो जारी नहीं किया गया है जब इस सवाल का जवाब दिया गया था)

अपने application.rb फ़ाइल में:

config.filter_parameters << :parameter_name 

यह निकाल देंगे कि अपने लॉग में प्रदर्शित होने से विशेषता, इसे [FILTERED] के साथ प्रतिस्थापित करना फ़िल्टरिंग पैरामीटर के लिए सामान्य उपयोग केस निश्चित रूप से पासवर्ड है, लेकिन मुझे कोई कारण नहीं है कि इसे आपके बाइनरी फ़ाइल फ़ील्ड के साथ काम नहीं करना चाहिए।

+1

क्या यह SQL लॉग में पैरामीटर के बजाय HTTP अनुरोध पैरामीटर फ़िल्टर नहीं करता है? – Remo

+0

नहीं, यह रेल लॉग में सबकुछ फ़िल्टर करता है। आने वाले अनुरोधों पर दोनों पैरा हैश और लॉग इन एसक्यूएल कथन दिखाएंगे [फ़िल्टर] – agmin

+0

धन्यवाद! मैं कोशिश करूँगा और वापस आशुलिपि की रिपोर्ट करूंगा। – Remo

5

config/initializers में एक फ़ाइल बनाएँ whitch ActiveRecord::ConnectionAdapters::AbstractAdapter तो जैसे को संशोधित करता है:

class ActiveRecord::ConnectionAdapters::AbstractAdapter 
    protected 

    def log_with_trunkate(sql, name="SQL", binds=[], &block) 
    b = binds.map {|k,v| 
     v = v.truncate(20) if v.is_a? String and v.size > 20 
     [k,v] 
    } 
    log_without_trunkate(sql, name, b, &block) 
    end 

    alias_method_chain :log, :trunkate 
end 

यह सभी क्षेत्रों कि उत्पादन लॉग में लंबे समय तक 20 से वर्ण हैं trunkate होगा।

+0

यह भी ध्यान रखना चाहिए कि यह केवल सम्मिलित अनुरोधों को छोटा कर देगा। अद्यतन की स्थिति में सब कुछ एसक्यूएल परम में फेंक दिया जाता है ताकि उसे छोटा करने की भी आवश्यकता हो। रेल 3.0.9 में 'log_without_trunkate' कॉल में – Patrik

+0

तर्कों की गलत संख्या (2 के लिए 3)। – CHsurfer

+0

3.0.x रेल के लिए लॉग विधि एक लॉग विधि का उपयोग करती है जो केवल दो तर्क 'एसक्यूएल' और 'नाम' लेती है। तो तर्क से ब्लॉक और ब्लॉक को हटा दें और बस एसक्यूएल तर्क से बाहर फ़िल्टर करें। – Patrik

0

मुझे एक ही समस्या का सामना करना पड़ा, लेकिन मुझे समस्या का एक साफ समाधान नहीं पता था। मैंने ब्लॉगर को फ़िल्टर करने वाले रेल लॉगर के लिए a custom formatter लिखना समाप्त कर दिया।

ऊपर दिए गए कोड को कॉन्फ़िगर/प्रारंभकर्ताओं में रखा जाना चाहिए, और file_dat को उस कॉलम के साथ प्रतिस्थापित करें जिसे आप निकालना चाहते हैं और file_name नियमित अभिव्यक्ति में दिखाई देने वाले कॉलम के साथ।

3

यहां @Patrik द्वारा सुझाए गए दृष्टिकोण का कार्यान्वयन है जो PostgreSQL के खिलाफ दोनों प्रविष्टियों और अपडेट के लिए काम करता है। अन्य डेटाबेस के लिए एसक्यूएल के स्वरूपण के आधार पर रेगेक्स को tweaked करने की आवश्यकता हो सकती है।

class ActiveRecord::ConnectionAdapters::AbstractAdapter 
    protected 

    def log_with_binary_truncate(sql, name="SQL", binds=[], &block) 
    binds = binds.map do |col, data| 
     if col.type == :binary && data.is_a?(String) && data.size > 27 
     data = "#{data[0,10]}[REDACTED #{data.size - 20} bytes]#{data[-10,10]}" 
     end 
     [col, data] 
    end 

    sql = sql.gsub(/(?<='\\x[0-9a-f]{20})[0-9a-f]{20,}?(?=[0-9a-f]{20}')/) do |match| 
     "[REDACTED #{match.size} chars]" 
    end 

    log_without_binary_truncate(sql, name, binds, &block) 
    end 

    alias_method_chain :log, :binary_truncate 
end 

मैं इसके साथ भ्रमित रूप से खुश नहीं हूं, लेकिन अब यह काफी अच्छा है।यह बाइनरी स्ट्रिंग के पहले और अंतिम 10 बाइट्स को संरक्षित करता है और इंगित करता है कि बीच में कितने बाइट/वर्ण हटा दिए गए थे। यह तब तक रीडायरेक्ट नहीं होता जब तक कि रेडएक्टेड टेक्स्ट प्रतिस्थापन टेक्स्ट से अधिक लंबा न हो (यानी यदि कम से कम 20 वर्ण निकालने के लिए नहीं हैं, तो "[रेडएक्टेड एक्सएक्स वर्ण]" प्रतिस्थापित टेक्स्ट से अधिक लंबा होगा, इसलिए कोई बिंदु नहीं है) । मैंने यह निर्धारित करने के लिए प्रदर्शन परीक्षण नहीं किया कि क्या रेडक्टेड खंड के लिए लालची या आलसी पुनरावृत्ति का उपयोग तेजी से किया गया था। मेरी वृत्ति आलसी होनी थी, इसलिए मैंने किया, लेकिन यह संभव है कि लालची तेज हो जाए, खासकर यदि एसक्यूएल में केवल एक बाइनरी फ़ील्ड है।

+0

IMHO। यह इस सवाल में सबसे अच्छा समाधान है। – reto

+0

यह mysql के लिए regexp है। क्या आप इसे अपने समाधान में जोड़ना चाहते हैं?/(? <= एक्स '[0-9a-च] {20}) [0-9a-च] {20,}? (?= [0-9 ए-एफ] {20} ')/ – reto

6

यदि यह किसी की सहायता करता है, तो यहां ऊपर स्निपेट का एक रेल 4.1 संगत संस्करण है जिसमें गैर-बाइनरी बाइंड पैरा (उदा। टेक्स्ट या जेसन कॉलम) का रिडक्शन भी शामिल है, और रिडक्शन से पहले लॉगिंग को 100 char तक बढ़ा देता है। यहां हर किसी की मदद के लिए धन्यवाद!

class ActiveRecord::ConnectionAdapters::AbstractAdapter 
    protected 

    def log_with_binary_truncate(sql, name="SQL", binds=[], statement_name = nil, &block) 
    binds = binds.map do |col, data| 
     if data.is_a?(String) && data.size > 100 
     data = "#{data[0,10]} [REDACTED #{data.size - 20} bytes] #{data[-10,10]}" 
     end 
     [col, data] 
    end 

    sql = sql.gsub(/(?<='\\x[0-9a-f]{100})[0-9a-f]{100,}?(?=[0-9a-f]{100}')/) do |match| 
     "[REDACTED #{match.size} chars]" 
    end 

    log_without_binary_truncate(sql, name, binds, statement_name, &block) 
    end 

    alias_method_chain :log, :binary_truncate 
end 
+1

यह निश्चित रूप से रेल 4.2 तक काम करता है लेकिन 5.0+ में काम नहीं करता है। सबसे अच्छा मैं बता सकता हूं, रेल 5 में इसकी आवश्यकता नहीं है क्योंकि रेलों की समान कार्यक्षमता में प्रतीत होता है। – Ritchie

+1

@ रिची कार्यक्षमता में क्या बनाया गया है? – abonec

0

यहां एक रेल 5 संस्करण है। बॉक्स के बाहर रेल 5 बाइनरी डेटा को कम करता है, लेकिन लंबे टेक्स्ट कॉलम नहीं।

module SqlLogFilter 

    FILTERS = Set.new(%w(geo_data value timeline)) 
    def render_bind(attribute) 
    return [attribute.name, '<filtered>'] if FILTERS.include?(attribute.name) 
    super 
    end 

end 
ActiveRecord::LogSubscriber.prepend SqlLogFilter 

फिल्टर के लिए जिम्मेदार बताते हैं geo_data, value और उदाहरण के लिए timeline:

module LogTruncater 
    def render_bind(attribute) 
    num_chars = Integer(ENV['ACTIVERECORD_SQL_LOG_MAX_VALUE']) rescue 120 
    half_num_chars = num_chars/2 
    value = if attribute.type.binary? && attribute.value 
     if attribute.value.is_a?(Hash) 
     "<#{attribute.value_for_database.to_s.bytesize} bytes of binary data>" 
     else 
     "<#{attribute.value.bytesize} bytes of binary data>" 
     end 
    else 
     attribute.value_for_database 
    end 

    if value.is_a?(String) && value.size > num_chars 
     value = "#{value[0,half_num_chars]} [REDACTED #{value.size - num_chars} chars] #{value[-half_num_chars,half_num_chars]}" 
    end 

    [attribute.name, value] 
    end 

end 

class ActiveRecord::LogSubscriber 
    prepend LogTruncater 
end 
0

रेल में आप प्रारंभकर्ता में रख सकता है 5।

संबंधित मुद्दे