airbrake-ruby 4.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/lib/airbrake-ruby.rb +513 -0
- data/lib/airbrake-ruby/async_sender.rb +142 -0
- data/lib/airbrake-ruby/backtrace.rb +196 -0
- data/lib/airbrake-ruby/benchmark.rb +39 -0
- data/lib/airbrake-ruby/code_hunk.rb +51 -0
- data/lib/airbrake-ruby/config.rb +229 -0
- data/lib/airbrake-ruby/config/validator.rb +91 -0
- data/lib/airbrake-ruby/deploy_notifier.rb +36 -0
- data/lib/airbrake-ruby/file_cache.rb +48 -0
- data/lib/airbrake-ruby/filter_chain.rb +95 -0
- data/lib/airbrake-ruby/filters/context_filter.rb +29 -0
- data/lib/airbrake-ruby/filters/dependency_filter.rb +31 -0
- data/lib/airbrake-ruby/filters/exception_attributes_filter.rb +46 -0
- data/lib/airbrake-ruby/filters/gem_root_filter.rb +33 -0
- data/lib/airbrake-ruby/filters/git_last_checkout_filter.rb +92 -0
- data/lib/airbrake-ruby/filters/git_repository_filter.rb +64 -0
- data/lib/airbrake-ruby/filters/git_revision_filter.rb +66 -0
- data/lib/airbrake-ruby/filters/keys_blacklist.rb +49 -0
- data/lib/airbrake-ruby/filters/keys_filter.rb +140 -0
- data/lib/airbrake-ruby/filters/keys_whitelist.rb +48 -0
- data/lib/airbrake-ruby/filters/root_directory_filter.rb +28 -0
- data/lib/airbrake-ruby/filters/sql_filter.rb +104 -0
- data/lib/airbrake-ruby/filters/system_exit_filter.rb +23 -0
- data/lib/airbrake-ruby/filters/thread_filter.rb +92 -0
- data/lib/airbrake-ruby/hash_keyable.rb +37 -0
- data/lib/airbrake-ruby/ignorable.rb +44 -0
- data/lib/airbrake-ruby/inspectable.rb +39 -0
- data/lib/airbrake-ruby/loggable.rb +34 -0
- data/lib/airbrake-ruby/monotonic_time.rb +43 -0
- data/lib/airbrake-ruby/nested_exception.rb +38 -0
- data/lib/airbrake-ruby/notice.rb +162 -0
- data/lib/airbrake-ruby/notice_notifier.rb +134 -0
- data/lib/airbrake-ruby/performance_breakdown.rb +45 -0
- data/lib/airbrake-ruby/performance_notifier.rb +125 -0
- data/lib/airbrake-ruby/promise.rb +109 -0
- data/lib/airbrake-ruby/query.rb +53 -0
- data/lib/airbrake-ruby/request.rb +45 -0
- data/lib/airbrake-ruby/response.rb +74 -0
- data/lib/airbrake-ruby/stashable.rb +15 -0
- data/lib/airbrake-ruby/stat.rb +73 -0
- data/lib/airbrake-ruby/sync_sender.rb +113 -0
- data/lib/airbrake-ruby/tdigest.rb +393 -0
- data/lib/airbrake-ruby/time_truncate.rb +17 -0
- data/lib/airbrake-ruby/timed_trace.rb +58 -0
- data/lib/airbrake-ruby/truncator.rb +115 -0
- data/lib/airbrake-ruby/version.rb +6 -0
- data/spec/airbrake_spec.rb +324 -0
- data/spec/async_sender_spec.rb +155 -0
- data/spec/backtrace_spec.rb +427 -0
- data/spec/benchmark_spec.rb +33 -0
- data/spec/code_hunk_spec.rb +115 -0
- data/spec/config/validator_spec.rb +184 -0
- data/spec/config_spec.rb +154 -0
- data/spec/deploy_notifier_spec.rb +48 -0
- data/spec/file_cache.rb +36 -0
- data/spec/filter_chain_spec.rb +92 -0
- data/spec/filters/context_filter_spec.rb +23 -0
- data/spec/filters/dependency_filter_spec.rb +12 -0
- data/spec/filters/exception_attributes_filter_spec.rb +50 -0
- data/spec/filters/gem_root_filter_spec.rb +41 -0
- data/spec/filters/git_last_checkout_filter_spec.rb +46 -0
- data/spec/filters/git_repository_filter.rb +61 -0
- data/spec/filters/git_revision_filter_spec.rb +126 -0
- data/spec/filters/keys_blacklist_spec.rb +225 -0
- data/spec/filters/keys_whitelist_spec.rb +194 -0
- data/spec/filters/root_directory_filter_spec.rb +39 -0
- data/spec/filters/sql_filter_spec.rb +219 -0
- data/spec/filters/system_exit_filter_spec.rb +14 -0
- data/spec/filters/thread_filter_spec.rb +277 -0
- data/spec/fixtures/notroot.txt +7 -0
- data/spec/fixtures/project_root/code.rb +221 -0
- data/spec/fixtures/project_root/empty_file.rb +0 -0
- data/spec/fixtures/project_root/long_line.txt +1 -0
- data/spec/fixtures/project_root/short_file.rb +3 -0
- data/spec/fixtures/project_root/vendor/bundle/ignored_file.rb +5 -0
- data/spec/helpers.rb +9 -0
- data/spec/ignorable_spec.rb +14 -0
- data/spec/inspectable_spec.rb +45 -0
- data/spec/monotonic_time_spec.rb +12 -0
- data/spec/nested_exception_spec.rb +73 -0
- data/spec/notice_notifier_spec.rb +356 -0
- data/spec/notice_notifier_spec/options_spec.rb +259 -0
- data/spec/notice_spec.rb +296 -0
- data/spec/performance_breakdown_spec.rb +12 -0
- data/spec/performance_notifier_spec.rb +435 -0
- data/spec/promise_spec.rb +197 -0
- data/spec/query_spec.rb +11 -0
- data/spec/request_spec.rb +11 -0
- data/spec/response_spec.rb +88 -0
- data/spec/spec_helper.rb +100 -0
- data/spec/stashable_spec.rb +23 -0
- data/spec/stat_spec.rb +47 -0
- data/spec/sync_sender_spec.rb +133 -0
- data/spec/tdigest_spec.rb +230 -0
- data/spec/time_truncate_spec.rb +13 -0
- data/spec/timed_trace_spec.rb +125 -0
- data/spec/truncator_spec.rb +238 -0
- metadata +213 -0
@@ -0,0 +1,134 @@
|
|
1
|
+
module Airbrake
|
2
|
+
# NoticeNotifier is reponsible for sending notices to Airbrake. It supports
|
3
|
+
# synchronous and asynchronous delivery.
|
4
|
+
#
|
5
|
+
# @see Airbrake::Config The list of options
|
6
|
+
# @since v1.0.0
|
7
|
+
# @api public
|
8
|
+
class NoticeNotifier
|
9
|
+
# @return [Array<Class>] filters to be executed first
|
10
|
+
DEFAULT_FILTERS = [
|
11
|
+
Airbrake::Filters::SystemExitFilter,
|
12
|
+
Airbrake::Filters::GemRootFilter
|
13
|
+
|
14
|
+
# Optional filters (must be included by users):
|
15
|
+
# Airbrake::Filters::ThreadFilter
|
16
|
+
].freeze
|
17
|
+
|
18
|
+
include Inspectable
|
19
|
+
include Loggable
|
20
|
+
|
21
|
+
def initialize
|
22
|
+
@config = Airbrake::Config.instance
|
23
|
+
@context = {}
|
24
|
+
@filter_chain = FilterChain.new
|
25
|
+
@async_sender = AsyncSender.new
|
26
|
+
@sync_sender = SyncSender.new
|
27
|
+
|
28
|
+
DEFAULT_FILTERS.each { |filter| add_filter(filter.new) }
|
29
|
+
|
30
|
+
add_filter(Airbrake::Filters::ContextFilter.new(@context))
|
31
|
+
add_filter(Airbrake::Filters::ExceptionAttributesFilter.new)
|
32
|
+
end
|
33
|
+
|
34
|
+
# @see Airbrake.notify
|
35
|
+
def notify(exception, params = {}, &block)
|
36
|
+
send_notice(exception, params, default_sender, &block)
|
37
|
+
end
|
38
|
+
|
39
|
+
# @see Airbrake.notify_sync
|
40
|
+
def notify_sync(exception, params = {}, &block)
|
41
|
+
send_notice(exception, params, @sync_sender, &block).value
|
42
|
+
end
|
43
|
+
|
44
|
+
# @see Airbrake.add_filte
|
45
|
+
def add_filter(filter = nil, &block)
|
46
|
+
@filter_chain.add_filter(block_given? ? block : filter)
|
47
|
+
end
|
48
|
+
|
49
|
+
# @see Airbrake.delete_filter
|
50
|
+
def delete_filter(filter_class)
|
51
|
+
@filter_chain.delete_filter(filter_class)
|
52
|
+
end
|
53
|
+
|
54
|
+
# @see Airbrake.build_notice
|
55
|
+
def build_notice(exception, params = {})
|
56
|
+
if @async_sender.closed?
|
57
|
+
raise Airbrake::Error,
|
58
|
+
"attempted to build #{exception} with closed Airbrake instance"
|
59
|
+
end
|
60
|
+
|
61
|
+
if exception.is_a?(Airbrake::Notice)
|
62
|
+
exception[:params].merge!(params)
|
63
|
+
exception
|
64
|
+
else
|
65
|
+
Notice.new(convert_to_exception(exception), params.dup)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# @see Airbrake.close
|
70
|
+
def close
|
71
|
+
@async_sender.close
|
72
|
+
end
|
73
|
+
|
74
|
+
# @see Airbrake.configured?
|
75
|
+
def configured?
|
76
|
+
@config.valid?
|
77
|
+
end
|
78
|
+
|
79
|
+
# @see Airbrake.merge_context
|
80
|
+
def merge_context(context)
|
81
|
+
@context.merge!(context)
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
def convert_to_exception(ex)
|
87
|
+
if ex.is_a?(Exception) || Backtrace.java_exception?(ex)
|
88
|
+
# Manually created exceptions don't have backtraces, so we create a fake
|
89
|
+
# one, whose first frame points to the place where Airbrake was called
|
90
|
+
# (normally via `notify`).
|
91
|
+
ex.set_backtrace(clean_backtrace) unless ex.backtrace
|
92
|
+
return ex
|
93
|
+
end
|
94
|
+
|
95
|
+
e = RuntimeError.new(ex.to_s)
|
96
|
+
e.set_backtrace(clean_backtrace)
|
97
|
+
e
|
98
|
+
end
|
99
|
+
|
100
|
+
def send_notice(exception, params, sender)
|
101
|
+
promise = @config.check_configuration
|
102
|
+
return promise if promise.rejected?
|
103
|
+
|
104
|
+
notice = build_notice(exception, params)
|
105
|
+
yield notice if block_given?
|
106
|
+
@filter_chain.refine(notice)
|
107
|
+
|
108
|
+
promise = Airbrake::Promise.new
|
109
|
+
return promise.reject("#{notice} was marked as ignored") if notice.ignored?
|
110
|
+
|
111
|
+
sender.send(notice, promise)
|
112
|
+
end
|
113
|
+
|
114
|
+
def default_sender
|
115
|
+
return @async_sender if @async_sender.has_workers?
|
116
|
+
|
117
|
+
logger.warn(
|
118
|
+
"#{LOG_LABEL} falling back to sync delivery because there are no " \
|
119
|
+
"running async workers"
|
120
|
+
)
|
121
|
+
@sync_sender
|
122
|
+
end
|
123
|
+
|
124
|
+
def clean_backtrace
|
125
|
+
caller_copy = Kernel.caller
|
126
|
+
clean_bt = caller_copy.drop_while { |frame| frame.include?('/lib/airbrake') }
|
127
|
+
|
128
|
+
# If true, then it's likely an internal library error. In this case return
|
129
|
+
# at least some backtrace to simplify debugging.
|
130
|
+
return caller_copy if clean_bt.empty?
|
131
|
+
clean_bt
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Airbrake
|
2
|
+
# PerformanceBreakdown holds data that shows how much time a request spent
|
3
|
+
# doing certaing subtasks such as (DB querying, view rendering, etc).
|
4
|
+
#
|
5
|
+
# @see Airbrake.notify_breakdown
|
6
|
+
# @api public
|
7
|
+
# @since v4.2.0
|
8
|
+
# rubocop:disable Metrics/BlockLength, Metrics/ParameterLists
|
9
|
+
PerformanceBreakdown = Struct.new(
|
10
|
+
:method, :route, :response_type, :groups, :start_time, :end_time
|
11
|
+
) do
|
12
|
+
include HashKeyable
|
13
|
+
include Ignorable
|
14
|
+
include Stashable
|
15
|
+
|
16
|
+
def initialize(
|
17
|
+
method:,
|
18
|
+
route:,
|
19
|
+
response_type:,
|
20
|
+
groups:,
|
21
|
+
start_time:,
|
22
|
+
end_time: Time.now
|
23
|
+
)
|
24
|
+
super(method, route, response_type, groups, start_time, end_time)
|
25
|
+
end
|
26
|
+
|
27
|
+
def destination
|
28
|
+
'routes-breakdowns'
|
29
|
+
end
|
30
|
+
|
31
|
+
def cargo
|
32
|
+
'routes'
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_h
|
36
|
+
{
|
37
|
+
'method' => method,
|
38
|
+
'route' => route,
|
39
|
+
'responseType' => response_type,
|
40
|
+
'time' => TimeTruncate.utc_truncate_minutes(start_time)
|
41
|
+
}.delete_if { |_key, val| val.nil? }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
# rubocop:enable Metrics/BlockLength, Metrics/ParameterLists
|
45
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
module Airbrake
|
2
|
+
# QueryNotifier aggregates information about SQL queries and periodically sends
|
3
|
+
# collected data to Airbrake.
|
4
|
+
#
|
5
|
+
# @api public
|
6
|
+
# @since v3.2.0
|
7
|
+
class PerformanceNotifier
|
8
|
+
include Inspectable
|
9
|
+
include Loggable
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@config = Airbrake::Config.instance
|
13
|
+
@flush_period = Airbrake::Config.instance.performance_stats_flush_period
|
14
|
+
@sender = SyncSender.new(:put)
|
15
|
+
@payload = {}
|
16
|
+
@schedule_flush = nil
|
17
|
+
@mutex = Mutex.new
|
18
|
+
@filter_chain = FilterChain.new
|
19
|
+
end
|
20
|
+
|
21
|
+
# @param [Hash] resource
|
22
|
+
# @see Airbrake.notify_query
|
23
|
+
# @see Airbrake.notify_request
|
24
|
+
def notify(resource)
|
25
|
+
promise = @config.check_configuration
|
26
|
+
return promise if promise.rejected?
|
27
|
+
|
28
|
+
promise = @config.check_performance_options(resource)
|
29
|
+
return promise if promise.rejected?
|
30
|
+
|
31
|
+
@filter_chain.refine(resource)
|
32
|
+
return if resource.ignored?
|
33
|
+
|
34
|
+
@mutex.synchronize do
|
35
|
+
update_payload(resource)
|
36
|
+
@flush_period > 0 ? schedule_flush(promise) : send(@payload, promise)
|
37
|
+
end
|
38
|
+
|
39
|
+
promise
|
40
|
+
end
|
41
|
+
|
42
|
+
# @see Airbrake.add_performance_filter
|
43
|
+
def add_filter(filter = nil, &block)
|
44
|
+
@filter_chain.add_filter(block_given? ? block : filter)
|
45
|
+
end
|
46
|
+
|
47
|
+
# @see Airbrake.delete_performance_filter
|
48
|
+
def delete_filter(filter_class)
|
49
|
+
@filter_chain.delete_filter(filter_class)
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def update_payload(resource)
|
55
|
+
@payload[resource] ||= { total: Airbrake::Stat.new }
|
56
|
+
@payload[resource][:total].increment(resource.start_time, resource.end_time)
|
57
|
+
|
58
|
+
resource.groups.each do |name, ms|
|
59
|
+
@payload[resource][name] ||= Airbrake::Stat.new
|
60
|
+
@payload[resource][name].increment_ms(ms)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def schedule_flush(promise)
|
65
|
+
@schedule_flush ||= Thread.new do
|
66
|
+
sleep(@flush_period)
|
67
|
+
|
68
|
+
payload = nil
|
69
|
+
@mutex.synchronize do
|
70
|
+
payload = @payload
|
71
|
+
@payload = {}
|
72
|
+
@schedule_flush = nil
|
73
|
+
end
|
74
|
+
|
75
|
+
send(payload, promise)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def send(payload, promise)
|
80
|
+
signature = "#{self.class.name}##{__method__}"
|
81
|
+
raise "#{signature}: payload (#{payload}) cannot be empty. Race?" if payload.none?
|
82
|
+
|
83
|
+
logger.debug { "#{LOG_LABEL} #{signature}: #{payload}" }
|
84
|
+
|
85
|
+
with_grouped_payload(payload) do |resource_hash, destination|
|
86
|
+
url = URI.join(
|
87
|
+
@config.host,
|
88
|
+
"api/v5/projects/#{@config.project_id}/#{destination}"
|
89
|
+
)
|
90
|
+
@sender.send(resource_hash, promise, url)
|
91
|
+
end
|
92
|
+
|
93
|
+
promise
|
94
|
+
end
|
95
|
+
|
96
|
+
def with_grouped_payload(raw_payload)
|
97
|
+
grouped_payload = raw_payload.group_by do |resource, _stats|
|
98
|
+
[resource.cargo, resource.destination]
|
99
|
+
end
|
100
|
+
|
101
|
+
grouped_payload.each do |(cargo, destination), resources|
|
102
|
+
payload = {}
|
103
|
+
payload[cargo] = serialize_resources(resources)
|
104
|
+
payload['environment'] = @config.environment if @config.environment
|
105
|
+
|
106
|
+
yield(payload, destination)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def serialize_resources(resources)
|
111
|
+
resources.map do |resource, stats|
|
112
|
+
resource_hash = resource.to_h.merge!(stats[:total].to_h)
|
113
|
+
|
114
|
+
if resource.groups.any?
|
115
|
+
group_stats = stats.reject { |name, _stat| name == :total }
|
116
|
+
resource_hash['groups'] = group_stats.merge(group_stats) do |_name, stat|
|
117
|
+
stat.to_h
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
resource_hash
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
module Airbrake
|
2
|
+
# Represents a simplified promise object (similar to promises found in
|
3
|
+
# JavaScript), which allows chaining callbacks that are executed when the
|
4
|
+
# promise is either resolved or rejected.
|
5
|
+
#
|
6
|
+
# @see https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise
|
7
|
+
# @see https://github.com/ruby-concurrency/concurrent-ruby/blob/master/lib/concurrent/promise.rb
|
8
|
+
# @since v1.7.0
|
9
|
+
class Promise
|
10
|
+
def initialize
|
11
|
+
@on_resolved = []
|
12
|
+
@on_rejected = []
|
13
|
+
@value = {}
|
14
|
+
@mutex = Mutex.new
|
15
|
+
end
|
16
|
+
|
17
|
+
# Attaches a callback to be executed when the promise is resolved.
|
18
|
+
#
|
19
|
+
# @example
|
20
|
+
# Airbrake::Promise.new.then { |response| puts response }
|
21
|
+
# #=> {"id"=>"00054415-8201-e9c6-65d6-fc4d231d2871",
|
22
|
+
# # "url"=>"http://localhost/locate/00054415-8201-e9c6-65d6-fc4d231d2871"}
|
23
|
+
#
|
24
|
+
# @yield [response]
|
25
|
+
# @yieldparam response [Hash<String,String>] Contains the `id` & `url` keys
|
26
|
+
# @return [self]
|
27
|
+
def then(&block)
|
28
|
+
@mutex.synchronize do
|
29
|
+
if @value.key?('ok')
|
30
|
+
yield(@value['ok'])
|
31
|
+
return self
|
32
|
+
end
|
33
|
+
|
34
|
+
@on_resolved << block
|
35
|
+
end
|
36
|
+
|
37
|
+
self
|
38
|
+
end
|
39
|
+
|
40
|
+
# Attaches a callback to be executed when the promise is rejected.
|
41
|
+
#
|
42
|
+
# @example
|
43
|
+
# Airbrake::Promise.new.rescue { |error| raise error }
|
44
|
+
#
|
45
|
+
# @yield [error] The error message from the API
|
46
|
+
# @yieldparam error [String]
|
47
|
+
# @return [self]
|
48
|
+
def rescue(&block)
|
49
|
+
@mutex.synchronize do
|
50
|
+
if @value.key?('error')
|
51
|
+
yield(@value['error'])
|
52
|
+
return self
|
53
|
+
end
|
54
|
+
|
55
|
+
@on_rejected << block
|
56
|
+
end
|
57
|
+
|
58
|
+
self
|
59
|
+
end
|
60
|
+
|
61
|
+
# @example
|
62
|
+
# Airbrake::Promise.new.resolve('id' => '123')
|
63
|
+
#
|
64
|
+
# @param reason [Object]
|
65
|
+
# @return [self]
|
66
|
+
def resolve(reason = 'resolved')
|
67
|
+
@mutex.synchronize do
|
68
|
+
@value['ok'] = reason
|
69
|
+
@on_resolved.each { |callback| callback.call(reason) }
|
70
|
+
end
|
71
|
+
|
72
|
+
self
|
73
|
+
end
|
74
|
+
|
75
|
+
# @example
|
76
|
+
# Airbrake::Promise.new.reject('Something went wrong')
|
77
|
+
#
|
78
|
+
# @param reason [String]
|
79
|
+
# @return [self]
|
80
|
+
def reject(reason = 'rejected')
|
81
|
+
@mutex.synchronize do
|
82
|
+
@value['error'] = reason
|
83
|
+
@on_rejected.each { |callback| callback.call(reason) }
|
84
|
+
end
|
85
|
+
|
86
|
+
self
|
87
|
+
end
|
88
|
+
|
89
|
+
# @return [Boolean]
|
90
|
+
def rejected?
|
91
|
+
@value.key?('error')
|
92
|
+
end
|
93
|
+
|
94
|
+
# @return [Boolean]
|
95
|
+
def resolved?
|
96
|
+
@value.key?('ok')
|
97
|
+
end
|
98
|
+
|
99
|
+
# @return [Hash<String,String>] either successful response containing the
|
100
|
+
# +id+ key or unsuccessful response containing the +error+ key
|
101
|
+
# @note This is a non-blocking call!
|
102
|
+
# @todo Get rid of this method and use an accessor. The resolved guard is
|
103
|
+
# needed for compatibility but it shouldn't exist in the future
|
104
|
+
def value
|
105
|
+
return @value['ok'] if resolved?
|
106
|
+
@value
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Airbrake
|
2
|
+
# Query holds SQL query data that powers SQL query collection.
|
3
|
+
#
|
4
|
+
# @see Airbrake.notify_query
|
5
|
+
# @api public
|
6
|
+
# @since v3.2.0
|
7
|
+
# rubocop:disable Metrics/ParameterLists, Metrics/BlockLength
|
8
|
+
Query = Struct.new(
|
9
|
+
:method, :route, :query, :func, :file, :line, :start_time, :end_time
|
10
|
+
) do
|
11
|
+
include HashKeyable
|
12
|
+
include Ignorable
|
13
|
+
include Stashable
|
14
|
+
|
15
|
+
def initialize(
|
16
|
+
method:,
|
17
|
+
route:,
|
18
|
+
query:,
|
19
|
+
func: nil,
|
20
|
+
file: nil,
|
21
|
+
line: nil,
|
22
|
+
start_time:,
|
23
|
+
end_time: Time.now
|
24
|
+
)
|
25
|
+
super(method, route, query, func, file, line, start_time, end_time)
|
26
|
+
end
|
27
|
+
|
28
|
+
def destination
|
29
|
+
'queries-stats'
|
30
|
+
end
|
31
|
+
|
32
|
+
def cargo
|
33
|
+
'queries'
|
34
|
+
end
|
35
|
+
|
36
|
+
def groups
|
37
|
+
{}
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_h
|
41
|
+
{
|
42
|
+
'method' => method,
|
43
|
+
'route' => route,
|
44
|
+
'query' => query,
|
45
|
+
'time' => TimeTruncate.utc_truncate_minutes(start_time),
|
46
|
+
'function' => func,
|
47
|
+
'file' => file,
|
48
|
+
'line' => line
|
49
|
+
}.delete_if { |_key, val| val.nil? }
|
50
|
+
end
|
51
|
+
# rubocop:enable Metrics/ParameterLists, Metrics/BlockLength
|
52
|
+
end
|
53
|
+
end
|