2010-01-06 10 views
6

Wir haben Code, um Daten in unserer Webanwendung Ruby 1.8.6 zu protokollieren. Sie nennen es etwa wie folgt:Modul des Aufrufers in Ruby erhalten

$log.info("Some text here") 

Jetzt, in der angemeldeten Ausgang, ich möchte das Modul schließen, wo diese Linie erschien. Ich weiß, dass die Kernel#caller mir ein Array geben wird, wo ich die Datei und Zeilennummer, die die Protokollzeile aufgetreten ist, ziehen kann, aber das will ich nicht. Ich möchte das Modul, nicht den Dateinamen. Die naheliegende Lösung besteht darin, die Protokollzeile so zu ändern, dass sie wie folgt lautet:

und dann das Ergebnis analysieren. Das wird jedoch nicht funktionieren, weil ich versuche, diese Informationen im Standardfall zu extrahieren. Das heißt, ich brauche die Lösung, um zu funktionieren, wenn der Programmierer vergessen hat, das Modul, den zweiten Parameter für die Protokollzeile anzugeben.

Gibt es eine Möglichkeit, dies zu tun? Wenn nicht, muss ich nur mit dem Array caller auskommen; Die meisten unserer Module befinden sich in separaten Verzeichnissen. Dies wäre eine 80% ige Lösung.

vollständigeres Beispiel, entschuldigen Sie bitte kleinere Syntaxfehler:

in Datei log.rb:

module Log 
    class Logger 
    def info(msg, mod = '') 
     puts "Module: #{mod} Msg: #{msg}" 
    end 
    end # class Logger 
end # module Log 
$log = Log::Logger.new 

in Datei foo.rb:

module Foo 
    class Bar 
    def do_something 
     # Do not pass in self.class.name. 
     # We want the output to look like: 
     # Module: Foo Msg: I did something! 
     $log.info "I did something!" 
    end 
    end # class Bar 
end #module Foo 
+0

Ich sehe nicht, wie Sie es tun können, es sei denn, um "Selbst" oder "Bindung" an das Logger-Objekt zu übergeben. Sie müssten die Datei mit den Informationen von 'caller' analysieren, was Sie sicher nicht tun möchten. –

Antwort

3

Verwendung call_stack.

Zuerst es mit RubyGems installieren:

gem install call_stack 

Dann log.rb ändern:

require 'rubygems' 
require 'call_stack' 

call_stack_on 

module Log 
    class Logger 
    def info(msg, mod = '') 
     mod = call_stack(2)[0][0] if mod == '' 
     puts "Module: #{mod} Msg: #{msg}" 
    end 
    end # class Logger 
end # module Log 
$log = Log::Logger.new 

Works für mich (Rubin 1.8.7).

$ ruby foo.rb 
Module: Foo::Bar Msg: I did something! 
+0

Laut ihrer Website möchten wir stattdessen ruby-debug verwenden, obwohl die Links gebrochen erscheinen. Es stellt auch fest, dass dies eine erhebliche Verlangsamung bedeutet. Tatsächlich funktioniert es möglicherweise nicht einmal. Dennoch, die beste Lösung bisher, also bin ich + 1'ing diese Antwort. Vielen Dank. – ChrisInEdmonton

+0

Hier ist Ruby-Debug: http://rubyforge.org/projects/ruby-debug/, und ja, es wäre langsam. Die standardmäßige Unterstützung von Ruby für die Überprüfung von Callstacks ist erbärmlich und es gab zahlreiche Vorschläge, um sie zu verbessern. Sie erhalten also nur den Kernel-Aufrufer. Jede Lösung würde entweder die Rückverfolgung oder die Arbeit mit dem CAPI beinhalten, also habe ich das dargestellt, was am einfachsten zu sein scheint. Ich schlage vor, dass, wenn Sie diese Funktionalität wirklich benötigen, Sie eine Kodierungskonvention durchsetzen und Programmierer immer das Modul beim Aufrufen angeben lassen (kein Standardwert). Unbequem, aber schnell. Oder Sie können call_stack deaktivieren, wenn Sie nicht debuggen. –

2

Kam über diesen Beitrag während der Suche nach einer Antwort für meine eigenen Zwecke.

Ich habe nicht eine gefunden, die angemessen war, also habe ich die Ruby-Quelle durchforstet und eine Erweiterung zusammengestellt. Ich habe es als gem-gebündelt ohne Probleme installieren sollten so lange, wie Sie Rubin verwenden 1.9.1:

sudo gem Absender

Diese funktioniert nicht installieren mit Ruby 1.8 , da 1.8 ein anderes Modell zum Verfolgen von Frames hat.

http://rubygems.org/gems/sender

3

A mixin löst den spezifischen Anforderungen des OP (inzwischen +1 bis Asher zur Lösung des generic "den ich als" Fall!).

Verwandte Themen