<commit_before>require 'spec_helper'
require 'securerandom'

class MockController
  def user_id
    @user_id ||= SecureRandom.hex(16)
  end
end

class MockRequest
  def remote_ip
    '127.0.0.1'
  end
end

describe LogStasher::LogSubscriber do
  subject { described_class.new }

  let(:logger) { ::Logger.new('/dev/null') }
  let(:mock_controller) { MockController.new }
  let(:mock_request) { MockRequest.new }
  let(:context) {{ :controller => mock_controller, :request => mock_request }}

  around do |example|
    backup_logger = LogStasher.logger
    LogStasher.logger = logger
    Thread.current[:logstasher_context] = context
    Timecop.freeze { example.run }
    Thread.current[:logstasher_context] = nil
    LogStasher.logger = backup_logger
  end

  describe '#process_action' do
    let(:timestamp) { ::Time.new.utc.iso8601(3) }
    let(:controller) { 'users' }
    let(:action) { 'show' }
    let(:params) {{ 'foo' => 'bar' }}
    let(:format) { 'text/plain' }
    let(:method) { 'method' }
    let(:path) { '/users/1' }
    let(:duration) { 12.4 }
    let(:status) { 200 }
    let(:payload) {{
      :controller => controller,
      :action     => action,
      :params     => params,
      :format     => format,
      :method     => method,
      :path       => path,
      :status     => status
    }}

    let(:event) { double(:payload => payload, :duration => duration) }

    it 'logs the event in logstash format' do
      logger.should_receive(:<<) do |json|
        JSON.parse(json).should eq({
          '@timestamp' => timestamp,
          '@version'   => '1',
          'tags'       => ['request'],
          'action'     => action,
          'controller' => controller,
          'format'     => format,
          'ip'         => mock_request.remote_ip,
          'method'     => method,
          'path'       => path,
          'route'      => "#{controller}##{action}",
          'status'     => status,
          'duration'   => duration
        })
      end

      subject.process_action(event)
    end

    it 'includes custom fields in the log' do
      ::LogStasher.add_custom_fields do |fields|
        fields['user_id'] = user_id
        fields['other']   = 'stuff'
      end

      logger.should_receive(:<<) do |json|
        fields = JSON.parse(json)
        fields['user_id'].should eq mock_controller.user_id
        fields['other'].should eq 'stuff'
      end

      subject.process_action(event)
    end

    it 'includes parameters in the log' do
      ::LogStasher.stub(:log_controller_parameters => true)

      logger.should_receive(:<<) do |json|
        JSON.parse(json)['parameters'].should eq params
      end

      subject.process_action(event)
    end

    it 'includes redirect location in the log' do
      redirect_event = double(:payload => {:location => 'new/location'})
      subject.redirect_to(redirect_event)

      logger.should_receive(:<<) do |json|
        JSON.parse(json)['location'].should eq 'new/location'
      end

      subject.process_action(event)
    end

    it 'includes runtimes in the log' do
      payload.merge!({
        :view_runtime => 3.3,
        :db_runtime =>  2.1<commit_msg>Cleanup specs a bit<commit_after>require 'spec_helper'
require 'securerandom'

class MockController
  def user_id
    @user_id ||= SecureRandom.hex(16)
  end
end

class MockRequest
  def remote_ip
    '127.0.0.1'
  end
end

describe LogStasher::LogSubscriber do
  subject { described_class.new }

  let(:logger) { ::Logger.new('/dev/null') }
  let(:mock_controller) { MockController.new }
  let(:mock_request) { MockRequest.new }
  let(:context) {{ :controller => mock_controller, :request => mock_request }}

  around do |example|
    backup_logger = LogStasher.logger
    LogStasher.logger = logger
    Thread.current[:logstasher_context] = context
    Timecop.freeze { example.run }
    Thread.current[:logstasher_context] = nil
    LogStasher.logger = backup_logger
  end

  describe '#process_action' do
    let(:timestamp) { ::Time.new.utc.iso8601(3) }
    let(:duration) { 12.4 }
    let(:payload) {{
      :controller => 'users',
      :action     => 'show',
      :params     => { 'foo' => 'bar' },
      :format     => 'text/plain',
      :method     => 'method',
      :path       => '/users/1',
      :status     => 200
    }}

    let(:event) { double(:payload => payload, :duration => duration) }

    it 'logs the event in logstash format' do
      logger.should_receive(:<<) do |json|
        JSON.parse(json).should eq({
          '@timestamp' => timestamp,
          '@version'   => '1',
          'tags'       => ['request'],
          'action'     => payload[:action],
          'controller' => payload[:controller],
          'format'     => payload[:format],
          'ip'         => mock_request.remote_ip,
          'method'     => payload[:method],
          'path'       => payload[:path],
          'route'      => "#{payload[:controller]}##{payload[:action]}",
          'status'     => payload[:status],
          'duration'   => duration
        })
      end

      subject.process_action(event)
    end

    it 'includes custom fields in the log' do
      ::LogStasher.add_custom_fields do |fields|
        fields['user_id'] = user_id
        fields['other']   = 'stuff'
      end

      logger.should_receive(:<<) do |json|
        fields = JSON.parse(json)
        fields['user_id'].should eq mock_controller.user_id
        fields['other'].should eq 'stuff'
      end

      subject.process_action(event)
    end

    it 'includes parameters in the log' do
      ::LogStasher.stub(:log_controller_parameters => true)

      logger.should_receive(:<<) do |json|
        JSON.parse(json)['parameters'].should eq payload[:params]
      end

      subject.process_action(event)
    end

    it 'includes redirect location in the log' do
      redirect_event = double(:payload => {:location => 'new/location'})
      subject.redirect_to(redirect_event)

      logger.should_receive(:<<) do |json|
        JSON.parse(json)['location'].should eq 'new/location'
      end

      subject.process_action(event)
    end

    it 'includes runtimes in the log' do
      payload.merge!({
        :view_runtime => 3.3,
        :db_runtime =>  2.1
{'fraction_non_alphanumeric': 0.1401989092075714, 'fraction_numerical': 0.008020532563362208, 'mean_word_length': 2.4447513812154695, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 61, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 2, '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': '7546876', 'n_tokens_mistral': 1965, 'n_tokens_neox': 1897, 'n_words': 418}