summaryrefslogtreecommitdiff
path: root/spec/lib/gitlab/metrics/methods_spec.rb
blob: bca94deb1d8cac33774b4e344ffc63b052b64f43 (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
# frozen_string_literal: true

require 'spec_helper'

describe Gitlab::Metrics::Methods do
  subject { Class.new { include Gitlab::Metrics::Methods } }

  shared_context 'metric' do |metric_type, *args|
    let(:docstring) { 'description' }
    let(:metric_name) { :sample_metric }

    describe "#define_#{metric_type}" do
      define_method(:call_define_metric_method) do |**args|
        subject.__send__("define_#{metric_type}", metric_name, **args)
      end

      context 'metrics access method not defined' do
        it "defines metrics accessing method" do
          expect(subject).not_to respond_to(metric_name)

          call_define_metric_method(docstring: docstring)

          expect(subject).to respond_to(metric_name)
        end
      end

      context 'metrics access method defined' do
        before do
          call_define_metric_method(docstring: docstring)
        end

        it 'raises error when trying to redefine method' do
          expect { call_define_metric_method(docstring: docstring) }.to raise_error(ArgumentError)
        end

        context 'metric is not cached' do
          it 'calls fetch_metric' do
            expect(subject).to receive(:init_metric).with(metric_type, metric_name, docstring: docstring)

            subject.public_send(metric_name)
          end
        end

        context 'metric is cached' do
          before do
            subject.public_send(metric_name)
          end

          it 'returns cached metric' do
            expect(subject).not_to receive(:init_metric)

            subject.public_send(metric_name)
          end
        end
      end
    end

    describe "#fetch_#{metric_type}" do
      let(:null_metric) { Gitlab::Metrics::NullMetric.instance }

      define_method(:call_fetch_metric_method) do |**args|
        subject.__send__("fetch_#{metric_type}", metric_name, **args)
      end

      context "when #{metric_type} is not cached" do
        it 'initializes counter metric' do
          allow(Gitlab::Metrics).to receive(metric_type).and_return(null_metric)

          call_fetch_metric_method(docstring: docstring)

          expect(Gitlab::Metrics).to have_received(metric_type).with(metric_name, docstring, *args)
        end
      end

      context "when #{metric_type} is cached" do
        before do
          call_fetch_metric_method(docstring: docstring)
        end

        it 'uses class metric cache' do
          expect(Gitlab::Metrics).not_to receive(metric_type)

          call_fetch_metric_method(docstring: docstring)
        end

        context 'when metric is reloaded' do
          before do
            subject.reload_metric!(metric_name)
          end

          it "initializes #{metric_type} metric" do
            allow(Gitlab::Metrics).to receive(metric_type).and_return(null_metric)

            call_fetch_metric_method(docstring: docstring)

            expect(Gitlab::Metrics).to have_received(metric_type).with(metric_name, docstring, *args)
          end
        end
      end

      context 'when metric is configured with feature' do
        let(:feature_name) { :some_metric_feature }
        let(:metric) { call_fetch_metric_method(docstring: docstring, with_feature: feature_name) }

        context 'when feature is enabled' do
          before do
            Feature.get(feature_name).enable
          end

          it "initializes #{metric_type} metric" do
            allow(Gitlab::Metrics).to receive(metric_type).and_return(null_metric)

            metric

            expect(Gitlab::Metrics).to have_received(metric_type).with(metric_name, docstring, *args)
          end
        end

        context 'when feature is disabled' do
          before do
            Feature.get(feature_name).disable
          end

          it "returns NullMetric" do
            allow(Gitlab::Metrics).to receive(metric_type)

            expect(metric).to be_instance_of(Gitlab::Metrics::NullMetric)

            expect(Gitlab::Metrics).not_to have_received(metric_type)
          end
        end
      end
    end
  end

  include_examples 'metric', :counter, {}
  include_examples 'metric', :gauge, {}, :all
  include_examples 'metric', :histogram, {}, [0.005, 0.01, 0.1, 1, 10]
end