sentry-ruby-core 4.8.0 → 5.2.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 +4 -4
- data/.yardopts +2 -0
- data/Gemfile +3 -0
- data/README.md +2 -0
- data/lib/sentry/background_worker.rb +33 -3
- data/lib/sentry/backtrace.rb +1 -3
- data/lib/sentry/breadcrumb/sentry_logger.rb +2 -0
- data/lib/sentry/breadcrumb.rb +24 -3
- data/lib/sentry/breadcrumb_buffer.rb +16 -0
- data/lib/sentry/client.rb +38 -2
- data/lib/sentry/configuration.rb +94 -41
- data/lib/sentry/core_ext/object/deep_dup.rb +2 -0
- data/lib/sentry/core_ext/object/duplicable.rb +1 -0
- data/lib/sentry/dsn.rb +2 -0
- data/lib/sentry/envelope.rb +45 -0
- data/lib/sentry/event.rb +55 -18
- data/lib/sentry/exceptions.rb +2 -0
- data/lib/sentry/hub.rb +38 -2
- data/lib/sentry/integrable.rb +2 -0
- data/lib/sentry/interface.rb +3 -10
- data/lib/sentry/interfaces/exception.rb +14 -3
- data/lib/sentry/interfaces/request.rb +37 -20
- data/lib/sentry/interfaces/single_exception.rb +2 -0
- data/lib/sentry/interfaces/stacktrace.rb +6 -0
- data/lib/sentry/interfaces/stacktrace_builder.rb +39 -10
- data/lib/sentry/interfaces/threads.rb +12 -2
- data/lib/sentry/linecache.rb +3 -0
- data/lib/sentry/net/http.rb +54 -65
- data/lib/sentry/rack/capture_exceptions.rb +28 -24
- data/lib/sentry/rack.rb +2 -0
- data/lib/sentry/rake.rb +16 -6
- data/lib/sentry/redis.rb +90 -0
- data/lib/sentry/release_detector.rb +3 -0
- data/lib/sentry/scope.rb +85 -6
- data/lib/sentry/session.rb +35 -0
- data/lib/sentry/session_flusher.rb +79 -0
- data/lib/sentry/span.rb +84 -8
- data/lib/sentry/transaction.rb +48 -14
- data/lib/sentry/transaction_event.rb +8 -0
- data/lib/sentry/transport/configuration.rb +3 -2
- data/lib/sentry/transport/dummy_transport.rb +8 -1
- data/lib/sentry/transport/http_transport.rb +55 -42
- data/lib/sentry/transport.rb +79 -37
- data/lib/sentry/utils/argument_checking_helper.rb +2 -0
- data/lib/sentry/utils/custom_inspection.rb +2 -0
- data/lib/sentry/utils/exception_cause_chain.rb +2 -0
- data/lib/sentry/utils/logging_helper.rb +6 -4
- data/lib/sentry/utils/real_ip.rb +2 -0
- data/lib/sentry/utils/request_id.rb +2 -0
- data/lib/sentry/version.rb +3 -1
- data/lib/sentry-ruby.rb +212 -41
- data/sentry-ruby-core.gemspec +0 -1
- data/sentry-ruby.gemspec +0 -1
- metadata +7 -16
data/lib/sentry/net/http.rb
CHANGED
@@ -1,9 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "net/http"
|
2
4
|
|
3
5
|
module Sentry
|
6
|
+
# @api private
|
4
7
|
module Net
|
5
8
|
module HTTP
|
6
|
-
OP_NAME = "
|
9
|
+
OP_NAME = "http.client"
|
10
|
+
BREADCRUMB_CATEGORY = "net.http"
|
7
11
|
|
8
12
|
# To explain how the entire thing works, we need to know how the original Net::HTTP#request works
|
9
13
|
# Here's part of its definition. As you can see, it usually calls itself inside a #start block
|
@@ -20,90 +24,67 @@ module Sentry
|
|
20
24
|
# end
|
21
25
|
# ```
|
22
26
|
#
|
23
|
-
# So
|
24
|
-
#
|
25
|
-
# 1. #request is called.
|
26
|
-
# - But because the request hasn't started yet, it calls #start (which then calls #do_start)
|
27
|
-
# - At this moment @sentry_span is still nil, so #set_sentry_trace_header returns early
|
28
|
-
# 2. #do_start then creates a new Span and assigns it to @sentry_span
|
29
|
-
# 3. #request is called for the second time.
|
30
|
-
# - This time @sentry_span should present. So #set_sentry_trace_header will set the sentry-trace header on the request object
|
31
|
-
# 4. Once the request finished, it
|
32
|
-
# - Records a breadcrumb if http_logger is set
|
33
|
-
# - Finishes the Span inside @sentry_span and clears the instance variable
|
34
|
-
#
|
27
|
+
# So we're only instrumenting request when `Net::HTTP` is already started
|
35
28
|
def request(req, body = nil, &block)
|
36
|
-
|
29
|
+
return super unless started?
|
30
|
+
|
31
|
+
sentry_span = start_sentry_span
|
32
|
+
set_sentry_trace_header(req, sentry_span)
|
37
33
|
|
38
34
|
super.tap do |res|
|
39
35
|
record_sentry_breadcrumb(req, res)
|
40
|
-
record_sentry_span(req, res)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
def do_start
|
45
|
-
super.tap do
|
46
|
-
start_sentry_span
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
def do_finish
|
51
|
-
super.tap do
|
52
|
-
finish_sentry_span
|
36
|
+
record_sentry_span(req, res, sentry_span)
|
53
37
|
end
|
54
38
|
end
|
55
39
|
|
56
40
|
private
|
57
41
|
|
58
|
-
def set_sentry_trace_header(req)
|
59
|
-
return unless
|
42
|
+
def set_sentry_trace_header(req, sentry_span)
|
43
|
+
return unless sentry_span
|
60
44
|
|
61
|
-
trace = Sentry.get_current_client.generate_sentry_trace(
|
45
|
+
trace = Sentry.get_current_client.generate_sentry_trace(sentry_span)
|
62
46
|
req[SENTRY_TRACE_HEADER_NAME] = trace if trace
|
63
47
|
end
|
64
48
|
|
65
49
|
def record_sentry_breadcrumb(req, res)
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
end
|
50
|
+
return unless Sentry.initialized? && Sentry.configuration.breadcrumbs_logger.include?(:http_logger)
|
51
|
+
return if from_sentry_sdk?
|
52
|
+
|
53
|
+
request_info = extract_request_info(req)
|
54
|
+
|
55
|
+
crumb = Sentry::Breadcrumb.new(
|
56
|
+
level: :info,
|
57
|
+
category: BREADCRUMB_CATEGORY,
|
58
|
+
type: :info,
|
59
|
+
data: {
|
60
|
+
status: res.code.to_i,
|
61
|
+
**request_info
|
62
|
+
}
|
63
|
+
)
|
64
|
+
Sentry.add_breadcrumb(crumb)
|
82
65
|
end
|
83
66
|
|
84
|
-
def record_sentry_span(req, res)
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
67
|
+
def record_sentry_span(req, res, sentry_span)
|
68
|
+
return unless Sentry.initialized? && sentry_span
|
69
|
+
|
70
|
+
request_info = extract_request_info(req)
|
71
|
+
sentry_span.set_description("#{request_info[:method]} #{request_info[:url]}")
|
72
|
+
sentry_span.set_data(:status, res.code.to_i)
|
73
|
+
finish_sentry_span(sentry_span)
|
90
74
|
end
|
91
75
|
|
92
76
|
def start_sentry_span
|
93
|
-
|
94
|
-
|
95
|
-
|
77
|
+
return unless Sentry.initialized? && transaction = Sentry.get_current_scope.get_transaction
|
78
|
+
return if from_sentry_sdk?
|
79
|
+
return if transaction.sampled == false
|
96
80
|
|
97
|
-
|
98
|
-
@sentry_span = child_span
|
99
|
-
end
|
81
|
+
transaction.start_child(op: OP_NAME, start_timestamp: Sentry.utc_now.to_f)
|
100
82
|
end
|
101
83
|
|
102
|
-
def finish_sentry_span
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
end
|
84
|
+
def finish_sentry_span(sentry_span)
|
85
|
+
return unless Sentry.initialized? && sentry_span
|
86
|
+
|
87
|
+
sentry_span.set_timestamp(Sentry.utc_now.to_f)
|
107
88
|
end
|
108
89
|
|
109
90
|
def from_sentry_sdk?
|
@@ -112,9 +93,17 @@ module Sentry
|
|
112
93
|
end
|
113
94
|
|
114
95
|
def extract_request_info(req)
|
115
|
-
uri = req.uri
|
96
|
+
uri = req.uri || URI.parse("#{use_ssl? ? 'https' : 'http'}://#{address}#{req.path}")
|
116
97
|
url = "#{uri.scheme}://#{uri.host}#{uri.path}" rescue uri.to_s
|
117
|
-
|
98
|
+
|
99
|
+
result = { method: req.method, url: url }
|
100
|
+
|
101
|
+
if Sentry.configuration.send_default_pii
|
102
|
+
result[:url] = result[:url] + "?#{uri.query}"
|
103
|
+
result[:body] = req.body
|
104
|
+
end
|
105
|
+
|
106
|
+
result
|
118
107
|
end
|
119
108
|
end
|
120
109
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Sentry
|
2
4
|
module Rack
|
3
5
|
class CaptureExceptions
|
@@ -12,30 +14,32 @@ module Sentry
|
|
12
14
|
Sentry.clone_hub_to_current_thread
|
13
15
|
|
14
16
|
Sentry.with_scope do |scope|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
17
|
+
Sentry.with_session_tracking do
|
18
|
+
scope.clear_breadcrumbs
|
19
|
+
scope.set_transaction_name(env["PATH_INFO"]) if env["PATH_INFO"]
|
20
|
+
scope.set_rack_env(env)
|
21
|
+
|
22
|
+
transaction = start_transaction(env, scope)
|
23
|
+
scope.set_span(transaction) if transaction
|
24
|
+
|
25
|
+
begin
|
26
|
+
response = @app.call(env)
|
27
|
+
rescue Sentry::Error
|
28
|
+
finish_transaction(transaction, 500)
|
29
|
+
raise # Don't capture Sentry errors
|
30
|
+
rescue Exception => e
|
31
|
+
capture_exception(e)
|
32
|
+
finish_transaction(transaction, 500)
|
33
|
+
raise
|
34
|
+
end
|
35
|
+
|
36
|
+
exception = collect_exception(env)
|
37
|
+
capture_exception(exception) if exception
|
38
|
+
|
39
|
+
finish_transaction(transaction, response[0])
|
40
|
+
|
41
|
+
response
|
31
42
|
end
|
32
|
-
|
33
|
-
exception = collect_exception(env)
|
34
|
-
capture_exception(exception) if exception
|
35
|
-
|
36
|
-
finish_transaction(transaction, response[0])
|
37
|
-
|
38
|
-
response
|
39
43
|
end
|
40
44
|
end
|
41
45
|
|
@@ -57,7 +61,7 @@ module Sentry
|
|
57
61
|
sentry_trace = env["HTTP_SENTRY_TRACE"]
|
58
62
|
options = { name: scope.transaction_name, op: transaction_op }
|
59
63
|
transaction = Sentry::Transaction.from_sentry_trace(sentry_trace, **options) if sentry_trace
|
60
|
-
Sentry.start_transaction(transaction: transaction, **options)
|
64
|
+
Sentry.start_transaction(transaction: transaction, custom_sampling_context: { env: env }, **options)
|
61
65
|
end
|
62
66
|
|
63
67
|
|
data/lib/sentry/rack.rb
CHANGED
data/lib/sentry/rake.rb
CHANGED
@@ -1,11 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "rake"
|
2
4
|
require "rake/task"
|
3
5
|
|
4
6
|
module Sentry
|
5
7
|
module Rake
|
6
8
|
module Application
|
9
|
+
# @api private
|
7
10
|
def display_error_message(ex)
|
8
|
-
Sentry.capture_exception(ex
|
11
|
+
Sentry.capture_exception(ex) do |scope|
|
9
12
|
task_name = top_level_tasks.join(' ')
|
10
13
|
scope.set_transaction_name(task_name)
|
11
14
|
scope.set_tag("rake_task", task_name)
|
@@ -16,16 +19,23 @@ module Sentry
|
|
16
19
|
end
|
17
20
|
|
18
21
|
module Task
|
22
|
+
# @api private
|
19
23
|
def execute(args=nil)
|
20
24
|
return super unless Sentry.initialized? && Sentry.get_current_hub
|
21
25
|
|
22
|
-
|
23
|
-
super
|
24
|
-
end
|
26
|
+
super
|
25
27
|
end
|
26
28
|
end
|
27
29
|
end
|
28
30
|
end
|
29
31
|
|
30
|
-
|
31
|
-
Rake
|
32
|
+
# @api private
|
33
|
+
module Rake
|
34
|
+
class Application
|
35
|
+
prepend(Sentry::Rake::Application)
|
36
|
+
end
|
37
|
+
|
38
|
+
class Task
|
39
|
+
prepend(Sentry::Rake::Task)
|
40
|
+
end
|
41
|
+
end
|
data/lib/sentry/redis.rb
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sentry
|
4
|
+
# @api private
|
5
|
+
class Redis
|
6
|
+
OP_NAME = "db.redis.command"
|
7
|
+
LOGGER_NAME = :redis_logger
|
8
|
+
|
9
|
+
def initialize(commands, host, port, db)
|
10
|
+
@commands, @host, @port, @db = commands, host, port, db
|
11
|
+
end
|
12
|
+
|
13
|
+
def instrument
|
14
|
+
return yield unless Sentry.initialized?
|
15
|
+
|
16
|
+
record_span do
|
17
|
+
yield.tap do
|
18
|
+
record_breadcrumb
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
attr_reader :commands, :host, :port, :db
|
26
|
+
|
27
|
+
def record_span
|
28
|
+
return yield unless (transaction = Sentry.get_current_scope.get_transaction) && transaction.sampled
|
29
|
+
|
30
|
+
sentry_span = transaction.start_child(op: OP_NAME, start_timestamp: Sentry.utc_now.to_f)
|
31
|
+
|
32
|
+
yield.tap do
|
33
|
+
sentry_span.set_description(commands_description)
|
34
|
+
sentry_span.set_data(:server, server_description)
|
35
|
+
sentry_span.set_timestamp(Sentry.utc_now.to_f)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def record_breadcrumb
|
40
|
+
return unless Sentry.configuration.breadcrumbs_logger.include?(LOGGER_NAME)
|
41
|
+
|
42
|
+
Sentry.add_breadcrumb(
|
43
|
+
Sentry::Breadcrumb.new(
|
44
|
+
level: :info,
|
45
|
+
category: OP_NAME,
|
46
|
+
type: :info,
|
47
|
+
data: {
|
48
|
+
commands: parsed_commands,
|
49
|
+
server: server_description
|
50
|
+
}
|
51
|
+
)
|
52
|
+
)
|
53
|
+
end
|
54
|
+
|
55
|
+
def commands_description
|
56
|
+
parsed_commands.map do |statement|
|
57
|
+
statement.values.join(" ").strip
|
58
|
+
end.join(", ")
|
59
|
+
end
|
60
|
+
|
61
|
+
def parsed_commands
|
62
|
+
commands.map do |statement|
|
63
|
+
command, key, *arguments = statement
|
64
|
+
|
65
|
+
{ command: command.to_s.upcase, key: key }.tap do |command_set|
|
66
|
+
command_set[:arguments] = arguments.join(" ") if Sentry.configuration.send_default_pii
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def server_description
|
72
|
+
"#{host}:#{port}/#{db}"
|
73
|
+
end
|
74
|
+
|
75
|
+
module Client
|
76
|
+
def logging(commands, &block)
|
77
|
+
Sentry::Redis.new(commands, host, port, db).instrument do
|
78
|
+
super
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
if defined?(::Redis::Client)
|
86
|
+
Sentry.register_patch do
|
87
|
+
patch = Sentry::Redis::Client
|
88
|
+
Redis::Client.prepend(patch) unless Redis::Client.ancestors.include?(patch)
|
89
|
+
end
|
90
|
+
end
|
data/lib/sentry/scope.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "sentry/breadcrumb_buffer"
|
2
4
|
require "etc"
|
3
5
|
|
@@ -5,19 +7,26 @@ module Sentry
|
|
5
7
|
class Scope
|
6
8
|
include ArgumentCheckingHelper
|
7
9
|
|
8
|
-
ATTRIBUTES = [:transaction_names, :contexts, :extra, :tags, :user, :level, :breadcrumbs, :fingerprint, :event_processors, :rack_env, :span]
|
10
|
+
ATTRIBUTES = [:transaction_names, :contexts, :extra, :tags, :user, :level, :breadcrumbs, :fingerprint, :event_processors, :rack_env, :span, :session]
|
9
11
|
|
10
12
|
attr_reader(*ATTRIBUTES)
|
11
13
|
|
14
|
+
# @param max_breadcrumbs [Integer] the maximum number of breadcrumbs to be stored in the scope.
|
12
15
|
def initialize(max_breadcrumbs: nil)
|
13
16
|
@max_breadcrumbs = max_breadcrumbs
|
14
17
|
set_default_value
|
15
18
|
end
|
16
19
|
|
20
|
+
# Resets the scope's attributes to defaults.
|
21
|
+
# @return [void]
|
17
22
|
def clear
|
18
23
|
set_default_value
|
19
24
|
end
|
20
25
|
|
26
|
+
# Applies stored attributes and event processors to the given event.
|
27
|
+
# @param event [Event]
|
28
|
+
# @param hint [Hash] the hint data that'll be passed to event processors.
|
29
|
+
# @return [Event]
|
21
30
|
def apply_to_event(event, hint = nil)
|
22
31
|
event.tags = tags.merge(event.tags)
|
23
32
|
event.user = user.merge(event.user)
|
@@ -43,14 +52,20 @@ module Sentry
|
|
43
52
|
event
|
44
53
|
end
|
45
54
|
|
55
|
+
# Adds the breadcrumb to the scope's breadcrumbs buffer.
|
56
|
+
# @param breadcrumb [Breadcrumb]
|
57
|
+
# @return [void]
|
46
58
|
def add_breadcrumb(breadcrumb)
|
47
59
|
breadcrumbs.record(breadcrumb)
|
48
60
|
end
|
49
61
|
|
62
|
+
# Clears the scope's breadcrumbs buffer
|
63
|
+
# @return [void]
|
50
64
|
def clear_breadcrumbs
|
51
65
|
set_new_breadcrumb_buffer
|
52
66
|
end
|
53
67
|
|
68
|
+
# @return [Scope]
|
54
69
|
def dup
|
55
70
|
copy = super
|
56
71
|
copy.breadcrumbs = breadcrumbs.dup
|
@@ -61,9 +76,13 @@ module Sentry
|
|
61
76
|
copy.transaction_names = transaction_names.deep_dup
|
62
77
|
copy.fingerprint = fingerprint.deep_dup
|
63
78
|
copy.span = span.deep_dup
|
79
|
+
copy.session = session.deep_dup
|
64
80
|
copy
|
65
81
|
end
|
66
82
|
|
83
|
+
# Updates the scope's data from a given scope.
|
84
|
+
# @param scope [Scope]
|
85
|
+
# @return [void]
|
67
86
|
def update_from_scope(scope)
|
68
87
|
self.breadcrumbs = scope.breadcrumbs
|
69
88
|
self.contexts = scope.contexts
|
@@ -75,6 +94,14 @@ module Sentry
|
|
75
94
|
self.span = scope.span
|
76
95
|
end
|
77
96
|
|
97
|
+
# Updates the scope's data from the given options.
|
98
|
+
# @param contexts [Hash]
|
99
|
+
# @param extras [Hash]
|
100
|
+
# @param tags [Hash]
|
101
|
+
# @param user [Hash]
|
102
|
+
# @param level [String, Symbol]
|
103
|
+
# @param fingerprint [Array]
|
104
|
+
# @return [void]
|
78
105
|
def update_from_options(
|
79
106
|
contexts: nil,
|
80
107
|
extra: nil,
|
@@ -91,75 +118,125 @@ module Sentry
|
|
91
118
|
self.fingerprint = fingerprint if fingerprint
|
92
119
|
end
|
93
120
|
|
121
|
+
# Sets the scope's rack_env attribute.
|
122
|
+
# @param env [Hash]
|
123
|
+
# @return [Hash]
|
94
124
|
def set_rack_env(env)
|
95
125
|
env = env || {}
|
96
126
|
@rack_env = env
|
97
127
|
end
|
98
128
|
|
129
|
+
# Sets the scope's span attribute.
|
130
|
+
# @param span [Span]
|
131
|
+
# @return [Span]
|
99
132
|
def set_span(span)
|
100
133
|
check_argument_type!(span, Span)
|
101
134
|
@span = span
|
102
135
|
end
|
103
136
|
|
137
|
+
# @!macro set_user
|
104
138
|
def set_user(user_hash)
|
105
139
|
check_argument_type!(user_hash, Hash)
|
106
140
|
@user = user_hash
|
107
141
|
end
|
108
142
|
|
143
|
+
# @!macro set_extras
|
109
144
|
def set_extras(extras_hash)
|
110
145
|
check_argument_type!(extras_hash, Hash)
|
111
146
|
@extra.merge!(extras_hash)
|
112
147
|
end
|
113
148
|
|
149
|
+
# Adds a new key-value pair to current extras.
|
150
|
+
# @param key [String, Symbol]
|
151
|
+
# @param value [Object]
|
152
|
+
# @return [Hash]
|
114
153
|
def set_extra(key, value)
|
115
|
-
|
154
|
+
set_extras(key => value)
|
116
155
|
end
|
117
156
|
|
157
|
+
# @!macro set_tags
|
118
158
|
def set_tags(tags_hash)
|
119
159
|
check_argument_type!(tags_hash, Hash)
|
120
160
|
@tags.merge!(tags_hash)
|
121
161
|
end
|
122
162
|
|
163
|
+
# Adds a new key-value pair to current tags.
|
164
|
+
# @param key [String, Symbol]
|
165
|
+
# @param value [Object]
|
166
|
+
# @return [Hash]
|
123
167
|
def set_tag(key, value)
|
124
|
-
|
168
|
+
set_tags(key => value)
|
125
169
|
end
|
126
170
|
|
171
|
+
# Updates the scope's contexts attribute by merging with the old value.
|
172
|
+
# @param contexts [Hash]
|
173
|
+
# @return [Hash]
|
127
174
|
def set_contexts(contexts_hash)
|
128
175
|
check_argument_type!(contexts_hash, Hash)
|
129
|
-
@contexts.merge!(contexts_hash)
|
176
|
+
@contexts.merge!(contexts_hash) do |key, old, new|
|
177
|
+
old.merge(new)
|
178
|
+
end
|
130
179
|
end
|
131
180
|
|
181
|
+
# @!macro set_context
|
132
182
|
def set_context(key, value)
|
133
183
|
check_argument_type!(value, Hash)
|
134
|
-
|
184
|
+
set_contexts(key => value)
|
135
185
|
end
|
136
186
|
|
187
|
+
# Sets the scope's level attribute.
|
188
|
+
# @param level [String, Symbol]
|
189
|
+
# @return [void]
|
137
190
|
def set_level(level)
|
138
191
|
@level = level
|
139
192
|
end
|
140
193
|
|
194
|
+
# Appends a new transaction name to the scope.
|
195
|
+
# The "transaction" here does not refer to `Transaction` objects.
|
196
|
+
# @param transaction_name [String]
|
197
|
+
# @return [void]
|
141
198
|
def set_transaction_name(transaction_name)
|
142
199
|
@transaction_names << transaction_name
|
143
200
|
end
|
144
201
|
|
202
|
+
# Sets the currently active session on the scope.
|
203
|
+
# @param session [Session, nil]
|
204
|
+
# @return [void]
|
205
|
+
def set_session(session)
|
206
|
+
@session = session
|
207
|
+
end
|
208
|
+
|
209
|
+
# Returns current transaction name.
|
210
|
+
# The "transaction" here does not refer to `Transaction` objects.
|
211
|
+
# @return [String, nil]
|
145
212
|
def transaction_name
|
146
213
|
@transaction_names.last
|
147
214
|
end
|
148
215
|
|
216
|
+
# Returns the associated Transaction object.
|
217
|
+
# @return [Transaction, nil]
|
149
218
|
def get_transaction
|
150
219
|
span.transaction if span
|
151
220
|
end
|
152
221
|
|
222
|
+
# Returns the associated Span object.
|
223
|
+
# @return [Span, nil]
|
153
224
|
def get_span
|
154
225
|
span
|
155
226
|
end
|
156
227
|
|
228
|
+
# Sets the scope's fingerprint attribute.
|
229
|
+
# @param fingerprint [Array]
|
230
|
+
# @return [Array]
|
157
231
|
def set_fingerprint(fingerprint)
|
158
232
|
check_argument_type!(fingerprint, Array)
|
159
233
|
|
160
234
|
@fingerprint = fingerprint
|
161
235
|
end
|
162
236
|
|
237
|
+
# Adds a new event processor [Proc] to the scope.
|
238
|
+
# @param block [Proc]
|
239
|
+
# @return [void]
|
163
240
|
def add_event_processor(&block)
|
164
241
|
@event_processors << block
|
165
242
|
end
|
@@ -182,6 +259,7 @@ module Sentry
|
|
182
259
|
@event_processors = []
|
183
260
|
@rack_env = {}
|
184
261
|
@span = nil
|
262
|
+
@session = nil
|
185
263
|
set_new_breadcrumb_buffer
|
186
264
|
end
|
187
265
|
|
@@ -189,8 +267,8 @@ module Sentry
|
|
189
267
|
@breadcrumbs = BreadcrumbBuffer.new(@max_breadcrumbs)
|
190
268
|
end
|
191
269
|
|
192
|
-
|
193
270
|
class << self
|
271
|
+
# @return [Hash]
|
194
272
|
def os_context
|
195
273
|
@os_context ||=
|
196
274
|
begin
|
@@ -204,6 +282,7 @@ module Sentry
|
|
204
282
|
end
|
205
283
|
end
|
206
284
|
|
285
|
+
# @return [Hash]
|
207
286
|
def runtime_context
|
208
287
|
@runtime_context ||= {
|
209
288
|
name: RbConfig::CONFIG["ruby_install_name"],
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sentry
|
4
|
+
class Session
|
5
|
+
attr_reader :started, :status
|
6
|
+
|
7
|
+
# TODO-neel add :crashed after adding handled mechanism
|
8
|
+
STATUSES = %i(ok errored exited)
|
9
|
+
AGGREGATE_STATUSES = %i(errored exited)
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@started = Sentry.utc_now
|
13
|
+
@status = :ok
|
14
|
+
end
|
15
|
+
|
16
|
+
# TODO-neel add :crashed after adding handled mechanism
|
17
|
+
def update_from_exception(_exception = nil)
|
18
|
+
@status = :errored
|
19
|
+
end
|
20
|
+
|
21
|
+
def close
|
22
|
+
@status = :exited if @status == :ok
|
23
|
+
end
|
24
|
+
|
25
|
+
# truncate seconds from the timestamp since we only care about
|
26
|
+
# minute level granularity for aggregation
|
27
|
+
def aggregation_key
|
28
|
+
Time.utc(started.year, started.month, started.day, started.hour, started.min)
|
29
|
+
end
|
30
|
+
|
31
|
+
def deep_dup
|
32
|
+
dup
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|