peak_flow_utils 0.1.15 → 0.1.16
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 +4 -4
- data/app/services/peak_flow_utils/deep_merger.rb +24 -7
- data/lib/peak_flow_utils/inherited_local_var.rb +84 -0
- data/lib/peak_flow_utils/notifier.rb +59 -47
- data/lib/peak_flow_utils/thread_callbacks_patch.rb +23 -0
- data/lib/peak_flow_utils/version.rb +1 -1
- data/lib/peak_flow_utils.rb +4 -0
- metadata +32 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c01a814a1aad134f668f7144f6addea59f8b8afdc75a2ae8ff2280dbe3a9867c
|
4
|
+
data.tar.gz: b6746741a1ff204c7b2a31319409d84a4529c14a55f8e9cfbf7b7fcad37eacea
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5a82e952b87453cfde4fbcb42fd43a0f2bca93f43dc2b3dbdca3109c6d25a21dd587745c602680d89c446cda1c1be251167b46248b98bc1e5354f408ae9f2758
|
7
|
+
data.tar.gz: d2020073122505feaa6cb3923f79a76ff6f8608ac45af16625cae83f79c6232a9f4ac677e834faa015bfd1d9e287946b4cc0662557507dcfab89ea7c3faf665e
|
@@ -1,18 +1,35 @@
|
|
1
1
|
class PeakFlowUtils::DeepMerger < PeakFlowUtils::ApplicationService
|
2
|
-
|
2
|
+
attr_reader :hashes, :object_mappings
|
3
|
+
|
4
|
+
def initialize(hashes:, object_mappings: {})
|
3
5
|
@hashes = hashes
|
6
|
+
@object_mappings = object_mappings
|
4
7
|
end
|
5
8
|
|
6
9
|
def perform
|
7
10
|
merged = {}
|
8
11
|
|
9
|
-
|
12
|
+
hashes.each do |hash|
|
10
13
|
merge_hash(hash, merged)
|
11
14
|
end
|
12
15
|
|
13
16
|
succeed! merged
|
14
17
|
end
|
15
18
|
|
19
|
+
def clone_something(object)
|
20
|
+
if object.is_a?(Hash)
|
21
|
+
new_hash = {}
|
22
|
+
merge_hash(object, new_hash)
|
23
|
+
new_hash
|
24
|
+
elsif object.is_a?(Array)
|
25
|
+
new_array = []
|
26
|
+
merge_array(object, new_array)
|
27
|
+
new_array
|
28
|
+
else
|
29
|
+
object
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
16
33
|
def merge_something(object, merged)
|
17
34
|
if object.is_a?(Array)
|
18
35
|
merge_array(object, merged)
|
@@ -25,20 +42,20 @@ class PeakFlowUtils::DeepMerger < PeakFlowUtils::ApplicationService
|
|
25
42
|
|
26
43
|
def merge_array(array, merged)
|
27
44
|
array.each do |value|
|
28
|
-
merged << value
|
45
|
+
merged << clone_something(value)
|
29
46
|
end
|
30
47
|
end
|
31
48
|
|
32
49
|
def merge_hash(hash, merged)
|
33
50
|
hash.each do |key, value|
|
34
|
-
if
|
35
|
-
merged[key] =
|
36
|
-
elsif value.is_a?(Array)
|
51
|
+
if value.is_a?(Array)
|
52
|
+
merged[key] = []
|
37
53
|
merge_array(value, merged[key])
|
38
54
|
elsif value.is_a?(Hash)
|
55
|
+
merged[key] ||= {}
|
39
56
|
merge_hash(value, merged[key])
|
40
57
|
else
|
41
|
-
|
58
|
+
merged[key] = clone_something(value)
|
42
59
|
end
|
43
60
|
end
|
44
61
|
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require "monitor"
|
2
|
+
require_relative "thread_callbacks_patch"
|
3
|
+
|
4
|
+
Thread.on_initialize do |parent:, thread:|
|
5
|
+
thread.instance_variable_set(:@_inherited_local_vars, parent.instance_variable_get(:@_inherited_local_vars))
|
6
|
+
end
|
7
|
+
|
8
|
+
Thread.class_eval do
|
9
|
+
def self.inherited_local_vars_mutex
|
10
|
+
@inherited_local_vars_mutex ||= Mutex.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def self._inherited_local_vars
|
14
|
+
Thread.current.instance_variable_set(:@_inherited_local_vars, {}) unless Thread.current.instance_variable_get(:@_inherited_local_vars)
|
15
|
+
Thread.current.instance_variable_get(:@_inherited_local_vars)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.inherited_local_vars_reset
|
19
|
+
ObjectSpace.each_object(Thread) do |thread|
|
20
|
+
inherited_local_vars_mutex.synchronize do
|
21
|
+
thread.instance_variable_set(:@_inherited_local_vars, nil)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.inherited_local_vars_delete(key)
|
27
|
+
inherited_local_vars_mutex.synchronize do
|
28
|
+
raise "Key didn't exist: #{key}" unless _inherited_local_vars.key?(key)
|
29
|
+
|
30
|
+
_inherited_local_vars.delete(key)
|
31
|
+
end
|
32
|
+
rescue ThreadError # This can happen when process is closing down
|
33
|
+
_inherited_local_vars.delete(key)
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.inherited_local_vars_fetch(key)
|
37
|
+
inherited_local_vars_mutex.synchronize do
|
38
|
+
return _inherited_local_vars.fetch(key)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.inherited_local_vars_get(key)
|
43
|
+
inherited_local_vars_mutex.synchronize do
|
44
|
+
return _inherited_local_vars[key]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.inherited_local_vars_set(values)
|
49
|
+
inherited_local_vars_mutex.synchronize do
|
50
|
+
current_vars = _inherited_local_vars
|
51
|
+
new_vars = PeakFlowUtils::DeepMerger.execute!(hashes: [current_vars, values])
|
52
|
+
Thread.current.instance_variable_set(:@_inherited_local_vars, new_vars)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
class PeakFlowUtils::InheritedLocalVar
|
58
|
+
attr_reader :identifier
|
59
|
+
|
60
|
+
def self.finalize(inherited_local_var_object_id)
|
61
|
+
Thread.inherited_local_vars_delete("inherited_local_var_#{inherited_local_var_object_id}")
|
62
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
63
|
+
puts e.inspect # rubocop:disable Rails/Output
|
64
|
+
puts e.backtrace # rubocop:disable Rails/Output
|
65
|
+
|
66
|
+
raise e
|
67
|
+
end
|
68
|
+
|
69
|
+
def initialize(new_value = nil)
|
70
|
+
ObjectSpace.define_finalizer(self, PeakFlowUtils::InheritedLocalVar.method(:finalize))
|
71
|
+
|
72
|
+
@identifier = "inherited_local_var_#{__id__}"
|
73
|
+
|
74
|
+
Thread.inherited_local_vars_set(identifier => new_value)
|
75
|
+
end
|
76
|
+
|
77
|
+
def value
|
78
|
+
Thread.inherited_local_vars_fetch(identifier)
|
79
|
+
end
|
80
|
+
|
81
|
+
def value=(new_value)
|
82
|
+
Thread.inherited_local_vars_set(identifier => new_value)
|
83
|
+
end
|
84
|
+
end
|
@@ -2,73 +2,89 @@ class PeakFlowUtils::Notifier
|
|
2
2
|
class FailedToReportError < RuntimeError; end
|
3
3
|
class NotConfiguredError < RuntimeError; end
|
4
4
|
|
5
|
-
attr_reader :auth_token
|
5
|
+
attr_reader :auth_token, :mutex, :parameters
|
6
6
|
|
7
7
|
def self.configure(auth_token:)
|
8
8
|
@current = PeakFlowUtils::Notifier.new(auth_token: auth_token)
|
9
9
|
end
|
10
10
|
|
11
|
-
def self.current
|
12
|
-
raise PeakFlowUtils::Notifier::NotConfiguredError, "Hasn't been configured" if !@current && Rails.env.test?
|
13
|
-
|
11
|
+
def self.current # rubocop:disable Style/TrivialAccessors
|
14
12
|
@current
|
15
13
|
end
|
16
14
|
|
17
|
-
def self.
|
18
|
-
|
19
|
-
hashes << parameters if parameters
|
20
|
-
|
21
|
-
PeakFlowUtils::DeepMerger.execute!(hashes: hashes)
|
15
|
+
def self.notify(*args, **opts, &blk)
|
16
|
+
PeakFlowUtils::Notifier.current&.notify(*args, **opts, &blk)
|
22
17
|
end
|
23
18
|
|
24
|
-
def self.
|
25
|
-
|
19
|
+
def self.reset_parameters
|
20
|
+
::PeakFlowUtils::Notifier.current&.instance_variable_set(:@parameters, ::PeakFlowUtils::InheritedLocalVar.new({}))
|
21
|
+
end
|
26
22
|
|
27
|
-
|
28
|
-
|
29
|
-
hashes << more_parameters
|
30
|
-
end
|
23
|
+
def self.with_parameters(parameters)
|
24
|
+
return yield unless ::PeakFlowUtils::Notifier.current
|
31
25
|
|
32
|
-
|
33
|
-
end
|
26
|
+
random_id = ::SecureRandom.hex(16)
|
34
27
|
|
35
|
-
|
36
|
-
|
37
|
-
end
|
28
|
+
::PeakFlowUtils::Notifier.current.mutex.synchronize do
|
29
|
+
raise "'parameters' was nil?" if ::PeakFlowUtils::Notifier.current.parameters.value.nil?
|
38
30
|
|
39
|
-
|
40
|
-
|
31
|
+
parameters_with = ::PeakFlowUtils::Notifier.current.parameters.value.clone
|
32
|
+
parameters_with[random_id] = parameters
|
41
33
|
|
42
|
-
|
43
|
-
|
44
|
-
Thread.current[:peakflow_utils][:notifier][:with_parameters] ||= {}
|
45
|
-
Thread.current[:peakflow_utils][:notifier][:with_parameters][random_id] = parameters
|
34
|
+
::PeakFlowUtils::Notifier.current.parameters.value = parameters_with
|
35
|
+
end
|
46
36
|
|
47
37
|
begin
|
48
38
|
yield
|
49
39
|
ensure
|
50
|
-
|
40
|
+
::PeakFlowUtils::Notifier.current.mutex.synchronize do
|
41
|
+
parameters_without = ::PeakFlowUtils::Notifier.current.parameters.value.clone
|
42
|
+
parameters_without.delete(random_id)
|
43
|
+
|
44
|
+
::PeakFlowUtils::Notifier.current.parameters.value = parameters_without
|
45
|
+
end
|
51
46
|
end
|
52
47
|
end
|
53
48
|
|
54
49
|
def initialize(auth_token:)
|
55
50
|
@auth_token = auth_token
|
51
|
+
@mutex = ::Mutex.new
|
52
|
+
@parameters = ::PeakFlowUtils::InheritedLocalVar.new({})
|
53
|
+
end
|
54
|
+
|
55
|
+
def current_parameters(parameters: nil)
|
56
|
+
hashes = current_parameters_hashes
|
57
|
+
hashes << parameters if parameters
|
58
|
+
|
59
|
+
::PeakFlowUtils::DeepMerger.execute!(hashes: hashes)
|
60
|
+
end
|
61
|
+
|
62
|
+
def current_parameters_hashes
|
63
|
+
parameters.value.values
|
64
|
+
end
|
65
|
+
|
66
|
+
def error_message_from_response(response)
|
67
|
+
message = "Couldn't report error to Peakflow (code #{response.code})"
|
68
|
+
|
69
|
+
if response["content-type"]&.starts_with?("application/json")
|
70
|
+
response_data = ::JSON.parse(response.body)
|
71
|
+
message << ": #{response_data.fetch("errors").join(". ")}" if response_data["errors"]
|
72
|
+
end
|
73
|
+
|
74
|
+
message
|
56
75
|
end
|
57
76
|
|
58
77
|
def notify(error:, environment: nil, parameters: nil)
|
59
|
-
error_parser = PeakFlowUtils::NotifierErrorParser.new(
|
78
|
+
error_parser = ::PeakFlowUtils::NotifierErrorParser.new(
|
60
79
|
backtrace: error.backtrace,
|
61
80
|
environment: environment,
|
62
81
|
error: error
|
63
82
|
)
|
64
83
|
|
65
|
-
merged_parameters =
|
84
|
+
merged_parameters = current_parameters(parameters: parameters)
|
66
85
|
|
67
86
|
uri = URI("https://www.peakflow.io/errors/reports")
|
68
87
|
|
69
|
-
https = Net::HTTP.new(uri.host, uri.port)
|
70
|
-
https.use_ssl = true
|
71
|
-
|
72
88
|
data = {
|
73
89
|
auth_token: auth_token,
|
74
90
|
error: {
|
@@ -85,18 +101,25 @@ class PeakFlowUtils::Notifier
|
|
85
101
|
}
|
86
102
|
}
|
87
103
|
|
88
|
-
|
104
|
+
send_notify_request(data: data, uri: uri)
|
105
|
+
end
|
106
|
+
|
107
|
+
def send_notify_request(data:, uri:)
|
108
|
+
https = ::Net::HTTP.new(uri.host, uri.port)
|
109
|
+
https.use_ssl = true
|
110
|
+
|
111
|
+
request = ::Net::HTTP::Post.new(uri.path)
|
89
112
|
request["Content-Type"] = "application/json"
|
90
|
-
request.body = JSON.generate(data)
|
113
|
+
request.body = ::JSON.generate(data)
|
91
114
|
|
92
115
|
response = https.request(request)
|
93
116
|
|
94
117
|
raise FailedToReportError, error_message_from_response(response) unless response.code == "200"
|
95
118
|
|
96
|
-
response_data = JSON.parse(response.body)
|
119
|
+
response_data = ::JSON.parse(response.body)
|
97
120
|
|
98
121
|
# Data not always present so dont use fetch
|
99
|
-
PeakFlowUtils::NotifierResponse.new(
|
122
|
+
::PeakFlowUtils::NotifierResponse.new(
|
100
123
|
bug_report_id: response_data["bug_report_id"],
|
101
124
|
bug_report_instance_id: response_data["bug_report_instance_id"],
|
102
125
|
project_id: response_data["project_id"],
|
@@ -104,15 +127,4 @@ class PeakFlowUtils::Notifier
|
|
104
127
|
url: response_data["url"]
|
105
128
|
)
|
106
129
|
end
|
107
|
-
|
108
|
-
def error_message_from_response(response)
|
109
|
-
message = "Couldn't report error to Peakflow (code #{response.code})"
|
110
|
-
|
111
|
-
if response["content-type"]&.starts_with?("application/json")
|
112
|
-
response_data = JSON.parse(response.body)
|
113
|
-
message << ": #{response_data.fetch("errors").join(". ")}" if response_data["errors"]
|
114
|
-
end
|
115
|
-
|
116
|
-
message
|
117
|
-
end
|
118
130
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class Thread
|
2
|
+
alias_method :_initialize, :initialize # rubocop:disable Style/Alias
|
3
|
+
|
4
|
+
def self.on_initialize(&callback)
|
5
|
+
@@on_initialize_count = 0 if @on_initialize_count.nil? # rubocop:disable Style/ClassVars
|
6
|
+
count_to_use = @@on_initialize_count
|
7
|
+
@@on_initialize_count += 1 # rubocop:disable Style/ClassVars
|
8
|
+
|
9
|
+
@@on_initialize_callbacks ||= {} # rubocop:disable Style/ClassVars
|
10
|
+
@@on_initialize_callbacks[count_to_use] = callback
|
11
|
+
|
12
|
+
count_to_use
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(*args, &block)
|
16
|
+
@@on_initialize_callbacks ||= {} # rubocop:disable Style/ClassVars
|
17
|
+
@@on_initialize_callbacks.each_value do |callback|
|
18
|
+
callback.call(parent: Thread.current, thread: self)
|
19
|
+
end
|
20
|
+
|
21
|
+
_initialize(*args, &block)
|
22
|
+
end
|
23
|
+
end
|
data/lib/peak_flow_utils.rb
CHANGED
@@ -6,7 +6,11 @@ require "service_pattern"
|
|
6
6
|
module PeakFlowUtils
|
7
7
|
path = "#{__dir__}/peak_flow_utils"
|
8
8
|
models_path = "#{__dir__}/peak_flow_utils/models"
|
9
|
+
services_path = File.realpath("#{__dir__}/../app/services/peak_flow_utils")
|
9
10
|
|
11
|
+
autoload :ApplicationService, "#{services_path}/application_service"
|
12
|
+
autoload :DeepMerger, "#{services_path}/deep_merger"
|
13
|
+
autoload :InheritedLocalVar, "#{path}/inherited_local_var"
|
10
14
|
autoload :Notifier, "#{path}/notifier"
|
11
15
|
autoload :NotifierErrorParser, "#{path}/notifier_error_parser"
|
12
16
|
autoload :NotifierRack, "#{path}/notifier_rack"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: peak_flow_utils
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.16
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- kaspernj
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-02-
|
11
|
+
date: 2022-02-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -66,6 +66,34 @@ dependencies:
|
|
66
66
|
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: 1.0.5
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: appraisal
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
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
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
69
97
|
- !ruby/object:Gem::Dependency
|
70
98
|
name: redis
|
71
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -147,6 +175,7 @@ files:
|
|
147
175
|
- lib/peak_flow_utils.rb
|
148
176
|
- lib/peak_flow_utils/engine.rb
|
149
177
|
- lib/peak_flow_utils/handler_helper.rb
|
178
|
+
- lib/peak_flow_utils/inherited_local_var.rb
|
150
179
|
- lib/peak_flow_utils/migrations/20150902155200_create_translation_keys.rb
|
151
180
|
- lib/peak_flow_utils/migrations/20150907070908_create_handlers.rb
|
152
181
|
- lib/peak_flow_utils/migrations/20150907070909_create_groups.rb
|
@@ -166,6 +195,7 @@ files:
|
|
166
195
|
- lib/peak_flow_utils/notifier_rails.rb
|
167
196
|
- lib/peak_flow_utils/notifier_response.rb
|
168
197
|
- lib/peak_flow_utils/notifier_sidekiq.rb
|
198
|
+
- lib/peak_flow_utils/thread_callbacks_patch.rb
|
169
199
|
- lib/peak_flow_utils/version.rb
|
170
200
|
- lib/tasks/peak_flow_utils_tasks.rake
|
171
201
|
homepage: https://github.com/kaspernj/peak_flow_utils
|