2015-04-07 29 views
5

Mam element oprogramowania pośredniczącego typu Rack, który ładuje dzierżawcę za pośrednictwem poddomeny i stosuje pewne ustawienia domyślne. Oprogramowanie pośrednie, choć nie ładne, działa wystarczająco dobrze. Jednakże, gdy wyjątek jest zgłaszany w aplikacji, oprogramowanie pośrednie "zatrzymuje" pełne śledzenie stosu. Kiedy mówię o pułapce, mam na myśli to, że ukrywa oczekiwany ślad stosu.Śledzenie stosu warstwy pośredniej "zalewkowanie"

Oto przykład.

mam rzucać wyjątek w działaniu regulatora tak:

def index 
    throw "Exception in a Rails controller action" 
    @taxonomies = Spree::Taxonomy.all 
end 

Można by oczekiwać, że ślad stosu byłoby odwołać tę lokalizację, ale tak nie jest. Zamiast tego odnosi się do linii w oprogramowaniu pośredniczącym.

Completed 500 Internal Server Error in 139ms 

UncaughtThrowError (uncaught throw "Exception in a Rails controller action"): 
lib/tenant_manager/middleware/loader.rb:42:in `call' 

Dlaczego tak się dzieje? Czy widziałeś coś takiego wcześniej?

Oto middleware:

# lib/tenant_manager/middleware/loader.rb 
module TenantManager 
    module Middleware 
    class Loader 
    # Middleware to detect an tenant via subdomain early in 
    # the request process 
    # 
    # Usage: 
    # # config/application.rb 
    # config.middleware.use TenantManager::Middleware::Loader 
    # 
    # A scaled down version of https://github.com/radar/houser 

     def initialize(app) 
     @app = app 
     end 

     def call(env) 
     domain_parts = env['HTTP_HOST'].split('.') 
     if domain_parts.length > 2 
      subdomain = domain_parts.first 
      tenant = Leafer::Tenant.find_by_database(subdomain) 
      if tenant 
      ENV['CURRENT_TENANT_ID'] = tenant.id.to_s 
      ENV['RAILS_CACHE_ID'] = tenant.database 
      Spree::Image.change_paths tenant.database 
      Apartment::Tenant.process(tenant.database) do 
       country = Spree::Country.find_by_name('United States') 
       Spree.config do |config| 
       config.default_country_id = country.id if country.present? 
       config.track_inventory_levels = false 
       end 
       Spree::Auth::Config.set(:registration_step => false) 
      end 
      end 
     else 
      ENV['CURRENT_TENANT_ID'] = nil 
      ENV['RAILS_CACHE_ID'] = "" 
     end 
     @app.call(env) 
     end 

    end 
    end 
end 

Używam rubin 2.2.0p0 i rails 4.1.8.

Przeszukałem strony internetowe, ale nie mogłem nic znaleźć, prawdopodobnie dlatego, że nie szukam właściwej rzeczy.

Jakieś myśli o tym, dlaczego tak się dzieje i co robię źle?

Pozdrawiam!

Odpowiedz

7

końcu znalazłem rozwiązanie tego. Okazuje się, że ostatnia linia w mojej aplikacji jest w oprogramowaniu pośredniczącym. Resztę kodu uruchamiałem w lokalnym silniku szynowym znajdującym się w katalogu components. Wszystko, co musieliśmy zrobić, to stworzyć nowy tłumik dla BacktraceCleaner. Zwróć uwagę, że katalog składników jest teraz dołączony.

Jeśli są Państwo zainteresowani, tutaj jest problem, który napisałem na temat projektu szyn, aby szczegółowo opisać tę replikę. https://github.com/rails/rails/issues/22265

0

Nie robisz niczego złego. Ale wiele wyjątków pułapek pośrednich w celu oczyszczenia, w tym oprogramowanie pośrednie, które Rack wstawia automatycznie w trybie programowania. Jest to specyficzny middleware Rack włożony w rozwój, który złapie niezłapane wyjątki i dać rozsądny stronę HTML zamiast zrzut stosu surowy (które często nie widzieć w ogóle z typowymi serwerami aplikacji.)

  • Można złap wyjątek, umieszczając początek/ratowanie/koniec na najwyższym poziomie. Pamiętaj, aby złapać "wyjątek", a nie tylko domyślny "ratunkowy" bez argumentów, jeśli chcesz dostać wszystko. I możesz chcieć ponownie rzucić wyjątek, jeśli chcesz zostawić ten kod.
  • Możesz uruchomić w trybie produkcyjnym - może to uniemożliwić automatyczne wstawianie oprogramowania pośredniego przez stelaż.
  • Możesz dowiedzieć się, jakie wstawiono oprogramowanie pośrednie (w Railsach: "middleware rake"), a następnie ręcznie usunąć oprogramowanie pośrednie (w Railsach "config.middleware.delete" lub "config.middleware.disable").

Prawdopodobnie istnieją inne metody.

3

Twoje oprogramowanie pośrednie wydaje się być dobre. Myślę, że masz problem z ustawieniem backtrace_cleaner. Być może czystsze zostanie przesłonięte przez klejnot 3rd party. Spróbuj umieścić punkt przerwania (debugger) W sposobie działania kontroler przed gromadzenia błędów, i druk:

puts env['action_dispatch.backtrace_cleaner'].instance_variable_get(:@silencers).map(&:source_location).map{|l| l.join(':')} 

aby zobaczyć lokalizacje źródłem wszystkich tłumików, które zdejmować śladów non-app. Domyślnie powinien używać tylko Rails :: BacktraceCleaner, który lokalizuje na railages-4.1.8/lib/rails/backtrace_cleaner.rb

Aby bezpośrednio zobaczyć kod źródłowy tłumik:

puts env['action_dispatch.backtrace_cleaner'].instance_variable_get(:@silencers).map{|s| RubyVM::InstructionSequence.disasm s } 

Zobacz więcej od https://github.com/rails/rails/blob/master/railties/lib/rails/backtrace_cleaner.rb https://github.com/rails/rails/blob/master/activesupport/lib/active_support/backtrace_cleaner.rb

Powiązane problemy