posthog-rails 3.12.2 → 3.13.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 62ff8f270eaa05f59e416c798a1788f8ce3baa16c1dcba8b09f58039a4ac52c6
4
- data.tar.gz: 4bc7f6753ef7bd80fca9418c679085ae894441b5efcb06bd4d31348a30ec2ef7
3
+ metadata.gz: dbadf59825cbf2d519a1eab2aa36e56cba2bc9c395076857e50bc126e41300b0
4
+ data.tar.gz: de897b215980ee6bcbbfe54416073fed3d5b9321fce30443dacb015a7785b073
5
5
  SHA512:
6
- metadata.gz: 849ca061d5d4ce429e2361f22b89c95b1ee9e8f4ce2fb1462e841a5deaef896f38b4095335fa6aafa4a70d92a5b53218d08fb0772c4089d4117cb1639a4f0dcb
7
- data.tar.gz: 2f117183afbf4ec5cce029afe3e4170739b1f52707c4465a2a3312891bf10cc2a0d0202c37622ea32e6ccae6d4e2e211057b8fdbe1851cdf66d33414de086a8e
6
+ metadata.gz: 33068f5f9b2673d0f9acf9f1acb20f50a8f99c04e1182911d9245c539e8d2566a3c42fb6da125d89853a7cadadf187754b3d49e24666a46d274800bc9badf82f
7
+ data.tar.gz: d94d7cff285e97a7769683f1349689b770d8ddb3610ceb0f21cf68067ca56b0fe2ffbb103f2c5720fd39270cc3d84f6c8fb9e9c4e39fb83e2fb65a8da35123c3
@@ -37,6 +37,12 @@ PostHog::Rails.configure do |config|
37
37
  # making it easier to identify affected users and debug user-specific issues.
38
38
  # config.current_user_method = :current_user
39
39
 
40
+ # Or provide a resolver for apps that store user context outside controllers,
41
+ # such as ActiveSupport::CurrentAttributes. The resolver takes precedence over
42
+ # current_user_method and may accept the controller as an argument.
43
+ # config.current_user_resolver = proc { Current.user }
44
+ # config.current_user_resolver = proc { |controller| controller.current_user }
45
+
40
46
  # Additional exception classes to exclude from reporting
41
47
  # These are added to the default excluded exceptions
42
48
  # config.excluded_exceptions = [
@@ -69,20 +69,40 @@ module PostHog
69
69
  def extract_distinct_id(env)
70
70
  # Prefer authenticated Rails user context. Request/tracing context is
71
71
  # applied later by the core capture path if this returns nil.
72
- if PostHog::Rails.config&.capture_user_context && env['action_controller.instance']
73
- controller = env['action_controller.instance']
74
- method_name = PostHog::Rails.config&.current_user_method || :current_user
72
+ return nil unless PostHog::Rails.config&.capture_user_context
75
73
 
76
- if controller.respond_to?(method_name, true)
77
- user = controller.send(method_name)
78
- user_id = extract_user_id(user) if user
79
- return user_id if present?(user_id)
80
- end
81
- end
74
+ user = extract_current_user(env['action_controller.instance'])
75
+ user_id = extract_user_id(user) if user
76
+ return user_id if present?(user_id)
82
77
 
83
78
  nil
84
79
  end
85
80
 
81
+ def extract_current_user(controller)
82
+ resolver = PostHog::Rails.config&.current_user_resolver
83
+ return resolve_current_user(resolver, controller) if resolver
84
+
85
+ method_name = PostHog::Rails.config&.current_user_method || :current_user
86
+ return unless controller.respond_to?(method_name, true)
87
+
88
+ controller.send(method_name)
89
+ end
90
+
91
+ def resolve_current_user(resolver, controller)
92
+ call_current_user_resolver(resolver, controller)
93
+ rescue StandardError => e
94
+ PostHog::Logging.logger.warn("current_user_resolver failed: #{e.message}")
95
+ nil
96
+ end
97
+
98
+ def call_current_user_resolver(resolver, controller)
99
+ if resolver.arity.zero?
100
+ controller ? controller.instance_exec(&resolver) : resolver.call
101
+ elsif controller
102
+ resolver.call(controller)
103
+ end
104
+ end
105
+
86
106
  def extract_user_id(user)
87
107
  # Use configured method if specified
88
108
  method_name = PostHog::Rails.config&.user_id_method
@@ -32,6 +32,10 @@ module PostHog
32
32
  # @return [Symbol] Method name to call on controller to get the current user. Defaults to :current_user.
33
33
  attr_accessor :current_user_method
34
34
 
35
+ # @return [Proc, nil] Callable used to resolve the current user. When set, this takes precedence over
36
+ # current_user_method. The callable may accept the controller instance or no arguments.
37
+ attr_accessor :current_user_resolver
38
+
35
39
  # @return [Symbol, nil] Method name to call on the user object to get distinct_id. When nil, tries:
36
40
  # posthog_distinct_id, distinct_id, id, pk, uuid in order.
37
41
  attr_accessor :user_id_method
@@ -68,6 +72,7 @@ module PostHog
68
72
  @use_tracing_headers = true
69
73
  @capture_user_context = true
70
74
  @current_user_method = :current_user
75
+ @current_user_resolver = nil
71
76
  @user_id_method = nil
72
77
  @logs_enabled = false
73
78
  @logs_forward_rails_logger = true
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PostHog
4
+ module Rails
5
+ # Install the Rails singleton-style PostHog facade at load time so Rails app
6
+ # initializers can call PostHog.init before Railtie initializers run.
7
+ #
8
+ # @api private
9
+ # @return [void]
10
+ def self.install_posthog_facade!
11
+ return if @posthog_facade_installed
12
+
13
+ PostHog.class_eval do
14
+ class << self
15
+ attr_accessor :client
16
+
17
+ # Initialize the singleton PostHog client used by Rails delegators.
18
+ #
19
+ # @param options [Hash] Core {PostHog::Client} options.
20
+ # @yieldparam config [PostHog::Rails::InitConfig] Block-based core SDK configuration.
21
+ # @return [PostHog::Client]
22
+ def init(options = {})
23
+ # If block given, yield to configuration
24
+ if block_given?
25
+ config = PostHog::Rails::InitConfig.new(options)
26
+ yield config
27
+ options = config.to_client_options
28
+ end
29
+
30
+ # Let the PostHog Logs pipeline reuse the same api_key/host without
31
+ # the core client exposing public readers.
32
+ PostHog::Rails::Logs::Setup.remember_client_options(options) if defined?(PostHog::Rails::Logs::Setup)
33
+
34
+ # Create the PostHog client. If a client already exists, shut it down
35
+ # after replacement so repeated init calls do not leave background
36
+ # resources from the previous instance running.
37
+ previous_client = @client
38
+ @client = PostHog::Client.new(options)
39
+ begin
40
+ previous_client&.shutdown
41
+ rescue StandardError => e
42
+ PostHog::Logging.logger.warn("Failed to shut down previous PostHog client: #{e.message}")
43
+ end
44
+ @client
45
+ end
46
+
47
+ # @return [Boolean] Whether {PostHog.init} has created a client.
48
+ def initialized?
49
+ !@client.nil?
50
+ end
51
+
52
+ # Fallback for any client methods not explicitly defined.
53
+ #
54
+ # @api private
55
+ def method_missing(method_name, ...)
56
+ ensure_initialized!
57
+
58
+ if client.respond_to?(method_name)
59
+ client.public_send(method_name, ...)
60
+ else
61
+ super
62
+ end
63
+ end
64
+
65
+ # @api private
66
+ def respond_to_missing?(method_name, include_private = false)
67
+ ensure_initialized!
68
+ client.respond_to?(method_name, include_private) || super
69
+ end
70
+
71
+ private
72
+
73
+ def ensure_initialized!
74
+ return if initialized?
75
+
76
+ @client = PostHog::Client.new(api_key: nil, silence_disabled_client_error: true)
77
+ end
78
+ end
79
+ end
80
+
81
+ %i[
82
+ capture
83
+ capture_exception
84
+ identify
85
+ alias
86
+ group_identify
87
+ is_feature_enabled
88
+ get_feature_flag
89
+ get_all_flags
90
+ ].each do |method_name|
91
+ PostHog.define_singleton_method(method_name) do |*args, **kwargs, &block|
92
+ ensure_initialized!
93
+ client.public_send(method_name, *args, **kwargs, &block)
94
+ end
95
+ end
96
+
97
+ @posthog_facade_installed = true
98
+ end
99
+ end
100
+ end
@@ -1,97 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'posthog/rails/facade'
4
+
3
5
  module PostHog
4
6
  module Rails
5
7
  class Railtie < ::Rails::Railtie
6
- # Add PostHog module methods for accessing Rails-specific client
8
+ # Keep the historical Railtie initializer name, but install the facade at
9
+ # load time so application initializers can call PostHog.init.
7
10
  initializer 'posthog.set_configs' do |_app|
8
- PostHog.class_eval do
9
- class << self
10
- attr_accessor :client
11
-
12
- # Methods explicitly delegated to the client
13
- DELEGATED_METHODS = %i[
14
- capture
15
- capture_exception
16
- identify
17
- alias
18
- group_identify
19
- is_feature_enabled
20
- get_feature_flag
21
- get_all_flags
22
- ].freeze
23
-
24
- # Initialize the singleton PostHog client used by Rails delegators.
25
- #
26
- # @param options [Hash] Core {PostHog::Client} options.
27
- # @yieldparam config [PostHog::Rails::InitConfig] Block-based core SDK configuration.
28
- # @return [PostHog::Client]
29
- def init(options = {})
30
- # If block given, yield to configuration
31
- if block_given?
32
- config = PostHog::Rails::InitConfig.new(options)
33
- yield config
34
- options = config.to_client_options
35
- end
36
-
37
- # Let the PostHog Logs pipeline reuse the same api_key/host without
38
- # the core client exposing public readers.
39
- PostHog::Rails::Logs::Setup.remember_client_options(options) if defined?(PostHog::Rails::Logs::Setup)
40
-
41
- # Create the PostHog client. If a client already exists, shut it down
42
- # after replacement so repeated init calls do not leave background
43
- # resources from the previous instance running.
44
- previous_client = @client
45
- @client = PostHog::Client.new(options)
46
- begin
47
- previous_client&.shutdown
48
- rescue StandardError => e
49
- PostHog::Logging.logger.warn("Failed to shut down previous PostHog client: #{e.message}")
50
- end
51
- @client
52
- end
53
-
54
- # Define delegated methods using metaprogramming
55
- DELEGATED_METHODS.each do |method_name|
56
- define_method(method_name) do |*args, **kwargs, &block|
57
- ensure_initialized!
58
- client.public_send(method_name, *args, **kwargs, &block)
59
- end
60
- end
61
-
62
- # @return [Boolean] Whether {PostHog.init} has created a client.
63
- def initialized?
64
- !@client.nil?
65
- end
66
-
67
- # Fallback for any client methods not explicitly defined.
68
- #
69
- # @api private
70
- def method_missing(method_name, ...)
71
- ensure_initialized!
72
-
73
- if client.respond_to?(method_name)
74
- client.public_send(method_name, ...)
75
- else
76
- super
77
- end
78
- end
79
-
80
- # @api private
81
- def respond_to_missing?(method_name, include_private = false)
82
- ensure_initialized!
83
- client.respond_to?(method_name, include_private) || super
84
- end
85
-
86
- private
87
-
88
- def ensure_initialized!
89
- return if initialized?
90
-
91
- @client = PostHog::Client.new(api_key: nil, silence_disabled_client_error: true)
92
- end
93
- end
94
- end
11
+ PostHog::Rails.install_posthog_facade!
95
12
  end
96
13
 
97
14
  # Insert middleware for request context and exception capturing
data/lib/posthog/rails.rb CHANGED
@@ -12,6 +12,7 @@ require 'posthog/rails/logs/severity'
12
12
  require 'posthog/rails/logs/rate_limiter'
13
13
  require 'posthog/rails/logs/appender'
14
14
  require 'posthog/rails/logs/setup'
15
+ require 'posthog/rails/facade'
15
16
  require 'posthog/rails/railtie'
16
17
 
17
18
  module PostHog
@@ -63,3 +64,5 @@ module PostHog
63
64
  end
64
65
  end
65
66
  end
67
+
68
+ PostHog::Rails.install_posthog_facade!
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: posthog-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.12.2
4
+ version: 3.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - PostHog
@@ -29,14 +29,14 @@ dependencies:
29
29
  requirements:
30
30
  - - "~>"
31
31
  - !ruby/object:Gem::Version
32
- version: '3.12'
32
+ version: '3.13'
33
33
  type: :runtime
34
34
  prerelease: false
35
35
  version_requirements: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: '3.12'
39
+ version: '3.13'
40
40
  description: Automatic exception tracking and instrumentation for Ruby on Rails applications
41
41
  using PostHog
42
42
  email: engineering@posthog.com
@@ -52,6 +52,7 @@ files:
52
52
  - lib/posthog/rails/capture_exceptions.rb
53
53
  - lib/posthog/rails/configuration.rb
54
54
  - lib/posthog/rails/error_subscriber.rb
55
+ - lib/posthog/rails/facade.rb
55
56
  - lib/posthog/rails/logs/appender.rb
56
57
  - lib/posthog/rails/logs/rate_limiter.rb
57
58
  - lib/posthog/rails/logs/setup.rb