sentry-ruby 5.10.0 → 5.26.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.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +3 -1
  3. data/Gemfile +12 -13
  4. data/README.md +26 -11
  5. data/Rakefile +9 -11
  6. data/bin/console +2 -0
  7. data/lib/sentry/attachment.rb +40 -0
  8. data/lib/sentry/background_worker.rb +11 -5
  9. data/lib/sentry/backpressure_monitor.rb +45 -0
  10. data/lib/sentry/backtrace.rb +12 -9
  11. data/lib/sentry/baggage.rb +7 -7
  12. data/lib/sentry/breadcrumb/sentry_logger.rb +6 -6
  13. data/lib/sentry/breadcrumb.rb +13 -6
  14. data/lib/sentry/check_in_event.rb +61 -0
  15. data/lib/sentry/client.rb +214 -25
  16. data/lib/sentry/configuration.rb +221 -38
  17. data/lib/sentry/core_ext/object/deep_dup.rb +1 -1
  18. data/lib/sentry/cron/configuration.rb +23 -0
  19. data/lib/sentry/cron/monitor_check_ins.rb +77 -0
  20. data/lib/sentry/cron/monitor_config.rb +53 -0
  21. data/lib/sentry/cron/monitor_schedule.rb +42 -0
  22. data/lib/sentry/dsn.rb +4 -4
  23. data/lib/sentry/envelope/item.rb +88 -0
  24. data/lib/sentry/envelope.rb +2 -68
  25. data/lib/sentry/error_event.rb +2 -2
  26. data/lib/sentry/event.rb +28 -47
  27. data/lib/sentry/excon/middleware.rb +77 -0
  28. data/lib/sentry/excon.rb +10 -0
  29. data/lib/sentry/faraday.rb +77 -0
  30. data/lib/sentry/graphql.rb +9 -0
  31. data/lib/sentry/hub.rb +138 -6
  32. data/lib/sentry/integrable.rb +10 -0
  33. data/lib/sentry/interface.rb +1 -0
  34. data/lib/sentry/interfaces/exception.rb +5 -3
  35. data/lib/sentry/interfaces/mechanism.rb +20 -0
  36. data/lib/sentry/interfaces/request.rb +8 -8
  37. data/lib/sentry/interfaces/single_exception.rb +13 -9
  38. data/lib/sentry/interfaces/stacktrace.rb +3 -1
  39. data/lib/sentry/interfaces/stacktrace_builder.rb +23 -2
  40. data/lib/sentry/linecache.rb +3 -3
  41. data/lib/sentry/log_event.rb +206 -0
  42. data/lib/sentry/log_event_buffer.rb +75 -0
  43. data/lib/sentry/logger.rb +1 -1
  44. data/lib/sentry/metrics/aggregator.rb +248 -0
  45. data/lib/sentry/metrics/configuration.rb +47 -0
  46. data/lib/sentry/metrics/counter_metric.rb +25 -0
  47. data/lib/sentry/metrics/distribution_metric.rb +25 -0
  48. data/lib/sentry/metrics/gauge_metric.rb +35 -0
  49. data/lib/sentry/metrics/local_aggregator.rb +53 -0
  50. data/lib/sentry/metrics/metric.rb +19 -0
  51. data/lib/sentry/metrics/set_metric.rb +28 -0
  52. data/lib/sentry/metrics/timing.rb +51 -0
  53. data/lib/sentry/metrics.rb +56 -0
  54. data/lib/sentry/net/http.rb +27 -44
  55. data/lib/sentry/profiler/helpers.rb +46 -0
  56. data/lib/sentry/profiler.rb +41 -60
  57. data/lib/sentry/propagation_context.rb +135 -0
  58. data/lib/sentry/puma.rb +12 -5
  59. data/lib/sentry/rack/capture_exceptions.rb +17 -8
  60. data/lib/sentry/rack.rb +2 -2
  61. data/lib/sentry/rake.rb +4 -15
  62. data/lib/sentry/redis.rb +10 -4
  63. data/lib/sentry/release_detector.rb +5 -5
  64. data/lib/sentry/rspec.rb +91 -0
  65. data/lib/sentry/scope.rb +75 -39
  66. data/lib/sentry/session.rb +2 -2
  67. data/lib/sentry/session_flusher.rb +15 -43
  68. data/lib/sentry/span.rb +92 -8
  69. data/lib/sentry/std_lib_logger.rb +50 -0
  70. data/lib/sentry/structured_logger.rb +138 -0
  71. data/lib/sentry/test_helper.rb +42 -13
  72. data/lib/sentry/threaded_periodic_worker.rb +39 -0
  73. data/lib/sentry/transaction.rb +44 -43
  74. data/lib/sentry/transaction_event.rb +10 -6
  75. data/lib/sentry/transport/configuration.rb +73 -1
  76. data/lib/sentry/transport/http_transport.rb +71 -41
  77. data/lib/sentry/transport/spotlight_transport.rb +50 -0
  78. data/lib/sentry/transport.rb +53 -49
  79. data/lib/sentry/utils/argument_checking_helper.rb +12 -0
  80. data/lib/sentry/utils/env_helper.rb +21 -0
  81. data/lib/sentry/utils/http_tracing.rb +74 -0
  82. data/lib/sentry/utils/logging_helper.rb +10 -7
  83. data/lib/sentry/utils/real_ip.rb +2 -2
  84. data/lib/sentry/utils/request_id.rb +1 -1
  85. data/lib/sentry/utils/uuid.rb +13 -0
  86. data/lib/sentry/vernier/output.rb +89 -0
  87. data/lib/sentry/vernier/profiler.rb +132 -0
  88. data/lib/sentry/version.rb +1 -1
  89. data/lib/sentry-ruby.rb +206 -35
  90. data/sentry-ruby-core.gemspec +3 -1
  91. data/sentry-ruby.gemspec +15 -6
  92. metadata +61 -11
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sentry
4
+ module Metrics
5
+ class LocalAggregator
6
+ # exposed only for testing
7
+ attr_reader :buckets
8
+
9
+ def initialize
10
+ @buckets = {}
11
+ end
12
+
13
+ def add(key, value)
14
+ if @buckets[key]
15
+ @buckets[key].add(value)
16
+ else
17
+ @buckets[key] = GaugeMetric.new(value)
18
+ end
19
+ end
20
+
21
+ def to_hash
22
+ return nil if @buckets.empty?
23
+
24
+ @buckets.map do |bucket_key, metric|
25
+ type, key, unit, tags = bucket_key
26
+
27
+ payload_key = "#{type}:#{key}@#{unit}"
28
+ payload_value = {
29
+ tags: deserialize_tags(tags),
30
+ min: metric.min,
31
+ max: metric.max,
32
+ count: metric.count,
33
+ sum: metric.sum
34
+ }
35
+
36
+ [payload_key, payload_value]
37
+ end.to_h
38
+ end
39
+
40
+ private
41
+
42
+ def deserialize_tags(tags)
43
+ tags.inject({}) do |h, tag|
44
+ k, v = tag
45
+ old = h[k]
46
+ # make it an array if key repeats
47
+ h[k] = old ? (old.is_a?(Array) ? old << v : [old, v]) : v
48
+ h
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sentry
4
+ module Metrics
5
+ class Metric
6
+ def add(value)
7
+ raise NotImplementedError
8
+ end
9
+
10
+ def serialize
11
+ raise NotImplementedError
12
+ end
13
+
14
+ def weight
15
+ raise NotImplementedError
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "set"
4
+ require "zlib"
5
+
6
+ module Sentry
7
+ module Metrics
8
+ class SetMetric < Metric
9
+ attr_reader :value
10
+
11
+ def initialize(value)
12
+ @value = Set[value]
13
+ end
14
+
15
+ def add(value)
16
+ @value << value
17
+ end
18
+
19
+ def serialize
20
+ value.map { |x| x.is_a?(String) ? Zlib.crc32(x) : x.to_i }
21
+ end
22
+
23
+ def weight
24
+ value.size
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sentry
4
+ module Metrics
5
+ module Timing
6
+ class << self
7
+ def nanosecond
8
+ time = Sentry.utc_now
9
+ time.to_i * (10 ** 9) + time.nsec
10
+ end
11
+
12
+ def microsecond
13
+ time = Sentry.utc_now
14
+ time.to_i * (10 ** 6) + time.usec
15
+ end
16
+
17
+ def millisecond
18
+ Sentry.utc_now.to_i * (10 ** 3)
19
+ end
20
+
21
+ def second
22
+ Sentry.utc_now.to_i
23
+ end
24
+
25
+ def minute
26
+ Sentry.utc_now.to_i / 60.0
27
+ end
28
+
29
+ def hour
30
+ Sentry.utc_now.to_i / 3600.0
31
+ end
32
+
33
+ def day
34
+ Sentry.utc_now.to_i / (3600.0 * 24.0)
35
+ end
36
+
37
+ def week
38
+ Sentry.utc_now.to_i / (3600.0 * 24.0 * 7.0)
39
+ end
40
+
41
+ def duration_start
42
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
43
+ end
44
+
45
+ def duration_end(start)
46
+ Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "sentry/metrics/metric"
4
+ require "sentry/metrics/counter_metric"
5
+ require "sentry/metrics/distribution_metric"
6
+ require "sentry/metrics/gauge_metric"
7
+ require "sentry/metrics/set_metric"
8
+ require "sentry/metrics/timing"
9
+ require "sentry/metrics/aggregator"
10
+
11
+ module Sentry
12
+ module Metrics
13
+ DURATION_UNITS = %w[nanosecond microsecond millisecond second minute hour day week]
14
+ INFORMATION_UNITS = %w[bit byte kilobyte kibibyte megabyte mebibyte gigabyte gibibyte terabyte tebibyte petabyte pebibyte exabyte exbibyte]
15
+ FRACTIONAL_UNITS = %w[ratio percent]
16
+
17
+ OP_NAME = "metric.timing"
18
+ SPAN_ORIGIN = "auto.metric.timing"
19
+
20
+ class << self
21
+ def increment(key, value = 1.0, unit: "none", tags: {}, timestamp: nil)
22
+ Sentry.metrics_aggregator&.add(:c, key, value, unit: unit, tags: tags, timestamp: timestamp)
23
+ end
24
+
25
+ def distribution(key, value, unit: "none", tags: {}, timestamp: nil)
26
+ Sentry.metrics_aggregator&.add(:d, key, value, unit: unit, tags: tags, timestamp: timestamp)
27
+ end
28
+
29
+ def set(key, value, unit: "none", tags: {}, timestamp: nil)
30
+ Sentry.metrics_aggregator&.add(:s, key, value, unit: unit, tags: tags, timestamp: timestamp)
31
+ end
32
+
33
+ def gauge(key, value, unit: "none", tags: {}, timestamp: nil)
34
+ Sentry.metrics_aggregator&.add(:g, key, value, unit: unit, tags: tags, timestamp: timestamp)
35
+ end
36
+
37
+ def timing(key, unit: "second", tags: {}, timestamp: nil, &block)
38
+ return unless block_given?
39
+ return yield unless DURATION_UNITS.include?(unit)
40
+
41
+ result, value = Sentry.with_child_span(op: OP_NAME, description: key, origin: SPAN_ORIGIN) do |span|
42
+ tags.each { |k, v| span.set_tag(k, v.is_a?(Array) ? v.join(", ") : v.to_s) } if span
43
+
44
+ start = Timing.send(unit.to_sym)
45
+ result = yield
46
+ value = Timing.send(unit.to_sym) - start
47
+
48
+ [result, value]
49
+ end
50
+
51
+ Sentry.metrics_aggregator&.add(:d, key, value, unit: unit, tags: tags, timestamp: timestamp)
52
+ result
53
+ end
54
+ end
55
+ end
56
+ end
@@ -1,13 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "net/http"
4
+ require "resolv"
5
+ require "sentry/utils/http_tracing"
4
6
 
5
7
  module Sentry
6
8
  # @api private
7
9
  module Net
8
10
  module HTTP
11
+ include Utils::HttpTracing
12
+
9
13
  OP_NAME = "http.client"
14
+ SPAN_ORIGIN = "auto.http.net_http"
10
15
  BREADCRUMB_CATEGORY = "net.http"
16
+ URI_PARSER = URI.const_defined?("RFC2396_PARSER") ? URI::RFC2396_PARSER : URI::DEFAULT_PARSER
11
17
 
12
18
  # To explain how the entire thing works, we need to know how the original Net::HTTP#request works
13
19
  # Here's part of its definition. As you can see, it usually calls itself inside a #start block
@@ -19,8 +25,7 @@ module Sentry
19
25
  # req['connection'] ||= 'close'
20
26
  # return request(req, body, &block) # <- request will be called for the second time from the first call
21
27
  # }
22
- # end
23
- # # .....
28
+ # end # .....
24
29
  # end
25
30
  # ```
26
31
  #
@@ -29,54 +34,29 @@ module Sentry
29
34
  return super unless started? && Sentry.initialized?
30
35
  return super if from_sentry_sdk?
31
36
 
32
- Sentry.with_child_span(op: OP_NAME, start_timestamp: Sentry.utc_now.to_f) do |sentry_span|
33
- set_sentry_trace_header(req, sentry_span)
34
-
35
- super.tap do |res|
36
- record_sentry_breadcrumb(req, res)
37
+ Sentry.with_child_span(op: OP_NAME, start_timestamp: Sentry.utc_now.to_f, origin: SPAN_ORIGIN) do |sentry_span|
38
+ request_info = extract_request_info(req)
37
39
 
38
- if sentry_span
39
- request_info = extract_request_info(req)
40
- sentry_span.set_description("#{request_info[:method]} #{request_info[:url]}")
41
- sentry_span.set_data('url', request_info[:url])
42
- sentry_span.set_data('http.method', request_info[:method])
43
- sentry_span.set_data('http.query', request_info[:query]) if request_info[:query]
44
- sentry_span.set_data('status', res.code.to_i)
45
- end
40
+ if propagate_trace?(request_info[:url])
41
+ set_propagation_headers(req)
46
42
  end
47
- end
48
- end
49
-
50
- private
51
43
 
52
- def set_sentry_trace_header(req, sentry_span)
53
- return unless sentry_span
44
+ res = super
45
+ response_status = res.code.to_i
54
46
 
55
- client = Sentry.get_current_client
47
+ if record_sentry_breadcrumb?
48
+ record_sentry_breadcrumb(request_info, response_status)
49
+ end
56
50
 
57
- trace = client.generate_sentry_trace(sentry_span)
58
- req[SENTRY_TRACE_HEADER_NAME] = trace if trace
51
+ if sentry_span
52
+ set_span_info(sentry_span, request_info, response_status)
53
+ end
59
54
 
60
- baggage = client.generate_baggage(sentry_span)
61
- req[BAGGAGE_HEADER_NAME] = baggage if baggage && !baggage.empty?
55
+ res
56
+ end
62
57
  end
63
58
 
64
- def record_sentry_breadcrumb(req, res)
65
- return unless Sentry.initialized? && Sentry.configuration.breadcrumbs_logger.include?(:http_logger)
66
-
67
- request_info = extract_request_info(req)
68
-
69
- crumb = Sentry::Breadcrumb.new(
70
- level: :info,
71
- category: BREADCRUMB_CATEGORY,
72
- type: :info,
73
- data: {
74
- status: res.code.to_i,
75
- **request_info
76
- }
77
- )
78
- Sentry.add_breadcrumb(crumb)
79
- end
59
+ private
80
60
 
81
61
  def from_sentry_sdk?
82
62
  dsn = Sentry.configuration.dsn
@@ -84,7 +64,10 @@ module Sentry
84
64
  end
85
65
 
86
66
  def extract_request_info(req)
87
- uri = req.uri || URI.parse("#{use_ssl? ? 'https' : 'http'}://#{address}#{req.path}")
67
+ # IPv6 url could look like '::1/path', and that won't parse without
68
+ # wrapping it in square brackets.
69
+ hostname = address =~ Resolv::IPv6::Regex ? "[#{address}]" : address
70
+ uri = req.uri || URI.parse(URI_PARSER.escape("#{use_ssl? ? 'https' : 'http'}://#{hostname}#{req.path}"))
88
71
  url = "#{uri.scheme}://#{uri.host}#{uri.path}" rescue uri.to_s
89
72
 
90
73
  result = { method: req.method, url: url }
@@ -100,4 +83,4 @@ module Sentry
100
83
  end
101
84
  end
102
85
 
103
- Sentry.register_patch(Sentry::Net::HTTP, Net::HTTP)
86
+ Sentry.register_patch(:http, Sentry::Net::HTTP, Net::HTTP)
@@ -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
@@ -1,26 +1,31 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'securerandom'
3
+ require "securerandom"
4
+ require_relative "profiler/helpers"
5
+ require "sentry/utils/uuid"
4
6
 
5
7
  module Sentry
6
8
  class Profiler
7
- VERSION = '1'
8
- PLATFORM = 'ruby'
9
+ include Profiler::Helpers
10
+
11
+ VERSION = "1"
12
+ PLATFORM = "ruby"
9
13
  # 101 Hz in microseconds
10
14
  DEFAULT_INTERVAL = 1e6 / 101
11
15
  MICRO_TO_NANO_SECONDS = 1e3
16
+ MIN_SAMPLES_REQUIRED = 2
12
17
 
13
18
  attr_reader :sampled, :started, :event_id
14
19
 
15
20
  def initialize(configuration)
16
- @event_id = SecureRandom.uuid.delete('-')
21
+ @event_id = Utils.uuid
17
22
  @started = false
18
23
  @sampled = nil
19
24
 
20
25
  @profiling_enabled = defined?(StackProf) && configuration.profiling_enabled?
21
26
  @profiles_sample_rate = configuration.profiles_sample_rate
22
27
  @project_root = configuration.project_root
23
- @app_dirs_pattern = configuration.app_dirs_pattern || Backtrace::APP_DIRS_PATTERN
28
+ @app_dirs_pattern = configuration.app_dirs_pattern
24
29
  @in_app_pattern = Regexp.new("^(#{@project_root}/)?#{@app_dirs_pattern}")
25
30
  end
26
31
 
@@ -32,7 +37,7 @@ module Sentry
32
37
  raw: true,
33
38
  aggregate: false)
34
39
 
35
- @started ? log('Started') : log('Not started since running elsewhere')
40
+ @started ? log("Started") : log("Not started since running elsewhere")
36
41
  end
37
42
 
38
43
  def stop
@@ -40,7 +45,11 @@ module Sentry
40
45
  return unless @started
41
46
 
42
47
  StackProf.stop
43
- log('Stopped')
48
+ log("Stopped")
49
+ end
50
+
51
+ def active_thread_id
52
+ "0"
44
53
  end
45
54
 
46
55
  # Sets initial sampling decision of the profile.
@@ -53,14 +62,14 @@ module Sentry
53
62
 
54
63
  unless transaction_sampled
55
64
  @sampled = false
56
- log('Discarding profile because transaction not sampled')
65
+ log("Discarding profile because transaction not sampled")
57
66
  return
58
67
  end
59
68
 
60
69
  case @profiles_sample_rate
61
70
  when 0.0
62
71
  @sampled = false
63
- log('Discarding profile because sample_rate is 0')
72
+ log("Discarding profile because sample_rate is 0")
64
73
  return
65
74
  when 1.0
66
75
  @sampled = true
@@ -69,28 +78,32 @@ module Sentry
69
78
  @sampled = Random.rand < @profiles_sample_rate
70
79
  end
71
80
 
72
- log('Discarding profile due to sampling decision') unless @sampled
81
+ log("Discarding profile due to sampling decision") unless @sampled
73
82
  end
74
83
 
75
84
  def to_hash
76
- return {} unless @sampled
85
+ unless @sampled
86
+ record_lost_event(:sample_rate)
87
+ return {}
88
+ end
89
+
77
90
  return {} unless @started
78
91
 
79
92
  results = StackProf.results
80
- return {} unless results
81
- return {} if results.empty?
82
- return {} if results[:samples] == 0
83
- return {} unless results[:raw]
84
93
 
85
- frame_map = {}
94
+ if !results || results.empty? || results[:samples] == 0 || !results[:raw]
95
+ record_lost_event(:insufficient_data)
96
+ return {}
97
+ end
86
98
 
87
- frames = results[:frames].to_enum.with_index.map do |frame, idx|
88
- frame_id, frame_data = frame
99
+ frame_map = {}
89
100
 
101
+ frames = results[:frames].map.with_index do |(frame_id, frame_data), idx|
90
102
  # need to map over stackprof frame ids to ours
91
103
  frame_map[frame_id] = idx
92
104
 
93
105
  file_path = frame_data[:file]
106
+ lineno = frame_data[:line]
94
107
  in_app = in_app?(file_path)
95
108
  filename = compute_filename(file_path, in_app)
96
109
  function, mod = split_module(frame_data[:name])
@@ -103,7 +116,7 @@ module Sentry
103
116
  }
104
117
 
105
118
  frame_hash[:module] = mod if mod
106
- frame_hash[:lineno] = frame_data[:line] if frame_data[:line]
119
+ frame_hash[:lineno] = lineno if lineno && lineno >= 0
107
120
 
108
121
  frame_hash
109
122
  end
@@ -124,7 +137,7 @@ module Sentry
124
137
  num_seen << results[:raw][idx + len]
125
138
  idx += len + 1
126
139
 
127
- log('Unknown frame in stack') if stack.size != len
140
+ log("Unknown frame in stack") if stack.size != len
128
141
  end
129
142
 
130
143
  idx = 0
@@ -149,16 +162,17 @@ module Sentry
149
162
  # Till then, on multi-threaded servers like puma, we will get frames from other active threads when the one
150
163
  # we're profiling is idle/sleeping/waiting for IO etc.
151
164
  # https://bugs.ruby-lang.org/issues/10602
152
- thread_id: '0',
165
+ thread_id: "0",
153
166
  elapsed_since_start_ns: elapsed_since_start_ns.to_s
154
167
  }
155
168
  end
156
169
  end
157
170
 
158
- log('Some samples thrown away') if samples.size != results[:samples]
171
+ log("Some samples thrown away") if samples.size != results[:samples]
159
172
 
160
- if samples.size <= 2
161
- log('Not enough samples, discarding profiler')
173
+ if samples.size <= MIN_SAMPLES_REQUIRED
174
+ log("Not enough samples, discarding profiler")
175
+ record_lost_event(:insufficient_data)
162
176
  return {}
163
177
  end
164
178
 
@@ -179,44 +193,11 @@ module Sentry
179
193
  private
180
194
 
181
195
  def log(message)
182
- Sentry.logger.debug(LOGGER_PROGNAME) { "[Profiler] #{message}" }
183
- end
184
-
185
- def in_app?(abs_path)
186
- abs_path.match?(@in_app_pattern)
187
- end
188
-
189
- # copied from stacktrace.rb since I don't want to touch existing code
190
- # TODO-neel-profiler try to fetch this from stackprof once we patch
191
- # the native extension
192
- def compute_filename(abs_path, in_app)
193
- return nil if abs_path.nil?
194
-
195
- under_project_root = @project_root && abs_path.start_with?(@project_root)
196
-
197
- prefix =
198
- if under_project_root && in_app
199
- @project_root
200
- else
201
- longest_load_path = $LOAD_PATH.select { |path| abs_path.start_with?(path.to_s) }.max_by(&:size)
202
-
203
- if under_project_root
204
- longest_load_path || @project_root
205
- else
206
- longest_load_path
207
- end
208
- end
209
-
210
- prefix ? abs_path[prefix.to_s.chomp(File::SEPARATOR).length + 1..-1] : abs_path
196
+ Sentry.sdk_logger.debug(LOGGER_PROGNAME) { "[Profiler] #{message}" }
211
197
  end
212
198
 
213
- def split_module(name)
214
- # last module plus class/instance method
215
- i = name.rindex('::')
216
- function = i ? name[(i + 2)..-1] : name
217
- mod = i ? name[0...i] : nil
218
-
219
- [function, mod]
199
+ def record_lost_event(reason)
200
+ Sentry.get_current_client&.transport&.record_lost_event(reason, "profile")
220
201
  end
221
202
  end
222
203
  end