sentry-ruby 0.1.2 → 4.0.1
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/CHANGELOG.md +25 -0
- data/Gemfile +5 -0
- data/README.md +53 -7
- data/Rakefile +3 -1
- data/lib/{sentry.rb → sentry-ruby.rb} +28 -2
- data/lib/sentry/benchmarks/benchmark_transport.rb +14 -0
- data/lib/sentry/breadcrumb.rb +7 -7
- data/lib/sentry/breadcrumb/sentry_logger.rb +10 -26
- data/lib/sentry/breadcrumb_buffer.rb +2 -5
- data/lib/sentry/client.rb +17 -5
- data/lib/sentry/configuration.rb +76 -87
- data/lib/sentry/dsn.rb +6 -3
- data/lib/sentry/event.rb +32 -26
- data/lib/sentry/hub.rb +13 -2
- data/lib/sentry/interfaces/request.rb +1 -10
- data/lib/sentry/rack.rb +1 -0
- data/lib/sentry/rack/tracing.rb +39 -0
- data/lib/sentry/rake.rb +17 -0
- data/lib/sentry/scope.rb +26 -4
- data/lib/sentry/span.rb +155 -0
- data/lib/sentry/transaction.rb +113 -0
- data/lib/sentry/transaction_event.rb +29 -0
- data/lib/sentry/transport.rb +7 -5
- data/lib/sentry/transport/configuration.rb +1 -8
- data/lib/sentry/transport/http_transport.rb +5 -2
- data/lib/sentry/transport/state.rb +2 -2
- data/lib/sentry/utils/request_id.rb +16 -0
- data/lib/sentry/version.rb +1 -1
- metadata +10 -4
- data/lib/sentry/ruby.rb +0 -1
@@ -0,0 +1,113 @@
|
|
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
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sentry
|
4
|
+
class TransactionEvent < Event
|
5
|
+
ATTRIBUTES = %i(
|
6
|
+
event_id level timestamp start_timestamp
|
7
|
+
release environment server_name modules
|
8
|
+
user tags contexts extra
|
9
|
+
transaction platform sdk type
|
10
|
+
)
|
11
|
+
|
12
|
+
attr_accessor(*ATTRIBUTES)
|
13
|
+
attr_accessor :spans
|
14
|
+
|
15
|
+
def start_timestamp=(time)
|
16
|
+
@start_timestamp = time.is_a?(Time) ? time.to_f : time
|
17
|
+
end
|
18
|
+
|
19
|
+
def type
|
20
|
+
"transaction"
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_hash
|
24
|
+
data = super
|
25
|
+
data[:spans] = @spans.map(&:to_hash) if @spans
|
26
|
+
data
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/sentry/transport.rb
CHANGED
@@ -32,10 +32,11 @@ module Sentry
|
|
32
32
|
event
|
33
33
|
rescue => e
|
34
34
|
failed_for_exception(e, event)
|
35
|
+
nil
|
35
36
|
end
|
36
37
|
|
37
38
|
def generate_auth_header
|
38
|
-
now =
|
39
|
+
now = Sentry.utc_now.to_i
|
39
40
|
fields = {
|
40
41
|
'sentry_version' => PROTOCOL_VERSION,
|
41
42
|
'sentry_client' => USER_AGENT,
|
@@ -48,11 +49,12 @@ module Sentry
|
|
48
49
|
|
49
50
|
def encode(event_hash)
|
50
51
|
event_id = event_hash[:event_id] || event_hash['event_id']
|
52
|
+
event_type = event_hash[:type] || event_hash['type']
|
51
53
|
|
52
54
|
envelope = <<~ENVELOPE
|
53
|
-
{"event_id":"#{event_id}","dsn":"#{configuration.dsn.to_s}","sdk":#{Sentry.sdk_meta.to_json},"sent_at":"#{
|
54
|
-
{"type":"
|
55
|
-
#{event_hash
|
55
|
+
{"event_id":"#{event_id}","dsn":"#{configuration.dsn.to_s}","sdk":#{Sentry.sdk_meta.to_json},"sent_at":"#{Sentry.utc_now.iso8601}"}
|
56
|
+
{"type":"#{event_type}","content_type":"application/json"}
|
57
|
+
#{JSON.generate(event_hash)}
|
56
58
|
ENVELOPE
|
57
59
|
|
58
60
|
[CONTENT_TYPE, envelope]
|
@@ -86,7 +88,7 @@ module Sentry
|
|
86
88
|
end
|
87
89
|
|
88
90
|
def log_not_sending(event)
|
89
|
-
configuration.logger.warn(LOGGER_PROGNAME) { "Failed to submit event: #{Event.get_log_message(event.to_hash)}" }
|
91
|
+
configuration.logger.warn(LOGGER_PROGNAME) { "Failed to submit event. Unreported Event: #{Event.get_log_message(event.to_hash)}" }
|
90
92
|
end
|
91
93
|
end
|
92
94
|
end
|
@@ -1,19 +1,12 @@
|
|
1
1
|
module Sentry
|
2
2
|
class Transport
|
3
3
|
class Configuration
|
4
|
-
attr_accessor :timeout, :open_timeout, :proxy, :ssl, :ssl_ca_file, :ssl_verification, :
|
4
|
+
attr_accessor :timeout, :open_timeout, :proxy, :ssl, :ssl_ca_file, :ssl_verification, :http_adapter, :faraday_builder, :transport_class
|
5
5
|
|
6
6
|
def initialize
|
7
7
|
@ssl_verification = true
|
8
8
|
@open_timeout = 1
|
9
9
|
@timeout = 2
|
10
|
-
@encoding = 'gzip'
|
11
|
-
end
|
12
|
-
|
13
|
-
def encoding=(encoding)
|
14
|
-
raise(Error, 'Unsupported encoding') unless %w(gzip json).include? encoding
|
15
|
-
|
16
|
-
@encoding = encoding
|
17
10
|
end
|
18
11
|
|
19
12
|
def transport_class=(klass)
|
@@ -23,9 +23,12 @@ module Sentry
|
|
23
23
|
end
|
24
24
|
rescue Faraday::Error => e
|
25
25
|
error_info = e.message
|
26
|
-
|
27
|
-
|
26
|
+
|
27
|
+
if e.response
|
28
|
+
error_info += "\nbody: #{e.response[:body]}"
|
29
|
+
error_info += " Error in headers is: #{e.response[:headers]['x-sentry-error']}" if e.response[:headers]['x-sentry-error']
|
28
30
|
end
|
31
|
+
|
29
32
|
raise Sentry::Error, error_info
|
30
33
|
end
|
31
34
|
|
@@ -9,7 +9,7 @@ module Sentry
|
|
9
9
|
return true if @status == :online
|
10
10
|
|
11
11
|
interval = @retry_after || [@retry_number, 6].min**2
|
12
|
-
return true if
|
12
|
+
return true if Sentry.utc_now - @last_check >= interval
|
13
13
|
|
14
14
|
false
|
15
15
|
end
|
@@ -17,7 +17,7 @@ module Sentry
|
|
17
17
|
def failure(retry_after = nil)
|
18
18
|
@status = :error
|
19
19
|
@retry_number += 1
|
20
|
-
@last_check =
|
20
|
+
@last_check = Sentry.utc_now
|
21
21
|
@retry_after = retry_after
|
22
22
|
end
|
23
23
|
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Sentry
|
2
|
+
module Utils
|
3
|
+
module RequestId
|
4
|
+
REQUEST_ID_HEADERS = %w(action_dispatch.request_id HTTP_X_REQUEST_ID).freeze
|
5
|
+
|
6
|
+
# Request ID based on ActionDispatch::RequestId
|
7
|
+
def self.read_from(env_hash)
|
8
|
+
REQUEST_ID_HEADERS.each do |key|
|
9
|
+
request_id = env_hash[key]
|
10
|
+
return request_id if request_id
|
11
|
+
end
|
12
|
+
nil
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/sentry/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sentry-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
4
|
+
version: 4.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sentry Team
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-11
|
11
|
+
date: 2020-12-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -44,8 +44,9 @@ files:
|
|
44
44
|
- Rakefile
|
45
45
|
- bin/console
|
46
46
|
- bin/setup
|
47
|
-
- lib/sentry.rb
|
47
|
+
- lib/sentry-ruby.rb
|
48
48
|
- lib/sentry/backtrace.rb
|
49
|
+
- lib/sentry/benchmarks/benchmark_transport.rb
|
49
50
|
- lib/sentry/breadcrumb.rb
|
50
51
|
- lib/sentry/breadcrumb/sentry_logger.rb
|
51
52
|
- lib/sentry/breadcrumb_buffer.rb
|
@@ -65,8 +66,12 @@ files:
|
|
65
66
|
- lib/sentry/logger.rb
|
66
67
|
- lib/sentry/rack.rb
|
67
68
|
- lib/sentry/rack/capture_exception.rb
|
68
|
-
- lib/sentry/
|
69
|
+
- lib/sentry/rack/tracing.rb
|
70
|
+
- lib/sentry/rake.rb
|
69
71
|
- lib/sentry/scope.rb
|
72
|
+
- lib/sentry/span.rb
|
73
|
+
- lib/sentry/transaction.rb
|
74
|
+
- lib/sentry/transaction_event.rb
|
70
75
|
- lib/sentry/transport.rb
|
71
76
|
- lib/sentry/transport/configuration.rb
|
72
77
|
- lib/sentry/transport/dummy_transport.rb
|
@@ -74,6 +79,7 @@ files:
|
|
74
79
|
- lib/sentry/transport/state.rb
|
75
80
|
- lib/sentry/utils/exception_cause_chain.rb
|
76
81
|
- lib/sentry/utils/real_ip.rb
|
82
|
+
- lib/sentry/utils/request_id.rb
|
77
83
|
- lib/sentry/version.rb
|
78
84
|
- sentry-ruby.gemspec
|
79
85
|
homepage: https://github.com/getsentry/raven-ruby
|
data/lib/sentry/ruby.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
require "sentry"
|