Skip to content
Snippets Groups Projects
Verified Commit f03e0726 authored by Max Woolf's avatar Max Woolf :red_circle: Committed by GitLab
Browse files

Add issue prefilling support for o11y metrics

Adds support in query params to accept
a linked observability metric

EE: true
parent a0485aba
No related branches found
No related tags found
2 merge requests!162233Draft: Script to update Topology Service Gem,!161329Add issue prefilling support for o11y metrics
......@@ -122,6 +122,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)
......
# frozen_string_literal: true
module Observability
module MetricsIssuesHelper
def observability_metric_issue_description(params)
<<-TEXT
[Metric details](#{params['fullUrl']}) \\
Name: `#{params['name']}` \\
Type: `#{params['type']}` \\
Timeframe: `#{params.dig('timeframe', 0)} - #{params.dig('timeframe', 1)}`
TEXT
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_issue_description(links_params)
}
rescue JSON::ParserError, TypeError
{}
end
end
end
end
......@@ -4,6 +4,7 @@ module EE
module Issues
module BuildService
extend ::Gitlab::Utils::Override
include ::Observability::MetricsIssuesHelper
def issue_params_from_template
return {} unless container.feature_available?(:issuable_default_templates)
......@@ -22,7 +23,10 @@ def issue_params_from_template
# 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
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Observability::MetricsIssuesHelper, feature_category: :metrics do
using RSpec::Parameterized::TableSyntax
let_it_be(:project) { build_stubbed(:project) } # rubocop:disable RSpec/FactoryBot/AvoidCreate -- we need a project with a repository
let_it_be(:developer) { build_stubbed(:user) }
let(:user) { developer }
before_all do
project.add_developer(developer)
end
describe '#observability_issue_params' do
let(:params) { {} }
subject(:service) do
::Issues::BuildService.new(container: project, current_user: user, params: params).observability_issue_params
end
context 'when feature flag or licence flag is disabled' do
where(:feature_flag_enabled, :licence_flag_enabled) do
true | false
false | true
false | false
end
with_them do
before do
stub_feature_flags(observability_features: licence_flag_enabled)
stub_licensed_features(observability: feature_flag_enabled)
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', :aggregate_failures do
before do
allow(Ability).to receive(:allowed?).and_call_original
allow(Ability).to receive(:allowed?).with(user, :read_observability, project).and_return(true)
end
# rubocop:disable Layout/LineLength -- urls with params will be too long
let(:params) do
{ observability_links: CGI.escape(
%({"fullUrl":"http://gdk.test:3000/gitlab-org/gitlab-test/-/metrics/app.ads.ad_requests?type=Sum&date_range=1h&group_by_fn=sum&group_by_attrs[]=app.ads.ad_request_type&group_by_attrs[]=app.ads.ad_response_type", "name": "app.ads.ad_requests", "type": "Sum", "timeframe":["2024-07-2504:47:00UTC","2024-07-2505:47:00UTC"]})
) }
end
# rubocop:enable Layout/LineLength
it 'has the correct output' do
expect(service[:description]).to include("Name: `app.ads.ad_requests`")
expect(service[:description]).to include("Type: `Sum`")
expect(service[:description]).to include("Timeframe: `2024-07-2504:47:00UTC - 2024-07-2505:47:00UTC`")
expect(service[:title]).to eq("Issue created from app.ads.ad_requests")
end
end
context 'when observability_links params are invalid JSON' do
before do
allow(Ability).to receive(:allowed?).and_call_original
allow(Ability).to receive(:allowed?).with(user, :read_observability, project).and_return(true)
end
# rubocop:disable Layout/LineLength -- urls with params will be too long
let(:params) do
{ observability_links: "thisisnotjson" }
end
# rubocop:enable Layout/LineLength
it { is_expected.to eq({}) }
end
end
end
end
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