summaryrefslogtreecommitdiff
path: root/spec/lib/gitlab/lograge/custom_options_spec.rb
blob: 58b05be6ff930c25ca590b58c14195ff163098d6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# frozen_string_literal: true

require 'spec_helper'

RSpec.describe Gitlab::Lograge::CustomOptions do
  describe '.call' do
    let(:params) do
      {
        'controller' => 'ApplicationController',
        'action' => 'show',
        'format' => 'html',
        'a' => 'b'
      }
    end

    let(:event_payload) do
      {
        params: params,
        user_id: 'test',
        cf_ray: SecureRandom.hex,
        cf_request_id: SecureRandom.hex,
        metadata: { 'meta.user' => 'jane.doe' },
        request_urgency: :default,
        target_duration_s: 1,
        remote_ip: '192.168.1.2',
        ua: 'Nyxt',
        queue_duration_s: 0.2,
        etag_route: '/etag'
      }
    end

    let(:event) { ActiveSupport::Notifications::Event.new('test', 1, 2, 'transaction_id', event_payload) }

    subject { described_class.call(event) }

    it 'ignores some parameters' do
      param_keys = subject[:params].map { |param| param[:key] }

      expect(param_keys).not_to include(*described_class::IGNORE_PARAMS)
    end

    it 'formats the parameters' do
      expect(subject[:params]).to eq([{ key: 'a', value: 'b' }])
    end

    it 'adds the current time' do
      travel_to(5.days.ago) do
        expected_time = Time.now.utc.iso8601(3)

        expect(subject[:time]).to eq(expected_time)
      end
    end

    it 'adds the user id' do
      expect(subject[:user_id]).to eq('test')
    end

    it 'adds Cloudflare headers' do
      expect(subject[:cf_ray]).to eq(event.payload[:cf_ray])
      expect(subject[:cf_request_id]).to eq(event.payload[:cf_request_id])
    end

    it 'adds the metadata' do
      expect(subject['meta.user']).to eq('jane.doe')
    end

    context 'when metadata is missing' do
      let(:event_payload) { { params: {} } }

      it 'does not break' do
        expect { subject }.not_to raise_error
      end
    end

    context 'trusted payload' do
      it { is_expected.to include(event_payload.slice(*described_class::KNOWN_PAYLOAD_PARAMS)) }

      context 'payload with rejected fields' do
        let(:event_payload) { { params: {}, request_urgency: :high, something: 'random', username: nil } }

        it { is_expected.to include({ request_urgency: :high }) }
        it { is_expected.not_to include({ something: 'random' }) }
        it { is_expected.not_to include({ username: nil }) }
      end
    end

    context 'when correlation_id is overridden' do
      let(:correlation_id_key) { Labkit::Correlation::CorrelationId::LOG_KEY }

      before do
        event_payload[correlation_id_key] = '123456'
      end

      it 'sets the overridden value' do
        expect(subject[correlation_id_key]).to eq('123456')
      end
    end

    context 'when feature flags are present', :request_store do
      before do
        allow(Feature).to receive(:log_feature_flag_states?).and_return(false)

        [:enabled_feature, :disabled_feature].each do |flag_name|
          stub_feature_flag_definition(flag_name, log_state_changes: true)
          allow(Feature).to receive(:log_feature_flag_states?).with(flag_name).and_call_original
        end

        Feature.enable(:enabled_feature)
        Feature.disable(:disabled_feature)
      end

      context 'and :feature_flag_log_states is enabled' do
        before do
          Feature.enable(:feature_flag_state_logs)
        end

        it 'adds feature flag events' do
          Feature.enabled?(:enabled_feature)
          Feature.enabled?(:disabled_feature)

          expect(subject).to have_key(:feature_flag_states)
          expect(subject[:feature_flag_states]).to match_array(%w[enabled_feature:1 disabled_feature:0])
        end
      end

      context 'and :feature_flag_log_states is disabled' do
        before do
          Feature.disable(:feature_flag_state_logs)
        end

        it 'does not track or add feature flag events' do
          Feature.enabled?(:enabled_feature)
          Feature.enabled?(:disabled_feature)

          expect(subject).not_to have_key(:feature_flag_states)
          expect(Feature).not_to receive(:log_feature_flag_state)
        end
      end
    end
  end
end