skylight-core 2.0.0.beta3 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/lib/skylight/core.rb +1 -0
  3. data/lib/skylight/core/config.rb +2 -0
  4. data/lib/skylight/core/deprecation.rb +15 -0
  5. data/lib/skylight/core/instrumentable.rb +8 -0
  6. data/lib/skylight/core/instrumenter.rb +20 -12
  7. data/lib/skylight/core/middleware.rb +46 -14
  8. data/lib/skylight/core/normalizers.rb +34 -86
  9. data/lib/skylight/core/normalizers/action_view/render_collection.rb +2 -0
  10. data/lib/skylight/core/normalizers/action_view/render_partial.rb +2 -0
  11. data/lib/skylight/core/normalizers/action_view/render_template.rb +2 -0
  12. data/lib/skylight/core/normalizers/render.rb +77 -0
  13. data/lib/skylight/core/probes.rb +73 -73
  14. data/lib/skylight/core/probes/action_controller.rb +1 -1
  15. data/lib/skylight/core/probes/action_dispatch.rb +1 -0
  16. data/lib/skylight/core/probes/action_dispatch/request_id.rb +31 -0
  17. data/lib/skylight/core/probes/action_view.rb +1 -1
  18. data/lib/skylight/core/probes/active_model_serializers.rb +1 -1
  19. data/lib/skylight/core/probes/elasticsearch.rb +1 -1
  20. data/lib/skylight/core/probes/excon.rb +1 -1
  21. data/lib/skylight/core/probes/faraday.rb +1 -1
  22. data/lib/skylight/core/probes/httpclient.rb +1 -1
  23. data/lib/skylight/core/probes/middleware.rb +19 -3
  24. data/lib/skylight/core/probes/mongo.rb +1 -1
  25. data/lib/skylight/core/probes/mongoid.rb +3 -3
  26. data/lib/skylight/core/probes/moped.rb +1 -1
  27. data/lib/skylight/core/probes/net_http.rb +1 -1
  28. data/lib/skylight/core/probes/redis.rb +1 -1
  29. data/lib/skylight/core/probes/sequel.rb +1 -1
  30. data/lib/skylight/core/probes/sinatra.rb +1 -1
  31. data/lib/skylight/core/probes/tilt.rb +1 -1
  32. data/lib/skylight/core/test.rb +95 -82
  33. data/lib/skylight/core/trace.rb +48 -19
  34. data/lib/skylight/core/user_config.rb +1 -0
  35. data/lib/skylight/core/util.rb +0 -1
  36. data/lib/skylight/core/util/logging.rb +12 -4
  37. data/lib/skylight/core/version.rb +1 -1
  38. metadata +9 -8
  39. data/lib/skylight/core/normalizers/couch_potato/query.rb +0 -20
  40. data/lib/skylight/core/probes/grape.rb +0 -80
  41. data/lib/skylight/core/util/deploy.rb +0 -132
@@ -8,14 +8,14 @@ module Skylight::Core
8
8
  version = Gem::Version.new(::Mongoid::VERSION)
9
9
 
10
10
  if version < Gem::Version.new("5.0")
11
- require 'skylight/core/probes/moped'
11
+ Skylight::Core::Probes.probe(:moped)
12
12
  else
13
- require 'skylight/core/probes/mongo'
13
+ Skylight::Core::Probes.probe(:mongo)
14
14
  end
15
15
  end
16
16
  end
17
17
  end
18
18
 
19
- register("Mongoid", "mongoid", Mongoid::Probe.new)
19
+ register(:mongoid, "Mongoid", "mongoid", Mongoid::Probe.new)
20
20
  end
21
21
  end
@@ -34,6 +34,6 @@ module Skylight::Core
34
34
  end
35
35
  end
36
36
 
37
- register("Moped", "moped", Moped::Probe.new)
37
+ register(:moped, "Moped", "moped", Moped::Probe.new)
38
38
  end
39
39
  end
@@ -59,6 +59,6 @@ module Skylight::Core
59
59
  end
60
60
  end
61
61
 
62
- register("Net::HTTP", "net/http", NetHTTP::Probe.new)
62
+ register(:net_http, "Net::HTTP", "net/http", NetHTTP::Probe.new)
63
63
  end
64
64
  end
@@ -66,6 +66,6 @@ module Skylight::Core
66
66
  end
67
67
  end
68
68
 
69
- register("Redis", "redis", Redis::Probe.new)
69
+ register(:redis, "Redis", "redis", Redis::Probe.new)
70
70
  end
71
71
  end
@@ -28,6 +28,6 @@ module Skylight::Core
28
28
  end
29
29
  end
30
30
 
31
- register("Sequel", "sequel", Sequel::Probe.new)
31
+ register(:sequel, "Sequel", "sequel", Sequel::Probe.new)
32
32
  end
33
33
  end
@@ -64,6 +64,6 @@ module Skylight::Core
64
64
  end
65
65
  end
66
66
 
67
- register("Sinatra::Base", "sinatra/base", Sinatra::Probe.new)
67
+ register(:sinatra, "Sinatra::Base", "sinatra/base", Sinatra::Probe.new)
68
68
  end
69
69
  end
@@ -22,6 +22,6 @@ module Skylight::Core
22
22
  end
23
23
  end
24
24
 
25
- register("Tilt::Template", "tilt/template", Tilt::Probe.new)
25
+ register(:tilt, "Tilt::Template", "tilt/template", Tilt::Probe.new)
26
26
  end
27
27
  end
@@ -7,94 +7,107 @@ module Skylight
7
7
  config_opts[:mock_submission] ||= callback || proc {}
8
8
  config = config_class.load(config_opts)
9
9
 
10
- mock_instrumenter_klass = Class.new(instrumenter_class) do
11
- def self.trace_class
12
- @trace_class ||= Class.new(super) do
13
- def self.native_new(start, _uuid, endpoint, meta)
14
- inst = allocate
15
- inst.instance_variable_set(:@start, start)
16
- inst.instance_variable_set(:@endpoint, endpoint)
17
- inst.instance_variable_set(:@starting_endpoint, endpoint)
18
- inst.instance_variable_set(:@meta, meta)
19
- inst
20
- end
21
-
22
- attr_reader :endpoint, :starting_endpoint, :meta
23
-
24
- def mock_spans
25
- @mock_spans ||= []
26
- end
27
-
28
- def native_get_started_at
29
- @start
30
- end
31
-
32
- def native_set_endpoint(endpoint)
33
- @endpoint = endpoint
34
- end
35
-
36
- def native_start_span(time, cat)
37
- span = {
38
- start: time,
39
- cat: cat
40
- }
41
- mock_spans << span
42
- # Return integer like the native method does
43
- mock_spans.index(span)
44
- end
45
-
46
- def native_span_set_title(sp, title)
47
- mock_spans[sp][:title] = title
48
-
49
- end
50
-
51
- def native_span_set_description(sp, desc)
52
- mock_spans[sp][:desc] = desc
53
- end
54
-
55
- def native_span_set_meta(sp, meta)
56
- mock_spans[sp][:meta] = meta
57
- end
58
-
59
- def native_span_started(sp)
60
- end
61
-
62
- def native_span_set_exception(sp, exception_object, exception)
63
- mock_spans[sp][:exception_object] = exception_object
64
- mock_spans[sp][:exception] = exception
65
- end
66
-
67
- def native_stop_span(span, time)
68
- span = mock_spans[span]
69
- span[:duration] = time - span[:start]
70
- nil
10
+ unless respond_to?(:__original_instrumenter_class)
11
+ class_eval do
12
+ class << self
13
+ alias __original_instrumenter_class instrumenter_class
14
+
15
+ def instrumenter_class
16
+ @instrumenter_class ||= Class.new(__original_instrumenter_class) do
17
+ def self.name
18
+ "Mocked Instrumenter"
19
+ end
20
+
21
+ def self.native_new(*)
22
+ allocate
23
+ end
24
+
25
+ def self.trace_class
26
+ @trace_class ||= Class.new(super) do
27
+ def self.native_new(start, _uuid, endpoint, meta)
28
+ inst = allocate
29
+ inst.instance_variable_set(:@start, start)
30
+ inst.instance_variable_set(:@endpoint, endpoint)
31
+ inst.instance_variable_set(:@starting_endpoint, endpoint)
32
+ inst.instance_variable_set(:@meta, meta)
33
+ inst
34
+ end
35
+
36
+ attr_reader :endpoint, :starting_endpoint, :meta
37
+
38
+ def mock_spans
39
+ @mock_spans ||= []
40
+ end
41
+
42
+ def native_get_started_at
43
+ @start
44
+ end
45
+
46
+ def native_set_endpoint(endpoint)
47
+ @endpoint = endpoint
48
+ end
49
+
50
+ def native_start_span(time, cat)
51
+ span = {
52
+ start: time,
53
+ cat: cat
54
+ }
55
+ mock_spans << span
56
+ # Return integer like the native method does
57
+ mock_spans.index(span)
58
+ end
59
+
60
+ def native_span_set_title(sp, title)
61
+ mock_spans[sp][:title] = title
62
+
63
+ end
64
+
65
+ def native_span_set_description(sp, desc)
66
+ mock_spans[sp][:desc] = desc
67
+ end
68
+
69
+ def native_span_set_meta(sp, meta)
70
+ mock_spans[sp][:meta] = meta
71
+ end
72
+
73
+ def native_span_started(sp)
74
+ end
75
+
76
+ def native_span_set_exception(sp, exception_object, exception)
77
+ mock_spans[sp][:exception_object] = exception_object
78
+ mock_spans[sp][:exception] = exception
79
+ end
80
+
81
+ def native_stop_span(span, time)
82
+ span = mock_spans[span]
83
+ span[:duration] = time - span[:start]
84
+ nil
85
+ end
86
+ end
87
+ end
88
+
89
+ def native_start
90
+ true
91
+ end
92
+
93
+ def native_submit_trace(trace)
94
+ config[:mock_submission].call(trace)
95
+ end
96
+
97
+ def native_stop
98
+ end
99
+
100
+ def limited_description(description)
101
+ description
102
+ end
103
+ end
71
104
  end
72
105
  end
73
106
  end
74
-
75
- def self.native_new(*)
76
- allocate
77
- end
78
-
79
- def native_start
80
- true
81
- end
82
-
83
- def native_submit_trace(trace)
84
- config[:mock_submission].call(trace)
85
- end
86
-
87
- def native_stop
88
- end
89
-
90
- def limited_description(description)
91
- description
92
- end
93
107
  end
94
108
 
95
- @instrumenter = mock_instrumenter_klass.new(config).start!
109
+ start!(config)
96
110
  end
97
-
98
111
  end
99
112
  end
100
113
  end
@@ -1,3 +1,5 @@
1
+ require 'securerandom'
2
+
1
3
  module Skylight::Core
2
4
  class Trace
3
5
  GC_CAT = 'noise.gc'.freeze
@@ -5,10 +7,13 @@ module Skylight::Core
5
7
  include Util::Logging
6
8
 
7
9
  attr_reader :instrumenter, :endpoint, :notifications, :meta
10
+ attr_accessor :uuid
8
11
 
9
12
  def self.new(instrumenter, endpoint, start, cat, title=nil, desc=nil, meta=nil)
10
- inst = native_new(normalize_time(start), "TODO", endpoint, meta)
13
+ uuid = SecureRandom.uuid
14
+ inst = native_new(normalize_time(start), uuid, endpoint, meta)
11
15
  inst.send(:initialize, instrumenter, cat, title, desc, meta)
16
+ inst.uuid = uuid
12
17
  inst.endpoint = endpoint
13
18
  inst
14
19
  end
@@ -40,6 +45,10 @@ module Skylight::Core
40
45
  @gc = config.gc.track unless ENV.key?("SKYLIGHT_DISABLE_GC_TRACKING")
41
46
  end
42
47
 
48
+ def log_context
49
+ @log_context ||= { trace: uuid }
50
+ end
51
+
43
52
  def endpoint=(value)
44
53
  @endpoint = value
45
54
  native_set_endpoint(value)
@@ -54,6 +63,11 @@ module Skylight::Core
54
63
  !!@broken
55
64
  end
56
65
 
66
+ def maybe_broken(e)
67
+ error "failed to instrument span; msg=%s; endpoint=%s", e.message, endpoint
68
+ broken!
69
+ end
70
+
57
71
  def record(cat, title=nil, desc=nil)
58
72
  return if broken?
59
73
 
@@ -68,8 +82,7 @@ module Skylight::Core
68
82
 
69
83
  nil
70
84
  rescue => e
71
- error "failed to record span; msg=%s", e.message
72
- broken!
85
+ maybe_broken(e)
73
86
  nil
74
87
  end
75
88
 
@@ -93,8 +106,7 @@ module Skylight::Core
93
106
 
94
107
  start(now - gc_time, cat, title, desc, meta)
95
108
  rescue => e
96
- error "failed to instrument span; msg=%s", e.message
97
- broken!
109
+ maybe_broken(e)
98
110
  nil
99
111
  end
100
112
 
@@ -104,7 +116,10 @@ module Skylight::Core
104
116
  end
105
117
 
106
118
  def done(span, meta=nil)
119
+ # `span` will be `nil` if we failed to start instrumenting, such as in
120
+ # the case of too many spans in a request.
107
121
  return unless span
122
+
108
123
  return if broken?
109
124
 
110
125
  if meta && (meta[:exception_object] || meta[:exception])
@@ -113,12 +128,13 @@ module Skylight::Core
113
128
 
114
129
  stop(span, Util::Clock.nanos - gc_time)
115
130
  rescue => e
116
- error "failed to close span; msg=%s", e.message
131
+ error "failed to close span; msg=%s; endpoint=%s", e.message, endpoint
117
132
  broken!
118
133
  nil
119
134
  end
120
135
 
121
136
  def release
137
+ t { "release; is_current=#{@instrumenter.current_trace == self}" }
122
138
  return unless @instrumenter.current_trace == self
123
139
  @instrumenter.current_trace = nil
124
140
  end
@@ -129,28 +145,28 @@ module Skylight::Core
129
145
  end
130
146
 
131
147
  def traced
132
- time = gc_time
148
+ gc = gc_time
133
149
  now = Util::Clock.nanos
134
-
135
- if time > 0
136
- t { fmt "tracking GC time; duration=%d", time }
137
- stop(start(now - time, GC_CAT, nil, nil, nil), now)
138
- end
139
-
150
+ track_gc(gc, now)
140
151
  stop(@root, now)
141
152
  end
142
153
 
143
154
  def submit
144
- t { "submitting trace; broken=#{broken?}" }
155
+ t { "submitting trace" }
145
156
 
146
- return if broken?
157
+ # This must always be called to clean up properly
158
+ release
159
+
160
+ if broken?
161
+ t { "broken, not submitting" }
162
+ return
163
+ end
147
164
 
148
165
  if @submitted
149
166
  t { "already submitted" }
150
167
  return
151
168
  end
152
169
 
153
- release
154
170
  @submitted = true
155
171
 
156
172
  traced
@@ -163,6 +179,13 @@ module Skylight::Core
163
179
 
164
180
  private
165
181
 
182
+ def track_gc(time, now)
183
+ if time > 0
184
+ t { fmt "tracking GC time; duration=%d", time }
185
+ stop(start(now - time, GC_CAT, nil, nil, nil), now)
186
+ end
187
+ end
188
+
166
189
  def start(time, cat, title, desc, meta, opts={})
167
190
  time = self.class.normalize_time(time) unless opts[:normalize] == false
168
191
 
@@ -186,9 +209,15 @@ module Skylight::Core
186
209
  message = "[E0001] Spans were closed out of order. Expected to see '#{native_span_get_title(expected)}', " \
187
210
  "but got '#{native_span_get_title(span)}' instead."
188
211
 
189
- if native_span_get_category(span) == "rack.middleware"
190
- message << "\n#{native_span_get_title(span)} may be a Middleware that doesn't fully conform " \
191
- "to the Rack SPEC."
212
+ if native_span_get_category(span) == "rack.middleware" &&
213
+ Probes.installed.keys.include?("ActionDispatch::MiddlewareStack::Middleware")
214
+ if Probes::Middleware::Probe.disabled?
215
+ message << "\nWe disabled the Middleware probe but unfortunately, this didn't solve the issue."
216
+ else
217
+ Probes::Middleware::Probe.disable!
218
+ message << "\n#{native_span_get_title(span)} may be a Middleware that doesn't fully conform " \
219
+ "to the Rack SPEC. We've disabled the Middleware probe to see if that resolves the issue."
220
+ end
192
221
  end
193
222
 
194
223
  message << "\nThis request will not be tracked. Please contact support@skylight.io for more information."
@@ -8,6 +8,7 @@ module Skylight::Core
8
8
 
9
9
  def initialize(config)
10
10
  @config = config
11
+ @file_path = nil
11
12
  reload
12
13
  end
13
14
 
@@ -4,7 +4,6 @@ module Skylight::Core
4
4
  # Used from the main lib
5
5
  require 'skylight/core/util/allocation_free'
6
6
  require 'skylight/core/util/clock'
7
- require 'skylight/core/util/deploy'
8
7
  require 'skylight/core/util/logging'
9
8
 
10
9
  # Used from the CLI
@@ -9,7 +9,7 @@ module Skylight::Core
9
9
  end
10
10
 
11
11
  def write(*args)
12
- STDERR.write *args
12
+ STDERR.write(*args)
13
13
 
14
14
  # Try to avoid writing to STDOUT/STDERR twice
15
15
  logger_logdev = @logger.instance_variable_get(:@logdev)
@@ -25,6 +25,10 @@ module Skylight::Core
25
25
 
26
26
  module Logging
27
27
 
28
+ def log_context
29
+ {}
30
+ end
31
+
28
32
  def log_env_prefix
29
33
  if c = config_for_logging
30
34
  c.class.env_prefix
@@ -114,6 +118,8 @@ module Skylight::Core
114
118
  c = config_for_logging
115
119
  logger = c ? c.logger : nil
116
120
 
121
+ msg = log_context.map{|(k,v)| "#{k}=#{v}; " }.join << msg
122
+
117
123
  if logger
118
124
  if logger.respond_to?(level)
119
125
  if args.length > 0
@@ -128,9 +134,11 @@ module Skylight::Core
128
134
  end
129
135
 
130
136
  # Fallback
131
- module_name = self.is_a?(Module) ? name : self.class.name
132
- root_name = module_name.split('::').first.upcase
133
- puts sprintf("[#{root_name}] #{msg}", *args)
137
+ if module_name = self.is_a?(Module) ? name : self.class.name
138
+ root_name = module_name.split('::').first.upcase
139
+ msg.prepend("[#{root_name}] ")
140
+ end
141
+ puts sprintf(msg, *args)
134
142
  rescue Exception => e
135
143
  if trace?
136
144
  puts "[ERROR] #{e.message}"