<commit_before>module Middleware
  class ExceptionHandler
    def initialize(app)
      @app = app
    end

    def call(env)
      begin
        @app.call(env)
      rescue => ex
        env["rack.errors"].puts ex
        env["rack.errors"].puts ex.backtrace.join("\n")
        env["rack.errors"].flush

        hash = { error: ex.to_s, status: 500 }

        # Set exception backtrace only for development mode
        if ENV["RACK_ENV"] == "development"
          hash[:backtrace] = ex.backtrace
          hash[:params]    = env
        end

        [
          500,
          { "Content-Type" => "application/json" },
          JSON.dump(hash)
        ]
      end
    end
  end
end<commit_msg>Fix serialization issues with exception middleware<commit_after>module Middleware
  class ExceptionHandler
    def initialize(app)
      @app = app
    end

    def call(env)
      begin
        @app.call(env)
      rescue => ex
        env["rack.errors"].puts ex
        env["rack.errors"].puts ex.backtrace.join("\n")
        env["rack.errors"].flush

        hash = { error: ex.to_s, status: 500 }

        # Set exception backtrace only for development mode
        if ENV["RACK_ENV"] == "development"
          hash[:backtrace] = ex.backtrace
          hash[:env]       = serialize_object(env)
        end

        [
          500,
          { "Content-Type" => "application/json" },
          [JSON.dump(hash)]
        ]
      end
    end

    private

    def serializable?(object)
      [Integer, String, Array, Hash].include?(object.class)
    end

    def serialize_object(data)
      data.select{|k,v| serializable?(v) }.inject({}) do |h, pair|
        h[pair.first] = pair.last.is_a?(Hash) ? serialize_object(pair.last) : pair.last
        h
      end
    end
  end
end
{'fraction_non_alphanumeric': 0.12092238470191226, 'fraction_numerical': 0.006749156355455568, 'mean_word_length': 1.8926829268292682, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2209110', 'n_tokens_mistral': 566, 'n_tokens_neox': 541, 'n_words': 123}