peak_flow_utils 0.1.19 → 0.1.21

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: bbb8a48ea294481df8df3c87b5b17eca7c7b2715027a512655f66a318acb8e2e
4
- data.tar.gz: 1970d5b4843db5df6396e12d6cacfa70049af0ac8946f4e7243d3a7f70b5d981
3
+ metadata.gz: 228e66c09e2025f5df9ad150b660a3a8dabac0e1eececf027383206c3231714d
4
+ data.tar.gz: 6e245675c567304fbdcace379d668b1683a94999e80b3473e35a970e3d20c5dc
5
5
  SHA512:
6
- metadata.gz: d1866c116955f38e9f2dc3c2e06fbeca908ed4c0bb425348a82fa8f1522fcfb1e47d1c96fe1a32328bd44f439f26dfddb97285dd0c19b0725f5241dcdb671d51
7
- data.tar.gz: ac9fa1d930c30b5d32d450b10bd2af6ec95ead713b64e686ab07de7cbec5db94e5b4048e0a16e13657d06f1d483a5d4252d1c3d4068e188cfcd4586cc55a1349
6
+ metadata.gz: 0cbaad9919787a02b65b6e84413ef6a1f193ade8cf2b8d650f73138af2dfb7fd42b7850f988cd3459621ac10659a1eb2a562ea1184a41d87b78ded1b68c3b460
7
+ data.tar.gz: ea68e773ede1c61dbe304ddc29ba9b4626f215572455f5da7c8ba9ebf71a9974ad09473b96837f85243596a387649e5250b72540c6dfa8611052c55aa6d585ae
@@ -2,7 +2,7 @@ class PeakFlowUtils::FileHandler < PeakFlowUtils::ApplicationHandler
2
2
  def groups
3
3
  ArrayEnumerator.new do |yielder|
4
4
  erb_inspector.files.each do |file|
5
- id = file.file_path.gsub(/[^A-z0-9]/, "_")
5
+ id = file.file_path.gsub(/[^A-Za-z0-9]/, "_")
6
6
 
7
7
  group = PeakFlowUtils::GroupService.new(
8
8
  id: id,
@@ -79,7 +79,7 @@ private
79
79
  yielder << PeakFlowUtils::TranslationService.new(
80
80
  key: "activerecord.errors.models.#{snake_clazz_name}.attributes.#{attribute_name}.#{key}",
81
81
  key_show: "#{attribute_name}.#{key}",
82
- dir: "#{Rails.root}/config/locales/awesome_translations/models/#{snake_clazz_name}"
82
+ dir: Rails.root.join("config/locales/awesome_translations/models/#{snake_clazz_name}").to_s
83
83
  )
84
84
  end
85
85
  end
@@ -0,0 +1,33 @@
1
+ class PeakFlowUtils::ActiveRecordQuery
2
+ class SlowSQLError < RuntimeError; end
3
+
4
+ attr_reader :event
5
+
6
+ def initialize(event)
7
+ @event = event
8
+ end
9
+
10
+ def perform
11
+ report_slow_sql if duration_seconds >= 3
12
+ end
13
+
14
+ def duration_seconds
15
+ @duration_seconds ||= event.duration / 1000
16
+ end
17
+
18
+ def report_slow_sql
19
+ PeakFlowUtils::Notifier.with_parameters(sql: sql, duration_seconds: duration_seconds) do
20
+ raise SlowSQLError, "Slow SQL: #{sql_as_single_line}"
21
+ rescue StandardError => e
22
+ PeakFlowUtils::Notifier.notify(error: e)
23
+ end
24
+ end
25
+
26
+ def sql
27
+ @sql ||= event.payload.fetch(:sql)
28
+ end
29
+
30
+ def sql_as_single_line
31
+ @sql_as_single_line ||= sql.tr("\n", " ")
32
+ end
33
+ end
@@ -1,5 +1,3 @@
1
1
  class PeakFlowUtils::ApplicationMigration < ActiveRecord::Migration[5.1]
2
- def connection
3
- PeakFlowUtils::ApplicationRecord.connection
4
- end
2
+ delegate :connection, to: :"PeakFlowUtils::ApplicationRecord"
5
3
  end
@@ -3,7 +3,7 @@ class PeakFlowUtils::DatabaseInitializerService < PeakFlowUtils::ApplicationServ
3
3
  path = File.realpath("#{__dir__}/../../../lib/peak_flow_utils/migrations")
4
4
  create_schema_table unless schema_table_exists?
5
5
 
6
- Dir["#{path}/[0-9]*_*.rb"].sort.map do |filename|
6
+ Dir["#{path}/[0-9]*_*.rb"].map do |filename|
7
7
  match = filename.match(/migrations\/(\d+)_(.+)\.rb\Z/)
8
8
  next unless match
9
9
 
@@ -132,6 +132,6 @@ private
132
132
  end
133
133
 
134
134
  def translation_with_key_exists?(translations_found, translation_full_key)
135
- translations_found.select { |t| t.full_key == translation_full_key }.any?
135
+ translations_found.any? { |t| t.full_key == translation_full_key }
136
136
  end
137
137
  end
@@ -92,7 +92,7 @@ private
92
92
  def generate_dir
93
93
  parts = %w[config locales awesome_translations]
94
94
 
95
- key_parts = @full_key.split(".").reject(&:blank?)
95
+ key_parts = @full_key.split(".").compact_blank
96
96
  key_parts.pop
97
97
 
98
98
  @dir = Rails.root.join(*(parts + key_parts)).to_s
@@ -3,11 +3,7 @@ class PeakFlowUtils::ErbInspector
3
3
  @args = args
4
4
  @args[:exts] ||= [".erb", ".haml", ".liquid", ".markerb", ".rb", ".rake", ".slim", "."] + PeakFlowUtils::ErbInspector::FileInspector::JS_FILE_EXTS
5
5
 
6
- if @args[:dirs]
7
- @dirs = @args[:dirs]
8
- else
9
- @dirs = PeakFlowUtils::ConfigurationService.current.paths_to_translate
10
- end
6
+ @dirs = @args[:dirs] || PeakFlowUtils::ConfigurationService.current.paths_to_translate
11
7
  end
12
8
 
13
9
  # Yields all relevant .erb- and .haml-files.
@@ -6,7 +6,7 @@ class PeakFlowUtils::ModelInspector
6
6
  # Yields a model-inspector for each model found in the application.
7
7
  def self.model_classes
8
8
  # Make sure all models are loaded.
9
- load_models
9
+ load_models!
10
10
 
11
11
  @scanned = {}
12
12
  @yielded = {}
@@ -92,20 +92,20 @@ class PeakFlowUtils::ModelInspector
92
92
  to_s
93
93
  end
94
94
 
95
- def self.find_subclasses(clazz, &blk)
95
+ def self.find_subclasses(clazz, &)
96
96
  return if @scanned[clazz.name]
97
97
 
98
98
  @scanned[clazz.name] = true
99
99
 
100
100
  clazz.subclasses.each do |subclass|
101
- blk.call ::PeakFlowUtils::ModelInspector.new(subclass)
102
- find_subclasses(subclass, &blk)
101
+ yield ::PeakFlowUtils::ModelInspector.new(subclass)
102
+ find_subclasses(subclass, &)
103
103
  end
104
104
  end
105
105
 
106
106
  # Preloads all models for Rails app and all engines (if they aren't loaded, then they cant be inspected).
107
- def self.load_models
108
- return false if PeakFlowUtils::ModelInspector.models_loaded
107
+ def self.load_models!
108
+ return if PeakFlowUtils::ModelInspector.models_loaded
109
109
 
110
110
  PeakFlowUtils::ModelInspector.models_loaded = true
111
111
 
@@ -113,8 +113,6 @@ class PeakFlowUtils::ModelInspector
113
113
  engines.each do |engine|
114
114
  load_models_for(engine.root)
115
115
  end
116
-
117
- true
118
116
  end
119
117
 
120
118
  def self.engines
@@ -123,7 +121,7 @@ class PeakFlowUtils::ModelInspector
123
121
 
124
122
  # Loads models for the given app-directory (Rails-root or engine).
125
123
  def self.load_models_for(root)
126
- Dir.glob("#{root}/app/models/**/*.rb").sort.each do |model_path|
124
+ Dir.glob("#{root}/app/models/**/*.rb").each do |model_path|
127
125
  require model_path
128
126
  rescue StandardError => e
129
127
  warn "Could not load model in #{model_path}"
@@ -100,7 +100,7 @@ class PeakFlowUtils::TranslationsParserService < PeakFlowUtils::ApplicationServi
100
100
  private
101
101
 
102
102
  def debug(message)
103
- puts message.to_s if @debug # rubocop:disable Rails/Output
103
+ puts message if @debug # rubocop:disable Rails/Output
104
104
  end
105
105
 
106
106
  def perform_migrations
@@ -2,6 +2,6 @@ require "rails"
2
2
 
3
3
  module PeakFlowUtils; end
4
4
 
5
- class PeakFlowUtils::Engine < ::Rails::Engine
5
+ class PeakFlowUtils::Engine < Rails::Engine
6
6
  isolate_namespace PeakFlowUtils
7
7
  end
@@ -2,7 +2,9 @@ require "monitor"
2
2
  require_relative "thread_callbacks_patch"
3
3
 
4
4
  Thread.on_initialize do |parent:, thread:|
5
- thread.instance_variable_set(:@_inherited_local_vars, parent.instance_variable_get(:@_inherited_local_vars))
5
+ parent_vars = parent.instance_variable_get(:@_inherited_local_vars)
6
+ new_cloned_vars = PeakFlowUtils::DeepMerger.execute!(hashes: [parent_vars])
7
+ thread.instance_variable_set(:@_inherited_local_vars, new_cloned_vars)
6
8
  end
7
9
 
8
10
  Thread.class_eval do
@@ -57,8 +59,13 @@ end
57
59
  class PeakFlowUtils::InheritedLocalVar
58
60
  attr_reader :identifier
59
61
 
62
+ def self.identifier_for_object_id(object_id)
63
+ "inherited_local_var_#{object_id}"
64
+ end
65
+
60
66
  def self.finalize(inherited_local_var_object_id)
61
- Thread.inherited_local_vars_delete("inherited_local_var_#{inherited_local_var_object_id}")
67
+ identifier = PeakFlowUtils::InheritedLocalVar.identifier_for_object_id(inherited_local_var_object_id)
68
+ Thread.inherited_local_vars_delete(identifier)
62
69
  rescue Exception => e # rubocop:disable Lint/RescueException
63
70
  puts e.inspect # rubocop:disable Rails/Output
64
71
  puts e.backtrace # rubocop:disable Rails/Output
@@ -68,9 +75,7 @@ class PeakFlowUtils::InheritedLocalVar
68
75
 
69
76
  def initialize(new_value = nil)
70
77
  ObjectSpace.define_finalizer(self, PeakFlowUtils::InheritedLocalVar.method(:finalize))
71
-
72
- @identifier = "inherited_local_var_#{__id__}"
73
-
78
+ @identifier = PeakFlowUtils::InheritedLocalVar.identifier_for_object_id(__id__)
74
79
  Thread.inherited_local_vars_set(identifier => new_value)
75
80
  end
76
81
 
@@ -6,7 +6,7 @@ class PeakFlowUtils::Group < PeakFlowUtils::ApplicationRecord
6
6
  has_many :handler_translations, dependent: :destroy
7
7
  has_many :translation_keys, dependent: :destroy
8
8
 
9
- validates :name, :handler, presence: true
9
+ validates :name, presence: true
10
10
 
11
11
  def at_handler
12
12
  @at_handler ||= handler.at_handler
@@ -3,7 +3,6 @@ class PeakFlowUtils::HandlerText < PeakFlowUtils::ApplicationRecord
3
3
  belongs_to :handler
4
4
  belongs_to :translation_key
5
5
 
6
- validates :handler, :translation_key, presence: true
7
6
 
8
7
  delegate :key, :last_key, to: :translation_key
9
8
  delegate :value, to: :translation, prefix: true
@@ -1,7 +1,6 @@
1
1
  class PeakFlowUtils::TranslationValue < PeakFlowUtils::ApplicationRecord
2
2
  belongs_to :translation_key
3
3
 
4
- validates :translation_key, presence: true
5
4
 
6
5
  delegate :key, to: :translation_key
7
6
 
@@ -10,7 +9,9 @@ class PeakFlowUtils::TranslationValue < PeakFlowUtils::ApplicationRecord
10
9
  end
11
10
 
12
11
  def handler_translation
13
- @handler_translation ||= PeakFlowUtils::HandlerText
12
+ return @handler_translation if defined?(@handler_translation)
13
+
14
+ @handler_translation = PeakFlowUtils::HandlerText
14
15
  .find_by(translation_key_id: translation_key_id)
15
16
  end
16
17
 
@@ -13,12 +13,12 @@ class PeakFlowUtils::Notifier
13
13
  @current
14
14
  end
15
15
 
16
- def self.notify(*args, **opts, &blk)
17
- PeakFlowUtils::Notifier.current&.notify(*args, **opts, &blk)
16
+ def self.notify(...)
17
+ PeakFlowUtils::Notifier.current&.notify(...)
18
18
  end
19
19
 
20
- def self.notify_message(*args, **opts, &blk)
21
- PeakFlowUtils::Notifier.current&.notify_message(*args, **opts, &blk)
20
+ def self.notify_message(...)
21
+ PeakFlowUtils::Notifier.current&.notify_message(...)
22
22
  end
23
23
 
24
24
  def self.reset_parameters
@@ -54,6 +54,7 @@ class PeakFlowUtils::Notifier
54
54
  def initialize(auth_token:)
55
55
  @auth_token = auth_token
56
56
  @mutex = ::Mutex.new
57
+ @on_notify_callbacks = []
57
58
  @parameters = ::PeakFlowUtils::InheritedLocalVar.new({})
58
59
  end
59
60
 
@@ -80,6 +81,7 @@ class PeakFlowUtils::Notifier
80
81
  end
81
82
 
82
83
  def notify(error:, environment: nil, parameters: nil)
84
+ error = normalize_error(error, fallback_backtrace: caller(2))
83
85
  error_parser = ::PeakFlowUtils::NotifierErrorParser.new(
84
86
  backtrace: error.backtrace,
85
87
  environment: environment,
@@ -90,6 +92,10 @@ class PeakFlowUtils::Notifier
90
92
 
91
93
  uri = URI("https://www.peakflow.io/errors/reports")
92
94
 
95
+ @on_notify_callbacks.each do |on_notify_callback|
96
+ on_notify_callback.call(parameters: merged_parameters)
97
+ end
98
+
93
99
  data = {
94
100
  auth_token: auth_token,
95
101
  error: {
@@ -109,10 +115,14 @@ class PeakFlowUtils::Notifier
109
115
  send_notify_request(data: PeakFlowUtils::ParseJson.new(data).parse, uri: uri)
110
116
  end
111
117
 
112
- def notify_message(message, **opts)
118
+ def notify_message(message, **)
113
119
  raise NotifyMessageError, message
114
120
  rescue NotifyMessageError => e
115
- notify(error: e, **opts)
121
+ notify(error: e, **)
122
+ end
123
+
124
+ def on_notify(&blk)
125
+ @on_notify_callbacks << blk
116
126
  end
117
127
 
118
128
  def send_notify_request(data:, uri:)
@@ -138,4 +148,18 @@ class PeakFlowUtils::Notifier
138
148
  url: response_data["url"]
139
149
  )
140
150
  end
151
+
152
+ private
153
+
154
+ def normalize_error(error, fallback_backtrace:)
155
+ error = RuntimeError.new(error) if error.is_a?(String)
156
+
157
+ if error.backtrace.blank?
158
+ backtrace = fallback_backtrace
159
+ backtrace = caller(1) if backtrace.blank?
160
+ error.set_backtrace(backtrace)
161
+ end
162
+
163
+ error
164
+ end
141
165
  end
@@ -0,0 +1,8 @@
1
+ class PeakFlowUtils::NotifierActiveRecord
2
+ def self.configure
3
+ ActiveSupport::Notifications.subscribe("sql.active_record") do |*args|
4
+ event = ActiveSupport::Notifications::Event.new(*args)
5
+ PeakFlowUtils::ActiveRecordQuery.new(event).perform
6
+ end
7
+ end
8
+ end
@@ -11,7 +11,7 @@ class PeakFlowUtils::NotifierErrorParser
11
11
 
12
12
  def detect_file_path_and_line_number
13
13
  backtrace.each do |trace|
14
- match = trace.match(/^((.+)\.([A-z]{2,4})):(\d+)(:|$)/)
14
+ match = trace.match(/^((.+)\.([A-Za-z]{2,4})):(\d+)(:|$)/)
15
15
  next unless match
16
16
 
17
17
  file_path = match[1]
@@ -12,12 +12,12 @@ class Thread
12
12
  count_to_use
13
13
  end
14
14
 
15
- def initialize(*args, &block)
15
+ def initialize(*, &)
16
16
  @@on_initialize_callbacks ||= {} # rubocop:disable Style/ClassVars
17
17
  @@on_initialize_callbacks.each_value do |callback|
18
18
  callback.call(parent: Thread.current, thread: self)
19
19
  end
20
20
 
21
- _initialize(*args, &block)
21
+ _initialize(*, &)
22
22
  end
23
23
  end
@@ -1,3 +1,3 @@
1
1
  module PeakFlowUtils
2
- VERSION = "0.1.19".freeze
2
+ VERSION = "0.1.21".freeze
3
3
  end
@@ -10,6 +10,7 @@ module PeakFlowUtils
10
10
 
11
11
  autoload :InheritedLocalVar, "#{path}/inherited_local_var"
12
12
  autoload :Notifier, "#{path}/notifier"
13
+ autoload :NotifierActiveRecord, "#{path}/notifier_active_record"
13
14
  autoload :NotifierErrorParser, "#{path}/notifier_error_parser"
14
15
  autoload :NotifierRack, "#{path}/notifier_rack"
15
16
  autoload :NotifierRails, "#{path}/notifier_rails"
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: peak_flow_utils
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.19
4
+ version: 0.1.21
5
5
  platform: ruby
6
6
  authors:
7
7
  - kaspernj
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2024-06-13 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: rails
@@ -53,41 +52,13 @@ dependencies:
53
52
  - !ruby/object:Gem::Version
54
53
  version: '0'
55
54
  - !ruby/object:Gem::Dependency
56
- name: service_pattern
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: 1.0.5
62
- type: :runtime
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: 1.0.5
69
- - !ruby/object:Gem::Dependency
70
- name: appraisal
55
+ name: bigdecimal
71
56
  requirement: !ruby/object:Gem::Requirement
72
57
  requirements:
73
58
  - - ">="
74
59
  - !ruby/object:Gem::Version
75
60
  version: '0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
- - !ruby/object:Gem::Dependency
84
- name: pry-rails
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: '0'
90
- type: :development
61
+ type: :runtime
91
62
  prerelease: false
92
63
  version_requirements: !ruby/object:Gem::Requirement
93
64
  requirements:
@@ -95,13 +66,13 @@ dependencies:
95
66
  - !ruby/object:Gem::Version
96
67
  version: '0'
97
68
  - !ruby/object:Gem::Dependency
98
- name: redis
69
+ name: drb
99
70
  requirement: !ruby/object:Gem::Requirement
100
71
  requirements:
101
72
  - - ">="
102
73
  - !ruby/object:Gem::Version
103
74
  version: '0'
104
- type: :development
75
+ type: :runtime
105
76
  prerelease: false
106
77
  version_requirements: !ruby/object:Gem::Requirement
107
78
  requirements:
@@ -109,13 +80,13 @@ dependencies:
109
80
  - !ruby/object:Gem::Version
110
81
  version: '0'
111
82
  - !ruby/object:Gem::Dependency
112
- name: sidekiq
83
+ name: mutex_m
113
84
  requirement: !ruby/object:Gem::Requirement
114
85
  requirements:
115
86
  - - ">="
116
87
  - !ruby/object:Gem::Version
117
88
  version: '0'
118
- type: :development
89
+ type: :runtime
119
90
  prerelease: false
120
91
  version_requirements: !ruby/object:Gem::Requirement
121
92
  requirements:
@@ -123,19 +94,19 @@ dependencies:
123
94
  - !ruby/object:Gem::Version
124
95
  version: '0'
125
96
  - !ruby/object:Gem::Dependency
126
- name: tzinfo-data
97
+ name: service_pattern
127
98
  requirement: !ruby/object:Gem::Requirement
128
99
  requirements:
129
100
  - - ">="
130
101
  - !ruby/object:Gem::Version
131
- version: '0'
132
- type: :development
102
+ version: 1.0.5
103
+ type: :runtime
133
104
  prerelease: false
134
105
  version_requirements: !ruby/object:Gem::Requirement
135
106
  requirements:
136
107
  - - ">="
137
108
  - !ruby/object:Gem::Version
138
- version: '0'
109
+ version: 1.0.5
139
110
  description: Utilities to be used with PeakFlow.
140
111
  email:
141
112
  - k@spernj.org
@@ -158,6 +129,7 @@ files:
158
129
  - app/handlers/peak_flow_utils/validations_handler.rb
159
130
  - app/handlers/peak_flow_utils/will_paginate_handler.rb
160
131
  - app/services/peak_flow_utils/active_job_parameters_logging.rb
132
+ - app/services/peak_flow_utils/active_record_query.rb
161
133
  - app/services/peak_flow_utils/application_migration.rb
162
134
  - app/services/peak_flow_utils/application_service.rb
163
135
  - app/services/peak_flow_utils/attribute_service.rb
@@ -193,6 +165,7 @@ files:
193
165
  - lib/peak_flow_utils/models/translation_key.rb
194
166
  - lib/peak_flow_utils/models/translation_value.rb
195
167
  - lib/peak_flow_utils/notifier.rb
168
+ - lib/peak_flow_utils/notifier_active_record.rb
196
169
  - lib/peak_flow_utils/notifier_error_parser.rb
197
170
  - lib/peak_flow_utils/notifier_rack.rb
198
171
  - lib/peak_flow_utils/notifier_rails.rb
@@ -204,8 +177,8 @@ files:
204
177
  homepage: https://github.com/kaspernj/peak_flow_utils
205
178
  licenses:
206
179
  - MIT
207
- metadata: {}
208
- post_install_message:
180
+ metadata:
181
+ rubygems_mfa_required: 'true'
209
182
  rdoc_options: []
210
183
  require_paths:
211
184
  - lib
@@ -213,15 +186,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
213
186
  requirements:
214
187
  - - ">="
215
188
  - !ruby/object:Gem::Version
216
- version: '2.5'
189
+ version: 3.4.0
217
190
  required_rubygems_version: !ruby/object:Gem::Requirement
218
191
  requirements:
219
192
  - - ">="
220
193
  - !ruby/object:Gem::Version
221
194
  version: '0'
222
195
  requirements: []
223
- rubygems_version: 3.5.3
224
- signing_key:
196
+ rubygems_version: 3.6.9
225
197
  specification_version: 4
226
198
  summary: Utilities to be used with PeakFlow.
227
199
  test_files: []