RSpec.shared_examples 'additional metrics query' do include Prometheus::MetricBuilders let(:metric_group_class) { Gitlab::Prometheus::MetricGroup } let(:metric_class) { Gitlab::Prometheus::Metric } let(:metric_names) { %w{metric_a metric_b} } let(:query_range_result) do [{ 'metric': {}, 'values': [[1488758662.506, '0.00002996364761904785'], [1488758722.506, '0.00003090239047619091']] }] end let(:client) { double('prometheus_client') } let(:query_result) { described_class.new(client).query(*query_params) } let(:environment) { create(:environment, slug: 'environment-slug') } before do allow(client).to receive(:label_values).and_return(metric_names) allow(metric_group_class).to receive(:all).and_return([simple_metric_group(metrics: [simple_metric])]) end context 'metrics query context' do subject! { described_class.new(client) } shared_examples 'query context containing environment slug and filter' do it 'contains ci_environment_slug' do expect(subject).to receive(:query_metrics).with(hash_including(ci_environment_slug: environment.slug)) subject.query(*query_params) end it 'contains environment filter' do expect(subject).to receive(:query_metrics).with( hash_including( environment_filter: "container_name!=\"POD\",environment=\"#{environment.slug}\"" ) ) subject.query(*query_params) end end describe 'project has Kubernetes service' do let(:project) { create(:kubernetes_project) } let(:environment) { create(:environment, slug: 'environment-slug', project: project) } let(:kube_namespace) { project.kubernetes_service.actual_namespace } it_behaves_like 'query context containing environment slug and filter' it 'query context contains kube_namespace' do expect(subject).to receive(:query_metrics).with(hash_including(kube_namespace: kube_namespace)) subject.query(*query_params) end end describe 'project without Kubernetes service' do it_behaves_like 'query context containing environment slug and filter' it 'query context contains empty kube_namespace' do expect(subject).to receive(:query_metrics).with(hash_including(kube_namespace: '')) subject.query(*query_params) end end end context 'with one group where two metrics is found' do before do allow(metric_group_class).to receive(:all).and_return([simple_metric_group]) end context 'some queries return results' do before do allow(client).to receive(:query_range).with('query_range_a', any_args).and_return(query_range_result) allow(client).to receive(:query_range).with('query_range_b', any_args).and_return(query_range_result) allow(client).to receive(:query_range).with('query_range_empty', any_args).and_return([]) end it 'return group data only for queries with results' do expected = [ { group: 'name', priority: 1, metrics: [ { title: 'title', weight: 1, y_label: 'Values', queries: [ { query_range: 'query_range_a', result: query_range_result }, { query_range: 'query_range_b', label: 'label', unit: 'unit', result: query_range_result } ] } ] } ] expect(query_result).to match_schema('prometheus/additional_metrics_query_result') expect(query_result).to eq(expected) end end end context 'with two groups with one metric each' do let(:metrics) { [simple_metric(queries: [simple_query])] } before do allow(metric_group_class).to receive(:all).and_return( [ simple_metric_group(name: 'group_a', metrics: [simple_metric(queries: [simple_query])]), simple_metric_group(name: 'group_b', metrics: [simple_metric(title: 'title_b', queries: [simple_query('b')])]) ]) allow(client).to receive(:label_values).and_return(metric_names) end context 'both queries return results' do before do allow(client).to receive(:query_range).with('query_range_a', any_args).and_return(query_range_result) allow(client).to receive(:query_range).with('query_range_b', any_args).and_return(query_range_result) end it 'return group data both queries' do queries_with_result_a = { queries: [{ query_range: 'query_range_a', result: query_range_result }] } queries_with_result_b = { queries: [{ query_range: 'query_range_b', result: query_range_result }] } expect(query_result).to match_schema('prometheus/additional_metrics_query_result') expect(query_result.count).to eq(2) expect(query_result).to all(satisfy { |r| r[:metrics].count == 1 }) expect(query_result[0][:metrics].first).to include(queries_with_result_a) expect(query_result[1][:metrics].first).to include(queries_with_result_b) end end context 'one query returns result' do before do allow(client).to receive(:query_range).with('query_range_a', any_args).and_return(query_range_result) allow(client).to receive(:query_range).with('query_range_b', any_args).and_return([]) end it 'return group data only for query with results' do queries_with_result = { queries: [{ query_range: 'query_range_a', result: query_range_result }] } expect(query_result).to match_schema('prometheus/additional_metrics_query_result') expect(query_result.count).to eq(1) expect(query_result).to all(satisfy { |r| r[:metrics].count == 1 }) expect(query_result.first[:metrics].first).to include(queries_with_result) end end end end