gitlab-qa 10.4.1 → 11.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/.gitlab/changelog_config.yml +13 -0
  3. data/.gitlab/merge_request_templates/Release.md +9 -36
  4. data/.rubocop_todo.yml +0 -12
  5. data/Dangerfile +1 -5
  6. data/Gemfile.lock +4 -4
  7. data/README.md +1 -2
  8. data/docs/running_against_remote_grid.md +39 -2
  9. data/gitlab-qa.gemspec +1 -1
  10. data/lib/gitlab/qa/component/gitaly_cluster.rb +0 -1
  11. data/lib/gitlab/qa/component/gitlab.rb +10 -9
  12. data/lib/gitlab/qa/component/selenoid.rb +8 -3
  13. data/lib/gitlab/qa/runtime/env.rb +21 -41
  14. data/lib/gitlab/qa/scenario/test/instance/airgapped.rb +0 -2
  15. data/lib/gitlab/qa/scenario/test/integration/gitaly_cluster.rb +0 -2
  16. data/lib/gitlab/qa/scenario/test/integration/mtls.rb +0 -1
  17. data/lib/gitlab/qa/scenario/test/integration/praefect.rb +0 -2
  18. data/lib/gitlab/qa/scenario/test/integration/registry_with_cdn.rb +2 -2
  19. data/lib/gitlab/qa/version.rb +1 -1
  20. data/lib/gitlab/qa.rb +0 -1
  21. data/support/data/admin_access_token_seed.rb +4 -1
  22. metadata +5 -39
  23. data/bin/slack +0 -14
  24. data/exe/gitlab-qa-report +0 -10
  25. data/lib/gitlab/qa/report/base_test_results.rb +0 -39
  26. data/lib/gitlab/qa/report/find_set_dri.rb +0 -43
  27. data/lib/gitlab/qa/report/generate_test_session.rb +0 -275
  28. data/lib/gitlab/qa/report/gitlab_issue_client.rb +0 -190
  29. data/lib/gitlab/qa/report/gitlab_issue_dry_client.rb +0 -28
  30. data/lib/gitlab/qa/report/j_unit_test_results.rb +0 -27
  31. data/lib/gitlab/qa/report/json_test_results.rb +0 -29
  32. data/lib/gitlab/qa/report/prepare_stage_reports.rb +0 -86
  33. data/lib/gitlab/qa/report/relate_failure_issue.rb +0 -374
  34. data/lib/gitlab/qa/report/report_as_issue.rb +0 -176
  35. data/lib/gitlab/qa/report/report_results.rb +0 -64
  36. data/lib/gitlab/qa/report/results_in_issues.rb +0 -126
  37. data/lib/gitlab/qa/report/results_in_testcases.rb +0 -111
  38. data/lib/gitlab/qa/report/results_reporter_shared.rb +0 -70
  39. data/lib/gitlab/qa/report/summary_table.rb +0 -43
  40. data/lib/gitlab/qa/report/test_result.rb +0 -184
  41. data/lib/gitlab/qa/report/update_screenshot_path.rb +0 -63
  42. data/lib/gitlab/qa/reporter.rb +0 -131
  43. data/lib/gitlab/qa/runtime/token_finder.rb +0 -44
  44. data/lib/gitlab/qa/slack/post_to_slack.rb +0 -30
  45. data/lib/gitlab/qa/system_logs/finders/json_log_finder.rb +0 -65
  46. data/lib/gitlab/qa/system_logs/finders/rails/api_log_finder.rb +0 -21
  47. data/lib/gitlab/qa/system_logs/finders/rails/application_log_finder.rb +0 -21
  48. data/lib/gitlab/qa/system_logs/finders/rails/exception_log_finder.rb +0 -21
  49. data/lib/gitlab/qa/system_logs/finders/rails/graphql_log_finder.rb +0 -21
  50. data/lib/gitlab/qa/system_logs/log_types/log.rb +0 -38
  51. data/lib/gitlab/qa/system_logs/log_types/rails/api_log.rb +0 -34
  52. data/lib/gitlab/qa/system_logs/log_types/rails/application_log.rb +0 -27
  53. data/lib/gitlab/qa/system_logs/log_types/rails/exception_log.rb +0 -23
  54. data/lib/gitlab/qa/system_logs/log_types/rails/graphql_log.rb +0 -30
  55. data/lib/gitlab/qa/system_logs/shared_fields.rb +0 -29
  56. data/lib/gitlab/qa/system_logs/system_logs_formatter.rb +0 -65
@@ -1,184 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'active_support/core_ext/object/blank'
4
-
5
- module Gitlab
6
- module QA
7
- module Report
8
- class TestResult
9
- def self.from_json(report)
10
- JsonTestResult.new(report)
11
- end
12
-
13
- def self.from_junit(report)
14
- JUnitTestResult.new(report)
15
- end
16
-
17
- attr_accessor :report, :failures
18
-
19
- def initialize(report)
20
- self.report = report
21
- self.failures = failures_from_exceptions
22
- end
23
-
24
- def stage
25
- @stage ||= file[%r{(?:api|browser_ui)/(?:(?:\d+_)?(\w+))}, 1]
26
- end
27
-
28
- def name
29
- raise NotImplementedError
30
- end
31
-
32
- def file
33
- raise NotImplementedError
34
- end
35
-
36
- def skipped
37
- raise NotImplementedError
38
- end
39
-
40
- private
41
-
42
- def failures_from_exceptions
43
- raise NotImplementedError
44
- end
45
-
46
- class JsonTestResult < TestResult
47
- def name
48
- report['full_description']
49
- end
50
-
51
- def file
52
- report['file_path']
53
- end
54
-
55
- def status
56
- report['status']
57
- end
58
-
59
- def ci_job_url
60
- report['ci_job_url']
61
- end
62
-
63
- def skipped
64
- status == 'pending'
65
- end
66
-
67
- def testcase
68
- report['testcase']
69
- end
70
-
71
- def testcase=(new_testcase)
72
- report['testcase'] = new_testcase
73
- end
74
-
75
- def failure_issue
76
- report['failure_issue']
77
- end
78
-
79
- def failure_issue=(new_failure_issue)
80
- report['failure_issue'] = new_failure_issue
81
- end
82
-
83
- def quarantine?
84
- # The value for 'quarantine' could be nil, a hash, a string,
85
- # or true (if the test just has the :quarantine tag)
86
- # But any non-nil or false value should means the test is in quarantine
87
- report['quarantine'].present?
88
- end
89
-
90
- def quarantine_type
91
- report['quarantine']['type'] if quarantine?
92
- end
93
-
94
- def quarantine_issue
95
- report['quarantine']['issue'] if quarantine?
96
- end
97
-
98
- def screenshot?
99
- report['screenshot'].present?
100
- end
101
-
102
- def failure_screenshot
103
- report['screenshot']['image'] if screenshot?
104
- end
105
-
106
- def product_group?
107
- report['product_group'].present?
108
- end
109
-
110
- def product_group
111
- report['product_group'] if product_group?
112
- end
113
-
114
- private
115
-
116
- # rubocop:disable Metrics/AbcSize
117
- def failures_from_exceptions
118
- return [] unless report.key?('exceptions')
119
-
120
- report['exceptions'].map do |exception|
121
- spec_file_first_index = exception['backtrace'].rindex do |line|
122
- line.include?(File.basename(report['file_path']))
123
- end
124
-
125
- exception['message'].gsub!(/(private_token=)[\w-]+/, '********')
126
- Array(exception['message_lines']).each { |line| line.gsub!(/(private_token=)([\w-]+)/, '********') }
127
-
128
- {
129
- 'message' => "#{exception['class']}: #{exception['message']}",
130
- 'message_lines' => exception['message_lines'],
131
- 'stacktrace' => "#{format_message_lines(exception['message_lines'])}\n#{exception['backtrace'].slice(0..spec_file_first_index).join("\n")}",
132
- 'correlation_id' => exception['correlation_id']
133
- }
134
- end
135
- end
136
-
137
- def format_message_lines(message_lines)
138
- message_lines.is_a?(Array) ? message_lines.join("\n") : message_lines
139
- end
140
- # rubocop:enable Metrics/AbcSize
141
- end
142
-
143
- class JUnitTestResult < TestResult
144
- def name
145
- report['name']
146
- end
147
-
148
- def file
149
- report['file']
150
- end
151
-
152
- def skipped
153
- report.search('skipped').any?
154
- end
155
-
156
- attr_accessor :testcase # Ignore it for now
157
-
158
- private
159
-
160
- # rubocop:disable Metrics/AbcSize
161
- def failures_from_exceptions
162
- failures = report.search('failure')
163
- return [] if failures.empty?
164
-
165
- failures.map do |exception|
166
- trace = exception.content.split("\n").map(&:strip)
167
- spec_file_first_index = trace.rindex do |line|
168
- line.include?(File.basename(report['file']))
169
- end
170
-
171
- exception['message'].gsub!(/(private_token=)[\w-]+/, '********')
172
-
173
- {
174
- 'message' => "#{exception['type']}: #{exception['message']}",
175
- 'stacktrace' => trace.slice(0..spec_file_first_index).join("\n")
176
- }
177
- end
178
- end
179
- # rubocop:enable Metrics/AbcSize
180
- end
181
- end
182
- end
183
- end
184
- end
@@ -1,63 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'nokogiri'
4
- require 'json'
5
- require 'active_support/core_ext/object/blank'
6
-
7
- module Gitlab
8
- module QA
9
- module Report
10
- class UpdateScreenshotPath
11
- def initialize(files:)
12
- @files = files
13
- end
14
-
15
- REGEX = %r{(?<gitlab_qa_run>gitlab-qa-run-.*?(?=\/))\/(?<gitlab_ce_ee_qa>gitlab-(ee|ce)-qa-.*?(?=\/))}
16
- CONTAINER_PATH = File.join(Docker::Volumes::QA_CONTAINER_WORKDIR, 'tmp').freeze
17
-
18
- def invoke!
19
- Dir.glob(@files).each do |rspec_report_file|
20
- match_data = rspec_report_file.match(REGEX)
21
- artifact_path = "#{match_data[:gitlab_qa_run]}/#{match_data[:gitlab_ce_ee_qa]}"
22
-
23
- xml_report = rewrite_each_xml_screenshot_path(rspec_report_file, artifact_path)
24
-
25
- File.write(rspec_report_file, xml_report)
26
-
27
- puts "Saved #{rspec_report_file}"
28
-
29
- json_rspec_report_file = rspec_report_file.gsub('.xml', '.json')
30
- json_report = rewrite_each_json_screenshot_path(json_rspec_report_file, artifact_path)
31
-
32
- File.write(json_rspec_report_file, json_report)
33
-
34
- puts "Saved #{json_rspec_report_file}"
35
- end
36
- end
37
-
38
- private
39
-
40
- def rewrite_each_xml_screenshot_path(rspec_report_file, artifact_path)
41
- report = Nokogiri::XML(File.open(rspec_report_file))
42
-
43
- report.xpath('//system-out').each do |system_out|
44
- system_out.content = system_out.content.gsub(CONTAINER_PATH, artifact_path)
45
- end
46
-
47
- report.to_s
48
- end
49
-
50
- def rewrite_each_json_screenshot_path(json_rspec_report_file, artifact_path)
51
- report = JSON.parse(File.read(json_rspec_report_file))
52
- examples = report['examples']
53
-
54
- examples.each do |example|
55
- example['screenshot']['image'] = example['screenshot']['image'].gsub(CONTAINER_PATH, artifact_path) if example['screenshot'].present?
56
- end
57
-
58
- JSON.pretty_generate(report)
59
- end
60
- end
61
- end
62
- end
63
- end
@@ -1,131 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'optparse'
4
-
5
- module Gitlab
6
- module QA
7
- class Reporter
8
- # rubocop:disable Metrics/AbcSize
9
- # rubocop:disable Metrics/PerceivedComplexity
10
- # rubocop:disable Metrics/CyclomaticComplexity
11
- def self.invoke(args)
12
- report_options = {}
13
- slack_options = {}
14
-
15
- options = OptionParser.new do |opts|
16
- opts.banner = 'Usage: gitlab-qa-reporter [options]'
17
-
18
- opts.on('--prepare-stage-reports FILES', 'Prepare separate reports for each Stage from the provided JUnit XML files') do |files|
19
- report_options[:prepare_stage_reports] = true
20
- report_options[:input_files] = files if files
21
- end
22
-
23
- opts.on('--report-results FILES', String, 'Report test results from JUnit XML files in GitLab test cases and results issues') do |files|
24
- report_options[:report_results] = true
25
- report_options[:input_files] = files if files
26
- end
27
-
28
- opts.on('--relate-failure-issue FILES', String, 'Relate test failures to failure issues from RSpec JSON files') do |files|
29
- report_options[:relate_failure_issue] = true
30
- report_options[:input_files] = files if files
31
- end
32
-
33
- opts.on('--max-diff-ratio DIFF_RATO', Float, 'Max stacktrace diff ratio for QA failure issues detection. Used by with --relate-failure-issue') do |value|
34
- report_options[:max_diff_ratio] = value
35
- end
36
-
37
- opts.on('-p', '--project PROJECT_ID', String, 'A valid project ID. Can be an integer or a group/project string. Required by --relate-failure-issue') do |value|
38
- report_options[:project] = value
39
- end
40
-
41
- opts.on('--results-issue-project RESULTS_ISSUE_PROJECT_ID', String, 'A valid project ID. Can be an integer or a group/project string. Required by --report-results') do |value|
42
- report_options[:results_issue_project] = value
43
- end
44
-
45
- opts.on('--test-case-project TEST_CASE_PROJECT_ID', String, 'A valid project ID. Can be an integer or a group/project string. Required by --report-results') do |value|
46
- report_options[:test_case_project] = value
47
- end
48
-
49
- opts.on('--generate-test-session FILES', String, 'Generate test session report') do |files|
50
- report_options[:generate_test_session] = true
51
- report_options[:input_files] = files if files
52
- end
53
-
54
- opts.on('-t', '--token ACCESS_TOKEN', String, 'A valid access token. Required by --report-results and --relate-failure-issue') do |value|
55
- report_options[:token] = value
56
- end
57
-
58
- opts.on('--post-to-slack MSG', 'Post message to slack') do |msg|
59
- slack_options[:post_to_slack] = true
60
- slack_options[:message] = msg
61
- end
62
-
63
- opts.on('--include-summary-table FILES', 'Create a results summary table to post to slack. To be used with --post-to-slack.') do |files|
64
- raise 'This option should be used with --post-to-slack.' unless slack_options[:post_to_slack]
65
-
66
- slack_options[:message] = slack_options[:message] + "\n\n" + Gitlab::QA::Report::SummaryTable.create(input_files: files)
67
- end
68
-
69
- opts.on('--include-system-log-errors FILES', String, 'Include errors from system logs in failure issues. To be used with --relate-failure-issue') do |files|
70
- raise 'This option should be used with --relate-failure-issue.' unless report_options[:relate_failure_issue]
71
-
72
- report_options[:system_logs] = files if files
73
- end
74
-
75
- opts.on('--update-screenshot-path FILES', "Update the path to screenshots to container's host") do |files|
76
- report_options[:update_screenshot_path] = true
77
- report_options[:files] = files
78
- end
79
-
80
- opts.on('--dry-run', "Perform a dry-run (don't create or update issues or test cases)") do |files|
81
- report_options[:dry_run] = true
82
- end
83
-
84
- opts.on_tail('-v', '--version', 'Show the version') do
85
- require 'gitlab/qa/version'
86
- puts "#{$PROGRAM_NAME} : #{VERSION}"
87
- exit
88
- end
89
-
90
- opts.on_tail('-h', '--help', 'Show the usage') do
91
- puts opts
92
- exit
93
- end
94
-
95
- opts.parse(args)
96
- end
97
-
98
- if args.any?
99
- if report_options.delete(:prepare_stage_reports)
100
- Gitlab::QA::Report::PrepareStageReports.new(**report_options).invoke!
101
-
102
- elsif report_options.delete(:relate_failure_issue)
103
- report_options[:token] = Runtime::TokenFinder.find_token!(report_options[:token])
104
- Gitlab::QA::Report::RelateFailureIssue.new(**report_options).invoke!
105
-
106
- elsif report_options.delete(:report_results)
107
- report_options[:token] = Runtime::TokenFinder.find_token!(report_options[:token])
108
- Gitlab::QA::Report::ReportResults.new(**report_options).invoke!
109
-
110
- elsif report_options.delete(:generate_test_session)
111
- report_options[:token] = Runtime::TokenFinder.find_token!(report_options[:token])
112
- Gitlab::QA::Report::GenerateTestSession.new(**report_options).invoke!
113
-
114
- elsif slack_options.delete(:post_to_slack)
115
- Gitlab::QA::Slack::PostToSlack.new(**slack_options).invoke!
116
-
117
- elsif report_options.delete(:update_screenshot_path)
118
- Gitlab::QA::Report::UpdateScreenshotPath.new(**report_options).invoke!
119
-
120
- end
121
- else
122
- puts options
123
- exit 1
124
- end
125
- end
126
- # rubocop:enable Metrics/CyclomaticComplexity
127
- # rubocop:enable Metrics/PerceivedComplexity
128
- # rubocop:enable Metrics/AbcSize
129
- end
130
- end
131
- end
@@ -1,44 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Gitlab
4
- module QA
5
- module Runtime
6
- class TokenFinder
7
- def self.find_token!(token, suffix: nil)
8
- new(token, suffix).find_token!
9
- end
10
-
11
- attr_reader :token, :suffix
12
-
13
- def initialize(token, suffix)
14
- @token = token
15
- @suffix = suffix
16
- end
17
-
18
- def find_token!
19
- find_token_from_attrs || find_token_from_env || find_token_from_file
20
- end
21
-
22
- def find_token_from_attrs
23
- token
24
- end
25
-
26
- def find_token_from_env
27
- Env.qa_access_token
28
- end
29
-
30
- def find_token_from_file
31
- @token_from_file ||= File.read(token_file_path).strip
32
- rescue Errno::ENOENT
33
- fail "Please provide a valid access token with the `-t/--token` option, the `GITLAB_QA_ACCESS_TOKEN` environment variable, or in the `#{token_file_path}` file!"
34
- end
35
-
36
- private
37
-
38
- def token_file_path
39
- @token_file_path ||= File.expand_path("../api_token#{"_#{suffix}" if suffix}", __dir__)
40
- end
41
- end
42
- end
43
- end
44
- end
@@ -1,30 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Gitlab
4
- module QA
5
- module Slack
6
- class PostToSlack
7
- def initialize(message:, icon_emoji: Runtime::Env.slack_icon_emoji, channel: Runtime::Env.slack_qa_channel)
8
- @channel = channel
9
- @message = message
10
- @icon_emoji = icon_emoji
11
- end
12
-
13
- def invoke!
14
- Runtime::Env.require_slack_qa_channel! unless @channel
15
- Runtime::Env.require_ci_slack_webhook_url!
16
-
17
- params = {}
18
- params['channel'] = @channel
19
- params['username'] = "GitLab QA Bot"
20
- params['icon_emoji'] = @icon_emoji
21
- params['text'] = @message
22
-
23
- url = Runtime::Env.ci_slack_webhook_url
24
-
25
- Support::HttpRequest.make_http_request(method: 'post', url: url, params: params, show_response: true)
26
- end
27
- end
28
- end
29
- end
30
- end
@@ -1,65 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'json'
4
-
5
- module Gitlab
6
- module QA
7
- module SystemLogs
8
- module Finders
9
- class JsonLogFinder
10
- def initialize(base_path, file_path)
11
- @base_path = base_path
12
- @file_path = file_path
13
- end
14
-
15
- def find(correlation_id)
16
- log_file_path = "#{@base_path}/#{@file_path}"
17
- logs = []
18
-
19
- if File.exist?(log_file_path) && !correlation_id.nil?
20
- File.foreach(log_file_path) do |line|
21
- begin
22
- json_line = JSON.parse(line, symbolize_names: true)
23
- rescue JSON::ParserError
24
- Runtime::Logger.debug("JsonLogFinder#find attempted to parse invalid JSON: #{line}")
25
-
26
- next
27
- end
28
-
29
- if (json_line[:correlation_id])&.casecmp?(correlation_id)
30
- normalized_line = normalize_keys(json_line)
31
- logs << new_log(normalized_line)
32
- end
33
- end
34
- end
35
-
36
- logs
37
- end
38
-
39
- def new_log(data)
40
- raise 'abstract method new_log must be defined!'
41
- end
42
-
43
- private
44
-
45
- def normalize_keys(json_line)
46
- normalized_hash = {}
47
-
48
- json_line.each_key do |old_key|
49
- key_string = old_key.to_s
50
-
51
- if key_string.include?('.')
52
- normalized_key = key_string.tr('.', '_').to_sym
53
- normalized_hash[normalized_key] = json_line[old_key]
54
- else
55
- normalized_hash[old_key] = json_line[old_key]
56
- end
57
- end
58
-
59
- normalized_hash
60
- end
61
- end
62
- end
63
- end
64
- end
65
- end
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Gitlab
4
- module QA
5
- module SystemLogs
6
- module Finders
7
- module Rails
8
- class ApiLogFinder < JsonLogFinder
9
- def initialize(base_path, file_path = 'gitlab-rails/api_json.log')
10
- super(base_path, file_path)
11
- end
12
-
13
- def new_log(data)
14
- LogTypes::Rails::ApiLog.new(data)
15
- end
16
- end
17
- end
18
- end
19
- end
20
- end
21
- end
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Gitlab
4
- module QA
5
- module SystemLogs
6
- module Finders
7
- module Rails
8
- class ApplicationLogFinder < JsonLogFinder
9
- def initialize(base_path, file_path = 'gitlab-rails/application_json.log')
10
- super(base_path, file_path)
11
- end
12
-
13
- def new_log(data)
14
- LogTypes::Rails::ApplicationLog.new(data)
15
- end
16
- end
17
- end
18
- end
19
- end
20
- end
21
- end
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Gitlab
4
- module QA
5
- module SystemLogs
6
- module Finders
7
- module Rails
8
- class ExceptionLogFinder < JsonLogFinder
9
- def initialize(base_path, file_path = 'gitlab-rails/exceptions_json.log')
10
- super(base_path, file_path)
11
- end
12
-
13
- def new_log(data)
14
- LogTypes::Rails::ExceptionLog.new(data)
15
- end
16
- end
17
- end
18
- end
19
- end
20
- end
21
- end
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Gitlab
4
- module QA
5
- module SystemLogs
6
- module Finders
7
- module Rails
8
- class GraphqlLogFinder < JsonLogFinder
9
- def initialize(base_path, file_path = 'gitlab-rails/graphql_json.log')
10
- super(base_path, file_path)
11
- end
12
-
13
- def new_log(data)
14
- LogTypes::Rails::GraphqlLog.new(data)
15
- end
16
- end
17
- end
18
- end
19
- end
20
- end
21
- end
@@ -1,38 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Gitlab
4
- module QA
5
- module SystemLogs
6
- module LogTypes
7
- class Log
8
- def initialize(name, data)
9
- @name = name
10
- @data = data
11
- end
12
-
13
- attr_reader :name, :data
14
-
15
- def summary_fields
16
- [
17
- :severity,
18
- :correlation_id,
19
- :time,
20
- :message
21
- ]
22
- end
23
-
24
- def summary
25
- summary = {}
26
-
27
- summary_fields.each do |field|
28
- value = data[field]
29
- summary[field] = value unless value.nil?
30
- end
31
-
32
- summary
33
- end
34
- end
35
- end
36
- end
37
- end
38
- end
@@ -1,34 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Gitlab
4
- module QA
5
- module SystemLogs
6
- module LogTypes
7
- module Rails
8
- class ApiLog < Log
9
- include SharedFields::Exception
10
- include SharedFields::Meta
11
-
12
- def initialize(data)
13
- super('Rails API', data)
14
- end
15
-
16
- def summary_fields
17
- super.concat(
18
- [
19
- :method,
20
- :path,
21
- :status,
22
- :params,
23
- :api_error
24
- ],
25
- exception_fields,
26
- meta_fields
27
- )
28
- end
29
- end
30
- end
31
- end
32
- end
33
- end
34
- end