mnemosyne-ruby 1.0.1 → 1.1.0.rc1

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 (35) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +10 -0
  4. data/CHANGELOG.md +7 -0
  5. data/Gemfile +11 -0
  6. data/lib/mnemosyne/client.rb +11 -4
  7. data/lib/mnemosyne/configuration.rb +7 -5
  8. data/lib/mnemosyne/instrumenter.rb +19 -17
  9. data/lib/mnemosyne/middleware/acfs.rb +2 -2
  10. data/lib/mnemosyne/middleware/rack.rb +1 -10
  11. data/lib/mnemosyne/middleware/restify.rb +6 -7
  12. data/lib/mnemosyne/middleware/sidekiq.rb +39 -0
  13. data/lib/mnemosyne/probe.rb +0 -1
  14. data/lib/mnemosyne/probes/acfs/request.rb +0 -1
  15. data/lib/mnemosyne/probes/action_controller/process_action.rb +0 -1
  16. data/lib/mnemosyne/probes/action_controller/renderers.rb +0 -1
  17. data/lib/mnemosyne/probes/action_view/render_partial.rb +0 -1
  18. data/lib/mnemosyne/probes/action_view/render_template.rb +0 -1
  19. data/lib/mnemosyne/probes/active_record/query.rb +0 -1
  20. data/lib/mnemosyne/probes/grape/endpoint_render.rb +0 -1
  21. data/lib/mnemosyne/probes/grape/endpoint_run.rb +0 -1
  22. data/lib/mnemosyne/probes/grape/endpoint_run_filters.rb +0 -1
  23. data/lib/mnemosyne/probes/mnemosyne/tracer.rb +0 -1
  24. data/lib/mnemosyne/probes/msgr/client.rb +42 -0
  25. data/lib/mnemosyne/probes/msgr/consumer.rb +70 -0
  26. data/lib/mnemosyne/probes/responder/respond.rb +0 -1
  27. data/lib/mnemosyne/probes/sidekiq/client.rb +44 -0
  28. data/lib/mnemosyne/probes/sidekiq/server.rb +23 -0
  29. data/lib/mnemosyne/probes.rb +7 -61
  30. data/lib/mnemosyne/registry.rb +87 -0
  31. data/lib/mnemosyne/span.rb +15 -2
  32. data/lib/mnemosyne/trace.rb +3 -3
  33. data/lib/mnemosyne/version.rb +3 -3
  34. data/lib/mnemosyne.rb +5 -0
  35. metadata +10 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3be644845f56d638f37c5bbaab9e17a10cadc24b
4
- data.tar.gz: abffc04c98a65ee9e6b24fc3d57fd2d1c53e943a
3
+ metadata.gz: 99dce4e5dc6cc2a267e8189e7d02bec8bc06beae
4
+ data.tar.gz: 0b5f1bf920009d85c5147ee52a2fdbf6fe313ce9
5
5
  SHA512:
6
- metadata.gz: d242c0b3f668a17253aa1c153f19d902dd0681c49bb4f001390ec6690e72a539a362c45a6f283d0260a8e10a0dc85ce7a2d7d4a230a4d86a659e328da66d7cbb
7
- data.tar.gz: 41a21abe608d7ca68c0493ff80929addb7d85c45687b5b24861cfb4295c9b75ce91349957b17c6bc221eaec78df8f218b7f328fddfc04b821a9a3cbf23ca0a82
6
+ metadata.gz: 77e0cd8aad0ccc076168d44f433a9dee967d7d426807fd5d8870892888523ddbe046fa5d9f3e980050abb1a3d844f7fe7d82a101a470ad160e25089925ed047b
7
+ data.tar.gz: da9ad5a98a9cfded7a8358dd18f62132e238b501d82264d6b9ed04d748206814613fa1c0973cf7b484cc080a50b38e6269ff8e7d60b055910dc4500f82891be3
data/.gitignore CHANGED
@@ -7,3 +7,4 @@
7
7
  /pkg/
8
8
  /spec/reports/
9
9
  /tmp/
10
+ spec/examples.txt
data/.rubocop.yml CHANGED
@@ -46,5 +46,15 @@ Metrics/LineLength:
46
46
  Exclude:
47
47
  - 'mnemosyne.gemspec'
48
48
 
49
+ Metrics/BlockLength:
50
+ Exclude:
51
+ - 'spec/**/*'
52
+
53
+ Metrics/ParameterLists:
54
+ Enabled: false
55
+
56
+ Metrics/MethodLength:
57
+ Enabled: false
58
+
49
59
  Style/Documentation:
50
60
  Enabled: false
data/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.1.0
4
+
5
+ * Add msgr server & client instrumentation
6
+ * Add sidekiq client instrumentation
7
+ * Add sidekiq server instrumentation
8
+ * Add acfs request parameter tracing
9
+
3
10
  ## 1.0.1
4
11
 
5
12
  * Fix issue with `enabled` configuration flag (#1)
data/Gemfile CHANGED
@@ -1,5 +1,16 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  source 'https://rubygems.org'
3
4
 
4
5
  # Specify your gem's dependencies in mnemosyne.gemspec
5
6
  gemspec
7
+
8
+ group :development, :test do
9
+ gem 'pry', require: false
10
+ gem 'pry-byebug', require: false
11
+ end
12
+
13
+ group :test do
14
+ gem 'restify', require: false
15
+ gem 'sidekiq', require: false
16
+ end
@@ -30,12 +30,19 @@ module Mnemosyne
30
30
  @exchange ||= channel.topic @config.exchange, durable: true
31
31
  end
32
32
 
33
- def send(key, data)
34
- blob = JSON.dump data
33
+ def call(trace)
34
+ message = {
35
+ hostname: @config.hostname,
36
+ platform: @config.platform,
37
+ application: @config.application
38
+ }
35
39
 
36
- exchange.publish blob,
37
- routing_key: key,
40
+ # TODO: nest
41
+ message.merge! trace.serialize
42
+
43
+ exchange.publish JSON.dump(message),
38
44
  persistent: true,
45
+ routing_key: 'mnemosyne.trace',
39
46
  content_type: 'application/json'
40
47
  end
41
48
 
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'socket'
3
4
  require 'uri'
4
5
  require 'cgi'
@@ -13,14 +14,15 @@ module Mnemosyne
13
14
  attr_reader :logger
14
15
  attr_reader :server
15
16
 
16
- # rubocop:disable Metrics/AbcSize
17
- def initialize(config)
17
+ def initialize(config) # rubocop:disable AbcSize
18
18
  @platform = config.fetch('platform', 'default').to_s.strip.freeze
19
19
  @application = config.fetch('application', nil).to_s.strip.freeze
20
20
  @enabled = config.fetch('enabled', true)
21
- @hostname = config.fetch('hostname') { default_hostname }.to_s.strip.freeze
22
21
  @exchange = config.fetch('exchange', 'mnemosyne').to_s.freeze
23
- @logger = config.fetch('logger') { Logger.new($stdout) }
22
+ @logger = config.fetch('logger') { Logger.new(STDOUT) }
23
+
24
+ hostname = config.fetch('hostname') { default_hostname }
25
+ @hostname = hostname.to_s.strip.freeze
24
26
 
25
27
  server = config.fetch('server', 'amqp://localhost')
26
28
  @amqp = AMQ::Settings.configure(server).freeze
@@ -40,7 +42,7 @@ module Mnemosyne
40
42
  Socket.gethostname
41
43
  end
42
44
 
43
- def make_amqp_uri(amqp)
45
+ def make_amqp_uri(amqp) # rubocop:disable AbcSize
44
46
  uri = URI('')
45
47
 
46
48
  uri.scheme = amqp[:scheme]
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'thread'
3
4
 
4
5
  module Mnemosyne
@@ -8,13 +9,12 @@ module Mnemosyne
8
9
 
9
10
  attr_reader :logger
10
11
 
11
- def initialize(config)
12
+ def initialize(config:, client:, logger:)
13
+ @client = client
12
14
  @config = config
15
+ @logger = logger
13
16
 
14
- raise 'Config required!' unless @config
15
-
16
- @logger = config.logger
17
- @client = Client.new(config)
17
+ ::Mnemosyne::Probes.activate!
18
18
 
19
19
  logger.info 'Mnemosyne instrumenter started.'
20
20
  end
@@ -27,7 +27,6 @@ module Mnemosyne
27
27
  Thread.current[IDENT] = trace
28
28
  end
29
29
 
30
- # rubocop:disable Metrics/MethodLength
31
30
  def trace(name, **kwargs)
32
31
  if (trace = current_trace)
33
32
  return yield trace if block_given?
@@ -47,18 +46,9 @@ module Mnemosyne
47
46
  end
48
47
 
49
48
  def submit(trace)
50
- blob = {
51
- hostname: @config.hostname,
52
- platform: @config.platform,
53
- application: @config.application,
54
- }
55
-
56
- # TODO: nest
57
- blob.merge! trace.serialize
58
-
59
49
  logger.debug { "Submit trace #{trace.uuid}" }
60
50
 
61
- @client.send 'mnemosyne.trace', blob
51
+ @client.call trace
62
52
  end
63
53
 
64
54
  def release(trace)
@@ -76,7 +66,10 @@ module Mnemosyne
76
66
  MUTEX.synchronize do
77
67
  return @instance if @instance
78
68
 
79
- @instance = new(config)
69
+ client = Client.new(config)
70
+ logger = config.logger
71
+
72
+ @instance = new(config: config, client: client, logger: logger)
80
73
  end
81
74
  rescue => err
82
75
  message = "Unable to start instrumenter: #{err}"
@@ -90,6 +83,15 @@ module Mnemosyne
90
83
  raise
91
84
  end
92
85
 
86
+ def with(instrumenter)
87
+ old = instance
88
+ @instance = instrumenter
89
+
90
+ yield(instrumenter)
91
+ ensure
92
+ @instance = old
93
+ end
94
+
93
95
  def trace(*args)
94
96
  return unless (instrumenter = instance)
95
97
  instrumenter.trace(*args)
@@ -7,7 +7,6 @@ module Mnemosyne
7
7
  @app = app
8
8
  end
9
9
 
10
- # rubocop:disable Metrics/MethodLength
11
10
  def call(request)
12
11
  trace = ::Mnemosyne::Instrumenter.current_trace
13
12
 
@@ -35,8 +34,9 @@ module Mnemosyne
35
34
 
36
35
  def extract_meta(request)
37
36
  {
37
+ url: request.url,
38
38
  method: request.method,
39
- url: request.url
39
+ params: request.params
40
40
  }
41
41
  end
42
42
  end
@@ -54,7 +54,6 @@ module Mnemosyne
54
54
  @app = app
55
55
  end
56
56
 
57
- # rubocop:disable Metrics/MethodLength
58
57
  def call(env)
59
58
  origin = env.fetch('HTTP_X_MNEMOSYNE_ORIGIN', false)
60
59
  transaction = env.fetch('HTTP_X_MNEMOSYNE_TRANSACTION') do
@@ -74,20 +73,12 @@ module Mnemosyne
74
73
  else
75
74
  @app.call env
76
75
  end
77
-
78
- # rubocop:disable Lint/RescueException
79
- rescue Exception
76
+ rescue Exception # rubocop:disable RescueException
80
77
  trace.submit if trace
81
78
  raise
82
79
  ensure
83
80
  trace.release if trace
84
81
  end
85
82
  end
86
-
87
- private
88
-
89
- def _uuid
90
- ::SecureRandom.uuid
91
- end
92
83
  end
93
84
  end
@@ -3,10 +3,9 @@
3
3
  module Mnemosyne
4
4
  module Middleware
5
5
  module Restify
6
- # rubocop:disable Metrics/MethodLength
7
6
  def call(request)
8
7
  if (trace = ::Mnemosyne::Instrumenter.current_trace)
9
- meta = {url: request.uri, method: request.method}
8
+ meta = {url: request.uri.to_s, method: request.method}
10
9
 
11
10
  span = ::Mnemosyne::Span.new('external.http.restify', meta: meta)
12
11
  span.start!
@@ -14,11 +13,11 @@ module Mnemosyne
14
13
  request.headers['X-Mnemosyne-Transaction'] = trace.transaction
15
14
  request.headers['X-Mnemosyne-Origin'] = span.uuid
16
15
 
17
- super.then do |response|
18
- span.finish!
19
- trace << span
20
-
21
- response
16
+ super.tap do |x|
17
+ x.add_observer do |_, _response, _err|
18
+ span.finish!
19
+ trace << span
20
+ end
22
21
  end
23
22
  else
24
23
  super
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mnemosyne
4
+ module Middleware
5
+ class Sidekiq
6
+ def call(worker, job, queue)
7
+ origin = job.delete('mnemosyne.origin') { false }
8
+ transaction = job.delete('mnemosyne.transaction') { uuid }
9
+
10
+ meta = {
11
+ raw: job,
12
+ queue: queue,
13
+ worker: worker.class.name,
14
+ arguments: job['args']
15
+ }
16
+
17
+ trace = ::Mnemosyne::Instrumenter.trace 'app.job.perform.sidekiq',
18
+ transaction: transaction,
19
+ origin: origin,
20
+ meta: meta
21
+
22
+ trace.start! if trace
23
+
24
+ yield
25
+ ensure
26
+ if trace
27
+ trace.submit
28
+ trace.release
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def uuid
35
+ ::SecureRandom.uuid
36
+ end
37
+ end
38
+ end
39
+ end
@@ -2,7 +2,6 @@
2
2
 
3
3
  module Mnemosyne
4
4
  class Probe
5
- # rubocop:disable Metrics/MethodLength
6
5
  def install
7
6
  setup
8
7
 
@@ -13,7 +13,6 @@ module Mnemosyne
13
13
  ::Acfs::Runner.use ::Mnemosyne::Middleware::Acfs
14
14
  end
15
15
 
16
- # rubocop:disable Metrics/ParameterLists
17
16
  def call(trace, _name, start, finish, _id, _payload)
18
17
  start = ::Mnemosyne::Clock.to_tick(start)
19
18
  finish = ::Mnemosyne::Clock.to_tick(finish)
@@ -7,7 +7,6 @@ module Mnemosyne
7
7
  class Probe < ::Mnemosyne::Probe
8
8
  subscribe 'process_action.action_controller'
9
9
 
10
- # rubocop:disable Metrics/ParameterLists
11
10
  def call(trace, _name, start, finish, _id, payload)
12
11
  start = ::Mnemosyne::Clock.to_tick(start)
13
12
  finish = ::Mnemosyne::Clock.to_tick(finish)
@@ -13,7 +13,6 @@ module Mnemosyne
13
13
  ::ActionController::Base.prepend Instrumentation
14
14
  end
15
15
 
16
- # rubocop:disable Metrics/ParameterLists
17
16
  def call(trace, _name, start, finish, _id, _payload)
18
17
  start = ::Mnemosyne::Clock.to_tick(start)
19
18
  finish = ::Mnemosyne::Clock.to_tick(finish)
@@ -7,7 +7,6 @@ module Mnemosyne
7
7
  class Probe < ::Mnemosyne::Probe
8
8
  subscribe 'render_partial.action_view'
9
9
 
10
- # rubocop:disable Metrics/ParameterLists
11
10
  def call(trace, _name, start, finish, _id, payload)
12
11
  start = ::Mnemosyne::Clock.to_tick(start)
13
12
  finish = ::Mnemosyne::Clock.to_tick(finish)
@@ -7,7 +7,6 @@ module Mnemosyne
7
7
  class Probe < ::Mnemosyne::Probe
8
8
  subscribe 'render_template.action_view'
9
9
 
10
- # rubocop:disable Metrics/ParameterLists
11
10
  def call(trace, _name, start, finish, _id, payload)
12
11
  start = ::Mnemosyne::Clock.to_tick(start)
13
12
  finish = ::Mnemosyne::Clock.to_tick(finish)
@@ -7,7 +7,6 @@ module Mnemosyne
7
7
  class Probe < ::Mnemosyne::Probe
8
8
  subscribe 'sql.active_record'
9
9
 
10
- # rubocop:disable Metrics/ParameterLists
11
10
  def call(trace, _name, start, finish, _id, payload)
12
11
  return if payload[:name] == 'SCHEMA' || payload[:name] == 'CACHE'
13
12
 
@@ -7,7 +7,6 @@ module Mnemosyne
7
7
  class Probe < ::Mnemosyne::Probe
8
8
  subscribe 'endpoint_render.grape'
9
9
 
10
- # rubocop:disable Metrics/ParameterLists
11
10
  def call(trace, _name, start, finish, _id, payload)
12
11
  start = ::Mnemosyne::Clock.to_tick(start)
13
12
  finish = ::Mnemosyne::Clock.to_tick(finish)
@@ -7,7 +7,6 @@ module Mnemosyne
7
7
  class Probe < ::Mnemosyne::Probe
8
8
  subscribe 'endpoint_run.grape'
9
9
 
10
- # rubocop:disable Metrics/ParameterLists
11
10
  def call(trace, _name, start, finish, _id, payload)
12
11
  start = ::Mnemosyne::Clock.to_tick(start)
13
12
  finish = ::Mnemosyne::Clock.to_tick(finish)
@@ -7,7 +7,6 @@ module Mnemosyne
7
7
  class Probe < ::Mnemosyne::Probe
8
8
  subscribe 'endpoint_run_filters.grape'
9
9
 
10
- # rubocop:disable Metrics/ParameterLists
11
10
  def call(trace, _name, start, finish, _id, payload)
12
11
  start = ::Mnemosyne::Clock.to_tick(start)
13
12
  finish = ::Mnemosyne::Clock.to_tick(finish)
@@ -7,7 +7,6 @@ module Mnemosyne
7
7
  class Probe < ::Mnemosyne::Probe
8
8
  subscribe 'trace.mnemosyne'
9
9
 
10
- # rubocop:disable Metrics/ParameterLists
11
10
  def call(trace, _name, start, finish, _id, payload)
12
11
  start = ::Mnemosyne::Clock.to_tick(start)
13
12
  finish = ::Mnemosyne::Clock.to_tick(finish)
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mnemosyne
4
+ module Probes
5
+ module Msgr
6
+ module Client
7
+ NAME = 'external.publish.msgr'.freeze
8
+
9
+ class Probe < ::Mnemosyne::Probe
10
+ def setup
11
+ ::Msgr::Client.send :prepend, Instrumentation
12
+ end
13
+ end
14
+
15
+ module Instrumentation
16
+ def publish(payload, **options)
17
+ if (trace = ::Mnemosyne::Instrumenter.current_trace)
18
+ meta = {}
19
+ span = ::Mnemosyne::Span.new(NAME, meta: meta)
20
+ span.start!
21
+
22
+ options[:headers] ||= {}
23
+ options[:headers][:'mnemosyne.transaction'] = trace.transaction
24
+ options[:headers][:'mnemosyne.origin'] = span.uuid
25
+
26
+ begin
27
+ super
28
+ ensure
29
+ span.finish!
30
+ trace << span
31
+ end
32
+ else
33
+ super
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ register 'Msgr::Client', 'msgr/client', Msgr::Client::Probe.new
41
+ end
42
+ end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mnemosyne
4
+ module Probes
5
+ module Msgr
6
+ module Consumer
7
+ NAME = 'app.messaging.receive.msgr'.freeze
8
+
9
+ class Probe < ::Mnemosyne::Probe
10
+ def setup
11
+ ::Msgr::Consumer.send :prepend, Instrumentation
12
+ end
13
+ end
14
+
15
+ module Instrumentation
16
+ def dispatch(message) # rubocop:disable AbcSize
17
+ route = message.route
18
+ metadata = message.metadata
19
+ delivery_info = message.delivery_info
20
+
21
+ origin = metadata.headers.delete('mnemosyne.origin')
22
+ transaction = metadata.headers.delete('mnemosyne.transaction') do
23
+ ::SecureRandom.uuid
24
+ end
25
+
26
+ trace = ::Mnemosyne::Instrumenter.trace NAME,
27
+ transaction: transaction,
28
+ origin: origin
29
+
30
+ if trace
31
+ trace.meta[:properties] = {
32
+ content_type: metadata.content_type,
33
+ priority: metadata.priority,
34
+ headers: metadata.headers,
35
+ type: metadata.type,
36
+ reply_to: metadata.reply_to,
37
+ correlation_id: metadata.correlation_id,
38
+ message_id: metadata.message_id,
39
+ app_id: metadata.app_id
40
+ }
41
+
42
+ trace.meta[:delivery_info] = {
43
+ consumer_tag: delivery_info.consumer_tag,
44
+ redelivered: delivery_info.redelivered?,
45
+ routing_key: delivery_info.routing_key,
46
+ exchange: delivery_info.exchange
47
+ }
48
+
49
+ trace.meta[:route] = {
50
+ consumer: route.consumer,
51
+ action: route.action
52
+ }
53
+
54
+ trace.start!
55
+ end
56
+
57
+ super
58
+ ensure
59
+ if trace
60
+ trace.submit
61
+ trace.release
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+
68
+ register 'Msgr::Consumer', 'msgr/consumer', Msgr::Consumer::Probe.new
69
+ end
70
+ end
@@ -12,7 +12,6 @@ module Mnemosyne
12
12
  ::Mnemosyne::Probes::Responder::Respond::Instrumentation
13
13
  end
14
14
 
15
- # rubocop:disable Metrics/ParameterLists
16
15
  def call(trace, _name, start, finish, _id, _payload)
17
16
  start = ::Mnemosyne::Clock.to_tick(start)
18
17
  finish = ::Mnemosyne::Clock.to_tick(finish)
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mnemosyne
4
+ module Probes
5
+ module Sidekiq
6
+ module Client
7
+ class Probe < ::Mnemosyne::Probe
8
+ def setup
9
+ ::Sidekiq.configure_client do |config|
10
+ config.client_middleware do |chain|
11
+ chain.prepend Middleware
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ class Middleware
18
+ def call(_worker, job, _queue, _redis)
19
+ if (trace = ::Mnemosyne::Instrumenter.current_trace)
20
+ meta = {
21
+ worker: job['class'],
22
+ queue: job['queue'],
23
+ arguments: job['args'],
24
+ raw: job.clone
25
+ }
26
+
27
+ span = ::Mnemosyne::Span.new('external.job.sidekiq', meta: meta)
28
+ span.finish! oneshot: true
29
+
30
+ job['mnemosyne.transaction'] = trace.transaction
31
+ job['mnemosyne.origin'] = span.uuid
32
+
33
+ trace << span
34
+ end
35
+
36
+ yield
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ register 'Sidekiq::Client', 'sidekiq/client', Sidekiq::Client::Probe.new
43
+ end
44
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mnemosyne
4
+ module Probes
5
+ module Sidekiq
6
+ module Server
7
+ class Probe < ::Mnemosyne::Probe
8
+ def setup
9
+ require 'mnemosyne/middleware/sidekiq'
10
+
11
+ ::Sidekiq.configure_server do |config|
12
+ config.server_middleware do |chain|
13
+ chain.prepend ::Mnemosyne::Middleware::Sidekiq
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+
21
+ register 'Sidekiq::Worker', 'sidekiq/worker', Sidekiq::Server::Probe.new
22
+ end
23
+ end
@@ -1,71 +1,20 @@
1
1
  # frozen_string_literal: true
2
- require 'forwardable'
3
2
 
4
3
  module Mnemosyne
5
4
  module Probes
6
- class Registration
7
- extend ::Forwardable
8
-
9
- attr_reader :class_name, :require_paths
10
-
11
- def initialize(class_name, require_paths, probe)
12
- @class_name = class_name
13
- @require_paths = Array require_paths
14
- @probe = probe
15
- end
16
-
17
- def installable?
18
- return true unless class_name
19
-
20
- ::Mnemosyne::Probes.class_available? class_name
21
- end
22
-
23
- delegate install: :@probe
24
- end
25
-
26
5
  class << self
27
- def class_available?(class_name)
28
- Module.const_get(class_name).is_a? Class
29
- rescue NameError
30
- false
31
- end
32
-
33
6
  def register(*args)
34
- registration = Registration.new(*args)
35
-
36
- if registration.installable?
37
- registration.install
38
- else
39
- register_require_hook registration
40
- end
7
+ registry.register(*args)
41
8
  end
42
9
 
43
- def require_hook(name)
44
- registration = require_hooks[name]
45
- return unless registration
46
- return unless registration.installable?
47
-
48
- registration.install
49
-
50
- unregister_require_hook registration
51
- end
52
-
53
- def register_require_hook(registration)
54
- registration.require_paths.each do |path|
55
- require_hooks[path] = registration
56
- end
57
- end
58
-
59
- def unregister_require_hook(registration)
60
- registration.require_paths.each do |path|
61
- require_hooks.delete path
62
- end
10
+ def activate!
11
+ registry.activate!
63
12
  end
64
13
 
65
14
  private
66
15
 
67
- def require_hooks
68
- @require_hooks ||= {}
16
+ def registry
17
+ @registry ||= ::Mnemosyne::Registry.new
69
18
  end
70
19
  end
71
20
  end
@@ -77,12 +26,9 @@ module Kernel
77
26
  def require(name)
78
27
  ret = require_without_mn(name)
79
28
 
80
- # rubocop:disable Lint/RescueException
81
29
  begin
82
- ::Mnemosyne::Probes.require_hook(name)
83
-
84
- # rubocop:disable Lint/HandleExceptions
85
- rescue Exception
30
+ ::Mnemosyne::Probes.registry.required(name)
31
+ rescue Exception # rubocop:disable RescueException, HandleExceptions
86
32
  end
87
33
 
88
34
  ret
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'forwardable'
4
+
5
+ module Mnemosyne
6
+ class Registry
7
+ class Registration
8
+ extend ::Forwardable
9
+
10
+ attr_reader :class_name, :require_paths
11
+
12
+ def initialize(class_name, require_paths, probe)
13
+ @class_name = class_name
14
+ @require_paths = Array(require_paths)
15
+ @probe = probe
16
+ end
17
+
18
+ def installable?
19
+ return true unless class_name
20
+
21
+ begin
22
+ Module.const_get(class_name).is_a?(Class) ||
23
+ Module.const_get(class_name).is_a?(Module)
24
+ rescue NameError
25
+ false
26
+ end
27
+ end
28
+
29
+ delegate install: :@probe
30
+ end
31
+
32
+ def initialize
33
+ @registrations = []
34
+ @activated = false
35
+ @monitor = Monitor.new
36
+ end
37
+
38
+ def activate!
39
+ return if activated?
40
+
41
+ @registrations.each(&method(:activate))
42
+
43
+ @activated = true
44
+ end
45
+
46
+ def activated?
47
+ @activated
48
+ end
49
+
50
+ def register(*args)
51
+ @registrations << (registration = Registration.new(*args))
52
+
53
+ activate(registration) if activated?
54
+ end
55
+
56
+ private
57
+
58
+ attr_reader :monitor
59
+
60
+ def activate(registration)
61
+ if registration.installable?
62
+ registration.install
63
+ else
64
+ monitor << registration
65
+ end
66
+ end
67
+
68
+ class Monitor
69
+ def initialize
70
+ @requirements = {}
71
+ end
72
+
73
+ def <<(registration)
74
+ registration.require_paths.each do |path|
75
+ @requirements[path] ||= []
76
+ @requirements[path] << registration
77
+ end
78
+ end
79
+
80
+ def delete(registration)
81
+ registration.require_paths.each do |path|
82
+ @requirements[path].delete(registration)
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
@@ -2,9 +2,10 @@
2
2
 
3
3
  module Mnemosyne
4
4
  class Span
5
- attr_reader :uuid, :name, :start, :finish, :meta
5
+ attr_reader :uuid, :name, :start, :finish, :meta, :type
6
6
 
7
7
  def initialize(name, start: false, finish: false, meta: {})
8
+ @type = nil
8
9
  @name = name
9
10
  @meta = meta
10
11
  @uuid = ::SecureRandom.uuid
@@ -14,12 +15,23 @@ module Mnemosyne
14
15
  end
15
16
 
16
17
  def start!
18
+ raise 'Already started' if @start
19
+
17
20
  @start = ::Mnemosyne::Clock.tick
21
+
18
22
  self
19
23
  end
20
24
 
21
- def finish!
25
+ def finish!(oneshot: false)
26
+ raise 'Already finished' if @finish
27
+
22
28
  @finish = ::Mnemosyne::Clock.tick
29
+
30
+ if oneshot
31
+ @start = @finish unless @start
32
+ @type = :oneshot
33
+ end
34
+
23
35
  self
24
36
  end
25
37
 
@@ -27,6 +39,7 @@ module Mnemosyne
27
39
  {
28
40
  uuid: uuid,
29
41
  name: name,
42
+ type: type,
30
43
  start: start,
31
44
  stop: finish,
32
45
  meta: meta
@@ -2,10 +2,10 @@
2
2
 
3
3
  module Mnemosyne
4
4
  class Trace < Span
5
- attr_reader :uuid, :transaction, :origin
5
+ attr_reader :uuid, :transaction, :origin, :span
6
6
 
7
- def initialize(instrumenter, name, transaction: nil, origin: nil)
8
- super name
7
+ def initialize(instrumenter, name, transaction: nil, origin: nil, **kwargs)
8
+ super(name, **kwargs)
9
9
 
10
10
  @uuid = ::SecureRandom.uuid
11
11
  @span = []
@@ -3,9 +3,9 @@
3
3
  module Mnemosyne
4
4
  module VERSION
5
5
  MAJOR = 1
6
- MINOR = 0
7
- PATCH = 1
8
- STAGE = nil
6
+ MINOR = 1
7
+ PATCH = 0
8
+ STAGE = :rc1
9
9
 
10
10
  STRING = [MAJOR, MINOR, PATCH, STAGE].reject(&:nil?).join('.')
11
11
 
data/lib/mnemosyne.rb CHANGED
@@ -17,6 +17,7 @@ module Mnemosyne
17
17
  require 'mnemosyne/client'
18
18
  require 'mnemosyne/instrumenter'
19
19
 
20
+ require 'mnemosyne/registry'
20
21
  require 'mnemosyne/probe'
21
22
  require 'mnemosyne/probes'
22
23
 
@@ -32,8 +33,12 @@ module Mnemosyne
32
33
  require 'mnemosyne/probes/grape/endpoint_render'
33
34
  require 'mnemosyne/probes/grape/endpoint_run'
34
35
  require 'mnemosyne/probes/grape/endpoint_run_filters'
36
+ require 'mnemosyne/probes/msgr/client'
37
+ require 'mnemosyne/probes/msgr/consumer'
35
38
  require 'mnemosyne/probes/responder/respond'
36
39
  require 'mnemosyne/probes/restify/base'
40
+ require 'mnemosyne/probes/sidekiq/client'
41
+ require 'mnemosyne/probes/sidekiq/server'
37
42
  end
38
43
 
39
44
  module Middleware
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mnemosyne-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jan Graichen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-04-19 00:00:00.000000000 Z
11
+ date: 2017-05-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bunny
@@ -134,6 +134,7 @@ files:
134
134
  - lib/mnemosyne/middleware/acfs.rb
135
135
  - lib/mnemosyne/middleware/rack.rb
136
136
  - lib/mnemosyne/middleware/restify.rb
137
+ - lib/mnemosyne/middleware/sidekiq.rb
137
138
  - lib/mnemosyne/probe.rb
138
139
  - lib/mnemosyne/probes.rb
139
140
  - lib/mnemosyne/probes/acfs/request.rb
@@ -146,9 +147,14 @@ files:
146
147
  - lib/mnemosyne/probes/grape/endpoint_run.rb
147
148
  - lib/mnemosyne/probes/grape/endpoint_run_filters.rb
148
149
  - lib/mnemosyne/probes/mnemosyne/tracer.rb
150
+ - lib/mnemosyne/probes/msgr/client.rb
151
+ - lib/mnemosyne/probes/msgr/consumer.rb
149
152
  - lib/mnemosyne/probes/responder/respond.rb
150
153
  - lib/mnemosyne/probes/restify/base.rb
154
+ - lib/mnemosyne/probes/sidekiq/client.rb
155
+ - lib/mnemosyne/probes/sidekiq/server.rb
151
156
  - lib/mnemosyne/railtie.rb
157
+ - lib/mnemosyne/registry.rb
152
158
  - lib/mnemosyne/span.rb
153
159
  - lib/mnemosyne/trace.rb
154
160
  - lib/mnemosyne/version.rb
@@ -170,9 +176,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
170
176
  version: '0'
171
177
  required_rubygems_version: !ruby/object:Gem::Requirement
172
178
  requirements:
173
- - - ">="
179
+ - - ">"
174
180
  - !ruby/object:Gem::Version
175
- version: '0'
181
+ version: 1.3.1
176
182
  requirements: []
177
183
  rubyforge_project:
178
184
  rubygems_version: 2.6.11