Skip to content
Snippets Groups Projects
Verified Commit 3cfd0122 authored by Max Woolf's avatar Max Woolf Committed by GitLab
Browse files

Merge branch '2886/opstrace/prefil-metric-issues' into 'master'

Add issue prefilling support for o11y metrics

See merge request !161329



Merged-by: Max Woolf's avatarMax Woolf <mwoolf@gitlab.com>
Approved-by: default avatarDaniele Rossetti <drossetti@gitlab.com>
Reviewed-by: Max Woolf's avatarMax Woolf <mwoolf@gitlab.com>
Reviewed-by: default avatarDaniele Rossetti <drossetti@gitlab.com>
Co-authored-by: default avatarMax Woolf <max@woolf.io>
parents 8a91b20a e49f51d5
No related branches found
No related tags found
No related merge requests found
Pipeline #1397410487 passed
Pipeline: E2E GDK

#1397428698

    Pipeline: Ruby 3.2.4 as-if-foss

    #1397414636

      ......@@ -120,6 +120,7 @@ def new
      build_params = issue_params.merge(
      merge_request_to_resolve_discussions_of: params[:merge_request_to_resolve_discussions_of],
      discussion_to_resolve: params[:discussion_to_resolve],
      observability_links: params[:observability_metric_details],
      confidential: !!Gitlab::Utils.to_boolean(issue_params[:confidential])
      )
      service = ::Issues::BuildService.new(container: project, current_user: current_user, params: build_params)
      ......
      ......@@ -16,13 +16,49 @@ def issue_params_from_template
      end
      end
      def observability_issue_params
      return {} unless can?(current_user, :read_observability, container)
      begin
      links_params = ::Gitlab::Json.parse(CGI.unescape(params[:observability_links]))
      return {} if links_params.blank?
      {
      title: "Issue created from #{links_params['name']}",
      description: observability_metric_description(links_params)
      }
      rescue JSON::ParserError, TypeError
      {}
      end
      end
      def observability_metric_description(params)
      <<-TEXT
      [Metric details](#{params['fullUrl']}) \\
      Name: `#{params['name']}` \\
      Type: `#{params['type']}` \\
      Selected dimension(s): `#{params['dimensions'].join(', ')}` \\
      Timeframe: `#{params.dig('timeframe', 0)} - #{params.dig('timeframe', 1)}` \\
      Latest value within timeframe (time: `#{params.dig('timeframe', 1)}`):
      #{observability_latest_values(params)}
      TEXT
      end
      def observability_latest_values(params)
      params['latestValues'].map { |value| " * `#{value}`" }.join("\n")
      end
      # Issue params can be built from 3 types of passed params,
      # They take precedence over eachother like this
      # passed params > discussion params > template params
      # The template params are filled in here, and might be overwritten by super
      override :build_issue_params
      def build_issue_params
      issue_params_from_template.merge(super).with_indifferent_access
      issue_params_from_template
      .merge(super)
      .merge(observability_issue_params)
      .with_indifferent_access
      end
      end
      end
      ......
      ......@@ -3,6 +3,8 @@
      require 'spec_helper'
      RSpec.describe Issues::BuildService, feature_category: :team_planning do
      using RSpec::Parameterized::TableSyntax
      let_it_be(:project) { create(:project, :repository) }
      let_it_be(:developer) { create(:user) }
      let_it_be(:guest) { create(:user) }
      ......@@ -18,6 +20,55 @@ def build_issue(issue_params = {})
      described_class.new(container: project, current_user: user, params: issue_params).execute
      end
      describe '#observability_issue_params' do
      let(:params) { {} }
      subject(:service) { described_class.new(container: project, current_user: user, params: params).observability_issue_params }
      context 'when feature flag or licence flag is disabled' do
      where(:feature_flag, :licence_flag) do
      true | false
      false | true
      false | false
      end
      with_them do
      before do
      stub_feature_flags(observability_features: feature_flag)
      stub_licensed_features(observability: licence_flag)
      end
      it { is_expected.to eq({}) }
      end
      end
      context 'when feature flag and licence flag are enabled' do
      before do
      stub_feature_flags(observability_features: true)
      stub_licensed_features(observability: true)
      end
      context 'when observabiilty_links params are empty' do
      it { is_expected.to eq({}) }
      end
      context 'when observability_links params are invalid' do
      let(:params) { { observability_links: 'this is not valid at all' } }
      it { is_expected.to eq({}) }
      end
      context 'when observability_links params are valid' do
      let(:params) { { observability_links: "%7B%22fullUrl%22%3A%22http%3A%2F%2Fgdk.test%3A3000%2Fgitlab-org%2Fgitlab-test%2F-%2Fmetrics%2Fapp.ads.ad_requests%3Ftype%3DSum%26date_range%3D1h%26group_by_fn%3Dsum%26group_by_attrs%5B%5D%3Dapp.ads.ad_request_type%26group_by_attrs%5B%5D%3Dapp.ads.ad_response_type%22%2C%22name%22%3A%22app.ads.ad_requests%22%2C%22type%22%3A%22Sum%22%2C%22dimensions%22%3A%5B%22app.ads.ad_request_type%22%2C%22app.ads.ad_response_type%22%5D%2C%22timeframe%22%3A%5B%222024-07-2504%3A47%3A00UTC%22%2C%222024-07-2505%3A47%3A00UTC%22%5D%2C%22latestValues%22%3A%5B%22app.ads.ad_request_type%3ANOT_TARGETED%2Capp.ads.ad_response_type%3ARANDOM%3A281.000%22%2C%22app.ads.ad_request_type%3ATARGETED%2Capp.ads.ad_response_type%3ATARGETED%3A1387.000%22%2C%22app.ads.ad_request_type%3ATARGETED%2Capp.ads.ad_response_type%3ARANDOM%3A287.000%22%5D%7D" } }
      it 'has the correct output' do
      expect(service[:description]).not_to be_nil
      expect(service[:title]).to eq("Issue created from app.ads.ad_requests")
      end
      end
      end
      end
      context 'with an issue template' do
      describe '#execute' do
      let(:project) { build(:project, issues_template: 'Work hard, play hard!') }
      ......
      0% Loading or .
      You are about to add 0 people to the discussion. Proceed with caution.
      Finish editing this message first!
      Please register or to comment