rails_surrogate_key_logging 0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: d4508c5a982897fd625ce7ee7625cedd7a78691b42a6562f9e036e2577f54b91
4
+ data.tar.gz: 5d5b0395a7cb737fd5f1dc90f0dbbf74a493fcdb91ad8644a9e802584b649e9a
5
+ SHA512:
6
+ metadata.gz: 3201bc7f7e84b36813141a3c9e24883d1fd3a416ec4f05d6e6345fd46d063ebf494bcf39ca333f5292eed7ca845e0604d80f4907064b3db78aac6a496a477a08
7
+ data.tar.gz: 105d8ed9be27bf5e3f633f230b5836668793c45960628749b09e71570279d7f754207ce4275542fd886129975a6e342da0ac221c32c7ba4b81d27ddc49e12d68
data/README.md ADDED
@@ -0,0 +1 @@
1
+ # rails-surrogate-key-logging
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'surrogate_key_logging'
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'action_controller/log_subscriber'
4
+
5
+ module SurrogateKeyLogging
6
+ module ActionController
7
+ class LogSubscriber < ::ActionController::LogSubscriber
8
+
9
+ def start_processing(event)
10
+ event.payload[:params] = SurrogateKeyLogging.filter_parameters event.payload[:params]
11
+ super
12
+ end
13
+
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SurrogateKeyLogging
4
+ module ActionController
5
+ extend ActiveSupport::Autoload
6
+
7
+ autoload :LogSubscriber
8
+
9
+ end
10
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SurrogateKeyLogging
4
+ module ActionDispatch
5
+ module Request
6
+
7
+ def filtered_query_string
8
+ super.gsub(::ActionDispatch::Request::PAIR_RE) do |_|
9
+ SurrogateKeyLogging.filter_parameters(::Regexp.last_match(1) => ::Regexp.last_match(2)).first.join('=')
10
+ end
11
+ end
12
+
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SurrogateKeyLogging
4
+ module ActionDispatch
5
+ extend ActiveSupport::Autoload
6
+
7
+ autoload :Request
8
+
9
+ end
10
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/concern'
4
+
5
+ module SurrogateKeyLogging
6
+ module ActiveRecord
7
+ module Attributes
8
+ extend ActiveSupport::Concern
9
+
10
+ included do
11
+ surrogate_parent_names model_name.singular, model_name.plural
12
+ end
13
+
14
+ class_methods do
15
+ def surrogate_parent_names(*names)
16
+ @surrogate_parent_names ||= []
17
+ names.each do |name|
18
+ @surrogate_parent_names << name.to_sym
19
+ surrogate_attributes.each do |attr|
20
+ SurrogateKeyLogging.add_param_to_filter(attr, name)
21
+ end
22
+ end
23
+ @surrogate_parent_names
24
+ end
25
+
26
+ def surrogate_attributes(*attrs)
27
+ @surrogate_attributes ||= []
28
+ attrs.each do |attr|
29
+ @surrogate_attributes << attr.to_sym
30
+ surrogate_parent_names.each do |parent|
31
+ SurrogateKeyLogging.add_param_to_filter(attr, parent)
32
+ end
33
+ end
34
+ @surrogate_attributes
35
+ end
36
+ end
37
+
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SurrogateKeyLogging
4
+ module ActiveRecord
5
+ class LogSubscriber < ::ActiveRecord::LogSubscriber
6
+
7
+ def sql(event) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
8
+ self.class.runtime += event.duration
9
+ return unless logger.debug?
10
+
11
+ payload = event.payload
12
+
13
+ return if IGNORE_PAYLOAD_NAMES.include?(payload[:name])
14
+
15
+ name = "#{payload[:name]} (#{event.duration.round(1)}ms)"
16
+ name = "CACHE #{name}" if payload[:cached]
17
+ sql = payload[:sql]
18
+ binds = nil
19
+
20
+ name_match = /([A-Za-z]+) (Load|Update|Cache)/.match(payload[:name])
21
+ model = if name_match && name_match[1] && ::ActiveRecord::Base.descendants.map(&:to_s).include?(name_match[1])
22
+ name_match[1].safe_constantize
23
+ end
24
+
25
+ if payload[:binds]&.any?
26
+ casted_params = type_casted_binds(payload[:type_casted_binds])
27
+
28
+ binds = []
29
+ payload[:binds].each_with_index do |attr, i|
30
+ binds << render_bind(attr, casted_params[i], payload, model)
31
+ end
32
+ binds = binds.inspect
33
+ binds.prepend(' ')
34
+ end
35
+
36
+ name = colorize_payload_name(name, payload[:name])
37
+ sql = color(sql, sql_color(sql), true) if colorize_logging
38
+
39
+ debug " #{name} #{sql}#{binds}"
40
+ end
41
+
42
+ private
43
+
44
+ def basic_parameter_filter
45
+ @basic_parameter_filter ||= ::ActiveSupport::ParameterFilter.new(Rails.application.config.filter_parameters)
46
+ end
47
+
48
+ def type_casted_binds(casted_binds)
49
+ casted_binds.respond_to?(:call) ? casted_binds.call : casted_binds
50
+ end
51
+
52
+ def render_bind(attr, value, _payload, model) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
53
+ case attr
54
+ when ActiveModel::Attribute
55
+ value = "<#{attr.value_for_database.to_s.bytesize} bytes of binary data>" if attr.type.binary? && attr.value
56
+ when Array
57
+ attr = attr.first
58
+ else
59
+ attr = nil
60
+ end
61
+
62
+ attr_name = attr&.name
63
+ if model && attr_name && model.respond_to?(:surrogate_attributes) && model.surrogate_attributes.include?(attr_name.to_sym)
64
+ value = SurrogateKeyLogging.key_manager.call(attr_name, value, model.to_s.underscore)
65
+ elsif attr_name
66
+ value = basic_parameter_filter.filter(attr_name => value)[attr_name]
67
+ end
68
+ [attr_name, value]
69
+ end
70
+
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SurrogateKeyLogging
4
+ module ActiveRecord
5
+ extend ActiveSupport::Autoload
6
+
7
+ autoload :Attributes
8
+ autoload :LogSubscriber
9
+
10
+ end
11
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/parameter_filter'
4
+
5
+ # Add ability for @mask to be a class/instance/lambda/proc
6
+ module ActiveSupport
7
+ module ParameterFilter
8
+ class CompiledFilter
9
+
10
+ def value_for_key(key, value, parents = [], original_params = nil) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
11
+ parents.push(key) if deep_regexps
12
+ if regexps.any? { |r| r.match?(key.to_s) }
13
+ value = @mask.respond_to?(:call) ? @mask.call(key, value, parents, original_params) : @mask
14
+ elsif deep_regexps && (joined = parents.join('.')) && deep_regexps.any? { |r| r.match?(joined) } # rubocop:disable Lint/DuplicateBranch
15
+ value = @mask.respond_to?(:call) ? @mask.call(key, value, parents, original_params) : @mask
16
+ elsif value.is_a?(Hash)
17
+ value = call(value, parents, original_params)
18
+ elsif value.is_a?(Array)
19
+ # If we don't pop the current parent it will be duplicated as we
20
+ # process each array value.
21
+ parents.pop if deep_regexps
22
+ value = value.map { |v| value_for_key(key, v, parents, original_params) }
23
+ # Restore the parent stack after processing the array.
24
+ parents.push(key) if deep_regexps
25
+ elsif blocks.any?
26
+ key = key.dup if key.duplicable?
27
+ value = value.dup if value.duplicable?
28
+ blocks.each { |b| b.arity == 2 ? b.call(key, value) : b.call(key, value, original_params) }
29
+ end
30
+ parents.pop if deep_regexps
31
+ value
32
+ end
33
+
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SurrogateKeyLogging
4
+ class KeyManager
5
+
6
+ def call(key, value, _parents = [], _original_params = nil)
7
+ surrogate = "SK#{Digest::SHA512.hexdigest(value.to_s)}"
8
+ puts "surrogate for key: `#{key}`, value: `#{value}`, surrogate: `#{surrogate}`"
9
+ surrogate
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SurrogateKeyLogging
4
+ class Middleware
5
+ attr_reader :app
6
+
7
+ def initialize(app)
8
+ @app = app
9
+ puts 'surrogate new'
10
+ end
11
+
12
+ def call(env)
13
+ SurrogateKeyLogging.reset
14
+ @app.call(env)
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails'
4
+
5
+ module SurrogateKeyLogging
6
+ class Railtie < Rails::Railtie
7
+ railtie_name :surrogate_key_logging
8
+
9
+ initializer 'surrogate_key_logging.filter_parameters' do
10
+ puts 'surrogate_key_logging.filter_parameters'
11
+ end
12
+
13
+ initializer 'surrogate_key_logging.logs' do
14
+ puts 'surrogate_key_logging.logs'
15
+ ::ActiveRecord::LogSubscriber.detach_from(:active_record)
16
+ ::SurrogateKeyLogging::ActiveRecord::LogSubscriber.attach_to(:active_record)
17
+ ::ActiveSupport::LogSubscriber.detach_from(:action_controller)
18
+ ::SurrogateKeyLogging::ActionController::LogSubscriber.attach_to(:action_controller)
19
+ ::ActionDispatch::Request.include SurrogateKeyLogging::ActionDispatch::Request
20
+ end
21
+
22
+ initializer 'surrogate_key_logging.middleware' do
23
+ puts 'surrogate_key_logging.middleware'
24
+ Rails.application.config.middleware.insert_before 0, Middleware
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SurrogateKeyLogging
4
+
5
+ module Version
6
+ MAJOR = 0
7
+ MINOR = 0
8
+ PATCH = 1
9
+
10
+ end
11
+
12
+ VERSION = [
13
+ Version::MAJOR,
14
+ Version::MINOR,
15
+ Version::PATCH,
16
+ ].join('.').freeze
17
+
18
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support'
4
+
5
+ # Container Module
6
+ module SurrogateKeyLogging
7
+ extend ActiveSupport::Autoload
8
+
9
+ autoload :Railtie
10
+ autoload :Version
11
+ autoload :ActionController
12
+ autoload :ActionDispatch
13
+ autoload :ActiveSupport
14
+ autoload :ActiveRecord
15
+ autoload :KeyManager
16
+ autoload :Middleware
17
+
18
+ class << self
19
+
20
+ def surrogate_attributes(*attrs)
21
+ @surrogate_attributes ||= []
22
+ attrs.each do |attr|
23
+ @surrogate_attributes << attr.to_s
24
+ end
25
+ @surrogate_attributes
26
+ end
27
+
28
+ def reset
29
+ @key_manager = @parameter_filter = nil
30
+ end
31
+
32
+ def key_manager
33
+ @key_manager ||= KeyManager.new
34
+ end
35
+
36
+ def parameter_filter
37
+ @parameter_filter ||= ::ActiveSupport::ParameterFilter.new(surrogate_attributes, mask: key_manager)
38
+ end
39
+
40
+ def filter_parameters(params)
41
+ parameter_filter.filter params
42
+ end
43
+
44
+ def add_param_to_filter(attr, parent = nil)
45
+ if parent.nil?
46
+ surrogate_attributes attr.to_s
47
+ else
48
+ surrogate_attributes(
49
+ "#{parent}.#{attr}",
50
+ "#{parent}[#{attr}]",
51
+ "[#{parent}][#{attr}]"
52
+ )
53
+ end
54
+ end
55
+
56
+ end
57
+
58
+ end
59
+
60
+ require 'surrogate_key_logging/railtie'
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ $LOAD_PATH << File.join(File.dirname(__FILE__), 'lib')
4
+ require 'surrogate_key_logging/version'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = 'rails_surrogate_key_logging'
8
+ s.version = SurrogateKeyLogging::VERSION
9
+ s.authors = ['Taylor Yelverton']
10
+ s.email = 'rubygems@yelvert.io'
11
+ s.homepage = 'https://github.com/ComplyMD/rails_surrogate_key_logging'
12
+ s.summary = ''
13
+ s.license = 'MIT'
14
+ s.description = ''
15
+ s.metadata = {
16
+ 'bug_tracker_uri' => 'https://github.com/ComplyMD/rails_surrogate_key_logging/issues',
17
+ 'changelog_uri' => 'https://github.com/ComplyMD/rails_surrogate_key_logging/commits/master',
18
+ 'documentation_uri' => 'https://github.com/ComplyMD/rails_surrogate_key_logging/wiki',
19
+ 'homepage_uri' => 'https://github.com/ComplyMD/rails_surrogate_key_logging',
20
+ 'source_code_uri' => 'https://github.com/ComplyMD/rails_surrogate_key_logging',
21
+ 'rubygems_mfa_required' => 'true',
22
+ }
23
+
24
+ s.files = Dir['lib/**/*', 'README.md', 'MIT-LICENSE', 'rails_surrogate_key_logging.gemspec']
25
+
26
+ s.require_paths = %w[ lib ]
27
+
28
+ s.required_ruby_version = '>= 2.7.0'
29
+
30
+ s.add_dependency('actionpack', '>= 6.0.0')
31
+ s.add_dependency('activerecord', '>= 6.0.0')
32
+ s.add_dependency('activesupport', '>= 6.0.0')
33
+ s.add_dependency('railties', '>= 6.0.0')
34
+ end
metadata ADDED
@@ -0,0 +1,120 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rails_surrogate_key_logging
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Taylor Yelverton
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-01-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: actionpack
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 6.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 6.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: activerecord
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 6.0.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 6.0.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: activesupport
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 6.0.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 6.0.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: railties
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: 6.0.0
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: 6.0.0
69
+ description: ''
70
+ email: rubygems@yelvert.io
71
+ executables: []
72
+ extensions: []
73
+ extra_rdoc_files: []
74
+ files:
75
+ - README.md
76
+ - lib/rails_surrogate_key_logging.rb
77
+ - lib/surrogate_key_logging.rb
78
+ - lib/surrogate_key_logging/action_controller.rb
79
+ - lib/surrogate_key_logging/action_controller/log_subscriber.rb
80
+ - lib/surrogate_key_logging/action_dispatch.rb
81
+ - lib/surrogate_key_logging/action_dispatch/request.rb
82
+ - lib/surrogate_key_logging/active_record.rb
83
+ - lib/surrogate_key_logging/active_record/attributes.rb
84
+ - lib/surrogate_key_logging/active_record/log_subscriber.rb
85
+ - lib/surrogate_key_logging/active_support.rb
86
+ - lib/surrogate_key_logging/key_manager.rb
87
+ - lib/surrogate_key_logging/middleware.rb
88
+ - lib/surrogate_key_logging/railtie.rb
89
+ - lib/surrogate_key_logging/version.rb
90
+ - rails_surrogate_key_logging.gemspec
91
+ homepage: https://github.com/ComplyMD/rails_surrogate_key_logging
92
+ licenses:
93
+ - MIT
94
+ metadata:
95
+ bug_tracker_uri: https://github.com/ComplyMD/rails_surrogate_key_logging/issues
96
+ changelog_uri: https://github.com/ComplyMD/rails_surrogate_key_logging/commits/master
97
+ documentation_uri: https://github.com/ComplyMD/rails_surrogate_key_logging/wiki
98
+ homepage_uri: https://github.com/ComplyMD/rails_surrogate_key_logging
99
+ source_code_uri: https://github.com/ComplyMD/rails_surrogate_key_logging
100
+ rubygems_mfa_required: 'true'
101
+ post_install_message:
102
+ rdoc_options: []
103
+ require_paths:
104
+ - lib
105
+ required_ruby_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: 2.7.0
110
+ required_rubygems_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ requirements: []
116
+ rubygems_version: 3.1.4
117
+ signing_key:
118
+ specification_version: 4
119
+ summary: ''
120
+ test_files: []