dial 0.5.0 → 0.5.2

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: 204280e63f9f71fe949ccc5497b5e12e207ae681314caf73063163f785b7126b
4
- data.tar.gz: 21c70e61114ef47f38e194b812c3b0f52aba68ba7976972b13700db90e1451a8
3
+ metadata.gz: 6cd83bb50a207183202f0f0f9775d060446a352cf88382252fdfc00c4dbb4de6
4
+ data.tar.gz: a84109907f3884386ce2122ba5173c33ebc8da6e1c900bb94439389a274887b7
5
5
  SHA512:
6
- metadata.gz: e94c02266b0abd60727413d95bf7ec6238466dfa03725c904dac9443d1be63c448e05e7099d2c5ea44f7c153b155f8dd6176ca972103a0a3778bd8d7076b2f6e
7
- data.tar.gz: a6207c9decc7cdd7c009e6d85b38745a53c49b9703740ea35c143ebbbe9f347784136c718f902de4050e9f7dbc02d9b339b3f0a3e28332db3d43c1105d25191a
6
+ metadata.gz: b1e2a82ea64022c1dcf83f5fc5ae7cdfc3f53794552c9752f4d39f4f490bfcbc25bb3b1632b211ba08c4e4af7c1dd22483c037d06cf2b59dcda44b9d36c92bd7
7
+ data.tar.gz: 27075354578df3d541fdacb9704959c097a4cd2a128653b8e67b57424b64d934e5c50e1f335a33111012ba2f87b381048cde8ac4d12961dce86cea4059edf54d
data/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.5.2] - 2025-10-04
4
+
5
+ - Preserve existing prosopite custom loggers
6
+
7
+ ## [0.5.1] - 2025-09-27
8
+
9
+ - Don't clean up stale storage data in railtie
10
+ - Add enabled configuration option and force parameter for per-request profiling
11
+
3
12
  ## [0.5.0] - 2025-09-21
4
13
 
5
14
  - Add storage interface with Redis cluster and Memcached adapters for distributed deployments
data/README.md CHANGED
@@ -41,9 +41,15 @@ mount Dial::Engine, at: "/"
41
41
  # config/initializers/dial.rb
42
42
 
43
43
  Dial.configure do |config|
44
- config.sampling_percentage = 50
45
- config.storage = Dial::Storage::RedisAdapter
46
- config.storage_options = { client: Redis.new(url: ENV["REDIS_URL"]), ttl: 86400 }
44
+ config.enabled = !Rails.env.production? # disable by default in production, use force_param to enable per request
45
+ config.force_param = "profile" # override param name to force profiling
46
+ if Rails.env.staging?
47
+ config.sampling_percentage = 50 # override sampling percentage in staging for A/B testing profiler impact
48
+ end
49
+ unless Rails.env.development?
50
+ config.storage = Dial::Storage::RedisAdapter # use Redis storage in non-development environments
51
+ config.storage_options = { client: Redis.new(url: ENV["REDIS_URL"]), ttl: 86400 }
52
+ end
47
53
  config.vernier_interval = 100
48
54
  config.vernier_allocation_interval = 10_000
49
55
  config.prosopite_ignore_queries += [/pg_sleep/i]
@@ -54,9 +60,11 @@ end
54
60
 
55
61
  Option | Description | Default
56
62
  :- | :- | :-
63
+ `enabled` | Whether profiling is enabled. | `true`
64
+ `force_param` | Request parameter name to force profiling even when disabled. Always profiles (bypasses sampling). | `"dial_force"`
57
65
  `sampling_percentage` | Percentage of requests to profile. | `100` in development, `1` in production
58
- `storage` | Storage adapter class for profile data | `Dial::Storage::FileAdapter`
59
- `storage_options` | Options hash passed to storage adapter | `{ ttl: 3600 }`
66
+ `storage` | Storage adapter class for profile data. | `Dial::Storage::FileAdapter`
67
+ `storage_options` | Options hash passed to storage adapter. | `{ ttl: 3600 }`
60
68
  `content_security_policy_nonce` | Sets the content security policy nonce to use when inserting Dial's script. Can be a string, or a Proc which receives `env` and response `headers` as arguments and returns the nonce string. | Rails generated nonce or `nil`
61
69
  `vernier_interval` | Sets the `interval` option for vernier. | `200`
62
70
  `vernier_allocation_interval` | Sets the `allocation_interval` option for vernier. | `2_000`
@@ -12,8 +12,10 @@ module Dial
12
12
  class Configuration
13
13
  def initialize
14
14
  @options = {
15
- sampling_percentage: default_sampling_percentage,
16
- storage: default_storage,
15
+ enabled: true,
16
+ force_param: FORCE_PARAM,
17
+ sampling_percentage: ::Rails.env.development? ? SAMPLING_PERCENTAGE_DEV : SAMPLING_PERCENTAGE_PROD,
18
+ storage: Storage::FileAdapter,
17
19
  storage_options: { ttl: STORAGE_TTL },
18
20
  content_security_policy_nonce: -> env, _headers { env[NONCE] || EMPTY_NONCE },
19
21
  vernier_interval: VERNIER_INTERVAL,
@@ -37,15 +39,5 @@ module Dial
37
39
 
38
40
  super
39
41
  end
40
-
41
- private
42
-
43
- def default_sampling_percentage
44
- ::Rails.env.development? ? SAMPLING_PERCENTAGE_DEV : SAMPLING_PERCENTAGE_PROD
45
- end
46
-
47
- def default_storage
48
- Storage::FileAdapter
49
- end
50
42
  end
51
43
  end
@@ -16,6 +16,7 @@ module Dial
16
16
  NONCE = ::ActionDispatch::ContentSecurityPolicy::Request::NONCE
17
17
  REQUEST_TIMING = "dial_request_timing"
18
18
 
19
+ FORCE_PARAM = "dial_force"
19
20
  SAMPLING_PERCENTAGE_DEV = 100
20
21
  SAMPLING_PERCENTAGE_PROD = 1
21
22
  STORAGE_TTL = 60 * 60
@@ -22,7 +22,8 @@ module Dial
22
22
  return @app.call env
23
23
  end
24
24
 
25
- unless should_profile?
25
+ request = ::Rack::Request.new env
26
+ unless should_profile? request
26
27
  return @app.call env
27
28
  end
28
29
 
@@ -125,8 +126,12 @@ module Dial
125
126
  end
126
127
  end
127
128
 
128
- def should_profile?
129
- rand(100) < Dial._configuration.sampling_percentage
129
+ def should_profile? request
130
+ force_param = Dial._configuration.force_param
131
+ return true if request.params[force_param]
132
+
133
+ Dial._configuration.enabled &&
134
+ rand(100) < Dial._configuration.sampling_percentage
130
135
  end
131
136
  end
132
137
 
@@ -2,8 +2,35 @@
2
2
 
3
3
  require "active_support/core_ext/string/filters"
4
4
 
5
+ require_relative "prosopite_composite_logger"
6
+
5
7
  module Dial
6
8
  module Prosopite
9
+ def custom_logger= logger
10
+ return super logger if @setting_dial_logger
11
+
12
+ @original_logger = logger
13
+
14
+ if @dial_logger && @original_logger
15
+ super ProsopiteCompositeLogger.new @dial_logger, @original_logger
16
+ else
17
+ super logger
18
+ end
19
+ end
20
+
21
+ def dial_logger= logger
22
+ @dial_logger = logger
23
+
24
+ @setting_dial_logger = true
25
+ if @original_logger
26
+ self.custom_logger = ProsopiteCompositeLogger.new @dial_logger, @original_logger
27
+ else
28
+ self.custom_logger = @dial_logger
29
+ end
30
+ ensure
31
+ @setting_dial_logger = false
32
+ end
33
+
7
34
  def send_notifications
8
35
  tc[:prosopite_notifications] = tc[:prosopite_notifications].to_h do |queries, kaller|
9
36
  [queries.map { |query| query.squish }, kaller]
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "logger"
4
+
5
+ module Dial
6
+ class ProsopiteCompositeLogger
7
+ def initialize dial_logger, existing_logger = nil
8
+ @dial_logger = dial_logger
9
+ @existing_logger = existing_logger
10
+ end
11
+
12
+ def level
13
+ @dial_logger.level
14
+ end
15
+
16
+ def level= value
17
+ @dial_logger.level = value
18
+ @existing_logger.level = value if @existing_logger&.respond_to? :level=
19
+ end
20
+
21
+ def method_missing method, *args, &block
22
+ result = nil
23
+ result = @dial_logger.send method, *args, &block if @dial_logger.respond_to? method
24
+ @existing_logger.send method, *args, &block if @existing_logger&.respond_to? method
25
+ result
26
+ end
27
+
28
+ def respond_to_missing? method, include_private = false
29
+ @dial_logger.respond_to?(method, include_private) ||
30
+ @existing_logger&.respond_to?(method, include_private) ||
31
+ false
32
+ end
33
+ end
34
+ end
data/lib/dial/railtie.rb CHANGED
@@ -10,15 +10,12 @@ require_relative "prosopite_logger"
10
10
  module Dial
11
11
  class Railtie < ::Rails::Railtie
12
12
  initializer "dial.setup", after: :load_config_initializers do |app|
13
- # clean up stale storage data
14
- Storage.cleanup
15
-
16
13
  app.config.after_initialize do
17
14
  # set up prosopite
18
15
  if ::ActiveRecord::Base.configurations.configurations.any? { |config| config.adapter == "postgresql" }
19
16
  require "pg_query"
20
17
  end
21
- ::Prosopite.custom_logger = ProsopiteLogger.new
18
+ ::Prosopite.dial_logger = ProsopiteLogger.new
22
19
 
23
20
  # finalize configuration
24
21
  Dial._configuration.freeze
data/lib/dial/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Dial
4
- VERSION = "0.5.0"
4
+ VERSION = "0.5.2"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dial
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.5.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joshua Young
@@ -114,6 +114,7 @@ files:
114
114
  - lib/dial/middleware/rails_stat.rb
115
115
  - lib/dial/middleware/ruby_stat.rb
116
116
  - lib/dial/prosopite.rb
117
+ - lib/dial/prosopite_composite_logger.rb
117
118
  - lib/dial/prosopite_logger.rb
118
119
  - lib/dial/railtie.rb
119
120
  - lib/dial/storage.rb