mnemosyne-ruby 1.0.1 → 1.1.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
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