goodsorcery 0.1.1 → 0.3.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 +4 -4
- data/CHANGELOG.md +15 -0
- data/README.md +35 -7
- data/lib/generators/goodsorcery/install/templates/initializer.rb +8 -2
- data/lib/goodsorcery/client.rb +13 -4
- data/lib/goodsorcery/configuration/performance_settings.rb +37 -0
- data/lib/goodsorcery/configuration/validation.rb +10 -0
- data/lib/goodsorcery/configuration.rb +24 -10
- data/lib/goodsorcery/defaults.rb +4 -0
- data/lib/goodsorcery/delivery.rb +3 -12
- data/lib/goodsorcery/errors.rb +0 -4
- data/lib/goodsorcery/integrations/active_job.rb +4 -2
- data/lib/goodsorcery/integrations/rails/error_subscriber.rb +1 -5
- data/lib/goodsorcery/integrations/rails.rb +3 -2
- data/lib/goodsorcery/integrations/sidekiq.rb +18 -2
- data/lib/goodsorcery/integrations.rb +0 -6
- data/lib/goodsorcery/performance/agent.rb +103 -0
- data/lib/goodsorcery/performance/aggregator.rb +63 -0
- data/lib/goodsorcery/performance/call_site.rb +61 -0
- data/lib/goodsorcery/performance/flusher.rb +224 -0
- data/lib/goodsorcery/performance/histogram.rb +23 -0
- data/lib/goodsorcery/performance/job_timing.rb +106 -0
- data/lib/goodsorcery/performance/measurement.rb +117 -0
- data/lib/goodsorcery/performance/net_http.rb +37 -0
- data/lib/goodsorcery/performance/payloads.rb +110 -0
- data/lib/goodsorcery/performance/process_label.rb +22 -0
- data/lib/goodsorcery/performance/recorder.rb +202 -0
- data/lib/goodsorcery/performance/span_list.rb +156 -0
- data/lib/goodsorcery/performance/sql_normalizer.rb +149 -0
- data/lib/goodsorcery/performance/subscribers.rb +140 -0
- data/lib/goodsorcery/performance/trace_buffer.rb +78 -0
- data/lib/goodsorcery/performance/trace_builder.rb +121 -0
- data/lib/goodsorcery/performance/transaction_stats.rb +93 -0
- data/lib/goodsorcery/performance/uuid_v7.rb +27 -0
- data/lib/goodsorcery/performance.rb +158 -0
- data/lib/goodsorcery/rack/middleware.rb +10 -3
- data/lib/goodsorcery/status_report.rb +1 -2
- data/lib/goodsorcery/transport.rb +12 -1
- data/lib/goodsorcery/version.rb +1 -1
- data/lib/goodsorcery.rb +17 -0
- metadata +21 -4
- data/lib/goodsorcery/delivery/active_job_queue.rb +0 -71
- data/lib/goodsorcery/delivery/custom.rb +0 -27
- data/lib/goodsorcery/delivery_job.rb +0 -26
data/lib/goodsorcery/version.rb
CHANGED
data/lib/goodsorcery.rb
CHANGED
|
@@ -51,6 +51,7 @@ require_relative "goodsorcery/delivery"
|
|
|
51
51
|
require_relative "goodsorcery/verification"
|
|
52
52
|
require_relative "goodsorcery/test_event"
|
|
53
53
|
require_relative "goodsorcery/client"
|
|
54
|
+
require_relative "goodsorcery/performance"
|
|
54
55
|
require_relative "goodsorcery/rack/middleware"
|
|
55
56
|
|
|
56
57
|
# Reports exceptions to a Good Sorcery error tracker. See README.md.
|
|
@@ -152,13 +153,29 @@ module GoodSorcery
|
|
|
152
153
|
client.test_events
|
|
153
154
|
end
|
|
154
155
|
|
|
156
|
+
# Also forgets the performance payloads kept by the :test delivery.
|
|
155
157
|
def clear_test_events
|
|
158
|
+
Performance.clear_test_payloads
|
|
156
159
|
client.clear_test_events
|
|
157
160
|
end
|
|
158
161
|
|
|
162
|
+
# Sends the recorded performance data now (with the :test delivery:
|
|
163
|
+
# builds it into test_performance_payloads). Never raises.
|
|
164
|
+
def flush_performance(include_open_minute: true)
|
|
165
|
+
Performance.flush_performance(include_open_minute: include_open_minute)
|
|
166
|
+
rescue StandardError
|
|
167
|
+
false
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# [{ "path" => "/api/v1/apm/metrics", "body" => Hash }, ...] with the :test delivery.
|
|
171
|
+
def test_performance_payloads
|
|
172
|
+
Performance.test_payloads
|
|
173
|
+
end
|
|
174
|
+
|
|
159
175
|
# Forgets configuration, client and the current scope. For tests.
|
|
160
176
|
def reset!
|
|
161
177
|
shutdown(0.5)
|
|
178
|
+
Performance.reset!
|
|
162
179
|
LOCK.synchronize do
|
|
163
180
|
@client = nil
|
|
164
181
|
@configuration = nil
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: goodsorcery
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Philip Q Nguyen
|
|
@@ -32,18 +32,16 @@ files:
|
|
|
32
32
|
- lib/goodsorcery/bundler_plugin.rb
|
|
33
33
|
- lib/goodsorcery/client.rb
|
|
34
34
|
- lib/goodsorcery/configuration.rb
|
|
35
|
+
- lib/goodsorcery/configuration/performance_settings.rb
|
|
35
36
|
- lib/goodsorcery/configuration/validation.rb
|
|
36
37
|
- lib/goodsorcery/defaults.rb
|
|
37
38
|
- lib/goodsorcery/delivery.rb
|
|
38
|
-
- lib/goodsorcery/delivery/active_job_queue.rb
|
|
39
39
|
- lib/goodsorcery/delivery/async.rb
|
|
40
40
|
- lib/goodsorcery/delivery/backoff.rb
|
|
41
|
-
- lib/goodsorcery/delivery/custom.rb
|
|
42
41
|
- lib/goodsorcery/delivery/event_queue.rb
|
|
43
42
|
- lib/goodsorcery/delivery/sync.rb
|
|
44
43
|
- lib/goodsorcery/delivery/test.rb
|
|
45
44
|
- lib/goodsorcery/delivery/worker.rb
|
|
46
|
-
- lib/goodsorcery/delivery_job.rb
|
|
47
45
|
- lib/goodsorcery/env_flag.rb
|
|
48
46
|
- lib/goodsorcery/environment_gate.rb
|
|
49
47
|
- lib/goodsorcery/errors.rb
|
|
@@ -82,6 +80,25 @@ files:
|
|
|
82
80
|
- lib/goodsorcery/key_filter.rb
|
|
83
81
|
- lib/goodsorcery/log.rb
|
|
84
82
|
- lib/goodsorcery/masked_key.rb
|
|
83
|
+
- lib/goodsorcery/performance.rb
|
|
84
|
+
- lib/goodsorcery/performance/agent.rb
|
|
85
|
+
- lib/goodsorcery/performance/aggregator.rb
|
|
86
|
+
- lib/goodsorcery/performance/call_site.rb
|
|
87
|
+
- lib/goodsorcery/performance/flusher.rb
|
|
88
|
+
- lib/goodsorcery/performance/histogram.rb
|
|
89
|
+
- lib/goodsorcery/performance/job_timing.rb
|
|
90
|
+
- lib/goodsorcery/performance/measurement.rb
|
|
91
|
+
- lib/goodsorcery/performance/net_http.rb
|
|
92
|
+
- lib/goodsorcery/performance/payloads.rb
|
|
93
|
+
- lib/goodsorcery/performance/process_label.rb
|
|
94
|
+
- lib/goodsorcery/performance/recorder.rb
|
|
95
|
+
- lib/goodsorcery/performance/span_list.rb
|
|
96
|
+
- lib/goodsorcery/performance/sql_normalizer.rb
|
|
97
|
+
- lib/goodsorcery/performance/subscribers.rb
|
|
98
|
+
- lib/goodsorcery/performance/trace_buffer.rb
|
|
99
|
+
- lib/goodsorcery/performance/trace_builder.rb
|
|
100
|
+
- lib/goodsorcery/performance/transaction_stats.rb
|
|
101
|
+
- lib/goodsorcery/performance/uuid_v7.rb
|
|
85
102
|
- lib/goodsorcery/rack/middleware.rb
|
|
86
103
|
- lib/goodsorcery/rack/request_details.rb
|
|
87
104
|
- lib/goodsorcery/rack/request_enricher.rb
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module GoodSorcery
|
|
4
|
-
module Delivery
|
|
5
|
-
# Enqueues GoodSorcery::DeliveryJob with the filtered event as a JSON
|
|
6
|
-
# string. Falls back to the background thread when ActiveJob is not loaded
|
|
7
|
-
# or enqueueing raises. Note: the event is stored in the job backend.
|
|
8
|
-
class ActiveJobQueue
|
|
9
|
-
def initialize(serializer:, queue_name:, log:, &fallback_builder)
|
|
10
|
-
@serializer = serializer
|
|
11
|
-
@queue_name = queue_name
|
|
12
|
-
@log = log
|
|
13
|
-
@fallback_builder = fallback_builder
|
|
14
|
-
@fallback = nil
|
|
15
|
-
@lock = Mutex.new
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def deliver(event)
|
|
19
|
-
job = DeliveryJobLoader.job_class
|
|
20
|
-
return deliver_in_background(event, "ActiveJob is not loaded") unless job
|
|
21
|
-
|
|
22
|
-
json = @serializer.dump(event)
|
|
23
|
-
return false unless json
|
|
24
|
-
|
|
25
|
-
return true if enqueued?(job.set(queue: @queue_name).perform_later(json))
|
|
26
|
-
|
|
27
|
-
deliver_in_background(event, "GoodSorcery::DeliveryJob was not enqueued")
|
|
28
|
-
rescue StandardError => e
|
|
29
|
-
deliver_in_background(event, "enqueueing GoodSorcery::DeliveryJob failed (#{e.class})")
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def flush(timeout = 5)
|
|
33
|
-
@fallback ? @fallback.flush(timeout) : true
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def shutdown(timeout = 5)
|
|
37
|
-
@fallback ? @fallback.shutdown(timeout) : true
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
private
|
|
41
|
-
|
|
42
|
-
# perform_later returns false when a callback aborted the enqueue or
|
|
43
|
-
# the adapter raised ActiveJob::EnqueueError.
|
|
44
|
-
def enqueued?(job)
|
|
45
|
-
return false unless job
|
|
46
|
-
|
|
47
|
-
job.respond_to?(:successfully_enqueued?) ? job.successfully_enqueued? != false : true
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def deliver_in_background(event, reason)
|
|
51
|
-
@log.warn_every(:active_job_fallback, 60, "#{reason}; delivering in the background thread instead")
|
|
52
|
-
fallback.deliver(event)
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def fallback
|
|
56
|
-
@fallback || @lock.synchronize { @fallback ||= @fallback_builder.call }
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
# Defines GoodSorcery::DeliveryJob on first use, once ActiveJob is loaded.
|
|
61
|
-
module DeliveryJobLoader
|
|
62
|
-
def self.job_class
|
|
63
|
-
return GoodSorcery::DeliveryJob if GoodSorcery.const_defined?(:DeliveryJob, false)
|
|
64
|
-
return nil unless defined?(::ActiveJob::Base)
|
|
65
|
-
|
|
66
|
-
require_relative "../delivery_job"
|
|
67
|
-
GoodSorcery::DeliveryJob
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
|
-
end
|
|
71
|
-
end
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module GoodSorcery
|
|
4
|
-
module Delivery
|
|
5
|
-
# Wraps an app-supplied delivery object. It must respond to
|
|
6
|
-
# deliver(event_hash) and may respond to flush(timeout) and shutdown(timeout).
|
|
7
|
-
class Custom
|
|
8
|
-
attr_reader :target
|
|
9
|
-
|
|
10
|
-
def initialize(target)
|
|
11
|
-
@target = target
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def deliver(event)
|
|
15
|
-
@target.deliver(event)
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def flush(timeout = 5)
|
|
19
|
-
@target.respond_to?(:flush) ? @target.flush(timeout) : true
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def shutdown(timeout = 5)
|
|
23
|
-
@target.respond_to?(:shutdown) ? @target.shutdown(timeout) : true
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
end
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module GoodSorcery
|
|
4
|
-
# Sends one already-filtered event (a JSON string) synchronously. Retries
|
|
5
|
-
# 429/5xx/network failures with ActiveJob's retry_on. Any exception raised
|
|
6
|
-
# here is marked as reported first, so no integration reports it back to
|
|
7
|
-
# Good Sorcery (no recursion). The argument is captured error data, so
|
|
8
|
-
# Active Job never writes it to the log.
|
|
9
|
-
class DeliveryJob < ::ActiveJob::Base
|
|
10
|
-
WAIT = ::ActiveJob.gem_version >= Gem::Version.new("7.1") ? :polynomially_longer : :exponentially_longer
|
|
11
|
-
|
|
12
|
-
self.log_arguments = false
|
|
13
|
-
queue_as { GoodSorcery.configuration.active_job_queue }
|
|
14
|
-
retry_on GoodSorcery::RetryableDeliveryError, wait: WAIT, attempts: 5
|
|
15
|
-
|
|
16
|
-
def perform(event_json)
|
|
17
|
-
result = GoodSorcery.client.transport.post_event(event_json)
|
|
18
|
-
return unless result.retry_later?
|
|
19
|
-
|
|
20
|
-
raise GoodSorcery::RetryableDeliveryError, "event delivery failed (#{result.description})"
|
|
21
|
-
rescue Exception => e # rubocop:disable Lint/RescueException
|
|
22
|
-
ReportedMark.mark(e)
|
|
23
|
-
raise
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
end
|