sentry-ruby 0.3.0 → 4.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/README.md +102 -14
- metadata +41 -54
- data/.craft.yml +0 -19
- data/.gitignore +0 -11
- data/.rspec +0 -3
- data/.travis.yml +0 -6
- data/CHANGELOG.md +0 -31
- data/CODE_OF_CONDUCT.md +0 -74
- data/Gemfile +0 -16
- data/Rakefile +0 -8
- data/bin/console +0 -14
- data/bin/setup +0 -8
- data/lib/sentry/backtrace.rb +0 -128
- data/lib/sentry/benchmarks/benchmark_transport.rb +0 -14
- data/lib/sentry/breadcrumb/sentry_logger.rb +0 -87
- data/lib/sentry/breadcrumb.rb +0 -25
- data/lib/sentry/breadcrumb_buffer.rb +0 -47
- data/lib/sentry/client.rb +0 -80
- data/lib/sentry/configuration.rb +0 -387
- data/lib/sentry/core_ext/object/deep_dup.rb +0 -57
- data/lib/sentry/core_ext/object/duplicable.rb +0 -153
- data/lib/sentry/dsn.rb +0 -48
- data/lib/sentry/event.rb +0 -177
- data/lib/sentry/hub.rb +0 -137
- data/lib/sentry/interface.rb +0 -22
- data/lib/sentry/interfaces/exception.rb +0 -11
- data/lib/sentry/interfaces/request.rb +0 -95
- data/lib/sentry/interfaces/single_exception.rb +0 -14
- data/lib/sentry/interfaces/stacktrace.rb +0 -57
- data/lib/sentry/linecache.rb +0 -44
- data/lib/sentry/logger.rb +0 -20
- data/lib/sentry/rack/capture_exception.rb +0 -45
- data/lib/sentry/rack/tracing.rb +0 -39
- data/lib/sentry/rack.rb +0 -5
- data/lib/sentry/scope.rb +0 -214
- data/lib/sentry/span.rb +0 -155
- data/lib/sentry/transaction.rb +0 -113
- data/lib/sentry/transaction_event.rb +0 -29
- data/lib/sentry/transport/configuration.rb +0 -21
- data/lib/sentry/transport/dummy_transport.rb +0 -14
- data/lib/sentry/transport/http_transport.rb +0 -65
- data/lib/sentry/transport/state.rb +0 -40
- data/lib/sentry/transport.rb +0 -97
- data/lib/sentry/utils/exception_cause_chain.rb +0 -20
- data/lib/sentry/utils/real_ip.rb +0 -70
- data/lib/sentry/utils/request_id.rb +0 -16
- data/lib/sentry/version.rb +0 -3
- data/lib/sentry-ruby.rb +0 -123
- data/sentry-ruby.gemspec +0 -26
@@ -1,57 +0,0 @@
|
|
1
|
-
module Sentry
|
2
|
-
class StacktraceInterface < Interface
|
3
|
-
attr_accessor :frames
|
4
|
-
|
5
|
-
def to_hash
|
6
|
-
data = super
|
7
|
-
data[:frames] = data[:frames].map(&:to_hash)
|
8
|
-
data
|
9
|
-
end
|
10
|
-
|
11
|
-
# Not actually an interface, but I want to use the same style
|
12
|
-
class Frame < Interface
|
13
|
-
attr_accessor :abs_path, :context_line, :function, :in_app,
|
14
|
-
:lineno, :module, :pre_context, :post_context, :vars
|
15
|
-
|
16
|
-
def initialize(project_root)
|
17
|
-
@project_root = project_root
|
18
|
-
end
|
19
|
-
|
20
|
-
def filename
|
21
|
-
return if abs_path.nil?
|
22
|
-
return @filename if instance_variable_defined?(:@filename)
|
23
|
-
|
24
|
-
prefix =
|
25
|
-
if under_project_root? && in_app
|
26
|
-
@project_root
|
27
|
-
elsif under_project_root?
|
28
|
-
longest_load_path || @project_root
|
29
|
-
else
|
30
|
-
longest_load_path
|
31
|
-
end
|
32
|
-
|
33
|
-
@filename = prefix ? abs_path[prefix.to_s.chomp(File::SEPARATOR).length + 1..-1] : abs_path
|
34
|
-
end
|
35
|
-
|
36
|
-
def to_hash(*args)
|
37
|
-
data = super(*args)
|
38
|
-
data[:filename] = filename
|
39
|
-
data.delete(:vars) unless vars && !vars.empty?
|
40
|
-
data.delete(:pre_context) unless pre_context && !pre_context.empty?
|
41
|
-
data.delete(:post_context) unless post_context && !post_context.empty?
|
42
|
-
data.delete(:context_line) unless context_line && !context_line.empty?
|
43
|
-
data
|
44
|
-
end
|
45
|
-
|
46
|
-
private
|
47
|
-
|
48
|
-
def under_project_root?
|
49
|
-
@project_root && abs_path.start_with?(@project_root)
|
50
|
-
end
|
51
|
-
|
52
|
-
def longest_load_path
|
53
|
-
$LOAD_PATH.select { |path| abs_path.start_with?(path.to_s) }.max_by(&:size)
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
data/lib/sentry/linecache.rb
DELETED
@@ -1,44 +0,0 @@
|
|
1
|
-
module Sentry
|
2
|
-
class LineCache
|
3
|
-
def initialize
|
4
|
-
@cache = {}
|
5
|
-
end
|
6
|
-
|
7
|
-
# Any linecache you provide to Sentry must implement this method.
|
8
|
-
# Returns an Array of Strings representing the lines in the source
|
9
|
-
# file. The number of lines retrieved is (2 * context) + 1, the middle
|
10
|
-
# line should be the line requested by lineno. See specs for more information.
|
11
|
-
def get_file_context(filename, lineno, context)
|
12
|
-
return nil, nil, nil unless valid_path?(filename)
|
13
|
-
|
14
|
-
lines = Array.new(2 * context + 1) do |i|
|
15
|
-
getline(filename, lineno - context + i)
|
16
|
-
end
|
17
|
-
[lines[0..(context - 1)], lines[context], lines[(context + 1)..-1]]
|
18
|
-
end
|
19
|
-
|
20
|
-
private
|
21
|
-
|
22
|
-
def valid_path?(path)
|
23
|
-
lines = getlines(path)
|
24
|
-
!lines.nil?
|
25
|
-
end
|
26
|
-
|
27
|
-
def getlines(path)
|
28
|
-
@cache[path] ||= begin
|
29
|
-
IO.readlines(path)
|
30
|
-
rescue
|
31
|
-
nil
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def getline(path, n)
|
36
|
-
return nil if n < 1
|
37
|
-
|
38
|
-
lines = getlines(path)
|
39
|
-
return nil if lines.nil?
|
40
|
-
|
41
|
-
lines[n - 1]
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
data/lib/sentry/logger.rb
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'logger'
|
4
|
-
|
5
|
-
module Sentry
|
6
|
-
class Logger < ::Logger
|
7
|
-
LOG_PREFIX = "** [Sentry] "
|
8
|
-
PROGNAME = "sentry"
|
9
|
-
|
10
|
-
def initialize(*)
|
11
|
-
super
|
12
|
-
@level = ::Logger::INFO
|
13
|
-
original_formatter = ::Logger::Formatter.new
|
14
|
-
@default_formatter = proc do |severity, datetime, _progname, msg|
|
15
|
-
msg = "#{LOG_PREFIX}#{msg}"
|
16
|
-
original_formatter.call(severity, datetime, PROGNAME, msg)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
@@ -1,45 +0,0 @@
|
|
1
|
-
module Sentry
|
2
|
-
module Rack
|
3
|
-
class CaptureException
|
4
|
-
def initialize(app)
|
5
|
-
@app = app
|
6
|
-
end
|
7
|
-
|
8
|
-
def call(env)
|
9
|
-
# this call clones the main (global) hub
|
10
|
-
# and assigns it to the current thread's Sentry#get_current_hub
|
11
|
-
# it's essential for multi-thread servers (e.g. puma)
|
12
|
-
Sentry.clone_hub_to_current_thread unless Sentry.get_current_hub
|
13
|
-
# this call creates an isolated scope for every request
|
14
|
-
# it's essential for multi-process servers (e.g. unicorn)
|
15
|
-
Sentry.with_scope do |scope|
|
16
|
-
# there could be some breadcrumbs already stored in the top-level scope
|
17
|
-
# and for request information, we don't need those breadcrumbs
|
18
|
-
scope.clear_breadcrumbs
|
19
|
-
env['sentry.client'] = Sentry.get_current_client
|
20
|
-
|
21
|
-
scope.set_transaction_name(env["PATH_INFO"]) if env["PATH_INFO"]
|
22
|
-
scope.set_rack_env(env)
|
23
|
-
|
24
|
-
begin
|
25
|
-
response = @app.call(env)
|
26
|
-
rescue Sentry::Error
|
27
|
-
raise # Don't capture Sentry errors
|
28
|
-
rescue Exception => e
|
29
|
-
Sentry.capture_exception(e)
|
30
|
-
raise
|
31
|
-
end
|
32
|
-
|
33
|
-
exception = collect_exception(env)
|
34
|
-
Sentry.capture_exception(exception) if exception
|
35
|
-
|
36
|
-
response
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def collect_exception(env)
|
41
|
-
env['rack.exception'] || env['sinatra.error']
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
data/lib/sentry/rack/tracing.rb
DELETED
@@ -1,39 +0,0 @@
|
|
1
|
-
module Sentry
|
2
|
-
module Rack
|
3
|
-
class Tracing
|
4
|
-
def initialize(app)
|
5
|
-
@app = app
|
6
|
-
end
|
7
|
-
|
8
|
-
def call(env)
|
9
|
-
Sentry.clone_hub_to_current_thread unless Sentry.get_current_hub
|
10
|
-
|
11
|
-
if Sentry.configuration.traces_sample_rate.to_f == 0.0
|
12
|
-
return @app.call(env)
|
13
|
-
end
|
14
|
-
|
15
|
-
Sentry.with_scope do |scope|
|
16
|
-
scope.clear_breadcrumbs
|
17
|
-
scope.set_transaction_name(env["PATH_INFO"]) if env["PATH_INFO"]
|
18
|
-
span = Sentry.start_transaction(name: scope.transaction_name, op: "rack.request")
|
19
|
-
scope.set_span(span)
|
20
|
-
|
21
|
-
begin
|
22
|
-
response = @app.call(env)
|
23
|
-
rescue
|
24
|
-
finish_span(span, 500)
|
25
|
-
raise
|
26
|
-
end
|
27
|
-
|
28
|
-
finish_span(span, response[0])
|
29
|
-
response
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def finish_span(span, status_code)
|
34
|
-
span.set_http_status(status_code)
|
35
|
-
span.finish
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
data/lib/sentry/rack.rb
DELETED
data/lib/sentry/scope.rb
DELETED
@@ -1,214 +0,0 @@
|
|
1
|
-
require "sentry/breadcrumb_buffer"
|
2
|
-
require "etc"
|
3
|
-
|
4
|
-
module Sentry
|
5
|
-
class Scope
|
6
|
-
ATTRIBUTES = [:transaction_names, :contexts, :extra, :tags, :user, :level, :breadcrumbs, :fingerprint, :event_processors, :rack_env, :span]
|
7
|
-
|
8
|
-
attr_reader(*ATTRIBUTES)
|
9
|
-
|
10
|
-
def initialize
|
11
|
-
set_default_value
|
12
|
-
end
|
13
|
-
|
14
|
-
def clear
|
15
|
-
set_default_value
|
16
|
-
end
|
17
|
-
|
18
|
-
def apply_to_event(event, hint = nil)
|
19
|
-
event.tags = tags.merge(event.tags)
|
20
|
-
event.user = user.merge(event.user)
|
21
|
-
event.extra = extra.merge(event.extra)
|
22
|
-
event.contexts = contexts.merge(event.contexts)
|
23
|
-
|
24
|
-
if span
|
25
|
-
event.contexts[:trace] = span.get_trace_context
|
26
|
-
end
|
27
|
-
|
28
|
-
event.fingerprint = fingerprint
|
29
|
-
event.level = level
|
30
|
-
event.transaction = transaction_names.last
|
31
|
-
event.breadcrumbs = breadcrumbs
|
32
|
-
event.rack_env = rack_env
|
33
|
-
|
34
|
-
unless @event_processors.empty?
|
35
|
-
@event_processors.each do |processor_block|
|
36
|
-
event = processor_block.call(event, hint)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
event
|
41
|
-
end
|
42
|
-
|
43
|
-
def add_breadcrumb(breadcrumb)
|
44
|
-
breadcrumbs.record(breadcrumb)
|
45
|
-
end
|
46
|
-
|
47
|
-
def clear_breadcrumbs
|
48
|
-
@breadcrumbs = BreadcrumbBuffer.new
|
49
|
-
end
|
50
|
-
|
51
|
-
def dup
|
52
|
-
copy = super
|
53
|
-
copy.breadcrumbs = breadcrumbs.dup
|
54
|
-
copy.contexts = contexts.deep_dup
|
55
|
-
copy.extra = extra.deep_dup
|
56
|
-
copy.tags = tags.deep_dup
|
57
|
-
copy.user = user.deep_dup
|
58
|
-
copy.transaction_names = transaction_names.deep_dup
|
59
|
-
copy.fingerprint = fingerprint.deep_dup
|
60
|
-
copy.span = span
|
61
|
-
copy
|
62
|
-
end
|
63
|
-
|
64
|
-
def update_from_scope(scope)
|
65
|
-
self.breadcrumbs = scope.breadcrumbs
|
66
|
-
self.contexts = scope.contexts
|
67
|
-
self.extra = scope.extra
|
68
|
-
self.tags = scope.tags
|
69
|
-
self.user = scope.user
|
70
|
-
self.transaction_names = scope.transaction_names
|
71
|
-
self.fingerprint = scope.fingerprint
|
72
|
-
self.span = scope.span
|
73
|
-
end
|
74
|
-
|
75
|
-
def update_from_options(
|
76
|
-
contexts: nil,
|
77
|
-
extra: nil,
|
78
|
-
tags: nil,
|
79
|
-
user: nil,
|
80
|
-
level: nil,
|
81
|
-
fingerprint: nil
|
82
|
-
)
|
83
|
-
self.contexts.merge!(contexts) if contexts
|
84
|
-
self.extra.merge!(extra) if extra
|
85
|
-
self.tags.merge!(tags) if tags
|
86
|
-
self.user = user if user
|
87
|
-
self.level = level if level
|
88
|
-
self.fingerprint = fingerprint if fingerprint
|
89
|
-
end
|
90
|
-
|
91
|
-
def set_rack_env(env)
|
92
|
-
env = env || {}
|
93
|
-
@rack_env = env
|
94
|
-
end
|
95
|
-
|
96
|
-
def set_span(span)
|
97
|
-
check_argument_type!(span, Span)
|
98
|
-
@span = span
|
99
|
-
end
|
100
|
-
|
101
|
-
def set_user(user_hash)
|
102
|
-
check_argument_type!(user_hash, Hash)
|
103
|
-
@user = user_hash
|
104
|
-
end
|
105
|
-
|
106
|
-
def set_extras(extras_hash)
|
107
|
-
check_argument_type!(extras_hash, Hash)
|
108
|
-
@extra.merge!(extras_hash)
|
109
|
-
end
|
110
|
-
|
111
|
-
def set_extra(key, value)
|
112
|
-
@extra.merge!(key => value)
|
113
|
-
end
|
114
|
-
|
115
|
-
def set_tags(tags_hash)
|
116
|
-
check_argument_type!(tags_hash, Hash)
|
117
|
-
@tags.merge!(tags_hash)
|
118
|
-
end
|
119
|
-
|
120
|
-
def set_tag(key, value)
|
121
|
-
@tags.merge!(key => value)
|
122
|
-
end
|
123
|
-
|
124
|
-
def set_contexts(contexts_hash)
|
125
|
-
check_argument_type!(contexts_hash, Hash)
|
126
|
-
@contexts = contexts_hash
|
127
|
-
end
|
128
|
-
|
129
|
-
def set_context(key, value)
|
130
|
-
@contexts.merge!(key => value)
|
131
|
-
end
|
132
|
-
|
133
|
-
def set_level(level)
|
134
|
-
@level = level
|
135
|
-
end
|
136
|
-
|
137
|
-
def set_transaction_name(transaction_name)
|
138
|
-
@transaction_names << transaction_name
|
139
|
-
end
|
140
|
-
|
141
|
-
def transaction_name
|
142
|
-
@transaction_names.last
|
143
|
-
end
|
144
|
-
|
145
|
-
def get_transaction
|
146
|
-
# transaction will always be the first in the span_recorder
|
147
|
-
span.span_recorder.spans.first if span
|
148
|
-
end
|
149
|
-
|
150
|
-
def get_span
|
151
|
-
span
|
152
|
-
end
|
153
|
-
|
154
|
-
def set_fingerprint(fingerprint)
|
155
|
-
check_argument_type!(fingerprint, Array)
|
156
|
-
|
157
|
-
@fingerprint = fingerprint
|
158
|
-
end
|
159
|
-
|
160
|
-
def add_event_processor(&block)
|
161
|
-
@event_processors << block
|
162
|
-
end
|
163
|
-
|
164
|
-
protected
|
165
|
-
|
166
|
-
# for duplicating scopes internally
|
167
|
-
attr_writer(*ATTRIBUTES)
|
168
|
-
|
169
|
-
private
|
170
|
-
|
171
|
-
def check_argument_type!(argument, expected_type)
|
172
|
-
unless argument.is_a?(expected_type)
|
173
|
-
raise ArgumentError, "expect the argument to be a #{expected_type}, got #{argument.class} (#{argument})"
|
174
|
-
end
|
175
|
-
end
|
176
|
-
|
177
|
-
def set_default_value
|
178
|
-
@breadcrumbs = BreadcrumbBuffer.new
|
179
|
-
@contexts = { :os => self.class.os_context, :runtime => self.class.runtime_context }
|
180
|
-
@extra = {}
|
181
|
-
@tags = {}
|
182
|
-
@user = {}
|
183
|
-
@level = :error
|
184
|
-
@fingerprint = []
|
185
|
-
@transaction_names = []
|
186
|
-
@event_processors = []
|
187
|
-
@rack_env = {}
|
188
|
-
@span = nil
|
189
|
-
end
|
190
|
-
|
191
|
-
class << self
|
192
|
-
def os_context
|
193
|
-
@os_context ||=
|
194
|
-
begin
|
195
|
-
uname = Etc.uname
|
196
|
-
{
|
197
|
-
name: uname[:sysname] || RbConfig::CONFIG["host_os"],
|
198
|
-
version: uname[:version],
|
199
|
-
build: uname[:release],
|
200
|
-
kernel_version: uname[:version]
|
201
|
-
}
|
202
|
-
end
|
203
|
-
end
|
204
|
-
|
205
|
-
def runtime_context
|
206
|
-
@runtime_context ||= {
|
207
|
-
name: RbConfig::CONFIG["ruby_install_name"],
|
208
|
-
version: RUBY_DESCRIPTION || Sentry.sys_command("ruby -v")
|
209
|
-
}
|
210
|
-
end
|
211
|
-
end
|
212
|
-
|
213
|
-
end
|
214
|
-
end
|
data/lib/sentry/span.rb
DELETED
@@ -1,155 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require "securerandom"
|
3
|
-
|
4
|
-
module Sentry
|
5
|
-
class Span
|
6
|
-
STATUS_MAP = {
|
7
|
-
400 => "invalid_argument",
|
8
|
-
401 => "unauthenticated",
|
9
|
-
403 => "permission_denied",
|
10
|
-
404 => "not_found",
|
11
|
-
409 => "already_exists",
|
12
|
-
429 => "resource_exhausted",
|
13
|
-
499 => "cancelled",
|
14
|
-
500 => "internal_error",
|
15
|
-
501 => "unimplemented",
|
16
|
-
503 => "unavailable",
|
17
|
-
504 => "deadline_exceeded"
|
18
|
-
}
|
19
|
-
|
20
|
-
|
21
|
-
attr_reader :trace_id, :span_id, :parent_span_id, :sampled, :start_timestamp, :timestamp, :description, :op, :status, :tags, :data
|
22
|
-
attr_accessor :span_recorder
|
23
|
-
|
24
|
-
def initialize(description: nil, op: nil, status: nil, trace_id: nil, parent_span_id: nil, sampled: nil, start_timestamp: nil, timestamp: nil)
|
25
|
-
@trace_id = trace_id || SecureRandom.uuid.delete("-")
|
26
|
-
@span_id = SecureRandom.hex(8)
|
27
|
-
@parent_span_id = parent_span_id
|
28
|
-
@sampled = sampled
|
29
|
-
@start_timestamp = start_timestamp || Sentry.utc_now.to_f
|
30
|
-
@timestamp = timestamp
|
31
|
-
@description = description
|
32
|
-
@op = op
|
33
|
-
@status = status
|
34
|
-
@data = {}
|
35
|
-
@tags = {}
|
36
|
-
end
|
37
|
-
|
38
|
-
def set_span_recorder
|
39
|
-
@span_recorder = SpanRecorder.new(1000)
|
40
|
-
@span_recorder.add(self)
|
41
|
-
end
|
42
|
-
|
43
|
-
def finish
|
44
|
-
# already finished
|
45
|
-
return if @timestamp
|
46
|
-
|
47
|
-
@timestamp = Sentry.utc_now.to_f
|
48
|
-
self
|
49
|
-
end
|
50
|
-
|
51
|
-
def to_sentry_trace
|
52
|
-
sampled_flag = ""
|
53
|
-
sampled_flag = @sampled ? 1 : 0 unless @sampled.nil?
|
54
|
-
|
55
|
-
"#{@trace_id}-#{@span_id}-#{sampled_flag}"
|
56
|
-
end
|
57
|
-
|
58
|
-
def to_hash
|
59
|
-
{
|
60
|
-
trace_id: @trace_id,
|
61
|
-
span_id: @span_id,
|
62
|
-
parent_span_id: @parent_span_id,
|
63
|
-
start_timestamp: @start_timestamp,
|
64
|
-
timestamp: @timestamp,
|
65
|
-
description: @description,
|
66
|
-
op: @op,
|
67
|
-
status: @status,
|
68
|
-
tags: @tags,
|
69
|
-
data: @data
|
70
|
-
}
|
71
|
-
end
|
72
|
-
|
73
|
-
def get_trace_context
|
74
|
-
{
|
75
|
-
trace_id: @trace_id,
|
76
|
-
span_id: @span_id,
|
77
|
-
description: @description,
|
78
|
-
op: @op,
|
79
|
-
status: @status
|
80
|
-
}
|
81
|
-
end
|
82
|
-
|
83
|
-
def start_child(**options)
|
84
|
-
options = options.dup.merge(trace_id: @trace_id, parent_span_id: @span_id, sampled: @sampled)
|
85
|
-
child_span = Span.new(options)
|
86
|
-
child_span.span_recorder = @span_recorder
|
87
|
-
|
88
|
-
if @span_recorder && @sampled
|
89
|
-
@span_recorder.add(child_span)
|
90
|
-
end
|
91
|
-
|
92
|
-
child_span
|
93
|
-
end
|
94
|
-
|
95
|
-
def with_child_span(**options, &block)
|
96
|
-
child_span = start_child(**options)
|
97
|
-
|
98
|
-
yield(child_span)
|
99
|
-
|
100
|
-
child_span.finish
|
101
|
-
end
|
102
|
-
|
103
|
-
def set_op(op)
|
104
|
-
@op = op
|
105
|
-
end
|
106
|
-
|
107
|
-
def set_description(description)
|
108
|
-
@description = description
|
109
|
-
end
|
110
|
-
|
111
|
-
def set_status(status)
|
112
|
-
@status = status
|
113
|
-
end
|
114
|
-
|
115
|
-
def set_timestamp(timestamp)
|
116
|
-
@timestamp = timestamp
|
117
|
-
end
|
118
|
-
|
119
|
-
def set_http_status(status_code)
|
120
|
-
status_code = status_code.to_i
|
121
|
-
set_data("status_code", status_code)
|
122
|
-
|
123
|
-
status =
|
124
|
-
if status_code >= 200 && status_code < 299
|
125
|
-
"ok"
|
126
|
-
else
|
127
|
-
STATUS_MAP[status_code]
|
128
|
-
end
|
129
|
-
set_status(status)
|
130
|
-
end
|
131
|
-
|
132
|
-
def set_data(key, value)
|
133
|
-
@data[key] = value
|
134
|
-
end
|
135
|
-
|
136
|
-
def set_tag(key, value)
|
137
|
-
@tags[key] = value
|
138
|
-
end
|
139
|
-
|
140
|
-
class SpanRecorder
|
141
|
-
attr_reader :max_length, :spans
|
142
|
-
|
143
|
-
def initialize(max_length)
|
144
|
-
@max_length = max_length
|
145
|
-
@spans = []
|
146
|
-
end
|
147
|
-
|
148
|
-
def add(span)
|
149
|
-
if @spans.count < @max_length
|
150
|
-
@spans << span
|
151
|
-
end
|
152
|
-
end
|
153
|
-
end
|
154
|
-
end
|
155
|
-
end
|
data/lib/sentry/transaction.rb
DELETED
@@ -1,113 +0,0 @@
|
|
1
|
-
module Sentry
|
2
|
-
class Transaction < Span
|
3
|
-
SENTRY_TRACE_REGEXP = Regexp.new(
|
4
|
-
"^[ \t]*" + # whitespace
|
5
|
-
"([0-9a-f]{32})?" + # trace_id
|
6
|
-
"-?([0-9a-f]{16})?" + # span_id
|
7
|
-
"-?([01])?" + # sampled
|
8
|
-
"[ \t]*$" # whitespace
|
9
|
-
)
|
10
|
-
UNLABELD_NAME = "<unlabeled transaction>".freeze
|
11
|
-
MESSAGE_PREFIX = "[Tracing]"
|
12
|
-
|
13
|
-
attr_reader :name, :parent_sampled
|
14
|
-
|
15
|
-
def initialize(name: nil, parent_sampled: nil, **options)
|
16
|
-
super(**options)
|
17
|
-
|
18
|
-
@name = name
|
19
|
-
@parent_sampled = parent_sampled
|
20
|
-
set_span_recorder
|
21
|
-
end
|
22
|
-
|
23
|
-
def self.from_sentry_trace(sentry_trace, **options)
|
24
|
-
return unless sentry_trace
|
25
|
-
|
26
|
-
match = SENTRY_TRACE_REGEXP.match(sentry_trace)
|
27
|
-
trace_id, parent_span_id, sampled_flag = match[1..3]
|
28
|
-
|
29
|
-
sampled = sampled_flag != "0"
|
30
|
-
|
31
|
-
new(trace_id: trace_id, parent_span_id: parent_span_id, parent_sampled: sampled, **options)
|
32
|
-
end
|
33
|
-
|
34
|
-
def to_hash
|
35
|
-
hash = super
|
36
|
-
hash.merge!(name: @name, sampled: @sampled, parent_sampled: @parent_sampled)
|
37
|
-
hash
|
38
|
-
end
|
39
|
-
|
40
|
-
def set_initial_sample_desicion(sampling_context = {})
|
41
|
-
unless Sentry.configuration.tracing_enabled?
|
42
|
-
@sampled = false
|
43
|
-
return
|
44
|
-
end
|
45
|
-
|
46
|
-
return unless @sampled.nil?
|
47
|
-
|
48
|
-
transaction_description = generate_transaction_description
|
49
|
-
|
50
|
-
logger = Sentry.configuration.logger
|
51
|
-
sample_rate = Sentry.configuration.traces_sample_rate
|
52
|
-
traces_sampler = Sentry.configuration.traces_sampler
|
53
|
-
|
54
|
-
if traces_sampler.is_a?(Proc)
|
55
|
-
sampling_context = sampling_context.merge(
|
56
|
-
parent_sampled: @parent_sampled,
|
57
|
-
transaction_context: self.to_hash
|
58
|
-
)
|
59
|
-
|
60
|
-
sample_rate = traces_sampler.call(sampling_context)
|
61
|
-
end
|
62
|
-
|
63
|
-
unless [true, false].include?(sample_rate) || (sample_rate.is_a?(Float) && sample_rate >= 0.0 && sample_rate <= 1.0)
|
64
|
-
@sampled = false
|
65
|
-
logger.warn("#{MESSAGE_PREFIX} Discarding #{transaction_description} because of invalid sample_rate: #{sample_rate}")
|
66
|
-
return
|
67
|
-
end
|
68
|
-
|
69
|
-
if sample_rate == 0.0 || sample_rate == false
|
70
|
-
@sampled = false
|
71
|
-
logger.debug("#{MESSAGE_PREFIX} Discarding #{transaction_description} because traces_sampler returned 0 or false")
|
72
|
-
return
|
73
|
-
end
|
74
|
-
|
75
|
-
if sample_rate == true
|
76
|
-
@sampled = true
|
77
|
-
else
|
78
|
-
@sampled = Random.rand < sample_rate
|
79
|
-
end
|
80
|
-
|
81
|
-
if @sampled
|
82
|
-
logger.debug("#{MESSAGE_PREFIX} Starting #{transaction_description}")
|
83
|
-
else
|
84
|
-
logger.debug(
|
85
|
-
"#{MESSAGE_PREFIX} Discarding #{transaction_description} because it's not included in the random sample (sampling rate = #{sample_rate})"
|
86
|
-
)
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
def finish(hub: nil)
|
91
|
-
super() # Span#finish doesn't take arguments
|
92
|
-
|
93
|
-
if @name.nil?
|
94
|
-
@name = UNLABELD_NAME
|
95
|
-
end
|
96
|
-
|
97
|
-
return unless @sampled
|
98
|
-
|
99
|
-
hub ||= Sentry.get_current_hub
|
100
|
-
event = hub.current_client.event_from_transaction(self)
|
101
|
-
hub.capture_event(event)
|
102
|
-
end
|
103
|
-
|
104
|
-
private
|
105
|
-
|
106
|
-
def generate_transaction_description
|
107
|
-
result = op.nil? ? "" : "<#{@op}> "
|
108
|
-
result += "transaction"
|
109
|
-
result += " <#{@name}>" if @name
|
110
|
-
result
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|