skylight 0.8.0.beta.1 → 0.8.0.beta.3

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 (36) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +14 -0
  3. data/lib/skylight/config.rb +2 -1
  4. data/lib/skylight/core.rb +5 -4
  5. data/lib/skylight/formatters/http.rb +1 -8
  6. data/lib/skylight/instrumenter.rb +4 -4
  7. data/lib/skylight/normalizers.rb +10 -6
  8. data/lib/skylight/normalizers/action_controller/process_action.rb +1 -13
  9. data/lib/skylight/normalizers/action_controller/send_file.rb +1 -27
  10. data/lib/skylight/normalizers/action_view/render_collection.rb +1 -4
  11. data/lib/skylight/normalizers/action_view/render_partial.rb +1 -4
  12. data/lib/skylight/normalizers/action_view/render_template.rb +1 -4
  13. data/lib/skylight/normalizers/active_record/sql.rb +5 -39
  14. data/lib/skylight/normalizers/active_support/cache_clear.rb +2 -2
  15. data/lib/skylight/normalizers/active_support/cache_decrement.rb +2 -2
  16. data/lib/skylight/normalizers/active_support/cache_delete.rb +2 -2
  17. data/lib/skylight/normalizers/active_support/cache_exist.rb +2 -2
  18. data/lib/skylight/normalizers/active_support/cache_fetch_hit.rb +2 -2
  19. data/lib/skylight/normalizers/active_support/cache_generate.rb +2 -2
  20. data/lib/skylight/normalizers/active_support/cache_increment.rb +2 -2
  21. data/lib/skylight/normalizers/active_support/cache_read.rb +2 -2
  22. data/lib/skylight/normalizers/active_support/cache_read_multi.rb +2 -2
  23. data/lib/skylight/normalizers/active_support/cache_write.rb +2 -2
  24. data/lib/skylight/normalizers/default.rb +2 -4
  25. data/lib/skylight/normalizers/grape/endpoint.rb +30 -0
  26. data/lib/skylight/normalizers/grape/endpoint_render.rb +26 -0
  27. data/lib/skylight/normalizers/grape/endpoint_run.rb +33 -0
  28. data/lib/skylight/normalizers/grape/endpoint_run_filters.rb +23 -0
  29. data/lib/skylight/normalizers/moped/query.rb +12 -58
  30. data/lib/skylight/probes/grape.rb +29 -61
  31. data/lib/skylight/railtie.rb +3 -3
  32. data/lib/skylight/subscriber.rb +13 -4
  33. data/lib/skylight/trace.rb +14 -42
  34. data/lib/skylight/version.rb +1 -1
  35. metadata +6 -3
  36. data/lib/skylight/grape.rb +0 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b0e3fa37632ad3220389279e789146f96720de4d
4
- data.tar.gz: 6a338bac5dfcaaafa26e1737da491f6281bc5470
3
+ metadata.gz: 0993e8d64b2871c815490a9f891733c1a6beaf7d
4
+ data.tar.gz: c003faa733b2421b9cca0843ee188333556a045e
5
5
  SHA512:
6
- metadata.gz: 5b15f061ab93da78cbe138458d81b93c2019473c46040740c06bdd079179c781b2267f2261d16ef3325bc9c91fff2c459c1a78c731e782ff2bd95f9d4baa2c90
7
- data.tar.gz: 70bb2e9ea8f4effb5d3878a0e6159366ebbdf836f7111f65f004ac9244933420edf1121a9533989c2abb8891261e12a12cc70495c59898c2dcd60a708364fe62
6
+ metadata.gz: 5da96227e2f82d8f035f71647d8a3bbbcbd65655c16bf3bc5a1ec244a30cf95dd50747b047919c7d6931d8982e51bae69edb68e84ad6da2e6efaeb0c6babd2c5
7
+ data.tar.gz: ff421edd707482cbf4e750d86b9977925448d1159bce989a72fd58852dec1197f8ef1066dea0b70046f76aed7afbf2f10896d6590ccb10b8b2356f0f3950997d
@@ -1,3 +1,13 @@
1
+ ## 0.8.0-beta.3 (August 10, 2015)
2
+
3
+ * [BUGFIX] Fix require issue in Grape probe
4
+
5
+ ## 0.8.0-beta.2 (August 10, 2015) [YANKED]
6
+
7
+ * [FEATURE] Process ERB in config/skylight.yml
8
+ * [IMPROVEMENT] Switch Grape instrumentation to use ActiveSupport::Notifications hooks provided by future Grape versions.
9
+ * [IMPROVEMENT] Internal cleanup
10
+
1
11
  ## 0.8.0-beta.1 (August 4, 2015)
2
12
 
3
13
  * [FEATURE] Add Grape instumentation
@@ -60,6 +70,10 @@
60
70
  * Featherweight Agent: lowered CPU and memory overhead
61
71
  * [IMPROVEMENT] Add support for ignoring an endpoint by name
62
72
 
73
+ ## 0.3.21 (October 8, 2014)
74
+
75
+ * [BUGFIX] Skylight crashing on start won't crash entire app
76
+
63
77
  ## 0.3.20 (September 3, 2014)
64
78
 
65
79
  * [BUGFIX] Fix app name fetching on Windows for `skylight setup`
@@ -3,6 +3,7 @@ require 'yaml'
3
3
  require 'fileutils'
4
4
  require 'thread'
5
5
  require 'openssl'
6
+ require 'erb'
6
7
  require 'skylight/util/hostname'
7
8
  require 'skylight/util/logging'
8
9
  require 'skylight/util/platform'
@@ -181,7 +182,7 @@ module Skylight
181
182
  if path
182
183
  error = nil
183
184
  begin
184
- attrs = YAML.load_file(path)
185
+ attrs = YAML.load(ERB.new(File.read(path)).result)
185
186
  error = "empty file" unless attrs
186
187
  error = "invalid format" if attrs && !attrs.is_a?(Hash)
187
188
  rescue Exception => e
@@ -95,18 +95,19 @@ module Skylight
95
95
  category = opts[:category] || DEFAULT_CATEGORY
96
96
  title = opts[:title]
97
97
  desc = opts[:description]
98
- annotations = opts[:annotations]
98
+ if opts.key?(:annotations)
99
+ warn "call to #instrument included deprecated annotations"
100
+ end
99
101
  else
100
102
  category = DEFAULT_CATEGORY
101
103
  title = opts.to_s
102
104
  desc = nil
103
- annotations = nil
104
105
  end
105
106
 
106
107
  if block_given?
107
- inst.instrument(category, title, desc, annotations) { yield }
108
+ inst.instrument(category, title, desc) { yield }
108
109
  else
109
- inst.instrument(category, title, desc, annotations)
110
+ inst.instrument(category, title, desc)
110
111
  end
111
112
  end
112
113
 
@@ -3,14 +3,7 @@ module Skylight
3
3
  module HTTP
4
4
  def self.build_opts(method, scheme, host, port, path, query)
5
5
  { category: "api.http.#{method.downcase}",
6
- title: "#{method.upcase} #{host}",
7
- annotations: {
8
- method: method.upcase,
9
- scheme: scheme,
10
- host: host,
11
- port: port ? port.to_i : nil,
12
- path: path,
13
- query: query }}
6
+ title: "#{method.upcase} #{host}" }
14
7
  end
15
8
  end
16
9
  end
@@ -138,7 +138,7 @@ module Skylight
138
138
  native_stop
139
139
  end
140
140
 
141
- def trace(endpoint, cat, title=nil, desc=nil, annot=nil)
141
+ def trace(endpoint, cat, title=nil, desc=nil)
142
142
  # If a trace is already in progress, continue with that one
143
143
  if trace = @trace_info.current
144
144
  return yield(trace) if block_given?
@@ -146,7 +146,7 @@ module Skylight
146
146
  end
147
147
 
148
148
  begin
149
- trace = Trace.new(self, endpoint, Util::Clock.nanos, cat, title, desc, annot)
149
+ trace = Trace.new(self, endpoint, Util::Clock.nanos, cat, title, desc)
150
150
  rescue Exception => e
151
151
  log_error e.message
152
152
  t { e.backtrace.join("\n") }
@@ -192,7 +192,7 @@ module Skylight
192
192
  trace.done(span)
193
193
  end
194
194
 
195
- def instrument(cat, title=nil, desc=nil, annot=nil)
195
+ def instrument(cat, title=nil, desc=nil)
196
196
  raise ArgumentError, 'cat is required' unless cat
197
197
 
198
198
  unless trace = @trace_info.current
@@ -210,7 +210,7 @@ module Skylight
210
210
 
211
211
  cat = "other.#{cat}" unless match?(cat, TIER_REGEX)
212
212
 
213
- unless sp = trace.instrument(cat, title, desc, annot)
213
+ unless sp = trace.instrument(cat, title, desc)
214
214
  return yield if block_given?
215
215
  return
216
216
  end
@@ -47,16 +47,16 @@ module Skylight
47
47
  @paths = config['normalizers.render.view_paths'] || []
48
48
  end
49
49
 
50
- def normalize_render(category, payload, annotations)
50
+ def normalize_render(category, payload)
51
51
  if path = payload[:identifier]
52
- title = relative_path(path, annotations)
52
+ title = relative_path(path)
53
53
  path = nil if path == title
54
54
  end
55
55
 
56
- [ category, title, nil, annotations ]
56
+ [ category, title, nil ]
57
57
  end
58
58
 
59
- def relative_path(path, annotations)
59
+ def relative_path(path)
60
60
  return path if relative_path?(path)
61
61
 
62
62
  root = array_find(@paths) { |p| path.start_with?(p) }
@@ -114,8 +114,11 @@ module Skylight
114
114
  end
115
115
 
116
116
  def normalize(trace, name, payload)
117
- normalizer = @normalizers[name] || DEFAULT
118
- normalizer.normalize(trace, name, payload)
117
+ normalizer_for(name).normalize(trace, name, payload)
118
+ end
119
+
120
+ def normalizer_for(name)
121
+ @normalizers[name] || DEFAULT
119
122
  end
120
123
  end
121
124
 
@@ -126,6 +129,7 @@ module Skylight
126
129
  action_view/render_template
127
130
  active_record/sql
128
131
  active_support/cache
132
+ grape/endpoint
129
133
  moped/query).each do |file|
130
134
  require "skylight/normalizers/#{file}"
131
135
  end
@@ -9,7 +9,7 @@ module Skylight
9
9
 
10
10
  def normalize(trace, name, payload)
11
11
  trace.endpoint = controller_action(payload)
12
- [ CAT, trace.endpoint, nil, normalize_payload(payload) ]
12
+ [ CAT, trace.endpoint, nil ]
13
13
  end
14
14
 
15
15
  private
@@ -17,18 +17,6 @@ module Skylight
17
17
  def controller_action(payload)
18
18
  "#{payload[:controller]}##{payload[:action]}"
19
19
  end
20
-
21
- def normalize_payload(payload)
22
- normalized = {}
23
-
24
- PAYLOAD_KEYS.each do |key|
25
- val = payload[key]
26
- val = val.inspect unless val.is_a?(String) || val.is_a?(Numeric)
27
- normalized[key] = val
28
- end
29
-
30
- normalized
31
- end
32
20
  end
33
21
  end
34
22
  end
@@ -17,13 +17,6 @@ module Skylight
17
17
  def normalize(trace, name, payload)
18
18
  path = payload[:path]
19
19
 
20
- annotations = {
21
- path: path,
22
- filename: payload[:filename],
23
- type: normalize_type(payload),
24
- disposition: normalize_disposition(payload),
25
- status: normalize_status(payload) }
26
-
27
20
  title = TITLE
28
21
 
29
22
  # depending on normalization, we probably want this to eventually
@@ -31,7 +24,7 @@ module Skylight
31
24
  # deduping strategy first.
32
25
  desc = nil
33
26
 
34
- [ CAT, title, desc, annotations ]
27
+ [ CAT, title, desc ]
35
28
  end
36
29
 
37
30
  private
@@ -47,25 +40,6 @@ module Skylight
47
40
  hash
48
41
  end
49
42
  end
50
-
51
- def normalize_type(payload)
52
- type = payload[:type] || OCTET_STREAM
53
- type = @mimes[type] if type.is_a?(Symbol)
54
- type
55
- end
56
-
57
- def mime_for(type)
58
- @mimes[type] ||= Mime[type].to_s.freeze
59
- end
60
-
61
- def normalize_status(payload)
62
- status = payload[:status] || 200
63
- Rack::Utils.status_code(status)
64
- end
65
-
66
- def normalize_disposition(payload)
67
- payload[:disposition] || ATTACHMENT
68
- end
69
43
  end
70
44
 
71
45
  rescue LoadError
@@ -7,10 +7,7 @@ module Skylight
7
7
  CAT = "view.render.collection".freeze
8
8
 
9
9
  def normalize(trace, name, payload)
10
- normalize_render(
11
- CAT,
12
- payload,
13
- count: payload[:count])
10
+ normalize_render(CAT, payload)
14
11
  end
15
12
  end
16
13
  end
@@ -7,10 +7,7 @@ module Skylight
7
7
  CAT = "view.render.template".freeze
8
8
 
9
9
  def normalize(trace, name, payload)
10
- normalize_render(
11
- CAT,
12
- payload,
13
- partial: 1)
10
+ normalize_render(CAT, payload)
14
11
  end
15
12
  end
16
13
  end
@@ -7,10 +7,7 @@ module Skylight
7
7
  CAT = "view.render.template".freeze
8
8
 
9
9
  def normalize(trace, name, payload)
10
- normalize_render(
11
- CAT,
12
- payload,
13
- partial: 0)
10
+ normalize_render(CAT, payload)
14
11
  end
15
12
  end
16
13
  end
@@ -26,52 +26,18 @@ module Skylight
26
26
  binds = binds.map { |col, val| val.inspect }
27
27
  end
28
28
 
29
- extracted_title, sql, binds, _ = extract_binds(payload, binds)
29
+ extracted_title, sql, binds = extract_binds(payload, binds)
30
30
  title = extracted_title if extracted_title
31
31
 
32
- if sql
33
- annotations = {
34
- sql: sql,
35
- binds: binds,
36
- }
37
- end
38
-
39
- [ name, title, sql, annotations ]
32
+ [ name, title, sql ]
40
33
  end
41
34
 
42
35
  private
43
36
  def extract_binds(payload, precalculated)
44
- title, sql, binds = SqlLexer::Lexer.bindify(payload[:sql], precalculated, true)
45
- [ title, sql, binds, nil ]
37
+ SqlLexer::Lexer.bindify(payload[:sql], precalculated, true)
46
38
  rescue => e
47
- group = "sql_parse"
48
- description = e.inspect
49
- details = encode(backtrace: e.backtrace,
50
- original_exception: {
51
- class_name: e.class.name,
52
- message: e.message
53
- },
54
- payload: payload,
55
- precalculated: precalculated)
56
-
57
- error = [group, description, details]
58
- [ nil, nil, nil, error ]
59
- end
60
-
61
- # While operating in place would save memory, some of these passed in items are re-used elsewhere
62
- # and, as such, should not be modified.
63
- def encode(body)
64
- if body.is_a?(Hash)
65
- hash = {}
66
- body.each{|k,v| hash[k] = encode(v) }
67
- hash
68
- elsif body.is_a?(Array)
69
- body.map{|v| encode(v) }
70
- elsif body.respond_to?(:encoding) && (body.encoding == Encoding::BINARY || !body.valid_encoding?)
71
- Base64.encode64(body)
72
- else
73
- body
74
- end
39
+ # TODO: log
40
+ [ nil, nil, nil ]
75
41
  end
76
42
  end
77
43
  end
@@ -8,9 +8,9 @@ module Skylight
8
8
  TITLE = "cache clear".freeze
9
9
 
10
10
  def normalize(trace, name, payload)
11
- [ CAT, TITLE, nil, payload ]
11
+ [ CAT, TITLE, nil ]
12
12
  end
13
13
  end
14
14
  end
15
15
  end
16
- end
16
+ end
@@ -8,9 +8,9 @@ module Skylight
8
8
  TITLE = "cache decrement"
9
9
 
10
10
  def normalize(trace, name, payload)
11
- [ CAT, TITLE, nil, payload ]
11
+ [ CAT, TITLE, nil ]
12
12
  end
13
13
  end
14
14
  end
15
15
  end
16
- end
16
+ end
@@ -8,9 +8,9 @@ module Skylight
8
8
  TITLE = "cache delete"
9
9
 
10
10
  def normalize(trace, name, payload)
11
- [ CAT, TITLE, nil, payload ]
11
+ [ CAT, TITLE, nil ]
12
12
  end
13
13
  end
14
14
  end
15
15
  end
16
- end
16
+ end
@@ -8,9 +8,9 @@ module Skylight
8
8
  TITLE = "cache exist?"
9
9
 
10
10
  def normalize(trace, name, payload)
11
- [ CAT, TITLE, nil, payload ]
11
+ [ CAT, TITLE, nil ]
12
12
  end
13
13
  end
14
14
  end
15
15
  end
16
- end
16
+ end
@@ -8,9 +8,9 @@ module Skylight
8
8
  TITLE = "cache fetch hit"
9
9
 
10
10
  def normalize(trace, name, payload)
11
- [ CAT, TITLE, nil, payload ]
11
+ [ CAT, TITLE, nil ]
12
12
  end
13
13
  end
14
14
  end
15
15
  end
16
- end
16
+ end
@@ -8,9 +8,9 @@ module Skylight
8
8
  TITLE = "cache generate"
9
9
 
10
10
  def normalize(trace, name, payload)
11
- [ CAT, TITLE, nil, payload ]
11
+ [ CAT, TITLE, nil ]
12
12
  end
13
13
  end
14
14
  end
15
15
  end
16
- end
16
+ end
@@ -8,9 +8,9 @@ module Skylight
8
8
  TITLE = "cache increment"
9
9
 
10
10
  def normalize(trace, name, payload)
11
- [ CAT, TITLE, nil, payload ]
11
+ [ CAT, TITLE, nil ]
12
12
  end
13
13
  end
14
14
  end
15
15
  end
16
- end
16
+ end
@@ -8,9 +8,9 @@ module Skylight
8
8
  TITLE = "cache read"
9
9
 
10
10
  def normalize(trace, name, payload)
11
- [ CAT, TITLE, nil, payload ]
11
+ [ CAT, TITLE, nil ]
12
12
  end
13
13
  end
14
14
  end
15
15
  end
16
- end
16
+ end
@@ -8,9 +8,9 @@ module Skylight
8
8
  TITLE = "cache read multi"
9
9
 
10
10
  def normalize(trace, name, payload)
11
- [ CAT, TITLE, nil, payload ]
11
+ [ CAT, TITLE, nil ]
12
12
  end
13
13
  end
14
14
  end
15
15
  end
16
- end
16
+ end
@@ -8,9 +8,9 @@ module Skylight
8
8
  TITLE = "cache write"
9
9
 
10
10
  def normalize(trace, name, payload)
11
- [ CAT, TITLE, nil, payload ]
11
+ [ CAT, TITLE, nil ]
12
12
  end
13
13
  end
14
14
  end
15
15
  end
16
- end
16
+ end
@@ -4,12 +4,10 @@ module Skylight
4
4
 
5
5
  def normalize(trace, name, payload)
6
6
  if name =~ TIER_REGEX
7
- annot = payload.dup
8
7
  [
9
8
  name,
10
- annot.delete(:title),
11
- annot.delete(:description),
12
- annot
9
+ payload[:title],
10
+ payload[:description]
13
11
  ]
14
12
  else
15
13
  :skip
@@ -0,0 +1,30 @@
1
+ module Skylight
2
+ module Normalizers
3
+ module Grape
4
+ class Endpoint < Normalizer
5
+ %w(run
6
+ render
7
+ run_filters).each do |type|
8
+ require "skylight/normalizers/grape/endpoint_#{type}"
9
+ end
10
+
11
+ private
12
+
13
+ def get_method(endpoint)
14
+ method = endpoint.options[:method].first
15
+ method << "..." if endpoint.options[:method].length > 1
16
+ method
17
+ end
18
+
19
+ def get_path(endpoint)
20
+ endpoint.options[:path].join("/")
21
+ end
22
+
23
+ def get_namespace(endpoint)
24
+ ::Grape::Namespace.joined_space(endpoint.namespace_stackable(:namespace))
25
+ end
26
+
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,26 @@
1
+ module Skylight
2
+ module Normalizers
3
+ module Grape
4
+ class EndpointRender < Endpoint
5
+ register "endpoint_render.grape"
6
+
7
+ CAT = "app.grape.endpoint".freeze
8
+
9
+ def normalize(trace, name, payload)
10
+ if endpoint = payload[:endpoint]
11
+ path = get_path(endpoint)
12
+ namespace = get_namespace(endpoint)
13
+ method = get_method(endpoint)
14
+
15
+ title = [method, namespace, path].join(' ').gsub(/\s+/, ' ')
16
+
17
+ [CAT, title, nil]
18
+ else
19
+ :skip
20
+ end
21
+ end
22
+
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,33 @@
1
+ module Skylight
2
+ module Normalizers
3
+ module Grape
4
+ class EndpointRun < Endpoint
5
+ register "endpoint_run.grape"
6
+
7
+ def normalize(trace, name, payload)
8
+ trace.endpoint = get_endpoint_name(payload[:endpoint]) if payload[:endpoint]
9
+
10
+ # We don't necessarily want this to be all instrumented since it's fairly internal.
11
+ # However, it is a good place to get the endpoint name.
12
+ :skip
13
+ end
14
+
15
+ private
16
+
17
+ def get_endpoint_name(endpoint)
18
+ method = get_method(endpoint)
19
+ path = get_path(endpoint)
20
+ namespace = get_namespace(endpoint)
21
+
22
+ if namespace && !namespace.empty?
23
+ path = "/#{path}" if path[0] != '/'
24
+ path = "#{namespace}#{path}"
25
+ end
26
+
27
+ "#{endpoint.options[:for]} [#{method}] #{path}"
28
+ end
29
+
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,23 @@
1
+ module Skylight
2
+ module Normalizers
3
+ module Grape
4
+ class EndpointRunFilters < Endpoint
5
+ register "endpoint_run_filters.grape"
6
+
7
+ CAT = "app.grape.filters".freeze
8
+
9
+ def normalize(trace, name, payload)
10
+ filters = payload[:filters]
11
+ type = payload[:type]
12
+
13
+ if (!filters || filters.empty?) || !type
14
+ return :skip
15
+ end
16
+
17
+ [CAT, "#{type.to_s.capitalize} Filters", nil]
18
+ end
19
+
20
+ end
21
+ end
22
+ end
23
+ end
@@ -29,106 +29,60 @@ module Skylight
29
29
  def normalize_query(operation)
30
30
  title = normalize_title("QUERY", operation)
31
31
 
32
- hash, binds = extract_binds(operation.selector)
32
+ hash = extract_binds(operation.selector)
33
33
  description = hash.to_json
34
34
 
35
- annotations = build_annotations(operation)
36
- annotations[:skip] = operation.skip
37
- if operation.fields
38
- annotations[:fields] = operation.fields.select{|k,v| v == 1 }.keys.map(&:to_s)
39
- end
40
- annotations[:binds] = binds unless binds.empty?
41
-
42
- [CAT, title, description, annotations]
35
+ [CAT, title, description]
43
36
  end
44
37
 
45
38
  def normalize_get_more(operation)
46
39
  title = normalize_title("GET_MORE", operation)
47
40
 
48
- annotations = build_annotations(operation)
49
- annotations[:limit] = operation.limit
50
-
51
- [CAT, title, nil, annotations]
41
+ [CAT, title, nil]
52
42
  end
53
43
 
54
44
  def normalize_insert(operation)
55
45
  title = normalize_title("INSERT", operation)
56
46
 
57
- annotations = build_annotations(operation)
58
- annotations[:count] = operation.documents.count
59
-
60
- [CAT, title, nil, annotations]
47
+ [CAT, title, nil]
61
48
  end
62
49
 
63
50
  def normalize_update(operation)
64
51
  title = normalize_title("UPDATE", operation)
65
52
 
66
- selector_hash, selector_binds = extract_binds(operation.selector)
67
- update_hash, update_binds = extract_binds(operation.update)
53
+ selector_hash = extract_binds(operation.selector)
54
+ update_hash = extract_binds(operation.update)
68
55
 
69
56
  description = { selector: selector_hash, update: update_hash }.to_json
70
57
 
71
- annotations = build_annotations(operation)
72
-
73
- binds = {}
74
- binds[:selector] = selector_binds unless selector_binds.empty?
75
- binds[:update] = update_binds unless update_binds.empty?
76
- annotations[:binds] = binds unless binds.empty?
77
-
78
- [CAT, title, description, annotations]
58
+ [CAT, title, description]
79
59
  end
80
60
 
81
61
  def normalize_delete(operation)
82
62
  title = normalize_title("DELETE", operation)
83
63
 
84
- hash, binds = extract_binds(operation.selector)
64
+ hash = extract_binds(operation.selector)
85
65
  description = hash.to_json
86
66
 
87
- annotations = build_annotations(operation)
88
- annotations[:binds] = binds unless binds.empty?
89
-
90
- [CAT, title, description, annotations]
67
+ [CAT, title, description]
91
68
  end
92
69
 
93
70
  def normalize_title(type, operation)
94
71
  "#{type} #{operation.collection}"
95
72
  end
96
73
 
97
- def build_annotations(operation)
98
- annotations = {}
99
-
100
- if operation.respond_to?(:flags)
101
- flags = operation.flags.map{|f| flag_name(f) }
102
- annotations[:flags] = flags unless flags.empty?
103
- end
104
-
105
- annotations
106
- end
107
-
108
- # Some flags used by Moped don't map directly to the Mongo docs
109
- # See http://docs.mongodb.org/meta-driver/latest/legacy/mongodb-wire-protocol/
110
- FLAG_MAP = {
111
- tailable: "TailableCursor",
112
- multi: "MultiUpdate"
113
- }
114
-
115
- def flag_name(flag)
116
- FLAG_MAP[flag] || flag.to_s.sub(/^[a-z\d]*/) { $&.capitalize }.gsub(/(?:_|(\/))([a-z\d]*)/) { "#{$1}#{$2.capitalize}" }
117
- end
118
-
119
- def extract_binds(hash, binds=[])
74
+ def extract_binds(hash)
120
75
  ret = {}
121
76
 
122
77
  hash.each do |k,v|
123
78
  if v.is_a?(Hash)
124
- ret[k] = extract_binds(v, binds)[0]
79
+ ret[k] = extract_binds(v)
125
80
  else
126
- binds << stringify(hash[k])
127
81
  ret[k] = '?'
128
82
  end
129
83
  end
130
84
 
131
- [ret, binds]
85
+ ret
132
86
  end
133
87
 
134
88
  def stringify(value)
@@ -3,8 +3,14 @@ module Skylight
3
3
  module Grape
4
4
  class Probe
5
5
  def install
6
- version = ::Grape::VERSION.split('.')
7
- if version[0] == '0' && version[1].to_i < 10
6
+ version = Gem::Version.new(::Grape::VERSION)
7
+
8
+ if version > Gem::Version.new("0.12.1")
9
+ # AS::N is built in to newer versions
10
+ return
11
+ end
12
+
13
+ if version < Gem::Version.new("0.10.0")
8
14
  # Using $stderr here isn't great, but we don't have a logger accessible
9
15
  $stderr.puts "[SKYLIGHT] [#{Skylight::VERSION}] The Grape probe only works with version 0.10.0+ " \
10
16
  "and will be disabled."
@@ -28,13 +34,8 @@ module Skylight
28
34
  # modified block. However, Grape does some odd stuff with the block binding
29
35
  # that makes this difficult to reason about.
30
36
  if original_block = @block
31
- opts = {
32
- category: "app.grape.endpoint",
33
- title: method_name.gsub(/\s+/, ' ')
34
- }
35
-
36
37
  @block = lambda do |endpoint_instance|
37
- Skylight.instrument(opts) do
38
+ ActiveSupport::Notifications.instrument('endpoint_render.grape', endpoint: endpoint_instance) do
38
39
  original_block.call(endpoint_instance)
39
40
  end
40
41
  end
@@ -43,68 +44,35 @@ module Skylight
43
44
 
44
45
  alias run_without_sk run
45
46
  def run(*args)
46
- # We run the original method first since it gives us access to more information
47
- # about the current state, including populating `route`.
48
- run_without_sk(*args)
49
- ensure
50
- if instrumenter = Skylight::Instrumenter.instance
51
- if trace = instrumenter.current_trace
52
- # FIXME: How do we handle endpoints with multiple methods?
53
- # Currently we'll see things like "PUT POST DELETE PATCH HEAD"
54
-
55
- # OPTION A: GET /prefix/name [v1]
56
- # # FIXME: Ideally we wouldn't have to do this, but I don't know
57
- # # of a better way
58
- # info = route.instance_variable_get :@options
59
-
60
- # # FIXME: Consider whether we should include the module name
61
- # name = "#{info[:method]} #{info[:path]}"
62
- # name << " [#{info[:version]}]" if info[:version]
63
-
64
-
65
- # OPTION B: Module::Class GET /name
66
- http_method = options[:method].first
67
- http_method << "..." if options[:method].length > 1
68
-
69
- path = options[:path].join("/")
70
- namespace = ::Grape::Namespace.joined_space(namespace_stackable(:namespace))
71
-
72
- if namespace && !namespace.empty?
73
- path = "/#{path}" if path[0] != '/'
74
- path = "#{namespace}#{path}"
75
- end
76
-
77
- name = "#{options[:for]} [#{http_method}] #{path}"
78
-
79
- trace.endpoint = name
80
- end
47
+ ActiveSupport::Notifications.instrument('endpoint_run.grape', endpoint: self) do
48
+ run_without_sk(*args)
81
49
  end
82
50
  end
83
51
 
84
52
  alias run_filters_without_sk run_filters
85
53
  def run_filters(filters)
86
- if !filters || filters.empty?
87
- # If there's no filters nothing should happen, but let Grape decide
88
- return run_filters_without_sk(filters)
54
+ # Unfortunately, the type isn't provided to the method so we have
55
+ # to try to guess it by looking at the contents. This is only reliable
56
+ # if the filters aren't empty.
57
+ if filters && !filters.empty?
58
+ type = case filters
59
+ when befores then :before
60
+ when before_validations then :before_validation
61
+ when after_validations then :after_validation
62
+ when afters then :after
63
+ else :other
64
+ end
65
+ else
66
+ type = :unknown
89
67
  end
90
68
 
91
- # Unfortunately, this method only gets passed an array of filters.
92
- # This means we have to compare to known lists to attempt to detect
93
- # the type.
94
- type = case filters
95
- when befores then "Before"
96
- when before_validations then "Before Validation"
97
- when after_validations then "After Validation"
98
- when afters then "After"
99
- else "Other"
100
- end
101
-
102
- opts = {
103
- category: "app.grape.filters",
104
- title: "#{type} Filters"
69
+ payload = {
70
+ endpoint: self,
71
+ filters: filters,
72
+ type: type
105
73
  }
106
74
 
107
- Skylight.instrument(opts) do
75
+ ActiveSupport::Notifications.instrument('endpoint_run_filters.grape', payload) do
108
76
  run_filters_without_sk(filters)
109
77
  end
110
78
  end
@@ -13,9 +13,9 @@ module Skylight
13
13
  config.skylight.config_path = "config/skylight.yml"
14
14
 
15
15
  # The probes to load
16
- # net_http and action_view are on by default
17
- # Also available: excon, redis
18
- config.skylight.probes = ['net_http', 'action_view']
16
+ # net_http, action_view, and grape are on by default
17
+ # Also available: excon, redis, sinatra, tilt, sequel
18
+ config.skylight.probes = ['net_http', 'action_view', 'grape']
19
19
 
20
20
  initializer 'skylight.configure' do |app|
21
21
  # Load probes even when agent is inactive to catch probe related bugs sooner
@@ -40,10 +40,20 @@ module Skylight
40
40
  return if @instrumenter.disabled?
41
41
  return unless trace = @instrumenter.current_trace
42
42
 
43
- cat, title, desc, annot = normalize(trace, name, payload)
43
+ result = normalize(trace, name, payload)
44
+
45
+ unless result == :skip
46
+ case result.size
47
+ when 4
48
+ error "old style normalizer; name=#{name.inspect}; normalizer=#{@normalizers.normalizer_for(name).class}"
49
+ cat, title, desc, _ = result
50
+ when 3
51
+ cat, title, desc = result
52
+ else
53
+ raise "Invalid normalizer result: #{result.inspect}"
54
+ end
44
55
 
45
- unless cat == :skip
46
- span = trace.instrument(cat, title, desc, annot)
56
+ span = trace.instrument(cat, title, desc)
47
57
  end
48
58
 
49
59
  trace.notifications << Notification.new(name, span)
@@ -53,7 +63,6 @@ module Skylight
53
63
  debug "in: name=%s", name.inspect
54
64
  debug "in: payload=%s", payload.inspect
55
65
  debug "out: cat=%s, title=%s, desc=%s", cat.inspect, name.inspect, desc.inspect
56
- debug "out: annot=%s", annot.inspect
57
66
  t { e.backtrace.join("\n") }
58
67
  nil
59
68
  end
@@ -6,9 +6,9 @@ module Skylight
6
6
 
7
7
  attr_reader :endpoint, :notifications
8
8
 
9
- def self.new(instrumenter, endpoint, start, cat, title = nil, desc = nil, annot = nil)
9
+ def self.new(instrumenter, endpoint, start, cat, title = nil, desc = nil)
10
10
  inst = native_new(normalize_time(start), "TODO", endpoint)
11
- inst.send(:initialize, instrumenter, cat, title, desc, annot)
11
+ inst.send(:initialize, instrumenter, cat, title, desc)
12
12
  inst.endpoint = endpoint
13
13
  inst
14
14
  end
@@ -20,7 +20,7 @@ module Skylight
20
20
  (time.to_i / 100_000).to_i
21
21
  end
22
22
 
23
- def initialize(instrumenter, cat, title, desc, annot)
23
+ def initialize(instrumenter, cat, title, desc)
24
24
  raise ArgumentError, 'instrumenter is required' unless instrumenter
25
25
 
26
26
  @instrumenter = instrumenter
@@ -29,14 +29,6 @@ module Skylight
29
29
 
30
30
  @notifications = []
31
31
 
32
- if Hash === title
33
- annot = title
34
- title = desc = nil
35
- elsif Hash === desc
36
- annot = desc
37
- desc = nil
38
- end
39
-
40
32
  # create the root node
41
33
  @root = native_start_span(native_get_started_at, cat)
42
34
  native_span_set_title(@root, title) if title
@@ -55,16 +47,8 @@ module Skylight
55
47
  @instrumenter.config
56
48
  end
57
49
 
58
- def record(cat, title=nil, desc=nil, annot=nil)
59
- @return if @broken
60
-
61
- if Hash === title
62
- annot = title
63
- title = desc = nil
64
- elsif Hash === desc
65
- annot = desc
66
- desc = nil
67
- end
50
+ def record(cat, title=nil, desc=nil)
51
+ return if @broken
68
52
 
69
53
  title.freeze if title.is_a?(String)
70
54
  desc.freeze if desc.is_a?(String)
@@ -82,18 +66,10 @@ module Skylight
82
66
  nil
83
67
  end
84
68
 
85
- def instrument(cat, title=nil, desc=nil, annot=nil)
69
+ def instrument(cat, title=nil, desc=nil)
86
70
  return if @broken
87
71
  t { "instrument: #{cat}, #{title}" }
88
72
 
89
- if Hash === title
90
- annot = title
91
- title = desc = nil
92
- elsif Hash === desc
93
- annot = desc
94
- desc = nil
95
- end
96
-
97
73
  title.freeze if title.is_a?(String)
98
74
  desc.freeze if desc.is_a?(String)
99
75
 
@@ -104,10 +80,10 @@ module Skylight
104
80
  if desc == Instrumenter::TOO_MANY_UNIQUES
105
81
  debug "[SKYLIGHT] [#{Skylight::VERSION}] A payload description produced <too many uniques>"
106
82
  debug "original desc=%s", original_desc
107
- debug "cat=%s, title=%s, desc=%s, annot=%s", cat, title, desc, annot.inspect
83
+ debug "cat=%s, title=%s, desc=%s", cat, title, desc
108
84
  end
109
85
 
110
- start(now - gc_time, cat, title, desc, annot)
86
+ start(now - gc_time, cat, title, desc)
111
87
  rescue => e
112
88
  error "failed to instrument span; msg=%s", e.message
113
89
  @broken = true
@@ -135,7 +111,7 @@ module Skylight
135
111
 
136
112
  if time > 0
137
113
  t { fmt "tracking GC time; duration=%d", time }
138
- stop(start(now - time, GC_CAT, nil, nil, {}), now)
114
+ stop(start(now - time, GC_CAT, nil, nil), now)
139
115
  end
140
116
 
141
117
  stop(@root, now)
@@ -164,8 +140,11 @@ module Skylight
164
140
 
165
141
  private
166
142
 
167
- def start(time, cat, title, desc, annot=nil)
168
- span(self.class.normalize_time(time), cat, title, desc, annot)
143
+ def start(time, cat, title, desc)
144
+ sp = native_start_span(self.class.normalize_time(time), cat.to_s)
145
+ native_span_set_title(sp, title.to_s) if title
146
+ native_span_set_description(sp, desc.to_s) if desc
147
+ sp
169
148
  end
170
149
 
171
150
  def stop(span, time)
@@ -173,13 +152,6 @@ module Skylight
173
152
  nil
174
153
  end
175
154
 
176
- def span(time, cat, title=nil, desc=nil, annot=nil)
177
- sp = native_start_span(time, cat.to_s)
178
- native_span_set_title(sp, title.to_s) if title
179
- native_span_set_description(sp, desc.to_s) if desc
180
- sp
181
- end
182
-
183
155
  def gc_time
184
156
  return 0 unless @gc
185
157
  @gc.update
@@ -1,4 +1,4 @@
1
1
  module Skylight
2
- VERSION = '0.8.0-beta.1'
2
+ VERSION = '0.8.0-beta.3'
3
3
  end
4
4
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: skylight
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0.beta.1
4
+ version: 0.8.0.beta.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tilde, Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-08-04 00:00:00.000000000 Z
11
+ date: 2015-08-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -53,7 +53,6 @@ files:
53
53
  - lib/skylight/data/cacert.pem
54
54
  - lib/skylight/formatters/http.rb
55
55
  - lib/skylight/gc.rb
56
- - lib/skylight/grape.rb
57
56
  - lib/skylight/helpers.rb
58
57
  - lib/skylight/instrumenter.rb
59
58
  - lib/skylight/middleware.rb
@@ -77,6 +76,10 @@ files:
77
76
  - lib/skylight/normalizers/active_support/cache_read_multi.rb
78
77
  - lib/skylight/normalizers/active_support/cache_write.rb
79
78
  - lib/skylight/normalizers/default.rb
79
+ - lib/skylight/normalizers/grape/endpoint.rb
80
+ - lib/skylight/normalizers/grape/endpoint_render.rb
81
+ - lib/skylight/normalizers/grape/endpoint_run.rb
82
+ - lib/skylight/normalizers/grape/endpoint_run_filters.rb
80
83
  - lib/skylight/normalizers/moped/query.rb
81
84
  - lib/skylight/probes.rb
82
85
  - lib/skylight/probes/action_view.rb
@@ -1,2 +0,0 @@
1
- require 'skylight'
2
- require 'skylight/probes/grape'