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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +15 -0
  3. data/README.md +35 -7
  4. data/lib/generators/goodsorcery/install/templates/initializer.rb +8 -2
  5. data/lib/goodsorcery/client.rb +13 -4
  6. data/lib/goodsorcery/configuration/performance_settings.rb +37 -0
  7. data/lib/goodsorcery/configuration/validation.rb +10 -0
  8. data/lib/goodsorcery/configuration.rb +24 -10
  9. data/lib/goodsorcery/defaults.rb +4 -0
  10. data/lib/goodsorcery/delivery.rb +3 -12
  11. data/lib/goodsorcery/errors.rb +0 -4
  12. data/lib/goodsorcery/integrations/active_job.rb +4 -2
  13. data/lib/goodsorcery/integrations/rails/error_subscriber.rb +1 -5
  14. data/lib/goodsorcery/integrations/rails.rb +3 -2
  15. data/lib/goodsorcery/integrations/sidekiq.rb +18 -2
  16. data/lib/goodsorcery/integrations.rb +0 -6
  17. data/lib/goodsorcery/performance/agent.rb +103 -0
  18. data/lib/goodsorcery/performance/aggregator.rb +63 -0
  19. data/lib/goodsorcery/performance/call_site.rb +61 -0
  20. data/lib/goodsorcery/performance/flusher.rb +224 -0
  21. data/lib/goodsorcery/performance/histogram.rb +23 -0
  22. data/lib/goodsorcery/performance/job_timing.rb +106 -0
  23. data/lib/goodsorcery/performance/measurement.rb +117 -0
  24. data/lib/goodsorcery/performance/net_http.rb +37 -0
  25. data/lib/goodsorcery/performance/payloads.rb +110 -0
  26. data/lib/goodsorcery/performance/process_label.rb +22 -0
  27. data/lib/goodsorcery/performance/recorder.rb +202 -0
  28. data/lib/goodsorcery/performance/span_list.rb +156 -0
  29. data/lib/goodsorcery/performance/sql_normalizer.rb +149 -0
  30. data/lib/goodsorcery/performance/subscribers.rb +140 -0
  31. data/lib/goodsorcery/performance/trace_buffer.rb +78 -0
  32. data/lib/goodsorcery/performance/trace_builder.rb +121 -0
  33. data/lib/goodsorcery/performance/transaction_stats.rb +93 -0
  34. data/lib/goodsorcery/performance/uuid_v7.rb +27 -0
  35. data/lib/goodsorcery/performance.rb +158 -0
  36. data/lib/goodsorcery/rack/middleware.rb +10 -3
  37. data/lib/goodsorcery/status_report.rb +1 -2
  38. data/lib/goodsorcery/transport.rb +12 -1
  39. data/lib/goodsorcery/version.rb +1 -1
  40. data/lib/goodsorcery.rb +17 -0
  41. metadata +21 -4
  42. data/lib/goodsorcery/delivery/active_job_queue.rb +0 -71
  43. data/lib/goodsorcery/delivery/custom.rb +0 -27
  44. data/lib/goodsorcery/delivery_job.rb +0 -26
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GoodSorcery
4
- VERSION = "0.1.1"
4
+ VERSION = "0.3.0"
5
5
  NOTIFIER_NAME = "goodsorcery-ruby"
6
6
  end
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.1.1
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