skylight-core 4.0.0.alpha4 → 4.0.0.beta

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5b333f6d3704521099216e030773e068bbae7fb08cdea202b8ffc81e76a0beed
4
- data.tar.gz: 00042ab9ca7c24ccba1ea0ebebcbfb664aa78755cfc9d6ae6595f2f7e5754bd4
3
+ metadata.gz: ab9eed2e498ca4b55dfed12501b36fdea71433e0505a2c34733a0d025b03bbdd
4
+ data.tar.gz: c5a4eed17eb02f2beb8e0b54e90196429467676a9b79dbff10ecd24d0cd9c31d
5
5
  SHA512:
6
- metadata.gz: 38a125f7978eb1c05a848a06edaf10ffea2b16227ea474ea0e9a069633ed40029baf8667e569a9664621a486e0bea053011609c9703d634f20ca04489d9aae46
7
- data.tar.gz: c53a44d21608de2a245a8b36ef8d7d4b02870723c88dde340d036473803002f2bef202354cafe3e5b040988adc083dceebf4e575508add93d068945dd13f1fd5
6
+ metadata.gz: 823f266c1a844a4e8424569b34f35afb9b5998c2688b66e299bbc4ad16c335aceffa17d24ed0c38243d89f7b8b16b202f65fdb8d416dc13a830e3505848b86a2
7
+ data.tar.gz: 6c134666859922615c8083298fd42d7d7b04bbb6d2845ab08071daadb65fcc19aa471361cc197b84ddecb708694b3bebb3d8e35f9f825985348c5eacf4809afe
@@ -11,13 +11,14 @@ module Skylight::Core
11
11
  adapter_name = normalize_adapter_name(payload[:adapter])
12
12
  desc = "{ adapter: '#{adapter_name}', queue: '#{payload[:job].queue_name}' }"
13
13
 
14
- maybe_set_endpoint(trace, title)
14
+ maybe_set_endpoint(trace, payload)
15
15
 
16
16
  [CAT, title, desc]
17
17
  end
18
18
 
19
19
  def normalize_after(trace, _span, _name, payload)
20
- return unless config.enable_segments?
20
+ return unless config.enable_segments? && assign_endpoint?(trace, payload)
21
+
21
22
  trace.segment = payload[:job].queue_name
22
23
  end
23
24
 
@@ -30,14 +31,29 @@ module Skylight::Core
30
31
  "active_job"
31
32
  end
32
33
 
33
- def maybe_set_endpoint(trace, string)
34
- trace.endpoint ||= string
34
+ def maybe_set_endpoint(trace, payload)
35
+ if assign_endpoint?(trace, payload)
36
+ trace.endpoint = normalize_title(payload[:job])
37
+ end
38
+ end
39
+
40
+ def assign_endpoint?(trace, payload)
41
+ # Always assign the endpoint if it has not yet been assigned by the ActiveJob probe.
42
+ return true unless trace.endpoint
43
+ return unless defined?(Skylight::Core::Probes::ActiveJob::Probe::TITLE)
35
44
 
36
45
  # If a job is called using #perform_now inside a controller action
37
46
  # or within another job's #perform method, we do not want this to
38
47
  # overwrite the existing endpoint name (unless it is the default from ActiveJob).
39
- return unless trace.endpoint == Skylight::Core::Probes::ActiveJob::Probe::TITLE
40
- trace.endpoint = string
48
+ #
49
+ # If the current endpoint name matches this payload, return true to allow the
50
+ # segment to be assigned by normalize_after.
51
+ trace.endpoint == Skylight::Core::Probes::ActiveJob::Probe::TITLE ||
52
+ trace.endpoint == normalize_title(payload[:job])
53
+ end
54
+
55
+ def normalize_title(job_instance)
56
+ job_instance.class.to_s
41
57
  end
42
58
  end
43
59
  end
@@ -6,12 +6,20 @@ module Skylight::Core
6
6
  ::ActionView::TemplateRenderer.class_eval do
7
7
  alias_method :render_with_layout_without_sk, :render_with_layout
8
8
 
9
- def render_with_layout(path, locals, *args, &block) #:nodoc:
9
+ def render_with_layout(*args, &block) #:nodoc:
10
+ path, locals = case args.length
11
+ when 2
12
+ args
13
+ when 3
14
+ # Rails > 6.0.0.beta1 prepends an additional `view` argument
15
+ args.last(2)
16
+ end
17
+
10
18
  layout = nil
11
19
 
12
20
  if path
13
21
  layout =
14
- if ::ActionView.gem_version >= Gem::Version.new("5.x")
22
+ if ::ActionView::VERSION::MAJOR >= 5
15
23
  find_layout(path, locals.keys, [formats.first])
16
24
  else
17
25
  find_layout(path, locals.keys)
@@ -20,10 +28,10 @@ module Skylight::Core
20
28
 
21
29
  if layout
22
30
  instrument(:template, identifier: layout.identifier) do
23
- render_with_layout_without_sk(path, locals, *args, &block)
31
+ render_with_layout_without_sk(*args, &block)
24
32
  end
25
33
  else
26
- render_with_layout_without_sk(path, locals, *args, &block)
34
+ render_with_layout_without_sk(*args, &block)
27
35
  end
28
36
  end
29
37
  end
@@ -1,5 +1,5 @@
1
1
  module Skylight
2
2
  module Core
3
- VERSION = "4.0.0-alpha4".freeze
3
+ VERSION = "4.0.0-beta".freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: skylight-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.0.alpha4
4
+ version: 4.0.0.beta
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tilde, Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-01-16 00:00:00.000000000 Z
11
+ date: 2019-02-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -244,11 +244,6 @@ files:
244
244
  - lib/skylight/core/util/logging.rb
245
245
  - lib/skylight/core/util/platform.rb
246
246
  - lib/skylight/core/util/proxy.rb
247
- - lib/skylight/core/vendor/active_support/notifications.rb
248
- - lib/skylight/core/vendor/active_support/per_thread_registry.rb
249
- - lib/skylight/core/vendor/thread_safe.rb
250
- - lib/skylight/core/vendor/thread_safe/non_concurrent_cache_backend.rb
251
- - lib/skylight/core/vendor/thread_safe/synchronized_cache_backend.rb
252
247
  - lib/skylight/core/version.rb
253
248
  - lib/skylight/core/vm/gc.rb
254
249
  homepage: https://www.skylight.io
@@ -1,207 +0,0 @@
1
- require 'skylight/core/vendor/active_support/notifications/instrumenter'
2
- require 'skylight/core/vendor/active_support/notifications/fanout'
3
- require 'skylight/core/vendor/active_support/per_thread_registry'
4
-
5
- module ActiveSupport
6
- # = Notifications
7
- #
8
- # <tt>ActiveSupport::Notifications</tt> provides an instrumentation API for
9
- # Ruby.
10
- #
11
- # == Instrumenters
12
- #
13
- # To instrument an event you just need to do:
14
- #
15
- # ActiveSupport::Notifications.instrument('render', extra: :information) do
16
- # render text: 'Foo'
17
- # end
18
- #
19
- # That executes the block first and notifies all subscribers once done.
20
- #
21
- # In the example above +render+ is the name of the event, and the rest is called
22
- # the _payload_. The payload is a mechanism that allows instrumenters to pass
23
- # extra information to subscribers. Payloads consist of a hash whose contents
24
- # are arbitrary and generally depend on the event.
25
- #
26
- # == Subscribers
27
- #
28
- # You can consume those events and the information they provide by registering
29
- # a subscriber.
30
- #
31
- # ActiveSupport::Notifications.subscribe('render') do |name, start, finish, id, payload|
32
- # name # => String, name of the event (such as 'render' from above)
33
- # start # => Time, when the instrumented block started execution
34
- # finish # => Time, when the instrumented block ended execution
35
- # id # => String, unique ID for this notification
36
- # payload # => Hash, the payload
37
- # end
38
- #
39
- # For instance, let's store all "render" events in an array:
40
- #
41
- # events = []
42
- #
43
- # ActiveSupport::Notifications.subscribe('render') do |*args|
44
- # events << ActiveSupport::Notifications::Event.new(*args)
45
- # end
46
- #
47
- # That code returns right away, you are just subscribing to "render" events.
48
- # The block is saved and will be called whenever someone instruments "render":
49
- #
50
- # ActiveSupport::Notifications.instrument('render', extra: :information) do
51
- # render text: 'Foo'
52
- # end
53
- #
54
- # event = events.first
55
- # event.name # => "render"
56
- # event.duration # => 10 (in milliseconds)
57
- # event.payload # => { extra: :information }
58
- #
59
- # The block in the <tt>subscribe</tt> call gets the name of the event, start
60
- # timestamp, end timestamp, a string with a unique identifier for that event
61
- # (something like "535801666f04d0298cd6"), and a hash with the payload, in
62
- # that order.
63
- #
64
- # If an exception happens during that particular instrumentation the payload will
65
- # have a key <tt>:exception</tt> with an array of two elements as value: a string with
66
- # the name of the exception class, and the exception message.
67
- #
68
- # As the previous example depicts, the class <tt>ActiveSupport::Notifications::Event</tt>
69
- # is able to take the arguments as they come and provide an object-oriented
70
- # interface to that data.
71
- #
72
- # It is also possible to pass an object as the second parameter passed to the
73
- # <tt>subscribe</tt> method instead of a block:
74
- #
75
- # module ActionController
76
- # class PageRequest
77
- # def call(name, started, finished, unique_id, payload)
78
- # Rails.logger.debug ['notification:', name, started, finished, unique_id, payload].join(' ')
79
- # end
80
- # end
81
- # end
82
- #
83
- # ActiveSupport::Notifications.subscribe('process_action.action_controller', ActionController::PageRequest.new)
84
- #
85
- # resulting in the following output within the logs including a hash with the payload:
86
- #
87
- # notification: process_action.action_controller 2012-04-13 01:08:35 +0300 2012-04-13 01:08:35 +0300 af358ed7fab884532ec7 {
88
- # controller: "Devise::SessionsController",
89
- # action: "new",
90
- # params: {"action"=>"new", "controller"=>"devise/sessions"},
91
- # format: :html,
92
- # method: "GET",
93
- # path: "/login/sign_in",
94
- # status: 200,
95
- # view_runtime: 279.3080806732178,
96
- # db_runtime: 40.053
97
- # }
98
- #
99
- # You can also subscribe to all events whose name matches a certain regexp:
100
- #
101
- # ActiveSupport::Notifications.subscribe(/render/) do |*args|
102
- # ...
103
- # end
104
- #
105
- # and even pass no argument to <tt>subscribe</tt>, in which case you are subscribing
106
- # to all events.
107
- #
108
- # == Temporary Subscriptions
109
- #
110
- # Sometimes you do not want to subscribe to an event for the entire life of
111
- # the application. There are two ways to unsubscribe.
112
- #
113
- # WARNING: The instrumentation framework is designed for long-running subscribers,
114
- # use this feature sparingly because it wipes some internal caches and that has
115
- # a negative impact on performance.
116
- #
117
- # === Subscribe While a Block Runs
118
- #
119
- # You can subscribe to some event temporarily while some block runs. For
120
- # example, in
121
- #
122
- # callback = lambda {|*args| ... }
123
- # ActiveSupport::Notifications.subscribed(callback, "sql.active_record") do
124
- # ...
125
- # end
126
- #
127
- # the callback will be called for all "sql.active_record" events instrumented
128
- # during the execution of the block. The callback is unsubscribed automatically
129
- # after that.
130
- #
131
- # === Manual Unsubscription
132
- #
133
- # The +subscribe+ method returns a subscriber object:
134
- #
135
- # subscriber = ActiveSupport::Notifications.subscribe("render") do |*args|
136
- # ...
137
- # end
138
- #
139
- # To prevent that block from being called anymore, just unsubscribe passing
140
- # that reference:
141
- #
142
- # ActiveSupport::Notifications.unsubscribe(subscriber)
143
- #
144
- # == Default Queue
145
- #
146
- # Notifications ships with a queue implementation that consumes and publish events
147
- # to log subscribers in a thread. You can use any queue implementation you want.
148
- #
149
- module Notifications
150
- class << self
151
- attr_accessor :notifier
152
-
153
- def publish(name, *args)
154
- notifier.publish(name, *args)
155
- end
156
-
157
- def instrument(name, payload = {})
158
- if notifier.listening?(name)
159
- instrumenter.instrument(name, payload) { yield payload if block_given? }
160
- else
161
- yield payload if block_given?
162
- end
163
- end
164
-
165
- def subscribe(*args, &block)
166
- notifier.subscribe(*args, &block)
167
- end
168
-
169
- def subscribed(callback, *args, &block)
170
- subscriber = subscribe(*args, &callback)
171
- yield
172
- ensure
173
- unsubscribe(subscriber)
174
- end
175
-
176
- def unsubscribe(args)
177
- notifier.unsubscribe(args)
178
- end
179
-
180
- def instrumenter
181
- InstrumentationRegistry.instrumenter_for(notifier)
182
- end
183
- end
184
-
185
- # This class is a registry which holds all of the +Instrumenter+ objects
186
- # in a particular thread local. To access the +Instrumenter+ object for a
187
- # particular +notifier+, you can call the following method:
188
- #
189
- # InstrumentationRegistry.instrumenter_for(notifier)
190
- #
191
- # The instrumenters for multiple notifiers are held in a single instance of
192
- # this class.
193
- class InstrumentationRegistry # :nodoc:
194
- extend ActiveSupport::PerThreadRegistry
195
-
196
- def initialize
197
- @registry = {}
198
- end
199
-
200
- def instrumenter_for(notifier)
201
- @registry[notifier] ||= Instrumenter.new(notifier)
202
- end
203
- end
204
-
205
- self.notifier = Fanout.new
206
- end
207
- end
@@ -1,52 +0,0 @@
1
- module ActiveSupport
2
- # This module is used to encapsulate access to thread local variables.
3
- #
4
- # Instead of polluting the thread locals namespace:
5
- #
6
- # Thread.current[:connection_handler]
7
- #
8
- # you define a class that extends this module:
9
- #
10
- # module ActiveRecord
11
- # class RuntimeRegistry
12
- # extend ActiveSupport::PerThreadRegistry
13
- #
14
- # attr_accessor :connection_handler
15
- # end
16
- # end
17
- #
18
- # and invoke the declared instance accessors as class methods. So
19
- #
20
- # ActiveRecord::RuntimeRegistry.connection_handler = connection_handler
21
- #
22
- # sets a connection handler local to the current thread, and
23
- #
24
- # ActiveRecord::RuntimeRegistry.connection_handler
25
- #
26
- # returns a connection handler local to the current thread.
27
- #
28
- # This feature is accomplished by instantiating the class and storing the
29
- # instance as a thread local keyed by the class name. In the example above
30
- # a key "ActiveRecord::RuntimeRegistry" is stored in <tt>Thread.current</tt>.
31
- # The class methods proxy to said thread local instance.
32
- #
33
- # If the class has an initializer, it must accept no arguments.
34
- module PerThreadRegistry
35
- protected
36
-
37
- def method_missing(name, *args, &block) # :nodoc:
38
- # Caches the method definition as a singleton method of the receiver.
39
- define_singleton_method(name) do |*a, &b|
40
- per_thread_registry_instance.public_send(name, *a, &b)
41
- end
42
-
43
- send(name, *args, &block)
44
- end
45
-
46
- private
47
-
48
- def per_thread_registry_instance
49
- Thread.current[name] ||= new
50
- end
51
- end
52
- end
@@ -1,133 +0,0 @@
1
- module ThreadSafe
2
- class NonConcurrentCacheBackend
3
- # WARNING: all public methods of the class must operate on the @backend directly without calling each other. This is important
4
- # because of the SynchronizedCacheBackend which uses a non-reentrant mutex for perfomance reasons.
5
- def initialize(options = nil)
6
- @backend = {}
7
- end
8
-
9
- def [](key)
10
- @backend[key]
11
- end
12
-
13
- def []=(key, value)
14
- @backend[key] = value
15
- end
16
-
17
- def compute_if_absent(key)
18
- if NULL != (stored_value = @backend.fetch(key, NULL))
19
- stored_value
20
- else
21
- @backend[key] = yield
22
- end
23
- end
24
-
25
- def replace_pair(key, old_value, new_value)
26
- if pair?(key, old_value)
27
- @backend[key] = new_value
28
- true
29
- else
30
- false
31
- end
32
- end
33
-
34
- def replace_if_exists(key, new_value)
35
- if NULL != (stored_value = @backend.fetch(key, NULL))
36
- @backend[key] = new_value
37
- stored_value
38
- end
39
- end
40
-
41
- def compute_if_present(key)
42
- if NULL != (stored_value = @backend.fetch(key, NULL))
43
- store_computed_value(key, yield(stored_value))
44
- end
45
- end
46
-
47
- def compute(key)
48
- store_computed_value(key, yield(@backend[key]))
49
- end
50
-
51
- def merge_pair(key, value)
52
- if NULL == (stored_value = @backend.fetch(key, NULL))
53
- @backend[key] = value
54
- else
55
- store_computed_value(key, yield(stored_value))
56
- end
57
- end
58
-
59
- def get_and_set(key, value)
60
- stored_value = @backend[key]
61
- @backend[key] = value
62
- stored_value
63
- end
64
-
65
- def key?(key)
66
- @backend.key?(key)
67
- end
68
-
69
- def value?(value)
70
- @backend.value?(value)
71
- end
72
-
73
- def delete(key)
74
- @backend.delete(key)
75
- end
76
-
77
- def delete_pair(key, value)
78
- if pair?(key, value)
79
- @backend.delete(key)
80
- true
81
- else
82
- false
83
- end
84
- end
85
-
86
- def clear
87
- @backend.clear
88
- self
89
- end
90
-
91
- def each_pair
92
- dupped_backend.each_pair do |k, v|
93
- yield k, v
94
- end
95
- self
96
- end
97
-
98
- def size
99
- @backend.size
100
- end
101
-
102
- def get_or_default(key, default_value)
103
- @backend.fetch(key, default_value)
104
- end
105
-
106
- alias_method :_get, :[]
107
- alias_method :_set, :[]=
108
- private :_get, :_set
109
- private
110
- def initialize_copy(other)
111
- super
112
- @backend = {}
113
- self
114
- end
115
-
116
- def dupped_backend
117
- @backend.dup
118
- end
119
-
120
- def pair?(key, expected_value)
121
- NULL != (stored_value = @backend.fetch(key, NULL)) && expected_value.equal?(stored_value)
122
- end
123
-
124
- def store_computed_value(key, new_value)
125
- if new_value.nil?
126
- @backend.delete(key)
127
- nil
128
- else
129
- @backend[key] = new_value
130
- end
131
- end
132
- end
133
- end
@@ -1,76 +0,0 @@
1
- module ThreadSafe
2
- class SynchronizedCacheBackend < NonConcurrentCacheBackend
3
- require 'mutex_m'
4
- include Mutex_m
5
- # WARNING: Mutex_m is a non-reentrant lock, so the synchronized methods are not allowed to call each other.
6
-
7
- def [](key)
8
- synchronize { super }
9
- end
10
-
11
- def []=(key, value)
12
- synchronize { super }
13
- end
14
-
15
- def compute_if_absent(key)
16
- synchronize { super }
17
- end
18
-
19
- def compute_if_present(key)
20
- synchronize { super }
21
- end
22
-
23
- def compute(key)
24
- synchronize { super }
25
- end
26
-
27
- def merge_pair(key, value)
28
- synchronize { super }
29
- end
30
-
31
- def replace_pair(key, old_value, new_value)
32
- synchronize { super }
33
- end
34
-
35
- def replace_if_exists(key, new_value)
36
- synchronize { super }
37
- end
38
-
39
- def get_and_set(key, value)
40
- synchronize { super }
41
- end
42
-
43
- def key?(key)
44
- synchronize { super }
45
- end
46
-
47
- def value?(value)
48
- synchronize { super }
49
- end
50
-
51
- def delete(key)
52
- synchronize { super }
53
- end
54
-
55
- def delete_pair(key, value)
56
- synchronize { super }
57
- end
58
-
59
- def clear
60
- synchronize { super }
61
- end
62
-
63
- def size
64
- synchronize { super }
65
- end
66
-
67
- def get_or_default(key, default_value)
68
- synchronize { super }
69
- end
70
-
71
- private
72
- def dupped_backend
73
- synchronize { super }
74
- end
75
- end
76
- end
@@ -1,126 +0,0 @@
1
- require 'thread'
2
-
3
- module ThreadSafe
4
- autoload :NonConcurrentCacheBackend, 'skylight/core/vendor/thread_safe/non_concurrent_cache_backend'
5
- autoload :SynchronizedCacheBackend, 'skylight/core/vendor/thread_safe/synchronized_cache_backend'
6
-
7
- ConcurrentCacheBackend = SynchronizedCacheBackend
8
-
9
- class Cache < ConcurrentCacheBackend
10
- KEY_ERROR = defined?(KeyError) ? KeyError : IndexError # there is no KeyError in 1.8 mode
11
-
12
- def initialize(options = nil, &block)
13
- if options.kind_of?(::Hash)
14
- validate_options_hash!(options)
15
- else
16
- options = nil
17
- end
18
-
19
- super(options)
20
- @default_proc = block
21
- end
22
-
23
- def [](key)
24
- if value = super
25
- value
26
- elsif @default_proc && !key?(key)
27
- @default_proc.call(self, key)
28
- else
29
- value
30
- end
31
- end
32
-
33
- def fetch(key, default_value = NULL)
34
- if NULL != (value = get_or_default(key, NULL))
35
- value
36
- elsif block_given?
37
- yield key
38
- elsif NULL != default_value
39
- default_value
40
- else
41
- raise KEY_ERROR, 'key not found'
42
- end
43
- end
44
-
45
- def put_if_absent(key, value)
46
- computed = false
47
- result = compute_if_absent(key) do
48
- computed = true
49
- value
50
- end
51
- computed ? nil : result
52
- end unless method_defined?(:put_if_absent)
53
-
54
- def value?(value)
55
- each_value do |v|
56
- return true if value.equal?(v)
57
- end
58
- false
59
- end unless method_defined?(:value?)
60
-
61
- def keys
62
- arr = []
63
- each_pair {|k, v| arr << k}
64
- arr
65
- end unless method_defined?(:keys)
66
-
67
- def values
68
- arr = []
69
- each_pair {|k, v| arr << v}
70
- arr
71
- end unless method_defined?(:values)
72
-
73
- def each_key
74
- each_pair {|k, v| yield k}
75
- end unless method_defined?(:each_key)
76
-
77
- def each_value
78
- each_pair {|k, v| yield v}
79
- end unless method_defined?(:each_value)
80
-
81
- def empty?
82
- each_pair {|k, v| return false}
83
- true
84
- end unless method_defined?(:empty?)
85
-
86
- def size
87
- count = 0
88
- each_pair {|k, v| count += 1}
89
- count
90
- end unless method_defined?(:size)
91
-
92
- def marshal_dump
93
- raise TypeError, "can't dump hash with default proc" if @default_proc
94
- h = {}
95
- each_pair {|k, v| h[k] = v}
96
- h
97
- end
98
-
99
- def marshal_load(hash)
100
- initialize
101
- populate_from(hash)
102
- end
103
-
104
- undef :freeze
105
-
106
- private
107
- def initialize_copy(other)
108
- super
109
- populate_from(other)
110
- end
111
-
112
- def populate_from(hash)
113
- hash.each_pair {|k, v| self[k] = v}
114
- self
115
- end
116
-
117
- def validate_options_hash!(options)
118
- if (initial_capacity = options[:initial_capacity]) && (!initial_capacity.kind_of?(Fixnum) || initial_capacity < 0)
119
- raise ArgumentError, ":initial_capacity must be a positive Fixnum"
120
- end
121
- if (load_factor = options[:load_factor]) && (!load_factor.kind_of?(Numeric) || load_factor <= 0 || load_factor > 1)
122
- raise ArgumentError, ":load_factor must be a number between 0 and 1"
123
- end
124
- end
125
- end
126
- end