sentry-ruby 5.13.0 → 5.21.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/Gemfile +7 -18
- data/README.md +20 -10
- data/Rakefile +3 -1
- data/bin/console +2 -0
- data/lib/sentry/attachment.rb +40 -0
- data/lib/sentry/background_worker.rb +9 -2
- data/lib/sentry/backpressure_monitor.rb +45 -0
- data/lib/sentry/backtrace.rb +10 -8
- data/lib/sentry/baggage.rb +7 -7
- data/lib/sentry/breadcrumb/sentry_logger.rb +6 -6
- data/lib/sentry/check_in_event.rb +5 -5
- data/lib/sentry/client.rb +71 -18
- data/lib/sentry/configuration.rb +108 -32
- data/lib/sentry/core_ext/object/deep_dup.rb +1 -1
- data/lib/sentry/cron/configuration.rb +23 -0
- data/lib/sentry/cron/monitor_check_ins.rb +42 -26
- data/lib/sentry/cron/monitor_config.rb +1 -1
- data/lib/sentry/cron/monitor_schedule.rb +1 -1
- data/lib/sentry/dsn.rb +4 -4
- data/lib/sentry/envelope/item.rb +88 -0
- data/lib/sentry/envelope.rb +2 -68
- data/lib/sentry/error_event.rb +2 -2
- data/lib/sentry/event.rb +20 -46
- data/lib/sentry/faraday.rb +77 -0
- data/lib/sentry/graphql.rb +9 -0
- data/lib/sentry/hub.rb +25 -5
- data/lib/sentry/integrable.rb +4 -0
- data/lib/sentry/interface.rb +1 -0
- data/lib/sentry/interfaces/exception.rb +5 -3
- data/lib/sentry/interfaces/mechanism.rb +20 -0
- data/lib/sentry/interfaces/request.rb +7 -7
- data/lib/sentry/interfaces/single_exception.rb +10 -7
- data/lib/sentry/interfaces/stacktrace.rb +3 -1
- data/lib/sentry/interfaces/stacktrace_builder.rb +23 -2
- data/lib/sentry/logger.rb +1 -1
- data/lib/sentry/metrics/aggregator.rb +248 -0
- data/lib/sentry/metrics/configuration.rb +47 -0
- data/lib/sentry/metrics/counter_metric.rb +25 -0
- data/lib/sentry/metrics/distribution_metric.rb +25 -0
- data/lib/sentry/metrics/gauge_metric.rb +35 -0
- data/lib/sentry/metrics/local_aggregator.rb +53 -0
- data/lib/sentry/metrics/metric.rb +19 -0
- data/lib/sentry/metrics/set_metric.rb +28 -0
- data/lib/sentry/metrics/timing.rb +43 -0
- data/lib/sentry/metrics.rb +56 -0
- data/lib/sentry/net/http.rb +22 -39
- data/lib/sentry/profiler/helpers.rb +46 -0
- data/lib/sentry/profiler.rb +25 -56
- data/lib/sentry/propagation_context.rb +10 -9
- data/lib/sentry/puma.rb +1 -1
- data/lib/sentry/rack/capture_exceptions.rb +16 -4
- data/lib/sentry/rack.rb +2 -2
- data/lib/sentry/rake.rb +4 -15
- data/lib/sentry/redis.rb +2 -1
- data/lib/sentry/release_detector.rb +5 -5
- data/lib/sentry/scope.rb +48 -37
- data/lib/sentry/session.rb +2 -2
- data/lib/sentry/session_flusher.rb +7 -39
- data/lib/sentry/span.rb +46 -5
- data/lib/sentry/test_helper.rb +5 -2
- data/lib/sentry/threaded_periodic_worker.rb +39 -0
- data/lib/sentry/transaction.rb +27 -18
- data/lib/sentry/transaction_event.rb +6 -2
- data/lib/sentry/transport/configuration.rb +73 -1
- data/lib/sentry/transport/http_transport.rb +72 -41
- data/lib/sentry/transport/spotlight_transport.rb +50 -0
- data/lib/sentry/transport.rb +36 -41
- data/lib/sentry/utils/argument_checking_helper.rb +6 -0
- data/lib/sentry/utils/env_helper.rb +21 -0
- data/lib/sentry/utils/http_tracing.rb +41 -0
- data/lib/sentry/utils/logging_helper.rb +0 -4
- data/lib/sentry/utils/real_ip.rb +2 -2
- data/lib/sentry/utils/request_id.rb +1 -1
- data/lib/sentry/vernier/output.rb +89 -0
- data/lib/sentry/vernier/profiler.rb +125 -0
- data/lib/sentry/version.rb +1 -1
- data/lib/sentry-ruby.rb +61 -27
- data/sentry-ruby-core.gemspec +3 -1
- data/sentry-ruby.gemspec +15 -6
- metadata +47 -7
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "securerandom"
|
4
|
+
|
5
|
+
module Sentry
|
6
|
+
class Profiler
|
7
|
+
module Helpers
|
8
|
+
def in_app?(abs_path)
|
9
|
+
abs_path.match?(@in_app_pattern)
|
10
|
+
end
|
11
|
+
|
12
|
+
# copied from stacktrace.rb since I don't want to touch existing code
|
13
|
+
# TODO-neel-profiler try to fetch this from stackprof once we patch
|
14
|
+
# the native extension
|
15
|
+
def compute_filename(abs_path, in_app)
|
16
|
+
return nil if abs_path.nil?
|
17
|
+
|
18
|
+
under_project_root = @project_root && abs_path.start_with?(@project_root)
|
19
|
+
|
20
|
+
prefix =
|
21
|
+
if under_project_root && in_app
|
22
|
+
@project_root
|
23
|
+
else
|
24
|
+
longest_load_path = $LOAD_PATH.select { |path| abs_path.start_with?(path.to_s) }.max_by(&:size)
|
25
|
+
|
26
|
+
if under_project_root
|
27
|
+
longest_load_path || @project_root
|
28
|
+
else
|
29
|
+
longest_load_path
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
prefix ? abs_path[prefix.to_s.chomp(File::SEPARATOR).length + 1..-1] : abs_path
|
34
|
+
end
|
35
|
+
|
36
|
+
def split_module(name)
|
37
|
+
# last module plus class/instance method
|
38
|
+
i = name.rindex("::")
|
39
|
+
function = i ? name[(i + 2)..-1] : name
|
40
|
+
mod = i ? name[0...i] : nil
|
41
|
+
|
42
|
+
[function, mod]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/sentry/profiler.rb
CHANGED
@@ -1,11 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "securerandom"
|
4
|
+
require_relative "profiler/helpers"
|
4
5
|
|
5
6
|
module Sentry
|
6
7
|
class Profiler
|
7
|
-
|
8
|
-
|
8
|
+
include Profiler::Helpers
|
9
|
+
|
10
|
+
VERSION = "1"
|
11
|
+
PLATFORM = "ruby"
|
9
12
|
# 101 Hz in microseconds
|
10
13
|
DEFAULT_INTERVAL = 1e6 / 101
|
11
14
|
MICRO_TO_NANO_SECONDS = 1e3
|
@@ -14,14 +17,14 @@ module Sentry
|
|
14
17
|
attr_reader :sampled, :started, :event_id
|
15
18
|
|
16
19
|
def initialize(configuration)
|
17
|
-
@event_id = SecureRandom.uuid.delete(
|
20
|
+
@event_id = SecureRandom.uuid.delete("-")
|
18
21
|
@started = false
|
19
22
|
@sampled = nil
|
20
23
|
|
21
24
|
@profiling_enabled = defined?(StackProf) && configuration.profiling_enabled?
|
22
25
|
@profiles_sample_rate = configuration.profiles_sample_rate
|
23
26
|
@project_root = configuration.project_root
|
24
|
-
@app_dirs_pattern = configuration.app_dirs_pattern
|
27
|
+
@app_dirs_pattern = configuration.app_dirs_pattern
|
25
28
|
@in_app_pattern = Regexp.new("^(#{@project_root}/)?#{@app_dirs_pattern}")
|
26
29
|
end
|
27
30
|
|
@@ -33,7 +36,7 @@ module Sentry
|
|
33
36
|
raw: true,
|
34
37
|
aggregate: false)
|
35
38
|
|
36
|
-
@started ? log(
|
39
|
+
@started ? log("Started") : log("Not started since running elsewhere")
|
37
40
|
end
|
38
41
|
|
39
42
|
def stop
|
@@ -41,7 +44,11 @@ module Sentry
|
|
41
44
|
return unless @started
|
42
45
|
|
43
46
|
StackProf.stop
|
44
|
-
log(
|
47
|
+
log("Stopped")
|
48
|
+
end
|
49
|
+
|
50
|
+
def active_thread_id
|
51
|
+
"0"
|
45
52
|
end
|
46
53
|
|
47
54
|
# Sets initial sampling decision of the profile.
|
@@ -54,14 +61,14 @@ module Sentry
|
|
54
61
|
|
55
62
|
unless transaction_sampled
|
56
63
|
@sampled = false
|
57
|
-
log(
|
64
|
+
log("Discarding profile because transaction not sampled")
|
58
65
|
return
|
59
66
|
end
|
60
67
|
|
61
68
|
case @profiles_sample_rate
|
62
69
|
when 0.0
|
63
70
|
@sampled = false
|
64
|
-
log(
|
71
|
+
log("Discarding profile because sample_rate is 0")
|
65
72
|
return
|
66
73
|
when 1.0
|
67
74
|
@sampled = true
|
@@ -70,7 +77,7 @@ module Sentry
|
|
70
77
|
@sampled = Random.rand < @profiles_sample_rate
|
71
78
|
end
|
72
79
|
|
73
|
-
log(
|
80
|
+
log("Discarding profile due to sampling decision") unless @sampled
|
74
81
|
end
|
75
82
|
|
76
83
|
def to_hash
|
@@ -90,13 +97,12 @@ module Sentry
|
|
90
97
|
|
91
98
|
frame_map = {}
|
92
99
|
|
93
|
-
frames = results[:frames].
|
94
|
-
frame_id, frame_data = frame
|
95
|
-
|
100
|
+
frames = results[:frames].map.with_index do |(frame_id, frame_data), idx|
|
96
101
|
# need to map over stackprof frame ids to ours
|
97
102
|
frame_map[frame_id] = idx
|
98
103
|
|
99
104
|
file_path = frame_data[:file]
|
105
|
+
lineno = frame_data[:line]
|
100
106
|
in_app = in_app?(file_path)
|
101
107
|
filename = compute_filename(file_path, in_app)
|
102
108
|
function, mod = split_module(frame_data[:name])
|
@@ -109,7 +115,7 @@ module Sentry
|
|
109
115
|
}
|
110
116
|
|
111
117
|
frame_hash[:module] = mod if mod
|
112
|
-
frame_hash[:lineno] =
|
118
|
+
frame_hash[:lineno] = lineno if lineno && lineno >= 0
|
113
119
|
|
114
120
|
frame_hash
|
115
121
|
end
|
@@ -130,7 +136,7 @@ module Sentry
|
|
130
136
|
num_seen << results[:raw][idx + len]
|
131
137
|
idx += len + 1
|
132
138
|
|
133
|
-
log(
|
139
|
+
log("Unknown frame in stack") if stack.size != len
|
134
140
|
end
|
135
141
|
|
136
142
|
idx = 0
|
@@ -155,16 +161,16 @@ module Sentry
|
|
155
161
|
# Till then, on multi-threaded servers like puma, we will get frames from other active threads when the one
|
156
162
|
# we're profiling is idle/sleeping/waiting for IO etc.
|
157
163
|
# https://bugs.ruby-lang.org/issues/10602
|
158
|
-
thread_id:
|
164
|
+
thread_id: "0",
|
159
165
|
elapsed_since_start_ns: elapsed_since_start_ns.to_s
|
160
166
|
}
|
161
167
|
end
|
162
168
|
end
|
163
169
|
|
164
|
-
log(
|
170
|
+
log("Some samples thrown away") if samples.size != results[:samples]
|
165
171
|
|
166
172
|
if samples.size <= MIN_SAMPLES_REQUIRED
|
167
|
-
log(
|
173
|
+
log("Not enough samples, discarding profiler")
|
168
174
|
record_lost_event(:insufficient_data)
|
169
175
|
return {}
|
170
176
|
end
|
@@ -189,45 +195,8 @@ module Sentry
|
|
189
195
|
Sentry.logger.debug(LOGGER_PROGNAME) { "[Profiler] #{message}" }
|
190
196
|
end
|
191
197
|
|
192
|
-
def in_app?(abs_path)
|
193
|
-
abs_path.match?(@in_app_pattern)
|
194
|
-
end
|
195
|
-
|
196
|
-
# copied from stacktrace.rb since I don't want to touch existing code
|
197
|
-
# TODO-neel-profiler try to fetch this from stackprof once we patch
|
198
|
-
# the native extension
|
199
|
-
def compute_filename(abs_path, in_app)
|
200
|
-
return nil if abs_path.nil?
|
201
|
-
|
202
|
-
under_project_root = @project_root && abs_path.start_with?(@project_root)
|
203
|
-
|
204
|
-
prefix =
|
205
|
-
if under_project_root && in_app
|
206
|
-
@project_root
|
207
|
-
else
|
208
|
-
longest_load_path = $LOAD_PATH.select { |path| abs_path.start_with?(path.to_s) }.max_by(&:size)
|
209
|
-
|
210
|
-
if under_project_root
|
211
|
-
longest_load_path || @project_root
|
212
|
-
else
|
213
|
-
longest_load_path
|
214
|
-
end
|
215
|
-
end
|
216
|
-
|
217
|
-
prefix ? abs_path[prefix.to_s.chomp(File::SEPARATOR).length + 1..-1] : abs_path
|
218
|
-
end
|
219
|
-
|
220
|
-
def split_module(name)
|
221
|
-
# last module plus class/instance method
|
222
|
-
i = name.rindex('::')
|
223
|
-
function = i ? name[(i + 2)..-1] : name
|
224
|
-
mod = i ? name[0...i] : nil
|
225
|
-
|
226
|
-
[function, mod]
|
227
|
-
end
|
228
|
-
|
229
198
|
def record_lost_event(reason)
|
230
|
-
Sentry.get_current_client&.transport&.record_lost_event(reason,
|
199
|
+
Sentry.get_current_client&.transport&.record_lost_event(reason, "profile")
|
231
200
|
end
|
232
201
|
end
|
233
202
|
end
|
@@ -50,14 +50,15 @@ module Sentry
|
|
50
50
|
if sentry_trace_data
|
51
51
|
@trace_id, @parent_span_id, @parent_sampled = sentry_trace_data
|
52
52
|
|
53
|
-
@baggage =
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
53
|
+
@baggage =
|
54
|
+
if baggage_header && !baggage_header.empty?
|
55
|
+
Baggage.from_incoming_header(baggage_header)
|
56
|
+
else
|
57
|
+
# If there's an incoming sentry-trace but no incoming baggage header,
|
58
|
+
# for instance in traces coming from older SDKs,
|
59
|
+
# baggage will be empty and frozen and won't be populated as head SDK.
|
60
|
+
Baggage.new({})
|
61
|
+
end
|
61
62
|
|
62
63
|
@baggage.freeze!
|
63
64
|
@incoming_trace = true
|
@@ -107,7 +108,7 @@ module Sentry
|
|
107
108
|
end
|
108
109
|
|
109
110
|
# Returns the Dynamic Sampling Context from the baggage.
|
110
|
-
# @return [
|
111
|
+
# @return [Hash, nil]
|
111
112
|
def get_dynamic_sampling_context
|
112
113
|
get_baggage&.dynamic_sampling_context
|
113
114
|
end
|
data/lib/sentry/puma.rb
CHANGED
@@ -4,6 +4,8 @@ module Sentry
|
|
4
4
|
module Rack
|
5
5
|
class CaptureExceptions
|
6
6
|
ERROR_EVENT_ID_KEY = "sentry.error_event_id"
|
7
|
+
MECHANISM_TYPE = "rack"
|
8
|
+
SPAN_ORIGIN = "auto.http.rack"
|
7
9
|
|
8
10
|
def initialize(app)
|
9
11
|
@app = app
|
@@ -48,21 +50,27 @@ module Sentry
|
|
48
50
|
private
|
49
51
|
|
50
52
|
def collect_exception(env)
|
51
|
-
env[
|
53
|
+
env["rack.exception"] || env["sinatra.error"]
|
52
54
|
end
|
53
55
|
|
54
56
|
def transaction_op
|
55
|
-
"http.server"
|
57
|
+
"http.server"
|
56
58
|
end
|
57
59
|
|
58
60
|
def capture_exception(exception, env)
|
59
|
-
Sentry.capture_exception(exception).tap do |event|
|
61
|
+
Sentry.capture_exception(exception, hint: { mechanism: mechanism }).tap do |event|
|
60
62
|
env[ERROR_EVENT_ID_KEY] = event.event_id if event
|
61
63
|
end
|
62
64
|
end
|
63
65
|
|
64
66
|
def start_transaction(env, scope)
|
65
|
-
options = {
|
67
|
+
options = {
|
68
|
+
name: scope.transaction_name,
|
69
|
+
source: scope.transaction_source,
|
70
|
+
op: transaction_op,
|
71
|
+
origin: SPAN_ORIGIN
|
72
|
+
}
|
73
|
+
|
66
74
|
transaction = Sentry.continue_trace(env, **options)
|
67
75
|
Sentry.start_transaction(transaction: transaction, custom_sampling_context: { env: env }, **options)
|
68
76
|
end
|
@@ -74,6 +82,10 @@ module Sentry
|
|
74
82
|
transaction.set_http_status(status_code)
|
75
83
|
transaction.finish
|
76
84
|
end
|
85
|
+
|
86
|
+
def mechanism
|
87
|
+
Sentry::Mechanism.new(type: MECHANISM_TYPE, handled: false)
|
88
|
+
end
|
77
89
|
end
|
78
90
|
end
|
79
91
|
end
|
data/lib/sentry/rack.rb
CHANGED
data/lib/sentry/rake.rb
CHANGED
@@ -8,8 +8,10 @@ module Sentry
|
|
8
8
|
module Application
|
9
9
|
# @api private
|
10
10
|
def display_error_message(ex)
|
11
|
-
Sentry.
|
12
|
-
|
11
|
+
mechanism = Sentry::Mechanism.new(type: "rake", handled: false)
|
12
|
+
|
13
|
+
Sentry.capture_exception(ex, hint: { mechanism: mechanism }) do |scope|
|
14
|
+
task_name = top_level_tasks.join(" ")
|
13
15
|
scope.set_transaction_name(task_name, source: :task)
|
14
16
|
scope.set_tag("rake_task", task_name)
|
15
17
|
end if Sentry.initialized? && !Sentry.configuration.skip_rake_integration
|
@@ -17,15 +19,6 @@ module Sentry
|
|
17
19
|
super
|
18
20
|
end
|
19
21
|
end
|
20
|
-
|
21
|
-
module Task
|
22
|
-
# @api private
|
23
|
-
def execute(args=nil)
|
24
|
-
return super unless Sentry.initialized? && Sentry.get_current_hub
|
25
|
-
|
26
|
-
super
|
27
|
-
end
|
28
|
-
end
|
29
22
|
end
|
30
23
|
end
|
31
24
|
|
@@ -34,8 +27,4 @@ module Rake
|
|
34
27
|
class Application
|
35
28
|
prepend(Sentry::Rake::Application)
|
36
29
|
end
|
37
|
-
|
38
|
-
class Task
|
39
|
-
prepend(Sentry::Rake::Task)
|
40
|
-
end
|
41
30
|
end
|
data/lib/sentry/redis.rb
CHANGED
@@ -4,6 +4,7 @@ module Sentry
|
|
4
4
|
# @api private
|
5
5
|
class Redis
|
6
6
|
OP_NAME = "db.redis"
|
7
|
+
SPAN_ORIGIN = "auto.db.redis"
|
7
8
|
LOGGER_NAME = :redis_logger
|
8
9
|
|
9
10
|
def initialize(commands, host, port, db)
|
@@ -13,7 +14,7 @@ module Sentry
|
|
13
14
|
def instrument
|
14
15
|
return yield unless Sentry.initialized?
|
15
16
|
|
16
|
-
Sentry.with_child_span(op: OP_NAME, start_timestamp: Sentry.utc_now.to_f) do |span|
|
17
|
+
Sentry.with_child_span(op: OP_NAME, start_timestamp: Sentry.utc_now.to_f, origin: SPAN_ORIGIN) do |span|
|
17
18
|
yield.tap do
|
18
19
|
record_breadcrumb
|
19
20
|
|
@@ -13,12 +13,12 @@ module Sentry
|
|
13
13
|
|
14
14
|
def detect_release_from_heroku(running_on_heroku)
|
15
15
|
return unless running_on_heroku
|
16
|
-
ENV[
|
16
|
+
ENV["HEROKU_SLUG_COMMIT"]
|
17
17
|
end
|
18
18
|
|
19
19
|
def detect_release_from_capistrano(project_root)
|
20
|
-
revision_file = File.join(project_root,
|
21
|
-
revision_log = File.join(project_root,
|
20
|
+
revision_file = File.join(project_root, "REVISION")
|
21
|
+
revision_log = File.join(project_root, "..", "revisions.log")
|
22
22
|
|
23
23
|
if File.exist?(revision_file)
|
24
24
|
File.read(revision_file).strip
|
@@ -28,11 +28,11 @@ module Sentry
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def detect_release_from_git
|
31
|
-
Sentry.sys_command("git rev-parse
|
31
|
+
Sentry.sys_command("git rev-parse HEAD") if File.directory?(".git")
|
32
32
|
end
|
33
33
|
|
34
34
|
def detect_release_from_env
|
35
|
-
ENV[
|
35
|
+
ENV["SENTRY_RELEASE"]
|
36
36
|
end
|
37
37
|
end
|
38
38
|
end
|
data/lib/sentry/scope.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require "sentry/breadcrumb_buffer"
|
4
4
|
require "sentry/propagation_context"
|
5
|
+
require "sentry/attachment"
|
5
6
|
require "etc"
|
6
7
|
|
7
8
|
module Sentry
|
@@ -9,8 +10,8 @@ module Sentry
|
|
9
10
|
include ArgumentCheckingHelper
|
10
11
|
|
11
12
|
ATTRIBUTES = [
|
12
|
-
:
|
13
|
-
:
|
13
|
+
:transaction_name,
|
14
|
+
:transaction_source,
|
14
15
|
:contexts,
|
15
16
|
:extra,
|
16
17
|
:tags,
|
@@ -22,6 +23,7 @@ module Sentry
|
|
22
23
|
:rack_env,
|
23
24
|
:span,
|
24
25
|
:session,
|
26
|
+
:attachments,
|
25
27
|
:propagation_context
|
26
28
|
]
|
27
29
|
|
@@ -44,25 +46,28 @@ module Sentry
|
|
44
46
|
# @param hint [Hash] the hint data that'll be passed to event processors.
|
45
47
|
# @return [Event]
|
46
48
|
def apply_to_event(event, hint = nil)
|
47
|
-
event.
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
49
|
+
unless event.is_a?(CheckInEvent)
|
50
|
+
event.tags = tags.merge(event.tags)
|
51
|
+
event.user = user.merge(event.user)
|
52
|
+
event.extra = extra.merge(event.extra)
|
53
|
+
event.contexts = contexts.merge(event.contexts)
|
54
|
+
event.transaction = transaction_name if transaction_name
|
55
|
+
event.transaction_info = { source: transaction_source } if transaction_source
|
56
|
+
event.fingerprint = fingerprint
|
57
|
+
event.level = level
|
58
|
+
event.breadcrumbs = breadcrumbs
|
59
|
+
event.rack_env = rack_env if rack_env
|
60
|
+
event.attachments = attachments
|
61
|
+
end
|
53
62
|
|
54
63
|
if span
|
55
64
|
event.contexts[:trace] ||= span.get_trace_context
|
65
|
+
event.dynamic_sampling_context ||= span.get_dynamic_sampling_context
|
56
66
|
else
|
57
67
|
event.contexts[:trace] ||= propagation_context.get_trace_context
|
58
68
|
event.dynamic_sampling_context ||= propagation_context.get_dynamic_sampling_context
|
59
69
|
end
|
60
70
|
|
61
|
-
event.fingerprint = fingerprint
|
62
|
-
event.level = level
|
63
|
-
event.breadcrumbs = breadcrumbs
|
64
|
-
event.rack_env = rack_env if rack_env
|
65
|
-
|
66
71
|
all_event_processors = self.class.global_event_processors + @event_processors
|
67
72
|
|
68
73
|
unless all_event_processors.empty?
|
@@ -95,12 +100,13 @@ module Sentry
|
|
95
100
|
copy.extra = extra.deep_dup
|
96
101
|
copy.tags = tags.deep_dup
|
97
102
|
copy.user = user.deep_dup
|
98
|
-
copy.
|
99
|
-
copy.
|
103
|
+
copy.transaction_name = transaction_name.dup
|
104
|
+
copy.transaction_source = transaction_source.dup
|
100
105
|
copy.fingerprint = fingerprint.deep_dup
|
101
106
|
copy.span = span.deep_dup
|
102
107
|
copy.session = session.deep_dup
|
103
108
|
copy.propagation_context = propagation_context.deep_dup
|
109
|
+
copy.attachments = attachments.dup
|
104
110
|
copy
|
105
111
|
end
|
106
112
|
|
@@ -113,11 +119,12 @@ module Sentry
|
|
113
119
|
self.extra = scope.extra
|
114
120
|
self.tags = scope.tags
|
115
121
|
self.user = scope.user
|
116
|
-
self.
|
117
|
-
self.
|
122
|
+
self.transaction_name = scope.transaction_name
|
123
|
+
self.transaction_source = scope.transaction_source
|
118
124
|
self.fingerprint = scope.fingerprint
|
119
125
|
self.span = scope.span
|
120
126
|
self.propagation_context = scope.propagation_context
|
127
|
+
self.attachments = scope.attachments
|
121
128
|
end
|
122
129
|
|
123
130
|
# Updates the scope's data from the given options.
|
@@ -127,14 +134,17 @@ module Sentry
|
|
127
134
|
# @param user [Hash]
|
128
135
|
# @param level [String, Symbol]
|
129
136
|
# @param fingerprint [Array]
|
130
|
-
# @
|
137
|
+
# @param attachments [Array<Attachment>]
|
138
|
+
# @return [Array]
|
131
139
|
def update_from_options(
|
132
140
|
contexts: nil,
|
133
141
|
extra: nil,
|
134
142
|
tags: nil,
|
135
143
|
user: nil,
|
136
144
|
level: nil,
|
137
|
-
fingerprint: nil
|
145
|
+
fingerprint: nil,
|
146
|
+
attachments: nil,
|
147
|
+
**options
|
138
148
|
)
|
139
149
|
self.contexts.merge!(contexts) if contexts
|
140
150
|
self.extra.merge!(extra) if extra
|
@@ -142,6 +152,9 @@ module Sentry
|
|
142
152
|
self.user = user if user
|
143
153
|
self.level = level if level
|
144
154
|
self.fingerprint = fingerprint if fingerprint
|
155
|
+
|
156
|
+
# Returns unsupported option keys so we can notify users.
|
157
|
+
options.keys
|
145
158
|
end
|
146
159
|
|
147
160
|
# Sets the scope's rack_env attribute.
|
@@ -226,8 +239,8 @@ module Sentry
|
|
226
239
|
# @param transaction_name [String]
|
227
240
|
# @return [void]
|
228
241
|
def set_transaction_name(transaction_name, source: :custom)
|
229
|
-
@
|
230
|
-
@
|
242
|
+
@transaction_name = transaction_name
|
243
|
+
@transaction_source = source
|
231
244
|
end
|
232
245
|
|
233
246
|
# Sets the currently active session on the scope.
|
@@ -237,18 +250,10 @@ module Sentry
|
|
237
250
|
@session = session
|
238
251
|
end
|
239
252
|
|
240
|
-
#
|
241
|
-
#
|
242
|
-
|
243
|
-
|
244
|
-
@transaction_names.last
|
245
|
-
end
|
246
|
-
|
247
|
-
# Returns current transaction source.
|
248
|
-
# The "transaction" here does not refer to `Transaction` objects.
|
249
|
-
# @return [String, nil]
|
250
|
-
def transaction_source
|
251
|
-
@transaction_sources.last
|
253
|
+
# These are high cardinality and thus bad.
|
254
|
+
# @return [Boolean]
|
255
|
+
def transaction_source_low_quality?
|
256
|
+
transaction_source == :url
|
252
257
|
end
|
253
258
|
|
254
259
|
# Returns the associated Transaction object.
|
@@ -286,6 +291,12 @@ module Sentry
|
|
286
291
|
@propagation_context = PropagationContext.new(self, env)
|
287
292
|
end
|
288
293
|
|
294
|
+
# Add a new attachment to the scope.
|
295
|
+
def add_attachment(**opts)
|
296
|
+
attachments << (attachment = Attachment.new(**opts))
|
297
|
+
attachment
|
298
|
+
end
|
299
|
+
|
289
300
|
protected
|
290
301
|
|
291
302
|
# for duplicating scopes internally
|
@@ -294,18 +305,19 @@ module Sentry
|
|
294
305
|
private
|
295
306
|
|
296
307
|
def set_default_value
|
297
|
-
@contexts = { :
|
308
|
+
@contexts = { os: self.class.os_context, runtime: self.class.runtime_context }
|
298
309
|
@extra = {}
|
299
310
|
@tags = {}
|
300
311
|
@user = {}
|
301
312
|
@level = :error
|
302
313
|
@fingerprint = []
|
303
|
-
@
|
304
|
-
@
|
314
|
+
@transaction_name = nil
|
315
|
+
@transaction_source = nil
|
305
316
|
@event_processors = []
|
306
317
|
@rack_env = {}
|
307
318
|
@span = nil
|
308
319
|
@session = nil
|
320
|
+
@attachments = []
|
309
321
|
generate_propagation_context
|
310
322
|
set_new_breadcrumb_buffer
|
311
323
|
end
|
@@ -354,6 +366,5 @@ module Sentry
|
|
354
366
|
global_event_processors << block
|
355
367
|
end
|
356
368
|
end
|
357
|
-
|
358
369
|
end
|
359
370
|
end
|
data/lib/sentry/session.rb
CHANGED
@@ -5,8 +5,8 @@ module Sentry
|
|
5
5
|
attr_reader :started, :status, :aggregation_key
|
6
6
|
|
7
7
|
# TODO-neel add :crashed after adding handled mechanism
|
8
|
-
STATUSES = %i
|
9
|
-
AGGREGATE_STATUSES = %i
|
8
|
+
STATUSES = %i[ok errored exited]
|
9
|
+
AGGREGATE_STATUSES = %i[errored exited]
|
10
10
|
|
11
11
|
def initialize
|
12
12
|
@started = Sentry.utc_now
|