txlemetry-rails 4.0.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.
@@ -0,0 +1,130 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'txlemetry/rails/version'
4
+ require 'txlemetry/rails/configuration'
5
+ require 'txlemetry/rails/tracing_headers'
6
+ require 'txlemetry/rails/request_metadata'
7
+ require 'txlemetry/rails/request_context'
8
+ require 'txlemetry/rails/capture_exceptions'
9
+ require 'txlemetry/rails/rescued_exception_interceptor'
10
+ require 'txlemetry/rails/active_job'
11
+ require 'txlemetry/rails/error_subscriber'
12
+ require 'txlemetry/rails/logs/severity'
13
+ require 'txlemetry/rails/logs/rate_limiter'
14
+ require 'txlemetry/rails/logs/appender'
15
+ require 'txlemetry/rails/logs/setup'
16
+ require 'txlemetry/rails/facade'
17
+ require 'txlemetry/rails/railtie'
18
+
19
+ module Txlemetry
20
+ module Rails
21
+ # Thread-local key for tracking web request context
22
+ IN_WEB_REQUEST_KEY = :txlemetry_in_web_request
23
+ ACTIVE_JOB_CAPTURED_EXCEPTION_IVAR = :@txlemetry_active_job_exception_captured
24
+ WEB_CAPTURED_EXCEPTION_IVAR = :@txlemetry_web_exception_captured
25
+
26
+ private_constant :ACTIVE_JOB_CAPTURED_EXCEPTION_IVAR
27
+ private_constant :WEB_CAPTURED_EXCEPTION_IVAR
28
+
29
+ class << self
30
+ # @return [Txlemetry::Rails::Configuration] Rails integration configuration.
31
+ def config
32
+ @config ||= Configuration.new
33
+ end
34
+
35
+ # @param config [Txlemetry::Rails::Configuration] Rails integration configuration.
36
+ attr_writer :config
37
+
38
+ # Configure Rails integration options.
39
+ #
40
+ # @yieldparam config [Txlemetry::Rails::Configuration]
41
+ # @return [void]
42
+ def configure
43
+ yield config if block_given?
44
+ end
45
+
46
+ # Mark that we're in a web request context
47
+ # CaptureExceptions middleware will handle exception capture
48
+ # @api private
49
+ # @return [void]
50
+ def enter_web_request
51
+ Thread.current[IN_WEB_REQUEST_KEY] = true
52
+ end
53
+
54
+ # Clear web request context (called at end of request)
55
+ # @api private
56
+ # @return [void]
57
+ def exit_web_request
58
+ Thread.current[IN_WEB_REQUEST_KEY] = false
59
+ end
60
+
61
+ # Check if we're currently in a web request context
62
+ # Used by ErrorSubscriber to avoid duplicate captures
63
+ # @api private
64
+ # @return [Boolean]
65
+ def in_web_request?
66
+ Thread.current[IN_WEB_REQUEST_KEY] == true
67
+ end
68
+
69
+ # Mark an exception as already captured by the ActiveJob integration.
70
+ # Used by ErrorSubscriber to avoid duplicate captures when Rails reports
71
+ # the same re-raised job exception via Rails.error.
72
+ # @api private
73
+ # @param exception [Exception]
74
+ # @return [void]
75
+ def mark_active_job_exception_captured(exception)
76
+ exception.instance_variable_set(ACTIVE_JOB_CAPTURED_EXCEPTION_IVAR, true)
77
+ rescue StandardError
78
+ nil
79
+ end
80
+
81
+ # Check whether an exception was already captured by ActiveJobExtensions.
82
+ # @api private
83
+ # @param exception [Exception]
84
+ # @return [Boolean]
85
+ def active_job_exception_captured?(exception)
86
+ exception.instance_variable_get(ACTIVE_JOB_CAPTURED_EXCEPTION_IVAR) == true
87
+ rescue StandardError
88
+ false
89
+ end
90
+
91
+ # Mark an exception as already captured by the CaptureExceptions middleware.
92
+ #
93
+ # ActionDispatch::Executor sits above our middleware and reports unhandled
94
+ # exceptions to Rails.error *after* the response has unwound back through
95
+ # CaptureExceptions, so `in_web_request?` is already false by then. The mark
96
+ # lets ErrorSubscriber recognize the report as a duplicate.
97
+ #
98
+ # The whole cause chain is marked because ActionDispatch::ExceptionWrapper
99
+ # unwraps ActionView::Template::Error to its cause, meaning Rails can report
100
+ # a different object than the one the middleware captured.
101
+ # @api private
102
+ # @param exception [Exception]
103
+ # @return [void]
104
+ def mark_web_exception_captured(exception)
105
+ current = exception
106
+ seen = {}.compare_by_identity
107
+
108
+ while current.is_a?(Exception) && !seen[current]
109
+ seen[current] = true
110
+ current.instance_variable_set(WEB_CAPTURED_EXCEPTION_IVAR, true)
111
+ current = current.cause
112
+ end
113
+ rescue StandardError
114
+ nil
115
+ end
116
+
117
+ # Check whether an exception was already captured by CaptureExceptions.
118
+ # @api private
119
+ # @param exception [Exception]
120
+ # @return [Boolean]
121
+ def web_exception_captured?(exception)
122
+ exception.instance_variable_get(WEB_CAPTURED_EXCEPTION_IVAR) == true
123
+ rescue StandardError
124
+ false
125
+ end
126
+ end
127
+ end
128
+ end
129
+
130
+ Txlemetry::Rails.install_txlemetry_facade!
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ unless defined?(Rails)
4
+ raise LoadError, 'txlemetry-rails requires Rails. Use the txlemetry-ruby gem directly for non-Rails applications.'
5
+ end
6
+
7
+ # Load core Txlemetry Ruby SDK
8
+ require 'txlemetry'
9
+
10
+ # Load Rails integration
11
+ require 'txlemetry/rails'
metadata ADDED
@@ -0,0 +1,91 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: txlemetry-rails
3
+ version: !ruby/object:Gem::Version
4
+ version: 4.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Txlemetry
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: railties
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: 5.2.0
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: 5.2.0
26
+ - !ruby/object:Gem::Dependency
27
+ name: txlemetry-ruby
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - '='
31
+ - !ruby/object:Gem::Version
32
+ version: 4.0.0
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - '='
38
+ - !ruby/object:Gem::Version
39
+ version: 4.0.0
40
+ description: Automatic exception tracking and instrumentation for Ruby on Rails applications
41
+ using Txlemetry
42
+ email: support@txlemetry.com
43
+ executables: []
44
+ extensions: []
45
+ extra_rdoc_files: []
46
+ files:
47
+ - LICENSE
48
+ - NOTICE
49
+ - lib/generators/txlemetry/install_generator.rb
50
+ - lib/generators/txlemetry/templates/txlemetry.rb
51
+ - lib/txlemetry-rails.rb
52
+ - lib/txlemetry/rails.rb
53
+ - lib/txlemetry/rails/active_job.rb
54
+ - lib/txlemetry/rails/capture_exceptions.rb
55
+ - lib/txlemetry/rails/configuration.rb
56
+ - lib/txlemetry/rails/error_subscriber.rb
57
+ - lib/txlemetry/rails/facade.rb
58
+ - lib/txlemetry/rails/logs/appender.rb
59
+ - lib/txlemetry/rails/logs/rate_limiter.rb
60
+ - lib/txlemetry/rails/logs/setup.rb
61
+ - lib/txlemetry/rails/logs/severity.rb
62
+ - lib/txlemetry/rails/parameter_filter.rb
63
+ - lib/txlemetry/rails/railtie.rb
64
+ - lib/txlemetry/rails/request_context.rb
65
+ - lib/txlemetry/rails/request_metadata.rb
66
+ - lib/txlemetry/rails/rescued_exception_interceptor.rb
67
+ - lib/txlemetry/rails/tracing_headers.rb
68
+ - lib/txlemetry/rails/version.rb
69
+ homepage: https://txlemetry.com
70
+ licenses:
71
+ - MIT
72
+ metadata:
73
+ rubygems_mfa_required: 'true'
74
+ rdoc_options: []
75
+ require_paths:
76
+ - lib
77
+ required_ruby_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '3.0'
82
+ required_rubygems_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ requirements: []
88
+ rubygems_version: 3.6.9
89
+ specification_version: 4
90
+ summary: Txlemetry integration for Rails
91
+ test_files: []