skylight-core 2.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +7 -0
  2. data/lib/skylight/core/config.rb +454 -0
  3. data/lib/skylight/core/errors.rb +6 -0
  4. data/lib/skylight/core/fanout.rb +44 -0
  5. data/lib/skylight/core/formatters/http.rb +23 -0
  6. data/lib/skylight/core/gc.rb +107 -0
  7. data/lib/skylight/core/instrumentable.rb +144 -0
  8. data/lib/skylight/core/instrumenter.rb +249 -0
  9. data/lib/skylight/core/middleware.rb +101 -0
  10. data/lib/skylight/core/normalizers/action_controller/process_action.rb +50 -0
  11. data/lib/skylight/core/normalizers/action_controller/send_file.rb +50 -0
  12. data/lib/skylight/core/normalizers/action_view/render_collection.rb +22 -0
  13. data/lib/skylight/core/normalizers/action_view/render_partial.rb +21 -0
  14. data/lib/skylight/core/normalizers/action_view/render_template.rb +21 -0
  15. data/lib/skylight/core/normalizers/active_job/enqueue_at.rb +21 -0
  16. data/lib/skylight/core/normalizers/active_model_serializers/render.rb +26 -0
  17. data/lib/skylight/core/normalizers/active_record/instantiation.rb +17 -0
  18. data/lib/skylight/core/normalizers/active_record/sql.rb +33 -0
  19. data/lib/skylight/core/normalizers/active_support/cache.rb +20 -0
  20. data/lib/skylight/core/normalizers/active_support/cache_clear.rb +16 -0
  21. data/lib/skylight/core/normalizers/active_support/cache_decrement.rb +16 -0
  22. data/lib/skylight/core/normalizers/active_support/cache_delete.rb +16 -0
  23. data/lib/skylight/core/normalizers/active_support/cache_exist.rb +16 -0
  24. data/lib/skylight/core/normalizers/active_support/cache_fetch_hit.rb +16 -0
  25. data/lib/skylight/core/normalizers/active_support/cache_generate.rb +16 -0
  26. data/lib/skylight/core/normalizers/active_support/cache_increment.rb +16 -0
  27. data/lib/skylight/core/normalizers/active_support/cache_read.rb +16 -0
  28. data/lib/skylight/core/normalizers/active_support/cache_read_multi.rb +16 -0
  29. data/lib/skylight/core/normalizers/active_support/cache_write.rb +16 -0
  30. data/lib/skylight/core/normalizers/coach/handler_finish.rb +36 -0
  31. data/lib/skylight/core/normalizers/coach/middleware_finish.rb +23 -0
  32. data/lib/skylight/core/normalizers/couch_potato/query.rb +20 -0
  33. data/lib/skylight/core/normalizers/data_mapper/sql.rb +12 -0
  34. data/lib/skylight/core/normalizers/default.rb +27 -0
  35. data/lib/skylight/core/normalizers/elasticsearch/request.rb +20 -0
  36. data/lib/skylight/core/normalizers/faraday/request.rb +37 -0
  37. data/lib/skylight/core/normalizers/grape/endpoint.rb +30 -0
  38. data/lib/skylight/core/normalizers/grape/endpoint_render.rb +26 -0
  39. data/lib/skylight/core/normalizers/grape/endpoint_run.rb +33 -0
  40. data/lib/skylight/core/normalizers/grape/endpoint_run_filters.rb +23 -0
  41. data/lib/skylight/core/normalizers/moped/query.rb +100 -0
  42. data/lib/skylight/core/normalizers/sequel/sql.rb +12 -0
  43. data/lib/skylight/core/normalizers/sql.rb +49 -0
  44. data/lib/skylight/core/normalizers.rb +170 -0
  45. data/lib/skylight/core/probes/action_controller.rb +31 -0
  46. data/lib/skylight/core/probes/action_view.rb +37 -0
  47. data/lib/skylight/core/probes/active_model_serializers.rb +55 -0
  48. data/lib/skylight/core/probes/elasticsearch.rb +37 -0
  49. data/lib/skylight/core/probes/excon/middleware.rb +72 -0
  50. data/lib/skylight/core/probes/excon.rb +26 -0
  51. data/lib/skylight/core/probes/faraday.rb +22 -0
  52. data/lib/skylight/core/probes/grape.rb +80 -0
  53. data/lib/skylight/core/probes/httpclient.rb +46 -0
  54. data/lib/skylight/core/probes/middleware.rb +58 -0
  55. data/lib/skylight/core/probes/mongo.rb +171 -0
  56. data/lib/skylight/core/probes/mongoid.rb +21 -0
  57. data/lib/skylight/core/probes/moped.rb +39 -0
  58. data/lib/skylight/core/probes/net_http.rb +64 -0
  59. data/lib/skylight/core/probes/redis.rb +71 -0
  60. data/lib/skylight/core/probes/sequel.rb +33 -0
  61. data/lib/skylight/core/probes/sinatra.rb +69 -0
  62. data/lib/skylight/core/probes/tilt.rb +27 -0
  63. data/lib/skylight/core/probes.rb +129 -0
  64. data/lib/skylight/core/railtie.rb +166 -0
  65. data/lib/skylight/core/subscriber.rb +124 -0
  66. data/lib/skylight/core/test.rb +98 -0
  67. data/lib/skylight/core/trace.rb +190 -0
  68. data/lib/skylight/core/user_config.rb +61 -0
  69. data/lib/skylight/core/util/allocation_free.rb +26 -0
  70. data/lib/skylight/core/util/clock.rb +56 -0
  71. data/lib/skylight/core/util/deploy.rb +132 -0
  72. data/lib/skylight/core/util/gzip.rb +21 -0
  73. data/lib/skylight/core/util/inflector.rb +112 -0
  74. data/lib/skylight/core/util/logging.rb +127 -0
  75. data/lib/skylight/core/util/platform.rb +77 -0
  76. data/lib/skylight/core/util/proxy.rb +13 -0
  77. data/lib/skylight/core/util.rb +14 -0
  78. data/lib/skylight/core/vendor/active_support/notifications.rb +207 -0
  79. data/lib/skylight/core/vendor/active_support/per_thread_registry.rb +52 -0
  80. data/lib/skylight/core/vendor/thread_safe/non_concurrent_cache_backend.rb +133 -0
  81. data/lib/skylight/core/vendor/thread_safe/synchronized_cache_backend.rb +76 -0
  82. data/lib/skylight/core/vendor/thread_safe.rb +126 -0
  83. data/lib/skylight/core/version.rb +6 -0
  84. data/lib/skylight/core/vm/gc.rb +70 -0
  85. data/lib/skylight/core.rb +99 -0
  86. metadata +254 -0
@@ -0,0 +1,144 @@
1
+ module Skylight
2
+ module Core
3
+ module Instrumentable
4
+
5
+ def self.included(base)
6
+ base.extend(ClassMethods)
7
+
8
+ base.const_set(:LOCK, Mutex.new)
9
+
10
+ base.class_eval do
11
+ at_exit do
12
+ if RUBY_VERSION == '1.9.2'
13
+ # workaround for MRI bug losing exit status in at_exit block
14
+ # http://bugs.ruby-lang.org/issues/5218
15
+ exit_status = $!.status if $!.is_a?(SystemExit)
16
+ stop!
17
+ exit exit_status if exit_status
18
+ else
19
+ stop!
20
+ end
21
+ end
22
+ end
23
+
24
+ Skylight::Core::Fanout.register(base)
25
+ end
26
+
27
+ module ClassMethods
28
+
29
+ def instrumenter_class
30
+ Skylight::Core::Instrumenter
31
+ end
32
+
33
+ def instrumenter
34
+ @instrumenter
35
+ end
36
+
37
+ def correlation_header
38
+ nil
39
+ end
40
+
41
+ # Start instrumenting
42
+ def start!(config=nil)
43
+ return @instrumenter if @instrumenter
44
+
45
+ const_get(:LOCK).synchronize do
46
+ return @instrumenter if @instrumenter
47
+
48
+ config ||= {}
49
+ config = config_class.load(config) unless config.is_a?(config_class)
50
+
51
+ @instrumenter = instrumenter_class.new(config).start!
52
+ end
53
+ rescue => e
54
+ message = sprintf("[SKYLIGHT] [#{VERSION}] Unable to start Instrumenter; msg=%s; class=%s", e.message, e.class)
55
+ if config && config.respond_to?(:logger)
56
+ config.logger.warn message
57
+ else
58
+ warn message
59
+ end
60
+ false
61
+ end
62
+
63
+ # Stop instrumenting
64
+ def stop!
65
+ const_get(:LOCK).synchronize do
66
+ return unless @instrumenter
67
+ # This is only really helpful for getting specs to pass.
68
+ @instrumenter.current_trace = nil
69
+
70
+ @instrumenter.shutdown
71
+ @instrumenter = nil
72
+ end
73
+ end
74
+
75
+ # Check tracing
76
+ def tracing?
77
+ instrumenter && instrumenter.current_trace
78
+ end
79
+
80
+ # Start a trace
81
+ def trace(endpoint=nil, cat=nil, title=nil, meta=nil)
82
+ unless instrumenter
83
+ return yield if block_given?
84
+ return
85
+ end
86
+
87
+ if block_given?
88
+ instrumenter.trace(endpoint, cat || DEFAULT_CATEGORY, title, nil, meta) { yield }
89
+ else
90
+ instrumenter.trace(endpoint, cat || DEFAULT_CATEGORY, title, nil, meta)
91
+ end
92
+ end
93
+
94
+ # Instrument
95
+ def instrument(opts = DEFAULT_OPTIONS, &block)
96
+ unless instrumenter
97
+ return yield if block_given?
98
+ return
99
+ end
100
+
101
+ if Hash === opts
102
+ category = opts[:category] || DEFAULT_CATEGORY
103
+ title = opts[:title]
104
+ desc = opts[:description]
105
+ meta = opts[:meta]
106
+ if opts.key?(:annotations)
107
+ warn "call to #instrument included deprecated annotations"
108
+ end
109
+ else
110
+ category = DEFAULT_CATEGORY
111
+ title = opts.to_s
112
+ desc = nil
113
+ meta = nil
114
+ end
115
+
116
+ instrumenter.instrument(category, title, desc, meta, &block)
117
+ end
118
+
119
+ def span_correlation_header(span)
120
+ return unless instrumenter
121
+ instrumenter.span_correlation_header(span)
122
+ end
123
+
124
+ # End a span
125
+ def done(span, meta=nil)
126
+ return unless instrumenter
127
+ instrumenter.done(span, meta)
128
+ end
129
+
130
+ # Temporarily disable
131
+ def disable
132
+ unless instrumenter
133
+ return yield if block_given?
134
+ return
135
+ end
136
+
137
+ instrumenter.disable { yield }
138
+ end
139
+
140
+ end
141
+
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,249 @@
1
+ require 'thread'
2
+ require 'strscan'
3
+
4
+ module Skylight::Core
5
+ # @api private
6
+ class Instrumenter
7
+ KEY = :__skylight_current_trace
8
+
9
+ TOO_MANY_UNIQUES = "<too many unique descriptions>"
10
+
11
+ include Util::Logging
12
+
13
+ class TraceInfo
14
+ def initialize(key=KEY)
15
+ @key = key
16
+ end
17
+
18
+ def current
19
+ Thread.current[@key]
20
+ end
21
+
22
+ def current=(trace)
23
+ Thread.current[@key] = trace
24
+ end
25
+ end
26
+
27
+ attr_reader :config, :gc, :trace_info
28
+
29
+ def self.trace_class
30
+ Trace
31
+ end
32
+
33
+ def self.native_new
34
+ raise "not implemented"
35
+ end
36
+
37
+ def self.new(config)
38
+ config.validate!
39
+
40
+ inst = native_new(config.to_native_env)
41
+ inst.send(:initialize, config)
42
+ inst
43
+ end
44
+
45
+ def initialize(config)
46
+ @gc = config.gc
47
+ @config = config
48
+ @subscriber = Subscriber.new(config, self)
49
+
50
+ key = "#{KEY}_#{self.class.trace_class.name}".gsub(/\W/, '_')
51
+ @trace_info = @config[:trace_info] || TraceInfo.new(key)
52
+ end
53
+
54
+ def native_start
55
+ raise "not implemented"
56
+ end
57
+
58
+ def native_stop
59
+ raise "not implemented"
60
+ end
61
+
62
+ def native_track_desc
63
+ raise "not implemented"
64
+ end
65
+
66
+ def native_submit_trace
67
+ raise "not implemented"
68
+ end
69
+
70
+ def current_trace
71
+ @trace_info.current
72
+ end
73
+
74
+ def current_trace=(trace)
75
+ @trace_info.current = trace
76
+ end
77
+
78
+ def check_install!
79
+ true
80
+ end
81
+
82
+ def start!
83
+ # We do this here since we can't report these issues via Gem install without stopping install entirely.
84
+ check_install!
85
+
86
+ t { "starting instrumenter" }
87
+
88
+ unless config.validate_with_server
89
+ log_error "invalid config"
90
+ return
91
+ end
92
+
93
+ t { "starting native instrumenter" }
94
+ unless native_start
95
+ warn "failed to start instrumenter"
96
+ return
97
+ end
98
+
99
+ config.gc.enable
100
+ @subscriber.register!
101
+
102
+ self
103
+
104
+ rescue Exception => e
105
+ log_error "failed to start instrumenter; msg=%s; config=%s", e.message, config.inspect
106
+ t { e.backtrace.join("\n") }
107
+ nil
108
+ end
109
+
110
+ def shutdown
111
+ @subscriber.unregister!
112
+ native_stop
113
+ end
114
+
115
+ def trace(endpoint, cat, title=nil, desc=nil, meta=nil)
116
+ # If a trace is already in progress, continue with that one
117
+ if trace = @trace_info.current
118
+ return yield(trace) if block_given?
119
+ return trace
120
+ end
121
+
122
+ begin
123
+ trace = self.class.trace_class.new(self, endpoint, Util::Clock.nanos, cat, title, desc, meta)
124
+ rescue Exception => e
125
+ log_error e.message
126
+ t { e.backtrace.join("\n") }
127
+ return
128
+ end
129
+
130
+ @trace_info.current = trace
131
+ return trace unless block_given?
132
+
133
+ begin
134
+ yield trace
135
+
136
+ ensure
137
+ @trace_info.current = nil
138
+ t { "submitting trace" }
139
+ trace.submit
140
+ end
141
+ end
142
+
143
+ def disable
144
+ @disabled = true
145
+ yield
146
+ ensure
147
+ @disabled = false
148
+ end
149
+
150
+ def disabled?
151
+ @disabled
152
+ end
153
+
154
+ def self.match?(string, regex)
155
+ @scanner ||= StringScanner.new('')
156
+ @scanner.string = string
157
+ @scanner.match?(regex)
158
+ end
159
+
160
+ def match?(string, regex)
161
+ self.class.match?(string, regex)
162
+ end
163
+
164
+ def instrument(cat, title=nil, desc=nil, meta=nil)
165
+ raise ArgumentError, 'cat is required' unless cat
166
+
167
+ unless trace = @trace_info.current
168
+ return yield if block_given?
169
+ return
170
+ end
171
+
172
+ cat = cat.to_s
173
+
174
+ unless match?(cat, Skylight::CATEGORY_REGEX)
175
+ warn "invalid skylight instrumentation category; value=%s", cat
176
+ return yield if block_given?
177
+ return
178
+ end
179
+
180
+ cat = "other.#{cat}" unless match?(cat, Skylight::TIER_REGEX)
181
+
182
+ unless sp = trace.instrument(cat, title, desc, meta)
183
+ return yield if block_given?
184
+ return
185
+ end
186
+
187
+ return sp unless block_given?
188
+
189
+ meta = {}
190
+ begin
191
+ yield sp
192
+ rescue Exception => e
193
+ meta = { exception: [e.class.name, e.message], exception_object: e }
194
+ raise e
195
+ ensure
196
+ trace.done(sp, meta)
197
+ end
198
+ end
199
+
200
+ def span_correlation_header(span)
201
+ return unless trace = @trace_info.current
202
+ trace.span_correlation_header(span)
203
+ end
204
+
205
+ def done(span, meta=nil)
206
+ return unless trace = @trace_info.current
207
+ trace.done(span, meta)
208
+ end
209
+
210
+ def limited_description(description)
211
+ endpoint = @trace_info.current.endpoint
212
+
213
+ if description
214
+ if native_track_desc(endpoint, description)
215
+ description
216
+ else
217
+ TOO_MANY_UNIQUES
218
+ end
219
+ end
220
+ end
221
+
222
+ def process(trace)
223
+ t { fmt "processing trace" }
224
+
225
+ if ignore?(trace)
226
+ t { fmt "ignoring trace" }
227
+ return false
228
+ end
229
+
230
+ begin
231
+ native_submit_trace(trace)
232
+ true
233
+ rescue => e
234
+ warn "failed to submit trace to worker; err=%s", e
235
+ false
236
+ end
237
+ end
238
+
239
+ def ignore?(trace)
240
+ config.ignored_endpoints.include?(trace.endpoint.sub(%r{<sk-segment>.+</sk-segment>}, ''))
241
+ end
242
+
243
+ # Return [title, sql]
244
+ def process_sql(sql)
245
+ [nil, sql]
246
+ end
247
+
248
+ end
249
+ end
@@ -0,0 +1,101 @@
1
+ module Skylight::Core
2
+ # @api private
3
+ class Middleware
4
+
5
+ class BodyProxy
6
+ def initialize(body, &block)
7
+ @body, @block, @closed = body, block, false
8
+ end
9
+
10
+ def respond_to?(*args)
11
+ return false if args.first.to_s =~ /^to_ary$/
12
+ super or @body.respond_to?(*args)
13
+ end
14
+
15
+ def close
16
+ return if @closed
17
+ @closed = true
18
+ begin
19
+ @body.close if @body.respond_to? :close
20
+ ensure
21
+ @block.call
22
+ end
23
+ end
24
+
25
+ def closed?
26
+ @closed
27
+ end
28
+
29
+ # N.B. This method is a special case to address the bug described by
30
+ # https://github.com/rack/rack/issues/434.
31
+ # We are applying this special case for #each only. Future bugs of this
32
+ # class will be handled by requesting users to patch their ruby
33
+ # implementation, to save adding too many methods in this class.
34
+ def each(*args, &block)
35
+ @body.each(*args, &block)
36
+ end
37
+
38
+ def method_missing(*args, &block)
39
+ super if args.first.to_s =~ /^to_ary$/
40
+ @body.__send__(*args, &block)
41
+ end
42
+ end
43
+
44
+ def self.with_after_close(resp, &block)
45
+ # Responses should be finished but in some situations they aren't
46
+ # e.g. https://github.com/ruby-grape/grape/issues/1041
47
+ if resp.respond_to?(:finish)
48
+ resp = resp.finish
49
+ end
50
+
51
+ resp[2] = BodyProxy.new(resp[2], &block)
52
+ resp
53
+ end
54
+
55
+ include Util::Logging
56
+
57
+ # For Util::Logging
58
+ attr_reader :config
59
+
60
+ def initialize(app, opts={})
61
+ @app = app
62
+ @config = opts[:config]
63
+ end
64
+
65
+ def instrumentable
66
+ Skylight
67
+ end
68
+
69
+ # Allow for overwriting
70
+ def endpoint_name(_env)
71
+ "Rack"
72
+ end
73
+
74
+ def endpoint_meta(_env)
75
+ nil
76
+ end
77
+
78
+ def call(env)
79
+ if env["REQUEST_METHOD"] == "HEAD"
80
+ t { "middleware skipping HEAD" }
81
+ @app.call(env)
82
+ else
83
+ begin
84
+ t { "middleware beginning trace" }
85
+ trace = instrumentable.trace(endpoint_name(env), 'app.rack.request', nil, endpoint_meta(env))
86
+ resp = @app.call(env)
87
+
88
+ if trace
89
+ Middleware.with_after_close(resp) { trace.submit }
90
+ else
91
+ resp
92
+ end
93
+ rescue Exception
94
+ t { "middleware exception: #{trace}"}
95
+ trace.submit if trace
96
+ raise
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,50 @@
1
+ module Skylight::Core
2
+ module Normalizers
3
+ module ActionController
4
+ # Normalizer for processing a Rails controller action
5
+ class ProcessAction < Normalizer
6
+ register "process_action.action_controller"
7
+
8
+ CAT = "app.controller.request".freeze
9
+
10
+ # Payload Keys: controller, action, params, format, method, path
11
+ # Additional keys available in `normalize_after`: status, view_runtime
12
+ # Along with ones added by probe: variant
13
+
14
+ # @param trace [Skylight::Messages::Trace::Builder]
15
+ # @param name [String] ignored, only present to match API
16
+ # @param payload [Hash]
17
+ # @option payload [String] :controller Controller name
18
+ # @option payload [String] :action Action name
19
+ # @return [Array]
20
+ def normalize(trace, name, payload)
21
+ trace.endpoint = controller_action(payload)
22
+ [ CAT, trace.endpoint, nil ]
23
+ end
24
+
25
+ def normalize_after(trace, span, name, payload)
26
+ return unless config.enable_segments?
27
+
28
+ # Show 'error' if there's an unhandled exception or if the status is 4xx or 5xx
29
+ if payload[:exception] || payload[:exception_object] || payload[:status].to_s =~ /^[45]/
30
+ segment = "error"
31
+ # We won't have a rendered_format if it's a `head` outside of a `respond_to` block.
32
+ elsif payload[:rendered_format]
33
+ # We only show the variant if we actually have a format
34
+ segment = [payload[:rendered_format], payload[:variant]].compact.flatten.join('+')
35
+ end
36
+
37
+ if segment
38
+ trace.endpoint += "<sk-segment>#{segment}</sk-segment>"
39
+ end
40
+ end
41
+
42
+ private
43
+
44
+ def controller_action(payload)
45
+ "#{payload[:controller]}##{payload[:action]}"
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,50 @@
1
+ module Skylight::Core
2
+ module Normalizers
3
+ module ActionController
4
+
5
+ # Temporary hacks
6
+ begin
7
+ require "action_dispatch/http/mime_type"
8
+ require "action_dispatch/http/mime_types"
9
+ require "rack/utils"
10
+
11
+ class SendFile < Normalizer
12
+ register "send_file.action_controller"
13
+
14
+ CAT = "app.controller.send_file".freeze
15
+ TITLE = "send file".freeze
16
+
17
+ def normalize(trace, name, payload)
18
+ path = payload[:path]
19
+
20
+ title = TITLE
21
+
22
+ # depending on normalization, we probably want this to eventually
23
+ # include the full path, but we need to make sure we have a good
24
+ # deduping strategy first.
25
+ desc = nil
26
+
27
+ [ CAT, title, desc ]
28
+ end
29
+
30
+ private
31
+
32
+ OCTET_STREAM = "application/octet-stream".freeze
33
+ ATTACHMENT = "attachment".freeze
34
+
35
+ def initialize(*)
36
+ super
37
+
38
+ @mimes = Mime::SET.reduce({}) do |hash, mime|
39
+ hash[mime.symbol] = mime.to_s.dup.freeze
40
+ hash
41
+ end
42
+ end
43
+ end
44
+
45
+ rescue LoadError
46
+ end
47
+
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,22 @@
1
+ module Skylight::Core
2
+ module Normalizers
3
+ module ActionView
4
+ # Normalizer for Rails collection rendering
5
+ class RenderCollection < RenderNormalizer
6
+ register "render_collection.action_view"
7
+
8
+ CAT = "view.render.collection".freeze
9
+
10
+ # @param trace [Skylight::Messages::Trace::Builder] ignored, only present to match API
11
+ # @param name [String] ignored, only present to match API
12
+ # @param payload (see RenderNormalizer#normalize_render)
13
+ # @option payload (see RenderNormalizer#normalize_render)
14
+ # @option payload [Integer] :count
15
+ # @return (see RenderNormalizer#normalize_render)
16
+ def normalize(trace, name, payload)
17
+ normalize_render(CAT, payload)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,21 @@
1
+ module Skylight::Core
2
+ module Normalizers
3
+ module ActionView
4
+ # Normalizer for Rails partial rendering
5
+ class RenderPartial < RenderNormalizer
6
+ register "render_partial.action_view"
7
+
8
+ CAT = "view.render.template".freeze
9
+
10
+ # @param trace [Skylight::Messages::Trace::Builder] ignored, only present to match API
11
+ # @param name [String] ignored, only present to match API
12
+ # @param payload (see RenderNormalizer#normalize_render)
13
+ # @option payload (see RenderNormalizer#normalize_render)
14
+ # @return (see RenderNormalizer#normalize_render)
15
+ def normalize(trace, name, payload)
16
+ normalize_render(CAT, payload)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ module Skylight::Core
2
+ module Normalizers
3
+ module ActionView
4
+ # Normalizer for Rails template rendering
5
+ class RenderTemplate < RenderNormalizer
6
+ register "render_template.action_view"
7
+
8
+ CAT = "view.render.template".freeze
9
+
10
+ # @param trace [Skylight::Messages::Trace::Builder] ignored, only present to match API
11
+ # @param name [String] ignored, only present to match API
12
+ # @param payload (see RenderNormalizer#normalize_render)
13
+ # @option payload (see RenderNormalizer#normalize_render)
14
+ # @return (see RenderNormalizer#normalize_render)
15
+ def normalize(trace, name, payload)
16
+ normalize_render(CAT, payload)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ module Skylight::Core
2
+ module Normalizers
3
+ module ActiveJob
4
+ class EnqueueAt < Normalizer
5
+ register "enqueue_at.active_job"
6
+
7
+ CAT = "other.job.enqueue_at".freeze
8
+
9
+ def normalize(_trace, _name, payload)
10
+ title = "Enqueue #{payload[:job].class}"
11
+
12
+ adapter_class_name = payload[:adapter].class.name
13
+ adapter_name = adapter_class_name.match(/^ActiveJob::QueueAdapters::(\w+)Adapter$/)[1].underscore
14
+ desc = "{ adapter: '#{adapter_name}', queue: '#{payload[:job].queue_name}' }"
15
+
16
+ [ CAT, title, desc ]
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,26 @@
1
+ module Skylight::Core
2
+ module Normalizers
3
+ module ActiveModelSerializers
4
+ class Render < Normalizer
5
+ register "render.active_model_serializers"
6
+
7
+ CAT = "view.render.active_model_serializers".freeze
8
+
9
+ def normalize(trace, name, payload)
10
+ serializer_class = payload[:serializer]
11
+
12
+ title = serializer_class.name.sub(/^ActiveModel::(Serializer::)?/, '')
13
+
14
+ if adapter_instance = payload[:adapter]
15
+ adapter_name = adapter_instance.class.name
16
+ .sub(/^ActiveModel::Serializer::Adapter::/, '')
17
+ .sub(/^ActiveModelSerializers::Adapter::/, '')
18
+ desc = "Adapter: #{adapter_name}"
19
+ end
20
+
21
+ [ CAT, title, desc ]
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end