reportportal 0.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +674 -0
- data/LICENSE.LESSER +165 -0
- data/README.md +81 -0
- data/lib/report_portal/cucumber/formatter.rb +67 -0
- data/lib/report_portal/cucumber/json_slurper.rb +177 -0
- data/lib/report_portal/cucumber/parallel_formatter.rb +53 -0
- data/lib/report_portal/cucumber/parallel_report.rb +69 -0
- data/lib/report_portal/cucumber/report.rb +232 -0
- data/lib/report_portal/logging/log4r_outputter.rb +34 -0
- data/lib/report_portal/logging/logger.rb +54 -0
- data/lib/report_portal/logging/logging_appender.rb +36 -0
- data/lib/report_portal/patches/rest_client.rb +63 -0
- data/lib/report_portal/rspec/formatter.rb +130 -0
- data/lib/report_portal/settings.rb +76 -0
- data/lib/report_portal/tasks.rb +44 -0
- data/lib/report_portal/version.rb +21 -0
- data/lib/reportportal.rb +208 -0
- metadata +90 -0
@@ -0,0 +1,53 @@
|
|
1
|
+
# Copyright 2015 EPAM Systems
|
2
|
+
#
|
3
|
+
#
|
4
|
+
# This file is part of Report Portal.
|
5
|
+
#
|
6
|
+
# Report Portal is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU Lesser General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# ReportPortal is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU Lesser General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU Lesser General Public License
|
17
|
+
# along with Report Portal. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
|
19
|
+
require_relative 'formatter'
|
20
|
+
require_relative 'parallel_report'
|
21
|
+
require 'parallel_tests/gherkin/io'
|
22
|
+
|
23
|
+
module ReportPortal
|
24
|
+
module Cucumber
|
25
|
+
class ParallelFormatter < Formatter
|
26
|
+
#include ::ParallelTests::Gherkin::Io
|
27
|
+
|
28
|
+
# @api private
|
29
|
+
def initialize(config)
|
30
|
+
ENV['REPORT_PORTAL_USED'] = 'true'
|
31
|
+
|
32
|
+
@queue = Queue.new
|
33
|
+
@thread = Thread.new do
|
34
|
+
@report = ReportPortal::Cucumber::ParallelReport.new
|
35
|
+
loop do
|
36
|
+
method_arr = @queue.pop
|
37
|
+
@report.public_send(*method_arr)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
@thread.abort_on_exception = true
|
41
|
+
|
42
|
+
@io = config.out_stream
|
43
|
+
|
44
|
+
[:test_case_started, :test_case_finished, :test_step_started, :test_step_finished].each do |event_name|
|
45
|
+
config.on_event event_name do |event|
|
46
|
+
@queue.push([event_name, event, ReportPortal.now])
|
47
|
+
end
|
48
|
+
end
|
49
|
+
config.on_event :test_run_finished, &method(:on_test_run_finished)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# Copyright 2015 EPAM Systems
|
2
|
+
#
|
3
|
+
#
|
4
|
+
# This file is part of Report Portal.
|
5
|
+
#
|
6
|
+
# Report Portal is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU Lesser General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# ReportPortal is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU Lesser General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU Lesser General Public License
|
17
|
+
# along with Report Portal. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
|
19
|
+
require_relative 'report'
|
20
|
+
|
21
|
+
module ReportPortal
|
22
|
+
module Cucumber
|
23
|
+
class ParallelReport < Report
|
24
|
+
FILE_WITH_LAUNCH_ID = Pathname(Dir.tmpdir) + "parallel_launch_id_for_#{Process.ppid}.lck"
|
25
|
+
|
26
|
+
def parallel?
|
27
|
+
true
|
28
|
+
end
|
29
|
+
|
30
|
+
def initialize
|
31
|
+
@root_node = Tree::TreeNode.new('')
|
32
|
+
@last_used_time ||= 0
|
33
|
+
|
34
|
+
if ParallelTests.first_process?
|
35
|
+
File.open(FILE_WITH_LAUNCH_ID, 'w') do |f|
|
36
|
+
f.flock(File::LOCK_EX)
|
37
|
+
start_launch
|
38
|
+
f.write(ReportPortal.launch_id)
|
39
|
+
f.flush
|
40
|
+
f.flock(File::LOCK_UN)
|
41
|
+
end
|
42
|
+
else
|
43
|
+
File.open(FILE_WITH_LAUNCH_ID, 'r') do |f|
|
44
|
+
f.flock(File::LOCK_SH)
|
45
|
+
ReportPortal.launch_id = f.read
|
46
|
+
f.flock(File::LOCK_UN)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def done(desired_time = ReportPortal.now)
|
52
|
+
end_feature(desired_time) if @feature_node
|
53
|
+
|
54
|
+
if ParallelTests.first_process?
|
55
|
+
ParallelTests.wait_for_other_processes_to_finish
|
56
|
+
|
57
|
+
File.delete(FILE_WITH_LAUNCH_ID)
|
58
|
+
|
59
|
+
unless attach_to_launch?
|
60
|
+
$stdout.puts "Finishing launch #{ReportPortal.launch_id}"
|
61
|
+
ReportPortal.close_child_items(nil)
|
62
|
+
time_to_send = time_to_send(desired_time)
|
63
|
+
ReportPortal.finish_launch(time_to_send)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,232 @@
|
|
1
|
+
# Copyright 2015 EPAM Systems
|
2
|
+
#
|
3
|
+
#
|
4
|
+
# This file is part of Report Portal.
|
5
|
+
#
|
6
|
+
# Report Portal is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU Lesser General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# ReportPortal is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU Lesser General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU Lesser General Public License
|
17
|
+
# along with Report Portal. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
|
19
|
+
require 'cucumber/formatter/io'
|
20
|
+
require 'cucumber/formatter/hook_query_visitor'
|
21
|
+
require 'tree'
|
22
|
+
require 'securerandom'
|
23
|
+
|
24
|
+
require_relative '../../reportportal'
|
25
|
+
require_relative '../logging/logger'
|
26
|
+
|
27
|
+
module ReportPortal
|
28
|
+
module Cucumber
|
29
|
+
# @api private
|
30
|
+
class Report
|
31
|
+
def parallel?
|
32
|
+
false
|
33
|
+
end
|
34
|
+
|
35
|
+
def attach_to_launch?
|
36
|
+
ReportPortal::Settings.instance.formatter_modes.include?('attach_to_launch')
|
37
|
+
end
|
38
|
+
|
39
|
+
def initialize
|
40
|
+
@last_used_time = 0
|
41
|
+
@root_node = Tree::TreeNode.new('')
|
42
|
+
start_launch
|
43
|
+
end
|
44
|
+
|
45
|
+
def start_launch(desired_time = ReportPortal.now)
|
46
|
+
if attach_to_launch?
|
47
|
+
ReportPortal.launch_id =
|
48
|
+
if ReportPortal::Settings.instance.launch_id
|
49
|
+
ReportPortal::Settings.instance.launch_id
|
50
|
+
else
|
51
|
+
file_path = ReportPortal::Settings.instance.file_with_launch_id || (Pathname(Dir.tmpdir) + 'rp_launch_id.tmp')
|
52
|
+
File.read(file_path)
|
53
|
+
end
|
54
|
+
$stdout.puts "Attaching to launch #{ReportPortal.launch_id}"
|
55
|
+
else
|
56
|
+
description = ReportPortal::Settings.instance.description
|
57
|
+
description ||= ARGV.map { |arg| arg.gsub(/rp_uuid=.+/, "rp_uuid=[FILTERED]") }.join(' ')
|
58
|
+
ReportPortal.start_launch(description, time_to_send(desired_time))
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_case_started(event, desired_time = ReportPortal.now) # TODO: time should be a required argument
|
63
|
+
test_case = event.test_case
|
64
|
+
feature = test_case.feature
|
65
|
+
unless same_feature_as_previous_test_case?(feature)
|
66
|
+
end_feature(desired_time) if @feature_node
|
67
|
+
start_feature_with_parentage(feature, desired_time)
|
68
|
+
end
|
69
|
+
|
70
|
+
name = "#{test_case.keyword}: #{test_case.name}"
|
71
|
+
description = test_case.location.to_s
|
72
|
+
tags = test_case.tags.map(&:name)
|
73
|
+
type = :STEP
|
74
|
+
|
75
|
+
ReportPortal.current_scenario = ReportPortal::TestItem.new(name, type, nil, time_to_send(desired_time), description, false, tags)
|
76
|
+
scenario_node = Tree::TreeNode.new(SecureRandom.hex, ReportPortal.current_scenario)
|
77
|
+
@feature_node << scenario_node
|
78
|
+
ReportPortal.current_scenario.id = ReportPortal.start_item(scenario_node)
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_case_finished(event, desired_time = ReportPortal.now)
|
82
|
+
result = event.result
|
83
|
+
status = result.to_sym
|
84
|
+
issue = nil
|
85
|
+
if [:undefined, :pending].include?(status)
|
86
|
+
status = :failed
|
87
|
+
issue = result.message
|
88
|
+
end
|
89
|
+
ReportPortal.finish_item(ReportPortal.current_scenario, status, time_to_send(desired_time), issue)
|
90
|
+
ReportPortal.current_scenario = nil
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_step_started(event, desired_time = ReportPortal.now)
|
94
|
+
test_step = event.test_step
|
95
|
+
if step?(test_step) # `after_test_step` is also invoked for hooks
|
96
|
+
step_source = test_step.source.last
|
97
|
+
message = "-- #{step_source.keyword}#{step_source.text} --"
|
98
|
+
if step_source.multiline_arg.doc_string?
|
99
|
+
message << %(\n"""\n#{step_source.multiline_arg.content}\n""")
|
100
|
+
elsif step_source.multiline_arg.data_table?
|
101
|
+
message << step_source.multiline_arg.raw.reduce("\n") { |acc, row| acc << "| #{row.join(' | ')} |\n" }
|
102
|
+
end
|
103
|
+
ReportPortal.send_log(:trace, message, time_to_send(desired_time))
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_step_finished(event, desired_time = ReportPortal.now)
|
108
|
+
test_step = event.test_step
|
109
|
+
result = event.result
|
110
|
+
status = result.to_sym
|
111
|
+
|
112
|
+
if [:failed, :pending, :undefined].include?(status)
|
113
|
+
exception_info = if [:failed, :pending].include?(status)
|
114
|
+
ex = result.exception
|
115
|
+
sprintf("%s: %s\n %s", ex.class.name, ex.message, ex.backtrace.join("\n "))
|
116
|
+
else
|
117
|
+
sprintf("Undefined step: %s:\n%s", test_step.text, test_step.source.last.backtrace_line)
|
118
|
+
end
|
119
|
+
ReportPortal.send_log(:error, exception_info, time_to_send(desired_time))
|
120
|
+
end
|
121
|
+
|
122
|
+
if status != :passed
|
123
|
+
log_level = (status == :skipped)? :warn : :error
|
124
|
+
step_type = if step?(test_step)
|
125
|
+
'Step'
|
126
|
+
else
|
127
|
+
hook_class_name = test_step.source.last.class.name.split('::').last
|
128
|
+
location = test_step.location
|
129
|
+
"#{hook_class_name} at `#{location}`"
|
130
|
+
end
|
131
|
+
ReportPortal.send_log(log_level, "#{step_type} #{status}", time_to_send(desired_time))
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def done(desired_time = ReportPortal.now)
|
136
|
+
end_feature(desired_time) if @feature_node
|
137
|
+
|
138
|
+
unless attach_to_launch?
|
139
|
+
close_all_children_of(@root_node) # Folder items are closed here as they can't be closed after finishing a feature
|
140
|
+
time_to_send = time_to_send(desired_time)
|
141
|
+
ReportPortal.finish_launch(time_to_send)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def puts(message, desired_time = ReportPortal.now)
|
146
|
+
ReportPortal.send_log(:info, message, time_to_send(desired_time))
|
147
|
+
end
|
148
|
+
|
149
|
+
def embed(src, mime_type, label, desired_time = ReportPortal.now)
|
150
|
+
ReportPortal.send_file(:info, src, label, time_to_send(desired_time),mime_type)
|
151
|
+
end
|
152
|
+
|
153
|
+
private
|
154
|
+
|
155
|
+
# Report Portal sorts logs by time. However, several logs might have the same time.
|
156
|
+
# So to get Report Portal sort them properly the time should be different in all logs related to the same item.
|
157
|
+
# And thus it should be stored.
|
158
|
+
# Only the last time needs to be stored as:
|
159
|
+
# * only one test framework process/thread may send data for a single Report Portal item
|
160
|
+
# * that process/thread can't start the next test until it's done with the previous one
|
161
|
+
def time_to_send(desired_time)
|
162
|
+
time_to_send = desired_time
|
163
|
+
if time_to_send <= @last_used_time
|
164
|
+
time_to_send = @last_used_time + 1
|
165
|
+
end
|
166
|
+
@last_used_time = time_to_send
|
167
|
+
end
|
168
|
+
|
169
|
+
def same_feature_as_previous_test_case?(feature)
|
170
|
+
@feature_node && @feature_node.name == feature.location.file.split(File::SEPARATOR).last
|
171
|
+
end
|
172
|
+
|
173
|
+
def start_feature_with_parentage(feature, desired_time)
|
174
|
+
parent_node = @root_node
|
175
|
+
child_node = nil
|
176
|
+
path_components = feature.location.file.split(File::SEPARATOR)
|
177
|
+
path_components.each_with_index do |path_component, index|
|
178
|
+
child_node = parent_node[path_component]
|
179
|
+
unless child_node # if child node was not created yet
|
180
|
+
if index < path_components.size - 1
|
181
|
+
name = "Folder: #{path_component}"
|
182
|
+
description = nil
|
183
|
+
tags = []
|
184
|
+
type = :SUITE
|
185
|
+
else
|
186
|
+
name = "#{feature.keyword}: #{feature.name}"
|
187
|
+
description = feature.file # TODO: consider adding feature description and comments
|
188
|
+
tags = feature.tags.map(&:name)
|
189
|
+
type = :TEST
|
190
|
+
end
|
191
|
+
# TODO: multithreading # Parallel formatter always executes scenarios inside the same feature in the same process
|
192
|
+
if parallel? &&
|
193
|
+
index < path_components.size - 1 && # is folder?
|
194
|
+
(id_of_created_item = ReportPortal.item_id_of(name, parent_node)) # get id for folder from report portal
|
195
|
+
# get child id from other process
|
196
|
+
item = ReportPortal::TestItem.new(name, type, id_of_created_item, time_to_send(desired_time), description, false, tags)
|
197
|
+
child_node = Tree::TreeNode.new(path_component, item)
|
198
|
+
parent_node << child_node
|
199
|
+
else
|
200
|
+
item = ReportPortal::TestItem.new(name, type, nil, time_to_send(desired_time), description, false, tags)
|
201
|
+
child_node = Tree::TreeNode.new(path_component, item)
|
202
|
+
parent_node << child_node
|
203
|
+
item.id = ReportPortal.start_item(child_node) # TODO: multithreading
|
204
|
+
end
|
205
|
+
end
|
206
|
+
parent_node = child_node
|
207
|
+
end
|
208
|
+
@feature_node = child_node
|
209
|
+
end
|
210
|
+
|
211
|
+
def end_feature(desired_time)
|
212
|
+
ReportPortal.finish_item(@feature_node.content, nil, time_to_send(desired_time))
|
213
|
+
# Folder items can't be finished here because when the folder started we didn't track
|
214
|
+
# which features the folder contains.
|
215
|
+
# It's not easy to do it using Cucumber currently:
|
216
|
+
# https://github.com/cucumber/cucumber-ruby/issues/887
|
217
|
+
end
|
218
|
+
|
219
|
+
def close_all_children_of(root_node)
|
220
|
+
root_node.postordered_each do |node|
|
221
|
+
if !node.is_root? && !node.content.closed
|
222
|
+
ReportPortal.finish_item(node.content)
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
def step?(test_step)
|
228
|
+
!::Cucumber::Formatter::HookQueryVisitor.new(test_step).hook?
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# Copyright 2015 EPAM Systems
|
2
|
+
#
|
3
|
+
#
|
4
|
+
# This file is part of Report Portal.
|
5
|
+
#
|
6
|
+
# Report Portal is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU Lesser General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# ReportPortal is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU Lesser General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU Lesser General Public License
|
17
|
+
# along with Report Portal. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
|
19
|
+
require 'log4r/outputter/outputter'
|
20
|
+
|
21
|
+
require_relative '../../reportportal'
|
22
|
+
|
23
|
+
module ReportPortal
|
24
|
+
# Custom ReportPortal outputter for 'log4r' gem
|
25
|
+
class Log4rOutputter < Log4r::Outputter
|
26
|
+
def canonical_log(logevent)
|
27
|
+
synch { write(Log4r::LNAMES[logevent.level], format(logevent)) }
|
28
|
+
end
|
29
|
+
|
30
|
+
def write(level, data)
|
31
|
+
ReportPortal.send_log(level, data, ReportPortal.now)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# Copyright 2015 EPAM Systems
|
2
|
+
#
|
3
|
+
#
|
4
|
+
# This file is part of Report Portal.
|
5
|
+
#
|
6
|
+
# Report Portal is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU Lesser General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# ReportPortal is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU Lesser General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU Lesser General Public License
|
17
|
+
# along with Report Portal. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
|
19
|
+
require 'logger'
|
20
|
+
|
21
|
+
module ReportPortal
|
22
|
+
class << self
|
23
|
+
# Monkey-patch for built-in Logger class
|
24
|
+
def patch_logger
|
25
|
+
Logger.class_eval do
|
26
|
+
alias_method :orig_add, :add
|
27
|
+
alias_method :orig_write, :<<
|
28
|
+
def add(severity, message = nil, progname = nil, &block)
|
29
|
+
ret = orig_add(severity, message, progname, &block)
|
30
|
+
|
31
|
+
unless severity < @level
|
32
|
+
progname ||= @progname
|
33
|
+
if message.nil?
|
34
|
+
if block_given?
|
35
|
+
message = yield
|
36
|
+
else
|
37
|
+
message = progname
|
38
|
+
progname = @progname
|
39
|
+
end
|
40
|
+
end
|
41
|
+
ReportPortal.send_log(format_severity(severity), format_message(format_severity(severity), Time.now, progname, message.to_s), ReportPortal.now)
|
42
|
+
end
|
43
|
+
ret
|
44
|
+
end
|
45
|
+
|
46
|
+
def <<(msg)
|
47
|
+
ret = orig_write(msg)
|
48
|
+
ReportPortal.send_log(ReportPortal::LOG_LEVELS[:unknown], msg.to_s, ReportPortal.now)
|
49
|
+
ret
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# Copyright 2015 EPAM Systems
|
2
|
+
#
|
3
|
+
#
|
4
|
+
# This file is part of Report Portal.
|
5
|
+
#
|
6
|
+
# Report Portal is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU Lesser General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# ReportPortal is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU Lesser General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU Lesser General Public License
|
17
|
+
# along with Report Portal. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
|
19
|
+
require 'logging'
|
20
|
+
|
21
|
+
require_relative '../../reportportal'
|
22
|
+
|
23
|
+
module ReportPortal
|
24
|
+
# Custom ReportPortal appender for 'logging' gem
|
25
|
+
class LoggingAppender < ::Logging::Appender
|
26
|
+
def write(event)
|
27
|
+
(str, lvl) = if event.instance_of?(::Logging::LogEvent)
|
28
|
+
[layout.format(event), event.level]
|
29
|
+
else
|
30
|
+
[event.to_s, ReportPortal::LOG_LEVELS[:unknown]]
|
31
|
+
end
|
32
|
+
|
33
|
+
ReportPortal.send_log(lvl, str, ReportPortal.now)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|