metrics_spec.rb 8.4 KB
Newer Older
1 2 3
require 'spec_helper'

describe Gitlab::Metrics do
4 5
  include StubENV

6 7 8
  describe '.settings' do
    it 'returns a Hash' do
      expect(described_class.settings).to be_an_instance_of(Hash)
9 10 11 12 13
    end
  end

  describe '.enabled?' do
    it 'returns a boolean' do
14
      expect(described_class.enabled?).to be_in([true, false])
15 16 17
    end
  end

P
Pawel Chojnacki 已提交
18 19
  describe '.prometheus_metrics_enabled?' do
    it 'returns a boolean' do
20
      expect(described_class.prometheus_metrics_enabled?).to be_in([true, false])
P
Pawel Chojnacki 已提交
21 22 23 24 25
    end
  end

  describe '.influx_metrics_enabled?' do
    it 'returns a boolean' do
26
      expect(described_class.influx_metrics_enabled?).to be_in([true, false])
P
Pawel Chojnacki 已提交
27 28 29
    end
  end

30
  describe '.submit_metrics' do
31 32 33 34 35 36
    it 'prepares and writes the metrics to InfluxDB' do
      connection = double(:connection)
      pool       = double(:pool)

      expect(pool).to receive(:with).and_yield(connection)
      expect(connection).to receive(:write_points).with(an_instance_of(Array))
37
      expect(described_class).to receive(:pool).and_return(pool)
38 39 40 41 42

      described_class.submit_metrics([{ 'series' => 'kittens', 'tags' => {} }])
    end
  end

43
  describe '.prepare_metrics' do
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
    it 'returns a Hash with the keys as Symbols' do
      metrics = described_class.
        prepare_metrics([{ 'values' => {}, 'tags' => {} }])

      expect(metrics).to eq([{ values: {}, tags: {} }])
    end

    it 'escapes tag values' do
      metrics = described_class.prepare_metrics([
        { 'values' => {}, 'tags' => { 'foo' => 'bar=' } }
      ])

      expect(metrics).to eq([{ values: {}, tags: { 'foo' => 'bar\\=' } }])
    end

    it 'drops empty tags' do
      metrics = described_class.prepare_metrics([
        { 'values' => {}, 'tags' => { 'cats' => '', 'dogs' => nil } }
      ])

      expect(metrics).to eq([{ values: {}, tags: {} }])
    end
  end

68
  describe '.escape_value' do
69 70 71 72 73 74 75 76
    it 'escapes an equals sign' do
      expect(described_class.escape_value('foo=')).to eq('foo\\=')
    end

    it 'casts values to Strings' do
      expect(described_class.escape_value(10)).to eq('10')
    end
  end
77 78 79 80

  describe '.measure' do
    context 'without a transaction' do
      it 'returns the return value of the block' do
81
        val = described_class.measure(:foo) { 10 }
82 83 84 85 86 87 88 89 90

        expect(val).to eq(10)
      end
    end

    context 'with a transaction' do
      let(:transaction) { Gitlab::Metrics::Transaction.new }

      before do
91
        allow(described_class).to receive(:current_transaction).
92 93 94 95
          and_return(transaction)
      end

      it 'adds a metric to the current transaction' do
96 97
        expect(transaction).to receive(:increment).
          with('foo_real_time', a_kind_of(Numeric))
98

99 100
        expect(transaction).to receive(:increment).
          with('foo_cpu_time', a_kind_of(Numeric))
101

102 103 104
        expect(transaction).to receive(:increment).
          with('foo_call_count', 1)

105
        described_class.measure(:foo) { 10 }
106 107 108
      end

      it 'returns the return value of the block' do
109
        val = described_class.measure(:foo) { 10 }
110 111 112 113 114

        expect(val).to eq(10)
      end
    end
  end
115 116 117 118 119 120 121

  describe '.tag_transaction' do
    context 'without a transaction' do
      it 'does nothing' do
        expect_any_instance_of(Gitlab::Metrics::Transaction).
          not_to receive(:add_tag)

122
        described_class.tag_transaction(:foo, 'bar')
123 124 125 126 127 128 129
      end
    end

    context 'with a transaction' do
      let(:transaction) { Gitlab::Metrics::Transaction.new }

      it 'adds the tag to the transaction' do
130
        expect(described_class).to receive(:current_transaction).
131 132 133 134 135
          and_return(transaction)

        expect(transaction).to receive(:add_tag).
          with(:foo, 'bar')

136
        described_class.tag_transaction(:foo, 'bar')
137 138 139
      end
    end
  end
140 141 142 143 144 145 146

  describe '.action=' do
    context 'without a transaction' do
      it 'does nothing' do
        expect_any_instance_of(Gitlab::Metrics::Transaction).
          not_to receive(:action=)

147
        described_class.action = 'foo'
148 149 150 151 152 153 154
      end
    end

    context 'with a transaction' do
      it 'sets the action of a transaction' do
        trans = Gitlab::Metrics::Transaction.new

155
        expect(described_class).to receive(:current_transaction).
156 157 158 159
          and_return(trans)

        expect(trans).to receive(:action=).with('foo')

160
        described_class.action = 'foo'
161 162 163
      end
    end
  end
Y
Yorick Peterse 已提交
164 165 166 167 168 169

  describe '#series_prefix' do
    it 'returns a String' do
      expect(described_class.series_prefix).to be_an_instance_of(String)
    end
  end
Y
Yorick Peterse 已提交
170 171 172 173 174 175 176

  describe '.add_event' do
    context 'without a transaction' do
      it 'does nothing' do
        expect_any_instance_of(Gitlab::Metrics::Transaction).
          not_to receive(:add_event)

177
        described_class.add_event(:meow)
Y
Yorick Peterse 已提交
178 179 180 181 182 183 184 185 186
      end
    end

    context 'with a transaction' do
      it 'adds an event' do
        transaction = Gitlab::Metrics::Transaction.new

        expect(transaction).to receive(:add_event).with(:meow)

187
        expect(described_class).to receive(:current_transaction).
Y
Yorick Peterse 已提交
188 189
          and_return(transaction)

190
        described_class.add_event(:meow)
Y
Yorick Peterse 已提交
191 192 193
      end
    end
  end
P
Pawel Chojnacki 已提交
194 195 196 197 198 199

  shared_examples 'prometheus metrics API' do
    describe '#counter' do
      subject { described_class.counter(:couter, 'doc') }

      describe '#increment' do
200 201 202 203 204 205 206 207 208 209 210
        it 'successfully calls #increment without arguments' do
          expect { subject.increment }.not_to raise_exception
        end

        it 'successfully calls #increment with 1 argument' do
          expect { subject.increment({}) }.not_to raise_exception
        end

        it 'successfully calls #increment with 2 arguments' do
          expect { subject.increment({}, 1) }.not_to raise_exception
        end
P
Pawel Chojnacki 已提交
211 212 213 214 215 216 217
      end
    end

    describe '#summary' do
      subject { described_class.summary(:summary, 'doc') }

      describe '#observe' do
218 219 220
        it 'successfully calls #observe with 2 arguments' do
          expect { subject.observe({}, 2) }.not_to raise_exception
        end
P
Pawel Chojnacki 已提交
221 222 223 224 225 226
      end
    end

    describe '#gauge' do
      subject { described_class.gauge(:gauge, 'doc') }

227 228 229 230
      describe '#set' do
        it 'successfully calls #set with 2 arguments' do
          expect { subject.set({}, 1) }.not_to raise_exception
        end
P
Pawel Chojnacki 已提交
231 232 233 234 235 236 237
      end
    end

    describe '#histogram' do
      subject { described_class.histogram(:histogram, 'doc') }

      describe '#observe' do
238 239 240
        it 'successfully calls #observe with 2 arguments' do
          expect { subject.observe({}, 2) }.not_to raise_exception
        end
P
Pawel Chojnacki 已提交
241 242 243 244 245 246 247 248 249 250 251
      end
    end
  end

  context 'prometheus metrics disabled' do
    before do
      allow(described_class).to receive(:prometheus_metrics_enabled?).and_return(false)
    end

    it_behaves_like 'prometheus metrics API'

252
    describe '#null_metric' do
P
Pawel Chojnacki 已提交
253 254
      subject { described_class.provide_metric(:test) }

255
      it { is_expected.to be_a(Gitlab::Metrics::NullMetric) }
P
Pawel Chojnacki 已提交
256 257 258 259 260
    end

    describe '#counter' do
      subject { described_class.counter(:counter, 'doc') }

261
      it { is_expected.to be_a(Gitlab::Metrics::NullMetric) }
P
Pawel Chojnacki 已提交
262 263 264 265 266
    end

    describe '#summary' do
      subject { described_class.summary(:summary, 'doc') }

267
      it { is_expected.to be_a(Gitlab::Metrics::NullMetric) }
P
Pawel Chojnacki 已提交
268 269 270 271 272
    end

    describe '#gauge' do
      subject { described_class.gauge(:gauge, 'doc') }

273
      it { is_expected.to be_a(Gitlab::Metrics::NullMetric) }
P
Pawel Chojnacki 已提交
274 275 276 277 278
    end

    describe '#histogram' do
      subject { described_class.histogram(:histogram, 'doc') }

279
      it { is_expected.to be_a(Gitlab::Metrics::NullMetric) }
P
Pawel Chojnacki 已提交
280 281 282 283
    end
  end

  context 'prometheus metrics enabled' do
284
    let(:metrics_multiproc_dir) { Dir.mktmpdir }
285

P
Pawel Chojnacki 已提交
286
    before do
287
      stub_const('Prometheus::Client::Multiprocdir', metrics_multiproc_dir)
P
Pawel Chojnacki 已提交
288 289 290 291 292
      allow(described_class).to receive(:prometheus_metrics_enabled?).and_return(true)
    end

    it_behaves_like 'prometheus metrics API'

293
    describe '#null_metric' do
P
Pawel Chojnacki 已提交
294 295 296 297 298 299 300 301
      subject { described_class.provide_metric(:test) }

      it { is_expected.to be_nil }
    end

    describe '#counter' do
      subject { described_class.counter(:name, 'doc') }

302
      it { is_expected.not_to be_a(Gitlab::Metrics::NullMetric) }
P
Pawel Chojnacki 已提交
303 304 305 306 307
    end

    describe '#summary' do
      subject { described_class.summary(:name, 'doc') }

308
      it { is_expected.not_to be_a(Gitlab::Metrics::NullMetric) }
P
Pawel Chojnacki 已提交
309 310 311 312 313
    end

    describe '#gauge' do
      subject { described_class.gauge(:name, 'doc') }

314
      it { is_expected.not_to be_a(Gitlab::Metrics::NullMetric) }
P
Pawel Chojnacki 已提交
315 316 317 318 319
    end

    describe '#histogram' do
      subject { described_class.histogram(:name, 'doc') }

320
      it { is_expected.not_to be_a(Gitlab::Metrics::NullMetric) }
P
Pawel Chojnacki 已提交
321 322
    end
  end
323
end